home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / WWIV2.ZIP / COM.C < prev    next >
C/C++ Source or Header  |  1995-07-31  |  24KB  |  1,172 lines

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