home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / W / DEVBBS.ZIP / COM.C < prev    next >
Text File  |  1992-08-15  |  26KB  |  1,126 lines

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