home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / UTIL / WWIVSOR / RETURN.C < prev    next >
C/C++ Source or Header  |  1995-05-20  |  54KB  |  2,370 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.  
  16.  
  17. #include <process.h>
  18. #include <math.h>
  19. #include <dir.h>
  20. #include <stdio.h>
  21. #include <io.h>
  22. #include <fcntl.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <sys\stat.h>
  26. #include <dos.h>
  27. #include <alloc.h>
  28. #include <time.h>
  29.  
  30.  
  31. #include "vardec.h"
  32. #include "share.h"
  33.  
  34.  
  35. void far *funcs[25];
  36. /****************************************************************************/
  37. char *interpret(char c);
  38. void my_video_int(void);
  39. int okansi(void);
  40. void wait1(long l);
  41. void setbeep(int i);
  42. void pla(char *s, int *abort);
  43. void checka(int *abort, int *next);
  44. void inli(char *s, char *rollover, int maxlen, int crend);
  45. long timer1(void);
  46. void movecsr(int x,int y);
  47. int WhereX(void);
  48. int WhereY(void);
  49. void lf(void);
  50. void cr(void);
  51. void clrscrb(void);
  52. void bs(void);
  53. void out1chx(unsigned char ch);
  54. void out1ch(unsigned char ch);
  55. void far interrupt async_isr(void);
  56. void outcomch(char ch);
  57. char get1c(void);
  58. int comhit(void);
  59. void dump(void);
  60. void set_baud(unsigned int rate);
  61. void initport(int portnum);
  62. void closeport(void);
  63. int cdet(void);
  64. void checkhangup(void);
  65. void addto(char *s, int i);
  66. void makeansi(unsigned char attr, char *s, int forceit);
  67. void setfgc(int i);
  68. void setbgc(int i);
  69. void execute_ansi(void);
  70. void outchr(char c);
  71. void outstr(char *s);
  72. void nl(void);
  73. void backspace(void);
  74. void setc(unsigned char ch);
  75. void pausescr(void);
  76. void pl(char *s);
  77. int kbhitb(void);
  78. int empty(void);
  79. void skey1(char *ch);
  80. char getchd(void);
  81. char getchd1(void);
  82. char inkey(void);
  83. void mpl(int i);
  84. char upcase(char ch);
  85. unsigned char getkey(void);
  86. void input1(char *s, int maxlen, int lc, int crend);
  87. void input(char *s, int len);
  88. void inputl(char *s, int len);
  89. int yn(void);
  90. int ny(void);
  91. void ansic(int n);
  92. char onek(char *s);
  93. void prt(int i, char *s);
  94. unsigned char getkeyext(void);
  95. int do_it(char *cl);
  96. int do_remote(char *s, int ccc);
  97. void checka2(void);
  98. void outdosstr(char *s);
  99. int full_external(char *s, int ccc);
  100. int init_r(void);
  101. void get_dir(char *s, int be);
  102. void cd_to(char *s);
  103. void setup_stuff(void);
  104. void main(int argc, char *argv[]);
  105.  
  106. /****************************************************************************/
  107. char *xenviron[50],newprompt[161];
  108. char ver_no1[51], ver_no2[51];
  109.  
  110.  
  111. int topline=0,screenbottom=24,tempio,curatr=0x07,lines_listed=0,outcom=0;
  112. int hangup=0,hungup=0,echo=1,lecho=1,input_extern=0,ctc=0,ccc=0;
  113. int defscreenbottom=24,debuglevel=0,instance=1;
  114.  
  115. char charbuffer[161]="",endofline[81]="";
  116. int charbufferpointer=0;
  117. int ansiptr=0;
  118.  
  119. int oldx,oldy,flow_control,save_dos;
  120. char ansistr[81];
  121. int change_color;
  122. userrec thisuser;
  123.  
  124. unsigned int baud_rate;
  125.  
  126. long timelastchar1,hanguptime1;
  127.  
  128. unsigned char andwith=255;
  129.  
  130. char cdir[81];
  131.  
  132.  
  133. volatile int head,tail;
  134. volatile char buffer[MAX_BUF];
  135. int base,async_irq,useron,in_extern,ok_modem_stuff;
  136. int outcom,incom,using_modem,chatting,screenlinest;
  137.  
  138. extern char *wwiv_version;
  139.  
  140. #pragma warn -par
  141. void sysoplog(char *s) {}
  142. #pragma warn +par
  143.  
  144. /****************************************************************************/
  145.  
  146. void my_video_int(void)
  147. {
  148. #if __TURBOC__ >= 0x0200
  149.   /* TC 2.0 or TC++ here */
  150.   static unsigned short sav_bp;
  151.  
  152.   __emit__(0x56, 0x57); /* push si, push di */
  153.   sav_bp = _BP;
  154.   geninterrupt(0x10);
  155.   _BP = sav_bp;
  156.   __emit__(0x5f, 0x5e); /* pop di, pop si */
  157. #else
  158.   /* TC 1.5 here */
  159.   _VideoInt();
  160. #endif
  161. }
  162.  
  163.  
  164. /****************************************************************************/
  165.  
  166. int okansi(void)
  167. /* This function checks the status of the current user's record to see if
  168.  * the user has specified that he wants ANSI graphics displayed.
  169.  */
  170. {
  171.   if (thisuser.sysstatus & sysstatus_ansi)
  172.     return(1);
  173.   else
  174.     return(0);
  175. }
  176.  
  177. void giveup_timeslice(void) {}
  178.  
  179. void wait1(long l)
  180. {
  181.   long l1;
  182.  
  183.   l1 = timer1()+l;
  184.  
  185.   enable();
  186.   while (timer1()<l1)
  187.     ;
  188. }
  189.  
  190.  
  191.  
  192.  
  193. #define frequency 500
  194.  
  195. void setbeep(int i)
  196. {
  197.   int i1,i2;
  198.  
  199.   if (i) {
  200.     i1 = 0x34DD / frequency;
  201.     i2 = inportb(0x61);
  202.     if (!(i2 & 0x03)) {
  203.       outportb(0x61, i2 | 0x03);
  204.       outportb(0x43, 0xB6);
  205.     }
  206.     outportb(0x42, i1 & 0x0F);
  207.     outportb(0x42, i1 >> 4);
  208.   } else
  209.     outportb(0x61, inportb(0x61) & 0xFC);
  210. }
  211.  
  212. void pla(char *s, int *abort)
  213. {
  214.   int i,next;
  215.  
  216.   i=0;
  217.   checkhangup();
  218.   if (hangup)
  219.     *abort=1;
  220.   checka(abort,&next);
  221.   while ((s[i]) && (!(*abort))) {
  222.     outchr(s[i++]);
  223.     checka(abort,&next);
  224.   }
  225.   if (!(*abort))
  226.     nl();
  227. }
  228.  
  229.  
  230. void checka(int *abort, int *next)
  231. {
  232.   char ch;
  233.  
  234.   while ((!empty()) && (!(*abort)) && (!hangup)) {
  235.     checkhangup();
  236.     ch=inkey();
  237.     switch(ch) {
  238.       case 14:
  239.         *next=1;
  240.       case 3:
  241.       case 32:
  242.       case 24:
  243.         *abort=1;
  244.         break;
  245.       case 'P':
  246.       case 'p':
  247.       case 19:
  248.         ch=getkey();
  249.         break;
  250.     }
  251.   }
  252. }
  253.  
  254.  
  255. void inli(char *s, char *rollover, int maxlen, int crend)
  256. {
  257.   int cp,i,i1,done,cm,begx;
  258.   char s1[255];
  259.   unsigned char ch;
  260.  
  261.   cm=chatting;
  262.  
  263.   begx=WhereX();
  264.   if (rollover[0]!=0) {
  265.     if (charbufferpointer) {
  266.       strcpy(s1,rollover);
  267.       strcat(s1,&charbuffer[charbufferpointer]);
  268.       strcpy(&charbuffer[1],s1);
  269.       charbufferpointer=1;
  270.     } else {
  271.       strcpy(&charbuffer[1],rollover);
  272.       charbufferpointer=1;
  273.     }
  274.     rollover[0]=0;
  275.   }
  276.   cp=0;
  277.   done=0;
  278.   do {
  279.     ch=getkey();
  280.     if (cm)
  281.       if (chatting==0)
  282.         ch=13;
  283.     if ((ch>=32)) {
  284.       if ((WhereX()<(thisuser.screenchars-1)) && (cp<maxlen)) {
  285.         s[cp++]=ch;
  286.         outchr(ch);
  287.         if (WhereX()==(thisuser.screenchars-1))
  288.           done=1;
  289.       } else {
  290.         if (WhereX()>=(thisuser.screenchars-1))
  291.           done=1;
  292.       }
  293.     } else
  294.         switch(ch) {
  295.       case 7:
  296.         if ((chatting) && (outcom))
  297.           outcomch(7);
  298.         break;
  299.           case 13: /* C/R */
  300.             s[cp]=0;
  301.             done=1;
  302.             break;
  303.           case 8:  /* Backspace */
  304.             if (cp) {
  305.               if (s[cp-2]==3) {
  306.                 cp-=2;
  307.                 ansic(0);
  308.               } else if (s[cp-2]==15) {
  309.                 for (i=strlen(interpret(s[cp-1])); i>0; i++)
  310.                   backspace();
  311.                 cp-=2;
  312.                 if (s[cp-1]==15)
  313.                   cp--;
  314.               } else {
  315.                 if (s[cp-1]==8) {
  316.                   cp--;
  317.                   outchr(32);
  318.                 } else {
  319.                   cp--;
  320.                   backspace();
  321.                 }
  322.               }
  323.             }
  324.             break;
  325.           case 24: /* Ctrl-X */
  326.             while (WhereX()>begx) {
  327.               backspace();
  328.               cp=0;
  329.             }
  330.             ansic(0);
  331.             break;
  332.           case 23: /* Ctrl-W */
  333.             if (cp) {
  334.               do {
  335.                 if (s[cp-2]==3) {
  336.                   cp-=2;
  337.                   ansic(0);
  338.                 } else
  339.                   if (s[cp-1]==8) {
  340.                     cp--;
  341.                     outchr(32);
  342.                   } else {
  343.                     cp--;
  344.                     backspace();
  345.                   }
  346.               } while ((cp) && (s[cp-1]!=32) && (s[cp-1]!=8) && (s[cp-2]!=3));
  347.             }
  348.             break;
  349.           case 14: /* Ctrl-N */
  350.             if ((WhereX()) && (cp<maxlen)) {
  351.               outchr(8);
  352.               s[cp++]=8;
  353.             }
  354.             break;
  355.           case 16: /* Ctrl-P */
  356.             if (cp<maxlen-1) {
  357.               ch=getkey();
  358.               if ((ch>='0') && (ch<='9')) {
  359.                 s[cp++]=3;
  360.                 s[cp++]=ch;
  361.                 ansic(ch-'0');
  362.               } else if ((ch==16) && (cp<maxlen-2)) {
  363.                 ch=getkey();
  364.  
  365.                 if (ch != 16) {     // RIP font style code
  366.                   s[cp++]=15;
  367.                   s[cp++]=15;
  368.                   s[cp++]=ch;
  369.                   outchr('\xf');
  370.                   outchr('\xf');
  371.                   outchr(ch);
  372.                 }
  373.               }
  374.             }
  375.             break;
  376.           case 9:  /* Tab */
  377.             i=5-(cp % 5);
  378.             if (((cp+i)<maxlen) && ((WhereX()+i)<thisuser.screenchars)) {
  379.               i=5-((WhereX()+1) % 5);
  380.               for (i1=0; i1<i; i1++) {
  381.                 s[cp++]=32;
  382.                 outchr(32);
  383.               }
  384.             }
  385.             break;
  386.         }
  387.   } while ((done==0) && (hangup==0));
  388.   if (ch!=13) {
  389.     i=cp-1;
  390.     while ((i>0) && (s[i]!=32) && (s[i]!=8) || (s[i-1]==3))
  391.       i--;
  392.     if ((i>(WhereX()/2)) && (i!=(cp-1))) {
  393.       i1=cp-i-1;
  394.       for (i=0; i<i1; i++)
  395.         outchr(8);
  396.       for (i=0; i<i1; i++)
  397.         outchr(32);
  398.       for (i=0; i<i1; i++)
  399.         rollover[i]=s[cp-i1+i];
  400.       rollover[i1]=0;
  401.       cp -= i1;
  402.     }
  403.     s[cp++]=1;
  404.     s[cp]=0;
  405.   }
  406.   if (crend)
  407.     nl();
  408.  
  409. }
  410.  
  411. /****************************************************************************/
  412.  
  413. long timer1(void)
  414. /* This function returns the time, in seconds since midnight. */
  415. {
  416.   unsigned short h,m;
  417.   long l;
  418.  
  419.   m=peek(0x0040,0x006c);
  420.   h=peek(0x0040,0x006e);
  421.   l=((long)h)*65536 + ((long)m);
  422.   return(l);
  423. }
  424.  
  425. #define SCROLL_UP(t,b,l) \
  426.   _CH=t;\
  427.   _DH=b;\
  428.   _BH=curatr;\
  429.   _AL=l;\
  430.   _CL=0;\
  431.   _DL=79;\
  432.   _AH=6;\
  433.   my_video_int();
  434.  
  435. void movecsr(int x,int y)
  436. /* This, obviously, moves the cursor to the location specified, offset from
  437.  * the protected dispaly at the top of the screen
  438.  */
  439. {
  440.   if (x<0)
  441.     x=0;
  442.   if (x>79)
  443.     x=79;
  444.   if (y<0)
  445.     y=0;
  446.   y+=topline;
  447.   if (y>screenbottom)
  448.     y=screenbottom;
  449.  
  450.   _BH=0x00;
  451.   _DH=y;
  452.   _DL=x;
  453.   _AH=0x02;
  454.   my_video_int();
  455. }
  456.  
  457.  
  458.  
  459. int WhereX(void)
  460. /* This function returns the current X cursor position, as the number of
  461.  * characters from the left hand side of the screen.  An X position of zero
  462.  * means the cursor is at the left-most position
  463.  */
  464. {
  465.   _BH=0x00;
  466.   _AH=0x03;
  467.   my_video_int();
  468.   tempio=_DL;
  469.   return(tempio);
  470. }
  471.  
  472.  
  473.  
  474. int WhereY(void)
  475. /* This function returns the Y cursor position, as the line number from
  476.  * the top of the logical window.  The offset due to the protected top
  477.  * of the screen display is taken into account.  A WhereY() of zero means
  478.  * the cursor is at the top-most position it can be at.
  479.  */
  480. {
  481.   _BH=0x00;
  482.   _AH=0x03;
  483.   my_video_int();
  484.   tempio=_DH;
  485.   return(tempio-topline);
  486. }
  487.  
  488.  
  489.  
  490. void lf(void)
  491. /* This function performs a linefeed to the screen (but not remotely) by
  492.  * either moving the cursor down one line, or scrolling the logical screen
  493.  * up one line.
  494.  */
  495. {
  496.   _BH=0x00;
  497.   _AH=0x03;
  498.   my_video_int();
  499.   tempio=_DL;
  500.   if (_DH==screenbottom) {
  501.     SCROLL_UP(topline,screenbottom,1);
  502.     _DL=tempio;
  503.     _DH=screenbottom;
  504.     _BH=0;
  505.     _AH=0x02;
  506.     my_video_int();
  507.   } else {
  508.     tempio=_DH+1;
  509.     _DH=tempio;
  510.     _AH=0x02;
  511.     my_video_int();
  512.   }
  513. }
  514.  
  515.  
  516.  
  517. void cr(void)
  518. /* This short function returns the local cursor to the left-most position
  519.  * on the screen.
  520.  */
  521. {
  522.   _BH=0x00;
  523.   _AH=0x03;
  524.   my_video_int();
  525.   _DL=0x00;
  526.   _AH=2;
  527.   my_video_int();
  528. }
  529.  
  530. void clrscrb(void)
  531. /* This clears the local logical screen */
  532. {
  533.   SCROLL_UP(topline,screenbottom,0);
  534.   movecsr(0,0);
  535.   lines_listed=0;
  536. }
  537.  
  538.  
  539.  
  540. void bs(void)
  541. /* This function moves the cursor one position to the left, or if the cursor
  542.  * is currently at its left-most position, the cursor is moved to the end of
  543.  * the previous line, except if it is on the top line, in which case nothing
  544.  * happens.
  545.  */
  546. {
  547.   _BH=0;
  548.   _AH=3;
  549.   my_video_int();
  550.   if (_DL==0) {
  551.     if (_DH != topline) {
  552.       _DL=79;
  553.       tempio=_DH-1;
  554.       _DH=tempio;
  555.       _AH=2;
  556.       my_video_int();
  557.     }
  558.   } else {
  559.     _DL--;
  560.     _AH=2;
  561.     my_video_int();
  562.   }
  563. }
  564.  
  565.  
  566.  
  567. void out1chx(unsigned char ch)
  568. /* This function outputs one character to the screen, then updates the
  569.  * cursor position accordingly, scolling the screen if necessary.  Not that
  570.  * this function performs no commands such as a C/R or L/F.  If a value of
  571.  * 8, 7, 13, 10, 12 (backspace, beep, C/R, L/F, TOF), or any other command-
  572.  * type characters are passed, the appropriate corresponding "graphics"
  573.  * symbol will be output to the screen as a normal character.
  574.  */
  575. {
  576.   _BL=curatr;
  577.   _BH=0x00;
  578.   _CX=0x01;
  579.   _AL=ch;
  580.   _AH=0x09;
  581.   my_video_int();
  582.   _BH=0x00;
  583.   _AH=0x03;
  584.   my_video_int();
  585.   ++_DL;
  586.   if (_DL==80) {
  587.     _DL=0;
  588.     if (_DH==screenbottom) {
  589.       SCROLL_UP(topline,screenbottom,1);
  590.       _DH=screenbottom;
  591.       _DL=0;
  592.       _BH=0;
  593.       _AH=0x02;
  594.       my_video_int();
  595.     } else {
  596.       tempio=_DH+1;
  597.       _DH=tempio;
  598.       _AH=0x02;
  599.       my_video_int();
  600.     }
  601.   } else {
  602.     _AH=0x02;
  603.     my_video_int();
  604.   }
  605. }
  606.  
  607.  
  608.  
  609.  
  610. void out1ch(unsigned char ch)
  611. /* This function outputs one character to the local screen.  C/R, L/F, TOF,
  612.  * BS, and BELL are interpreted as commands instead of characters.
  613.  */
  614. {
  615.   if (ch>31)
  616.     out1chx(ch);
  617.   else
  618.     if (ch==13)
  619.       cr();
  620.     else
  621.       if (ch==10)
  622.         lf();
  623.       else
  624.         if (ch==12)
  625.           clrscrb();
  626.         else
  627.           if (ch==8)
  628.             bs();
  629.           else
  630.             if (ch==7)
  631.               if (outcom==0) {
  632.                 setbeep(1);
  633.                 wait1(4);
  634.                 setbeep(0);
  635.               }
  636. }
  637.  
  638.  
  639.  
  640. /****************************************************************************/
  641. void far interrupt async_isr(void)
  642. /* This function is called every time a char is received on the com port.
  643.  * The character is stored in the buffer[] array, and the head pointer is
  644.  * updated.
  645.  */
  646. {
  647.   buffer[head++] = inportb(base);
  648.   if (head == MAX_BUF)
  649.     head = 0;
  650.   ISR_RESET(async_irq);
  651. }
  652.  
  653.  
  654.  
  655. void outcomch(char ch)
  656. /* This function outputs one character to the com port */
  657. {
  658.   while (!(inportb(base + 5) & 0x20))
  659.     ;
  660.   if (flow_control)
  661.     while (!(inportb(base + 6) & 0x10))
  662.       ;
  663.   outportb(base, ch);
  664. }
  665.  
  666.  
  667.  
  668.  
  669. char get1c(void)
  670. /* This function returns one character from the com port, or a zero if
  671.  * no character is waiting
  672.  */
  673. {
  674.   char c1;
  675.  
  676.   if (head != tail) {
  677.     disable();
  678.     c1 = buffer[tail++];
  679.     if (tail == MAX_BUF)
  680.       tail = 0;
  681.     enable();
  682.     return(c1);
  683.   } else
  684.     return(0);
  685. }
  686.  
  687.  
  688.  
  689. int comhit(void)
  690. /* This returns a value telling if there is a character waiting in the com
  691.  * buffer.
  692.  */
  693. {
  694.   return(head != tail);
  695. }
  696.  
  697.  
  698.  
  699. void dump(void)
  700. /* This function clears the com buffer */
  701. {
  702.   disable();
  703.   head = tail = 0;
  704.   enable();
  705. }
  706.  
  707. void set_baud(unsigned int rate)
  708. /* This function sets the com speed to that passed */
  709. {
  710.   float rl;
  711.  
  712.   if ((((rate > 49) && (rate < 57601)) || (rate==1)) && base) {
  713.     if ((rate==1) || (rate==49664)) /* 49664 = 115200 % 65536 */
  714.       rl = 1;
  715.     else
  716.       rl = 115200.0 / ((float) rate);
  717.     rate = (int) rl;
  718.     outportb(base + 3, inportb(base + 3) | 0x80);
  719.     outportb(base,     (rate & 0x00FF));
  720.     outportb(base + 1, ((rate >> 8) & 0x00FF));
  721.     outportb(base + 3, inportb(base + 3) & 0x7F);
  722.   }
  723. }
  724.  
  725.  
  726. void initport(int port_num)
  727. /* This function initializes the com buffer, setting up the interrupt,
  728.  * and com parameters
  729.  */
  730. {
  731.   int temp;
  732.  
  733.   temp=port_num;
  734.  
  735.   setvect(ISR_VECT(async_irq), async_isr);
  736.   head = tail = 0;
  737.   outportb(base + 3, 0x03);
  738.   disable();
  739.   temp = inportb(base + 5);
  740.   temp = inportb(base);
  741.  
  742.   temp = inportb(ISR_CTRLR(async_irq));
  743.   temp = temp & ((1 << (async_irq%8)) ^ 0x00FF);
  744.   outportb(ISR_CTRLR(async_irq), temp);
  745.   outportb(base + 1, 0x01);
  746.   temp=inportb(base + 4);
  747.   outportb(base + 4, temp | 0x0B);
  748.   enable();
  749.   set_baud(baud_rate);
  750. }
  751.  
  752. /****************************************************************************/
  753.  
  754. void closeport(void)
  755. /* This function closes out the com port, removing the interrupt routine,
  756.  * etc.
  757.  */
  758. {
  759.   int temp;
  760.  
  761.   if (base) {
  762.     disable();
  763.     temp = inportb(ISR_CTRLR(async_irq));
  764.     temp = temp | ((1 << (async_irq%8)));
  765.     outportb(ISR_CTRLR(async_irq), temp);
  766.     outportb(base + 2, 0);
  767.     outportb(base + 4, 3);
  768.     setvect(ISR_VECT(async_irq),getvect(8)); /* for desqview */
  769.     enable();
  770.     base=0;
  771.   }
  772. }
  773.  
  774. int cdet(void)
  775. /* This returns the status of the carrier detect lead from the modem */
  776. {
  777.   return((inportb(base + 6) & 0x80) ? 1 : 0);
  778. }
  779.  
  780.  
  781.  
  782. void checkhangup(void)
  783. /* This function checks to see if the user logged on to the com port has
  784.  * hung up.  Obviously, if no user is logged on remotely, this does nothing.
  785.  * If carrier detect is detected to be low, it is checked 100 times
  786.  * sequentially to make sure it stays down, and is not just a quirk.
  787.  */
  788. {
  789.   int i, ok;
  790.  
  791.   if (!hangup && using_modem && !cdet()) {
  792.     ok = 0;
  793.     for (i = 0; (i < 500) && !ok; i++)
  794.       if (cdet())
  795.         ok = 1;
  796.     if (!ok) {
  797.       hangup = hungup = 1;
  798.     }
  799.   }
  800. }
  801.  
  802.  
  803.  
  804.  
  805. void addto(char *s, int i)
  806. {
  807.   char temp[20];
  808.  
  809.   if (s[0])
  810.     strcat(s, ";");
  811.   else
  812.     strcpy(s, "\x1B[");
  813.   itoa(i, temp, 10);
  814.   strcat(s, temp);
  815. }
  816.  
  817.  
  818.  
  819. void makeansi(unsigned char attr, char *s, int forceit)
  820. /* Passed to this function is a one-byte attribute as defined for IBM type
  821.  * screens.  Returned is a string which, when printed, will change the
  822.  * display to the color desired, from the current function.
  823.  */
  824. {
  825.   unsigned char catr;
  826.   char *temp = "04261537";
  827.  
  828.   catr = curatr;
  829.   s[0] = 0;
  830.   if (attr != catr) {
  831.     if ((catr & 0x88) ^ (attr & 0x88)) {
  832.       addto(s, 0);
  833.       addto(s, 30 + temp[attr & 0x07] - '0');
  834.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  835.       catr = attr & 0x77;
  836.     }
  837.     if ((catr & 0x07) != (attr & 0x07))
  838.       addto(s, 30 + temp[attr & 0x07] - '0');
  839.     if ((catr & 0x70) != (attr & 0x70))
  840.       addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
  841.     if ((catr & 0x08) ^ (attr & 0x08))
  842.       addto(s, 1);
  843.     if ((catr & 0x80) ^ (attr & 0x80))
  844.       addto(s, 5);
  845.   }
  846.   if (s[0])
  847.     strcat(s, "m");
  848.   if (!okansi() && !forceit)
  849.     s[0]=0;
  850. }
  851.  
  852.  
  853.  
  854. void setfgc(int i)
  855. /* This sets the foreground color to that passed.  It is called only from
  856.  * execute_ansi
  857.  */
  858. {
  859.   curatr = (curatr & 0xf8) | i;
  860. }
  861.  
  862.  
  863.  
  864. void setbgc(int i)
  865. /* This sets the background color to that passed.  It is called only from
  866.  * execute_ansi
  867.  */
  868. {
  869.   curatr = (curatr & 0x8f) | (i << 4);
  870. }
  871.  
  872.  
  873. void execute_ansi(void)
  874. /* This function executes an ANSI string to change color, position the
  875.  * cursor, etc.
  876.  */
  877. {
  878.   int args[10], argptr, count, ptr, tempptr, ox, oy;
  879.   char cmd, temp[10], *clrlst = "04261537";
  880.  
  881.   if (ansistr[1] != '[') {
  882.  
  883.     /* do nothing if invalid ANSI string. */
  884.  
  885.   } else {
  886.     argptr = tempptr = 0;
  887.     ptr = 2;
  888.     for (count = 0; count < 10; count++)
  889.       args[count] = temp[count] = 0;
  890.     cmd = ansistr[ansiptr - 1];
  891.     ansistr[ansiptr - 1] = 0;
  892.     while (ansistr[ptr]) {
  893.       if (ansistr[ptr] == ';') {
  894.         temp[tempptr] = 0;
  895.         tempptr = 0;
  896.         args[argptr++] = atoi(temp);
  897.       } else
  898.         temp[tempptr++] = ansistr[ptr];
  899.       ++ptr;
  900.     }
  901.     if (tempptr) {
  902.       temp[tempptr]  = 0;
  903.       args[argptr++] = atoi(temp);
  904.     }
  905.     if ((cmd >= 'A') && (cmd <= 'D') && !args[0])
  906.       args[0] = 1;
  907.     switch (cmd) {
  908.         case 'f':
  909.         case 'H':
  910.           movecsr(args[1] - 1, args[0] - 1);
  911.           break;
  912.         case 'A':
  913.           movecsr(WhereX(), WhereY() - args[0]);
  914.           break;
  915.         case 'B':
  916.           movecsr(WhereX(), WhereY() + args[0]);
  917.           break;
  918.         case 'C':
  919.           movecsr(WhereX() + args[0], WhereY());
  920.           break;
  921.         case 'D':
  922.           movecsr(WhereX() - args[0], WhereY());
  923.           break;
  924.         case 's':
  925.           oldx = WhereX();
  926.           oldy = WhereY();
  927.           break;
  928.         case 'u':
  929.           movecsr(oldx, oldy);
  930.           break;
  931.         case 'J':
  932.           if (args[0] == 2)
  933.             clrscrb();
  934.           break;
  935.         case 'k':
  936.         case 'K':
  937.           ox = WhereX();
  938.           oy = WhereY();
  939.           _CX = 80 - ox;
  940.           _AH = 0x09;
  941.           _BH = 0x00;
  942.           _AL = 32;
  943.           _BL = curatr;
  944.           my_video_int();
  945.           movecsr(ox, oy);
  946.           break;
  947.         case 'm':
  948.           if (!argptr) {
  949.             argptr = 1;
  950.             args[0] = 0;
  951.           }
  952.           for (count = 0; count < argptr; count++)
  953.             switch (args[count]) {
  954.               case 0: curatr = 0x07; break;
  955.               case 1: curatr = curatr | 0x08; break;
  956.               case 4: break;
  957.               case 5: curatr = curatr | 0x80; break;
  958.               case 7:
  959.                 ptr = curatr & 0x77;
  960.                 curatr = (curatr & 0x88) | (ptr << 4) | (ptr >> 4);
  961.                 break;
  962.               case 8: curatr = 0; break;
  963.               default:
  964.                 if ((args[count] >= 30) && (args[count] <= 37))
  965.                   setfgc(clrlst[args[count] - 30] - '0');
  966.                 else if ((args[count] >= 40) && (args[count] <= 47))
  967.                   setbgc(clrlst[args[count] - 40] - '0');
  968.             }
  969.           break;
  970.       }
  971.     }
  972.   ansiptr = 0;
  973. }
  974.  
  975.  
  976.  
  977. void outchr(char c)
  978. /* This function outputs one character to the screen, and if output to the
  979.  * com port is enabled, the character is output there too.  ANSI graphics
  980.  * are also trapped here, and the ansi function is called to execute the
  981.  * ANSI codes
  982.  */
  983. {
  984.   int i, i1;
  985.  
  986.   if (change_color == 1) {
  987.     change_color = 0;
  988.     if ((c >= '0') && (c <= '9'))
  989.       ansic(c - '0');
  990.     return;
  991.   } else if (change_color == 2) {
  992.     // This byte is reserved for RIPscrip 2 font style commands & codes
  993.     if (c == 15)
  994.       change_color = 3;
  995.     else
  996.       change_color = 0;
  997.     return;
  998.   } else if (change_color == 3) {
  999.     // Control or substitution codes
  1000.     change_color = 0;
  1001.     outstr(interpret(c));
  1002.     return;
  1003.   }
  1004.  
  1005.   if (c == 3) {
  1006.     change_color = 1;
  1007.     return;
  1008.   } else if (c == 15) {
  1009.     change_color = 2;
  1010.     return;
  1011.   }
  1012.  
  1013.   if ((c == 10) && endofline[0]) {
  1014.     if (!in_extern)
  1015.       outstr(endofline);
  1016.     endofline[0] = 0;
  1017.   }
  1018.   if (outcom && (c != 9))
  1019.     outcomch(echo ? c : 'X');
  1020.   if (ansiptr) {
  1021.     ansistr[ansiptr++] = c;
  1022.     ansistr[ansiptr]   = 0;
  1023.     if (((c > '@') && (c != '[')) || (ansistr[1] != '['))
  1024.       execute_ansi();
  1025.   } else if (c == 27) {
  1026.     ansistr[0] = 27;
  1027.     ansiptr = 1;
  1028.   } else if (c == 9) {
  1029.     i1 = WhereX();
  1030.     for (i = i1; i< (((i1 / 8) + 1) * 8); i++)
  1031.       outchr(32);
  1032.   } else if (echo || lecho) {
  1033.     out1ch(c);
  1034.     if (c == 10) {
  1035.       ++lines_listed;
  1036.       if ((sysstatus_pause_on_page & thisuser.sysstatus) &&
  1037.           (lines_listed >= screenlinest - 1)) {
  1038.         pausescr();
  1039.         lines_listed = 0;
  1040.       }
  1041.     }
  1042.   } else
  1043.     out1ch('X');
  1044. }
  1045.  
  1046.  
  1047.  
  1048. void outstr(char *s)
  1049. /* This function outputs a string of characters to the screen (and remotely
  1050.  * if applicable).  The com port is also checked first to see if a remote
  1051.  * user has hung up
  1052.  */
  1053. {
  1054.   int i=0;
  1055.  
  1056.   checkhangup();
  1057.   if (!hangup)
  1058.     while (s[i])
  1059.       outchr(s[i++]);
  1060. }
  1061.  
  1062.  
  1063.  
  1064. void nl(void)
  1065. /* This function performs a CR/LF sequence to move the cursor to the next
  1066.  * line.  If any end-of-line ANSI codes are set (such as changing back to
  1067.  * the default color) are specified, those are executed first.
  1068.  */
  1069. {
  1070.   if (endofline[0]) {
  1071.     outstr(endofline);
  1072.     endofline[0] = 0;
  1073.   }
  1074.   outstr("\r\n");
  1075. }
  1076.  
  1077.  
  1078.  
  1079. void backspace(void)
  1080. /* This function executes a backspace, space, backspace sequence. */
  1081. {
  1082.   int i;
  1083.  
  1084.   i = echo;
  1085.   echo = 1;
  1086.   outstr("\b \b");
  1087.   echo = i;
  1088. }
  1089.  
  1090.  
  1091.  
  1092. void setc(unsigned char ch)
  1093. /* This sets the current color (both locally and remotely) to that
  1094.  * specified (in IBM format).
  1095.  */
  1096. {
  1097.   char s[30];
  1098.  
  1099.   makeansi(ch, s, 0);
  1100.   outstr(s);
  1101. }
  1102.  
  1103.  
  1104.  
  1105. void pausescr(void)
  1106. /* This will pause output, displaying the [PAUSE] message, and wait for
  1107.  * a key to be hit.
  1108.  */
  1109. {
  1110.   int i;
  1111.  
  1112.   if (okansi()) {
  1113.     i = curatr;
  1114.     setc((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[3] :
  1115.           thisuser.bwcolors[3]);
  1116.     outstr("[PAUSE]\x1b[7D");
  1117.     setc(i);
  1118.     getkey();
  1119.     outstr("       \x1b[7D");
  1120.   } else {
  1121.     outstr("[PAUSE]");
  1122.     getkey();
  1123.     for (i = 0; i < 7; i++)
  1124.       backspace();
  1125.   }
  1126. }
  1127.  
  1128.  
  1129.  
  1130. void pl(char *s)
  1131. {
  1132.   outstr(s);
  1133.   nl();
  1134. }
  1135.  
  1136.  
  1137. int kbhitb(void)
  1138. {
  1139.   union REGS r;
  1140.  
  1141.   r.h.ah = 1;
  1142.   int86(0x16, &r, &r);
  1143.   return((r.x.flags & 64) == 0);
  1144. }
  1145.  
  1146.  
  1147. int empty(void)
  1148. {
  1149.   if (kbhitb() || (incom && (head != tail)) ||
  1150.       (charbufferpointer && charbuffer[charbufferpointer]) ||
  1151.       (in_extern == 2))
  1152.     return(0);
  1153.   return(1);
  1154. }
  1155.  
  1156.  
  1157.  
  1158. void skey1(char *ch)
  1159. {
  1160.   char c;
  1161.  
  1162.   c = *ch;
  1163.   if (c == 127)
  1164.     c = 8;
  1165.     switch(c) {
  1166.       case 1:
  1167.       case 4:
  1168.       case 6:
  1169.         if (!charbufferpointer) {
  1170.           if (c == 1)
  1171.             c = 2;
  1172.           else if (c == 4)
  1173.             c = 0;
  1174.           else if (c == 6)
  1175.             c = 1;
  1176.           strcpy(charbuffer, &(thisuser.macros[c][0]));
  1177.           c = charbuffer[0];
  1178.           if (c)
  1179.             charbufferpointer = 1;
  1180.         }
  1181.         break;
  1182.     }
  1183.   *ch = c;
  1184. }
  1185.  
  1186. char getchd(void)
  1187. {
  1188.   union REGS r;
  1189.  
  1190.   r.h.ah = 0x07;
  1191.   int86(save_dos, &r, &r);
  1192.   return(r.h.al);
  1193. }
  1194.  
  1195.  
  1196. char getchd1(void)
  1197. {
  1198.   union REGS r;
  1199.  
  1200.   r.h.ah = 0x06;
  1201.   r.h.dl = 0xFF;
  1202.   int86(save_dos, &r, &r);
  1203.   return((r.x.flags & 0x40) ? 255 : r.h.al);
  1204. }
  1205.  
  1206.  
  1207. char inkey(void)
  1208. /* This function checks both the local keyboard, and the remote terminal
  1209.  * (if any) for input.  If there is input, the key is returned.  If there
  1210.  * is no input, a zero is returned.  Function keys hit are interpreted as
  1211.  * such within the routine and not returned.
  1212.  */
  1213. {
  1214.   char ch=0;
  1215.  
  1216.   if (charbufferpointer) {
  1217.     if (!charbuffer[charbufferpointer])
  1218.       charbufferpointer = charbuffer[0] = 0;
  1219.     else
  1220.       return(charbuffer[charbufferpointer++]);
  1221.   }
  1222.   if (kbhitb() || (in_extern == 2)) {
  1223.     ch = getchd1();
  1224.     if (!ch) {
  1225.       if (in_extern)
  1226.         in_extern = 2;
  1227.       else {
  1228.         ch = getchd1();
  1229.         ch=0;
  1230.       }
  1231.     } else if (in_extern)
  1232.       in_extern = 1;
  1233.     timelastchar1=timer1();
  1234.   } else if (incom && comhit()) {
  1235.     ch = (get1c() & andwith);
  1236.   }
  1237.   skey1(&ch);
  1238.   return(ch);
  1239. }
  1240.  
  1241.  
  1242.  
  1243. void mpl(int i)
  1244. /* This will make a reverse-video prompt line i characters long, repositioning
  1245.  * the cursor at the beginning of the input prompt area.  Of course, if the
  1246.  * user does not want ansi, this routine does nothing.
  1247.  */
  1248. {
  1249.   int i1;
  1250.   char s[81];
  1251.  
  1252.   if (okansi()) {
  1253.     ansic(4);
  1254.     for (i1 = 0; i1 < i; i1++)
  1255.       outchr(' ');
  1256.     outstr("\x1b[");
  1257.     itoa(i,s,10);
  1258.     outstr(s);
  1259.     outstr("D");
  1260.   }
  1261. }
  1262.  
  1263.  
  1264.  
  1265. char upcase(char ch)
  1266. /* This converts a character to uppercase */
  1267. {
  1268.   if ((ch > '`') && (ch < '{'))
  1269.     ch = ch - 32;
  1270.   return(ch);
  1271. }
  1272.  
  1273.  
  1274. unsigned char getkey(void)
  1275. /* This function returns one character from either the local keyboard or
  1276.  * remote com port (if applicable).  After 1.5 minutes of inactivity, a
  1277.  * beep is sounded.  After 3 minutes of inactivity, the user is hung up.
  1278.  */
  1279. {
  1280.   unsigned char ch;
  1281.   int beepyet;
  1282.   long dd;
  1283.  
  1284.   beepyet = 0;
  1285.   timelastchar1=timer1();
  1286.  
  1287.   lines_listed = 0;
  1288.   do {
  1289.     while (empty() && !hangup) {
  1290.       dd = timer1();
  1291.       if (labs(dd - timelastchar1) > 65536L)
  1292.         timelastchar1 -= 1572480L;
  1293.       if (((dd - timelastchar1) > 1638L) && (!beepyet)) {
  1294.         beepyet = 1;
  1295.         outchr(7);
  1296.       }
  1297.       if (labs(dd - timelastchar1) > 3276L) {
  1298.         nl();
  1299.         outstr("Call back later when you are there.");
  1300.         nl();
  1301.         hangup = 1;
  1302.       }
  1303.       checkhangup();
  1304.     }
  1305.     ch = inkey();
  1306.   } while (!ch && !in_extern && !hangup);
  1307.   return(ch);
  1308. }
  1309.  
  1310.  
  1311.  
  1312. void input1(char *s, int maxlen, int lc, int crend)
  1313. /* This will input a line of data, maximum maxlen characters long, terminated
  1314.  * by a C/R.  if (lc) is non-zero, lowercase is allowed, otherwise all
  1315.  * characters are converted to uppercase.
  1316.  */
  1317. {
  1318.   int curpos=0, done=0;
  1319.   unsigned char ch;
  1320.  
  1321.   while (!done && !hangup) {
  1322.     ch = getkey();
  1323.     if (ch > 31) {
  1324.       if (curpos < maxlen) {
  1325.         if (!lc)
  1326.           ch = upcase(ch);
  1327.         s[curpos++] = ch;
  1328.         outchr(ch);
  1329.       }
  1330.     } else
  1331.       switch(ch) {
  1332.         case 14:
  1333.         case 13:
  1334.           s[curpos] = 0;
  1335.           done = echo = 1;
  1336.           if (crend)
  1337.             nl();
  1338.           break;
  1339.         case 26:
  1340.           if (input_extern) {
  1341.             s[curpos++] = 26;
  1342.             outstr("^Z");
  1343.           }
  1344.           break;
  1345.         case 8:
  1346.           if (curpos) {
  1347.             curpos--;
  1348.             backspace();
  1349.             if (s[curpos] == 26)
  1350.               backspace();
  1351.           }
  1352.           break;
  1353.         case 24:
  1354.           while (curpos) {
  1355.             curpos--;
  1356.             backspace();
  1357.             if (s[curpos] == 26)
  1358.               backspace();
  1359.           }
  1360.           break;
  1361.       }
  1362.   }
  1363.   if (hangup)
  1364.     s[0] = 0;
  1365. }
  1366.  
  1367.  
  1368.  
  1369. void input(char *s, int len)
  1370. /* This will input an upper-case string */
  1371. {
  1372.   input1(s, len, 0, 1);
  1373. }
  1374.  
  1375.  
  1376.  
  1377. void inputl(char *s, int len)
  1378. /* This will input an upper or lowercase string of characters */
  1379. {
  1380.   input1(s, len, 1, 1);
  1381. }
  1382.  
  1383.  
  1384.  
  1385. int yn(void)
  1386. /* The keyboard is checked for either a Y, N, or C/R to be hit.  C/R is
  1387.  * assumed to be the same as a N.  Yes or No is output, and yn is set to
  1388.  * zero if No was returned, and yn() is non-zero if Y was hit.
  1389.  */
  1390. {
  1391.   char ch=0;
  1392.  
  1393.   ansic(1);
  1394.   while (!hangup && ((ch = upcase(getkey())) != 'Y') && (ch != 'N') && (ch != 13))
  1395.     ;
  1396.   outstr((ch == 'Y') ? "Yes" : "No");
  1397.   nl();
  1398.   return(ch == 'Y');
  1399. }
  1400.  
  1401.  
  1402.  
  1403. int ny(void)
  1404. /* This is the same as yn(), except C/R is assumed to be "Y" */
  1405. {
  1406.   char ch=0;
  1407.  
  1408.   ansic(1);
  1409.   while (!hangup && ((ch = upcase(getkey())) != 'Y') && (ch != 'N') && (ch != 13))
  1410.     ;
  1411.   outstr((ch == 'N') ? "No" : "Yes");
  1412.   nl();
  1413.   return((ch == 'Y') || (ch==13));
  1414. }
  1415.  
  1416.  
  1417. void ansic(int n)
  1418. {
  1419.   char c;
  1420.  
  1421.   c = ((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[n] :
  1422.         thisuser.bwcolors[n]);
  1423.   if (c == curatr)
  1424.     return;
  1425.   setc(c);
  1426.   makeansi((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[0] :
  1427.         thisuser.bwcolors[0],endofline, 0);
  1428. }
  1429.  
  1430.  
  1431. char onek(char *s)
  1432. {
  1433.   char ch;
  1434.  
  1435.   while (!strchr(s, ch = upcase(getkey())) && !hangup)
  1436.     ;
  1437.   if (hangup)
  1438.     ch = s[0];
  1439.   outchr(ch);
  1440.   nl();
  1441.   return(ch);
  1442. }
  1443.  
  1444.  
  1445. void prt(int i, char *s)
  1446. {
  1447.   ansic(i);
  1448.   outstr(s);
  1449.   ansic(0);
  1450. }
  1451.  
  1452. /****************************************************************************/
  1453. #pragma warn -par
  1454.  
  1455. void far interrupt inlii(unsigned bp, unsigned di, unsigned si,
  1456.                            unsigned ds, unsigned es, unsigned dx,
  1457.                            unsigned cx, unsigned bx, unsigned ax,
  1458.                            unsigned ip, unsigned cs, unsigned flags,
  1459.                            char *s1, char *s2, int i1, int i2)
  1460. {
  1461.   inli(s1,s2,i1,i2);
  1462. }
  1463.  
  1464. void far interrupt checkai(unsigned bp, unsigned di, unsigned si,
  1465.                            unsigned ds, unsigned es, unsigned dx,
  1466.                            unsigned cx, unsigned bx, unsigned ax,
  1467.                            unsigned ip, unsigned cs, unsigned flags,
  1468.                            int *i1, int *i2)
  1469. {
  1470.   checka(i1,i2);
  1471. }
  1472.  
  1473.  
  1474. void far interrupt plai(unsigned bp, unsigned di, unsigned si,
  1475.                            unsigned ds, unsigned es, unsigned dx,
  1476.                            unsigned cx, unsigned bx, unsigned ax,
  1477.                            unsigned ip, unsigned cs, unsigned flags,
  1478.                            char *s1, int *i1)
  1479. {
  1480.   pla(s1,i1);
  1481. }
  1482.  
  1483.  
  1484. void far interrupt outchri(unsigned bp, unsigned di, unsigned si,
  1485.                            unsigned ds, unsigned es, unsigned dx,
  1486.                            unsigned cx, unsigned bx, unsigned ax,
  1487.                            unsigned ip, unsigned cs, unsigned flags,
  1488.                            char ch)
  1489. {
  1490.   outchr(ch);
  1491. }
  1492.  
  1493.  
  1494. void far interrupt outstri(unsigned bp, unsigned di, unsigned si,
  1495.                            unsigned ds, unsigned es, unsigned dx,
  1496.                            unsigned cx, unsigned bx, unsigned ax,
  1497.                            unsigned ip, unsigned cs, unsigned flags,
  1498.                            char *s1)
  1499. {
  1500.   outstr(s1);
  1501. }
  1502.  
  1503.  
  1504. void far interrupt nli(unsigned bp, unsigned di, unsigned si,
  1505.                            unsigned ds, unsigned es, unsigned dx,
  1506.                            unsigned cx, unsigned bx, unsigned ax,
  1507.                            unsigned ip, unsigned cs, unsigned flags)
  1508. {
  1509.   nl();
  1510. }
  1511.  
  1512.  
  1513. void far interrupt pli(unsigned bp, unsigned di, unsigned si,
  1514.                            unsigned ds, unsigned es, unsigned dx,
  1515.                            unsigned cx, unsigned bx, unsigned ax,
  1516.                            unsigned ip, unsigned cs, unsigned flags,
  1517.                            char *s1)
  1518. {
  1519.   pl(s1);
  1520. }
  1521.  
  1522.  
  1523. void far interrupt emptyi(unsigned bp, unsigned di, unsigned si,
  1524.                            unsigned ds, unsigned es, unsigned dx,
  1525.                            unsigned cx, unsigned bx, unsigned ax,
  1526.                            unsigned ip, unsigned cs, unsigned flags)
  1527. {
  1528.   ax=empty();
  1529. }
  1530.  
  1531.  
  1532. void far interrupt inkeyi(unsigned bp, unsigned di, unsigned si,
  1533.                            unsigned ds, unsigned es, unsigned dx,
  1534.                            unsigned cx, unsigned bx, unsigned ax,
  1535.                            unsigned ip, unsigned cs, unsigned flags)
  1536. {
  1537.   ax=(unsigned) empty();
  1538. }
  1539.  
  1540.  
  1541. void far interrupt getkeyi(unsigned bp, unsigned di, unsigned si,
  1542.                            unsigned ds, unsigned es, unsigned dx,
  1543.                            unsigned cx, unsigned bx, unsigned ax,
  1544.                            unsigned ip, unsigned cs, unsigned flags)
  1545. {
  1546.   ax=(unsigned) getkey();
  1547. }
  1548.  
  1549.  
  1550. void far interrupt inputi(unsigned bp, unsigned di, unsigned si,
  1551.                            unsigned ds, unsigned es, unsigned dx,
  1552.                            unsigned cx, unsigned bx, unsigned ax,
  1553.                            unsigned ip, unsigned cs, unsigned flags,
  1554.                            char *s1, int i)
  1555. {
  1556.   input(s1,i);
  1557. }
  1558.  
  1559.  
  1560. void far interrupt inputli(unsigned bp, unsigned di, unsigned si,
  1561.                            unsigned ds, unsigned es, unsigned dx,
  1562.                            unsigned cx, unsigned bx, unsigned ax,
  1563.                            unsigned ip, unsigned cs, unsigned flags,
  1564.                            char *s1, int i)
  1565. {
  1566.   inputl(s1,i);
  1567. }
  1568.  
  1569.  
  1570. void far interrupt yni(unsigned bp, unsigned di, unsigned si,
  1571.                            unsigned ds, unsigned es, unsigned dx,
  1572.                            unsigned cx, unsigned bx, unsigned ax,
  1573.                            unsigned ip, unsigned cs, unsigned flags)
  1574. {
  1575.   ax=yn();
  1576. }
  1577.  
  1578.  
  1579.  
  1580. void far interrupt nyi(unsigned bp, unsigned di, unsigned si,
  1581.                            unsigned ds, unsigned es, unsigned dx,
  1582.                            unsigned cx, unsigned bx, unsigned ax,
  1583.                            unsigned ip, unsigned cs, unsigned flags)
  1584. {
  1585.   ax=ny();
  1586. }
  1587.  
  1588.  
  1589. void far interrupt ansici(unsigned bp, unsigned di, unsigned si,
  1590.                            unsigned ds, unsigned es, unsigned dx,
  1591.                            unsigned cx, unsigned bx, unsigned ax,
  1592.                            unsigned ip, unsigned cs, unsigned flags,
  1593.                            int i1)
  1594. {
  1595.   ansic(i1);
  1596. }
  1597.  
  1598.  
  1599. void far interrupt oneki(unsigned bp, unsigned di, unsigned si,
  1600.                            unsigned ds, unsigned es, unsigned dx,
  1601.                            unsigned cx, unsigned bx, unsigned ax,
  1602.                            unsigned ip, unsigned cs, unsigned flags,
  1603.                            char *s1)
  1604. {
  1605.   ax=(unsigned) onek(s1);
  1606. }
  1607.  
  1608.  
  1609. void far interrupt prti(unsigned bp, unsigned di, unsigned si,
  1610.                            unsigned ds, unsigned es, unsigned dx,
  1611.                            unsigned cx, unsigned bx, unsigned ax,
  1612.                            unsigned ip, unsigned cs, unsigned flags,
  1613.                            int i1, char *s1)
  1614. {
  1615.   prt(i1,s1);
  1616. }
  1617.  
  1618.  
  1619.  
  1620. void far interrupt mpli(unsigned bp, unsigned di, unsigned si,
  1621.                            unsigned ds, unsigned es, unsigned dx,
  1622.                            unsigned cx, unsigned bx, unsigned ax,
  1623.                            unsigned ip, unsigned cs, unsigned flags,
  1624.                            int i1)
  1625. {
  1626.   mpl(i1);
  1627. }
  1628.  
  1629.  
  1630. #pragma warn +par
  1631.  
  1632. /****************************************************************************/
  1633.  
  1634. unsigned char getkeyext(void)
  1635. {
  1636.   unsigned char ch;
  1637.   static int holding=0;
  1638.   static char held=0;
  1639.  
  1640.   if (holding) {
  1641.     holding=0;
  1642.     return(held);
  1643.   }
  1644.   ch=getkey();
  1645.   if (charbufferpointer==0) {
  1646.     if (ch==16) {
  1647.       ch=getkey();
  1648.       if ((ch==1) && (charbufferpointer==0)) {
  1649.         strcpy(charbuffer,&(thisuser.macros[2][0]));
  1650.         ch=charbuffer[0];
  1651.         if (ch) {
  1652.           charbufferpointer=1;
  1653.           return(ch);
  1654.         } else
  1655.           return(getkeyext());
  1656.       } else
  1657.         if ((ch==4) && (charbufferpointer==0)) {
  1658.           strcpy(charbuffer,&(thisuser.macros[0][0]));
  1659.           ch=charbuffer[0];
  1660.           if (ch) {
  1661.             charbufferpointer=1;
  1662.             return(ch);
  1663.           } else
  1664.             return(getkeyext());
  1665.         } else
  1666.           if ((ch==6) && (charbufferpointer==0)) {
  1667.             strcpy(charbuffer,&(thisuser.macros[1][0]));
  1668.             ch=charbuffer[0];
  1669.             if (ch) {
  1670.               charbufferpointer=1;
  1671.               return(ch);
  1672.             } else
  1673.               return(getkeyext());
  1674.           } else {
  1675.             holding=1;
  1676.             held=ch;
  1677.             return(16);
  1678.           }
  1679.     }
  1680.   }
  1681.   return(ch);
  1682. }
  1683.  
  1684.  
  1685. int do_it(char *cl)
  1686. {
  1687.   int i,i1,l;
  1688.   char s[160];
  1689.   char *ss[30];
  1690.  
  1691.   strcpy(s,cl);
  1692.   ss[0]=s;
  1693.   i=1;
  1694.   l=strlen(s);
  1695.   for (i1=1; i1<l; i1++)
  1696.     if (s[i1]==32) {
  1697.       s[i1]=0;
  1698.       ss[i++]=&(s[i1+1]);
  1699.     }
  1700.   ss[i]=NULL;
  1701.   funcs[20]=NULL;
  1702.   i=(spawnvpe(P_WAIT,ss[0],ss,xenviron) & 0x00ff);
  1703.   funcs[20]=NULL;
  1704. /*   spawnvp(P_WAIT,ss[0],ss); */
  1705.   return(i);
  1706. }
  1707.  
  1708.  
  1709.  
  1710. int do_remote(char *s, int ccc)
  1711. {
  1712.   int rc;
  1713.   char x[161];
  1714.  
  1715.   checkhangup();
  1716.   if (hangup)
  1717.     return(32767);
  1718.   strcpy(x,getenv("COMSPEC"));
  1719.   strcat(x," /C ");
  1720.   strcat(x,s);
  1721.   if (ccc)
  1722.     rc=do_it(x);
  1723.   else
  1724.     rc=do_it(s);
  1725.   chdir(cdir);
  1726.   setdisk(cdir[0]-'A');
  1727.   return(rc);
  1728. }
  1729.  
  1730.  
  1731. union REGS ca_r;
  1732. int ca_pause,ca_ctrl_c;
  1733. long ca_d1;
  1734.  
  1735.  
  1736. void checka2(void)
  1737. {
  1738.   ca_pause=0;
  1739.   ca_ctrl_c=0;
  1740.   ca_r.h.ah=1;
  1741.   int86(0x16,&ca_r,&ca_r);
  1742.   if ((ca_r.x.flags & 64)==0) {
  1743.     if (ca_r.x.ax==11779)
  1744.       ca_ctrl_c=1;
  1745.     if (ca_r.x.ax==7955)
  1746.       ca_pause=1;
  1747.   }
  1748.   if (head!=tail) {
  1749.     if (buffer[tail]==3)
  1750.       ca_ctrl_c=1;
  1751.     if (buffer[tail]==19)
  1752.       ca_pause=1;
  1753.   }
  1754.   if (ca_pause) {
  1755.     while (inkey()!=0)
  1756.       ;
  1757.     ca_d1=timer1();
  1758.     while ((inkey()==0) && (labs(timer1()-ca_d1)<3276L) && (!hangup))
  1759.       checkhangup();
  1760.     lines_listed=0;
  1761.   }
  1762.   if ((ca_ctrl_c) && (ctc)) {
  1763.     while (inkey()!=0)
  1764.       ;
  1765.     pl("^C");
  1766.     ca_r.x.ax=0x4c00;
  1767.     int86(save_dos,&ca_r,&ca_r);
  1768.   }
  1769. }
  1770.  
  1771.  
  1772.  
  1773.  
  1774. void outdosstr(char *s)
  1775. /* This function outputs a string of characters to the screen (and remotely
  1776.  * if applicable).  The com port is also checked first to see if a remote
  1777.  * user has hung up
  1778.  */
  1779. {
  1780.   int i;
  1781.  
  1782.   checkhangup();
  1783.   if (hangup==0) {
  1784.     i=0;
  1785.     while ((s[i] !='$') && (i<1024)) {
  1786.       checka2();
  1787.       outchr(s[i++]);
  1788.     }
  1789.   }
  1790. }
  1791.  
  1792.  
  1793.  
  1794. union REGS ni_r;
  1795. struct SREGS ni_s;
  1796. unsigned ni_n;
  1797. char ni_ch,ni_ch1,ni_ss[10],ni_ch2;
  1798. unsigned char *ni_st;
  1799.  
  1800. #define ST_SIZE 500
  1801. static unsigned short ni_stack[ST_SIZE];
  1802.  
  1803.  
  1804. #pragma warn -par
  1805.  
  1806. void far interrupt newintr1(unsigned bp, unsigned di, unsigned si,
  1807.                            unsigned ds, unsigned es, unsigned dx,
  1808.                            unsigned cx, unsigned bx, unsigned ax,
  1809.                            unsigned ip, unsigned cs, unsigned flags)
  1810. {
  1811.  
  1812.   unsigned short ni_SS, ni_SP;
  1813. #define NEW_STK() { _BX=FP_OFF(&ni_stack[ST_SIZE-2]); _SS=_DS; _SP=_BX; }
  1814. #define OLD_STK() { _AX=ni_SS; _BX=ni_SP; _SS=_AX; _SP=_BX; }
  1815.  
  1816.  
  1817.  
  1818.   ni_r.x.ax=ax;
  1819.   ni_r.x.bx=bx;
  1820.   ni_r.x.cx=cx;
  1821.   ni_r.x.dx=dx;
  1822.   ni_r.x.si=si;
  1823.   ni_r.x.di=di;
  1824.   ni_r.x.flags=flags;
  1825.   ni_s.ds=ds;
  1826.   ni_s.es=es;
  1827.  
  1828.   ni_SS=_SS;
  1829.   ni_SP=_SP;
  1830.  
  1831.   ni_ch=ni_r.h.ah;
  1832.   ni_ch1=0;
  1833.  
  1834.   if (ni_ch==0x0c) {
  1835.     dump();
  1836.     switch(ni_r.h.al) {
  1837.       case 0x01:
  1838.       case 0x06:
  1839.       case 0x07:
  1840.       case 0x08:
  1841.       case 0x0a:
  1842.         ni_r.h.al = ni_r.h.al;
  1843.         ni_ch = ni_r.h.al;
  1844.         break;
  1845.     }
  1846.   }
  1847.   switch(ni_ch) {
  1848.     case 0x01:
  1849.       NEW_STK();
  1850.       ni_ch=getkeyext();
  1851.       outchr(ni_ch);
  1852.       if (hangup)
  1853.         ni_ch=3;
  1854.       ni_r.h.al=ni_ch;
  1855.       ni_ch1=1;
  1856.       OLD_STK();
  1857.       break;
  1858.     case 0x02:
  1859.       NEW_STK();
  1860.       outchr(ni_r.h.dl);
  1861.       ni_ch1=1;
  1862.       checka2();
  1863.       OLD_STK();
  1864.       break;
  1865.     case 0x06:
  1866.       NEW_STK();
  1867.       if (ni_r.h.dl!=0xff) {
  1868.         outchr(ni_r.h.dl);
  1869.         ni_ch1=1;
  1870.       } else {
  1871.         if (empty()) {
  1872.           ni_r.x.flags |= 64;
  1873.         } else {
  1874.           ni_r.x.flags &= (0xffff ^ 64);
  1875.           ni_r.h.al=getkeyext();
  1876.         }
  1877.       }
  1878.       OLD_STK();
  1879.       break;
  1880.     case 0x07:
  1881.       NEW_STK();
  1882.       ni_ch1=1;
  1883.       ni_r.h.al=getkeyext();
  1884.       OLD_STK();
  1885.       break;
  1886.     case 0x08:
  1887.       NEW_STK();
  1888.       ni_ch1=1;
  1889.       ni_r.h.al=getkeyext();
  1890.       OLD_STK();
  1891.       break;
  1892.     case 0x09:
  1893.       NEW_STK();
  1894.       outdosstr((char *) MK_FP(ni_s.ds, ni_r.x.dx));
  1895.       ni_ch1=1;
  1896.       OLD_STK();
  1897.       break;
  1898.     case 0x0a:
  1899.       NEW_STK();
  1900.       ni_st=(char *) MK_FP(ni_s.ds,ni_r.x.dx);
  1901.       ni_n=(unsigned int)(ni_st[0]);
  1902.       if (in_extern==2)
  1903.         getkeyext();
  1904.       in_extern=0;
  1905.       input_extern=1;
  1906.       input1(&(ni_st[2]),ni_n-3,1,0);
  1907.       input_extern=0;
  1908.       in_extern=1;
  1909.       ni_st[1]=strlen(&(ni_st[2]));
  1910.       strcat(&(ni_st[2]),"\r");
  1911.       if ((hangup)) {
  1912.         strcpy(&(ni_st[2]),"EXIT\r");
  1913.         ni_st[1]=4;
  1914.         outstr("Exiting...");
  1915.       }
  1916.       ni_ch1=1;
  1917.       OLD_STK();
  1918.       break;
  1919.     case 0x0b:
  1920.       NEW_STK();
  1921.       if (empty())
  1922.         ni_r.h.al=0x00;
  1923.       else
  1924.         ni_r.h.al=0xff;
  1925.       ni_ch1=1;
  1926.       OLD_STK();
  1927.       break;
  1928.     case 0x0c:
  1929.       break;
  1930.     case 0x3f:
  1931.       if (ni_r.x.bx==0x0000) {
  1932.         NEW_STK();
  1933.         ni_st=(char *)MK_FP(ni_s.ds,ni_r.x.dx);
  1934.         inputl(ni_st,ni_r.x.cx);
  1935.         strcat(ni_st,"\r\n");
  1936.         ni_r.x.ax=strlen(ni_st);
  1937.         if (hangup)
  1938.           ni_r.x.ax=0;
  1939.         ni_r.x.flags &=(0xffff ^ 1);
  1940.         ni_ch1=1;
  1941.         OLD_STK();
  1942.       } else
  1943.         int86x(save_dos,&ni_r,&ni_r,&ni_s);
  1944.       break;
  1945.     case 0x40:
  1946.       if ((ni_r.x.bx==0x0001) || (ni_r.x.bx==0x0002)) {
  1947.         NEW_STK();
  1948.         ni_st=(char *)MK_FP(ni_s.ds,ni_r.x.dx);
  1949.         for (ni_n=0; ni_n<ni_r.x.cx; ni_n++) {
  1950.           outchr(ni_st[ni_n]);
  1951.           checka2();
  1952.         }
  1953.         ni_r.x.ax=ni_r.x.cx;
  1954.         ni_r.x.flags &=(0xffff ^ 1);
  1955.         ni_ch1=1;
  1956.         OLD_STK();
  1957.       } else
  1958.         int86x(save_dos,&ni_r,&ni_r,&ni_s);
  1959.       break;
  1960.     default:
  1961.       int86x(save_dos,&ni_r,&ni_r,&ni_s);
  1962.       break;
  1963.   }
  1964.  
  1965.   if (ni_ch1) {
  1966.     checkhangup();
  1967.     if (hangup) {
  1968.       if (hanguptime1<0L) {
  1969.         hanguptime1=timer1();
  1970.         if (funcs[20]) {
  1971.           outstr("Terminating...\r\n");
  1972.           ip=FP_OFF(funcs[20]);
  1973.           cs=FP_SEG(funcs[20]);
  1974.           funcs[20]=(void far *)36;
  1975.         } else {
  1976.           funcs[20]=(void far *)36;
  1977.           outstr("Aborting...\r\n");
  1978.           ni_r.x.ax=0x4c00;
  1979.           int86x(save_dos,&ni_r,&ni_r,&ni_s);
  1980.         }
  1981.       } else {
  1982.         if (labs(timer1()-hanguptime1)>36L) {
  1983.           hanguptime1=timer1();
  1984.           outstr("Aborting...\r\n");
  1985.           ni_r.x.ax=0x4c00;
  1986.           int86x(save_dos,&ni_r,&ni_r,&ni_s);
  1987.         }
  1988.       }
  1989.     }
  1990.   }
  1991.  
  1992.   ax=ni_r.x.ax;
  1993.   bx=ni_r.x.bx;
  1994.   cx=ni_r.x.cx;
  1995.   dx=ni_r.x.dx;
  1996.   si=ni_r.x.si;
  1997.   di=ni_r.x.di;
  1998.   flags=ni_r.x.flags;
  1999.   ds=ni_s.ds;
  2000.   es=ni_s.es;
  2001. }
  2002.  
  2003.  
  2004.  
  2005. int full_external(char *s, int ccc)
  2006. {
  2007.   int cy,cx,xxx;
  2008.  
  2009.   checkhangup();
  2010.   if (hangup)
  2011.     return(0);
  2012.   in_extern=1;
  2013.   hanguptime1=-1L;
  2014.   setvect(save_dos,getvect(INT_REAL_DOS));
  2015.  
  2016.   setvect(INT_REAL_DOS,newintr1);
  2017.  
  2018.   if ((screenlinest<=defscreenbottom) && (screenlinest>20)) {
  2019.     screenbottom=screenlinest-1;
  2020.     cy=WhereY();
  2021.     cx=WhereX();
  2022.     xxx=cy-screenbottom+topline;
  2023.     if (xxx>0) {
  2024.       SCROLL_UP(topline,defscreenbottom,xxx);
  2025.       movecsr(cx,screenbottom);
  2026.     }
  2027.   }
  2028.  
  2029.   do_remote(s,ccc);
  2030.  
  2031.   setvect(INT_REAL_DOS,getvect(save_dos));
  2032.  
  2033.   if (in_extern==2)
  2034.     getkey();
  2035.   in_extern=0;
  2036.   return(0);
  2037. }
  2038.  
  2039.  
  2040. /****************************************************************************/
  2041.  
  2042. #define READ(x) read(i,&(x),sizeof(x))
  2043.  
  2044. int init_r(void)
  2045. {
  2046.   int i;
  2047.   char s[81];
  2048.  
  2049.   for (i=0; i<25; i++)
  2050.     funcs[i]=NULL;
  2051.   funcs[0]=(void far *)inlii;
  2052.   funcs[1]=(void far *)checkai;
  2053.   funcs[2]=(void far *)plai;
  2054.   funcs[3]=(void far *)outchri;
  2055.   funcs[4]=(void far *)outstri;
  2056.   funcs[5]=(void far *)nli;
  2057.   funcs[8]=(void far *)pli;
  2058.   funcs[9]=(void far *)emptyi;
  2059.   funcs[10]=(void far *)inkeyi;
  2060.   funcs[11]=(void far *)getkeyi;
  2061.   funcs[12]=(void far *)inputi;
  2062.   funcs[13]=(void far *)inputli;
  2063.   funcs[14]=(void far *)yni;
  2064.   funcs[15]=(void far *)nyi;
  2065.   funcs[16]=(void far *)ansici;
  2066.   funcs[17]=(void far *)oneki;
  2067.   funcs[18]=(void far *)prti;
  2068.   funcs[19]=(void far *)mpli;
  2069.  
  2070.   if(instance > 1)
  2071.     sprintf(s,"STAT.%3.3d",instance);
  2072.   else
  2073.     sprintf(s,"STAT.WWV");
  2074.  
  2075.   i=sh_open1(s,O_RDONLY | O_BINARY);
  2076.   if (i<0)
  2077.     return(1);
  2078.  
  2079.   READ(incom);
  2080.   READ(outcom);
  2081.   using_modem=incom || outcom;
  2082.   READ(thisuser);
  2083.   READ(flow_control);
  2084.   READ(async_irq);
  2085.   READ(baud_rate);
  2086.   READ(base);
  2087.   READ(andwith);
  2088.   READ(ctc);
  2089.   READ(defscreenbottom);
  2090.   READ(ok_modem_stuff);
  2091.   READ(save_dos);
  2092.  
  2093.   sh_close(i);
  2094.  
  2095.   if (ok_modem_stuff)
  2096.     initport(0);
  2097.   return(0);
  2098. }
  2099.  
  2100. void get_dir(char *s, int be)
  2101. {
  2102.   strcpy(s,"X:\\");
  2103.   s[0]='A'+getdisk();
  2104.   getcurdir(0,&(s[3]));
  2105.   if (be) {
  2106.     if (s[strlen(s)-1]!='\\')
  2107.       strcat(s,"\\");
  2108.   }
  2109. }
  2110.  
  2111.  
  2112. void cd_to(char *s)
  2113. {
  2114.   char s1[81];
  2115.   int i,db;
  2116.  
  2117.   strcpy(s1,s);
  2118.   i=strlen(s1)-1;
  2119.   db=(s1[i]=='\\');
  2120.   if (i==0)
  2121.     db=0;
  2122.   if ((i==2) && (s1[1]==':'))
  2123.     db=0;
  2124.   if (db)
  2125.     s1[i]=0;
  2126.   chdir(s1);
  2127.   if (s[1]==':')
  2128.     setdisk(s[0]-'A');
  2129. }
  2130.  
  2131. void setup_stuff(void)
  2132. {
  2133.   char s[161], *ss;
  2134.   int i,i1;
  2135.  
  2136.   strcpy(ver_no1,"BBS=");
  2137.   strcat(ver_no1,wwiv_version);
  2138.  
  2139.  
  2140.   strcpy(s,getenv("PROMPT"));
  2141.   if (strncmp(s,"WWIV: ",5))
  2142.     strcpy(newprompt,"PROMPT=WWIV: ");
  2143.   else
  2144.     strcpy(newprompt,"PROMPT=");
  2145.   if (s[0])
  2146.     strcat(newprompt,s);
  2147.   else
  2148.     strcat(newprompt,"$P$G");
  2149.  
  2150.   ss=getenv("WWIV_INSTANCE");
  2151.   if(ss) {
  2152.     instance=atoi(ss);
  2153.   } else {
  2154.     instance=1;
  2155.   }
  2156.  
  2157.   sprintf(ver_no2,"WWIV_FP=%04.4X:%04.4X",FP_SEG(funcs), FP_OFF(funcs));
  2158.  
  2159.  
  2160.   i=i1=0;
  2161.   while (environ[i]!=NULL) {
  2162.     if (strncmp(environ[i],"PROMPT=",7)==0)
  2163.       xenviron[i1++]=newprompt;
  2164.     else {
  2165.       if (strncmp(environ[i],"BBS=",4) && (strncmp(environ[i],"WWIV_FP=",8)))
  2166.         xenviron[i1++]=environ[i];
  2167.       }
  2168.     ++i;
  2169.   }
  2170.   if (!getenv("PROMPT"))
  2171.     xenviron[i1++]=newprompt;
  2172.   if (!getenv("PKNOFASTCHAR"))
  2173.     xenviron[i1++]="PKNOFASTCHAR=Y";
  2174.   xenviron[i1++]=ver_no1;
  2175.   xenviron[i1++]=ver_no2;
  2176.   xenviron[i1]=NULL;
  2177.  
  2178. }
  2179.  
  2180. /****************************************************************************/
  2181.  
  2182. void main(int argc, char *argv[])
  2183. {
  2184.   int i,i1;
  2185.   char s[250], s1[80], *ss;
  2186.   FILE *f;
  2187.  
  2188.   get_dir(cdir,0);
  2189.  
  2190.   setup_stuff();
  2191.  
  2192.   strcpy(s,argv[0]);
  2193.   ss=strrchr(s,'.');
  2194.   if (ss)
  2195.     *ss=0;
  2196.   sprintf(s1,"%s.%03.3d", s, instance);
  2197.   if ((f=fopen(s1,"r"))!=NULL) {
  2198.     strcpy(s, argv[0]);
  2199.     argv = (char **) malloc(100 * sizeof(char *));
  2200.     argv[0] = strdup(s);
  2201.     argc=1;
  2202.     fgets(s, sizeof(s)-1, f);
  2203.     fclose(f);
  2204.     ss=strtok(s," \t\r\n");
  2205.     while (ss) {
  2206.       argv[argc++] = strdup(ss);
  2207.       ss=strtok(NULL," \t\r\n");
  2208.     }
  2209.     argv[argc] = NULL;
  2210.   }
  2211.  
  2212.   i=atoi(argv[1]);
  2213.   ccc=atoi(argv[2]);
  2214.  
  2215.  
  2216.   if (argc>=3) {
  2217.     s[0]=0;
  2218.     for (i1=3; i1<argc; i1++) {
  2219.       strcat(s,argv[i1]);
  2220.       strcat(s," ");
  2221.     }
  2222.     if (i) {
  2223.       if (!init_r()) {
  2224.         if (incom || outcom)
  2225.           screenbottom=thisuser.screenlines-1;
  2226.         else
  2227.           screenbottom=defscreenbottom;
  2228.         screenlinest=screenbottom+1;
  2229.         full_external(s,ccc);
  2230.         if (ok_modem_stuff)
  2231.           closeport();
  2232.       } else
  2233.         pl("Couldn't find data");
  2234.     } else
  2235.       do_remote(s,ccc);
  2236.   }
  2237.   cd_to(cdir);
  2238.   if (save_dos)
  2239.     setvect(save_dos, NULL);
  2240.   exit(0);
  2241. }
  2242.          
  2243. /* Interprets a code from the Ctrl-P Ctrl-P sequence, translating it
  2244.    into the correct string. */
  2245. char *interpret(char c)
  2246. {
  2247.   static char s[80];
  2248.  
  2249.   switch (c) {
  2250.     case '%':                   // Time left today
  2251.       sprintf(s, "%f", thisuser.extratime);
  2252.       break;
  2253.     case '$':                   // File points
  2254.       sprintf(s, "%d", thisuser.filepoints);
  2255.       break;
  2256.     case '*':                   // User reg num
  2257.       sprintf(s, "%d", thisuser.wwiv_regnum);
  2258.       break;
  2259.     case '-':                   // A** points
  2260.       sprintf(s, "%d", thisuser.ass_pts);
  2261.       break;
  2262.     case '!':                   // Built-in pause
  2263.       pausescr();
  2264.       break;
  2265.     case 'A':                   // User's age
  2266.       sprintf(s, "%d", thisuser.age);
  2267.       break;
  2268.     case 'B':                   // User's birthday
  2269.       sprintf(s, "%02.2d/%02.2d/%02.2d", thisuser.month, thisuser.day, thisuser.year);
  2270.       break;
  2271.     case 'b':                   // Minutes in bank
  2272.       sprintf(s, "%u", thisuser.banktime);
  2273.       break;
  2274.     case 'C':                   // User's city
  2275.       strcpy(s, thisuser.city);
  2276.       break;
  2277.     case 'c':                   // User's country
  2278.       strcpy(s, thisuser.country);
  2279.       break;
  2280.     case 'D':                   // Files downloaded
  2281.       sprintf(s, "%u", thisuser.downloaded);
  2282.       break;
  2283.     case 'd':                   // User's DSL
  2284.       sprintf(s, "%d", thisuser.dsl);
  2285.       break;
  2286.     case 'E':                   // E-mails sent
  2287.       sprintf(s, "%u", thisuser.emailsent);
  2288.       break;
  2289.     case 'F':
  2290.       sprintf(s, "%u", thisuser.feedbacksent);
  2291.       break;
  2292.     case 'f':                   // First time user called
  2293.       strcpy(s, thisuser.firston);
  2294.       break;
  2295.     case 'G':                   // MessaGes read
  2296.       sprintf(s, "%lu", thisuser.msgread);
  2297.       break;
  2298.     case 'g':                   // Gold
  2299.       sprintf(s, "%f", thisuser.gold);
  2300.       break;
  2301.     case 'I':                   // User's call sIgn
  2302.       strcpy(s, thisuser.callsign);
  2303.       break;
  2304.     case 'i':                   // Illegal log-ons
  2305.       sprintf(s, "%u", thisuser.illegal);
  2306.       break;
  2307.     case 'K':                   // Kb uploaded
  2308.       sprintf(s, "%lu", thisuser.uk);
  2309.       break;
  2310.     case 'k':                   // Kb downloaded
  2311.       sprintf(s, "%lu", thisuser.dk);
  2312.       break;
  2313.     case 'L':                   // Last call
  2314.       strcpy(s, thisuser.laston);
  2315.       break;
  2316.     case 'l':                   // Number of logons
  2317.       sprintf(s, "%u", thisuser.logons);
  2318.       break;
  2319.     case 'M':                   // Mail waiting
  2320.       sprintf(s, "%d", thisuser.waiting);
  2321.       break;
  2322.     case 'm':                   // Messages posted
  2323.       sprintf(s, "%u", thisuser.msgpost);
  2324.       break;
  2325.     case 'N':                   // User's name
  2326.       strcpy(s, thisuser.name);
  2327.       break;
  2328.     case 'n':                   // Sysop's note
  2329.       strcpy(s, thisuser.note);
  2330.       break;
  2331.     case 'O':                   // Times on today
  2332.       sprintf(s, "%d", thisuser.ontoday);
  2333.       break;
  2334.     case 'o':                   // Time on today
  2335.       sprintf(s, "%f", thisuser.timeontoday);
  2336.       break;
  2337.     case 'p':                   // User's phone
  2338.       strcpy(s, thisuser.dataphone);
  2339.       break;
  2340.     case 'R':                   // User's real name
  2341.       strcpy(s, thisuser.realname);
  2342.       break;
  2343.     case 'r':                   // Last baud rate
  2344.       sprintf(s, "%d", thisuser.lastrate);
  2345.       break;
  2346.     case 'S':                   // User's SL
  2347.       sprintf(s, "%d", thisuser.sl);
  2348.       break;
  2349.     case 's':                   // User's street address
  2350.       strcpy(s, thisuser.street);
  2351.       break;
  2352.     case 'T':                   // User's sTate
  2353.       strcpy(s, thisuser.state);
  2354.       break;
  2355.     case 'U':                   // Files uploaded
  2356.       sprintf(s, "%u", thisuser.uploaded);
  2357.       break;
  2358.     case 'X':                   // User's sex
  2359.       sprintf(s, "%c", thisuser.sex);
  2360.       break;
  2361.     case 'Z':                   // User's zip code
  2362.       strcpy(s, thisuser.zipcode);
  2363.       break;
  2364.     default:
  2365.       return "";
  2366.   }
  2367.   return s;
  2368. }
  2369.  
  2370.