home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / UTIL / WWIVE / COM.C < prev    next >
Text File  |  1992-01-22  |  23KB  |  1,079 lines

  1. /*****************************************************************************
  2.  
  3.                 WWIV Version 4
  4.                     Copyright (C) 1988-1991 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "vars.h"
  18.  
  19. #pragma hdrstop
  20.  
  21. #include <stdarg.h>
  22. #include <math.h>
  23. #include <stdlib.h>
  24.  
  25.  
  26.  
  27. #define frequency 500
  28.  
  29.  
  30. int check_comport(int pn)
  31. {
  32.   unsigned char new_iir, old_iir;
  33.  
  34.   old_iir = inportb(syscfg.com_base[pn]+2);
  35.   outportb(syscfg.com_base[pn]+2,0xc1);
  36.   new_iir = inportb(syscfg.com_base[pn]+2);
  37.   outportb(syscfg.com_base[pn]+2,old_iir);
  38.  
  39.   if (new_iir & 0x38) {
  40.     /* no com port */
  41.     return(0);
  42.   }
  43.  
  44.   switch ((new_iir >> 6) & 0x03) {
  45.     case 0: /* no 16550 */
  46.     case 1: /* huh? */
  47.       return(1);
  48.  
  49.     case 2: /* 16550 */
  50.     case 3: /* 16550A */
  51.       return(2);
  52.   }
  53.  
  54.   return(1);
  55. }
  56.  
  57.  
  58. void savel(char *cl, char *atr, char *xl, char *cc)
  59. {
  60.   int i, i1;
  61.  
  62.   *cc = curatr;
  63.   strcpy(xl, endofline);
  64.   i = ((wherey() + topline) * 80) * 2;
  65.   for (i1 = 0; i1 < wherex(); i1++) {
  66.     cl[i1]  = scrn[i + (i1 * 2)];
  67.     atr[i1] = scrn[i + (i1 * 2) + 1];
  68.   }
  69.   cl[wherex()]  = 0;
  70.   atr[wherex()] = 0;
  71. }
  72.  
  73.  
  74. void restorel(char *cl, char *atr, char *xl, char *cc)
  75. {
  76.   int i;
  77.  
  78.   if (wherex())
  79.     nl();
  80.   for (i = 0; cl[i] != 0; i++) {
  81.     setc(atr[i]);
  82.     outchr(cl[i]);
  83.   }
  84.   setc(*cc);
  85.   strcpy(endofline, xl);
  86. }
  87.  
  88.  
  89. void ptime()
  90. {
  91.   char xl[81], cl[81], atr[81], cc, s[81];
  92.   long l;
  93.  
  94.   savel(cl, atr, xl, &cc);
  95.  
  96.   ansic(0);
  97.   nl();
  98.   nl();
  99.   time(&l);
  100.   strcpy(s, ctime(&l));
  101.   s[strlen(s) - 1] = 0;
  102.   pl(s);
  103.   if (useron) {
  104.     npr("7[1Time on7]1   = 7%s\r\n", ctim(timer() - timeon));
  105.     npr("7[1Time left7]1 =7 %s\r\n", ctim(nsl()));
  106.   }
  107.   nl();
  108.  
  109.   restorel(cl, atr, xl, &cc);
  110. }
  111.  
  112.  
  113. void reprint()
  114. {
  115.   char xl[81], cl[81], atr[81], cc, ansistr_1[81];
  116.   int ansiptr_1;
  117.  
  118.   ansiptr_1=ansiptr;
  119.   ansiptr=0;
  120.   ansistr[ansiptr_1]=0;
  121.   strcpy(ansistr_1,ansistr);
  122.  
  123.   savel(cl, atr, xl, &cc);
  124.   nl();
  125.   restorel(cl, atr, xl, &cc);
  126.  
  127.   strcpy(ansistr,ansistr_1);
  128.   ansiptr=ansiptr_1;
  129. }
  130.  
  131.  
  132. void print_help(int n)
  133. {
  134.   char xl[81], cl[81], atr[81], cc, s[81];
  135.   int next;
  136.  
  137.   savel(cl, atr, xl, &cc);
  138.   ansic(0);
  139.   outstr("\x0c");
  140.  
  141.   sprintf(s,"%sHELP.MSG",syscfg.gfilesdir);
  142.   next = 0;
  143.   if (helps[n].stored_as)
  144.     read_message1(&helps[n], 0, 0, &next, s);
  145.  
  146.   restorel(cl, atr, xl, &cc);
  147. }
  148.  
  149.  
  150. void setbeep(int i)
  151. {
  152.   int i1,i2;
  153.  
  154.   if (i) {
  155.     i1 = 0x34DD / frequency;
  156.     i2 = inportb(0x61);
  157.     if (!(i2 & 0x03)) {
  158.       outportb(0x61, i2 | 0x03);
  159.       outportb(0x43, 0xB6);
  160.     }
  161.     outportb(0x42, i1 & 0x0F);
  162.     outportb(0x42, i1 >> 4);
  163.   } else
  164.     outportb(0x61, inportb(0x61) & 0xFC);
  165. }
  166.  
  167. void far interrupt async_isr ()
  168. /* This function is called every time a char is received on the com port.
  169.  * The character is stored in the buffer[] array, and the head pointer is
  170.  * updated.
  171.  */
  172. {
  173.   buffer[head++] = inportb(base);
  174.   if (head == max_buf)
  175.     head = 0;
  176.   outportb(0x20, 0x20);
  177. }
  178.  
  179.  
  180.  
  181. void outcomch(char ch)
  182. /* This function outputs one character to the com port */
  183. {
  184.   while (!(inportb(base + 5) & 0x20))
  185.     ;
  186.   if (flow_control)
  187.     while (!(inportb(base + 6) & 0x10))
  188.       ;
  189.   outportb(base, ch);
  190. }
  191.  
  192.  
  193.  
  194. char peek1c()
  195. {
  196.   if (head!=tail) {
  197.     return(buffer[tail]);
  198.   } else
  199.     return(0);
  200. }
  201.  
  202. char get1c()
  203. /* This function returns one character from the com port, or a zero if
  204.  * no character is waiting
  205.  */
  206. {
  207.   char c1;
  208.  
  209.   if (head != tail) {
  210.     disable();
  211.     c1 = buffer[tail++];
  212.     if (tail == max_buf)
  213.       tail = 0;
  214.     enable();
  215.     return(c1);
  216.   } else
  217.     return(0);
  218. }
  219.  
  220.  
  221.  
  222. int comhit()
  223. /* This returns a value telling if there is a character waiting in the com
  224.  * buffer.
  225.  */
  226. {
  227.   return(head != tail);
  228. }
  229.  
  230.  
  231.  
  232. void dump()
  233. /* This function clears the com buffer */
  234. {
  235.   disable();
  236.   head = tail = 0;
  237.   enable();
  238. }
  239.  
  240.  
  241.  
  242. void set_baud(unsigned int rate)
  243. /* This function sets the com speed to that passed */
  244. {
  245.   float rl;
  246.  
  247.   if ((rate > 49) && (rate < 57601)) {
  248.     rl   = 115200.0 / ((float) rate);
  249.     rate = (int) rl;
  250.     outportb(base + 3, inportb(base + 3) | 0x80);
  251.     outportb(base,     (rate & 0x00FF));
  252.     outportb(base + 1, ((rate >> 8) & 0x00FF));
  253.     outportb(base + 3, inportb(base + 3) & 0x7F);
  254.   }
  255. }
  256.  
  257.  
  258. void initport(int port_num)
  259. /* This function initializes the com buffer, setting up the interrupt,
  260.  * and com parameters
  261.  */
  262. {
  263.   int temp;
  264.  
  265.   base = syscfg.com_base[port_num];
  266.   async_irq = syscfg.com_ISR[port_num];
  267.   setvect(8 + async_irq, async_isr);
  268.   head = tail = 0;
  269.   outportb(base + 3, 0x03);
  270.   disable();
  271.   temp = inportb(base + 5);
  272.   temp = inportb(base);
  273.   temp = inportb(0x21);
  274.   temp = temp & ((1 << async_irq) ^ 0x00FF);
  275.   outportb(0x21, temp);
  276.   outportb(base + 1, 0x01);
  277.   temp=inportb(base + 4);
  278.   outportb(base + 4, temp | 0x0A);
  279.   outportb(base+2,0xc1);
  280.   enable();
  281.   dtr(1);
  282. }
  283.  
  284.  
  285.  
  286. void closeport()
  287. /* This function closes out the com port, removing the interrupt routine,
  288.  * etc.
  289.  */
  290. {
  291.   int temp;
  292.  
  293.   disable();
  294.   temp = inportb(0x21);
  295.   temp = temp | ((1 << async_irq));
  296.   outportb(0x21, temp | 0x10);
  297.   outportb(base + 2, 0);
  298.   outportb(base + 4, 3);
  299.   enable();
  300. }
  301.  
  302. void dtr(int i)
  303. /* This function sets the DTR pin to the status given */
  304. {
  305.   int i1;
  306.  
  307.   i1 = inportb(base + 4) & 0x00FE;
  308.   outportb(base + 4, (i || no_hangup) ? (i1 + 1) : i1);
  309. }
  310.  
  311.  
  312. void rts(int i)
  313. /* This function sets the RTS pin to the status given */
  314. {
  315.   int i1;
  316.  
  317.   i1 = inportb(base + 4) & 0x00FD;
  318.   outportb(base + 4, (i) ? (i1 + 2) : i1);
  319. }
  320.  
  321.  
  322. int cdet()
  323. /* This returns the status of the carrier detect lead from the modem */
  324. {
  325.   return((inportb(base + 6) & 0x80) ? 1 : 0);
  326. }
  327.  
  328.  
  329.  
  330. void checkhangup()
  331. /* This function checks to see if the user logged on to the com port has
  332.  * hung up.  Obviously, if no user is logged on remotely, this does nothing.
  333.  * If carrier detect is detected to be low, it is checked 100 times
  334.  * sequentially to make sure it stays down, and is not just a quirk.
  335.  */
  336. {
  337.   int i, ok;
  338.  
  339.   if (!hangup && using_modem && !cdet()) {
  340.     ok = 0;
  341.     for (i = 0; (i < 500) && !ok; i++)
  342.       if (cdet())
  343.         ok = 1;
  344.     if (!ok) {
  345.       hangup = hungup = 1;
  346.       if (useron && !in_extern)
  347.     sysoplog("That Bama hung Up!");
  348.     }
  349.   }
  350. }
  351.  
  352.  
  353.  
  354.  
  355. void addto(char *s, int i)
  356. {
  357.   char temp[20];
  358.  
  359.   if (s[0])
  360.     strcat(s, ";");
  361.   else
  362.     strcpy(s, "\x1B[");
  363.   itoa(i, temp, 10);
  364.   strcat(s, temp);
  365. }
  366.  
  367.  
  368. void makeansi(unsigned char attr, char *s, int forceit)
  369. /* Passed to this function is a one-byte attribute as defined for IBM type
  370.  * screens.  Returned is a string which, when printed, will change the
  371.  * display to the color desired, from the current function.
  372.  */
  373. {
  374.   unsigned char catr;
  375.   char *temp = "04261537";
  376.  
  377.   catr = curatr;
  378.   s[0] = 0;
  379.   if (attr != catr) {
  380.     if ((catr & 0x88) ^ (attr & 0x88)) {
  381.       addto(s, 0);
  382.       addto(s, 30 + temp[attr & 0x07] - '0');
  383.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  384.       catr = attr & 0x77;
  385.     }
  386.     if ((catr & 0x07) != (attr & 0x07))
  387.       addto(s, 30 + temp[attr & 0x07] - '0');
  388.     if ((catr & 0x70) != (attr & 0x70))
  389.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  390.     if ((catr & 0x08) ^ (attr & 0x08))
  391.       addto(s, 1);
  392.     if ((catr & 0x80) ^ (attr & 0x80)) {
  393.       if (checkcomp("Mac"))     /*This is the code for Mac's underline*/
  394.         addto(s, 4);            /*They don't have Blinking or Italics*/
  395.       else {
  396.         if (checkcomp("Ami"))   /*Some Amiga terminals use 3 instead of*/
  397.           addto(s, 3);          /*5 for italics.  Using both won't hurt*/
  398.         addto(s, 5);            /*anything, only italics will be generated*/
  399.       }
  400.     }
  401.   }
  402.   if (s[0])
  403.     strcat(s, "m");
  404.   if (!okansi() && !forceit)
  405.     s[0]=0;
  406. }
  407.  
  408.  
  409.  
  410. void setfgc(int i)
  411. /* This sets the foreground color to that passed.  It is called only from
  412.  * execute_ansi
  413.  */
  414. {
  415.   curatr = (curatr & 0xf8) | i;
  416. }
  417.  
  418.  
  419.  
  420. void setbgc(int i)
  421. /* This sets the background color to that passed.  It is called only from
  422.  * execute_ansi
  423.  */
  424. {
  425.   curatr = (curatr & 0x8f) | (i << 4);
  426. }
  427.  
  428.  
  429. void execute_ansi()
  430. /* This function executes an ANSI string to change color, position the
  431.  * cursor, etc.
  432.  */
  433. {
  434.   int args[11], argptr, count, ptr, tempptr, ox, oy;
  435.   char cmd, temp[11], teol[81], *clrlst = "04261537";
  436.  
  437.   if (ansistr[1] != '[') {
  438.  
  439.     /* do nothing if invalid ANSI string. */
  440.  
  441.   } else {
  442.     argptr = tempptr = 0;
  443.     ptr = 2;
  444.     for (count = 0; count < 10; count++)
  445.       args[count] = temp[count] = 0;
  446.     cmd = ansistr[ansiptr - 1];
  447.     ansistr[ansiptr - 1] = 0;
  448.     while ((ansistr[ptr]) && (argptr<10) && (tempptr<10)) {
  449.       if (ansistr[ptr] == ';') {
  450.         temp[tempptr] = 0;
  451.         tempptr = 0;
  452.         args[argptr++] = atoi(temp);
  453.       } else
  454.         temp[tempptr++] = ansistr[ptr];
  455.       ++ptr;
  456.     }
  457.     if (tempptr && (argptr<10)) {
  458.       temp[tempptr]  = 0;
  459.       args[argptr++] = atoi(temp);
  460.     }
  461.     if ((cmd >= 'A') && (cmd <= 'D') && !args[0])
  462.       args[0] = 1;
  463.     switch (cmd) {
  464.         case 'f':
  465.         case 'H':
  466.           movecsr(args[1] - 1, args[0] - 1);
  467.           break;
  468.         case 'A':
  469.           movecsr(wherex(), wherey() - args[0]);
  470.           break;
  471.         case 'B':
  472.           movecsr(wherex(), wherey() + args[0]);
  473.           break;
  474.         case 'C':
  475.           movecsr(wherex() + args[0], wherey());
  476.           break;
  477.         case 'D':
  478.           movecsr(wherex() - args[0], wherey());
  479.           break;
  480.         case 's':
  481.           oldx = wherex();
  482.           oldy = wherey();
  483.           break;
  484.         case 'u':
  485.           movecsr(oldx, oldy);
  486.           break;
  487.         case 'J':
  488.           if (args[0] == 2)
  489.             clrscrb();
  490.           break;
  491.         case 'k':
  492.         case 'K':
  493.           ox = wherex();
  494.           oy = wherey();
  495.           _CX = 80 - ox;
  496.           _AH = 0x09;
  497.           _BH = 0x00;
  498.           _AL = 32;
  499.           _BL = curatr;
  500.           my_video_int();
  501.           movecsr(ox, oy);
  502.           break;
  503.         case 'm':
  504.           if (!argptr) {
  505.             argptr = 1;
  506.             args[0] = 0;
  507.           }
  508.           for (count = 0; count < argptr; count++)
  509.             switch (args[count]) {
  510.               case 0: curatr = 0x07; break;
  511.               case 1: curatr = curatr | 0x08; break;
  512.               case 4: break;
  513.               case 5: curatr = curatr | 0x80; break;
  514.               case 7:
  515.                 ptr = curatr & 0x77;
  516.                 curatr = (curatr & 0x88) | (ptr << 4) | (ptr >> 4);
  517.                 break;
  518.               case 8: curatr = 0; break;
  519.               default:
  520.                 if ((args[count] >= 30) && (args[count] <= 37))
  521.                   setfgc(clrlst[args[count] - 30] - '0');
  522.                 else if ((args[count] >= 40) && (args[count] <= 47))
  523.                   setbgc(clrlst[args[count] - 40] - '0');
  524.             }
  525.           break;
  526.       }
  527.     }
  528.   ansiptr = 0;
  529. }
  530.  
  531.  
  532.  
  533. void outchr(char c)
  534. /* This function outputs one character to the screen, and if output to the
  535.  * com port is enabled, the character is output there too.  ANSI graphics
  536.  * are also trapped here, and the ansi function is called to execute the
  537.  * ANSI codes
  538.  */
  539. {
  540.   int i, i1;
  541.  
  542.   if (change_color) {
  543.     change_color = 0;
  544.     if ((c >= '0') && (c <= '9'))
  545.       ansic(c - '0');
  546.     else if ((c >= 'A') && (c <= 'F'))
  547.       ansic(c-'A'+10);
  548.     else if ((c >= 'a') && (c <= 'f'))
  549.       ansic(c-'a'+10);
  550.     return;
  551.   }
  552.   if (c == 3) {
  553.     change_color = 1;
  554.     return;
  555.   }
  556.   if (chatcall && !(syscfg.sysconfig & sysconfig_no_beep))
  557.     setbeep(1);
  558.   if ((c == 10) && endofline[0]) {
  559.     if (!in_extern)
  560.       outstr(endofline);
  561.     endofline[0] = 0;
  562.   }
  563.  
  564.   if (global_handle)
  565.     if (echo)
  566.       write(global_handle,&c,1);
  567.  
  568.   if (outcom && (c != 9))
  569.     outcomch(echo ? c : '■');
  570.   if (ansiptr) {
  571.     ansistr[ansiptr++] = c;
  572.     ansistr[ansiptr]   = 0;
  573.     if ((((c < '0') || (c > '9')) && (c!='[') && (c!=';')) ||
  574.         (ansistr[1] != '[') || (ansiptr>75))
  575.       execute_ansi();
  576.   } else if (c == 27) {
  577.     ansistr[0] = 27;
  578.     ansiptr = 1;
  579.     ansistr[ansiptr]=0;
  580.   } else if (c == 9) {
  581.     i1 = wherex();
  582.     for (i = i1; i< (((i1 / 8) + 1) * 8); i++)
  583.       outchr(32);
  584.   } else if (echo || lecho) {
  585.     out1ch(c);
  586.     if (c == 10) {
  587.       ++lines_listed;
  588.       if ((sysstatus_pause_on_page & thisuser.sysstatus) &&
  589.           (lines_listed >= screenlinest - 1)) {
  590.         pausescr();
  591.         lines_listed = 0;
  592.       }
  593.     }
  594.   } else
  595.     out1ch('X');
  596.   if (chatcall)
  597.     setbeep(0);
  598. }
  599.  
  600.  
  601.  
  602. void outstr(char *s)
  603. /* This function outputs a string of characters to the screen (and remotely
  604.  * if applicable).  The com port is also checked first to see if a remote
  605.  * user has hung up
  606.  */
  607. {
  608.   int i=0;
  609.  
  610.   checkhangup();
  611.   if (!hangup)
  612.     while (s[i])
  613.       outchr(s[i++]);
  614. }
  615.  
  616.  
  617.  
  618. void nl()
  619. /* This function performs a CR/LF sequence to move the cursor to the next
  620.  * line.  If any end-of-line ANSI codes are set (such as changing back to
  621.  * the default color) are specified, those are executed first.
  622.  */
  623. {
  624.   if (endofline[0]) {
  625.     outstr(endofline);
  626.     endofline[0] = 0;
  627.   }
  628.   outstr("\r\n");
  629. }
  630.  
  631.  
  632.  
  633. void backspace()
  634. /* This function executes a backspace, space, backspace sequence. */
  635. {
  636.   int i;
  637.  
  638.   i = echo;
  639.   echo = 1;
  640.   outstr("\b \b");
  641.   echo = i;
  642. }
  643.  
  644.  
  645.  
  646. void setc(unsigned char ch)
  647. /* This sets the current color (both locally and remotely) to that
  648.  * specified (in IBM format).
  649.  */
  650. {
  651.   char s[30];
  652.  
  653.   makeansi(ch, s, 0);
  654.   outstr(s);
  655. }
  656.  
  657. void pausescr()
  658. /* This will pause output, displaying the [PAUSE] message, and wait for
  659.  * a key to be hit.
  660.  */
  661. {
  662.   int i;
  663.  
  664.   if (okansi()) {
  665.     i = curatr;
  666.     setc((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[3] :
  667.           thisuser.bwcolors[3]);
  668.     outstr("[Pausing Bama!]\x1b[15D");
  669.     setc(i);
  670.     getkey();
  671.     outstr("               \x1b[15D");
  672.   } else {
  673.     outstr("[Pausing Bama!]");
  674.     getkey();
  675.     for (i = 0; i < 15; i++)
  676.       backspace();
  677.   }
  678. }
  679.  
  680. void npr(char *fmt, ...)
  681. /* just like printf, only out to the com port */
  682. {
  683.   va_list ap;
  684.   char s[512];
  685.  
  686.   va_start(ap, fmt);
  687.   vsprintf(s, fmt, ap);
  688.   va_end(ap);
  689.   outstr(s);
  690. }
  691.  
  692.  
  693. void pl(char *s)
  694. {
  695.   outstr(s);
  696.   nl();
  697. }
  698.  
  699.  
  700. int kbhitb()
  701. {
  702.   union REGS r;
  703.  
  704.   r.h.ah = 1;
  705.   int86(0x16, &r, &r);
  706.   return((r.x.flags & 64) == 0);
  707. }
  708.  
  709.  
  710. int empty()
  711. {
  712.   if (kbhitb() || (incom && (head != tail)) ||
  713.       (charbufferpointer && charbuffer[charbufferpointer]) ||
  714.       (in_extern == 2))
  715.     return(0);
  716.   return(1);
  717. }
  718.  
  719.  
  720.  
  721. void skey1(char *ch)
  722. {
  723.   char c;
  724.  
  725.   c = *ch;
  726.   if (c == 127)
  727.     c = 8;
  728.   if (okskey)
  729.     switch(c) {
  730.       case 1:
  731.       case 4:
  732.       case 6:
  733.         if (okmacro && !charbufferpointer) {
  734.           if (c == 1)
  735.             c = 2;
  736.           else if (c == 4)
  737.             c = 0;
  738.           else if (c == 6)
  739.             c = 1;
  740.           strcpy(charbuffer, &(thisuser.macros[c][0]));
  741.           c = charbuffer[0];
  742.           if (c)
  743.             charbufferpointer = 1;
  744.         }
  745.         break;
  746.       case 15:
  747.         if (helpl && !ihelp && !chatting && echo) {
  748.           ihelp = 1;
  749.           print_help(helpl);
  750.           ihelp = 0;
  751.         }
  752.         break;
  753.       case 20:
  754.         if (echo)
  755.           ptime();
  756.         break;
  757.       case 18:
  758.         if (echo)
  759.           reprint();
  760.         break;
  761.     }
  762.   *ch = c;
  763. }
  764.  
  765. char getchd()
  766. {
  767.   union REGS r;
  768.  
  769.   r.h.ah = 0x07;
  770.   int86(INT_SAVE_21, &r, &r);
  771.   return(r.h.al);
  772. }
  773.  
  774.  
  775. char getchd1()
  776. {
  777.   union REGS r;
  778.  
  779.   r.h.ah = 0x06;
  780.   r.h.dl = 0xFF;
  781.   int86(INT_SAVE_21, &r, &r);
  782.   return((r.x.flags & 0x40) ? 255 : r.h.al);
  783. }
  784.  
  785.  
  786. char inkey()
  787. /* This function checks both the local keyboard, and the remote terminal
  788.  * (if any) for input.  If there is input, the key is returned.  If there
  789.  * is no input, a zero is returned.  Function keys hit are interpreted as
  790.  * such within the routine and not returned.
  791.  */
  792. {
  793.   char ch=0;
  794.  
  795.   if (charbufferpointer) {
  796.     if (!charbuffer[charbufferpointer])
  797.       charbufferpointer = charbuffer[0] = 0;
  798.     else
  799.       return(charbuffer[charbufferpointer++]);
  800.   }
  801.   if (kbhitb() || (in_extern == 2)) {
  802.     ch = getchd1();
  803.     lastcon = 1;
  804.     if (!ch) {
  805.       if (in_extern)
  806.         in_extern = 2;
  807.       else {
  808.         ch = getchd1();
  809.         skey(ch);
  810.         ch = (((ch == 68) || (ch==103)) ? 2 : 0);
  811.       }
  812.     } else if (in_extern)
  813.       in_extern = 1;
  814.     timelastchar1=timer1();
  815.   } else if (incom && comhit()) {
  816.     ch = (get1c() & andwith);
  817.     lastcon = 0;
  818.   }
  819.   skey1(&ch);
  820.   return(ch);
  821. }
  822.  
  823.  
  824.  
  825. void mpl(int i)
  826. /* This will make a reverse-video prompt line i characters long, repositioning
  827.  * the cursor at the beginning of the input prompt area.  Of course, if the
  828.  * user does not want ansi, this routine does nothing.
  829.  */
  830. {
  831.   int i1;
  832.   char s[81];
  833.  
  834.   if (okansi()) {
  835.     ansic(4);
  836.     for (i1 = 0; i1 < i; i1++)
  837.       outchr(' ');
  838.     outstr("\x1b[");
  839.     itoa(i,s,10);
  840.     outstr(s);
  841.     outstr("D");
  842.   }
  843. }
  844.  
  845.  
  846.  
  847. char upcase(char ch)
  848. /* This converts a character to uppercase */
  849. {
  850.   if ((ch > '`') && (ch < '{'))
  851.     ch = ch - 32;
  852.   return(ch);
  853. }
  854.  
  855.  
  856. unsigned char getkey()
  857. /* This function returns one character from either the local keyboard or
  858.  * remote com port (if applicable).  After 1.5 minutes of inactivity, a
  859.  * beep is sounded.  After 3 minutes of inactivity, the user is hung up.
  860.  */
  861. {
  862.   unsigned char ch;
  863.   int beepyet;
  864.   long dd,tv,tv1;
  865.  
  866.   beepyet = 0;
  867.   timelastchar1=timer1();
  868.  
  869.   if (so())
  870.     tv=10920L;
  871.   else
  872.     tv=3276L;
  873.  
  874.   tv1=tv/2;
  875.  
  876.   lines_listed = 0;
  877.   do {
  878.     while (empty() && !hangup) {
  879.       dd = timer1();
  880.       if (labs(dd - timelastchar1) > 65536L)
  881.         timelastchar1 -= 1572480L;
  882.       if (((dd - timelastchar1) > tv1) && (!beepyet)) {
  883.         beepyet = 1;
  884.         outchr(7);
  885.       }
  886.       if (labs(dd - timelastchar1) > tv) {
  887.         nl();
  888.     outstr("3Oops! Looks like you waited too long!");
  889.     nl();
  890.     hangup = 1;
  891.       }
  892.       checkhangup();
  893.     }
  894.     ch = inkey();
  895.   } while (!ch && !in_extern && !hangup);
  896.   if (checkit && (ch > 127)) {
  897.     checkit = 0;
  898.     ch = ch & (andwith = 0x7F);
  899.   }
  900.   return(ch);
  901. }
  902.  
  903.  
  904.  
  905. void input1(char *s, int maxlen, int lc, int crend)
  906. /* This will input a line of data, maximum maxlen characters long, terminated
  907.  * by a C/R.  if (lc) is non-zero, lowercase is allowed, otherwise all
  908.  * characters are converted to uppercase.
  909.  */
  910. {
  911.   int curpos=0, done=0, in_ansi=0;
  912.   unsigned char ch;
  913.  
  914.   while (!done && !hangup) {
  915.     ch = getkey();
  916.     if (in_ansi) {
  917.       if ((in_ansi==1) && (ch!='['))
  918.         in_ansi=0;
  919.       else {
  920.         if (in_ansi==1)
  921.           in_ansi=2;
  922.         else if (((ch<'0') || (ch>'9')) && (ch!=';'))
  923.           in_ansi=3;
  924.         else
  925.           in_ansi=2;
  926.       }
  927.     }
  928.     if (!in_ansi) {
  929.       if (ch > 31) {
  930.         if (curpos < maxlen) {
  931.           if (!lc)
  932.             ch = upcase(ch);
  933.           s[curpos++] = ch;
  934.           outchr(ch);
  935.         }
  936.       } else
  937.         switch(ch) {
  938.           case 14:
  939.           case 13:
  940.             s[curpos] = 0;
  941.             done = echo = 1;
  942.             if (crend)
  943.               nl();
  944.             break;
  945.           case 23: /* Ctrl-W */
  946.             if (curpos) {
  947.               do {
  948.                 curpos--;
  949.                 backspace();
  950.                 if (s[curpos]==26)
  951.                   backspace();
  952.               } while ((curpos) && (s[curpos-1]!=32));
  953.             }
  954.             break;
  955.           case 26:
  956.             if (input_extern) {
  957.               s[curpos++] = 26;
  958.               outstr("^Z");
  959.             }
  960.             break;
  961.           case 8:
  962.             if (curpos) {
  963.               curpos--;
  964.               backspace();
  965.               if (s[curpos] == 26)
  966.                 backspace();
  967.             }
  968.             break;
  969.           case 21:
  970.           case 24:
  971.             while (curpos) {
  972.               curpos--;
  973.               backspace();
  974.               if (s[curpos] == 26)
  975.                 backspace();
  976.             }
  977.             break;
  978.           case 27:
  979.             in_ansi=1;
  980.             break;
  981.         }
  982.     }
  983.     if (in_ansi==3)
  984.       in_ansi=0;
  985.   }
  986.   if (hangup)
  987.     s[0] = 0;
  988. }
  989.  
  990.  
  991.  
  992. void input(char *s, int len)
  993. /* This will input an upper-case string */
  994. {
  995.   input1(s, len, 0, 1);
  996. }
  997.  
  998.  
  999.  
  1000. void inputl(char *s, int len)
  1001. /* This will input an upper or lowercase string of characters */
  1002. {
  1003.   input1(s, len, 1, 1);
  1004. }
  1005.  
  1006.  
  1007.  
  1008. int yn()
  1009. /* The keyboard is checked for either a Y, N, or C/R to be hit.  C/R is
  1010.  * assumed to be the same as a N.  Yes or No is output, and yn is set to
  1011.  * zero if No was returned, and yn() is non-zero if Y was hit.
  1012.  */
  1013. {
  1014.   char ch=0;
  1015.  
  1016.   ansic(1);
  1017.   while (!hangup && ((ch = upcase(getkey())) != 'Y') && (ch != 'N') && (ch != 13))
  1018.     ;
  1019.   outstr((ch == 'Y') ? "1Y2e3p5p7ecr1s2!" : "1N2o3p5p7ecr1s2!");
  1020.   nl();
  1021.   return(ch == 'Y');
  1022. }
  1023.  
  1024.  
  1025.  
  1026. int ny()
  1027. /* This is the same as yn(), except C/R is assumed to be "Y" */
  1028. {
  1029.   char ch=0;
  1030.  
  1031.   ansic(1);
  1032.   while (!hangup && ((ch = upcase(getkey())) != 'Y') && (ch != 'N') && (ch != 13))
  1033.     ;
  1034.   outstr((ch == 'N') ? "1N2o3p5p7ecr1s2!" : "1Y2e3p5p7ecr1s2!");
  1035.   nl();
  1036.   return((ch == 'Y') || (ch==13));
  1037. }
  1038.  
  1039.  
  1040. void ansic(int n)
  1041. {
  1042.   char s[81], c;
  1043.  
  1044.   if ((n>=0) && (n<=7))
  1045.     c = ((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[n] :
  1046.     thisuser.bwcolors[n]);
  1047.   if ((n>=8) && (n<=16))
  1048.     c = ((thisuser.sysstatus & sysstatus_color) ? status.resx[n-8] :
  1049.     thisuser.bwcolors[n-8]);
  1050.   if (c == curatr)
  1051.     return;
  1052.   makeansi(c, s, 1);
  1053.   outstr(s);
  1054.   makeansi((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[0] :
  1055.     thisuser.bwcolors[0],endofline,1);
  1056. }
  1057.  
  1058.  
  1059. char onek(char *s)
  1060. {
  1061.   char ch;
  1062.  
  1063.   while (!strchr(s, ch = upcase(getkey())) && !hangup)
  1064.     ;
  1065.   if (hangup)
  1066.     ch = s[0];
  1067.   outchr(ch);
  1068.   nl();
  1069.   return(ch);
  1070. }
  1071.  
  1072.  
  1073. void prt(int i, char *s)
  1074. {
  1075.   ansic(i);
  1076.   outstr(s);
  1077.   ansic(0);
  1078. }
  1079.