home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / larn.t.Z / larn.t / io.c < prev    next >
Text File  |  1988-11-13  |  23KB  |  969 lines

  1. /* io.c             Larn is copyrighted 1986 by Noah Morgan.
  2.  *
  3.  *    Below are the functions in this file:
  4.  *
  5.  *    setupvt100()     Subroutine to set up terminal in correct mode for game
  6.  *    clearvt100()      Subroutine to clean up terminal when the game is over
  7.  *    getchar()         Routine to read in one character from the terminal
  8.  *    scbr()            Function to set cbreak -echo for the terminal
  9.  *    sncbr()            Function to set -cbreak echo for the terminal
  10.  *    newgame()         Subroutine to save the initial time and seed rnd()
  11.  *
  12.  *    FILE OUTPUT ROUTINES
  13.  *
  14.  *    lprintf(format,args . . .)    printf to the output buffer
  15.  *    lprint(integer)                send binary integer to output buffer
  16.  *    lWrite(buf,len)                Write a buffer to the output buffer
  17.  *    lprcat(str)                    sent string to output buffer
  18.  *
  19.  *    FILE OUTPUT MACROS (in header.h)
  20.  *
  21.  *    lprc(character)                put the character into the output buffer
  22.  *
  23.  *    FILE INPUT ROUTINES
  24.  *
  25.  *    long lgetc()                read one character from input buffer
  26.  *    long lrint()                read one integer from input buffer
  27.  *    lrfill(address,number)        put input bytes into a buffer
  28.  *    char *lgetw()                get a whitespace ended word from input
  29.  *    char *lgetl()                get a \n or EOF ended line from input
  30.  *
  31.  *    FILE OPEN / CLOSE ROUTINES
  32.  *
  33.  *    lcreat(filename)            create a new file for Write
  34.  *    lopen(filename)                open a file for read
  35.  *    lappend(filename)            open for append to an existing file
  36.  *    lrclose()                    close the input file
  37.  *    lwclose()                    close output file
  38.  *    lflush()                    flush the output buffer
  39.  *
  40.  *    Other Routines
  41.  *
  42.  *    cursor(x,y)                    position cursor at [x,y]
  43.  *    cursors()                    position cursor at [1,24] (saves memory)
  44.  *  cl_line(x,y)                 Clear line at [1,y] and leave cursor at [x,y]
  45.  *  cl_up(x,y)                    Clear screen from [x,1] to current line.
  46.  *  cl_dn(x,y)                     Clear screen from [1,y] to end of display. 
  47.  *  standout(str)                 Print the string in standout mode.
  48.  *  set_score_output()             Called when output should be literally printed.
  49.  ** putchar(ch)                    Print one character in decoded output buffer.
  50.  ** flush_buf()                    Flush buffer with decoded output.
  51.  ** init_term()                    Terminal initialization -- setup termcap info
  52.  **    char *tmcapcnv(sd,ss)          Routine to convert VT100 \33's to termcap format
  53.  *    beep()        Routine to emit a beep if enabled (see no-beep in .larnopts)
  54.  *
  55.  * Note: ** entries are available only in termcap mode.
  56.  */
  57.  
  58. #include "header.h"
  59.  
  60. #ifdef SYSV    /* system III or system V */
  61. #include <termio.h>
  62. #define sgttyb termio
  63. #define stty(_a,_b) ioctl(_a,TCSETA,_b)
  64. #define gtty(_a,_b) ioctl(_a,TCGETA,_b)
  65. static int rawflg = 0;
  66. static char saveeof,saveeol;
  67. #define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\
  68.     _a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)
  69. #define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL
  70.  
  71. #else not SYSV
  72. # ifndef OSK
  73. #ifndef BSD
  74. #define CBREAK RAW        /* V7 has no CBREAK */
  75. #endif
  76.  
  77. #define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO)
  78. #define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO)
  79. #include <sgtty.h>
  80. # else OSK
  81. # include <modes.h>
  82. # include <sgstat.h>
  83. # endif OSK
  84. #endif not SYSV
  85.  
  86. #ifndef NOVARARGS    /* if we have varargs */
  87. #include <varargs.h>
  88. #else NOVARARGS    /* if we don't have varargs */
  89. typedef char *va_list;
  90. #define va_dcl int va_alist;
  91. #define va_start(plist) plist = (char *) &va_alist
  92. #define va_end(plist)
  93. #define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1]
  94. #endif NOVARARGS
  95.  
  96. #define LINBUFSIZE 128        /* size of the lgetw() and lgetl() buffer        */
  97. int lfd;                    /*  output file numbers                            */
  98. int fd;                        /*  input file numbers                            */
  99. # ifndef OSK
  100. static struct sgttyb ttx;    /* storage for the tty modes                    */
  101. # else OSK
  102. static struct sgbuf ttx,ttx_sav;    /* storage for the tty modes                    */
  103. # endif OSK
  104. static int ipoint=MAXIBUF,iepoint=MAXIBUF;    /*  input buffering pointers    */
  105. static char lgetwbuf[LINBUFSIZE];    /* get line (word) buffer                */
  106.  
  107. /*
  108.  *    setupvt100()         Subroutine to set up terminal in correct mode for game
  109.  *
  110.  *    Attributes off, clear screen, set scrolling region, set tty mode 
  111.  */
  112. setupvt100()
  113.     {
  114.     clear();  setscroll();  scbr(); /* system("stty cbreak -echo"); */
  115.     }
  116.  
  117. /*
  118.  *    clearvt100()          Subroutine to clean up terminal when the game is over
  119.  *
  120.  *    Attributes off, clear screen, unset scrolling region, restore tty mode 
  121.  */
  122. clearvt100()
  123.     {
  124.     resetscroll();  clear();  sncbr(); /* system("stty -cbreak echo"); */
  125.     }
  126.  
  127. /*
  128.  *    getchar()         Routine to read in one character from the terminal
  129.  */
  130. getchar()
  131.     {
  132.     char byt;
  133. #ifdef EXTRA
  134.     c[BYTESIN]++;
  135. #endif
  136.     lflush();        /* be sure output buffer is flushed */
  137.     read(0,&byt,1);     /* get byte from terminal */
  138.     return(byt);
  139.     }
  140.  
  141. /*
  142.  *    scbr()        Function to set cbreak -echo for the terminal
  143.  *
  144.  *    like: system("stty cbreak -echo")
  145.  */
  146. scbr()
  147.     {
  148. # ifndef OSK
  149.     gtty(0,&ttx);        doraw(ttx);        stty(0,&ttx);
  150. # else OSK
  151.     static int yet = 0;
  152.  
  153.     if (yet == 0) {
  154.         yet = 1;
  155.         _gs_opt (0, &ttx);
  156.         ttx_sav = ttx;
  157.         ttx.sg_pause = 0;
  158.         ttx.sg_echo = 0;
  159.         ttx.sg_eofch = 0;
  160.         ttx.sg_tabsiz = 8;
  161.     }
  162.     _ss_opt (0, &ttx);
  163. # endif OSK
  164.     }
  165.  
  166. # ifdef OSK
  167. void
  168. echo_on ()
  169. {
  170.     ttx.sg_echo = 1;
  171.     _ss_opt (0, &ttx);
  172.     ttx.sg_echo = 0;
  173. }
  174. # endif OSK
  175.  
  176. /*
  177.  *    sncbr()        Function to set -cbreak echo for the terminal
  178.  *
  179.  *    like: system("stty -cbreak echo")
  180.  */
  181. sncbr()
  182.     {
  183. # ifndef OSK
  184.     gtty(0,&ttx);        unraw(ttx);        stty(0,&ttx);
  185. # else OSK
  186.     _ss_opt (0, &ttx_sav);
  187. # endif OSK
  188.     }
  189.  
  190. /*
  191.  *    newgame()         Subroutine to save the initial time and seed rnd()
  192.  */
  193. newgame()
  194.     {
  195.     register long *p,*pe;
  196.     for (p=c,pe=c+100; p<pe; *p++ =0);
  197.     time(&initialtime);        srand(initialtime);
  198.     lcreat((char*)0);    /* open buffering for output to terminal */
  199.     }
  200.  
  201. /*
  202.  *    lprintf(format,args . . .)        printf to the output buffer
  203.  *        char *format;
  204.  *        ??? args . . .
  205.  *
  206.  *    Enter with the format string in "format", as per printf() usage
  207.  *        and any needed arguments following it
  208.  *    Note: lprintf() only supports %s, %c and %d, with width modifier and left
  209.  *        or right justification.
  210.  *    No correct checking for output buffer overflow is done, but flushes 
  211.  *        are done beforehand if needed.
  212.  *    Returns nothing of value.
  213.  */
  214. #ifdef lint
  215. /*VARARGS*/
  216. lprintf(str)
  217.     char *str;
  218.     {
  219.     char *str2;
  220.     str2 = str;
  221.     str = str2; /* to make lint happy */
  222.     }
  223. /*VARARGS*/
  224. sprintf(str)
  225.     char *str;
  226.     {
  227.     char *str2;
  228.     str2 = str;
  229.     str = str2; /* to make lint happy */
  230.     }
  231. #else lint
  232. /*VARARGS*/
  233. lprintf(va_alist)
  234. va_dcl
  235.     {
  236.     va_list ap;    /* pointer for variable argument list */
  237.     register char *fmt;
  238.     register char *outb,*tmpb;
  239.     register long wide,left,cont,n;        /* data for lprintf    */
  240.     char db[12];            /* %d buffer in lprintf    */
  241.  
  242.     va_start(ap);    /* initialize the var args pointer */
  243.     fmt = va_arg(ap, char *);    /* pointer to format string */
  244.     if (lpnt >= lpend) lflush(); 
  245.     outb = lpnt;
  246.     for ( ; ; )
  247.         {
  248.         while (*fmt != '%')
  249.             if (*fmt) *outb++ = *fmt++;  else { lpnt=outb;  return; }
  250.         wide = 0;    left = 1;    cont=1;
  251.         while (cont)
  252.           switch(*(++fmt))
  253.             {
  254.             case 'd':    n = va_arg(ap, long);
  255.                         if (n<0) { n = -n;  *outb++ = '-';  if (wide) --wide; }
  256.                         tmpb = db+11;    *tmpb = (char)(n % 10 + '0');
  257.                         while (n>9)  *(--tmpb) = (char)((n /= 10) % 10 + '0');
  258.                         if (wide==0)  while (tmpb < db+12) *outb++ = *tmpb++;
  259.                         else
  260.                             {
  261.                             wide -= db-tmpb+12;
  262.                             if (left)  while (wide-- > 0) *outb++ = ' ';
  263.                             while (tmpb < db+12) *outb++ = *tmpb++;
  264.                             if (left==0)  while (wide-- > 0) *outb++ = ' ';
  265.                             }
  266.                         cont=0;    break;
  267.  
  268.             case 's':    tmpb = va_arg(ap, char *);
  269.                         if (wide==0)  { while (*outb++ = *tmpb++);  --outb; } 
  270.                         else
  271.                             {
  272.                             n = wide - strlen(tmpb);
  273.                             if (left)  while (n-- > 0) *outb++ = ' ';
  274.                             while (*outb++ = *tmpb++);  --outb;
  275.                             if (left==0)  while (n-- > 0) *outb++ = ' ';
  276.                             }
  277.                         cont=0;    break;
  278.  
  279.             case 'c':    *outb++ = va_arg(ap, int);    cont=0;  break;
  280.  
  281.             case '0':
  282.             case '1':
  283.             case '2':
  284.             case '3':
  285.             case '4':
  286.             case '5':
  287.             case '6':
  288.             case '7':
  289.             case '8':
  290.             case '9':    wide = 10*wide + *fmt - '0';    break;
  291.  
  292.             case '-':    left = 0;    break;
  293.  
  294.             default:    *outb++ = *fmt;  cont=0;    break;
  295.             };
  296.         fmt++;
  297.         }
  298.     va_end(ap);
  299.     }
  300. #endif lint
  301.  
  302. /*
  303.  *    lprint(long-integer)                send binary integer to output buffer
  304.  *        long integer;
  305.  *
  306.  *        +---------+---------+---------+---------+
  307.  *        |    high  |            |          |      low    |
  308.  *        |  order  |            |          |  order    |
  309.  *        |   byte  |            |          |      byte    |
  310.  *        +---------+---------+---------+---------+
  311.  *       31  ---  24 23 --- 16 15 ---  8 7  ---   0
  312.  *
  313.  *    The save order is low order first, to high order (4 bytes total)
  314.  *        and is written to be system independent.
  315.  *    No checking for output buffer overflow is done, but flushes if needed!
  316.  *    Returns nothing of value.
  317.  */
  318. lprint(x)
  319.     register long x;
  320.     {
  321.     if (lpnt >= lpend) lflush();
  322.     *lpnt++ =  255 & x;            *lpnt++ =  255 & (x>>8);
  323.     *lpnt++ =  255 & (x>>16);    *lpnt++ =  255 & (x>>24);
  324.     }
  325.  
  326. /*
  327.  *    lWrite(buf,len)                    Write a buffer to the output buffer
  328.  *        char *buf;
  329.  *        int len;
  330.  *    
  331.  *    Enter with the address and number of bytes to Write out
  332.  *    Returns nothing of value
  333.  */
  334. lWrite(buf,len)
  335.     register char *buf;
  336.     int len;
  337.     {
  338.     register char *str;
  339.     register int num2;
  340.     if (len > 399)  /* don't copy data if can just Write it */
  341.         {
  342. #ifdef EXTRA
  343.         c[BYTESOUT] += len;
  344. #endif
  345.  
  346. #ifndef VT100
  347.         for (str=buf;  len>0; --len)
  348.             lprc(*str++);
  349. #else VT100
  350.         lflush();
  351.         Write(lfd,buf,len);
  352. #endif VT100
  353.         } 
  354.     else while (len)
  355.         {
  356.         if (lpnt >= lpend) lflush();    /* if buffer is full flush it    */
  357.         num2 = lpbuf+BUFBIG-lpnt;    /*    # bytes left in output buffer    */
  358.         if (num2 > len) num2=len;
  359.         str = lpnt;  len -= num2;
  360.         while (num2--)  *str++ = *buf++;    /* copy in the bytes */
  361.         lpnt = str;
  362.         }
  363.     }
  364.  
  365. /*
  366.  *    long lgetc()                Read one character from input buffer
  367.  *
  368.  *  Returns 0 if EOF, otherwise the character
  369.  */
  370. long lgetc()
  371.     {
  372.     register int i;
  373.     if (ipoint != iepoint)  return(inbuffer[ipoint++]);
  374.     if (iepoint!=MAXIBUF)   return(0);
  375.     if ((i=read(fd,inbuffer,MAXIBUF))<=0)
  376.         {
  377.         if (i!=0)  Write(1,"error reading from input file\n",30);
  378.         iepoint = ipoint = 0;        return(0);
  379.         }
  380.     ipoint=1;  iepoint=i;  return(*inbuffer);
  381.     }
  382.  
  383. /*
  384.  *    long lrint()            Read one integer from input buffer
  385.  *
  386.  *        +---------+---------+---------+---------+
  387.  *        |    high  |            |          |      low    |
  388.  *        |  order  |            |          |  order    |
  389.  *        |   byte  |            |          |      byte    |
  390.  *        +---------+---------+---------+---------+
  391.  *       31  ---  24 23 --- 16 15 ---  8 7  ---   0
  392.  *
  393.  *    The save order is low order first, to high order (4 bytes total)
  394.  *    Returns the int read
  395.  */
  396. long lrint()
  397.     {
  398.     register unsigned long i;
  399.     i  = 255 & lgetc();                i |= (255 & lgetc()) << 8;
  400.     i |= (255 & lgetc()) << 16;        i |= (255 & lgetc()) << 24;
  401.     return(i);
  402.     }
  403.  
  404. /*
  405.  *    lrfill(address,number)            put input bytes into a buffer
  406.  *        char *address;
  407.  *        int number;
  408.  *
  409.  *    Reads "number" bytes into the buffer pointed to by "address".
  410.  *    Returns nothing of value
  411.  */
  412. lrfill(adr,num)
  413.     register char *adr;
  414.     int num;
  415.     {
  416.     register char *pnt;
  417.     register int num2;
  418.     while (num)
  419.         {
  420.         if (iepoint == ipoint)
  421.             {
  422.             if (num>5) /* fast way */
  423.                 {
  424.                 if (read(fd,adr,num) != num)
  425.                     Write(2,"error reading from input file\n",30);
  426.                 num=0;
  427.                 }
  428.             else { *adr++ = lgetc();  --num; }
  429.             }
  430.         else
  431.             {
  432.             num2 = iepoint-ipoint;    /*    # of bytes left in the buffer    */
  433.             if (num2 > num) num2=num;
  434.             pnt = inbuffer+ipoint;    num -= num2;  ipoint += num2;
  435.             while (num2--)  *adr++ = *pnt++;
  436.             }
  437.         }
  438.     }
  439.  
  440. /*
  441.  *    char *lgetw()            Get a whitespace ended word from input
  442.  *
  443.  *    Returns pointer to a buffer that contains word.  If EOF, returns a NULL
  444.  */
  445. char *lgetw()
  446.     {
  447.     register char *lgp,cc;
  448.     register int n=LINBUFSIZE,quote=0;
  449.     lgp = lgetwbuf;
  450.     do cc=lgetc();  while ((cc <= 32) && (cc > NULL));  /* eat whitespace */
  451.     for ( ; ; --n,cc=lgetc())
  452.         {
  453.         if ((cc==NULL) && (lgp==lgetwbuf))  return(NULL);    /* EOF */
  454.         if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=NULL; return(lgetwbuf); }
  455.         if (cc != '"') *lgp++ = cc;   else quote ^= 1;
  456.         }
  457.     }
  458.  
  459. /*
  460.  *    char *lgetl()        Function to read in a line ended by newline or EOF
  461.  *
  462.  *    Returns pointer to a buffer that contains the line.  If EOF, returns NULL
  463.  */
  464. char *lgetl()
  465.     {
  466.     register int i=LINBUFSIZE,ch;
  467.     register char *str=lgetwbuf;
  468.     for ( ; ; --i)
  469.         {
  470.         if ((*str++ = ch = lgetc()) == NULL)
  471.             {
  472.             if (str == lgetwbuf+1)  return(NULL); /* EOF */
  473.         ot:    *str = NULL;    return(lgetwbuf);    /* line ended by EOF */
  474.             }
  475.         if ((ch=='\n') || (i<=1))  goto ot; /* line ended by \n */
  476.         }
  477.     }
  478.  
  479. /*
  480.  *    lcreat(filename)            Create a new file for Write
  481.  *        char *filename;
  482.  *
  483.  *    lcreat((char*)0); means to the terminal
  484.  *    Returns -1 if error, otherwise the file descriptor opened.
  485.  */
  486. lcreat(str)
  487.     char *str;
  488.     {
  489.     lpnt = lpbuf;    lpend = lpbuf+BUFBIG;
  490.     if (str==NULL) return(lfd=1);
  491. # ifndef OSK
  492.     if ((lfd=creat(str,0644)) < 0) 
  493. # else OSK
  494.     if (access (str, 0) < 0)
  495.         lfd=create(str, S_IWRITE, 013);
  496.     else
  497.         lfd=creat(str, S_IWRITE);
  498.     if (lfd < 0)
  499. # endif OSK
  500.         {
  501.         lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1);
  502.         }
  503.     return(lfd);
  504.     }
  505.  
  506. /*
  507.  *    lopen(filename)            Open a file for read
  508.  *        char *filename;
  509.  *
  510.  *    lopen(0) means from the terminal
  511.  *    Returns -1 if error, otherwise the file descriptor opened.
  512.  */
  513. lopen(str)
  514.     char *str;
  515.     {
  516.     ipoint = iepoint = MAXIBUF;
  517.     if (str==NULL) return(fd=0);
  518. # ifndef OSK
  519.     if ((fd=open(str,0)) < 0)
  520. # else OSK
  521.     if ((fd=open(str,S_IREAD)) < 0)
  522. # endif OSK
  523.         {
  524.         lwclose(); lfd=1; lpnt=lpbuf; return(-1);
  525.         }
  526.     return(fd);
  527.     }
  528.  
  529. /*
  530.  *    lappend(filename)        Open for append to an existing file
  531.  *        char *filename;
  532.  *
  533.  *    lappend(0) means to the terminal
  534.  *    Returns -1 if error, otherwise the file descriptor opened.
  535.  */
  536. lappend(str)
  537.     char *str;
  538.     {
  539.     lpnt = lpbuf;    lpend = lpbuf+BUFBIG;
  540.     if (str==NULL) return(lfd=1);
  541. # ifndef OSK
  542.     if ((lfd=open(str,2)) < 0)
  543. # else OSK
  544.     if ((lfd=open(str,S_IREAD | S_IWRITE)) < 0)
  545. # endif OSK
  546.         {
  547.         lfd=1; return(-1);
  548.         }
  549.     lseek(lfd,0,2);    /* seek to end of file */
  550.     return(lfd);
  551.     }
  552.  
  553. /*
  554.  *    lrclose()                        close the input file
  555.  *
  556.  *    Returns nothing of value.
  557.  */
  558. lrclose()
  559.     {
  560.     if (fd > 0) close(fd);
  561.     }
  562.  
  563. /*
  564.  *    lwclose()                        close output file flushing if needed
  565.  *
  566.  *    Returns nothing of value.
  567.  */
  568. lwclose()
  569.     {
  570.     lflush();    if (lfd > 2) close(lfd);
  571.     }
  572.  
  573. /*
  574.  *    lprcat(string)                    append a string to the output buffer
  575.  *                                    avoids calls to lprintf (time consuming)
  576.  */
  577. lprcat(str)
  578.     register char *str;
  579.     {
  580.     register char *str2;
  581.     if (lpnt >= lpend) lflush(); 
  582.     str2 = lpnt;
  583.     while (*str2++ = *str++);
  584.     lpnt = str2 - 1;
  585.     }
  586.  
  587. #ifdef VT100
  588. /*
  589.  *    cursor(x,y)         Subroutine to set the cursor position
  590.  *
  591.  *    x and y are the cursor coordinates, and lpbuff is the output buffer where
  592.  *    escape sequence will be placed. 
  593.  */
  594. static char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
  595.     "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
  596.     "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
  597.     "\33[23","\33[24" };
  598.  
  599. static char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
  600.     ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
  601.     ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
  602.     ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
  603.     ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
  604.     ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
  605.     ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
  606.     ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
  607.     ";80H" };
  608.  
  609. cursor(x,y)
  610.     int x,y;
  611.     {
  612.     register char *p;
  613.     if (lpnt >= lpend) lflush();
  614.  
  615.     p = y_num[y];    /* get the string to print */
  616.     while (*p) *lpnt++ = *p++;    /* print the string */
  617.  
  618.     p = x_num[x];    /* get the string to print */
  619.     while (*p) *lpnt++ = *p++;    /* print the string */
  620.     }
  621. #else VT100
  622. /*
  623.  * cursor(x,y)      Put cursor at specified coordinates staring at [1,1] (termcap)
  624.  */
  625. cursor (x,y)
  626.     int x,y;
  627.     {
  628.     if (lpnt >= lpend) lflush ();
  629.  
  630.     *lpnt++ = CURSOR;        *lpnt++ = x;        *lpnt++ = y;
  631.     }
  632. #endif VT100
  633.  
  634. /*
  635.  *    Routine to position cursor at beginning of 24th line
  636.  */
  637. cursors()
  638.     {
  639.     cursor(1,24);
  640.     }
  641.  
  642. #ifndef VT100
  643. /*
  644.  * Warning: ringing the bell is control code 7. Don't use in defines.
  645.  * Don't change the order of these defines.
  646.  * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
  647.  * obvious meanings.
  648.  */
  649.  
  650. static char cap[256];
  651. char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
  652. static char *outbuf=0;    /* translated output buffer */
  653.  
  654. int putchar ();
  655.  
  656. /*
  657.  * init_term()        Terminal initialization -- setup termcap info
  658.  */
  659. init_term()
  660.     {
  661.     char termbuf[1024];
  662.     char *capptr = cap+10;
  663.     char *term;
  664.  
  665.     switch (tgetent(termbuf, term = getenv("TERM")))
  666.         {
  667.         case -1: 
  668.             Write(2, "Cannot open termcap file.\n", 26); exit(1);
  669.         case 0: 
  670.             Write(2, "Cannot find entry of ", 21);
  671.             Write(2, term, strlen (term));
  672.             Write(2, " in termcap\n", 12);
  673.             exit(1);
  674.         };
  675.  
  676.     CM = tgetstr("cm", &capptr);  /* Cursor motion */
  677.     CE = tgetstr("ce", &capptr);  /* Clear to eoln */
  678.     CL = tgetstr("cl", &capptr);  /* Clear screen */
  679.  
  680. /* OPTIONAL */
  681.     AL = tgetstr("al", &capptr);  /* Insert line */
  682.     DL = tgetstr("dl", &capptr);  /* Delete line */
  683.     SO = tgetstr("so", &capptr);  /* Begin standout mode */
  684.     SE = tgetstr("se", &capptr);  /* End standout mode */
  685.     CD = tgetstr("cd", &capptr);  /* Clear to end of display */
  686.  
  687.     if (!CM)    /* can't find cursor motion entry */
  688.         {
  689.         Write(2, "Sorry, for a ",13);        Write(2, term, strlen(term));
  690.         Write(2, ", I can't find the cursor motion entry in termcap\n",50);
  691.         exit(1);
  692.         }
  693.     if (!CE)    /* can't find clear to end of line entry */
  694.         {
  695.         Write(2, "Sorry, for a ",13);        Write(2, term, strlen(term));
  696.         Write(2,", I can't find the clear to end of line entry in termcap\n",57);
  697.         exit(1);
  698.         }
  699.     if (!CL)    /* can't find clear entire screen entry */
  700.         {
  701.         Write(2, "Sorry, for a ",13);        Write(2, term, strlen(term));
  702.         Write(2, ", I can't find the clear entire screen entry in termcap\n",56);
  703.         exit(1);
  704.         }
  705.     if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/
  706.         {
  707.         Write(2,"Error malloc'ing memory for decoded output buffer\n",50);
  708.         died(-285);    /* malloc() failure */
  709.         }
  710.     }
  711. #endif VT100
  712.  
  713. /*
  714.  * cl_line(x,y)  Clear the whole line indicated by 'y' and leave cursor at [x,y]
  715.  */
  716. cl_line(x,y)
  717.     int x,y;
  718.     {
  719. #ifdef VT100
  720.     cursor(x,y);        lprcat("\33[2K");
  721. #else VT100
  722.     cursor(1,y);        *lpnt++ = CL_LINE;        cursor(x,y);
  723. #endif VT100
  724.     }
  725.  
  726. /*
  727.  * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
  728.  */
  729. cl_up(x,y)
  730.     register int x,y;
  731.     {
  732. #ifdef VT100
  733.     cursor(x,y);  lprcat("\33[1J\33[2K");
  734. #else VT100
  735.     register int i;
  736.     cursor(1,1);
  737.     for (i=1; i<=y; i++)   { *lpnt++ = CL_LINE;  *lpnt++ = '\n'; }
  738.     cursor(x,y);
  739. #endif VT100
  740.     }
  741.  
  742. /*
  743.  * cl_dn(x,y)     Clear screen from [1,y] to end of display. Leave cursor at [x,y]
  744.  */
  745. cl_dn(x,y)
  746.     register int x,y;
  747.     {
  748. #ifdef VT100
  749.     cursor(x,y); lprcat("\33[J\33[2K");
  750. #else VT100
  751.     register int i;
  752.     cursor(1,y);
  753.     if (!CD)
  754.         {
  755.         *lpnt++ = CL_LINE;
  756.         for (i=y; i<=24; i++) { *lpnt++ = CL_LINE;  if (i!=24) *lpnt++ = '\n'; }
  757.         cursor(x,y);
  758.         }
  759.     else
  760.         *lpnt++ = CL_DOWN;
  761.     cursor(x,y);
  762. #endif VT100
  763.     }
  764.  
  765. /*
  766.  * standout(str)    Print the argument string in inverse video (standout mode).
  767.  */
  768. standout(str)
  769.     register char *str;
  770.     {
  771. #ifdef VT100
  772.     setbold();
  773.     while (*str)
  774.         *lpnt++ = *str++;
  775.     resetbold();
  776. #else VT100
  777.     *lpnt++ = ST_START;
  778.     while (*str)
  779.         *lpnt++ = *str++;
  780.     *lpnt++ = ST_END;
  781. #endif VT100
  782.     }
  783.  
  784. /*
  785.  * set_score_output()     Called when output should be literally printed.
  786.  */
  787. set_score_output()
  788.     {
  789.     enable_scroll = -1;
  790.     }
  791.  
  792. /*
  793.  *    lflush()                        Flush the output buffer
  794.  *
  795.  *    Returns nothing of value.
  796.  *    for termcap version: Flush output in output buffer according to output
  797.  *                            status as indicated by `enable_scroll'
  798.  */
  799. #ifndef VT100
  800. static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
  801. lflush ()
  802.     {
  803.     register int lpoint;
  804.     register char *str;
  805.     static int curx = 0;
  806.     static int cury = 0;
  807.  
  808.     if ((lpoint = lpnt - lpbuf) > 0)
  809.         {
  810. #ifdef EXTRA
  811.         c[BYTESOUT] += lpoint;
  812. #endif
  813.         if (enable_scroll <= -1)
  814.             {
  815.             flush_buf();
  816.             if (Write(lfd,lpbuf,lpoint) != lpoint)
  817.                 Write(2,"error writing to output file\n",29);
  818.             lpnt = lpbuf;    /* point back to beginning of buffer */
  819.             return;
  820.             }
  821.         for (str = lpbuf; str < lpnt; str++)
  822.             {
  823.             if (*str>=32)    { putchar (*str); curx++; }
  824.             else switch (*str)
  825.                 {
  826.                 case CLEAR:        tputs (CL, 0, putchar);        curx = cury = 0;
  827.                                 break;
  828.  
  829.                 case CL_LINE:    tputs (CE, 0, putchar);
  830.                                 break;
  831.  
  832.                 case CL_DOWN:    tputs (CD, 0, putchar);
  833.                                 break;
  834.  
  835.                 case ST_START:    tputs (SO, 0, putchar);
  836.                                 break;
  837.  
  838.                 case ST_END:    tputs (SE, 0, putchar);
  839.                                 break;
  840.  
  841.                 case CURSOR:    curx = *++str - 1;        cury = *++str - 1;
  842.                                 tputs (tgoto (CM, curx, cury), 0, putchar);
  843.                                 break;
  844.  
  845.                 case '\n':        if ((cury == 23) && enable_scroll)
  846.                                   {
  847.                                   if (!DL || !AL) /* wraparound or scroll? */
  848.                                     {
  849.                                     if (++scrline > 23) scrline=19;
  850.  
  851.                                     if (++scrline > 23) scrline=19;
  852.                                     tputs (tgoto (CM, 0, scrline), 0, putchar);
  853.                                     tputs (CE, 0, putchar);
  854.  
  855.                                     if (--scrline < 19) scrline=23;
  856.                                     tputs (tgoto (CM, 0, scrline), 0, putchar);
  857.                                     tputs (CE, 0, putchar);
  858.                                     }
  859.                                   else
  860.                                     {
  861.                                     tputs (tgoto (CM, 0, 19), 0, putchar);
  862.                                     tputs (DL, 0, putchar);
  863.                                     tputs (tgoto (CM, 0, 23), 0, putchar);
  864.                                 /*    tputs (AL, 0, putchar); */
  865.                                     }
  866.                                   }
  867.                                 else
  868.                                   {
  869.                                   putchar ('\n');        cury++;
  870.                                   }
  871.                                 curx = 0;
  872.                                 break;
  873.  
  874.                 default:        putchar (*str); curx++;
  875.                 };
  876.             }
  877.         }
  878.     lpnt = lpbuf;
  879.     flush_buf();    /* flush real output buffer now */
  880.     }
  881. #else VT100
  882. /*
  883.  *    lflush()                        flush the output buffer
  884.  *
  885.  *    Returns nothing of value.
  886.  */
  887. lflush()
  888.     {
  889.     register int lpoint;
  890.     if ((lpoint = lpnt - lpbuf) > 0)
  891.         {
  892. #ifdef EXTRA
  893.         c[BYTESOUT] += lpoint;
  894. #endif
  895.         if (Write(lfd,lpbuf,lpoint) != lpoint)
  896.             Write(2,"error writing to output file\n",29);
  897.         }
  898.     lpnt = lpbuf;    /* point back to beginning of buffer */
  899.     }
  900. #endif VT100
  901.  
  902. #ifndef VT100
  903. static int index=0;
  904. /*
  905.  * putchar(ch)        Print one character in decoded output buffer.
  906.  */
  907. int putchar(c)
  908. int c;
  909.     {
  910.     outbuf[index++] = c;
  911.     if (index >= BUFBIG)  flush_buf();
  912.     }
  913.  
  914. /*
  915.  * flush_buf()            Flush buffer with decoded output.
  916.  */
  917. flush_buf()
  918.     {
  919.     if (index) Write(lfd, outbuf, index);
  920.     index = 0;
  921.     }
  922.  
  923. /*
  924.  *    char *tmcapcnv(sd,ss)  Routine to convert VT100 escapes to termcap format
  925.  *
  926.  *    Processes only the \33[#m sequence (converts . files for termcap use 
  927.  */
  928. char *tmcapcnv(sd,ss)  
  929.     register char *sd,*ss;
  930.     {
  931.     register int tmstate=0;    /* 0=normal, 1=\33 2=[ 3=# */
  932.     char tmdigit=0;    /* the # in \33[#m */
  933.     while (*ss)
  934.         {
  935.         switch(tmstate)
  936.             {
  937.             case 0:    if (*ss=='\33')  { tmstate++; break; }
  938.               ign:  *sd++ = *ss;
  939.               ign2: tmstate = 0;
  940.                     break;
  941.             case 1: if (*ss!='[') goto ign;
  942.                     tmstate++;
  943.                     break;
  944.             case 2: if (isdigit(*ss)) { tmdigit= *ss-'0'; tmstate++; break; }
  945.                     if (*ss == 'm') { *sd++ = ST_END; goto ign2; }
  946.                     goto ign;
  947.             case 3: if (*ss == 'm')
  948.                         {
  949.                         if (tmdigit) *sd++ = ST_START;
  950.                             else *sd++ = ST_END;
  951.                         goto ign2;
  952.                         }
  953.             default: goto ign;
  954.             };
  955.         ss++;
  956.         }
  957.     *sd=0; /* NULL terminator */
  958.     return(sd);
  959.     }
  960. #endif VT100
  961.  
  962. /*
  963.  *    beep()        Routine to emit a beep if enabled (see no-beep in .larnopts)
  964.  */
  965. beep()
  966.     {
  967.     if (!nobeep) *lpnt++ = '\7';
  968.     }
  969.