home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / W / WWIVSOR.ZIP / COM.C < prev    next >
C/C++ Source or Header  |  1995-05-20  |  42KB  |  1,780 lines

  1. /*****************************************************************************
  2.  
  3.                 WWIV Version 4
  4.                     Copyright (C) 1988-1995 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15. #include "vars.h"
  16.  
  17. #pragma hdrstop
  18.  
  19. #include "ripint.h"
  20. #include <stdarg.h>
  21. #include <math.h>
  22. #include <ctype.h>
  23. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  24. #include <conio.h>
  25. #endif
  26. #ifdef __OS2__
  27. #include "portio.h"
  28. #else
  29. #ifdef RIPDRIVE
  30. //#define rd_on() (ripdrive && (sysinfo.flags & OP_FLAGS_RIPDRIVE_ON))
  31.  char kbuf[768], *kb = NULL;
  32.  char lastkey;
  33. #endif
  34. #endif
  35.  
  36. #define frequency 500
  37.  
  38. #define UPPER_CASE  0
  39. #define MIXED_CASE  1
  40. #define PROPER_CASE 2
  41. #define FILE_NAME   3
  42.  
  43. /****************************************************************************/
  44.  
  45. #ifndef __OS2__
  46. int check_comport(int pn)
  47. {
  48.   unsigned char new_iir, old_iir;
  49.  
  50.   old_iir = inportb(syscfgovr.com_base[pn]+2);
  51.   outportb(syscfgovr.com_base[pn]+2,0x81);
  52.   new_iir = inportb(syscfgovr.com_base[pn]+2);
  53.   outportb(syscfgovr.com_base[pn]+2,old_iir);
  54.  
  55.   if (new_iir & 0x38) {
  56.     /* no com port */
  57.     return(0);
  58.   }
  59.  
  60.   if (new_iir==0) {
  61.     /* unbuffered */
  62.     return(1);
  63.   }
  64.  
  65.   outportb(syscfgovr.com_base[pn]+2,0xc1);
  66.   new_iir = inportb(syscfgovr.com_base[pn]+2);
  67.   outportb(syscfgovr.com_base[pn]+2,old_iir);
  68.  
  69.   switch ((new_iir >> 6) & 0x03) {
  70.     case 0: /* no 16550 */
  71.     case 1: /* huh? */
  72.       return(1);
  73.  
  74.     case 2: /* 16550 */
  75.     case 3: /* 16550A */
  76.       return(2);
  77.   }
  78.  
  79.   return(1);
  80. }
  81. #endif
  82.  
  83. /****************************************************************************/
  84.  
  85. void savel(char *cl, char *atr, char *xl, char *cc)
  86. {
  87.   int i, i1;
  88.  
  89.   *cc = curatr;
  90.   strcpy(xl, endofline);
  91. #ifdef __OS2__
  92.   { /* add in these extra braces to define more local vars */
  93.     char buf[1024];
  94.     USHORT CurX, CurY, BufLen = sizeof(buf);
  95.  
  96.     VioGetCurPos(&CurY, &CurX, 0);
  97.     VioReadCellStr(buf, &BufLen, CurY, 0, 0);
  98.     i = 0;
  99.     for (i1 = 0; i1 < WhereX(); i1++) {
  100.       cl[i1] = buf[i1 * 2];
  101.       atr[i1] = buf[(i1 * 2) + 1];
  102.     }
  103.   }
  104. #else
  105.   i = ((WhereY() + topline) * 80) * 2;
  106.   for (i1 = 0; i1 < WhereX(); i1++) {
  107.     cl[i1]  = scrn[i + (i1 * 2)];
  108.     atr[i1] = scrn[i + (i1 * 2) + 1];
  109.   }
  110. #endif
  111.   cl[WhereX()]  = 0;
  112.   atr[WhereX()] = 0;
  113. }
  114.  
  115. /****************************************************************************/
  116.  
  117. void restorel(char *cl, char *atr, char *xl, char *cc)
  118. {
  119.   int i;
  120.  
  121.   if (WhereX())
  122.     nl();
  123.   for (i = 0; cl[i] != 0; i++) {
  124.     setc(atr[i]);
  125.     outchr(cl[i]);
  126.   }
  127.   setc(*cc);
  128.   strcpy(endofline, xl);
  129. }
  130.  
  131. /****************************************************************************/
  132.  
  133. void ptime(void)
  134. {
  135.   char xl[81], cl[81], atr[81], cc, s[81];
  136.   long l;
  137.  
  138.   savel(cl, atr, xl, &cc);
  139.  
  140.   ansic(0);
  141.   nln(2);
  142.   time(&l);
  143.   strcpy(s, ctime(&l));
  144.   s[strlen(s) - 1] = 0;
  145.   pl(s);
  146.   if (useron && !in_extern) {
  147.     outstr(get_string(29)); npr("%s\r\n", ctim(timer() - timeon));
  148.     outstr(get_string(921)); npr("%s\r\n", ctim(nsl()));
  149.   }
  150.   nl();
  151.  
  152.   restorel(cl, atr, xl, &cc);
  153. }
  154.  
  155. /****************************************************************************/
  156.  
  157. void reprint(void)
  158. {
  159.   char xl[81], cl[81], atr[81], cc, ansistr_1[81];
  160.   int ansiptr_1;
  161.  
  162.   ansiptr_1=ansiptr;
  163.   ansiptr=0;
  164.   ansistr[ansiptr_1]=0;
  165.   strcpy(ansistr_1,ansistr);
  166.  
  167.   savel(cl, atr, xl, &cc);
  168.   nl();
  169.   restorel(cl, atr, xl, &cc);
  170.  
  171.   strcpy(ansistr,ansistr_1);
  172.   ansiptr=ansiptr_1;
  173. }
  174.  
  175. /****************************************************************************/
  176.  
  177. void print_help(int n)
  178. {
  179.   char xl[81], cl[81], atr[81], cc, s[81], ch;
  180.   int next, ot;
  181.  
  182.   if (menu_on() && (helpl == 1)) {
  183.     printmenu(340);
  184.     do {
  185.       ch=getkey();
  186.     } while ((ch = getkey()) != '\r' && ch != '\n' && (hangup == 0));
  187.     cleared = WASCLEARED;
  188.   }
  189.  
  190.   if (rip_on())
  191.     comstr("\x1|1\x1b""0000$COFF$$SAVE0$$SMF$\r");
  192.   sprintf(s,"%sHELP.MSG",languagedir);
  193.   next = 0;
  194.  
  195.   if (helps[n].stored_as) {
  196.     ot=tagging; tagging=0;
  197.     savel(cl, atr, xl, &cc);
  198.     ansic(0);
  199.     outstr("\f");
  200.  
  201.     read_message1(&helps[n], 0, 0, &next, s);
  202.     if (rip_on()) {
  203.       pausescr();
  204.       comstr("\x1|1\x1b""0000$RESTORE0$$RMF$$CON$\r");
  205. /*    if (menu_on())
  206.       if (rip_pause)
  207.         printmenu(334);
  208.       else
  209.         rip_cls();
  210. */
  211.     }
  212.  
  213.     if ((ot) && !(thisuser.sysstatus & sysstatus_no_tag)) {
  214.       pausescr();
  215.       relist();
  216.     }
  217.     restorel(cl, atr, xl, &cc);
  218.     tagging=ot;
  219.   }
  220. }
  221.  
  222. /****************************************************************************/
  223.  
  224. #ifdef __OS2__
  225. #define inportb inp
  226. #define outportb outp
  227. #endif
  228.  
  229. void setbeep(int i)
  230. {
  231.   int i1,i2;
  232.  
  233.   if (i) {
  234.     i1 = 0x34DD / frequency;
  235.     i2 = inportb(0x61);
  236.     if (!(i2 & 0x03)) {
  237.       outportb(0x61, i2 | 0x03);
  238.       outportb(0x43, 0xB6);
  239.     }
  240.     outportb(0x42, i1 & 0x0F);
  241.     outportb(0x42, i1 >> 4);
  242.   } else
  243.     outportb(0x61, inportb(0x61) & 0xFC);
  244. }
  245.  
  246. /****************************************************************************/
  247.  
  248. void far interrupt async_isr(void)
  249. /* This function is called every time a char is received on the com port.
  250.  * The character is stored in the buffer[] array, and the head pointer is
  251.  * updated.
  252.  */
  253. {
  254. #ifndef __OS2__
  255.   buffer[head++] = inportb(base);
  256.   if (head == MAX_BUF)
  257.     head = 0;
  258.   ISR_RESET(async_irq);
  259. #endif
  260. }
  261.  
  262. /****************************************************************************/
  263.  
  264. #ifndef __OS2__
  265. void outcomch(char ch)
  266. /* This function outputs one character to the com port */
  267. {
  268.   if (base) {
  269.     while (!(inportb(base + 5) & 0x20))
  270.       ;
  271.     if (flow_control)
  272.       while (!(inportb(base + 6) & 0x10))
  273.         ;
  274.     outportb(base, ch);
  275.   }
  276. }
  277. #endif
  278.  
  279. /****************************************************************************/
  280.  
  281. char peek1c(void)
  282. {
  283.   if (head!=tail) {
  284.     return(buffer[tail]);
  285.   } else
  286.     return(0);
  287. }
  288.  
  289. /****************************************************************************/
  290.  
  291. char get1c(void)
  292. /* This function returns one character from the com port, or a zero if
  293.  * no character is waiting
  294.  */
  295. {
  296.   char c1;
  297.  
  298.   if (head != tail) {
  299. #ifndef __OS2__
  300.     disable();
  301. #endif
  302.     c1 = buffer[tail++];
  303.     if (tail == MAX_BUF)
  304.       tail = 0;
  305. #ifndef __OS2__
  306.     enable();
  307. #endif
  308.     return(c1);
  309.   } else
  310.     return(0);
  311. }
  312.  
  313. /****************************************************************************/
  314.  
  315. int comhit(void)
  316. /* This returns a value telling if there is a character waiting in the com
  317.  * buffer.
  318.  */
  319. {
  320.   return(head != tail);
  321. }
  322.  
  323. /****************************************************************************/
  324.  
  325. void dump(void)
  326. /* This function clears the com buffer */
  327. {
  328. #ifndef __OS2__
  329.   disable();
  330. #endif
  331.   head = tail = 0;
  332. #ifndef __OS2__
  333.   enable();
  334. #endif
  335. }
  336.  
  337. /****************************************************************************/
  338.  
  339. #ifndef __OS2__
  340.  
  341. /****************************************************************************/
  342.  
  343. void set_baud(unsigned int rate)
  344. /* This function sets the com speed to that passed */
  345. {
  346.   float rl;
  347.  
  348.   if ((((rate > 49) && (rate < 57601)) || (rate==1)) && base) {
  349.     if ((rate==1) || (rate==49664)) /* 49664 = 115200 % 65536 */
  350.       rl = 1;
  351.     else
  352.       rl = 115200.0 / ((float) rate);
  353.     rate = (int) rl;
  354.     outportb(base + 3, inportb(base + 3) | 0x80);
  355.     outportb(base,     (rate & 0x00FF));
  356.     outportb(base + 1, ((rate >> 8) & 0x00FF));
  357.     outportb(base + 3, inportb(base + 3) & 0x7F);
  358.   }
  359. }
  360.  
  361. /****************************************************************************/
  362.  
  363. void initport(int port_num)
  364. /* This function initializes the com buffer, setting up the interrupt,
  365.  * and com parameters
  366.  */
  367. {
  368.   int temp;
  369.  
  370.   base = syscfgovr.com_base[port_num];
  371.   async_irq = syscfgovr.com_ISR[port_num];
  372.   setvect(ISR_VECT(async_irq), async_isr);
  373.   head = tail = 0;
  374.   outportb(base + 3, 0x03);
  375.   disable();
  376.   temp = inportb(base + 5);
  377.   temp = inportb(base);
  378.  
  379.   temp = inportb(ISR_CTRLR(async_irq));
  380.   temp = temp & ((1 << (async_irq%8)) ^ 0x00FF);
  381.   outportb(ISR_CTRLR(async_irq), temp);
  382.   outportb(base + 1, 0x01);
  383.   temp=inportb(base + 4);
  384.   outportb(base + 4, temp | 0x0A);
  385.   outportb(base+2,0x40);
  386.   enable();
  387.   dtr(1);
  388. }
  389.  
  390. /****************************************************************************/
  391.  
  392. void closeport(void)
  393. /* This function closes out the com port, removing the interrupt routine,
  394.  * etc.
  395.  */
  396. {
  397.   int temp;
  398.  
  399.   if (base) {
  400.     disable();
  401.     temp = inportb(ISR_CTRLR(async_irq));
  402.     temp = temp | ((1 << (async_irq%8)));
  403.     outportb(ISR_CTRLR(async_irq), temp);
  404.     outportb(base + 2, 0);
  405.     outportb(base + 4, 3);
  406.     setvect(ISR_VECT(async_irq),getvect(8)); /* for desqview */
  407.     enable();
  408.     base=0;
  409.   }
  410. }
  411.  
  412. /****************************************************************************/
  413.  
  414. void dtr(int i)
  415. /* This function sets the DTR pin to the status given */
  416. {
  417.   int i1;
  418.  
  419.   if (base) {
  420.     i1 = inportb(base + 4) & 0x00FE;
  421.     outportb(base + 4, (i || no_hangup) ? (i1 + 1) : i1);
  422.   }
  423. }
  424.  
  425. /****************************************************************************/
  426.  
  427. void rts(int i)
  428. /* This function sets the RTS pin to the status given */
  429. {
  430.   int i1;
  431.  
  432.   if (base) {
  433.     i1 = inportb(base + 4) & 0x00FD;
  434.     outportb(base + 4, (i) ? (i1 + 2) : i1);
  435.   }
  436. }
  437.  
  438. /****************************************************************************/
  439.  
  440. int cdet(void)
  441. /* This returns the status of the carrier detect lead from the modem */
  442. {
  443.   if (base)
  444.     return((inportb(base + 6) & 0x80) ? 1 : 0);
  445.   else
  446.     return(0);
  447. }
  448.  
  449. /****************************************************************************/
  450. #endif
  451. /****************************************************************************/
  452.  
  453. void checkhangup(void)
  454. /* This function checks to see if the user logged on to the com port has
  455.  * hung up.  Obviously, if no user is logged on remotely, this does nothing.
  456.  * If carrier detect is detected to be low, it is checked 100 times
  457.  * sequentially to make sure it stays down, and is not just a quirk.
  458.  */
  459. {
  460.   int i, ok;
  461.  
  462.   if (!hangup && using_modem && !cdet()) {
  463.     ok = 0;
  464.     for (i = 0; (i < 500) && !ok; i++)
  465.       if (cdet())
  466.         ok = 1;
  467.     if (!ok) {
  468.       hangup = hungup = 1;
  469.       if (useron && !in_extern)
  470.         sysoplog(get_stringx(1,99));
  471.     }
  472.   }
  473. }
  474.  
  475. /****************************************************************************/
  476.  
  477. void addto(char *s, int i)
  478. {
  479.   char temp[20];
  480.  
  481.   if (s[0])
  482.     strcat(s, ";");
  483.   else
  484.     strcpy(s, "\x1b[");
  485.   itoa(i, temp, 10);
  486.   strcat(s, temp);
  487. }
  488.  
  489. /****************************************************************************/
  490.  
  491. void makeansi(unsigned char attr, char *s, int forceit)
  492. /* Passed to this function is a one-byte attribute as defined for IBM type
  493.  * screens.  Returned is a string which, when printed, will change the
  494.  * display to the color desired, from the current function.
  495.  */
  496. {
  497.   unsigned char catr;
  498.   char *temp = "04261537";
  499.  
  500.   catr = curatr;
  501.   s[0] = 0;
  502.   if (attr != catr) {
  503.     if ((catr & 0x88) ^ (attr & 0x88)) {
  504.       addto(s, 0);
  505.       addto(s, 30 + temp[attr & 0x07] - '0');
  506.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  507.       catr = attr & 0x77;
  508.     }
  509.     if ((catr & 0x07) != (attr & 0x07))
  510.       addto(s, 30 + temp[attr & 0x07] - '0');
  511.     if ((catr & 0x70) != (attr & 0x70))
  512.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  513.     if ((catr & 0x08) ^ (attr & 0x08))
  514.       addto(s, 1);
  515.     if ((catr & 0x80) ^ (attr & 0x80)) {
  516.       if (checkcomp("Mac"))     /*This is the code for Mac's underline*/
  517.         addto(s, 4);            /*They don't have Blinking or Italics*/
  518.       else {
  519.         if (checkcomp("Ami"))   /*Some Amiga terminals use 3 instead of*/
  520.           addto(s, 3);          /*5 for italics.  Using both won't hurt*/
  521.         addto(s, 5);            /*anything, only italics will be generated*/
  522.       }
  523.     }
  524.   }
  525.   if (s[0])
  526.     strcat(s, "m");
  527.   if (!okansi() && !forceit)
  528.     s[0]=0;
  529. }
  530.  
  531. /****************************************************************************/
  532.  
  533. void setfgc(int i)
  534. /* This sets the foreground color to that passed.  It is called only from
  535.  * execute_ansi
  536.  */
  537. {
  538.   curatr = (curatr & 0xf8) | i;
  539. }
  540.  
  541. /****************************************************************************/
  542.  
  543. void setbgc(int i)
  544. /* This sets the background color to that passed.  It is called only from
  545.  * execute_ansi
  546.  */
  547. {
  548.   curatr = (curatr & 0x8f) | (i << 4);
  549. }
  550.  
  551. /****************************************************************************/
  552.  
  553. void execute_ansi(void)
  554. /* This function executes an ANSI string to change color, position the
  555.  * cursor, etc.
  556.  */
  557. {
  558.   int args[11],argptr,count,ptr,tempptr,ox,oy;
  559.   char cmd,temp[11],*clrlst="04261537";
  560.  
  561.   if (ansistr[1] != '[') {
  562.  
  563.     /* do nothing if invalid ANSI string. */
  564.  
  565.   } else {
  566.     argptr = tempptr = 0;
  567.     ptr = 2;
  568.     for (count = 0; count < 10; count++)
  569.       args[count] = temp[count] = 0;
  570.     cmd = ansistr[ansiptr - 1];
  571.     ansistr[ansiptr - 1] = 0;
  572.     while ((ansistr[ptr]) && (argptr<10) && (tempptr<10)) {
  573.       if (ansistr[ptr] == ';') {
  574.         temp[tempptr] = 0;
  575.         tempptr = 0;
  576.         args[argptr++] = atoi(temp);
  577.       } else
  578.         temp[tempptr++] = ansistr[ptr];
  579.       ++ptr;
  580.     }
  581.     if (tempptr && (argptr<10)) {
  582.       temp[tempptr]  = 0;
  583.       args[argptr++] = atoi(temp);
  584.     }
  585.     if ((cmd >= 'A') && (cmd <= 'D') && !args[0])
  586.       args[0] = 1;
  587.     switch (cmd) {
  588.         case 'f':
  589.         case 'H':
  590.           movecsr(args[1] - 1, args[0] - 1);
  591.           break;
  592.         case 'A':
  593.           movecsr(WhereX(), WhereY() - args[0]);
  594.           break;
  595.         case 'B':
  596.           movecsr(WhereX(), WhereY() + args[0]);
  597.           break;
  598.         case 'C':
  599.           movecsr(WhereX() + args[0], WhereY());
  600.           break;
  601.         case 'D':
  602.           movecsr(WhereX() - args[0], WhereY());
  603.           break;
  604.         case 's':
  605.           oldx = WhereX();
  606.           oldy = WhereY();
  607.           break;
  608.         case 'u':
  609.           movecsr(oldx, oldy);
  610.           break;
  611.         case 'J':
  612.           if (args[0] == 2) {
  613.             if (x_only)
  614.               movecsr(0,0);
  615.             else
  616.               clrscrb();
  617.           }
  618.           break;
  619.         case 'k':
  620.         case 'K':
  621.           if (!x_only) {
  622. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  623.           char EOLBuffer[160];
  624.           int Temp;
  625.  
  626.           for (Temp = 0; Temp < sizeof(EOLBuffer); Temp++)
  627.             if (Temp % 2)
  628.               EOLBuffer[Temp] = (char) curatr;
  629.             else
  630.               EOLBuffer[Temp] = ' ';
  631.           puttext(wherex(), wherey(), 80, wherey(), (void *)&EOLBuffer);
  632. #else
  633.             ox = WhereX();
  634.             oy = WhereY();
  635.             _CX = 80 - ox;
  636.             _AH = 0x09;
  637.             _BH = 0x00;
  638.             _AL = 32;
  639.             _BL = curatr;
  640.             my_video_int();
  641.             movecsr(ox, oy);
  642. #endif
  643.           }
  644.           break;
  645.         case 'm':
  646.           if (!argptr) {
  647.             argptr = 1;
  648.             args[0] = 0;
  649.           }
  650.           for (count = 0; count < argptr; count++)
  651.             switch (args[count]) {
  652.               case 0: curatr = 0x07; break;
  653.               case 1: curatr = curatr | 0x08; break;
  654.               case 4: break;
  655.               case 5: curatr = curatr | 0x80; break;
  656.               case 7:
  657.                 ptr = curatr & 0x77;
  658.                 curatr = (curatr & 0x88) | (ptr << 4) | (ptr >> 4);
  659.                 break;
  660.               case 8: curatr = 0; break;
  661.               default:
  662.                 if ((args[count] >= 30) && (args[count] <= 37))
  663.                   setfgc(clrlst[args[count] - 30] - '0');
  664.                 else if ((args[count] >= 40) && (args[count] <= 47))
  665.                   setbgc(clrlst[args[count] - 40] - '0');
  666.             }
  667.           break;
  668.       }
  669.     }
  670.   ansiptr = 0;
  671. }
  672.  
  673. /****************************************************************************/
  674.  
  675. void outchr(unsigned char c)
  676. /* This function outputs one character to the screen, and if output to the
  677.  * com port is enabled, the character is output there too.  ANSI graphics
  678.  * are also trapped here, and the ansi function is called to execute the
  679.  * ANSI codes
  680.  */
  681. {
  682.   int i, i1, nc;
  683.   char cc[20];
  684.   static char pipe_color[3];
  685.  
  686.   if (change_color==5) {
  687.     change_color=0;
  688.     outstr((char *)interpret(c));
  689.     return;
  690.   } if (change_color==4) {
  691.     if (c==15)
  692.       change_color=5;
  693.     else
  694.       change_color=0;
  695.     return;
  696.   } else if (change_color==3) {
  697.     change_color=0;
  698.     pipe_color[1]=c;
  699.     pipe_color[2]=0;
  700.  
  701.     if (isdigit(pipe_color[0])) {
  702.       if (isdigit(pipe_color[1]) || (pipe_color[1]==' ')) {
  703.         nc=atoi(pipe_color);
  704.       } else {
  705.         change_color=-1;
  706.       }
  707.     } else if ((pipe_color[0]==' ') && isdigit(pipe_color[1])) {
  708.       nc=atoi(pipe_color+1);
  709.     } else if ((pipe_color[0]=='b') || (pipe_color[0]=='B')) {
  710.       nc=16+atoi(pipe_color+1);
  711.     } else {
  712.       change_color=-1;
  713.     }
  714.     if (nc>=32)
  715.       change_color=-1;
  716.  
  717.  
  718.     if (change_color==-1) {
  719.       outchr('|');
  720.       outstr(pipe_color);
  721.     } else {
  722.       if (nc<16) {
  723.         makeansi((curatr&0xf0)|nc, cc, 0);
  724.         /* buildfor(nc, cc); */
  725.       } else {
  726.         makeansi((curatr&0x0f)|(nc<<4), cc, 0);
  727.         /* buildback(nc, cc); */
  728.       }
  729.       outstr(cc);
  730.     }
  731.     return;
  732.   } else if (change_color==2) {
  733.     pipe_color[0]=c;
  734.     ++change_color;
  735.     return;
  736.   } else if (change_color==1) {
  737.     change_color = 0;
  738.     if ((c >= '0') && (c <= '9'))
  739.       ansic(c - '0');
  740.     return;
  741.   }
  742.  
  743.   if (c == 3) {
  744.     change_color = 1;
  745.     return;
  746.   } else if (c==15) {
  747.     change_color=4;
  748.     return;
  749.   } else if ((c=='|') && (g_flags & g_flag_pipe_colors) && (change_color!=-1)) {
  750.     change_color = 2;
  751.     return;
  752.   } else if ((c == 10) && endofline[0]) {
  753.     if (!in_extern)
  754.       outstr(endofline);
  755.     endofline[0] = 0;
  756.   } else if (change_color==-1) {
  757.     change_color=0;
  758.   }
  759.  
  760.   if (global_handle) {
  761.     if (echo)
  762.       global_char(c);
  763.   }
  764.  
  765.   if (!(sysinfo.flags & OP_FLAGS_NEW_CHATSOUND)) {
  766.     if (chatcall && !x_only && !(syscfg.sysconfig & sysconfig_no_beep))
  767.       setbeep(1);
  768.   }
  769.  
  770.   if (outcom && !x_only && (c != 9)) {
  771.     if (!(!okansi() && (ansiptr || c==27)))
  772.       outcomch(echo ? c : 'X');
  773.   }
  774.   if (ansiptr) {
  775.     ansistr[ansiptr++] = c;
  776.     ansistr[ansiptr]   = 0;
  777.     if ((((c < '0') || (c > '9')) && (c!='[') && (c!=';')) ||
  778.         (ansistr[1] != '[') || (ansiptr>75))
  779.       execute_ansi();
  780.   } else if (c == 27) {
  781.     ansistr[0] = 27;
  782.     ansiptr = 1;
  783.     ansistr[ansiptr]=0;
  784.   } else {
  785.     if (c == 9) {
  786.       i1 = WhereX();
  787.       for (i = i1; i< (((i1 / 8) + 1) * 8); i++)
  788.         outchr(32);
  789.     } else if (echo || lecho) {
  790.       out1ch(c);
  791.       if (c == 10) {
  792.         ++lines_listed;
  793.         if (lines_listed >= screenlinest - 3) {
  794.           if(!in_extern) {
  795.             if ((tagging) && !(thisuser.sysstatus & sysstatus_no_tag) &&
  796.                 filelist && !chatting) {
  797.               if(num_listed!=0)
  798.                 tag_files();
  799.               lines_listed = 0;
  800.             }
  801.           }
  802.         }
  803.         if (lines_listed >= screenlinest - 1) {
  804.           if (sysstatus_pause_on_page & thisuser.sysstatus)
  805.             if (!x_only)
  806.               pausescr();
  807.           lines_listed = 0;
  808.         }
  809.       }
  810.     } else
  811.       out1ch('X');
  812.   }
  813.   if (chatcall)
  814.     setbeep(0);
  815. }
  816.  
  817. /****************************************************************************/
  818.  
  819. void outstr(unsigned char *s)
  820. /* This function outputs a string of characters to the screen (and remotely
  821.  * if applicable).  The com port is also checked first to see if a remote
  822.  * user has hung up
  823.  */
  824. {
  825.   int i=0;
  826.  
  827.   checkhangup();
  828.   if (!hangup)
  829.     while (s[i])
  830.       outchr(s[i++]);
  831. }
  832.  
  833. /****************************************************************************/
  834.  
  835. void nl(void)
  836. /* This function performs a CR/LF sequence to move the cursor to the next
  837.  * line.  If any end-of-line ANSI codes are set (such as changing back to
  838.  * the default color) are specified, those are executed first.
  839.  */
  840. {
  841.   if (endofline[0]) {
  842.     outstr(endofline);
  843.     endofline[0] = 0;
  844.   }
  845.   if (ripcode)
  846.     comstr("\r");
  847.   else
  848.     outstr("\r\n");
  849.   if (inst_msg_waiting())
  850.     process_inst_msgs();
  851. }
  852.  
  853. /****************************************************************************/
  854.  
  855. void nln(int n)
  856. {
  857.   int i;
  858.  
  859.   for (i=0; i<n; i++) {
  860.     nl();
  861.   }
  862. }
  863.  
  864. /****************************************************************************/
  865.  
  866. void backspace(void)
  867. /* This function executes a backspace, space, backspace sequence. */
  868. {
  869.   int i;
  870.  
  871.   i = echo;
  872.   echo = 1;
  873.   outstr("\b \b");
  874.   echo = i;
  875. }
  876.  
  877. /****************************************************************************/
  878.  
  879. void setc(unsigned char ch)
  880. /* This sets the current color (both locally and remotely) to that
  881.  * specified (in IBM format).
  882.  */
  883. {
  884.   char s[30];
  885.  
  886.   makeansi(ch, s, 0);
  887.   outstr(s);
  888. }
  889.  
  890. /****************************************************************************/
  891.  
  892. void pausescr(void)
  893. /* This will pause output, displaying the [PAUSE] message, and wait for
  894.  * a key to be hit.
  895.  */
  896. {
  897.   int i,i1,i2,oiia;
  898.   char *ss;
  899.  
  900.   if (x_only)
  901.     return;
  902.  
  903.   oiia=iia;
  904.   setiia(0);
  905.  
  906.   ss=str_pause;
  907.   i2=i1=strlen(ss);
  908.   for (i=0; i<i2; i++)
  909.     if ((ss[i]==3) && (i1>1))
  910.       i1-=2;
  911.  
  912.   if (okansi()) {
  913.     i = curatr;
  914.     setc((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[3] :
  915.           thisuser.bwcolors[3]);
  916.     outstr(ss);
  917.     npr("\x1b[%dD",i1);
  918.     setc(i);
  919.     if (in_extern)
  920.       getkey();
  921.     else
  922.       getkeymouse();
  923.     for (i=0; i<i1; i++)
  924.       outchr(' ');
  925.     npr("\x1b[%dD",i1);
  926.   } else {
  927.     outstr(ss);
  928.     if (in_extern)
  929.       getkey();
  930.     else
  931.       getkeymouse();
  932.     for (i = 0; i<i1; i++)
  933.       backspace();
  934.   }
  935.  
  936.   setiia(oiia);
  937. }
  938.  
  939. /****************************************************************************/
  940.  
  941. void npr(char *fmt, ...)
  942. /* just like printf, only out to the com port */
  943. {
  944.   va_list ap;
  945.   char s[512];
  946.  
  947.   va_start(ap, fmt);
  948.   vsprintf(s, fmt, ap);
  949.   va_end(ap);
  950.   outstr(s);
  951. }
  952.  
  953. /****************************************************************************/
  954.  
  955. void pl(char *s)
  956. {
  957.   outstr(s);
  958.   nl();
  959. }
  960.  
  961. /****************************************************************************/
  962.  
  963. void pln(int n)
  964. {
  965.   char s[81];
  966.  
  967.   sprintf(s,"%u",n);
  968.   pl(s);
  969. }
  970.  
  971. /****************************************************************************/
  972.  
  973. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  974. /*
  975.  * Define this to get around the bug where Borland's kbhit()
  976.  * will return false if user pressed an extended key AND
  977.  * WWIV has already read in the '0' that indicates an
  978.  * extended key.
  979.  */
  980. static int ExtendedKeyWaiting = 0;
  981. #endif
  982.  
  983. int kbhitb(void)
  984. {
  985. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  986.   return (x_only ? 0 : (kbhit() || ExtendedKeyWaiting));
  987. #else
  988.   union REGS r;
  989.  
  990.   if (x_only)
  991.     return(0);
  992.  
  993.   r.h.ah = 1;
  994.   int86(0x16, &r, &r);
  995. #ifdef RIPDRIVE
  996.   if (rd_on()) {
  997.     if (*kb == 0 || kb == NULL) {
  998.       *kbuf = 0;
  999.       kb = kbuf;
  1000.     }
  1001.     localrip_keyfilter(0, kbuf);
  1002.     if ((*kb != 0)) {
  1003.       return (*kb);
  1004.     }
  1005.   }
  1006. #endif
  1007.   return((r.x.flags & 64) == 0);
  1008. #endif
  1009. }
  1010.  
  1011. /****************************************************************************/
  1012.  
  1013. int empty(void)
  1014. {
  1015.   if (x_only)
  1016.     return(1);
  1017.  
  1018.   if (kbhitb() || (incom && (head != tail)) ||
  1019.       (charbufferpointer && charbuffer[charbufferpointer]) ||
  1020.       (in_extern == 2))
  1021.     return(0);
  1022.   return(1);
  1023. }
  1024.  
  1025. /****************************************************************************/
  1026.  
  1027. void skey1(unsigned char *ch)
  1028. {
  1029.   unsigned char c;
  1030.  
  1031.   c = *ch;
  1032.   if ((c == 127) && (!in_fsed))
  1033.     c = 8;
  1034.   if (okskey)
  1035.     switch(c) {
  1036.       case 1:
  1037.       case 4:
  1038.       case 6:
  1039.         if (okmacro && !charbufferpointer) {
  1040.           if (c == 1)
  1041.             c = 2;
  1042.           else if (c == 4)
  1043.             c = 0;
  1044.           else if (c == 6)
  1045.             c = 1;
  1046.           strcpy(charbuffer, &(thisuser.macros[c][0]));
  1047.           c = charbuffer[0];
  1048.           if (c)
  1049.             charbufferpointer = 1;
  1050.         }
  1051.         break;
  1052.       case 15:
  1053.         if (helpl && !ihelp && !chatting && echo) {
  1054.           if (menu_on())
  1055.              cleared = -1;
  1056.           ihelp = 1;
  1057.           print_help(helpl);
  1058.           ihelp = 0;
  1059.         }
  1060.         break;
  1061.       case submenu_code:
  1062.         if (rip_on()) {
  1063.           if (end_submenu)
  1064.             submenu();
  1065.           else
  1066.             end_submenu = -1;
  1067.         }
  1068.         break;
  1069.       case 5:
  1070.         if (rip_on())
  1071.           hypertext();
  1072.         break;
  1073.       case 20:
  1074.         if (echo)
  1075.           ptime();
  1076.         if (menu_on() && rip_pause) {
  1077.           pausescr();
  1078.         }
  1079.         break;
  1080.       case 18:
  1081.         if (echo)
  1082.           reprint();
  1083.         break;
  1084.       case 25:
  1085.         thisuser.sysstatus ^= sysstatus_pause_on_page;
  1086.         break;
  1087.     }
  1088.   *ch = c;
  1089. }
  1090.  
  1091. /****************************************************************************/
  1092. /*
  1093.  * returns the ASCII code of the next character waiting in the
  1094.  * keyboard buffer.  If there are no characters waiting in the
  1095.  * keyboard buffer, then it waits for one.
  1096.  *
  1097.  * A value of 0 is returned for all extended keys (such as F1,
  1098.  * Alt-X, etc.).  The function must be called again upon receiving
  1099.  * a value of 0 to obtain the value of the extended key pressed.
  1100.  */
  1101. unsigned char getchd(void)
  1102. {
  1103. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  1104.   unsigned char rc;
  1105.  
  1106.   if (ExtendedKeyWaiting)
  1107.     {
  1108.       ExtendedKeyWaiting = 0;
  1109.       return (unsigned char) getch();
  1110.     }
  1111.   rc = getch();
  1112.   if (rc == 0)
  1113.     ExtendedKeyWaiting = 1;
  1114.   return rc;
  1115. #else
  1116.   union REGS r;
  1117. #ifdef RIPDRIVE
  1118.   if ((kb == NULL) || (*kb == 0) || (rd_on() == 0)) {
  1119. #endif
  1120.  
  1121.     r.h.ah = 0x07;
  1122.     int86(save_dos, &r, &r);
  1123.   
  1124. #ifdef RIPDRIVE
  1125.     if (rd_on()) {
  1126.       lastkey = r.h.al;
  1127.       if (*kb == 0) {
  1128.         *kbuf = 0;
  1129.       }
  1130.       if (lastkey) {         // We don't want to process extd. keys
  1131.         localrip_keyfilter(r.h.al, kbuf);
  1132.         kb = kbuf;
  1133.       }
  1134.     }
  1135.   }
  1136.   if (rd_on() && (kb != NULL) && (*kb != 0)) {
  1137.     return (*(kb++));
  1138.   }
  1139. #endif
  1140.   return(r.h.al);
  1141. #endif
  1142. }
  1143.  
  1144. /****************************************************************************/
  1145. /*
  1146.  * returns the ASCII code of the next character waiting in the
  1147.  * keyboard buffer.  If there are no characters waiting in the
  1148.  * keyboard buffer, then it returns immediately with a value
  1149.  * of 255.
  1150.  *
  1151.  * A value of 0 is returned for all extended keys (such as F1,
  1152.  * Alt-X, etc.).  The function must be called again upon receiving
  1153.  * a value of 0 to obtain the value of the extended key pressed.
  1154.  */
  1155. unsigned char getchd1(void)
  1156. {
  1157. #if defined(BC_FAST_VIDEO) || defined(__OS2__)
  1158.   unsigned char rc;
  1159.  
  1160.   if (!((kbhit()) || ExtendedKeyWaiting))
  1161.     return 255;
  1162.   if (ExtendedKeyWaiting)
  1163.     {
  1164.       ExtendedKeyWaiting = 0;
  1165.       return (unsigned char) getch();
  1166.     }
  1167.   rc = getch();
  1168.   if (rc == 0)
  1169.     ExtendedKeyWaiting = 1;
  1170.   return rc;
  1171. #else
  1172.   union REGS r;
  1173. #ifdef RIPDRIVE
  1174.   static char last;
  1175.   int ky;
  1176.   if ((kb == NULL) || (*kb == 0) || (rd_on() == 0)) {
  1177. #endif
  1178.  
  1179.     r.h.ah = 0x06;
  1180.     r.h.dl = 0xFF;
  1181.     int86(save_dos, &r, &r);
  1182.     
  1183. #ifdef RIPDRIVE
  1184.     if (rd_on()) {
  1185.       if ((r.x.flags & 0x40) == 0) {
  1186.         ky = r.h.al;
  1187.         last = (char) ky;
  1188.        } else {
  1189.          ky = 0;
  1190.          last = 255;
  1191.        }
  1192.        if (*kb == 0) {
  1193.          *kbuf = 0;
  1194.        }
  1195.        if (last) {         // We don't want to process extd. keys
  1196.          localrip_keyfilter(ky, kbuf);
  1197.          kb = kbuf;
  1198.        }
  1199.     }
  1200.   }
  1201.   if (rd_on() && (kb != NULL) && (*kb != 0)) {
  1202.     return (*(kb++));
  1203.   }
  1204. #endif
  1205.          
  1206.   return((r.x.flags & 0x40) ? 255 : r.h.al);
  1207. #endif
  1208. }
  1209.  
  1210. /****************************************************************************/
  1211.  
  1212. unsigned char inkey(void)
  1213. /* This function checks both the local keyboard, and the remote terminal
  1214.  * (if any) for input.  If there is input, the key is returned.  If there
  1215.  * is no input, a zero is returned.  Function keys hit are interpreted as
  1216.  * such within the routine and not returned.
  1217.  */
  1218. {
  1219.   unsigned char ch=0;
  1220.  
  1221.   if (x_only)
  1222.     return(0);
  1223.  
  1224.   if (charbufferpointer) {
  1225.     if (!charbuffer[charbufferpointer]) {
  1226.       charbufferpointer = charbuffer[0] = 0;
  1227.     } else {
  1228.       if ((charbuffer[charbufferpointer])==3)
  1229.         charbuffer[charbufferpointer]=16;
  1230.       return(charbuffer[charbufferpointer++]);
  1231.     }
  1232.   }
  1233.   if (kbhitb() || (in_extern == 2)) {
  1234.     ch = getchd1();
  1235.     lastcon = 1;
  1236.     if (!(g_flags & g_flag_allow_extended)) {
  1237.       if (!ch) {
  1238.         if (in_extern)
  1239.           in_extern = 2;
  1240.         else {
  1241.           ch = getchd1();
  1242.           skey(ch);
  1243.           ch = (((ch == 68) || (ch==103)) ? 2 : 0);
  1244.         }
  1245.       } else if (in_extern)
  1246.         in_extern = 1;
  1247.     }
  1248.     timelastchar1=timer1();
  1249.   } else if (incom && comhit()) {
  1250.     ch = (get1c() & andwith);
  1251.     lastcon = 0;
  1252.   }
  1253.   if (!(g_flags & g_flag_allow_extended))
  1254.     skey1(&ch);
  1255.  
  1256.   return(ch);
  1257. }
  1258.  
  1259. /****************************************************************************/
  1260.  
  1261. void mpl(int i)
  1262. /* This will make a reverse-video prompt line i characters long, repositioning
  1263.  * the cursor at the beginning of the input prompt area.  Of course, if the
  1264.  * user does not want ansi, this routine does nothing.
  1265.  */
  1266. {
  1267.   int i1;
  1268.   char s[81];
  1269.  
  1270.   if (okansi()) {
  1271.     ansic(4);
  1272.     for (i1 = 0; i1 < i; i1++)
  1273.       outchr(' ');
  1274.     outstr("\x1b[");
  1275.     itoa(i,s,10);
  1276.     outstr(s);
  1277.     outstr("D");
  1278.   }
  1279. }
  1280.  
  1281. /****************************************************************************/
  1282.  
  1283. unsigned char upcase(unsigned char ch)
  1284. /* This converts a character to uppercase */
  1285. {
  1286.   unsigned char *ss;
  1287.  
  1288.   ss=strchr(translate_letters[0],ch);
  1289.   if (ss)
  1290.     ch=translate_letters[1][ss-translate_letters[0]];
  1291.   return(ch);
  1292. }
  1293.  
  1294. /****************************************************************************/
  1295.  
  1296. unsigned char locase(unsigned char ch)
  1297. /* This converts a character to lowercase */
  1298. {
  1299.   unsigned char *ss;
  1300.  
  1301.   ss=strchr(translate_letters[1],ch);
  1302.   if (ss)
  1303.     ch=translate_letters[0][ss-translate_letters[1]];
  1304.   return(ch);
  1305. }
  1306.  
  1307. /****************************************************************************/
  1308.  
  1309. unsigned char getkey(void)
  1310. /* This function returns one character from either the local keyboard or
  1311.  * remote com port (if applicable).  After 1.5 minutes of inactivity, a
  1312.  * beep is sounded.  After 3 minutes of inactivity, the user is hung up.
  1313.  */
  1314. {
  1315.   unsigned char ch;
  1316.   int beepyet;
  1317.   long dd,tv,tv1;
  1318.  
  1319.   beepyet = 0;
  1320.   timelastchar1=timer1();
  1321.  
  1322.   if (so())
  1323.     tv=10920L;
  1324.   else
  1325.     tv=3276L;
  1326.  
  1327.   tv1=tv/2;
  1328.  
  1329.   if (!tagging || (thisuser.sysstatus & sysstatus_no_tag))
  1330.     lines_listed = 0;
  1331.   do {
  1332.     while (empty() && !hangup) {
  1333.       /* if (!in_extern) */
  1334.         giveup_timeslice();
  1335.       dd = timer1();
  1336.       if ((dd<timelastchar1) && ((dd+1000)>timelastchar1))
  1337.         timelastchar1=dd;
  1338.       if (labs(dd - timelastchar1) > 65536L)
  1339.         timelastchar1 -= 1572480L;
  1340.       if (((dd - timelastchar1) > tv1) && (!beepyet)) {
  1341.         beepyet = 1;
  1342.         outchr(7);
  1343.       }
  1344.       if (labs(dd - timelastchar1) > tv) {
  1345.         nl();
  1346.         if (!in_extern)
  1347.           outstr(get_string(924));
  1348.         nl();
  1349.         hangup = 1;
  1350.       }
  1351.       checkhangup();
  1352.     }
  1353.     ch = inkey();
  1354.   } while (!ch && !in_extern && !hangup);
  1355.   if (checkit && (ch > 127)) {
  1356.     checkit = 0;
  1357.     ch = ch & (andwith = 0x7F);
  1358.   }
  1359.   return(ch);
  1360. }
  1361.  
  1362. /****************************************************************************/
  1363.  
  1364. void input1(unsigned char *s, int maxlen, int lc, int crend)
  1365. /* This will input a line of data, maximum maxlen characters long, terminated
  1366.  * by a C/R.  if (lc) is non-zero, lowercase is allowed, otherwise all
  1367.  * characters are converted to uppercase.
  1368.  */
  1369. {
  1370.   int curpos=0,done=0,in_ansi=0;
  1371.   unsigned char ch,*ss;
  1372.  
  1373.   while (!done && !hangup) {
  1374.     ch = getkey();
  1375.     if (in_ansi) {
  1376.       if ((in_ansi==1) && (ch!='['))
  1377.         in_ansi=0;
  1378.       else {
  1379.         if (in_ansi==1)
  1380.           in_ansi=2;
  1381.         else if (((ch<'0') || (ch>'9')) && (ch!=';'))
  1382.           in_ansi=3;
  1383.         else
  1384.           in_ansi=2;
  1385.       }
  1386.     }
  1387.     if (!in_ansi) {
  1388.       if (ch > 31) {
  1389.         switch (lc) {
  1390.           case UPPER_CASE:
  1391.             ch=upcase(ch);
  1392.             break;
  1393.           case MIXED_CASE:
  1394.             break;
  1395.           case PROPER_CASE:
  1396.             ch=upcase(ch);
  1397.             if (curpos) {
  1398.               ss=strchr(valid_letters,s[curpos-1]);
  1399.               if ((ss!=NULL) || (s[curpos-1]==39)) {
  1400.                 if ((curpos<2) || (s[curpos-2]!=77) || (s[curpos-1]!=99))
  1401.                   ch=locase(ch);
  1402.               }
  1403.             }
  1404.             break;
  1405.           case FILE_NAME:
  1406.             if (strchr("/\\+ <>|*?.,=\";:[]", ch))
  1407.               ch=0;
  1408.             else
  1409.               ch=upcase(ch);
  1410.             break;
  1411.         }
  1412.         if ((curpos<maxlen) && ch) {
  1413.           s[curpos++] = ch;
  1414.           outchr(ch);
  1415.         }
  1416.       } else
  1417.         switch(ch) {
  1418.           case 14:
  1419.           case 13:
  1420.             s[curpos] = 0;
  1421.             done = echo = 1;
  1422.             if (crend)
  1423.               nl();
  1424.             break;
  1425.           case 23: /* Ctrl-W */
  1426.             if (curpos) {
  1427.               do {
  1428.                 curpos--;
  1429.                 backspace();
  1430.                 if (s[curpos]==26)
  1431.                   backspace();
  1432.               } while ((curpos) && (s[curpos-1]!=32));
  1433.             }
  1434.             break;
  1435.           case 26:
  1436.             if (input_extern) {
  1437.               s[curpos++] = 26;
  1438.               outstr("^Z");
  1439.             }
  1440.             break;
  1441.           case 8:
  1442.             if (curpos) {
  1443.               curpos--;
  1444.               backspace();
  1445.               if (s[curpos] == 26)
  1446.                 backspace();
  1447.             }
  1448.             break;
  1449.           case 21:
  1450.           case 24:
  1451.             while (curpos) {
  1452.               curpos--;
  1453.               backspace();
  1454.               if (s[curpos] == 26)
  1455.                 backspace();
  1456.             }
  1457.             break;
  1458.           case 27:
  1459.             in_ansi=1;
  1460.             break;
  1461.         }
  1462.     }
  1463.     if (in_ansi==3)
  1464.       in_ansi=0;
  1465.   }
  1466.   if (hangup)
  1467.     s[0] = 0;
  1468. }
  1469.  
  1470. /****************************************************************************/
  1471.  
  1472. void input(unsigned char *s, int len)
  1473. /* This will input an upper-case string */
  1474. {
  1475.   input1(s, len, UPPER_CASE, 1);
  1476. }
  1477.  
  1478. /****************************************************************************/
  1479.  
  1480. void inputl(unsigned char *s, int len)
  1481. /* This will input an upper or lowercase string of characters */
  1482. {
  1483.   input1(s, len, MIXED_CASE, 1);
  1484. }
  1485.  
  1486. /****************************************************************************/
  1487.  
  1488. void inputp(unsigned char *s, int len)
  1489. /* This will input an upper or lowercase string of characters */
  1490. {
  1491.   input1(s, len, PROPER_CASE, 1);
  1492. }
  1493.  
  1494. /****************************************************************************/
  1495.  
  1496. void inputf(unsigned char *s, int len)
  1497. /* This will input an uppercase string of characters, suitable for a fielname */
  1498. {
  1499.   input1(s, len, FILE_NAME, 1);
  1500. }
  1501.  
  1502. /****************************************************************************/
  1503.  
  1504. static void print_yn(int i)
  1505. {
  1506.   if (num_strings(i))
  1507.     pl(getrandomstring(i));
  1508.   else switch(i) {
  1509.     case 2: pl(str_yes); break;
  1510.     case 3: pl(str_no); break;
  1511.   }
  1512. }
  1513.  
  1514. /****************************************************************************/
  1515.  
  1516. int yn(void)
  1517. /* The keyboard is checked for either a Y, N, or C/R to be hit.  C/R is
  1518.  * assumed to be the same as a N.  Yes or No is output, and yn is set to
  1519.  * zero if No was returned, and yn() is non-zero if Y was hit.
  1520.  */
  1521. {
  1522.   char ch=0;
  1523.  
  1524.   ansic(1);
  1525.   if (menu_on() && rip_popup && (!rip_subset)) {
  1526.     outstr("s\r");
  1527.     printmenu(330);
  1528.   }
  1529.   while ((!hangup) &&
  1530.          ((ch = upcase(getkey())) != *str_yes) &&
  1531.          (ch != *str_no) &&
  1532.          (ch != 13))
  1533.     ;
  1534.   if (menu_on() && rip_popup && (!rip_subset)) {
  1535.     printmenu(335);
  1536.     outstr("u");
  1537.   }
  1538.   if (ch==*str_yes)
  1539.     print_yn(2);
  1540.   else
  1541.     print_yn(3);
  1542.   return(ch == *str_yes);
  1543. }
  1544.  
  1545. /****************************************************************************/
  1546.  
  1547. int ny(void)
  1548. /* This is the same as yn(), except C/R is assumed to be "Y" */
  1549. {
  1550.   char ch=0;
  1551.  
  1552.   ansic(1);
  1553.   if (menu_on() && rip_popup && (!rip_subset)) {
  1554.     outstr("s\r");
  1555.     printmenu(330);
  1556.   }
  1557.   while ((!hangup) &&
  1558.          ((ch = upcase(getkey())) != *str_yes) &&
  1559.          (ch != *str_no) &&
  1560.          (ch != 13))
  1561.     ;
  1562.   if (menu_on() && rip_popup && (!rip_subset)) {
  1563.     printmenu(335);
  1564.     outstr("u");
  1565.   }
  1566.   if (ch==*str_no)
  1567.     print_yn(3);
  1568.   else
  1569.     print_yn(2);
  1570.   return((ch == *str_yes) || (ch==13));
  1571. }
  1572.  
  1573. /****************************************************************************/
  1574.  
  1575. char ynq(void)
  1576. {
  1577.   char ch=0;
  1578.   ansic(1);
  1579.   if (menu_on() && rip_popup && (!rip_subset)) {
  1580.     outstr("s\r");
  1581.     printmenu(331);
  1582.   }
  1583.   while ((!hangup) &&
  1584.          ((ch = upcase(getkey())) != *str_yes) &&
  1585.          (ch != *str_no) &&
  1586.          (ch != *str_quit) &&
  1587.          (ch != 13))
  1588.     ;
  1589.   if (menu_on() && rip_popup && (!rip_subset)) {
  1590.     printmenu(335);
  1591.     outstr("u");
  1592.   }
  1593.   if (ch==*str_yes) {
  1594.     ch='Y';
  1595.     print_yn(2);
  1596.   } else if (ch==*str_quit) {
  1597.     ch='Q';
  1598.     pl(str_quit);
  1599.   } else {
  1600.     ch='N';
  1601.     print_yn(3);
  1602.   }
  1603.   return(ch);
  1604. }
  1605.  
  1606. /****************************************************************************/
  1607.  
  1608. void ansic(int n)
  1609. {
  1610.   char c;
  1611.  
  1612.   c = ((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[n] :
  1613.         thisuser.bwcolors[n]);
  1614.   if (c == curatr)
  1615.     return;
  1616.   setc(c);
  1617.   makeansi((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[0] :
  1618.         thisuser.bwcolors[0],endofline, 0);
  1619. }
  1620.  
  1621. /****************************************************************************/
  1622.  
  1623. void ansic_x(int n)
  1624. {
  1625.   if (E_C) {
  1626.     ansic(n);
  1627.   }
  1628. }
  1629.  
  1630. /****************************************************************************/
  1631.  
  1632. char onek(char *s)
  1633. {
  1634.   char ch;
  1635.  
  1636.   while (!strchr(s, ch = upcase(getkey())) && !hangup)
  1637.     ;
  1638.   if (hangup)
  1639.     ch = s[0];
  1640.   outchr(ch);
  1641.   nl();
  1642.   return(ch);
  1643. }
  1644.  
  1645. /****************************************************************************/
  1646.  
  1647. void prt(int i, char *s)
  1648. {
  1649.   ansic(i);
  1650.   outstr(s);
  1651.   ansic(0);
  1652. }
  1653.  
  1654. /****************************************************************************/
  1655.  
  1656. void reset_colors(void)
  1657. {
  1658.   outstr("\x1b[0m");
  1659. }
  1660.  
  1661. /****************************************************************************/
  1662.  
  1663. void goxy(int x, int y)
  1664. {
  1665.   if (okansi())
  1666.     npr("\x1b[%d;%dH",y,x);
  1667. }
  1668.  
  1669. /****************************************************************************/
  1670.  
  1671. unsigned char *charstr(int len, unsigned char rc)
  1672. /* Returns string comprised of char rc, len characters in length */
  1673. {
  1674.   static unsigned char s[161];
  1675.  
  1676.   if ((rc==0) || (len<1))
  1677.     return("");
  1678.  
  1679.   if (len>160)
  1680.     len=160;
  1681.  
  1682.   memset(s,rc,len);
  1683.   s[len]=0;
  1684.   return(s);
  1685. }
  1686.  
  1687. /****************************************************************************/
  1688.  
  1689. unsigned char *stripcolors(unsigned char *instr)
  1690. /* Takes input string and returns same string stripped of color codes. */
  1691. {
  1692.   static unsigned char s[161];
  1693.   int i,i1;
  1694.  
  1695.   if (strlen(instr)==0)
  1696.     return("");
  1697.  
  1698.   i=0; i1=0;
  1699.   do {
  1700.     if (instr[i]==3)
  1701.       i++;
  1702.     else {
  1703.       s[i1]=instr[i];
  1704.       i1++;
  1705.     }
  1706.     i++;
  1707.   } while (i<strlen(instr));
  1708.   s[i1]=0;
  1709.   return(s);
  1710. }
  1711.  
  1712. /****************************************************************************/
  1713.  
  1714. void trimstr(unsigned char *s)
  1715. {
  1716.   int i;
  1717.  
  1718.   i=strlen(s);
  1719.   while ((i>0) && (s[i-1]==32))
  1720.     --i;
  1721.   s[i]=0;
  1722. }
  1723.  
  1724. /****************************************************************************/
  1725.  
  1726. char onek1(char *s)
  1727. {
  1728.   char ch;
  1729.  
  1730.   while (!strchr(s, ch = upcase(getkey())) && !hangup)
  1731.     ;
  1732.   if (hangup)
  1733.     ch = s[0];
  1734.   return(ch);
  1735. }
  1736.  
  1737. /****************************************************************************/
  1738.  
  1739. #ifdef DEBUG_DEBUG
  1740. /* These two functions were added to aid in the resolution of missing
  1741.  * string characters.  They can be used in place of outstr and npr in
  1742.  * those places where string characters are lost.  Seems 18-20 are the
  1743.  * magic numbers.
  1744.  */
  1745.  
  1746. void outstr1(unsigned char *s)
  1747. /* This function outputs a string of characters to the screen (and remotely
  1748.  * if applicable).  The com port is also checked first to see if a remote
  1749.  * user has hung up
  1750.  */
  1751. {
  1752.   int i=0;
  1753.  
  1754.   printf("outstr=%d, ",strlen(s)); /* debug */
  1755.   checkhangup();
  1756.   if (!hangup)
  1757.     while (s[i])
  1758.       outchr(s[i++]);
  1759. }
  1760.  
  1761. /****************************************************************************/
  1762.  
  1763. void npr1(char *fmt, ...)
  1764. /* just like printf, only out to the com port */
  1765. {
  1766.   va_list ap;
  1767.   char s[512];
  1768.  
  1769.   printf("\r\nFMT=%d, ",strlen(fmt)); /* debug */
  1770.   va_start(ap, fmt);
  1771.   printf("s=%d, ",strlen(s)); /* debug */
  1772.   vsprintf(s, fmt, ap);
  1773.   printf("s=%d, ",strlen(s)); /* debug */
  1774.   va_end(ap);
  1775.   printf("s=%d, ",strlen(s)); /* debug */
  1776.   outstr1(s);
  1777. }
  1778. #endif
  1779.  
  1780.