/*  Copyright (C) 1989 by Jingbai Wang, University of Pittsburgh

   This program is released to public as shareware.
   Any individual and institution can use, modify and distribute
   it freely provided the copyright note and the following box 
   are retained. One exception is that profitable distribution (i.e., charge
   over the cost of materials and ship&handling) should have author's written
   permission.
                             */   


/*

   This program is designed to view a page ASCII document file of 46 lines
   per page maximum, and page-marked by form-feed character. i.e., ^L.
   The first page of the table of contents should contain two characters
   ^T (not control T) and that of index  ^E (not control E).
   Line length is 80 characters maximum.


   But, this program can also be used to view a regular text file which
   will be cut into 23 lines  pages automatically.

   It is intended to have it adoptable to any systems. It is in my mind
   for VMS, MSDOS/PC-DOS and unix for the time being.
   (DOS part not fully hacked yet, it need large/huge memory model)   
*/


/* ****** The following definitions are site dependent   *****
 *             edit them before installation                 *
 *************************************************************/
#include "site.h"

/*     moved to site.h
#ifndef DOCFILEPATH
#define DOCFILEPATH "/class2/4246/jbw/tex/texdoc"
#endif
*/
/* **********************************************************************
 *            This program is an auxiliary program for Scribe TEC.mak   *
 *               desgined by myself. It is used to view a               *
 *                  DOC file generated by Scribe TEC.mak                *
 *                                                                      *
 *               @make(TEC)                                             *
 *               @libraryfile(vtdoc)                                    *
 *                                                                      *
 *           The user can set up the programs for other purposes too    *
 *                    Copyright by Jingbai Wang August 1988             *
 ************************************************************************/


#include <string.h>
#include <math.h>
#include <stdio.h>


#define INBUFSIZE 1024
int inhandle;

#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 RESTORE_CURSOR printf("\033[u")
#define BLINK printf("\033[5m")
#define BOLD printf("\033[1m")
#define UNDER printf("\033[4m")
#define ERASE printf("\033[K")
#define BELL printf("\007")
#define CURSOR_RIGHT printf("\033[1C")
#define CURSOR_LEFT printf("\033[1D")


#if unix|ultrix
#include <fcntl.h>
#endif
#if ultrix
#define V7 1
#endif

/*   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'


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

#if VMS|unix|V7|ultrix /* define getch() for VMS and unix*/

#define getch() ttgetc()

int getche()
{
char inchar;
inchar=getch();
printf("%c",inchar);
return((int)inchar);
}
#endif

/*Make the default page number=200, file length=2k*/

#define MAXPAGES 200
#define MAXLENGTH 204800
unsigned char AllBuffer[MAXLENGTH];

                 /* Global valuables, not too many*/
unsigned int pagenumber;
long int pageptr[MAXPAGES][2], filelength=0;
char  docfilename[80];
int buffer_length;
int lines=1;
int search_flag= -1;
int tt_status=0;

#define tt_open 1
#define tt_close 0

int the_menu=0;
int docfilenumber=0;
int docfiletaken=0;
#define MAX_ROW 20


extern int getch();

int tableofcontents = -1, theindex = -1; 
int initpage, startpage, down_screen, up_screen, thepage;
long int start_byte, end_byte;
char command_line[81], the_phrase[81];

struct LOCACTE {
int flag;
int num;
long int where[100];
};

   /* Find the help file */
get_help(str)
char *str;
{
int status, len, i;
char sysstr[128];

NORMAL;
GOTOXY(25, 1); ERASE;

          if (str[0]==0)          
            sprintf (docfilename, "%s/%s", DOCFILEPATH, "dvi2ps.doc");
           else 
            if ((strncmp(str, "tex", 3) == 0)||(strncmp(str, "latex", 5) == 0))
            sprintf (docfilename, "%s/texint.doc", DOCFILEPATH);
           else   sprintf (docfilename, "%s/%s", DOCFILEPATH, str);
          
#if !ANSITERMINAL
	sprintf(sysstr, "more %s", docfilename);
	system(sysstr);
	return;
#else

   if ( (inhandle=open(docfilename, O_RDONLY))<0)
      {fprintf(stderr, "Can't find help file %s\n", docfilename); return;}

     initpage=1;
     down_screen=0; up_screen=1;
     startpage=read_pro();
     start_page();
     control(); 
     fflush(stdin);
     return;
#endif
}

/**/

read_pro()  /* read in the DOC file and page it*/
{
int  quit_s, lines, flag, nonstandard;
char string[80];
long int i, tmplength;
int Newline;

buffer_length=0;
string[0]=0;
AllBuffer[0]=0;
nonstandard= -1;
Newline=1;

     for (i=0; i<MAXPAGES; i++)
      pageptr[i][1]= -1;

quit_s= 1; 
lines=0; pagenumber=1;
pageptr[0][0]=0;
pageptr[1][0]=0;


AllBuffer[0]='@';
filelength=1;

CLS;
GOTOXY(24,32); BLINK; 
show_error("                    Loading help file....\n");

  /* read in the file */
while( (flag=read(inhandle, &AllBuffer[filelength], INBUFSIZE))>0)
  {  
     while(AllBuffer[++filelength]>0);
  }

show_error("                      Proceccing ....");
NORMAL;

/* process it */

        tmplength=filelength;

        filelength=0;
        i=1;
        lines=0;


        while (i<tmplength)
         {  
           switch(AllBuffer[i])
           {
            case 12:
                       pageptr[++pagenumber][0]=filelength+1;
                       i++; lines=0; if (AllBuffer[i+1]==10) i++; break;
                     
            case 10: lines ++;
                AllBuffer[filelength]=AllBuffer[i];
                                  filelength++; i++;
                    if (AllBuffer[i]=='^')
                      {
                        switch(AllBuffer[i+1])
                          {
                           case 'E': theindex=pagenumber; i +=2; break;
                           case 'T': tableofcontents=pagenumber;  i +=2; break;
                          }
                       }

                if ((lines==23)&&(pageptr[pagenumber][1]<0)) 
                    {
                      pageptr[pagenumber][1]=filelength;
                      lines = 0;
                    }

                if (lines>23) nonstandard=1;
                break;

            default:

                AllBuffer[filelength]=AllBuffer[i];
                   filelength++; i++;
  
             }
            }


     if (pagenumber>1)
      {

       for (i=0; i<80; i++)
       switch(AllBuffer[i+pageptr[2][0]+5])
        {
        case 10:
        case 32: i=80; break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9': string[i]=AllBuffer[i+pageptr[2][0]+5];
                  break;
     default: nonstandard=2; break;
        }

      if (nonstandard!=2) {
        quit_s=atoi(string)-1; 
         }

       }


 if((nonstandard>0)&&(tableofcontents<0))
         {show_error("Not standard vtdoc file");BELL;BELL;
          for (i=0; i<MAXPAGES; i++)
          pageptr[i][1]= -1; pagenumber=1;
                                  lines=0;
                                      i=0;
                                 do
                                   {
                                     if(AllBuffer[i++]==10) lines++;

                                      if (lines==23)
                                         {
                                         pageptr[++pagenumber][0]=i;
                                         lines = 0;
                                         }
                                    }
                                  while (i<filelength) ;

                              }



AllBuffer[filelength]='\0';
return(quit_s);

}

help_menu() /* print the help menu */
{
char tmpstr[50];
CLS; GOTOXY(3, 1); REVERSE;
fprintf(stdout,
"                             CDOC Help Menu                                ");
NORMAL;GOTOXY(5, 5);
fprintf(stdout, "Space-bar down-page");
GOTOXY(6, 5);
fprintf(stdout, "Tab       up-page");

GOTOXY(7, 5);
fprintf(stdout, "return    next full-page");

GOTOXY(5, 40);
fprintf(stdout, "N next-page");
GOTOXY(6, 40);
fprintf(stdout, "P previous-page");
GOTOXY(7, 40);
fprintf(stdout, "H help");

GOTOXY(9, 5);
fprintf(stdout, "^H back delete in editing");
GOTOXY(10, 5);
fprintf(stdout, "T table of contents");

GOTOXY(9, 40);
fprintf(stdout, "Q exit CDOC");
GOTOXY(10, 40);
fprintf(stdout, "I Index");

GOTOXY(12, 5);
fprintf(stdout, "F forward search");
GOTOXY(12, 40);
fprintf(stdout, "R reverse search");

GOTOXY(13, 5);
fprintf(stdout, "G goto page (e.g., +10, -5, 100)");
GOTOXY(13, 40);
fprintf(stdout, "! system shell");

GOTOXY(16, 20); REVERSE;
fprintf(stdout, " Current DOC File Information ");
NORMAL;

GOTOXY(18, 1);
printf("      file length     = %ld bytes\n", filelength);
printf("      number of pages = %d\n", pagenumber);
printf("      starting page   = %d\n", startpage);

GOTOXY(23, 10); BOLD;
fprintf(stdout, " Hit <space bar> for more help and any other key to exit this menu ");
NORMAL;

ttopen();
if (getch()!=32) {ttclose(); return;}
 else ttclose();

CLS; GOTOXY(3, 1); REVERSE;
fprintf(stdout,
"                        CDOC Advaced User's Help Menu                           ");
NORMAL;GOTOXY(5, 2);
fprintf(stdout, "1. CDOC can view any ASCII text files on ANSI standard \
terminals (e.g., vt1xx)");

GOTOXY(6, 2);
fprintf(stdout, "2. CDOC is written in C for multiple operation systems, e.g., \
VMS, unix, MSDOS");

GOTOXY(7, 2);
fprintf(stdout, "3. CDOC uses the following Scribe TEC.mak vtdoc format as standard:");
GOTOXY(8, 4);
fprintf(stdout, "a. paged with ^L (form-feed) as page marker");
GOTOXY(9, 4);
fprintf(stdout, "b. maximum length of a page is 46 lines and that of a line \
 77 characters");

GOTOXY(10, 4);
fprintf(stdout, "c. page numbers are placed extreme left such as `Page 1'");
GOTOXY(11, 4);
fprintf(stdout, "d. The first page of Table of Contents contains ^T");

GOTOXY(12, 4);
fprintf(stdout, "e. The first page of Index contains ^E");
GOTOXY(13, 4);
fprintf(stdout, "f. max length of a DOC file is 1-megabyte on mainframe \
and 620-kbyte on PC");

GOTOXY(14, 4);
fprintf(stdout, "g. terminal escape characters allowed");
GOTOXY(15, 2);
fprintf(stdout, "4. The easiest way to produce such files is to use TEC.mak \
Scribe database");

GOTOXY(16, 2);
fprintf(stdout, "5. CDOC can let you view a vtdoc format \
file like reading a manual.");

GOTOXY(17, 2);
fprintf(stdout, "6. CDOC has many advanced features like system shell.");

GOTOXY(23, 10); BOLD;
fprintf(stdout, " Hit key to exit help menu ");
NORMAL;

ttopen();
getch(); ttclose();
}


control() /* control the menus */
{

char ch;
 fflush(stdin); 
   while(1)
    {  fflush(stdin);ttopen(); ch=getch(); ttclose();
      switch(ch)
       {
         case 32: down_page(); search_flag= -1; break;
         case 13: full_page(); search_flag= -1;  break;
         case 9:  up_page(); search_flag= -1;  break;
         case 'N':
         case 'n': next_page(); search_flag= -1;  break;
         case 'P':
         case 'p': previous_page(); search_flag= -1;  break;
         case 'H':
         case 'h': help_menu(); display_page(); break;
         case 'G':
         case 'g':  goto_page(); search_flag= -1;  break;
         case 'T':
         case 't':  goto_table(); search_flag= -1;  break;
         case 'I':
         case 'i': goto_index(); search_flag= -1;  break;
         case 'f':
         case 'F': forward_search(); break;
         case 'r':
         case 'R': reverse_search(); break;
         case 'Q':
         case 'q':  return; 
         
#if VMS
         case 25:
#endif
#if unix
         case 4:
#endif
         case 3: goto_quit(); break;
         case '!': get_shell(); 
                 display_page(); break;
        default: fflush(stdin);/* show_error("Type H for Help"); BELL;*/
      }

    }

}


next_page()  /* turn to next page*/
{
if ((++thepage)>pagenumber) {BELL;--thepage; return;}
down_screen=0; up_screen=0;
      if (thepage==pagenumber)
        { if (pageptr[thepage][1]<0)
           {start_byte=pageptr[thepage][0];
            end_byte=filelength;
           }
        else
          {
           start_byte = pageptr[thepage][0];
           end_byte = pageptr[thepage][1]-1;
           down_screen=1;
          }
        } 
      else 
        { if (pageptr[thepage][1]<0)
           {start_byte=pageptr[thepage][0];
            end_byte=pageptr[thepage+1][0]-1;
           }
        else
          {
           start_byte = pageptr[thepage][0];
           end_byte = pageptr[thepage][1]-1;
           down_screen=1;
          }
        }

  display_page();

}



full_page() /* display next full page*/
{
if ((++thepage)>pagenumber) {BELL;--thepage; return;}
down_screen=0; up_screen=0;
      if (thepage==pagenumber)
        { 
           start_byte=pageptr[thepage][0];
            end_byte=filelength;
        } 
      else 
        {
           start_byte=pageptr[thepage][0];
           end_byte=pageptr[thepage+1][0]-1;
        }

  display_page();


}


previous_page() /* turn to previous page*/
{
if ((--thepage)<initpage) {BELL; ++thepage; return;}
down_screen=0; up_screen=0;
        if (pageptr[thepage][1]<0)
           {start_byte=pageptr[thepage][0];
            end_byte=pageptr[thepage+1][0]-1;
           }
        else
          {
           start_byte = pageptr[thepage][0];
           end_byte = pageptr[thepage][1]-1;
           down_screen=1;
          }

  display_page();

}


down_page() /* go down page */
{
 if (down_screen==1)
     { if (pageptr[thepage][1]<0) {next_page(); return;}

       if (thepage==pagenumber)
          {  start_byte = pageptr[thepage][1];
           end_byte = filelength;
          }
       else 
          { 
           start_byte=pageptr[thepage][1];
            end_byte=pageptr[thepage+1][0]-1;
          }
       down_screen=0; up_screen=1;

       display_page();

 return;
     }
else next_page();

}


up_page() /* go up page*/
{
 if (up_screen==1)
     {  start_byte = pageptr[thepage][0];
        end_byte=pageptr[thepage][1]-1;
        display_page();
        up_screen=0; down_screen=1;
        return;
     }

if ((--thepage)<initpage) {BELL; ++thepage; return;}
down_screen=0; up_screen=0;
        if (pageptr[thepage][1]<0)
           {start_byte=pageptr[thepage][0];
            end_byte=pageptr[thepage+1][0]-1;
           }
        else
          {
           start_byte = pageptr[thepage][1];
           end_byte = pageptr[thepage+1][0]-1;
           down_screen=0; up_screen=1;
          }

  display_page();

}




start_page() /* the starting up page */
{

thepage=initpage;
if(thepage>pagenumber) thepage=pagenumber;
thepage = thepage-1; fflush(stdin);
next_page();

}

display_page() /* display a page */
{
   int i;
   char tmpch;
  
  CLS; GOTOXY(1,1);

tmpch=AllBuffer[end_byte];
AllBuffer[end_byte]='\0';
printf("%s", &AllBuffer[start_byte]);
AllBuffer[end_byte]=tmpch;

/* fflush(stdin);*/
GOTOXY(24,1); BOLD;
printf("    Type H for help");NORMAL; 
}



goto_table() /* goto table of contents */
{
if (tableofcontents>0) {thepage=tableofcontents-1; next_page();}
else {BELL; show_error("No table of contents");}

}

goto_index() /*goto index */
{
if (theindex>0) {thepage=theindex-1; next_page();}
else {BELL; show_error("No index"); }
}

next_line()
{
/* attempt to have line feed mode, no time*/
}

  /* search a string by page */
struct LOCACTE string_search(begin_buffer, end_buffer)
int begin_buffer, end_buffer;
{
char *ptr, thisbuffer[4000],  *startptr, *endptr;
int i, j;
long int  the_length;
struct LOCACTE location;

for (i=0; i<100; i++) location.where[i]= -1;
location.flag= -1;

location.num=0;
the_length=end_buffer-begin_buffer;

   for (j=0; j<the_length;j++)
      if ( (AllBuffer[j+begin_buffer]<91) && (AllBuffer[j+begin_buffer]>64))
          thisbuffer[j]=AllBuffer[j+begin_buffer]+32;
      else   thisbuffer[j]=AllBuffer[j+begin_buffer];

thisbuffer[the_length]=0;

ptr = thisbuffer;
startptr=ptr;
endptr=ptr+the_length;


while ((ptr=(char *)strchr(ptr, the_phrase[0]))!=NULL)
    { if(ptr>=endptr) break;
    if( strncmp(ptr, the_phrase, strlen(the_phrase))==0)
      {
     location.where[location.num++]=begin_buffer+ptr-startptr; location.flag=1;
      }
    ptr++; 
    }
return(location);
}


forward_search() /* forward search for a string*/
{
int  this_page, last_page, j;
struct LOCACTE location;
long begin_buffer, end_buffer;
last_page=0;
GOTOXY(24,1); ERASE; GOTOXY(24,1); REVERSE;
printf("Forward search:"); NORMAL; printf(" ");
if (the_phrase[0]>0) printf("[%s]", the_phrase);
get_line();

if (command_line[0]>0) {
   for (j=0; j<strlen(command_line);j++)
      if ( (command_line[j]<91) && (command_line[j]>64))
          the_phrase[j]=command_line[j]+32;
      else  the_phrase[j]=command_line[j];
    the_phrase[strlen(command_line)]=0;
      }
  else { if (the_phrase[0]==0)  {GOTOXY(24,1); ERASE;return;}
        else if (search_flag>0) last_page=1;
       }

search_flag=1;

BLINK; printf("  Searching ...");NORMAL; 


last_page += thepage;
this_page= last_page;

   while (this_page<pagenumber)
     { 
      begin_buffer=pageptr[last_page][0];       
      end_buffer=pageptr[++this_page][0];
      location=string_search(begin_buffer, end_buffer);
      if (location.flag>0) {display_found(last_page, location); return;}
      last_page=this_page;
     }

      begin_buffer=pageptr[pagenumber][0];       
      end_buffer=filelength;
      location=string_search(begin_buffer, end_buffer);
      if (location.flag>0) {display_found(last_page, location); return;}

show_error("String not found");
}

reverse_search() /* reverse search for a string */
{
int  this_page, last_page, j;
struct LOCACTE location;
long int begin_buffer, end_buffer;

GOTOXY(24,1); ERASE; GOTOXY(24,1); REVERSE;
printf("Reverse search:"); NORMAL; printf(" ");
if (the_phrase[0]>0) printf("[%s]", the_phrase);
get_line();

if (command_line[0]>0) 
   {for (j=0; j<strlen(command_line);j++)
      if ( (command_line[j]<91) && (command_line[j]>64))
          the_phrase[j]=command_line[j]+32;
      else  the_phrase[j]=command_line[j];
    the_phrase[strlen(command_line)]=0;
   }
  else {
        if (the_phrase[0]==0)  {GOTOXY(24,1); ERASE;return;}
       }

search_flag=1;

BLINK; printf("  Searching ...");NORMAL;

last_page=thepage;
this_page=thepage;

   while (this_page>initpage)
     { 
      begin_buffer=pageptr[--this_page][0];
      end_buffer=pageptr[last_page][0];       

      location=string_search(begin_buffer, end_buffer);
      if (location.flag>0) {location.flag=2;
                            display_found(this_page, location); return;}
      last_page=this_page;
     }
 
     begin_buffer=pageptr[initpage][0];       
      end_buffer=pageptr[initpage+1][0];
      location=string_search(begin_buffer, end_buffer);
      if (location.flag>0) {location.flag=2;
                            display_found(this_page, location); return;}

show_error("String not found");

}

display_found(thispage, location) /* display found string in a page */
int thispage;
struct LOCACTE location;
{
int i, len, locate;
char tmpch;
long int place[100], starting_ptr;
len=strlen(the_phrase);

locate=0;

for (i=0; i<100; i++)
   if (location.where[i]>0)
     {place[locate]=location.where[i]; locate++;}

thepage=thispage;

down_screen=0; up_screen=0;


      if (thepage==pagenumber)
        { start_byte=pageptr[thepage][0];
          end_byte=filelength;
        } 
      else 
        { start_byte=pageptr[thepage][0];
          end_byte=pageptr[thepage+1][0];
        }
locate=0;


        CLS; GOTOXY(1,1);

place[location.num]=end_byte;
starting_ptr=start_byte;


           for (i=0; i<location.num;i++)
           { 
tmpch=AllBuffer[place[i]];
AllBuffer[place[i]]=0;
printf("%s", &AllBuffer[starting_ptr]);
REVERSE;
AllBuffer[place[i]]=tmpch;
tmpch=AllBuffer[place[i]+len];
AllBuffer[place[i]+len]=0;
printf("%s", &AllBuffer[place[i]]);
NORMAL;
AllBuffer[place[i]+len]=tmpch;
starting_ptr=place[i]+len;

           }

tmpch=AllBuffer[end_byte];
AllBuffer[end_byte]=0;
printf("%s", &AllBuffer[starting_ptr]);
NORMAL;
AllBuffer[end_byte]=tmpch;


}



goto_page() /* goto a certain page */
{
char tmp_str[80], *tmpstr;
int how, starting, i, tmppage, thispage;
starting=0;

GOTOXY(24,1); ERASE; GOTOXY(24,1); REVERSE;
printf("Goto page:"); NORMAL; printf(" ");
get_line();

if (command_line[0]==0) {GOTOXY(24,1); ERASE; return;}
  GOTOXY(24,1); ERASE;

/*
while (command_line[starting++]==32) ;
*/

 switch(command_line[0])
  {
   case '+': how=1; starting=1; break;
   case '-': how= -1; starting=1; break;
   default: how=0; starting=0;
  }


tmpstr=command_line;
tmpstr += starting;

tmppage=atoi(tmpstr)-startpage+1;

   switch(how)
  {
   case 1: thispage=thepage+tmppage;
            if (thispage>pagenumber) {BELL; thepage=pagenumber-1;}
            else thepage=thispage-1; 
            next_page(); break;
   case -1: thispage = thepage-tmppage;
            if (thispage<initpage) {BELL; thepage=initpage-1;}
            else thepage=thispage-1; 
            next_page(); break;
   case 0: if( tmppage>pagenumber) {BELL; tmppage=pagenumber;}
           if (tmppage<initpage) {tmppage=initpage;BELL;}
            thepage=tmppage-1; next_page(); break;
  }


}


goto_quit() /* quit CDOC */
{

CLS;
GOTOXY(25,1); ERASE;
GOTOXY(24, 1); 
    close(inhandle);
exit(1);

}

show_error(message) /* print error message*/
char *message;
{
int i;
fflush(stdin);
GOTOXY(24,1); ERASE;
GOTOXY(24,3); BOLD; 
printf("******  %s ******", message); NORMAL;
for (i=1; i<10000; i++);
}


get_line() /* line editor */
{
char ch;
int ch_count;
command_line[0]=0;
ch_count=0;



     while(1)
      { 
         ttopen();  ch=getch(); ttclose();
         switch(ch)
          {
          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 26:
          case 27:  fflush(stdin); 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;
#if VMS
         case 25:
#endif
#if unix
         case 4:
#endif

	  case 3: command_line[0]=0; return(-1);
	  default: printf("%c",ch);command_line[ch_count++]=ch;

	 }
    }

}

init_buffer()
{
long int i;


     for (i=0; i<=filelength; i++)
     AllBuffer[i]=0;

pagenumber=0;
lines=1;
search_flag= -1;
tableofcontents = -1;
theindex = -1;
    
}


get_shell()
{

CLS;

#if MSDOS
system("command");
#endif

#if unix|ultrix
GOTOXY(24, 1);
ERASE; fprintf(stdout, "Type ^D to return");
system("csh");
#endif


#if VMS
printf(" Type logout to return\n");
system("spawn");
#endif

}


/* 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 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.
 * On VMS, it translates TT until it finds the terminal, then assigns
 * a channel to it and sets it raw. On CPM it is a no-op.
 */
ttopen()
{

#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. 
 */
ttclose()
{

#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


}

/*
 * 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     V7 | USG | BSD
        fflush(stdout);
#endif
}

#if ultrix
memmove(s1,s2,len) char *s1, *s2; unsigned len;
   { unsigned i;
   if(s1 <= s2) for(i=0; i<len; ++i) *s1++ = *s2++;
   else for(s1 += len, s2+= len, i=0; i<len; ++i) *--s1 = *--s2;
   }
#endif


ttgetc()
{

#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
}

#ifdef STANDALONE

char progname[128];
char helpfile[128];

main(argc, argv)
int argc;
char *argv[];
{
	(void) strcpy(progname,argv[0]);
	if (argc >= 1) {
		(void) strcpy(helpfile, argv[1]);
		get_help(helpfile);
	}
	else {
		(void) fprintf(stderr,"Usage: %s helpfile\n",progname);
		(void) fprintf(stderr,"Existing helpfiles include dvi2ps and tex.\n");
	}
}

#endif STANDALONE

#ifdef NOTDEF
			case 'H':   /* JBW, next arg is for help file
					 there can be various help files */
       			if ((argind+1<argc)&&(argv[argind+1][0]!='-'))
                                strcpy(helpfile, argv[++argind]);
                                get_help(helpfile);
                                exit;

#endif NOTDEF
