home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / UTIL / WWIVE / MYWIVE.ZIP / COM.C < prev    next >
Text File  |  1993-09-18  |  26KB  |  1,143 lines

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