/* Label.C
 *
 * Stores user-defined labels for backwards and forwards referencing with
 * the \ref and \pageref commands.
 *
 * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute,
 * edit and use as long as this copyright statement remains intact.
 *
 */

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "Global.h"
#include "Counter.h"
#include "Operator.h"

Label::Label(char *name, int chapter, int section)
{
     _name = strdup(name);
     _chapter = chapter;
     _section = section;
     _referenced = 0;
}

Label::~Label()
{
     delete _name;
}

Label::match(char *name)
{
     return !strcmp(name, _name);
}

Labels::Labels()
{
     numlabels = 0;
     unknown_references = 0;
}

Labels::~Labels()
{
     for(int x=0; x < numlabels; x++)
	  delete label[x];
}

void Labels::add_label(char *labelname)
{
     if(numlabels > MAXLABELS - 2)
	  Global::files->fatal_error("Too many labels defined");
     for(int x=0; x < numlabels; x++)
	  if(label[x]->match(labelname)) {
	       char message[50];
	       sprintf(message, "Same label name %s defined twice", labelname);
	       Global::files->fatal_error(message);
	  }

     label[numlabels++] =
	  new Label(labelname,
		    (int)Stack::get(Environment::PCounter,
				    Counter::Chapter, ""),
		    (int)Stack::get(Environment::PCounter,
				    Counter::Section, ""));
}


/* Print a reference to a given labelname done from the \ref command.
 * Must handle forward referencing as a special case.
 */
void Labels::print_ref(char *labelname)
{
     for(int x=0; x < numlabels; x++)
	  if(label[x]->match(labelname)) {
	       char printout[MAXSTRING];
	       sprintf(printout,"%d.%d",label[x]->_chapter,label[x]->_section);
	       Operator::plaintext(printout);
	       label[x]->_referenced = 1;
	       return;
	  }

     /* Label is undefined. We assume it is a forward referencing problem */
     unknown_references = 1;
     Global::files->outfile << endl << "LAMETEXLABELREF" << labelname << endl;
}

/* Shutdown the program by going through the file and changing all the
 * undone label references to the correct information.
 */
void Labels::shutdown()
{
     ifstream outfile;
     ofstream tempfile;
     char buffer[MAXSTRING];
     char *p;
     char *labelname;

     if(!unknown_references)
	  return;
     cerr << "Handling forward references..." << endl;
     outfile.open(Global::files->outfilename);
     tempfile.open("lametex.temp");
     outfile.getline(buffer, MAXSTRING, '\n');
     while(!outfile.eof() && !outfile.fail()) {
	  if((p = strstr(buffer, "LAMETEXLABELREF"))!=NULL) {
	       labelname = (char *)(p + 15);
	       for(int x=0; x < numlabels; x++)
		    if(label[x]->match(labelname)) {
			 tempfile << "(" << label[x]->_chapter
				 << "." << label[x]->_section
				 << ") NW" << endl;
			 label[x]->_referenced = 1;
			 break;
		    }
	       if(x >= numlabels) {
		    cerr << "No match found for label " << labelname << endl;
		    exit(-1);
	       }
          } else {
               tempfile << buffer << endl;
          }
	  outfile.getline(buffer, MAXSTRING, '\n');
     }

     outfile.close();
     tempfile.close();
     sprintf(buffer, "mv lametex.temp %s", Global::files->outfilename);
     system(buffer);
}