[comp.text] index insertor for Scribe, TeX/LaTeX, *roff , etc

jbw@unix.cis.pittsburgh.edu (Jingbai Wang) (07/14/89)

If you are a technical writer or book writer, you would have found that
the most tedious job is to add an index to a book you have written. I am
a heavy writer, and I use Scribe (with my own TEC.mak data base) and
TeX/LaTeX to format books.

To overcome the tediousness and boresomeness of index making, I developed
a program in C named 'indexor' that I revealed in a previous message in
comp.text. Here I am introducing the source code into comp.text and
comp.source.unix. 

This program named `indexor.c' can be compiled on VMS, UNIX or DOS, and have
helped me with two lengthy books already. You can called it a semi-automatic
index insertor. You need an ANSI terminal (like vt100, vt102) to make
it work properly.

Cut here
_________________________________________________________________


/*  Copyright (C) 1988 by Jingbai Wang */


/* **********************************************************************
 *            This program is an auxiliary program for Scribe and TeX   *
 *               It inserts index and glossary into Scribe/LaTeX file   *
 *                  It is an important program for book editing         *
 *    The user can set up the programs for other formattors like troff  *
 *                                                                      *
 *                    Copyright by Jingbai Wang August 1988             *
 *                                                                      *
 *    jbw@pittvms.bitnet                                                *
 *    jbw@cisunx.UUCP                                                   *
 ************************************************************************/
/*
    This program was created in 1988 by myself in order to include an
    index in the Scribe and TeX/LaTeX manuals I was writing. It is part
    of the Scribe TEC.mak package I developed, and can be re-distributed
    freely for non-profit purposes.

    It is like a special editor to introduce index entries into a Scribe,
    LaTeX, TeX or *troff file. It indeed makes a tedious and boresome job
    enjoyable.
    The primary attempt is to make this program portable among
    VAX/VMS, UNIX (BSD and Ultrix), and DOS (MSC and MS Quick C).

    To compile on our VMS,
    $ex indexor

    and on UNIX,
    %cc -o indexor indexor.c

    It takes two on-line arguments, i.e., the input and output file names,
    but you can also provide these piece of information when running it.
    The program is self-instructive, no documentation is necessary.
*/

#include <string.h>
#include <stdio.h>
#define CLS printf("\033[2J")
#define GOTOXY(x,y) printf("\033[%d;%df",x,y)
#define REVERSE printf("\033[7m")
#define NORMAL printf("\033[0m")
#define SAVE_CURSOR printf("\033[s")
#define BLINK printf("\033[5m")
#define BOLD printf("\033[1m")
#define UNDER printf("\033[4m")
#define ERASE printf("\033[K")
#define CURSOR_REPORT(x, y) scanf("\033[%d;%dR",x,y)
#define BELL printf("%c", 7)
#define CURSOR_RIGHT printf("\033[1C")
#define CURSOR_LEFT printf("\033[1D")

#define tt_open 1
#define tt_close 0
int tt_status=0;

#if VMS|unix
#define RESTORE_CURSOR cursor_position()
#else
#define RESTORE_CURSOR printf("\033[u")
#endif

#if ultrix
#define V7 1
#endif

#if unix|VMS
/*   ANSI escape, good for mainframe systems vt100 terminals, e.g., VAX*/
#define DEL 127
#define EXT 27
#define EXT1 '['
#define R_ARROW 'C'
#define L_ARROW 'D'
#define D_ARROW 'B'
#define U_ARROW 'A'

#if VMS
#include        <descrip.h>
#include        <iodef.h>
#include        <ssdef.h>
short   iochan;                  /* TTY I/O channel             */
#endif


#else
 /* MSDOS extended code escape */
#define DEL  8
#define EXT  0  
#define R_ARROW 77
#define L_ARROW 75
#define D_ARROW 80
#define U_ARROW 72
#endif

FILE *infile;
FILE *outfile;
char buffer[720];
int buffer_length;
int buffer_line[11];
int lines=1;
int cursor_mark=0;
int cursor_last=0;

char marker=0;
char phrase_str[512]="";
char the_phrase[512];
char save_str[128]="";
char out_str[512]="";
int phrase_on, phrase_off, phrase_len;
char end_infile=0;
char end_outfile=0;
char exit_flag=0;
char word_mark=0;
char the_index[20]="@Index";
char the_delimiter1[3]="{";
char the_delimiter2[3]="}";
char the2_delimiter1[3]="<";
char the2_delimiter2[3]=">";
char the_primary[20]="Primary=";
char the_second[20]="Secondary=";
char the_gloss[20]="@glossary";
char g_primary[20]="symbol=";
char g_second[20]="expln=";
char the_indexsecond[20]="@IndexSecondary";
char the_seealso[20]="@SeeAlso";
char the_indexentry[20]="@IndexEntry";
char the_entry[20]="Entry=";
char the_key[20]="Key=";
char the_number[20]="Number=";

struct CUR
{
short int x;
short int y;
} chr[720];

char next_str[512];
char next_flag=0;
char command_line[160];



/* The getch() and getche() */

#if VMS
char getch()
{
int ibuf,status;
int     iosb[2];
                        status = SYS$QIOW(0, iochan, IO$_READLBLK|IO$M_NOECHO,
                                 iosb, 0, 0, &ibuf, 1, 0, 0, 0, 0);

        return (ibuf & 0xFF);    /* Allow multinational  */

}

#endif


#if unix | ultrix | BSD

char getch()
{
int tmpch;
ttopen();
tmpch=ttgetc();
ttclose();
return(tmpch);
}
#endif


#if unix | VMS
char getche()
{
char inchar;
fputc(getch(), stdout);
return((int)inchar);
}

#endif

read_in()
{
int i, quit_s;
char string[81],quit;
GOTOXY(3,1);
buffer_length=0;
buffer[0]=0;
string[0]=0;
           quit_s=0;


for (i=1;i<=8;i++)
  { if( fgets(string,80,infile)==NULL)  { end_infile=1;
           quit_s=1; goto quit;}
     else { printf("%s",string);
           strcat(buffer,string);
           }
  }

quit:
buffer_length=strlen(buffer);

position();
GOTOXY(3,1);
return(quit_s);
 }

position()
{
int i,j;
int row,col;
char ch;
row=3; col=1;
buffer_line[1]=0;
lines=1;

for(i=0;i<buffer_length;i++)
  {  ch=buffer[i];
   chr[i].x=row; chr[i].y=col++;

   if(ch==10) {row++;col=1;lines++;buffer_line[lines]=i+1;}

   if (col==81) {row++;col=1;lines++; buffer_line[lines]=i+1;}
   }  

}


mark_begin()
{
int i;

 for (i=cursor_last;i<cursor_mark;i++)
      {fprintf(outfile, "%c", buffer[i]);
        if (buffer[i]==10)
	 {if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
	 }
       
      }
marker=1;
cursor_last=cursor_mark;
phrase_len=0;
phrase_on=cursor_mark;
phrase_str[0]=0;
REVERSE;
printf("%c",buffer[cursor_mark]);
cursor_position();
}

mark_end()
{
int i, length;
char  ch;
marker=0;

 for (i=cursor_last;i<=cursor_mark;i++)
      { fprintf(outfile, "%c", buffer[i]);
         if (buffer[i]==10)
	 { 
           if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
	 }


      }

length=strlen(phrase_str);
phrase_off=cursor_mark;
cursor_last=cursor_mark+1;
cursor_mark=cursor_last; cursor_position();
for (i=phrase_on; i<=phrase_off;i++)
  { ch=buffer[i];
   if ((ch==13)||(ch==10)) ch=32;
    phrase_str[length+i-phrase_on]=ch;
  }
phrase_str[length+1+phrase_off-phrase_on]=0;
phrase_on=0; phrase_off=0;
NORMAL;
}

cursor_position()
{
GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
}

cursor_right()
{

if (cursor_mark>=buffer_length-1) {next_page(); return;}
   ++cursor_mark; cursor_position();
   if (marker==1) printf("%c",buffer[cursor_mark]);
   GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);

}

cursor_left()
{
  if (cursor_mark<=cursor_last) {cursor_mark=cursor_last; cursor_position();BELL; return;}
  NORMAL; cursor_position();printf("%c",buffer[cursor_mark]);
  --cursor_mark;
  if (marker==1) REVERSE;
  GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);


}

cursor_down()
{
int i,the_stop;
char check;
the_stop=cursor_mark;

cursor_position();
for (i=cursor_mark;i<buffer_length;i++)
 {if (i>=buffer_length-2) {next_page();return;}
  if (buffer[i]==10) {cursor_mark=i+1;
     cursor_position();goto check;}
 }

check:
  if (marker)
   { GOTOXY(chr[the_stop].x,chr[the_stop].y);
     for (i=the_stop;i<=cursor_mark;i++)
      printf("%c",buffer[i]);
     cursor_position();
   }
}

cursor_up()
{
char check;
int i,the_stop;
if (cursor_mark<=cursor_last) {cursor_mark=cursor_last;cursor_position(); BELL; return;}

cursor_position();the_stop=cursor_mark;
for (i=cursor_mark;i>=cursor_last;i--)
 {
  if (buffer[i]==10) {cursor_mark=i-1;
  GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
  goto check;}
 }
 cursor_mark=cursor_last; cursor_position(); BELL;

check:
  if (marker)
   {
    NORMAL; GOTOXY(chr[cursor_mark+1].x,chr[cursor_mark+1].y);
    for (i=cursor_mark+1;i<=the_stop;i++)
       printf("%c",buffer[i]);
    REVERSE;
    GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
   }

}






mark_word()
{
if (marker==0) mark_begin(); word_skip();return;
}

pass_marked()
{
int i;
if (marker==0) { word_skip();return;}
GOTOXY(chr[cursor_last].x,chr[cursor_last].y);
marker=0; NORMAL;
 phrase_str[0]= 0;
 for (i=cursor_last;i<=cursor_mark;i++)
     printf("%c",buffer[i]);

cursor_mark=cursor_last;
cursor_position();
}


word_skip()
{
int i, the_stop;
char check;

the_stop=cursor_mark;
if (cursor_mark>=buffer_length-1) {next_page(); return;}

cursor_right();
for (i=cursor_mark; i<buffer_length;i++)
 {

  switch(buffer[i])
   {case '!':
    case ',':
    case '"':
    case '\'':
    case '`':
    case '(':
    case ')':
    case '[':
    case ']':
    case '/':
    case '+':
    case '=':
    case '?':
    case '<':
    case '>':
    case '{':
    case '}':
    case '*':
    case '^':
    case '&':
    case '#':
    case ':':
    case ';':
    case '|':
    case  9:
    case 10:
    case 13:
    case '~':
    case '@':
    case '\\':
    case 32:
    case '.': if (word_mark) {word_mark=0;cursor_mark=i-1;
			     cursor_position();
			     goto check;}
	      else break;
    default:   word_mark=1;

   }
  }

check:
  if(marker)
   { GOTOXY(chr[the_stop].x,chr[the_stop].y);
     for (i=the_stop;i<=cursor_mark;i++)
	printf("%c",buffer[i]);
    cursor_position();
   }

}



word_back()
{
int i, the_stop;
char check;
the_stop=cursor_mark;
cursor_left();
for (i=cursor_mark; i>=0;i--)
 { if (i<=cursor_last) {cursor_mark=cursor_last;
			cursor_position();BELL;goto check;}

  switch(buffer[i])
   {case '!':
    case ',':
    case '"':
    case '\'':
    case '`':
    case '(':
    case ')':
    case '[':
    case ']':
    case '/':
    case '+':
    case '=':
    case '?':
    case '<':
    case '>':
    case '{':
    case '}':
    case '*':
    case '^':
    case '&':
    case '#':
    case ':':
    case ';':
    case '|':
    case  9:
    case 10:
    case 13:
    case '~':
    case '@':
    case '\\':
    case 32:
    case '.':
	     if (word_mark) {word_mark=0; cursor_mark=i; cursor_position();
		goto check;
	      }
	      else  break;
    default:   word_mark=1;

    }
  }

check:
  if (marker)
   {GOTOXY(chr[cursor_mark+1].x,chr[cursor_mark+1].y);
    NORMAL;
     for (i=cursor_mark+1;i<=the_stop;i++)
	 printf("%c",buffer[i]);

    REVERSE;
    cursor_position();
   }
}


next_page()
{
int i, length, pre_row, ch_count;

NORMAL;
CLS_UP();
GOTOXY(1,1);  pre_row=0; ch_count=0;

if (end_outfile) {BELL; return;}


if (marker){
 if ((strlen(phrase_str)+strlen(&buffer[phrase_on]))<510)
  strcat(phrase_str, &buffer[phrase_on]);
 else marker=0;
}

for (i=buffer_line[lines-2];i<buffer_length;i++)
 {
 if ((marker==1) && (i>=phrase_on)) {REVERSE;}
   printf("%c", buffer[i]);
 }

for (i=cursor_last;i<buffer_length;i++)
  {   fprintf(outfile,"%c",buffer[i]);
  if (buffer[i]==10)
     {
      if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }

  }


cursor_last=0;
phrase_on=0;
cursor_mark=0;
buffer_length=0;
NORMAL;

if (end_infile) {end_outfile=1;
		 GOTOXY(17, 70); BOLD;printf("[EOF]"); BELL; return;}

end_infile=read_in();
if (marker) {REVERSE; printf("%c",buffer[0]);cursor_position();}
}


control(inchar)
char inchar;
{
char ch;


 switch(inchar)
     {
       case EXT:
#if unix|VMS
             /* mainframe  environment  */
               if (getch()!=EXT1) {BELL;break;}
               ch=getch();
#else
             /* DOS environment              */ 

             ch=getch();
#endif            

             switch(ch)
              { 
               case L_ARROW: cursor_left(); 
                   break;
               case R_ARROW: cursor_right();
                   break;
               case D_ARROW: cursor_down();
                   break;
	       case U_ARROW: cursor_up();
                   break;
               default: BELL;
              }

          break;
       case 13: if (marker==0) {mark_begin(); break;}
                if (marker==1) 
                 {mark_end(); index_now();}
                 break;     
       case 9:  word_skip(); break;
       case 'b':
       case 'B':
       case 8:
       case 127:
                word_back(); break;
       case 32: next_page(); break;
       case 'n':
       case 'N': if (marker==1) 
                {mark_end();index_next_line();} 
                 else BELL; break;    
       case 'p':
       case 'P': pass_marked(); break;
       case 'f':
       case 'F': finish_up(); return(1); break;
       case 'a':
       case 'A': if (marker==1) mark_end(); see_also();break;
       case 's':
       case 'S': if (marker==1) mark_end();index_secondary();break;
       case 'i':
       case 'I': if (marker==1) mark_end();index_entry();break;
       case 'g':
       case 'G': if (marker==1) mark_end();
	      else warning("No current marked, will take the previous one");
		 glossary();
		   break;
       case 'W':
       case 'w': mark_word(); break;
       case '@': set_up(); break;
       case  6 : str_search(); break;
       case  3 : all_done(); break;
#if unix
       case  4 : all_done(); break;
#endif
       default: BELL;
   }


}




main(argc, argv)
int argc;
char *argv[];
{
int in_file,out_file, status;
int i,j;
char infile_name[30], outfile_name[30];
char out_ok=1;
char ch, quit;
char getch();

#if     VMS
$DESCRIPTOR(terminal,"TT");

        status = SYS$ASSIGN(&terminal, &iochan, 0, 0);
        if (status != SS$_NORMAL) exit(status);

system("set broadcast=none");

#endif


NORMAL;
CLS;
 
switch(argc)
  {
    case 1: in_file=1; out_file=1; break;
    case 2: in_file=0; out_file=1; strcpy(infile_name,argv[1]); break;
    default: in_file=0;out_file=0;
           strcpy(infile_name,argv[1]); 
           strcpy(outfile_name,argv[2]); break;
  }

 if (in_file) 
   {GOTOXY(5,15);
   printf(" Input file (file to be indexed) >");
   scanf("%s",infile_name);
   fflush(stdin);
   }

   if ((infile=fopen(infile_name,"r"))==NULL)
     {GOTOXY(20,20); BLINK;
       printf("Can't find the input file");
       NORMAL; goto quit;
     }

while (out_ok)

 {
  if (out_file) 
    {GOTOXY(6,15); ERASE;
    printf(" Output file (indexed file) >");
    fscanf(stdin, "%s",outfile_name);
    fflush(stdin);
    }


    out_ok=0; 
   if ((outfile=fopen(outfile_name,"r"))!=NULL)
     { out_ok=1;
       GOTOXY(7,16); ERASE;
       out_file=1;
      fflush(stdin);
      printf("File %s already exits, overwrite ? [N]", outfile_name);
      ch=getch();
      ch=getch();
        if ((ch=='y')||(ch=='Y')) out_ok=0;
        fclose(outfile);

     }

    if (out_ok==0)
       {
	outfile=fopen(outfile_name,"w");
       }
 }



NORMAL;
CLS;

help_menu();
end_infile=read_in();

 while (1)
  {
   control(getch());
   if (exit_flag) goto quit;
  }

quit:
GOTOXY(25, 1);
printf("\n\t>>> Thank you for using INDEX MAKER >>>\n");
printf("\t>>> by Jingbai Wang, August 1988 >>>\n");



}

warning(warn_str)
char *warn_str;
{
char i;

SAVE_CURSOR;
GOTOXY(24,5); REVERSE; BLINK;
printf("%s", warn_str); BELL; BELL;
for (i=1;i<10000;i++) ;
GOTOXY(24,1); RESTORE_CURSOR; NORMAL;
}

void  clr_show()
{
int i;
for (i=13;i<17;i++)
  {NORMAL; GOTOXY(i,1);ERASE;}
}


index_now()
{ int i;
fprintf(outfile, "%s%s%s%s",the_index,the_delimiter1,phrase_str,the_delimiter2);
SAVE_CURSOR;
clr_show(); out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s",the_index,the_delimiter1,out_str,the_delimiter2);
NORMAL; RESTORE_CURSOR;
}

index_next_line()
{
int i;

next_flag=1;
strcat(next_str, the_index);
strcat(next_str, the_delimiter1);
    if ((strlen(next_str)+strlen(phrase_str))<510) 
        strcat(next_str, phrase_str);
strcat(next_str, the_delimiter2);
SAVE_CURSOR;
clr_show(); out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s}", the_index,the_delimiter1,out_str,the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

see_also()
{
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Primary=");  NORMAL;printf("[%s]",save_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(command_line, save_str);
 else strcpy(save_str, command_line);
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_seealso,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,phrase_str,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_seealso,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

index_entry()
{
char entry[20], number[30];
strcpy(save_str, phrase_str);

strcpy(number, ",\nNumber=<");
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Entry=");  NORMAL;printf("[%s]",phrase_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(entry, phrase_str);
 else strcpy(entry, command_line);
GOTOXY(24,1);ERASE;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Number=");  NORMAL;
get_line();
if (memcmp(command_line,"",1)==0) number[0]=0;
 else  {strcat(number, command_line); strcat(number, ">");}


fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s%s",the_indexentry,the_delimiter1,
the_key,the2_delimiter1,phrase_str, the2_delimiter2,the_entry,
the2_delimiter1,entry,the2_delimiter2,  number, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s%s",the_indexentry,the_delimiter1,
the_key,the2_delimiter1,out_str, the2_delimiter2,the_entry,
the2_delimiter1,entry,the2_delimiter2, number, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

index_secondary()
{
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Primary=");  NORMAL;printf("[%s]",save_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(command_line, save_str);
 else strcpy(save_str, command_line);
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_indexsecond,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,phrase_str,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_indexsecond,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

glossary()
{
SAVE_CURSOR;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Description:");  NORMAL;
get_line();
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_gloss,the_delimiter1,
g_primary,the2_delimiter1,phrase_str, the2_delimiter2,g_second,
the2_delimiter1,command_line,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_gloss,the_delimiter1,
g_primary,the2_delimiter1,command_line, the2_delimiter2,g_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}


finish_up()
{ char ch;
  int i;

if(end_infile && end_outfile) {all_done(); exit();}


if (marker) {mark_end(); index_now(); }

for (i=cursor_last;i<buffer_length;i++)
  {
  if (buffer[i]==13)
     { 
      if (next_flag==1) {
			 fprintf(outfile, "%s\n\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }
  else fprintf(outfile,"%c",buffer[i]);
  }



if (end_infile==1) {all_done(); return;}
GOTOXY(24,35); BLINK; printf("Working ... \n");

    while (fscanf(infile,"%c",&ch)!=EOF)
      {
	if (ch==13);
	else fprintf(outfile, "%c", ch);
      }
  all_done();NORMAL;
}


all_done()
{
fclose(infile); fclose(outfile); exit_flag=1;
#if VMS
system("set broadcast=all");
#endif
}


CLS_UP()
{ char i;

for(i=1;i<12;i++)
  {GOTOXY(i,1); ERASE;}

}

help_menu()
{
GOTOXY(12, 1);
REVERSE; printf("                                ");
printf(" Inserting                                 ");

GOTOXY(17,1);
printf(" ===== ^H delete ======================== ^F Search string ===============");
NORMAL;
GOTOXY(18,3); BOLD; printf("SPACE BAR"); NORMAL; printf(" -- next page");
GOTOXY(19,3); BOLD; printf("<RETURN> 1"); NORMAL; printf(" -- set mark");
GOTOXY(20,3); BOLD; printf("<RETURN> 2"); NORMAL; printf(" -- end mark & index");
GOTOXY(21,3); BOLD; printf("<TAB>"); NORMAL; printf(" -- forward a word");
GOTOXY(22,40); BOLD; printf("G"); NORMAL; printf(" -- end mark & glossary");
GOTOXY(22,3); BOLD; printf("W"); NORMAL; printf(" -- mark word");
GOTOXY(21,40); BOLD; printf("B"); NORMAL; printf(" -- backward a word");
GOTOXY(20,40); BOLD; printf("N"); NORMAL; printf(" -- end mark & index in next line");
GOTOXY(19,40); BOLD; printf("P"); NORMAL; printf(" -- abandon the marked/skip a word ");
GOTOXY(18,40); BOLD; printf("F"); NORMAL; printf(" -- finish     \
        ^F--string search");
GOTOXY(23,40); BOLD; printf("S"); NORMAL; printf(" -- IndexSecondary");
GOTOXY(23,17); BOLD; printf("I"); NORMAL; printf(" -- IndexEntry");
GOTOXY(23,3); BOLD; printf("A"); NORMAL; printf(" -- SeeAlso");
GOTOXY(23,65); BOLD; printf("@"); NORMAL; printf(" -- set up");
}


set_up()
{
int the_row, i;
int ch_count;
char ch, string[81];

ch_count=0;
SAVE_CURSOR;
NORMAL; REVERSE;
GOTOXY(12,1);
printf("                            Set-up Menu                  <TAB> to quit      ");
NORMAL;
for (i=13;i<24;i++)
  {GOTOXY(i,1);ERASE;}

GOTOXY(13,3);printf("[%s]:",the_index);
GOTOXY(14,3);printf("[%s]:",the_indexentry);
GOTOXY(15,3);printf("[%s]:",the_indexsecond);
GOTOXY(16,3);printf("[%s]:",the_seealso);
GOTOXY(17,3);printf("[%s]:",the_primary);
GOTOXY(18,3);printf("[%s]:",the_second);
GOTOXY(19,3);printf("[%s]:",the_gloss);
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second);
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1);
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);

the_row=13;
set_up_in(the_row);

     while(1)
      { ch=getch();
	 switch(ch)
	 {
	  case EXT:
#if unix | VMS

	     /* VAX */
	     ch=getch(); if (ch!=EXT1) {BELL;break;}
	     ch=getch();
#else
               /* DOS                 */
	      ch=getch(); 
#endif	    
	     switch(ch)
	     {
	      case L_ARROW:
	      case U_ARROW:
			   set_up_out(the_row); ch_count=0;string[0]=0;
			   --the_row; if (the_row<13) the_row=25;
			   set_up_in(the_row); break;
	      case R_ARROW:
	      case D_ARROW:
  down:                        set_up_out(the_row);ch_count=0;string[0]=0;
			   ++the_row; if (the_row>25) the_row=13;
			   set_up_in(the_row); break;
	     default: BELL;
	     } break;
       case  3 : all_done(); break;
#if unix
       case  4 : all_done(); break;
#endif
	  case 1:
	  case 2:
	  case 5:
	  case 6:
	  case 7:
	  case 10:
	  case 11:
	  case 12:
	  case 14:
	  case 15:
	  case 16:
	  case 19:
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	  case 26:BELL;break;
          case 8:
          case 127:
	          if (ch_count>0){
                  CURSOR_LEFT; ERASE;
                  string[--ch_count]=0;
                  }  break;

	  case 13: if (ch_count>0)
		  { string[ch_count]=0;
		   set_up_save(the_row, string);
		   } goto down;break;
	  case 9: NORMAL;for (i=12;i<24;i++)
		   {GOTOXY(i,1);ERASE;}
		   help_menu();RESTORE_CURSOR;
		   return;
	  default: printf("%c",ch);string[ch_count++]=ch;

	 }

      }


}





set_up_in( the_row)
int the_row;
{ REVERSE;
      switch(the_row)
	{
	 case 13:
GOTOXY(13,3);printf("[%s]:",the_index);break;
case 14:
GOTOXY(14,3);printf("[%s]:",the_indexentry);break;
case 15:
GOTOXY(15,3);printf("[%s]:",the_indexsecond);break;
case 16:
GOTOXY(16,3);printf("[%s]:",the_seealso);break;
case 17:
GOTOXY(17,3);printf("[%s]:",the_primary); break;
case 18:
GOTOXY(18,3);printf("[%s]:",the_second);  break;
case 19:
GOTOXY(19,3);printf("[%s]:",the_gloss);  break;
case 20:
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);break;
case 21:
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second); break;
case 22:
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);break;
case 23:
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);break;
case 24:
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1); break;
case 25:
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);break;

	}

}


set_up_save(the_row, string)
int the_row;
char *string;
{
      switch(the_row)
	{
	 case 13:strcpy(the_index,string);break;
	 case 14:strcpy(the_indexentry,string);break;
	 case 15:strcpy(the_indexsecond,string);break;
	 case 16:strcpy(the_seealso,string);break;
	 case 17:strcpy(the_primary,string);break;
	 case 18:strcpy(the_second,string);break;
	 case 19:strcpy(the_gloss,string);break;
	 case 20:strcpy(g_primary,string);break;
	 case 21:strcpy(g_second,string);break;
	 case 22:strcpy(the_delimiter1,string);break;
	 case 23:strcpy(the_delimiter2,string);break;
	 case 24:strcpy(the2_delimiter1,string);break;
	 case 25:strcpy(the2_delimiter2,string);break;

	}

}



set_up_out(the_row)
int the_row;
{  NORMAL;
      switch(the_row)
	{
	 case 13:GOTOXY(13,1);ERASE;
GOTOXY(13,3); printf("[%s]:",the_index);break;
case 14:GOTOXY(14,1);ERASE;
GOTOXY(14,3);printf("[%s]:",the_indexentry);break;
case 15:GOTOXY(15,1);ERASE;
GOTOXY(15,3);printf("[%s]:",the_indexsecond);break;
case 16:GOTOXY(16,1);ERASE;
GOTOXY(16,3);printf("[%s]:",the_seealso);break;
case 17:GOTOXY(17,1);ERASE;
GOTOXY(17,3);printf("[%s]:",the_primary); break;
case 18:GOTOXY(18,1);ERASE;
GOTOXY(18,3);printf("[%s]:",the_second);  break;
case 19:GOTOXY(19,1);ERASE;
GOTOXY(19,3);printf("[%s]:",the_gloss);  break;
case 20:GOTOXY(20,1);ERASE;
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);break;
case 21:GOTOXY(21,1);ERASE;
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second); break;
case 22:GOTOXY(22,3);printf("                                 ");
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);break;
case 23:GOTOXY(22,40);ERASE;
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);break;
case 24:GOTOXY(23,3);printf("                               ");
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1); break;
case 25:GOTOXY(23,40);ERASE;
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);break;

	}

}

out_check()
{int i, rows, length, trunc;
rows=1;  trunc=256;

strcpy(out_str,phrase_str);
length=strlen(out_str);

for (i=0;i<length; i++)
 {
  if (out_str[i]==10) ++rows;
  if (rows==2) {trunc=i-4;break;}
 }


if (length>trunc) {out_str[trunc]='.';out_str[trunc+1]='.';out_str[trunc+2]='.';
out_str[trunc+3]=0;}
}



get_line()
{
char ch;
int ch_count;

ch_count=0;

command_line[0]=0;

     while(1)
      { ch=getch();
         switch(ch)
          {
          case 3: all_done(); break;
#if unix
          case 4: all_done(); break;
#endif       
          case 0:
	  case 1:
	  case 2:

	  case 5:
	  case 6: 
	  case 7:
	  case 10:
	  case 11:
	  case 12:
	  case 14:
	  case 15:
	  case 16:
	  case 19:
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	  case 26: BELL;break;
          case 8:
          case 127:
	          if (ch_count>0){
                  CURSOR_LEFT; ERASE;
                  command_line[--ch_count]=0;
                  }  break;
	  case 13: if (ch_count>0)
		     command_line[ch_count]=0;
		     return;
	  default: printf("%c",ch);command_line[ch_count++]=ch;

	 }
    }

}


str_search()
{
char *ptr;
#if unix
char *memchr();
#endif
int same_page= -1;
void  this_page();
int cursor_here=0,i;
command_line[0]=0;
SAVE_CURSOR;

GOTOXY(24,2); REVERSE;
printf("String:"); NORMAL; printf(" ");
if (the_phrase[0]>0) printf("[%s]", the_phrase);
get_line();

if (command_line[0]>0) strcpy(the_phrase, command_line);
  else if (the_phrase[0]==0)  {GOTOXY(24,2); ERASE; RESTORE_CURSOR; 
        return;}

ptr=buffer;
if (same_page<0)
  while ( cursor_here<cursor_mark) {cursor_here++; ptr++;}  

while (1){

while ((ptr=memchr(ptr, the_phrase[0], buffer_length))!=NULL)
    {
    if( memcmp(ptr, the_phrase, strlen(the_phrase))==0)
      { GOTOXY(24,2); ERASE;
       this_page(same_page*cursor_here); return;}
    else {ptr++;}       
    }

   /* Writing the buffer into the output file */

for (i=cursor_last;i<buffer_length;i++)
  {   fprintf(outfile,"%c",buffer[i]);
  if ((same_page<0) && (buffer[i]==10))
     {
      if (next_flag) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }

  }


if (same_page<0)
{
 marker=0;
cursor_last=0;
phrase_on=0;
cursor_mark=0;
buffer_length=0;
next_flag=0;
same_page=1;
}


if (end_infile) { end_outfile=1;
		 GOTOXY(17, 70); BOLD;printf("[EOF]"); BELL;
GOTOXY(24, 2); printf("String not found"); 
all_done();
 exit();}

end_infile=read_in_only(); cursor_here=0; ptr=buffer;
 }

}


int read_in_only()
{
int i, quit_s;
char quit;
char string[81];


buffer_length=0;
buffer[0]=0;
string[0]=0;
           quit_s=0;

for (i=1;i<=8;i++)
  { if( fgets(string,80,infile)==NULL)
        {fclose(infile); quit_s=1; goto quit;}
           strcat(buffer,string);
  }

quit:
buffer_length=strlen(buffer);

return(quit_s);
}


void this_page(cursor_here)
int cursor_here;
{
int i, cursor_there, the_cursor;

if (cursor_here<0) cursor_there= (-1)*cursor_here;
   else cursor_there=0;

for (i=cursor_there;i<buffer_length;i++)
 if(memcmp(&buffer[i], the_phrase, strlen(the_phrase))==0) 
  {the_cursor=i; break;}

if (cursor_here<0) {
     if (marker) 
      {REVERSE; cursor_mark=cursor_last; cursor_position(); marker=0;
       for (i=cursor_last; i<=the_cursor; i++)
        {
        printf("%c", buffer[i]);
        }
       NORMAL;
      }
     cursor_mark= the_cursor;
     cursor_position();
      }
    else 
   {
   position();
   NORMAL; CLS_UP(); NORMAL; 
   GOTOXY(3,1);
   for (i=0;i<buffer_length;i++)
     printf("%c", buffer[i]);
   cursor_mark=the_cursor;
   cursor_position();
   }

return;
}



/* for ultrix define V7 = 1 */

/*
 * The functions in this file negotiate with the operating system for
 * characters, and write characters in a barely buffered fashion on the display.
 * All operating systems.
 */


#if   MSDOS & TURBO
#include <conio.h>
#endif

#if     AMIGA
#define NEW 1006L
#define AMG_MAXBUF      1024L
static long terminal;
static char     scrn_tmp[AMG_MAXBUF+1];
static long     scrn_tmp_p = 0;
#endif

#if     CPM
#include        <bdos.h>
#endif

#if     MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
union REGS rg;          /* cpu register for use of DOS calls */
int nxtchar = -1;       /* character held from type ahead    */
#endif

#if RAINBOW
#include "rainbow.h"
#endif

#if     USG                     /* System V */
#include        <signal.h>
#include        <termio.h>
#include        <fcntl.h>
int kbdflgs;                    /* saved keyboard fd flags      */
int kbdpoll;                    /* in O_NDELAY mode                     */
int kbdqp;                      /* there is a char in kbdq      */
char kbdq;                      /* char we've already read      */
struct  termio  otermio;        /* original terminal characteristics */
struct  termio  ntermio;        /* charactoristics to use inside */
#endif

#if V7 | BSD
/*
#undef  CTRL
*/
#include        <sgtty.h>        /* for stty/gtty functions */
#include        <signal.h>
struct  sgttyb  ostate;          /* saved tty state */
struct  sgttyb  nstate;          /* values for editor mode */
struct tchars   otchars;        /* Saved terminal special character set */
struct tchars   ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                                /* A lot of nothing */
#if BSD
#include <sys/ioctl.h>          /* to get at the typeahead */
extern  int rtfrmshell();       /* return from suspended shell */
#define         TBUFSIZ         128
char tobuf[TBUFSIZ];            /* terminal output buffer */
#endif
#endif

/*
 * This function is called once to set up the terminal device streams.
 */
ttopen()
{

#if     AMIGA
        char oline[NSTRING];
#if     AZTEC
        extern  Enable_Abort;   /* Turn off ctrl-C interrupt */

        Enable_Abort = 0;       /* for the Manx compiler */
#endif
        strcpy(oline, "RAW:0/0/640/200/");
        strcat(oline, PROGNAME);
        strcat(oline, " ");
        strcat(oline, VERSION);
        strcat(oline, "/Amiga");
        terminal = Open(oline, NEW);
#endif
#if     CPM
#endif

#if     MSDOS & (HP150 == 0) & LATTICE
        /* kill the ctrl-break interupt */
        rg.h.ah = 0x33;                 /* control-break check dos call */
        rg.h.al = 1;            /* set the current state */
        rg.h.dl = 0;            /* set it OFF */
        intdos(&rg, &rg);       /* go for it! */
#endif

#if     USG
        ioctl(0, TCGETA, &otermio);     /* save old settings */
        ntermio.c_iflag = 0;            /* setup new settings */
        ntermio.c_oflag = 0;
        ntermio.c_cflag = otermio.c_cflag;
        ntermio.c_lflag = 0;
        ntermio.c_line = otermio.c_line;
        ntermio.c_cc[VMIN] = 1;
        ntermio.c_cc[VTIME] = 0;
        ioctl(0, TCSETA, &ntermio);     /* and activate them */
        kbdflgs = fcntl( 0, F_GETFL, 0 );
        kbdpoll = FALSE;
#endif

#if     V7 | BSD
if (tt_status==tt_open) return;
        gtty(0, &ostate);                       /* save old state */
        gtty(0, &nstate);                       /* get base of new state */
        nstate.sg_flags |= RAW;
        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
        stty(0, &nstate);                       /* set mode */
        ioctl(0, TIOCGETC, &otchars);           /* Save old characters */
        ioctl(0, TIOCSETC, &ntchars);           /* Place new character into K */
tt_status=tt_open;
#if     BSD
        /* provide a smaller terminal output buffer so that
           the type ahead detection works better (more often) */
        setbuffer(stdout, &tobuf[0], TBUFSIZ);
/*---        signal(SIGTSTP,SIG_DFL);         set signals so that we can
        signal(SIGCONT,rtfrmshell);      suspend & restart emacs */
#endif
#endif
        /* on all screens we are not sure of the initial position
           of the cursor                                        */
/*---   ttrow = 999;
        ttcol = 999; */

}

/*
 * This function gets called just before we go back home to the command
 * interpreter. 
 * Another no-operation on CPM.
 */
ttclose()
{

#if     AMIGA
#if     LATTICE
        amg_flush();
        Close(terminal);
#endif
#if     AZTEC
        amg_flush();
        Enable_Abort = 1;       /* Fix for Manx */
        Close(terminal);
#endif
#endif
#if     CPM
#endif
#if     MSDOS & (HP150 == 0) & LATTICE
        /* restore the ctrl-break interupt */
        rg.h.ah = 0x33;                 /* control-break check dos call */
        rg.h.al = 1;            /* set the current state */
        rg.h.dl = 1;            /* set it ON */
        intdos(&rg, &rg);       /* go for it! */
#endif

#if     USG
        ioctl(0, TCSETA, &otermio);     /* restore terminal settings */
        fcntl(0, F_SETFL, kbdflgs);
#endif

#if     V7 | BSD
if (tt_status==tt_close) return;
        stty(0, &ostate);
        ioctl(0, TIOCSETC, &otchars);   /* Place old character into K */
tt_status=tt_close;
#endif


}

#if     AMIGA
amg_flush()
{
        if(scrn_tmp_p)
                Write(terminal,scrn_tmp,scrn_tmp_p);
        scrn_tmp_p = 0;
}
#endif

/*
 * Flush terminal buffer. Does real work where the terminal output is buffered
 * up. A no-operation on systems where byte at a time terminal I/O is done.
 */
ttflush()
{
#if     AMIGA
        amg_flush();
#endif

#if     CPM
#endif

#if     MSDOS
#endif

#if     V7 | USG | BSD
        fflush(stdout);
#endif
}

/*
 * Read a character from the terminal, performing no editing and doing no echo
 * at all.
 */
ttgetc()
{
#if     AMIGA
        char ch;
        amg_flush();
        Read(terminal, &ch, 1L);
        return(255 & (int)ch);
#endif
#if     CPM
        return (biosb(BCONIN, 0, 0));
#endif

#if RAINBOW
        int Ch;

        while ((Ch = Read_Keyboard()) < 0);

        if ((Ch & Function_Key) == 0)
                if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
                        Ch &= 0xFF;

        return Ch;
#endif

#if     MSDOS & MWC86
        return (getcnb());
#endif

#if     MSDOS & (LATTICE | MSC | TURBO | AZTEC)
        int c;          /* character read */

        /* if a char already is ready, return it */
        if (nxtchar >= 0) {
                c = nxtchar;
                nxtchar = -1;
                return(c);
        }

        /* call the dos to get a char */
        rg.h.ah = 7;            /* dos Direct Console Input call */
        intdos(&rg, &rg);
        c = rg.h.al;            /* grab the char */
        return(c & 255);
#endif

#if     V7 | BSD
        return(127 & fgetc(stdin));
#endif

#if     USG
        if( kbdqp )
                kbdqp = FALSE;
        else
        {
                if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
                        return FALSE;
                kbdpoll = FALSE;
                while (read(0, &kbdq, 1) != 1)
                        ;
        }
        return ( kbdq & 127 );
#endif
}

Newsgroups: comp.text,comp.source.unix
Subject: Indexor for Scribe, LaTeX/TeX, *roff and etc
Expires: 
References: 
Sender: 
Reply-To: jbw@unix.cis.pittsburgh.edu (Jingbai  Wang)
Followup-To: 
Distribution: na
Organization: Univ. of Pittsburgh, Comp & Info Sys
Keywords: 


If you are a technical writer or book writer, you would have found that
the most tedious job is to add an index to a book you have written. I am
a heavy writer, and I use Scribe (with my own TEC.mak data base) and
TeX/LaTeX to format books.

To overcome the tediousness and boresomeness of index making, I developed
a program in C named 'indexor' that I revealed in a previous message in
comp.text. Here I am introducing the source code into comp.text and
comp.source.unix. 

This program named `indexor.c' can be compiled on VMS, UNIX or DOS, and have
helped me with two lengthy books already. You can called it a semi-automatic
index insertor. You need an ANSI terminal (like vt100, vt102) to make
it work properly.

Cut here
_________________________________________________________________


/*  Copyright (C) 1988 by Jingbai Wang */


/* **********************************************************************
 *            This program is an auxiliary program for Scribe and TeX   *
 *               It inserts index and glossary into Scribe/LaTeX file   *
 *                  It is an important program for book editing         *
 *    The user can set up the programs for other formattors like troff  *
 *                                                                      *
 *                    Copyright by Jingbai Wang August 1988             *
 *                                                                      *
 *    jbw@pittvms.bitnet                                                *
 *    jbw@cisunx.UUCP                                                   *
 ************************************************************************/
/*
    This program was created in 1988 by myself in order to include an
    index in the Scribe and TeX/LaTeX manuals I was writing. It is part
    of the Scribe TEC.mak package I developed, and can be re-distributed
    freely for non-profit purposes.

    It is like a special editor to introduce index entries into a Scribe,
    LaTeX, TeX or *troff file. It indeed makes a tedious and boresome job
    enjoyable.
    The primary attempt is to make this program portable among
    VAX/VMS, UNIX (BSD and Ultrix), and DOS (MSC and MS Quick C).

    To compile on our VMS,
    $ex indexor

    and on UNIX,
    %cc -o indexor indexor.c

    It takes two on-line arguments, i.e., the input and output file names,
    but you can also provide these piece of information when running it.
    The program is self-instructive, no documentation is necessary.
*/

#include <string.h>
#include <stdio.h>
#define CLS printf("\033[2J")
#define GOTOXY(x,y) printf("\033[%d;%df",x,y)
#define REVERSE printf("\033[7m")
#define NORMAL printf("\033[0m")
#define SAVE_CURSOR printf("\033[s")
#define BLINK printf("\033[5m")
#define BOLD printf("\033[1m")
#define UNDER printf("\033[4m")
#define ERASE printf("\033[K")
#define CURSOR_REPORT(x, y) scanf("\033[%d;%dR",x,y)
#define BELL printf("%c", 7)
#define CURSOR_RIGHT printf("\033[1C")
#define CURSOR_LEFT printf("\033[1D")

#define tt_open 1
#define tt_close 0
int tt_status=0;

#if VMS|unix
#define RESTORE_CURSOR cursor_position()
#else
#define RESTORE_CURSOR printf("\033[u")
#endif

#if ultrix
#define V7 1
#endif

#if unix|VMS
/*   ANSI escape, good for mainframe systems vt100 terminals, e.g., VAX*/
#define DEL 127
#define EXT 27
#define EXT1 '['
#define R_ARROW 'C'
#define L_ARROW 'D'
#define D_ARROW 'B'
#define U_ARROW 'A'

#if VMS
#include        <descrip.h>
#include        <iodef.h>
#include        <ssdef.h>
short   iochan;                  /* TTY I/O channel             */
#endif


#else
 /* MSDOS extended code escape */
#define DEL  8
#define EXT  0  
#define R_ARROW 77
#define L_ARROW 75
#define D_ARROW 80
#define U_ARROW 72
#endif

FILE *infile;
FILE *outfile;
char buffer[720];
int buffer_length;
int buffer_line[11];
int lines=1;
int cursor_mark=0;
int cursor_last=0;

char marker=0;
char phrase_str[512]="";
char the_phrase[512];
char save_str[128]="";
char out_str[512]="";
int phrase_on, phrase_off, phrase_len;
char end_infile=0;
char end_outfile=0;
char exit_flag=0;
char word_mark=0;
char the_index[20]="@Index";
char the_delimiter1[3]="{";
char the_delimiter2[3]="}";
char the2_delimiter1[3]="<";
char the2_delimiter2[3]=">";
char the_primary[20]="Primary=";
char the_second[20]="Secondary=";
char the_gloss[20]="@glossary";
char g_primary[20]="symbol=";
char g_second[20]="expln=";
char the_indexsecond[20]="@IndexSecondary";
char the_seealso[20]="@SeeAlso";
char the_indexentry[20]="@IndexEntry";
char the_entry[20]="Entry=";
char the_key[20]="Key=";
char the_number[20]="Number=";

struct CUR
{
short int x;
short int y;
} chr[720];

char next_str[512];
char next_flag=0;
char command_line[160];



/* The getch() and getche() */

#if VMS
char getch()
{
int ibuf,status;
int     iosb[2];
                        status = SYS$QIOW(0, iochan, IO$_READLBLK|IO$M_NOECHO,
                                 iosb, 0, 0, &ibuf, 1, 0, 0, 0, 0);

        return (ibuf & 0xFF);    /* Allow multinational  */

}

#endif


#if unix | ultrix | BSD

char getch()
{
int tmpch;
ttopen();
tmpch=ttgetc();
ttclose();
return(tmpch);
}
#endif


#if unix | VMS
char getche()
{
char inchar;
fputc(getch(), stdout);
return((int)inchar);
}

#endif

read_in()
{
int i, quit_s;
char string[81],quit;
GOTOXY(3,1);
buffer_length=0;
buffer[0]=0;
string[0]=0;
           quit_s=0;


for (i=1;i<=8;i++)
  { if( fgets(string,80,infile)==NULL)  { end_infile=1;
           quit_s=1; goto quit;}
     else { printf("%s",string);
           strcat(buffer,string);
           }
  }

quit:
buffer_length=strlen(buffer);

position();
GOTOXY(3,1);
return(quit_s);
 }

position()
{
int i,j;
int row,col;
char ch;
row=3; col=1;
buffer_line[1]=0;
lines=1;

for(i=0;i<buffer_length;i++)
  {  ch=buffer[i];
   chr[i].x=row; chr[i].y=col++;

   if(ch==10) {row++;col=1;lines++;buffer_line[lines]=i+1;}

   if (col==81) {row++;col=1;lines++; buffer_line[lines]=i+1;}
   }  

}


mark_begin()
{
int i;

 for (i=cursor_last;i<cursor_mark;i++)
      {fprintf(outfile, "%c", buffer[i]);
        if (buffer[i]==10)
	 {if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
	 }
       
      }
marker=1;
cursor_last=cursor_mark;
phrase_len=0;
phrase_on=cursor_mark;
phrase_str[0]=0;
REVERSE;
printf("%c",buffer[cursor_mark]);
cursor_position();
}

mark_end()
{
int i, length;
char  ch;
marker=0;

 for (i=cursor_last;i<=cursor_mark;i++)
      { fprintf(outfile, "%c", buffer[i]);
         if (buffer[i]==10)
	 { 
           if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
	 }


      }

length=strlen(phrase_str);
phrase_off=cursor_mark;
cursor_last=cursor_mark+1;
cursor_mark=cursor_last; cursor_position();
for (i=phrase_on; i<=phrase_off;i++)
  { ch=buffer[i];
   if ((ch==13)||(ch==10)) ch=32;
    phrase_str[length+i-phrase_on]=ch;
  }
phrase_str[length+1+phrase_off-phrase_on]=0;
phrase_on=0; phrase_off=0;
NORMAL;
}

cursor_position()
{
GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
}

cursor_right()
{

if (cursor_mark>=buffer_length-1) {next_page(); return;}
   ++cursor_mark; cursor_position();
   if (marker==1) printf("%c",buffer[cursor_mark]);
   GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);

}

cursor_left()
{
  if (cursor_mark<=cursor_last) {cursor_mark=cursor_last; cursor_position();BELL; return;}
  NORMAL; cursor_position();printf("%c",buffer[cursor_mark]);
  --cursor_mark;
  if (marker==1) REVERSE;
  GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);


}

cursor_down()
{
int i,the_stop;
char check;
the_stop=cursor_mark;

cursor_position();
for (i=cursor_mark;i<buffer_length;i++)
 {if (i>=buffer_length-2) {next_page();return;}
  if (buffer[i]==10) {cursor_mark=i+1;
     cursor_position();goto check;}
 }

check:
  if (marker)
   { GOTOXY(chr[the_stop].x,chr[the_stop].y);
     for (i=the_stop;i<=cursor_mark;i++)
      printf("%c",buffer[i]);
     cursor_position();
   }
}

cursor_up()
{
char check;
int i,the_stop;
if (cursor_mark<=cursor_last) {cursor_mark=cursor_last;cursor_position(); BELL; return;}

cursor_position();the_stop=cursor_mark;
for (i=cursor_mark;i>=cursor_last;i--)
 {
  if (buffer[i]==10) {cursor_mark=i-1;
  GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
  goto check;}
 }
 cursor_mark=cursor_last; cursor_position(); BELL;

check:
  if (marker)
   {
    NORMAL; GOTOXY(chr[cursor_mark+1].x,chr[cursor_mark+1].y);
    for (i=cursor_mark+1;i<=the_stop;i++)
       printf("%c",buffer[i]);
    REVERSE;
    GOTOXY(chr[cursor_mark].x,chr[cursor_mark].y);
   }

}






mark_word()
{
if (marker==0) mark_begin(); word_skip();return;
}

pass_marked()
{
int i;
if (marker==0) { word_skip();return;}
GOTOXY(chr[cursor_last].x,chr[cursor_last].y);
marker=0; NORMAL;
 phrase_str[0]= 0;
 for (i=cursor_last;i<=cursor_mark;i++)
     printf("%c",buffer[i]);

cursor_mark=cursor_last;
cursor_position();
}


word_skip()
{
int i, the_stop;
char check;

the_stop=cursor_mark;
if (cursor_mark>=buffer_length-1) {next_page(); return;}

cursor_right();
for (i=cursor_mark; i<buffer_length;i++)
 {

  switch(buffer[i])
   {case '!':
    case ',':
    case '"':
    case '\'':
    case '`':
    case '(':
    case ')':
    case '[':
    case ']':
    case '/':
    case '+':
    case '=':
    case '?':
    case '<':
    case '>':
    case '{':
    case '}':
    case '*':
    case '^':
    case '&':
    case '#':
    case ':':
    case ';':
    case '|':
    case  9:
    case 10:
    case 13:
    case '~':
    case '@':
    case '\\':
    case 32:
    case '.': if (word_mark) {word_mark=0;cursor_mark=i-1;
			     cursor_position();
			     goto check;}
	      else break;
    default:   word_mark=1;

   }
  }

check:
  if(marker)
   { GOTOXY(chr[the_stop].x,chr[the_stop].y);
     for (i=the_stop;i<=cursor_mark;i++)
	printf("%c",buffer[i]);
    cursor_position();
   }

}



word_back()
{
int i, the_stop;
char check;
the_stop=cursor_mark;
cursor_left();
for (i=cursor_mark; i>=0;i--)
 { if (i<=cursor_last) {cursor_mark=cursor_last;
			cursor_position();BELL;goto check;}

  switch(buffer[i])
   {case '!':
    case ',':
    case '"':
    case '\'':
    case '`':
    case '(':
    case ')':
    case '[':
    case ']':
    case '/':
    case '+':
    case '=':
    case '?':
    case '<':
    case '>':
    case '{':
    case '}':
    case '*':
    case '^':
    case '&':
    case '#':
    case ':':
    case ';':
    case '|':
    case  9:
    case 10:
    case 13:
    case '~':
    case '@':
    case '\\':
    case 32:
    case '.':
	     if (word_mark) {word_mark=0; cursor_mark=i; cursor_position();
		goto check;
	      }
	      else  break;
    default:   word_mark=1;

    }
  }

check:
  if (marker)
   {GOTOXY(chr[cursor_mark+1].x,chr[cursor_mark+1].y);
    NORMAL;
     for (i=cursor_mark+1;i<=the_stop;i++)
	 printf("%c",buffer[i]);

    REVERSE;
    cursor_position();
   }
}


next_page()
{
int i, length, pre_row, ch_count;

NORMAL;
CLS_UP();
GOTOXY(1,1);  pre_row=0; ch_count=0;

if (end_outfile) {BELL; return;}


if (marker){
 if ((strlen(phrase_str)+strlen(&buffer[phrase_on]))<510)
  strcat(phrase_str, &buffer[phrase_on]);
 else marker=0;
}

for (i=buffer_line[lines-2];i<buffer_length;i++)
 {
 if ((marker==1) && (i>=phrase_on)) {REVERSE;}
   printf("%c", buffer[i]);
 }

for (i=cursor_last;i<buffer_length;i++)
  {   fprintf(outfile,"%c",buffer[i]);
  if (buffer[i]==10)
     {
      if (next_flag==1) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }

  }


cursor_last=0;
phrase_on=0;
cursor_mark=0;
buffer_length=0;
NORMAL;

if (end_infile) {end_outfile=1;
		 GOTOXY(17, 70); BOLD;printf("[EOF]"); BELL; return;}

end_infile=read_in();
if (marker) {REVERSE; printf("%c",buffer[0]);cursor_position();}
}


control(inchar)
char inchar;
{
char ch;


 switch(inchar)
     {
       case EXT:
#if unix|VMS
             /* mainframe  environment  */
               if (getch()!=EXT1) {BELL;break;}
               ch=getch();
#else
             /* DOS environment              */ 

             ch=getch();
#endif            

             switch(ch)
              { 
               case L_ARROW: cursor_left(); 
                   break;
               case R_ARROW: cursor_right();
                   break;
               case D_ARROW: cursor_down();
                   break;
	       case U_ARROW: cursor_up();
                   break;
               default: BELL;
              }

          break;
       case 13: if (marker==0) {mark_begin(); break;}
                if (marker==1) 
                 {mark_end(); index_now();}
                 break;     
       case 9:  word_skip(); break;
       case 'b':
       case 'B':
       case 8:
       case 127:
                word_back(); break;
       case 32: next_page(); break;
       case 'n':
       case 'N': if (marker==1) 
                {mark_end();index_next_line();} 
                 else BELL; break;    
       case 'p':
       case 'P': pass_marked(); break;
       case 'f':
       case 'F': finish_up(); return(1); break;
       case 'a':
       case 'A': if (marker==1) mark_end(); see_also();break;
       case 's':
       case 'S': if (marker==1) mark_end();index_secondary();break;
       case 'i':
       case 'I': if (marker==1) mark_end();index_entry();break;
       case 'g':
       case 'G': if (marker==1) mark_end();
	      else warning("No current marked, will take the previous one");
		 glossary();
		   break;
       case 'W':
       case 'w': mark_word(); break;
       case '@': set_up(); break;
       case  6 : str_search(); break;
       case  3 : all_done(); break;
#if unix
       case  4 : all_done(); break;
#endif
       default: BELL;
   }


}




main(argc, argv)
int argc;
char *argv[];
{
int in_file,out_file, status;
int i,j;
char infile_name[30], outfile_name[30];
char out_ok=1;
char ch, quit;
char getch();

#if     VMS
$DESCRIPTOR(terminal,"TT");

        status = SYS$ASSIGN(&terminal, &iochan, 0, 0);
        if (status != SS$_NORMAL) exit(status);

system("set broadcast=none");

#endif


NORMAL;
CLS;
 
switch(argc)
  {
    case 1: in_file=1; out_file=1; break;
    case 2: in_file=0; out_file=1; strcpy(infile_name,argv[1]); break;
    default: in_file=0;out_file=0;
           strcpy(infile_name,argv[1]); 
           strcpy(outfile_name,argv[2]); break;
  }

 if (in_file) 
   {GOTOXY(5,15);
   printf(" Input file (file to be indexed) >");
   scanf("%s",infile_name);
   fflush(stdin);
   }

   if ((infile=fopen(infile_name,"r"))==NULL)
     {GOTOXY(20,20); BLINK;
       printf("Can't find the input file");
       NORMAL; goto quit;
     }

while (out_ok)

 {
  if (out_file) 
    {GOTOXY(6,15); ERASE;
    printf(" Output file (indexed file) >");
    fscanf(stdin, "%s",outfile_name);
    fflush(stdin);
    }


    out_ok=0; 
   if ((outfile=fopen(outfile_name,"r"))!=NULL)
     { out_ok=1;
       GOTOXY(7,16); ERASE;
       out_file=1;
      fflush(stdin);
      printf("File %s already exits, overwrite ? [N]", outfile_name);
      ch=getch();
      ch=getch();
        if ((ch=='y')||(ch=='Y')) out_ok=0;
        fclose(outfile);

     }

    if (out_ok==0)
       {
	outfile=fopen(outfile_name,"w");
       }
 }



NORMAL;
CLS;

help_menu();
end_infile=read_in();

 while (1)
  {
   control(getch());
   if (exit_flag) goto quit;
  }

quit:
GOTOXY(25, 1);
printf("\n\t>>> Thank you for using INDEX MAKER >>>\n");
printf("\t>>> by Jingbai Wang, August 1988 >>>\n");



}

warning(warn_str)
char *warn_str;
{
char i;

SAVE_CURSOR;
GOTOXY(24,5); REVERSE; BLINK;
printf("%s", warn_str); BELL; BELL;
for (i=1;i<10000;i++) ;
GOTOXY(24,1); RESTORE_CURSOR; NORMAL;
}

void  clr_show()
{
int i;
for (i=13;i<17;i++)
  {NORMAL; GOTOXY(i,1);ERASE;}
}


index_now()
{ int i;
fprintf(outfile, "%s%s%s%s",the_index,the_delimiter1,phrase_str,the_delimiter2);
SAVE_CURSOR;
clr_show(); out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s",the_index,the_delimiter1,out_str,the_delimiter2);
NORMAL; RESTORE_CURSOR;
}

index_next_line()
{
int i;

next_flag=1;
strcat(next_str, the_index);
strcat(next_str, the_delimiter1);
    if ((strlen(next_str)+strlen(phrase_str))<510) 
        strcat(next_str, phrase_str);
strcat(next_str, the_delimiter2);
SAVE_CURSOR;
clr_show(); out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s}", the_index,the_delimiter1,out_str,the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

see_also()
{
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Primary=");  NORMAL;printf("[%s]",save_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(command_line, save_str);
 else strcpy(save_str, command_line);
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_seealso,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,phrase_str,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_seealso,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

index_entry()
{
char entry[20], number[30];
strcpy(save_str, phrase_str);

strcpy(number, ",\nNumber=<");
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Entry=");  NORMAL;printf("[%s]",phrase_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(entry, phrase_str);
 else strcpy(entry, command_line);
GOTOXY(24,1);ERASE;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Number=");  NORMAL;
get_line();
if (memcmp(command_line,"",1)==0) number[0]=0;
 else  {strcat(number, command_line); strcat(number, ">");}


fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s%s",the_indexentry,the_delimiter1,
the_key,the2_delimiter1,phrase_str, the2_delimiter2,the_entry,
the2_delimiter1,entry,the2_delimiter2,  number, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s%s",the_indexentry,the_delimiter1,
the_key,the2_delimiter1,out_str, the2_delimiter2,the_entry,
the2_delimiter1,entry,the2_delimiter2, number, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

index_secondary()
{
SAVE_CURSOR;BELL;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Primary=");  NORMAL;printf("[%s]",save_str);
get_line();
if (memcmp(command_line,"",1)==0) strcpy(command_line, save_str);
 else strcpy(save_str, command_line);
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_indexsecond,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,phrase_str,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_indexsecond,the_delimiter1,
the_primary,the2_delimiter1,command_line, the2_delimiter2,the_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}

glossary()
{
SAVE_CURSOR;
GOTOXY(24,2); BLINK; REVERSE;
printf("  Description:");  NORMAL;
get_line();
fprintf(outfile, "%s%s%s%s%s%s,\n %s%s%s%s%s",the_gloss,the_delimiter1,
g_primary,the2_delimiter1,phrase_str, the2_delimiter2,g_second,
the2_delimiter1,command_line,the2_delimiter2, the_delimiter2);
GOTOXY(24,1);ERASE;
clr_show();  out_check();
GOTOXY(13,1);
BOLD;
printf("%s%s%s%s%s%s,\n %s%s%s%s%s",the_gloss,the_delimiter1,
g_primary,the2_delimiter1,command_line, the2_delimiter2,g_second,
the2_delimiter1,out_str,the2_delimiter2, the_delimiter2);
NORMAL; RESTORE_CURSOR;

}


finish_up()
{ char ch;
  int i;

if(end_infile && end_outfile) {all_done(); exit();}


if (marker) {mark_end(); index_now(); }

for (i=cursor_last;i<buffer_length;i++)
  {
  if (buffer[i]==13)
     { 
      if (next_flag==1) {
			 fprintf(outfile, "%s\n\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }
  else fprintf(outfile,"%c",buffer[i]);
  }



if (end_infile==1) {all_done(); return;}
GOTOXY(24,35); BLINK; printf("Working ... \n");

    while (fscanf(infile,"%c",&ch)!=EOF)
      {
	if (ch==13);
	else fprintf(outfile, "%c", ch);
      }
  all_done();NORMAL;
}


all_done()
{
fclose(infile); fclose(outfile); exit_flag=1;
#if VMS
system("set broadcast=all");
#endif
}


CLS_UP()
{ char i;

for(i=1;i<12;i++)
  {GOTOXY(i,1); ERASE;}

}

help_menu()
{
GOTOXY(12, 1);
REVERSE; printf("                                ");
printf(" Inserting                                 ");

GOTOXY(17,1);
printf(" ===== ^H delete ======================== ^F Search string ===============");
NORMAL;
GOTOXY(18,3); BOLD; printf("SPACE BAR"); NORMAL; printf(" -- next page");
GOTOXY(19,3); BOLD; printf("<RETURN> 1"); NORMAL; printf(" -- set mark");
GOTOXY(20,3); BOLD; printf("<RETURN> 2"); NORMAL; printf(" -- end mark & index");
GOTOXY(21,3); BOLD; printf("<TAB>"); NORMAL; printf(" -- forward a word");
GOTOXY(22,40); BOLD; printf("G"); NORMAL; printf(" -- end mark & glossary");
GOTOXY(22,3); BOLD; printf("W"); NORMAL; printf(" -- mark word");
GOTOXY(21,40); BOLD; printf("B"); NORMAL; printf(" -- backward a word");
GOTOXY(20,40); BOLD; printf("N"); NORMAL; printf(" -- end mark & index in next line");
GOTOXY(19,40); BOLD; printf("P"); NORMAL; printf(" -- abandon the marked/skip a word ");
GOTOXY(18,40); BOLD; printf("F"); NORMAL; printf(" -- finish     \
        ^F--string search");
GOTOXY(23,40); BOLD; printf("S"); NORMAL; printf(" -- IndexSecondary");
GOTOXY(23,17); BOLD; printf("I"); NORMAL; printf(" -- IndexEntry");
GOTOXY(23,3); BOLD; printf("A"); NORMAL; printf(" -- SeeAlso");
GOTOXY(23,65); BOLD; printf("@"); NORMAL; printf(" -- set up");
}


set_up()
{
int the_row, i;
int ch_count;
char ch, string[81];

ch_count=0;
SAVE_CURSOR;
NORMAL; REVERSE;
GOTOXY(12,1);
printf("                            Set-up Menu                  <TAB> to quit      ");
NORMAL;
for (i=13;i<24;i++)
  {GOTOXY(i,1);ERASE;}

GOTOXY(13,3);printf("[%s]:",the_index);
GOTOXY(14,3);printf("[%s]:",the_indexentry);
GOTOXY(15,3);printf("[%s]:",the_indexsecond);
GOTOXY(16,3);printf("[%s]:",the_seealso);
GOTOXY(17,3);printf("[%s]:",the_primary);
GOTOXY(18,3);printf("[%s]:",the_second);
GOTOXY(19,3);printf("[%s]:",the_gloss);
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second);
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1);
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);

the_row=13;
set_up_in(the_row);

     while(1)
      { ch=getch();
	 switch(ch)
	 {
	  case EXT:
#if unix | VMS

	     /* VAX */
	     ch=getch(); if (ch!=EXT1) {BELL;break;}
	     ch=getch();
#else
               /* DOS                 */
	      ch=getch(); 
#endif	    
	     switch(ch)
	     {
	      case L_ARROW:
	      case U_ARROW:
			   set_up_out(the_row); ch_count=0;string[0]=0;
			   --the_row; if (the_row<13) the_row=25;
			   set_up_in(the_row); break;
	      case R_ARROW:
	      case D_ARROW:
  down:                        set_up_out(the_row);ch_count=0;string[0]=0;
			   ++the_row; if (the_row>25) the_row=13;
			   set_up_in(the_row); break;
	     default: BELL;
	     } break;
       case  3 : all_done(); break;
#if unix
       case  4 : all_done(); break;
#endif
	  case 1:
	  case 2:
	  case 5:
	  case 6:
	  case 7:
	  case 10:
	  case 11:
	  case 12:
	  case 14:
	  case 15:
	  case 16:
	  case 19:
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	  case 26:BELL;break;
          case 8:
          case 127:
	          if (ch_count>0){
                  CURSOR_LEFT; ERASE;
                  string[--ch_count]=0;
                  }  break;

	  case 13: if (ch_count>0)
		  { string[ch_count]=0;
		   set_up_save(the_row, string);
		   } goto down;break;
	  case 9: NORMAL;for (i=12;i<24;i++)
		   {GOTOXY(i,1);ERASE;}
		   help_menu();RESTORE_CURSOR;
		   return;
	  default: printf("%c",ch);string[ch_count++]=ch;

	 }

      }


}





set_up_in( the_row)
int the_row;
{ REVERSE;
      switch(the_row)
	{
	 case 13:
GOTOXY(13,3);printf("[%s]:",the_index);break;
case 14:
GOTOXY(14,3);printf("[%s]:",the_indexentry);break;
case 15:
GOTOXY(15,3);printf("[%s]:",the_indexsecond);break;
case 16:
GOTOXY(16,3);printf("[%s]:",the_seealso);break;
case 17:
GOTOXY(17,3);printf("[%s]:",the_primary); break;
case 18:
GOTOXY(18,3);printf("[%s]:",the_second);  break;
case 19:
GOTOXY(19,3);printf("[%s]:",the_gloss);  break;
case 20:
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);break;
case 21:
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second); break;
case 22:
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);break;
case 23:
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);break;
case 24:
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1); break;
case 25:
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);break;

	}

}


set_up_save(the_row, string)
int the_row;
char *string;
{
      switch(the_row)
	{
	 case 13:strcpy(the_index,string);break;
	 case 14:strcpy(the_indexentry,string);break;
	 case 15:strcpy(the_indexsecond,string);break;
	 case 16:strcpy(the_seealso,string);break;
	 case 17:strcpy(the_primary,string);break;
	 case 18:strcpy(the_second,string);break;
	 case 19:strcpy(the_gloss,string);break;
	 case 20:strcpy(g_primary,string);break;
	 case 21:strcpy(g_second,string);break;
	 case 22:strcpy(the_delimiter1,string);break;
	 case 23:strcpy(the_delimiter2,string);break;
	 case 24:strcpy(the2_delimiter1,string);break;
	 case 25:strcpy(the2_delimiter2,string);break;

	}

}



set_up_out(the_row)
int the_row;
{  NORMAL;
      switch(the_row)
	{
	 case 13:GOTOXY(13,1);ERASE;
GOTOXY(13,3); printf("[%s]:",the_index);break;
case 14:GOTOXY(14,1);ERASE;
GOTOXY(14,3);printf("[%s]:",the_indexentry);break;
case 15:GOTOXY(15,1);ERASE;
GOTOXY(15,3);printf("[%s]:",the_indexsecond);break;
case 16:GOTOXY(16,1);ERASE;
GOTOXY(16,3);printf("[%s]:",the_seealso);break;
case 17:GOTOXY(17,1);ERASE;
GOTOXY(17,3);printf("[%s]:",the_primary); break;
case 18:GOTOXY(18,1);ERASE;
GOTOXY(18,3);printf("[%s]:",the_second);  break;
case 19:GOTOXY(19,1);ERASE;
GOTOXY(19,3);printf("[%s]:",the_gloss);  break;
case 20:GOTOXY(20,1);ERASE;
GOTOXY(20,3);printf("Gloss k1 [%s]:",g_primary);break;
case 21:GOTOXY(21,1);ERASE;
GOTOXY(21,3);printf("Gloss k2 [%s]:",g_second); break;
case 22:GOTOXY(22,3);printf("                                 ");
GOTOXY(22,3);printf("left delimiter 1 [%s]:",the_delimiter1);break;
case 23:GOTOXY(22,40);ERASE;
GOTOXY(22,40);printf("right delimiter 1 [%s]:",the_delimiter2);break;
case 24:GOTOXY(23,3);printf("                               ");
GOTOXY(23,3);printf("left delimiter 2 [%s]:",the2_delimiter1); break;
case 25:GOTOXY(23,40);ERASE;
GOTOXY(23,40);printf("right delimiter 2 [%s]:",the2_delimiter2);break;

	}

}

out_check()
{int i, rows, length, trunc;
rows=1;  trunc=256;

strcpy(out_str,phrase_str);
length=strlen(out_str);

for (i=0;i<length; i++)
 {
  if (out_str[i]==10) ++rows;
  if (rows==2) {trunc=i-4;break;}
 }


if (length>trunc) {out_str[trunc]='.';out_str[trunc+1]='.';out_str[trunc+2]='.';
out_str[trunc+3]=0;}
}



get_line()
{
char ch;
int ch_count;

ch_count=0;

command_line[0]=0;

     while(1)
      { ch=getch();
         switch(ch)
          {
          case 3: all_done(); break;
#if unix
          case 4: all_done(); break;
#endif       
          case 0:
	  case 1:
	  case 2:

	  case 5:
	  case 6: 
	  case 7:
	  case 10:
	  case 11:
	  case 12:
	  case 14:
	  case 15:
	  case 16:
	  case 19:
	  case 20:
	  case 21:
	  case 22:
	  case 23:
	  case 24:
	  case 25:
	  case 26: BELL;break;
          case 8:
          case 127:
	          if (ch_count>0){
                  CURSOR_LEFT; ERASE;
                  command_line[--ch_count]=0;
                  }  break;
	  case 13: if (ch_count>0)
		     command_line[ch_count]=0;
		     return;
	  default: printf("%c",ch);command_line[ch_count++]=ch;

	 }
    }

}


str_search()
{
char *ptr;
#if unix
char *memchr();
#endif
int same_page= -1;
void  this_page();
int cursor_here=0,i;
command_line[0]=0;
SAVE_CURSOR;

GOTOXY(24,2); REVERSE;
printf("String:"); NORMAL; printf(" ");
if (the_phrase[0]>0) printf("[%s]", the_phrase);
get_line();

if (command_line[0]>0) strcpy(the_phrase, command_line);
  else if (the_phrase[0]==0)  {GOTOXY(24,2); ERASE; RESTORE_CURSOR; 
        return;}

ptr=buffer;
if (same_page<0)
  while ( cursor_here<cursor_mark) {cursor_here++; ptr++;}  

while (1){

while ((ptr=memchr(ptr, the_phrase[0], buffer_length))!=NULL)
    {
    if( memcmp(ptr, the_phrase, strlen(the_phrase))==0)
      { GOTOXY(24,2); ERASE;
       this_page(same_page*cursor_here); return;}
    else {ptr++;}       
    }

   /* Writing the buffer into the output file */

for (i=cursor_last;i<buffer_length;i++)
  {   fprintf(outfile,"%c",buffer[i]);
  if ((same_page<0) && (buffer[i]==10))
     {
      if (next_flag) {
			 fprintf(outfile, "%s\n", next_str);
			 next_str[0]=0; next_flag=0;
			 }
     }

  }


if (same_page<0)
{
 marker=0;
cursor_last=0;
phrase_on=0;
cursor_mark=0;
buffer_length=0;
next_flag=0;
same_page=1;
}


if (end_infile) { end_outfile=1;
		 GOTOXY(17, 70); BOLD;printf("[EOF]"); BELL;
GOTOXY(24, 2); printf("String not found"); 
all_done();
 exit();}

end_infile=read_in_only(); cursor_here=0; ptr=buffer;
 }

}


int read_in_only()
{
int i, quit_s;
char quit;
char string[81];


buffer_length=0;
buffer[0]=0;
string[0]=0;
           quit_s=0;

for (i=1;i<=8;i++)
  { if( fgets(string,80,infile)==NULL)
        {fclose(infile); quit_s=1; goto quit;}
           strcat(buffer,string);
  }

quit:
buffer_length=strlen(buffer);

return(quit_s);
}


void this_page(cursor_here)
int cursor_here;
{
int i, cursor_there, the_cursor;

if (cursor_here<0) cursor_there= (-1)*cursor_here;
   else cursor_there=0;

for (i=cursor_there;i<buffer_length;i++)
 if(memcmp(&buffer[i], the_phrase, strlen(the_phrase))==0) 
  {the_cursor=i; break;}

if (cursor_here<0) {
     if (marker) 
      {REVERSE; cursor_mark=cursor_last; cursor_position(); marker=0;
       for (i=cursor_last; i<=the_cursor; i++)
        {
        printf("%c", buffer[i]);
        }
       NORMAL;
      }
     cursor_mark= the_cursor;
     cursor_position();
      }
    else 
   {
   position();
   NORMAL; CLS_UP(); NORMAL; 
   GOTOXY(3,1);
   for (i=0;i<buffer_length;i++)
     printf("%c", buffer[i]);
   cursor_mark=the_cursor;
   cursor_position();
   }

return;
}



/* for ultrix define V7 = 1 */

/*
 * The functions in this file negotiate with the operating system for
 * characters, and write characters in a barely buffered fashion on the display.
 * All operating systems.
 */


#if   MSDOS & TURBO
#include <conio.h>
#endif

#if     AMIGA
#define NEW 1006L
#define AMG_MAXBUF      1024L
static long terminal;
static char     scrn_tmp[AMG_MAXBUF+1];
static long     scrn_tmp_p = 0;
#endif

#if     CPM
#include        <bdos.h>
#endif

#if     MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
union REGS rg;          /* cpu register for use of DOS calls */
int nxtchar = -1;       /* character held from type ahead    */
#endif

#if RAINBOW
#include "rainbow.h"
#endif

#if     USG                     /* System V */
#include        <signal.h>
#include        <termio.h>
#include        <fcntl.h>
int kbdflgs;                    /* saved keyboard fd flags      */
int kbdpoll;                    /* in O_NDELAY mode                     */
int kbdqp;                      /* there is a char in kbdq      */
char kbdq;                      /* char we've already read      */
struct  termio  otermio;        /* original terminal characteristics */
struct  termio  ntermio;        /* charactoristics to use inside */
#endif

#if V7 | BSD
/*
#undef  CTRL
*/
#include        <sgtty.h>        /* for stty/gtty functions */
#include        <signal.h>
struct  sgttyb  ostate;          /* saved tty state */
struct  sgttyb  nstate;          /* values for editor mode */
struct tchars   otchars;        /* Saved terminal special character set */
struct tchars   ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                                /* A lot of nothing */
#if BSD
#include <sys/ioctl.h>          /* to get at the typeahead */
extern  int rtfrmshell();       /* return from suspended shell */
#define         TBUFSIZ         128
char tobuf[TBUFSIZ];            /* terminal output buffer */
#endif
#endif

/*
 * This function is called once to set up the terminal device streams.
 */
ttopen()
{

#if     AMIGA
        char oline[NSTRING];
#if     AZTEC
        extern  Enable_Abort;   /* Turn off ctrl-C interrupt */

        Enable_Abort = 0;       /* for the Manx compiler */
#endif
        strcpy(oline, "RAW:0/0/640/200/");
        strcat(oline, PROGNAME);
        strcat(oline, " ");
        strcat(oline, VERSION);
        strcat(oline, "/Amiga");
        terminal = Open(oline, NEW);
#endif
#if     CPM
#endif

#if     MSDOS & (HP150 == 0) & LATTICE
        /* kill the ctrl-break interupt */
        rg.h.ah = 0x33;                 /* control-break check dos call */
        rg.h.al = 1;            /* set the current state */
        rg.h.dl = 0;            /* set it OFF */
        intdos(&rg, &rg);       /* go for it! */
#endif

#if     USG
        ioctl(0, TCGETA, &otermio);     /* save old settings */
        ntermio.c_iflag = 0;            /* setup new settings */
        ntermio.c_oflag = 0;
        ntermio.c_cflag = otermio.c_cflag;
        ntermio.c_lflag = 0;
        ntermio.c_line = otermio.c_line;
        ntermio.c_cc[VMIN] = 1;
        ntermio.c_cc[VTIME] = 0;
        ioctl(0, TCSETA, &ntermio);     /* and activate them */
        kbdflgs = fcntl( 0, F_GETFL, 0 );
        kbdpoll = FALSE;
#endif

#if     V7 | BSD
if (tt_status==tt_open) return;
        gtty(0, &ostate);                       /* save old state */
        gtty(0, &nstate);                       /* get base of new state */
        nstate.sg_flags |= RAW;
        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
        stty(0, &nstate);                       /* set mode */
        ioctl(0, TIOCGETC, &otchars);           /* Save old characters */
        ioctl(0, TIOCSETC, &ntchars);           /* Place new character into K */
tt_status=tt_open;
#if     BSD
        /* provide a smaller terminal output buffer so that
           the type ahead detection works better (more often) */
        setbuffer(stdout, &tobuf[0], TBUFSIZ);
/*---        signal(SIGTSTP,SIG_DFL);         set signals so that we can
        signal(SIGCONT,rtfrmshell);      suspend & restart emacs */
#endif
#endif
        /* on all screens we are not sure of the initial position
           of the cursor                                        */
/*---   ttrow = 999;
        ttcol = 999; */

}

/*
 * This function gets called just before we go back home to the command
 * interpreter. 
 * Another no-operation on CPM.
 */
ttclose()
{

#if     AMIGA
#if     LATTICE
        amg_flush();
        Close(terminal);
#endif
#if     AZTEC
        amg_flush();
        Enable_Abort = 1;       /* Fix for Manx */
        Close(terminal);
#endif
#endif
#if     CPM
#endif
#if     MSDOS & (HP150 == 0) & LATTICE
        /* restore the ctrl-break interupt */
        rg.h.ah = 0x33;                 /* control-break check dos call */
        rg.h.al = 1;            /* set the current state */
        rg.h.dl = 1;            /* set it ON */
        intdos(&rg, &rg);       /* go for it! */
#endif

#if     USG
        ioctl(0, TCSETA, &otermio);     /* restore terminal settings */
        fcntl(0, F_SETFL, kbdflgs);
#endif

#if     V7 | BSD
if (tt_status==tt_close) return;
        stty(0, &ostate);
        ioctl(0, TIOCSETC, &otchars);   /* Place old character into K */
tt_status=tt_close;
#endif


}

#if     AMIGA
amg_flush()
{
        if(scrn_tmp_p)
                Write(terminal,scrn_tmp,scrn_tmp_p);
        scrn_tmp_p = 0;
}
#endif

/*
 * Flush terminal buffer. Does real work where the terminal output is buffered
 * up. A no-operation on systems where byte at a time terminal I/O is done.
 */
ttflush()
{
#if     AMIGA
        amg_flush();
#endif

#if     CPM
#endif

#if     MSDOS
#endif

#if     V7 | USG | BSD
        fflush(stdout);
#endif
}

/*
 * Read a character from the terminal, performing no editing and doing no echo
 * at all.
 */
ttgetc()
{
#if     AMIGA
        char ch;
        amg_flush();
        Read(terminal, &ch, 1L);
        return(255 & (int)ch);
#endif
#if     CPM
        return (biosb(BCONIN, 0, 0));
#endif

#if RAINBOW
        int Ch;

        while ((Ch = Read_Keyboard()) < 0);

        if ((Ch & Function_Key) == 0)
                if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
                        Ch &= 0xFF;

        return Ch;
#endif

#if     MSDOS & MWC86
        return (getcnb());
#endif

#if     MSDOS & (LATTICE | MSC | TURBO | AZTEC)
        int c;          /* character read */

        /* if a char already is ready, return it */
        if (nxtchar >= 0) {
                c = nxtchar;
                nxtchar = -1;
                return(c);
        }

        /* call the dos to get a char */
        rg.h.ah = 7;            /* dos Direct Console Input call */
        intdos(&rg, &rg);
        c = rg.h.al;            /* grab the char */
        return(c & 255);
#endif

#if     V7 | BSD
        return(127 & fgetc(stdin));
#endif

#if     USG
        if( kbdqp )
                kbdqp = FALSE;
        else
        {
                if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
                        return FALSE;
                kbdpoll = FALSE;
                while (read(0, &kbdq, 1) != 1)
                        ;
        }
        return ( kbdq & 127 );
#endif
}