/* $Header: /bioy2/biocomputing/doelz/development/jam/RCS/jamparse.c,v 2.0 1995/07/23 08:56:38 doelz Exp doelz $ */ 
/* 
         ***********************************************************
         *                                                         *
         *                         J A M                           * 
         *        J u s t   A n o t h e r   M e t a f i l e        *
         *                                                         *
         ***********************************************************

        --- SEE MAIN PROGRAM (JAM.C) FOR COPYRIGHT AND DEFINITION ---
*/ 

#include "jam.h"       
#ifdef JAMGUI
#include "vibrant.h"
#define DEALEXIT ArrowCursor(); 
#else                  
/* declarations for non-vibrant code */
#define Message fprintf
#define MSG_ERROR stdout
#define MSG_OK stdout
#define MSG_POST stdout
#define DEALEXIT perror("Error in JAM"); 
#endif
#include "jamproto.h"

static char code_id[]="$Id: jamparse.c,v 2.0 1995/07/23 08:56:38 doelz Exp doelz $"; 

/* Global variables */ 

#ifdef DEBUG 
extern int jam_debug;
#else
extern int jam_debug; 
#endif 


extern char jam_line[MAXLINE],jam_link[MAXLINE];
extern char jam_file[MAXINC][MAXFIL],jam_out[MAXLINE];  
extern char myline[MAXLINE]; 
extern int jam_lineno[MAXINC],jam_indexdone;
extern FILE *jam_fp[MAXINC], *jam_op, *jam_index,*jam_all,*jam_cts, *jam_lnk, *jam_ref, *jam_inx; 
extern int current_jam; /* current open jam file */   
extern int def_flag; /* whether ifdef'ed or not */

/* conditionals */ 
extern int if_tstack;
extern int if_dstack; 
extern char if_token[MAXIF][MAXDEF];  
extern char if_defined[MAXIF][MAXDEF]; 

/* output modus */ 
extern int modus,sitespecific; 
extern int did_a_print; 
extern int vms_status; 
extern int single_file; 

/* chapters */ 
extern  int chapter_number; 
extern  int section_number;
extern  int subsection_number; 
extern  int line_number; 
extern  int line_in_file; 
extern  int line_in_input[MAXINC]; 

/* styles */ 
extern  int verbatim; 
extern  int special;  
extern  int special_on; 
extern  int emphasis_on; 
extern  int item_on; 
extern  int link_on;   
extern int did_feed; 
extern  int item; 
/* extern  int last_verbatim;  OLD CODE */
extern int behaviour; 

/* item formatter */
extern char item_prefix[MAXLINE]; 


/*---------------------------------------------------------------------*/

int jam_parse(char* line)
{ 
  int status; 
  status =0; 


  
  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  /* parsing. '#' statements first */ 
  
  if ( strncmp(line,"#ifdef", strlen("#ifdef")) == 0) { 
    if (!verbatim) status = STARTIFDEF; 
  } 
  if ( strncmp(line,"#else", strlen("#else")) == 0) { 
    if (!verbatim) status = ELSEIFDEF; 
  } 
  if ( strncmp(line,"#endif", strlen("#endif")) == 0) { 
    if (!verbatim) status = ENDIFDEF; 
  } 
  if ( strncmp(line,"#include", strlen("#include")) == 0) { 
    if (!verbatim) status = INCLUDE; 
  } 
  
  
  
  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  /* parsing. '%' comments */ 
  
  if ( strncmp(line,"%", strlen("%")) == 0) { 
    if  (!verbatim)  status = COMMENT; 
  } 
  



  /* parsing. process anything else only if we are active! */
  /* def_flag is a global variable telling us that we are defined. */
  
  if (def_flag) {
    
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* parsing. Linefeeds, pagefeeds. */ 
    if ( strncmp(line,"---", strlen("---")) == 0) { 
      if (!verbatim)
	status = LINEFEED; 
    }
    if ( strncmp(line,"===", strlen("===")) == 0) { 
      if (!verbatim)
	status = PAGEFEED; 
    }
    
    


    /* parsing. formats are with hyphen - letter - hyphen */ 
    
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* verbatim start may see nothing else ! */ 
    if ( strncmp(line,"-V-", strlen("-V-")) == 0) { 
      if (item_on) {
	Message (MSG_ERROR, "Line %d in %s : -V- but -I- active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      
      if (special_on) {
	Message (MSG_ERROR, "Line %d in %s : -V- but -S- active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      
      if (verbatim) {
	Message (MSG_ERROR, "Line %d in %s : -V- but already active", 
		 jam_lineno[current_jam], jam_file[current_jam]);
	DEALEXIT;
	exit (-1);  
      } else {
	status = VERBATIM; 
      }
    } 
    /* verbatim end */
    if ( strncmp(line,"-v-", strlen("-v-")) == 0) {  
      if (verbatim != TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -v- but no -V- seen", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } else {
	status = VERBATIM; 
      }
    } 
      

    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* special start. We do not tolerate others at all. */ 
    if ( strncmp(line,"-S-", strlen("-S-")) == 0) {
      if (item_on) {
	Message (MSG_ERROR, "Line %d in %s : -S- but -I- active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      
      if (verbatim) {
	Message (MSG_ERROR, "Line %d in %s : -S- but -V- active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      if (special_on) {
	Message (MSG_ERROR, "Line %d in %s : -S- but already active", 
		 jam_lineno[current_jam], jam_file[current_jam]);
	DEALEXIT;
	exit (-1);  
	
      } else {
	if (!verbatim) {
	  status = SPECIAL;
	}
      }
    } 
    /* special end */ 
    if ( strncmp(line,"-s-", strlen("-s-")) == 0) { 
      if (special_on != TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -s- but no -S- seen", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } else {	
	if (!verbatim) {
	  status = SPECIAL; 
	}                      
      }
    } 



    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* emphasis start. We toerate it everywhere but not in V or S. */ 
    if ( strncmp(line,"-E-", strlen("-E-")) == 0) {
      if (emphasis_on) {
	Message (MSG_ERROR, "Line %d in %s : -E- but already active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      if (verbatim) {
	Message (MSG_ERROR, "Line %d in %s : -E- but -V- active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      if (special_on) {
	Message (MSG_ERROR, "Line %d in %s : -S- but already active", 
		 jam_lineno[current_jam], jam_file[current_jam]);
	DEALEXIT;
	exit (-1);  
	
      } else {
	if (!verbatim) {
	  status = EMPHASIS;
	}
      }
    } 
    /* emphasis end */ 
    if ( strncmp(line,"-e-", strlen("-e-")) == 0) { 
      if (emphasis_on != TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -e- but no -E- seen", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } else {
	if (!verbatim) {
	  status = EMPHASIS; 
	}                      
      }
    } 
    


    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* itemize  start. Not allowed in verbatim. */ 
    if ( strncmp(line,"-I-", strlen("-I-")) == 0) { 
      if (item_on == TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -I- but already active", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	exit(-1); 
      } else {
	if (!verbatim) {
	  status = ITEM; 
	  item_on = TRUE; 
	} 
      }
    } 
    /* itemize end. */  
    if ( strncmp(line,"-i-", strlen("-i-")) == 0) {
      if (item_on != TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -i- but no -I- seen", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } else {
	
	if (!verbatim) {
	  status = ITEM;
	  item_on = FALSE; 
	} 
      }
    } 
    /* an item ! */ 
    if (((line[0] == 'o') && (line[1] == '\n') ) || (  strncmp(line,"o ", strlen("o ")) == 0)) {
      if (item_on != TRUE) {
	Message (MSG_ERROR, "Line %d in %s : (o) but no -I- seen", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	DEALEXIT;
	exit (-1); 
      } 
      if ((item) && (!verbatim))  status = ANITEM; 
    } 
    
    

    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* links . link on */ 
    if ( strncmp(line,"-L-", strlen("-L-")) == 0) { 
      if (link_on == TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -L- seen but previously unfinished", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	exit(-1); 
      } else {
	if (!verbatim) {
	  status = REFERENCE; 
	  link_on = TRUE; 
	} 
      }
    } 
    /* link off. */ 
    if ( strncmp(line,"-l-", strlen("-l-")) == 0) {        
      /* we should never see this while links are processed.
	 if so, there's a problem as previous processing failed. */
      if (link_on == TRUE) {
	Message (MSG_ERROR, "Line %d in %s : -l- seen but previously unfinished", 
		 jam_lineno[current_jam], jam_file[current_jam]); 
	exit(-1); 
      }
      status = COMMENT; 
    } 
    

    
    
    
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* chapters and sections */ 
    
    
    if ( strncmp(line,"* ", strlen("* ")) == 0) { 
      if (!verbatim) status = CHAPTER; 
    } 
    
    if ( strncmp(line,"-*- ", strlen("-*- ")) == 0) { 
      if (!verbatim) status = SECTION; 
    } 
    
    if ( strncmp(line,"-**- ", strlen("-**- ")) == 0) { 
      if (!verbatim) status = SUBSECTION; 
    } 
    
  } /* end of non-processed code if we are not active 
       (i.e., ifdef'ed out )
       */
  
  return(status); 
} 



/*---------------------------------------------------------------------*/
int jam_init (char* filename) 
{ 
  int status; 
  
  int i;          
  jam_indexdone = FALSE; 
  /* chapters */ 
  chapter_number=0; 
  section_number=0;
  subsection_number=0; 
  
  /* styles */ 
  verbatim = 0; 
  special = 0;  
  item = 0; 
  
  
  /* initialization */ 
#ifdef JAMGUITEST
  if_tstack = 0; 
  if_dstack = 2; 
  
  strcpy(if_defined[0], "HULLA"); 
  strcpy(if_defined[1], "SRS"); 
#endif
  
  /* jam index file link helper */ 
  jam_lnk = fopen("JAM.LNK","r"); 
  
  if (jam_lnk == NULL) { 
    Message (MSG_OK,"Cannot open, will create index file %s\n", "JAM.LNK"); 
    
    jam_lnk = fopen("JAM.LNK","w"); 
    if (jam_lnk == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open index file %s\n", "JAM.LNK"); 
      DEALEXIT;
      exit(-1); 
    }
    fclose (jam_lnk); 
    jam_lnk = fopen("JAM.LNK","r"); 
    
    if (jam_lnk == NULL) { 
      Message (MSG_ERROR,"Cannot reopen index file %s\n", "JAM.LNK"); 
      DEALEXIT;
      exit(-1); 
    }
  }           
  
  /* jam index file logger  */ 
  jam_ref = fopen("JAM.REF","w"); 
  
  if (jam_ref == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open log index file %s\n", "JAM.REF"); 
    DEALEXIT;
    exit(-1); 
  }        
  Message (MSG_POST, "will record all links in %s ", "JAM.REF"); 
  fprintf (jam_ref, "%s \n", "% JAM 2.1"); 
  fprintf (jam_ref, "%s %s\n", "%",CODE_CRN); 
  fprintf (jam_ref, "%s This file lists all links of the JAM document.\n","%"); 
  fprintf (jam_ref, "%s This file is generated by JAM in JAM and can be processed by JAM. \n","%"); 
  fprintf (jam_ref, "%s However, this is ONLY done in the HTML output for index generation. \n", "%"); 
  fprintf (jam_ref, "%s On non-PC systems, this index file is SORTED before processing. \n\n","%"); 
  fprintf (jam_ref, "-I-\n"); 
  fprintf (jam_ref, "\n"); 
#ifndef JAMGUI
  printf ("\n"); 
#endif 

  /* end of index file logger. We initialize other files now */
  /* modus is the recognized demanded output switch */ 

  switch (modus) { 
    
  case LATEX: 
    /* leader file will include other .TEX sources */ 
    jam_all= fopen("JAMINX.TEX","w"); 
    break; 
    
  case RTF:
    /* This format does not need an index file */ 
    break; 

  case HTML:
    /* special treatment - we make an index page, a welcome and 
       a TOC page. We'll use JAM.TIT as preamble if we find it */ 
    
    /* the welcome file writing */ 
    /* see for JAM.TIT - we'll take this as header */
    jam_cts= fopen("JAM.TIT","r");               
    if (jam_cts == NULL ) {
      /*we don't have any, create it */ 
      Message (MSG_OK, "Will create Master page with default header"); 
      jam_all= fopen("JAMINX.HTML","w");
      if (jam_all == NULL) { 
	/* cannot write welcome page */ 
	Message (MSG_ERROR,"FATAL: Cannot open index file %s\n", "JAMINX.HTML"); 
	DEALEXIT;
	exit (-1); 
      }else { 
	/* can write welcome page. Supply own default header */ 
        Message (MSG_OK,"... JAMINX.HTML (index page)\n"); 
        fprintf(jam_all,"<TITLE> Master Index Page </TITLE>\n");
        fprintf(jam_all,"<H1>Contents</H1><HR>\n"); 
      }
    } else {
      /* we have one JAM.TIT as preamble, copy it */ 
      jam_copyhtml(); 
      jam_all= fopen("JAMINX.HTML","a");
      Message (MSG_OK,"... JAMINX.HTML (index page)\n"); 
      if (jam_all == NULL) { 
	/* cannot write to welcome page */ 
	Message (MSG_ERROR,"FATAL: Cannot open index file %s\n", "JAMINX.HTML"); 
	DEALEXIT;
	exit (-1); 
      }       
    }
    
    /* write a contents file */ 
    jam_cts= fopen("JAMCTS.HTML","w");
    if (jam_cts == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open contents file %s\n", "JAMCTS.HTML"); 
      DEALEXIT;
      exit (-1); 
    } else {
      Message (MSG_OK,"will create file JAMCTS.HTML (contents page)\n"); 
      fprintf(jam_cts,"<TITLE>TABLE OF CONTENTS Page </TITLE>\n");
      fprintf(jam_cts,"<H1> Table of Contents </H1>\n");    
      fprintf(jam_cts,"<em> %s </em>\n <HR>\n",CODE_CRN);    
    } 
    fprintf(jam_all,"<UL>\n");    
    
    /* write a file for crossreferences */ 
    jam_index = fopen("JAM.INX", "w");
    if (jam_index == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open index file %s\n", "JAM.INX"); 
      DEALEXIT;
      exit (-1); 
    } 
    break; 
    
  default: 
    break; 
  } 
  
  
  /* open main file */ 
  if ((strstr(jam_file[current_jam],".STE") != NULL) && (sitespecific != 1) ) {
    /* if STE file found replace extension by netural file, INT */
    i=0; 
    while ((jam_file[current_jam][i] != '.' ) && ( i < (int) strlen(jam_file[current_jam]) ) )
      i++; i++;
    jam_file[current_jam][i] = 'I'; i++; 
    jam_file[current_jam][i] = 'N'; i++; 
    jam_file[current_jam][i] = 'T'; i++; 
  }
  
  jam_fp[current_jam] = fopen(jam_file[current_jam], "r"); 
  if (jam_fp[current_jam] == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open input JAM file %s\n",jam_file[current_jam] ); 
    DEALEXIT;
    exit (-1); 
  } 
  

  /* read a line - see whether the format is OK */ 
  status = readline(jam_line);
  status = strlen("% JAM 2.");
  if (strncmp(jam_line,"% JAM 2.",status) != 0) { 
    Message (MSG_ERROR,"FATAL: Not a recognized version or JAM file: %s\n",jam_file[current_jam] ); 
    Message (MSG_ERROR,"expected: 'JAM 2.x' found: %s", jam_line); 
    DEALEXIT;
    exit (-1); 
  }  
  return (1); 
} 




/*---------------------------------------------------------------------*/

int readline(char *line)
{ 
  int status;                                     
  int i; 
  char myline[MAXLINE*3]; 
  
  
  /* read from main file onlz if possible */ 
  if (jam_fp[current_jam] != NULL ) { 
       
    /* delete previous line */ 
    for (i=0; i<MAXLINE*3; i++) { myline[i]=0; };

    /* get a string three times the length */
    if (fgets(myline,MAXLINE*3, jam_fp[current_jam]) != NULL) {
      
      /* too long?*/ 
      if ((int) strlen(myline) >= MAXLINE) {
#ifndef JAMGUI
	printf ("\n"); 
#endif
	Message (MSG_ERROR, "FATAL: Line %d in %s : More than %d characters. ", 
		 jam_lineno[current_jam], jam_file[current_jam],MAXLINE);
#ifndef JAMGUI
	printf ("Line follows:\n%s\n", myline); 
#endif
	DEALEXIT;                    
	exit (-1); 
      }  
      line_in_input[current_jam]++;
      status = TRUE; 
    } else { 
      status = FALSE; 
    } 
    
    /* read line was not too long. Strange characters?*/ 
    for (i=0; i<(int) strlen(myline)-1; i++) { 
      if ((!isprint (myline[i])) && (!isspace (myline[i])) ) {
#ifndef JAMGUI
	printf ("\n"); 
#endif 
	Message (MSG_ERROR, "FATAL: Line %d in %s : Unprintable character at column %d .", 
		 jam_lineno[current_jam], jam_file[current_jam],i);
#ifndef JAMGUI
	printf ("Line follows:\n%s\n", myline); 
#endif
	DEALEXIT;                    
	exit (-1);
      }
    }  

    /* read line is ok. Return SUCCESS */ 
    strcpy (line,myline);	 
    if (status == TRUE) return (status);

    /* if the read line is NOT ok, status is FALSE, and we are done 
       with this file. We need to close this file, print a farewell if 
       it is the last, identify it otherwise, etc ... see below.*/

    /* close the file by purging the printbuffer */ 
    strcpy(myline,"!!!"); 
    pprint(myline);   
    strcpy(myline,"!!!"); 
    pprint(myline);  
#ifndef JAMGUI
    printf ("\n");
#endif
    if (current_jam >= 0) {
      Message(MSG_POST,"done with %s (level %d) ... ",jam_file[current_jam],current_jam);  
    } else {
      Message(MSG_POST,"done with JAM"); 
      return (-1); 
    }   
  }

  /* done. current_jam is the level we are working on. 
     If this level is 0, we are really done and subtracting
     1 gives a negative number. */ 
  
  current_jam--; 
  if ( current_jam >= 0) { 
    fclose(jam_fp[current_jam+1]);  
    status =0; 
    return(status); 
  } else  {

    /* For once we need to work on the index file!  This is done with the variable jam_indexdone. */
    /* jam_indexdone is for HTML modus ONLY. */ 
    
    if (jam_indexdone == FALSE) {
      
      /* fclose the reference file and reopen it for read */
      fclose (jam_fp[current_jam+1]); 
      fprintf (jam_ref, "\n-i-\n\n"); 
      fclose (jam_ref);
      /* reset file pointer */ 
      jam_ref = (void*) NULL; 
      if (current_jam < 0) jam_indexdone=TRUE;
      if (modus == HTML) {
	/* later we'll write a nice sort but now we don't */ 
#ifdef NEXTVERSION 
#if defined(BORLANDC) || defined(MICROSOFTC) || defined(OS2) || defined(THINKC)
	Message (MSG_POST,"including the INDEX (non-sorted, PC/Mac)"); 
#else                
#ifndef VMS
	system ("jamsort JAM.REF "); 
	system ("mv JAM.TMP JAM.REF"); 
#else
	system ("sort/out=JAM.TMP JAM.REF"); 
	system ("rename JAM.TMP JAM.REF"); 
#endif 
	Message (MSG_POST,"including the INDEX (sorted, UNIX/VMS)"); 
#endif
#else
	Message (MSG_POST,"including the INDEX");
#endif 
#ifndef JAMGUI
 	printf ("\n"); 
#endif	    	                                                 
	
	current_jam++;                            
	/* fclosed the reference file -  reopen it for read  as reference file */
	strcpy (myline, "Index");
	makeachapter (myline); 
	strcpy (jam_file[current_jam], "JAM.REF");  
	jam_fp[current_jam] = fopen(jam_file[current_jam], "r"); 
	if (jam_fp[current_jam] == NULL) { 
	  Message (MSG_ERROR,"FATAL: Cannot open input JAM file %s\n",jam_file[current_jam] ); 
	  DEALEXIT;
	  exit (-1); 
	} 
	
	fgets (jam_line,MAXLINE, jam_fp[current_jam]);
	status = strlen("% JAM 2.");
	if (strncmp(jam_line,"% JAM 2.",status) != 0) { 
	  Message (MSG_ERROR,"FATAL: Not a recognized version or JAM file: %s\n",jam_file[current_jam] ); 
	  Message (MSG_ERROR,"expected: 'JAM 2.x' found: %s", jam_line); 
	  DEALEXIT;
	  exit (-1); 
	} else                             
	  return (TRUE);
      } 
      /* return (TRUE); */ 
      /* This is if other formats than HTML encounter end of work.*/ 
    } else {
      /* jam_indexdone is TRUE and we tell good-byze on the last page. */
      /* close the index file */ 
      switch(modus) { 
      case RTF:
	fprintf (jam_op,"\\par \\par \\page "); 
	fprintf (jam_op,"{\\i \\qc This Document was written in the JAM language, \n"); 
	fprintf (jam_op,"which is (C) BioComputing Basel, 1994/5. \\par \\par \\qc For information on this facility or \n"); 
	fprintf (jam_op,"the institution {\\b EMBnet Switzerland} please send an electronic mail message \n"); 
	fprintf (jam_op, "to {\\b info@ch.embnet.org} or FAX a clearly addressed letter \n"); 
	fprintf (jam_op, "to {\\b BioComputing Basel}, x41 61 267 20 78}}\n}\n");
	break; 
      case LATEX:
	fprintf (jam_all,"\\clearpage"); 
	fprintf (jam_all," {\\bf  This Document was written in the JAM language, \n"); 
	fprintf (jam_all," which is (C) BioComputing Basel, 1994/5.  For information on this facility or\n"); 
	fprintf (jam_all," {\\em EMBnet Switzerland} please send an electronic mail message \n"); 
	fprintf (jam_all," to {\\tt info@ch.embnet.org} or FAX a clearly addressed letter \n"); 
	fprintf (jam_all," to \\mbox{BioComputing Basel}, x41 61 267 20 78}\n\n");
	break; 
      case HTML:     
	fprintf (jam_all,"</UL><HR><a href=%sJAMCTS.HTML> Extended Table of Contents</a>\n <p><em>%s</em><p>\n", 
		 JAMPATH,"This document was written with the multi-format authoring tool JAM (Just Another Metafile)."); 
	fprintf (jam_all,"<strong>JAM is (C)</strong> <a href=http://www.ch.embnet.org/>BioComputing Basel 1994/5</a>"); 
	break; 
      default: 
	break; 
      } 
      fclose(jam_fp[current_jam+1]); 
      fclose (jam_all); 
      /* close the link index */ 
      fclose (jam_index); 

      /* user interface good-bye */ 
      switch(modus) {
	/* tell the reader that you do a postprocessing with the link index */ 
      case LATEX: 
	Message (MSG_OK, "Use 'makeindex' to create the index files."); 
#ifndef JAMGUI
	printf ("\n");
#endif
	break; 
      case RTF:
	break; 
      case HTML:
	Message (MSG_POST, "JAM: rewriting index file."); 
#ifndef JAMGUI
	printf ("\n");
#endif
	jam_write(); 
	break; 
      default: 
	break; 
      } 
#ifdef JAMGUI
      DEALEXIT;
#else
      /* uncommment the beeping if you don't like it */ 
      /*  printf ("%s\n", "\7"); */
#endif
      switch(modus) { 
      case HTML:      
#ifdef JAMGUI      
	Message (MSG_OK,"SUCCESS: Rerun JAM to correct links if needed.");
#else
	Message (MSG_OK,"SUCCESS: JAM done.\nYou might need to rerun JAM for correct references/links.\n");
#endif
	break; 
      case LATEX:
      case RTF: 
	Message (MSG_OK,"SUCCESS: JAM done.\n");
	break; 
      default:
	break; 
      } 
      exit (1); 
    } 
  } 
}  




/*---------------------------------------------------------------------*/
int jam_copyhtml(void)
{ 
  char line[MAXLINE]; 
  FILE *indexfile,*newfile;
  int i; 
  int done = FALSE;      /* TRUE if perfect sort */ 
  int needto=TRUE;       /* FALSE if all is alphabetically */ 
  int pass=0;            /* number of passes */
#ifdef NEXTVERSION  
  char sortline[10][MAXLINE];
#endif    
  /* this is to copy file into indexfile. Needed for HTML and others. */ 
  
  newfile = fopen("JAMINX.HTML", "w");
  if (newfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", "JAMINX.HTML"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message(MSG_OK,"opened %s for HTML header\n", "JAM.TIT"); 
  } 
  indexfile = fopen("JAM.TIT", "r");
  if (indexfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open input destination %s\n", "JAM.TIT"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message (MSG_POST,"opened %s for input\n", "JAM.TIT"); 
  } 
  
  i=0; 
  
  while (fgets(line,MAXLINE,indexfile)) { 
    fprintf (newfile,"%s",line); 
    i++; 
  } 
  
  fclose (indexfile); 
  fclose(newfile); 
  Message (MSG_POST,"JAM: copied %d header lines \n", i); 
  return (TRUE); 
}                                                             




/*-----------------------------------------------------*/
int jam_write(void)
{ 
  char line[MAXLINE]; 
  FILE *indexfile,*newfile;
  int i; 
  int done = FALSE;      /* TRUE if perfect sort */ 
  int needto=TRUE;       /* FALSE if all is alphabetically */ 
  int pass=0;            /* number of passes */
#ifdef NEXTVERSION  
  char sortline[10][MAXLINE];
#endif    
  /* this is to copy file into indexfile. Needed for HTML and others. */ 
  
  newfile = fopen("JAMKEY.INX", "w");
  if (newfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", "JAMKEY.INX"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message(MSG_OK,"opened %s for cross-references\n", "JAMKEY.INX"); 
  } 
  indexfile = fopen("JAM.INX", "r");
  if (indexfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", "JAM.INX"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message (MSG_POST,"opened %s for input\n", "JAM.INX"); 
  } 
  
  i=0; 
  
  while (fgets(line,MAXLINE,indexfile)) { 
    fprintf (newfile,"%s",line); 
    i++; 
  } 
  
  fclose (indexfile); 
  fclose(newfile); 
  Message (MSG_POST,"JAM: rewrote %d index entries \n", i); 
  
#ifdef NEXTVERSION                            
  
  /* Next, sort the file JAMKEY.INX alphabetically. */
  /* copy all entries into TM1 */                             
  
  newfile = fopen("JAMKEY.TM1", "w");
  if (newfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", "JAMKEY.TM1"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message(MSG_OK,"opened %s for sorting\n", "JAMKEY.TM1"); 
  } 
  indexfile = fopen("JAM.INX", "r");
  if (indexfile == NULL) { 
    Message (MSG_ERROR,"FATAL: Cannot open input destination %s\n", "JAM.INX"); 
    DEALEXIT;
    exit (-1); 
  } else { 
    Message (MSG_POST,"opened %s for input\n", "JAM.INX"); 
  } 
  
  i=0; 
  /* load sorting array */
  while (fgets(sortline[i],MAXLINE,indexfile)) { 
    i++; 
  } 
  
  qsort( (void *)sortline, (size_t)i, sizeof( char * ), compare );
  /* Output sorted list: */
  for( i = 0; i < i; ++i )
    printf( "%s ", sortline[i] );
  printf( "\n" );
  
  exit (-1); 
  fclose (indexfile); 
  fclose(newfile); 
  Message (MSG_POST,"JAM: copied %d index entries \n", i); 
  
  /* This loop is executing assuming that all is in TM1 */                                                         
  while (!done) {
    newfile = fopen("JAMKEY.TM2", "w");
    if (newfile == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", "JAMKEY.TM2"); 
      DEALEXIT;
      exit (-1); 
    } else { 
      Message(MSG_OK,"opened %s for sort-index pass %d\n", "JAMKEY.TM2",pass); 
    } 
    indexfile = fopen("JAMKEY.TM1", "r");
    if (indexfile == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open input destination %s\n", "JAMKEY.TM1"); 
      DEALEXIT;
      exit (-1); 
    } else { 
      Message (MSG_POST,"opened %s for input\n", "JAMKEY.TM1"); 
    } 
    
    i=0; 
    
    while (fgets(line,MAXLINE,indexfile)) { 
      fprintf (newfile,"%s",line); 
      i++; 
    } 
    
    fclose (indexfile); 
    fclose(newfile); 
    Message (MSG_POST,"JAM: rewrote %d index entries \n", i); 
    
  }
#endif
  return(1);                                               
  
} 


#ifdef NEXTVERSION    
/*---------------------------------------------------------------------*/
int compare( const void *arg1, const void *arg2 )
{
  /* Compare all of both strings: in the qsort*/
  char string1[MAXLINE]; 
  char string2[MAXLINE]; 
  int ip; 
  
  strcpy (string1, arg1); 
  strcpy (string2, arg2); 
  
  for (ip=0; ip <= (int) strlen(string1); ip++)
    string1[ip]=tolower(string1[ip]);    
  for (ip=0; ip <= (int) strlen(string2); ip++)
    string2[ip]=tolower(string2[ip]);    
  
  return strcmp(string1,string2);
}
#endif



/*---------------------------------------------------------------------*/

int jam_find(char* token)
{ 
  char line[MAXLINE], test[MAXLINE], tofind[MAXLINE]; 
  FILE *indexfile;
  int i,status; 
  
  strcpy (tofind, token); 
  /* this is to find token in indexfile. Needed for HTML. */ 
  
  indexfile = fopen("JAMKEY.INX", "r");
  if (indexfile == NULL) { 
    indexfile = fopen("JAMKEY.INX","w"); 
    if (indexfile == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open index file %s\n", "JAMKEY.INX"); 
      DEALEXIT;
      exit(-1); 
    }
    fclose (indexfile); 
    indexfile = fopen("JAMKEY.INX","r"); 
    
    if (indexfile == NULL) { 
      Message (MSG_ERROR,"Cannot reopen index file %s\n", "JAMKEY.INX"); 
      DEALEXIT;
      exit(-1); 
    }
  }  
  
  status =0; 
  i=0; 
  
  
  while (fgets(line,MAXLINE,indexfile)) { 
    if (status ==0) { 
      sscanf (line,"%s %s", test, jam_link); 
      if (strncmp(test, tofind,strlen(test) ) == 0 ) status = TRUE;
    } 
  } 
  if (status == FALSE) strcpy(jam_link, "VOID"); 
  fclose(indexfile); 
  return(status); 
} 





/*---------------------------------------------------------------------*/

int makeachapter(char *line)
{ 
  int status; 
  int i,ii,maxdos,iib, ib; 
  char* pos; 
  char myline[MAXLINE];
  char savname[MAXLINE];
  char tmpstring[MAXLINE]; 
  char extension[MAXLINE]; 
  char title[MAXLINE]; 
  
  strcpy (savname,jam_out); 
  i=0; 
  pos = line; 
  while (line[i] != '\n') { 
    i++; 
    pos++; 
  } 
  *pos = '\0'; 
  
  chapter_number++;
  section_number=0; 
  subsection_number=0; 
  line_in_input[current_jam]=0;
  
  /* compose new filename, extension first */ 
  switch (modus) { 
  case LATEX: 
    strcpy(extension,LATEXEXTENSION); 
    break; 
  case RTF: 
    strcpy(extension,RTFEXTENSION); 
    break; 
  case HTML:
    strcpy(extension,HTMLEXTENSION); 
    break; 
  default:
    break; 
  } 
  strcpy(jam_out,line);
  
  /* find first blank in tmpstring */ 
  i=0; 
  while ( (i <= (int) strlen(jam_out))  && ( 
					    /* is ascii - not supported on some systems */ 
					    ( (jam_out[i]<='Z') && (jam_out[i]>='A') ) ||  
					    (jam_out[i]<='z') && (jam_out[i]>='a') ) )  
    i++; 
  for (ii = 0; ii<=i; ii++) { 
    if ((jam_out[ii]<='z') && (jam_out[ii]>='a') ) { 
      jam_out[ii]=jam_out[ii]-32; 
    } 
  } /* uppercasing */ 
  
  strncpy(title,jam_out,i);
  title[i]=0; 
  
  if (chapter_number < 10) maxdos=1; 
  if ((chapter_number > 9) && (chapter_number< 100)) maxdos=2; 
  if (chapter_number > 99) maxdos=3; 
  if (i >= 8-maxdos) i=8-maxdos; /* DOS file name convention, allow for three-digit number*/ 
  strncpy(tmpstring,jam_out,i); 
  tmpstring[i]=0; 
  
  sprintf (jam_out,"%s%d.%s\0",tmpstring,chapter_number,extension); 
  
  /* create jam.rtf for single rtf */
  if (chapter_number == 1) {
    if ( (single_file) && ( modus == RTF) ) { 
      strcpy (jam_out, "JAM.RTF"); 
      jam_op = fopen(jam_out, "w");
      if (jam_op == NULL) { 
	Message (MSG_ERROR,"FATAL: (?) Cannot open output destination %s\n", jam_out); 
	DEALEXIT;
      } 
    } 
  } else { 
    /* no longer  chapter 1, but other mode */
    strcpy(myline,"!!!"); 
    pprint(myline);   
    strcpy(myline,""); 
    pprint(myline);   
    
    switch (modus) { 
    case LATEX:
      i=0; 
      ii=0; 
      strcpy(title, jam_out); 
      while ((title[i] != '\n') && (i < MAXLINE)) {
	clean_latex (i,title,tmpstring,&ii,myline); 
	tmpstring[ii]=title[i]; 
	ii++; 
	i++; 
      } 
      sprintf(myline,"\\mbox{}\\\\\\vspace{60pt}{\\tiny JAM produced file: %s}\n", jam_out); 
      pprint(myline); 
      strcpy(myline,"!!!"); 
      pprint(myline); 
      strcpy(myline,"");
      break; 
    case RTF: 
      if (!single_file) 
	{ sprintf (myline, "\\par \\par  \n{ \\pard \\fs20{\\v {\\i\\fs18 (JAM produced file: %s)}}\\pard \\fs20 \\qj \\par \n", savname);
	  /* strcpy(myline,"");*/
      } else { /* need to continue later */
	strcpy (myline,""); 
      } 
      break; 
    case HTML:
      sprintf(myline,"<HR><em>JAM produced file</em>:"); 
      pprint(myline); 
      strcpy(myline,"!!!"); 
      pprint(myline); 
      strcpy(myline,""); 
      /* we supply information for the next page */
      fprintf (jam_op, "  %s as <a href= %s>[next page] </a>, ",savname, jam_out); 
      fprintf (jam_op, "or <a href= %s>[overview] </a>, ", "JAMINX.HTML"); 
      fprintf (jam_op, "or <a href= %s>[table of contents] </a><HR>\n", "JAMCTS.HTML"); 
      break; 
    default:
      break; 
    }  /* end modus switch */
    pprint(myline); 
    strcpy(myline,"!!!"); 
    pprint(myline);   
    
    /* close if we're > chapter 1 */
    if ((!single_file) && (modus == RTF) ) fclose (jam_op);
    if (( modus == HTML) ||(modus == LATEX) ) fclose (jam_op);
  }
  /* open real file , regardless chapters, if not single RTF */
  if ( (!single_file) || ( modus != RTF) )  { 
    jam_op = fopen(jam_out, "w");
    if (jam_op == NULL) { 
      Message (MSG_ERROR,"FATAL: Cannot open output destination %s\n", jam_out); 
      DEALEXIT;
      exit (-1); 
    } else { 
      Message (MSG_POST,"opened %s for output\n", jam_out); 
    } 
  }    
  
  switch (modus){ 
  case LATEX: 
    strcpy(title, tmpstring); 
    while ((title[i] != '\n') && (i < MAXLINE)) {
      clean_latex (i,title,tmpstring,&ii,tmpstring); 
      tmpstring[ii]=title[i]; 
      ii++; 
      i++; 
    } 
    strcat (tmpstring, "\0"); 
    sprintf (myline, "\n\\section{%s}\n", tmpstring);
    fprintf (jam_all,"\\input{%s}\n", jam_out); 
    sprintf (myline, "\n\\chapter{%s}\n", line);
    pprint(myline);
    strcpy(myline,"!!!"); 
    pprint(myline);
    sprintf (myline,"%s %s", "%",CODE_CRN);
    pprint(myline);
    strcpy(myline,"!!!"); 
    pprint(myline);
    sprintf (myline,"%s by %-0.40s", "%",code_id);
    pprint(myline);
    strcpy(myline,"!!!"); 
    pprint(myline);
    strcpy(myline, ""); 
    break; 
  case RTF: 
    if ((!single_file) || ( (single_file) &&  (chapter_number <= 1)) )  { 
#ifdef MSWINDOWS
      strcpy(myline, "{\\rtf1 \\deff25 \\deffs20{\\fonttbl{\\f25\\fswiss Helvetica;}{\\f26\\fCourier New;}}"); 
#else
      strcpy(myline, "{\\rtf1 \\deff25 \\deffs20{\\fonttbl{\\f25\\fswiss Helvetica;}{\\f26\\fmodern Courier;}}"); 
#endif
      pprint(myline);
      strcpy(myline, "\\sectd \\sbknone\\linemod0\\linex0\\cols1\\endnhere \\pard \\fs20\\plain \\qj \n "); 
      pprint(myline);
      sprintf (myline,"{\\v %s}", CODE_CRN); 
      pprint(myline);
      strcpy(myline,"!!!"); 
      pprint(myline);
      sprintf (myline,"{\\info{\\title %s}}", code_id); 
      pprint(myline);
      strcpy(myline,"!!!"); 
      pprint(myline);
    } else {          
      sprintf (myline," \\par \\sect \\page \n"); 
      pprint(myline);      
      strcpy(myline,"!!!"); 
      pprint(myline);      
    } 
    sprintf (myline, "{\\header {\\scaps \\i %d.%s }} \\par  ",chapter_number, line);
    pprint(myline);
    strcpy(myline,"!!!"); 
    sprintf (myline, "\\par \\par  \n{ {\\v {\\tc\\tcl1\\pard \\fs20\\plain \\qj \\b\\fs36 %d %s}}}\\par \\fs20  \\qj \\par \n",chapter_number, line);
    pprint(myline);
    strcpy(myline,"!!!"); 
    pprint(myline);
    strcpy(myline,""); 
    break; 
  case HTML: 
    fprintf (jam_all,"<LI> <a href=%s%s>%s</a>\n",JAMPATH,jam_out,line); 
    fprintf (jam_cts,"<HR><a href=%s%s><H2>%d. %s</H2></a>\n",
	     JAMPATH,jam_out,chapter_number,line);
    strcpy (title, line);
    iib=0;      
    for (ib=0; ib<= (int) strlen(line); ib++) {
      if (isalnum(line[ib])) {
	line[iib]=line[ib];
	iib++;
      }
    }		  	
    line[iib]=0;	 
    sprintf (myline, "<title>Chapter %d: %s</title><H1>%s</H1><p>\n",chapter_number,line, title);    
    fprintf(jam_index,"%s %s%s\n",line, JAMPATH,jam_out);
    pprint(myline);
    strcpy(myline,"!!!"); 
    pprint(myline);
    sprintf (myline,"<!--%s-->", CODE_CRN); 
    pprint(myline);
    sprintf (myline,"<!--this file was generated by %s-->", code_id); 
    pprint(myline);
    strcpy(myline, ""); 
    break; 
  default:
    break; 
  } 
  if (chapter_number == 1) { /* tell them who we are. We have no file 
				open if chapter is 0. Otherwise, this
				part is executed in open file. This is 
				nice as the self-evident MASTER.JAM 
				only shows up if it really contains 
				JAM code.       */
    switch (modus) {
    case RTF: 
      sprintf (myline, "{\\v JAM file: %s}",jam_file[current_jam]);     
      break; 
    case HTML: 
      sprintf (myline, "<!--- JAM file: %s -->",jam_file[current_jam]);     
      break; 
    case LATEX:
      sprintf (myline, "%s JAM file: %s","%",jam_file[current_jam]);     
      pprint(myline); 
      sprintf (myline,"!!!");  
      break; 
    default: 
      break; 
    }
  }
  
  pprint(myline); 
  status =1; 
  return(status); 
} 
/*---------------------------------------------------------------------*/

int makeasection(char *line)
{ 
  int status; 
  int i,ii; 
  char* pos; 
  char myline[MAXLINE],title[MAXLINE], tmpstring[MAXLINE]; 
  
  i=0; 
  pos = line; 
  while (line[i] != '\n') { 
    i++; 
    pos++; 
  } 
  *pos = '\0'; 
  
  section_number++; 
  subsection_number=0; 
  ii=0;
  i=0;  

  switch (modus){ 
  case LATEX: 
    strcpy(title, line); 
    while ((title[i] != '\n') && (i < MAXLINE)) {
      clean_latex (i,title,tmpstring,&ii,line); 
      tmpstring[ii]=title[i]; 
      ii++; 
      i++; 
    } 
    strcat (tmpstring, "\0"); 
    sprintf (myline, "\n\\section{%s}\n", tmpstring);
    break; 
  case RTF: 
    sprintf (myline, "\n\\par \\par \\par  \n{\\v {\\tc\\tcl2\\pard \\fs20\\plain \\qj \\fs28 \\b %d.%d %s}}\\par \\fs20 \\qj \\par \n",chapter_number,section_number, line);
    break; 
  case HTML: 
    sprintf (myline, "\n<p><HR><H1>%s</H1><p>\n", line);
    fprintf (jam_cts,"<H4>%d.%d. %s</H4>\n",chapter_number,section_number,line); 
    break; 
  default:
    break; 
  } 
  pprint(myline); 
  status =1; 
  return(status); 
} 
/*---------------------------------------------------------------------*/

int makeasubsection(char *line)
{ 
  int status; 
  int i,ii; 
  char* pos; 
  char myline[MAXLINE],title[MAXLINE], tmpstring[MAXLINE]; 
  
  i=0; 
  pos = line; 
  while (line[i] != '\n') { 
    i++; 
    pos++; 
  } 
  *pos = '\0'; 
  
  subsection_number++; 
  ii=0;
  i=0;  
  
  switch (modus){ 
  case LATEX: 
    strcpy(title, line); 
    while ((title[i] != '\n') && (i < MAXLINE)) {
      clean_latex (i,title,tmpstring,&ii,line); 
      tmpstring[ii]=title[i]; 
      ii++; 
      i++; 
    } 
    strcat (tmpstring, "\0"); 
    sprintf (myline, "\n\\subsection{%s}\n", tmpstring);
    break; 
  case RTF: 
    sprintf (myline, "\n\\par  \\par  \n{\\v {\\tc\\tcl3\\pard \\fs20\\plain \\qj \\ul \\fs20  %d.%d.%d %s }}\n \\fs20 \\par \\par \\qj \\par \n",chapter_number,section_number,subsection_number, line);
    break; 
  case HTML: 
    sprintf (myline, "\n<p> <H2>%s</H2><p>\n", line);
    fprintf (jam_cts,"<H5>%d.%d.%d. %s</H5>\n",
	     chapter_number,section_number,subsection_number,line); 
    break; 
  default:
    break; 
  } 
  pprint(myline); 
  status =1; 
  return(status); 
} 

/*---------------------------------------------------------------------*/

int process_verbatim(void)
{ 
  int status; 
  char myline[MAXLINE]; 
  
  switch (modus){ 
  case LATEX: 
    if (!verbatim){ 
      sprintf (myline,"!!!"); 
      pprint(myline); 
      /* OLD CODE sprintf (myline, "\n\\begin{verbatim}\n");   */   
      /* NEW CODE: WE'LL PRINT IF WE DIDN'T FIND -v- next line */
      sprintf (myline, ""); 
      verbatim = TRUE; 
      did_a_print = 0; 
    } else { 
      /* if (modus== LATEX) { OLD CODE */ 
      if (did_a_print < 2) { 
	/* OLD CODE 
	   sprintf(myline,"%80s\n","."); 
	   pprint(myline); 
	   }  
	   }          
	   */                                	
	/* NEW CODE FOLLOWS */                	
	sprintf (myline, "\\mbox{}\\\\\n\\mbox{} \\\\");  
	did_a_print= 0;  
      } else {
	sprintf (myline, "\\end{verbatim}");     
      } /* END OF NEW CODE */
      pprint(myline); 
      sprintf (myline,"!!!");
      pprint(myline); 
      sprintf (myline,"");
      did_a_print=0; 
      /* last_verbatim=line_in_input[current_jam]; OLD CODE */
      verbatim = FALSE; 
    } 
    break; 
  case HTML: 
    if (!verbatim){ 
      sprintf (myline, "\n <PRE>\n");
      verbatim = TRUE; 
    } else { 
      sprintf (myline, "\n </PRE>\n");
      verbatim = FALSE; 
    } 
    break; 
  case RTF: 
    if (!verbatim){     
      sprintf (myline, "{\\plain  \\f26 \\fs20\n \\ql\n" );
      verbatim = TRUE; 
    } else { 
      sprintf (myline, "}\\fs20 \\pard \\qj \n");
      did_feed = TRUE; 
      verbatim = FALSE; 
    } 
    break; 
    
  default:
    break; 
  } 
  pprint (myline); 
  status =1; 
  return(status); 
} 
/*---------------------------------------------------------------------*/

int process_special(void)
{
  int status;
  char myline[MAXLINE];
  
  if (special_on == TRUE) special_on=FALSE;
  else
    special_on=TRUE;
  switch (modus){
  case LATEX:
    sprintf (myline,"!!!");
    pprint (myline);
    if (!special){
      /* if (last_verbatim+1 == line_in_input[current_jam]) {
	 sprintf (myline, " \\mbox{}\\\\{\\em \n");
	 } else {
	 sprintf (myline, "\n\n \\mbox{}\\\\ { \\em \n");
	 } 
	 OLD CODE */
      sprintf (myline, "\n\\mbox{}\\\\ \n\\mbox{}\\\\ {\\em \n");		 
      special = TRUE;
    } else {
      sprintf (myline, "\n\\mbox{}\\\\ \n\\mbox{}\\\\}\n");
      special = FALSE;
      /* last_verbatim=line_in_input[current_jam];  OLD CODE */
    }
    pprint (myline);
    sprintf (myline,"!!!");
    break;
  case HTML:
    if (!special){
      sprintf (myline, "<p><em>\n");
      special = TRUE; 
    } else { 
      sprintf (myline, "</em><p>\n");
      special = FALSE; 
    } 
    break; 
  case RTF: 
    if (!special){       
      if (did_feed)   {
	sprintf (myline, "{\\par \\par \\fs20 \\i \\qj \n");
	did_feed = FALSE;
      } else {
	sprintf (myline, "{\\par \\par \\par \\fs20 \\i \\qj \n");
      }
      special = TRUE;
    } else {
      sprintf (myline, "\\par}\\pard \\qj \\fs20 \n");
      special = FALSE;
      did_feed = TRUE;
    }
    break;
  default:
    break;
  }
  pprint(myline);
  status =1; 
  strcpy (myline,""); 
  return(status); 
} 
/*---------------------------------------------------------------------*/

int process_emphasis(void)
{
  int status;
  char myline[MAXLINE];
  
  switch (modus){
  case LATEX:
    if (!emphasis_on) { 
      sprintf (myline, "{\\bf ");
    } else {
      sprintf (myline, " }\n ");
    }
    break;
  case HTML:
    if (!emphasis_on){
      sprintf (myline, "<strong>");
    } else { 
      sprintf (myline, "</strong>");
    } 
    break; 
  case RTF: 
    if (!emphasis_on){       
      sprintf (myline, "{\\b ");
    } else {
      sprintf (myline, "}");
    }
    break;
  default:
    break;
  }
  if (emphasis_on == TRUE) 
    emphasis_on=FALSE;
  else
    emphasis_on=TRUE;
  
  pprint(myline);
  status =1; 
  strcpy (myline,""); 
  return(status); 
} 
/*---------------------------------------------------------------------*/

void  process_reference(char *line)
{ 
  int status; 
  int i,curpointer; 
  char myline[MAXLINE], currentline[MAXLINE], realine[MAXLINE]; 
  
  /* we break the iron rule here and one line. We don't 
     really resolve this but it is for external referencing. */ 
  
  link_on = FALSE; 
  
  sprintf (myline,"!!!");   /* you never know how long the link is */ 
  pprint (myline); 
  strcpy (myline,""); 
  
  /* now the link */ 
  
  status = readline (currentline); 
  if (!status) { 
    /* bah! no link here! kill'em. */ 
    Message (MSG_ERROR, "Line %d in %s : Erraneous link", 
	     jam_lineno[current_jam], jam_file[current_jam]); 
    exit (-1); 
  } 
  
  for (i=0; i< MAXLINE; i++) myline[i]=0; 
  i=0; 
  curpointer=0; 
  
  /* if there's symbolic stuff do it here in currentline. Do this 
     by replacing anything ithin '$' pairs with the variable found in */
  
  process_link (currentline); 
  
  strcpy (myline, currentline ); 
  strcpy (realine, currentline); /* save copy for HTML */; 
  strcpy (currentline,""); 
  
  while ((myline[i] != '\0') && (i < MAXLINE)) {
    switch (modus) { 
    case LATEX:  
      if (!verbatim)  {   
	clean_latex(i,myline,currentline,&curpointer,"VOID"); 
      }
      break; 
    case HTML: 
      if (myline[i] == '>') { 
	currentline[curpointer] = '&';
	currentline[curpointer+1] = 'g';
	currentline[curpointer+2] = 't';
	myline[i] = ';';
	curpointer= curpointer+3;
      } 
      if (myline[i] == '<') { 
	currentline[curpointer] = '&';
	currentline[curpointer+1] = 'l';
	currentline[curpointer+2] = 't';
	myline[i] = ';';
	curpointer= curpointer+3;
      } 
      break; 
    case RTF:  
      if (myline[i] <  ' ') { 
	myline[i] = ' ';
      } 
      if (myline[i] == '\\') { 
	currentline[curpointer] = '\\';
	curpointer++; 
      } 
      if (myline[i] == '{') { 
	currentline[curpointer] = '\\';
	curpointer++; 
      } 
      if (myline[i] == '}') { 
	currentline[curpointer] = '\\';
	curpointer++; 
      } 
      
      break; 
    default:
      break;
    } 
    currentline[curpointer] = myline[i]; 
    curpointer++; 
    i++; 
  } 
  
  
  
  switch (modus){ 
  case LATEX: 
    sprintf (myline, "\\mbox{}\\\\ %s {\\em \n %s }\\\\\n", LATEXLINKSTRING, currentline);
    break; 
  case HTML: 
    sprintf (myline, "<p> %s <em> <a href=%s> %s </a> </em> <p>\n", 
	     HTMLLINKSTRING, realine, currentline);
    break; 
  case RTF:
    sprintf (myline, "{\\par %s \\i %s \\par} \n",RTFLINKSTRING,currentline);
    break; 
  default:
    break; 
  } 
  link_on=FALSE; 
  pprint(myline);
  strcpy (myline,""); 
  
} 
/*---------------------------------------------------------------------*/

int process_item(void)
{ 
  int status; 
  char myline[MAXLINE]; 
  
  switch (modus){ 
  case LATEX: 
    sprintf (myline,"!!!");  
    pprint(myline); 
    if (!item){ 
      sprintf (myline, "\n\\begin{itemize}\n");
      item = TRUE; 
    } else { 
      sprintf (myline, "\n\\end{itemize}\n");
      item = FALSE; 
      item_on = FALSE; 
    } 
    pprint(myline);
    sprintf (myline,"!!!");  
    break; 
  case HTML: 
    if (!item){ 
      sprintf (myline, "\n<UL>");
      item = TRUE; 
    } else { 
      sprintf (myline, "\n</UL><p>");
      item = FALSE; 
      item_on = FALSE; 
    } 
    break; 
  case RTF: 
    if (!item){  
      if (did_feed ) {
	sprintf (myline, " \\par \n");
	did_feed = FALSE;
      } else {
	sprintf (myline, "\n\\par \\par\n");
      }
      item = TRUE;
      did_feed = TRUE; 
    } else {        
      /* added in 2.1: justified after itemization */
      sprintf (myline, " \\par \\pard \\qj \n" ); 
      /* sprintf (myline, " \\par \\pard \n"); - OLD CODE */
      did_feed = TRUE;  
      item_on = FALSE;
      item = FALSE;
    }
    break; 
  default:
    break; 
  } 
  pprint(myline); 
  status =1; 
  return(status); 
} 
/*---------------------------------------------------------------------*/

int process_anitem(char* current)
{ 
  int status; 
  char myline[MAXLINE]; 
  
  
  switch (modus){ 
  case LATEX: 
    current[0] = ' ';
    sprintf (myline,"!!!"); 
    pprint(myline); 
    sprintf (item_prefix, "\n \\item");
    break; 
  case HTML: 
    current[0] = ' '; 
    sprintf (item_prefix, "<p><LI>");
    break; 
  case RTF: 
    current[0] = ' ';  
    if (did_feed ) {
      /* new in 2.1 - less identation for subsequent bulleted item lines */
      sprintf(item_prefix, " \\pard \\fs20 \\ql \\fi-600\\li1000\\tx600 \\bullet \\tab ");
      did_feed = FALSE;
    } else {
      sprintf(item_prefix, "\\par \\pard \\fs20 \\ql \\fi-600\\li1000\\tx600 \\bullet \\tab");
      /* OLD CODE 
	 sprintf(item_prefix, " \\pard \\fs20 \\ql \\fi-1300\\li1800 \\bullet");
	 did_feed = FALSE;
	 } else {
	 sprintf(item_prefix, "\\par \\pard \\fs20 \\ql \\fi-1300\\li1800 \\bullet");
	 END OF OLD CODE */ 
    }
    break;
  default:
    break;
  }
  status =1;
  return(status); 
} 


/*---------------------------------------------------------------------*/
int clean_latex(const i, char* interim_string, char* interim_rentline, 
		int *interim_pointer,char* linkbody)
     
{  
  int ii; 
  ii = *interim_pointer; 
  if (strcmp(linkbody,"NULL") == 0)  { 
    if (interim_string[i] == '%') { 
      interim_string[i] = ' ';
      /* VMS_STATUS link type -> index */ 
      if (interim_string[i+1] == '-') { 
	if (vms_status) interim_string[i+1] = '/';
      }
    } 
  } 
  if (interim_string[i] == '$') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '_') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '{') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '}') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  
  if (interim_string[i] == '#') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '%') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '&') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '^') { 
    interim_rentline[ii] = '\\';
    ii++; 
  } 
  if (interim_string[i] == '>') { 
    interim_rentline[ii] = '{';
    interim_rentline[ii+1] = '\\';
    interim_rentline[ii+2] = 't';
    interim_rentline[ii+3] = 't';
    interim_rentline[ii+4] = '>';
    
    interim_string[i] = '}';
    ii= ii+5;
  } 
  if (interim_string[i] == '~') { 
    interim_rentline[ii] = '\\';
    interim_rentline[ii+1] = '~';
    interim_rentline[ii+2] = '{';
    interim_rentline[ii+3] = ' ' ;
    
    interim_string[i] = '}';
    ii= ii+4;
  } 
  if (interim_string[i] == '<') { 
    interim_rentline[ii] = '{';
    interim_rentline[ii+1] = '\\';
    interim_rentline[ii+2] = 't';
    interim_rentline[ii+3] = 't';
    interim_rentline[ii+4] = '<';
    interim_string[i] = '}';
    ii= ii+5;
  } 
  if (interim_string[i] == '|') { 
    interim_rentline[ii] = '{';
    interim_rentline[ii+1] = '\\';
    interim_rentline[ii+2] = 't';
    interim_rentline[ii+3] = 't';
    interim_rentline[ii+4] = '|';
    interim_string[i] = '}';
    ii= ii+5;
  } 
  if (interim_string[i] == '\\') { 
    interim_rentline[ii] = '{';
    interim_rentline[ii+1] = '\\';
    interim_rentline[ii+2] = 't';
    interim_rentline[ii+3] = 't';
    interim_rentline[ii+4] = '\\';
    interim_string[i] = '}';
    ii= ii+5;
  } 
  *interim_pointer = ii;
  return(1);  
} 



/*---------------------------------------------------------------------*/

void pprint(char*  myline)
{ 
  static int done,printlinepos; 
  int counter,i,ipos,ii,needtoflag;
  static char printline[MAXLINE*2]; 
  int already_done = FALSE; 
  
  /* done is a static variable to hold the last position of a \n */ 
  counter=0; 
  ipos=0; 
  /* remove duplicate line feeds */ 
  while ( ipos < (int) strlen(myline)) 
    { 
      if (verbatim) { 
	if (myline[ipos] != '\n') counter++; 
      } else { 
	if ((myline[ipos] != '\n') && (myline[ipos] != ' ')) counter++; 
      } 
      if (myline[ipos] == '\n'){
	if (counter == 0 ) { 
	  myline[ipos] =' '; 
	}else{  
	  /* nothing, yet */  
	} 
      } 
      
      /* add mode-specific line feeds */ 
      
      
      /* myline[0],[1],[2] are '!!!' to 'flush' the line */ 
      /* if !x! is seen there is a requested linefeed. */ 
      if ( 
	  (printlinepos >= (MAXWIDTH-MARGIN) ) || 
	  (strncmp(myline,"!!!",3) == 0)        || 
	  (strncmp(myline,"!x!",3) == 0)        || 
	  (strncmp(myline,"!X!",3) == 0)     ) { 
	if ((myline[0] == '!') && ( myline[2] == '!')) {
	  if (strncmp(myline,"!!!",3) ==0){ 
	    strcpy(myline,"");
	    needtoflag = FALSE; 
	    printline[printlinepos]='\0'; 
	    if (strlen(printline) > 0 ) {
	      if (jam_op != NULL ) {
		fprintf (jam_op, "%s \n", printline);
		for (i=0; i < MAXLINE*2; i++) printline[i]=0; 
		ipos = strlen(myline); 
	      }
	    }
	  }
	  if (strncmp(myline,"!x!",3) ==0){
	    strcpy(myline,"");
	    needtoflag = FALSE;
	    printline[printlinepos]='\0';
	    if (jam_op != NULL ) {
	      if (!verbatim) {
		switch (modus) {
		case RTF:
		  fprintf (jam_op, "%s  \\par\n", printline);  
		  break; 
		case HTML: 
		  fprintf (jam_op, "%s  <p>\n", printline);  
		  break;
		case LATEX:  
		  fprintf (jam_op, "%s  \\mbox{} \\\\\n", printline);  
		  
		  break;
		}
		for (i=0; i < MAXLINE*2; i++) printline[i]=0;   
		ipos = strlen(myline);
	      }
	    } 
	  }
	  if (strncmp(myline,"!X!",3) ==0){
	    strcpy(myline,"");
	    needtoflag = FALSE;
	    printline[printlinepos]='\0';
	    if (jam_op != NULL ) {
	      if (!verbatim) {
		switch (modus) {
		case RTF:  
		  fprintf (jam_op, "%s \\par \\page\n", printline);  
		  break; 
		case HTML: 
		  fprintf (jam_op, "%s  <p><HR><HR><p>\n", printline);  
		  break;
		case LATEX:  
		  fprintf (jam_op, "%s  \\clearpage \\newpage \n", printline);  
		  strcpy (printline,""); 
		  break;
		}
		for (i=0; i < MAXLINE*2; i++) printline[i]=0; 
		ipos = strlen(myline); 
	      }
	    }      
	  }
	  printlinepos=0; 
	  counter=0;         
	  
	} else 
	  needtoflag=TRUE;
      } 
      else
	needtoflag=FALSE; 
      
      if (!verbatim && ( (myline[ipos] == ' ')  && ( needtoflag == TRUE) ) ) { 
	/* need to print */ 
	needtoflag = FALSE; 
	printline[printlinepos]=0; 
	if (jam_op != NULL ) { 
	  fprintf (jam_op, "%s \n", printline);    
	  for (i=0; i < MAXLINE*2; i++) printline[i]=0; 
	  
	  
	} else { 
	  Message (MSG_ERROR,"ERROR: JAM needs 'chapters' to work with \n"); 
	  DEALEXIT;
          exit (-1); 
	} 
	printlinepos=0; 
	for (ii=0; ii< MAXLINE*2; ii++) printline[ii]=0; 
	
	counter=0; 
      } 
      if (counter >0 ) {
	if ( verbatim && (myline[ipos] == '\n')){ 
	  printline[printlinepos]='\0'; 
	  fprintf (jam_op, "%s ", printline);    
	  for (i=0; i < MAXLINE*2; i++) printline[i]=0; 
	  
	  if ( (modus == RTF) && (verbatim))   fprintf (jam_op, "\\par "); 
	  printlinepos=0;    
	} 
	switch (modus) { 
	case LATEX:
	  if ((already_done == 0 ) && (verbatim))  { 
	    did_a_print++; 
	    already_done = TRUE; 
	  } /* empty verbatim lines hurt, therefore we count that we printed */ 
	  break; 
	case HTML:
	  if (!verbatim) 
	    if ( ( (myline[ipos] == '<' ) && 
		  (myline[ipos+1] == 'p' ) ) && 
		(myline[ipos+2] == '>' )  ) { 
	      printline[printlinepos]=0;
	      if (strlen(printline) > 0)  { 
		fprintf (jam_op, "%s \n", printline);
		
		for (i=0; i < MAXLINE*2; i++) printline[i]=0; 
		
		
	      } else { 
		if (jam_op != NULL ) { 
		  fprintf (jam_op, "<p>\n"); 
		  for (i=0; i < MAXLINE*2; i++) printline[i]=0;
		  
		} 
	      } 
	      printlinepos=0; 
	    } 
	default: 
	  break; 
	} 
	
	
	if (!verbatim) { 
	  if ((myline[ipos] == ' ') && (printline[printlinepos-1] == ' '))  { 
	    /* do nothing - don't accumulate spaces  */
	  } else { 
	    if (myline[ipos] == '\n')  { 
	      /* don't do line feeds either */ 
	    } else { 
	      if ( ipos < (int) strlen(myline) ) { /* we added up ipos in case of \n */ 
		printline[printlinepos] = myline[ipos]; 
		printlinepos++;
	      } 
	    } 
	  } 
	} else { 
	  printline[printlinepos] = myline[ipos]; 
	  printlinepos++; 
	} 
      } 
      ipos++;
    } 
  for (i=0; i < MAXLINE; i++) myline[i]=0;  
} 


/* use a simple way to detect $ characters and expand these accordingly */ 

void process_link (char* currentline) 
{ 
  char procline[MAXLINE], fileline[MAXLINE], foundlink[MAXLINE]; 
  char *token, *body, *link; 
  char bodystring[MAXFIL]; 
  
  body = bodystring; 
  
  if (strlen(currentline) > 0 ) {  
    sscanf (currentline,"%s", procline);
  } else { 
    return; 
  } 
  strcpy (foundlink, ""); 
  strcpy (body, ""); 
  strcpy (fileline, procline); /* save copy to see whether $ found */ 
  
  if ((link = strtok (procline,"$")) != NULL ) {
    if (strcmp(procline,fileline) == 0 ) { 
      /* same line, no $ */
      return; 
    } else { 
      /* found a $ charcater */ 
      body = strtok(NULL, "$"); 
      if (body == NULL) {
	body = bodystring; /* make it point to an empty string, not NULL */ 
      }
      /* search for it in the link database */ 
      rewind (jam_lnk); 
      while (fgets (fileline,MAXLINE-3,jam_lnk)) { 
	token = strtok (fileline," "); 
	if (strcmp(token,link) == 0 ){ 
	  /* found link! */ 
	  token = strtok (NULL, " \n\t"); 
	  if (token != NULL) { 
	    strcpy (foundlink, token);
	  } 
      	} 
      } /* end of reading file */            
    }
  } else { 
    /* nothing found */ 
    return; 
  } 
  
  if ((body != NULL ) && ((int) strlen(body) >0) ) { 
    /* only link expansion */ 
    sprintf (currentline, "%s",foundlink);
  } else { 
    /* new link ready */ 
    sprintf (currentline, "%s%s",foundlink,body); 
  } 
  return;
} 



