home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / W / WWIVSOR.ZIP / BBSOVL2.C < prev    next >
Text File  |  1995-04-25  |  29KB  |  1,064 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. /****************************************************************************/
  20.  
  21. /*
  22.  * makewindow makes a "shadowized" window with the upper-left hand corner at
  23.  * (x,y), and the lower-right corner at (x+xlen,y+ylen).
  24.  */
  25.  
  26. void makewindow(int x, int y, int xlen, int ylen)
  27. {
  28.   int i,xx,yy;
  29.   unsigned char s[81];
  30.  
  31.   if (xlen>80)
  32.     xlen=80;
  33.   if (ylen>(screenbottom+1-topline))
  34.     ylen=(screenbottom+1-topline);
  35.   if ((x+xlen)>80)
  36.     x=80-xlen;
  37.   if ((y+ylen)>screenbottom+1)
  38.     y=screenbottom+1-ylen;
  39.  
  40.   xx=WhereX();
  41.   yy=WhereY();
  42.   for (i=1; i<xlen-1; i++)
  43.     s[i]=196;
  44.   s[0]=218;
  45.   s[xlen-1]=191;
  46.   s[xlen]=0;
  47.   movecsr(x,y);
  48.   outs(s);
  49.   s[0]=192;
  50.   s[xlen-1]=217;
  51.   movecsr(x,y+ylen-1);
  52.   outs(s);
  53.   for (i=1; i<xlen-1; i++)
  54.     s[i]=32;
  55.   s[0]=179;
  56.   s[xlen-1]=179;
  57.   for (i=1; i<ylen-1; i++) {
  58.     movecsr(x,i+y);
  59.     outs(s);
  60.   }
  61.   for (i=0; i<xlen; i++)
  62.     set_attr_xy(x+1+i, y+ylen, 0x08);
  63.   for (i=0; i<ylen; i++)
  64.     set_attr_xy(x+xlen,y+1+i, 0x08);
  65.   movecsr(xx,yy);
  66. }
  67.  
  68. /****************************************************************************/
  69.  
  70. /*
  71.  * Edits a string, doing local screen I/O only.
  72.  */
  73.  
  74. void editline(unsigned char *s, int len, int status, int *returncode, unsigned char *ss)
  75. {
  76.   int i,oldatr,cx,cy,pos,ch,done,insert,i1;
  77.  
  78.   oldatr=curatr;
  79.   cx=WhereX();
  80.   cy=WhereY();
  81.   for (i=strlen(s); i<len; i++)
  82.     s[i]=32;
  83.   s[len]=0;
  84.   curatr=sysinfo.editline_color;
  85.   outs(s);
  86.   movecsr(cx,cy);
  87.   done=0;
  88.   pos=0;
  89.   insert=0;
  90.   do {
  91.     ch=getchd();
  92.     if (ch==0) {
  93.       ch=getchd();
  94.       switch (ch) {
  95.         case 59:
  96.           done=1;
  97.           *returncode=DONE;
  98.           break;
  99.         case 71: pos=0; movecsr(cx,cy); break;
  100.         case 79: pos=len; movecsr(cx+pos,cy); break;
  101.         case 77: if (pos<len) {
  102.             pos++;
  103.             movecsr(cx+pos,cy);
  104.           }
  105.           break;
  106.         case 75: if (pos>0) {
  107.             pos--;
  108.             movecsr(cx+pos,cy);
  109.           }
  110.           break;
  111.         case 72:
  112.         case 15:
  113.           done=1;
  114.           *returncode=PREV;
  115.           break;
  116.         case 80:
  117.           done=1;
  118.           *returncode=NEXT;
  119.           break;
  120.         case 82:
  121.           if (status!=SET) {
  122.             if (insert)
  123.               insert=0;
  124.             else
  125.               insert=1;
  126.           }
  127.           break;
  128.         case 83:
  129.           if (status!=SET) {
  130.             for (i=pos; i<len; i++)
  131.               s[i]=s[i+1];
  132.             s[len-1]=32;
  133.             movecsr(cx,cy);
  134.             outs(s);
  135.             movecsr(cx+pos,cy);
  136.           }
  137.           break;
  138.       }
  139.     } else {
  140.       if (ch>31) {
  141.         if (status==UPPER_ONLY)
  142.           ch=upcase(ch);
  143.         if (status==SET) {
  144.           ch=upcase(ch);
  145.           if (ch!=' ') {
  146.             i1=1;
  147.             for (i=0; i<len; i++)
  148.               if ((ch==ss[i]) && (i1)) {
  149.                 i1=0;
  150.                 pos=i;
  151.                 movecsr(cx+pos,cy);
  152.                 if (s[pos]==' ')
  153.                   ch=ss[pos];
  154.                 else
  155.                   ch=' ';
  156.               }
  157.             if (i1)
  158.               ch=ss[pos];
  159.           }
  160.         }
  161.         if ((pos<len)&&((status==ALL) || (status==UPPER_ONLY) || (status==SET) ||
  162.             ((status==NUM_ONLY) && (((ch>='0') && (ch<='9')) || (ch==' '))))) {
  163.           if (insert) {
  164.             for (i=len-1; i>pos; i--)
  165.               s[i]=s[i-1];
  166.             s[pos++]=ch;
  167.             movecsr(cx,cy);
  168.             outs(s);
  169.             movecsr(cx+pos,cy);
  170.           } else {
  171.             s[pos++]=ch;
  172.             out1ch(ch);
  173.           }
  174.         }
  175.       } else {
  176.         ch=ch;
  177.         switch(ch) {
  178.           case 13:
  179.           case 9:
  180.             done=1;
  181.             *returncode=NEXT;
  182.             break;
  183.           case 27:
  184.             done=1;
  185.             *returncode=ABORTED;
  186.             break;
  187.           case 8:
  188.             if (pos>0) {
  189.               if (insert) {
  190.                 for (i=pos-1; i<len; i++)
  191.                   s[i]=s[i+1];
  192.                 s[len-1]=32;
  193.                 pos--;
  194.                 movecsr(cx,cy);
  195.                 outs(s);
  196.                 movecsr(cx+pos,cy);
  197.               } else {
  198.                 pos--;
  199.                 movecsr(cx+pos,cy);
  200.               }
  201.             }
  202.             break;
  203.         }
  204.       }
  205.     }
  206.   } while (done==0);
  207.   movecsr(cx,cy);
  208.   curatr=oldatr;
  209.   outs(s);
  210.   movecsr(cx,cy);
  211. }
  212.  
  213. /****************************************************************************/
  214.  
  215. /*
  216.  * Allows local-only editing of some of the user data in a shadowized
  217.  * window.
  218.  */
  219.  
  220. #define utoa(s,v,r) ultoa((unsigned long)(s),v,r)
  221. void val_cur_user(void)
  222. {
  223.   char sl[4],dsl[4],exempt[4],sysopsub[4],ar[17],dar[17],restrict[17],
  224.        rst[17],tl[81],uk[8],dk[8],up[6],down[6],posts[6],banktime[6],
  225.        gold[6],ass[6],logons[6];
  226.   int cp,i,done,rc,wx,wy;
  227.  
  228.   pr_Wait(1);
  229.   savescreen(&screensave);
  230. #ifdef RIPDRIVE
  231.   rd_coff();
  232. #endif
  233.   curatr=sysinfo.f1_color;
  234.   wx=5;
  235.   wy=3;
  236.   makewindow(wx,wy,70,14);
  237.   sprintf(tl,"ā”œ%sā”¤", charstr(70-wx+3,'ā”€'));
  238.   movecsr(wx,wy+4);  outs(tl);
  239.   movecsr(wx,wy+7);  outs(tl);
  240.   movecsr(wx,wy+11); outs(tl);
  241.   utoa(thisuser.sl,sl,10);
  242.   utoa(thisuser.dsl,dsl,10);
  243.   utoa(thisuser.exempt,exempt,10);
  244.   if (*qsc>999)
  245.     *qsc=999;
  246.   utoa(*qsc,sysopsub,10);
  247.   ultoa((unsigned long)thisuser.uk,uk,10);
  248.   ultoa((unsigned long)thisuser.dk,dk,10);
  249.   utoa(thisuser.uploaded,up,10);
  250.   utoa(thisuser.downloaded,down,10);
  251.   utoa(thisuser.msgpost,posts,10);
  252.   utoa(thisuser.banktime,banktime,10);
  253.   utoa(thisuser.logons,logons,10);
  254.   utoa(thisuser.ass_pts,ass,10);
  255.   gcvt((float)thisuser.gold,5,gold);
  256.   strcpy(rst,restrict_string);
  257.   for (i=0; i<=15; i++) {
  258.     if (thisuser.ar & (1 << i))
  259.       ar[i]='A'+i;
  260.     else
  261.       ar[i]=32;
  262.     if (thisuser.dar & (1 << i))
  263.       dar[i]='A'+i;
  264.     else
  265.       dar[i]=32;
  266.     if (thisuser.restrict & (1 << i))
  267.       restrict[i]=rst[i];
  268.     else
  269.       restrict[i]=32;
  270.   }
  271.   dar[16]=0;
  272.   ar[16]=0;
  273.   restrict[16]=0;
  274.   cp=0;
  275.   done=0;
  276.   movecsr(wx+2,wy+1); sprintf(tl,get_stringx(1,77),sl); outs(tl);
  277.   movecsr(wx+36,wy+1); sprintf(tl,get_stringx(1,78),ar); outs(tl);
  278.   movecsr(wx+2,wy+2); sprintf(tl,get_stringx(1,79),dsl); outs(tl);
  279.   movecsr(wx+36,wy+2); sprintf(tl,get_stringx(1,80),dar); outs(tl);
  280.   movecsr(wx+2,wy+3); sprintf(tl,get_stringx(1,81),exempt); outs(tl);
  281.   movecsr(wx+36,wy+3); sprintf(tl,get_stringx(1,82),restrict); outs(tl);
  282.   movecsr(wx+2,wy+5); sprintf(tl,get_stringx(1,83),sysopsub); outs(tl);
  283.   movecsr(wx+36,wy+5); sprintf(tl,get_stringx(1,103),banktime); outs(tl);
  284.   movecsr(wx+2,wy+6); sprintf(tl,get_stringx(1,110),ass); outs(tl);
  285.   movecsr(wx+36,wy+6); sprintf(tl,get_stringx(1,111),gold); outs(tl);
  286.   movecsr(wx+2,wy+8); sprintf(tl,get_stringx(1,104),uk); outs(tl);
  287.   movecsr(wx+36,wy+8); sprintf(tl,get_stringx(1,105),dk); outs(tl);
  288.   movecsr(wx+2,wy+9); sprintf(tl,get_stringx(1,106),up); outs(tl);
  289.   movecsr(wx+36,wy+9); sprintf(tl,get_stringx(1,107),down); outs(tl);
  290.   movecsr(wx+2,wy+10); sprintf(tl,get_stringx(1,108),posts); outs(tl);
  291.   movecsr(wx+36,wy+10); sprintf(tl,get_stringx(1,109),logons); outs(tl);
  292.   movecsr(wx+2,wy+12); sprintf(tl,get_stringx(1,84),thisuser.note); outs(tl);
  293. #ifdef RIPDRIVE
  294.   rd_con();
  295. #endif
  296.   while (done==0) {
  297.     switch(cp) {
  298.       case 0:
  299.         movecsr(wx+22,wy+1);
  300.         editline(sl,3,NUM_ONLY,&rc,"");
  301.         thisuser.sl=(char) atoi(sl);
  302.         utoa(thisuser.sl,sl,10);
  303.         sprintf(tl,"%-3s",sl); outs(tl);
  304.         break;
  305.       case 1:
  306.         movecsr(wx+50,wy+1);
  307.         editline(ar,16,SET,&rc,"ABCDEFGHIJKLMNOP ");
  308.         thisuser.ar=0;
  309.         for (i=0; i<=15; i++)
  310.           if (ar[i]!=32)
  311.             thisuser.ar |= (1 << i);
  312.         break;
  313.       case 2:
  314.         movecsr(wx+22,wy+2);
  315.         editline(dsl,3,NUM_ONLY,&rc,"");
  316.         thisuser.dsl=(char) atoi(dsl);
  317.         utoa(thisuser.dsl,dsl,10);
  318.         sprintf(tl,"%-3s",dsl); outs(tl);
  319.         break;
  320.       case 3:
  321.         movecsr(wx+50,wy+2);
  322.         editline(dar,16,SET,&rc,"ABCDEFGHIJKLMNOP ");
  323.         thisuser.dar=0;
  324.         for (i=0; i<=15; i++)
  325.           if (dar[i]!=32)
  326.             thisuser.dar |= (1 << i);
  327.         break;
  328.       case 4:
  329.         movecsr(wx+22,wy+3);
  330.         editline(exempt,3,NUM_ONLY,&rc,"");
  331.         thisuser.exempt=(char) atoi(exempt);
  332.         utoa(thisuser.exempt,exempt,10);
  333.         sprintf(tl,"%-3s",exempt); outs(tl);
  334.         break;
  335.       case 5:
  336.         movecsr(wx+50,wy+3);
  337.         editline(restrict,16,SET,&rc,rst);
  338.         thisuser.restrict=0;
  339.         for (i=0; i<=15; i++)
  340.           if (restrict[i]!=32)
  341.             thisuser.restrict |= (1 << i);
  342.         break;
  343.       case 6:
  344.         movecsr(wx+14,wy+5);
  345.         editline(sysopsub,3,NUM_ONLY,&rc,"");
  346.         *qsc= atoi(sysopsub);
  347.         utoa(*qsc,sysopsub,10);
  348.         sprintf(tl,"%-3s",sysopsub); outs(tl);
  349.         break;
  350.       case 7:
  351.         movecsr(wx+49,wy+5);
  352.         editline(banktime,5,NUM_ONLY,&rc,"");
  353.         thisuser.banktime=(unsigned int)atoi(banktime);
  354.         utoa(thisuser.banktime,banktime,10);
  355.         sprintf(tl,"%-5s",banktime); outs(tl);
  356.         break;
  357.       case 8:
  358.         movecsr(wx+14,wy+6);
  359.         editline(ass,5,NUM_ONLY,&rc,"");
  360.         thisuser.ass_pts=(unsigned int)atoi(ass);
  361.         utoa(thisuser.ass_pts,ass,10);
  362.         sprintf(tl,"%-5s",ass); outs(tl);
  363.         break;
  364.       case 9:
  365.         movecsr(wx+49,wy+6);
  366.         editline(gold,5,NUM_ONLY,&rc,"");
  367.         thisuser.gold=(float) atof(gold);
  368.         gcvt((float)thisuser.gold,5,gold);
  369.         sprintf(tl,"%-5s",gold); outs(tl);
  370.         break;
  371.       case 10:
  372.         movecsr(wx+20,wy+8);
  373.         editline(uk,7,NUM_ONLY,&rc,"");
  374.         thisuser.uk=(unsigned long) atol(uk);
  375.         ultoa((unsigned long)thisuser.uk,uk,10);
  376.         sprintf(tl,"%-7s",uk); outs(tl);
  377.         break;
  378.       case 11:
  379.         movecsr(wx+54,wy+8);
  380.         editline(dk,7,NUM_ONLY,&rc,"");
  381.         thisuser.dk=(unsigned long) atol(dk);
  382.         ultoa((unsigned long)thisuser.dk,dk,10);
  383.         sprintf(tl,"%-7s",dk); outs(tl);
  384.         break;
  385.       case 12:
  386.         movecsr(wx+20,wy+9);
  387.         editline(up,5,NUM_ONLY,&rc,"");
  388.         thisuser.uploaded=(unsigned int) atoi(up);
  389.         utoa(thisuser.uploaded,up,10);
  390.         sprintf(tl,"%-5s",up); outs(tl);
  391.         break;
  392.       case 13:
  393.         movecsr(wx+54,wy+9);
  394.         editline(down,5,NUM_ONLY,&rc,"");
  395.         thisuser.downloaded=(unsigned int) atoi(down);
  396.         utoa(thisuser.downloaded,down,10);
  397.         sprintf(tl,"%-5s",down); outs(tl);
  398.         break;
  399.       case 14:
  400.         movecsr(wx+20,wy+10);
  401.         editline(posts,5,NUM_ONLY,&rc,"");
  402.         thisuser.msgpost=(unsigned int) atoi(posts);
  403.         utoa(thisuser.msgpost,posts,10);
  404.         sprintf(tl,"%-5s",posts); outs(tl);
  405.         break;
  406.       case 15:
  407.         movecsr(wx+54,wy+10);
  408.         editline(logons,5,NUM_ONLY,&rc,"");
  409.         thisuser.logons=(unsigned int) atoi(logons);
  410.         utoa(thisuser.logons,logons,10);
  411.         sprintf(tl,"%-5s",logons); outs(tl);
  412.         break;
  413.       case 16:
  414.         movecsr(wx+8,wy+12);
  415.         editline(thisuser.note,sizeof(thisuser.note)-1,ALL,&rc,"");
  416.         trimstr(thisuser.note);
  417.         break;
  418.     }
  419.     switch(rc) {
  420.       case ABORTED: done=1; break;
  421.       case DONE: done=1; break;
  422.       case NEXT: cp=(cp+1) % 17; break;
  423.       case PREV: cp--; if (cp==-1) cp=16;  break;
  424.     }
  425.   }
  426.   restorescreen(&screensave);
  427.   reset_act_sl();
  428.   changedsl();
  429.   pr_Wait(0);
  430. }
  431.  
  432. /****************************************************************************/
  433.  
  434. /*
  435.  * Reads a char and attribute at screen pos x,y. Returns char located at
  436.  * that position in *c, and the attribute of that character in *a.
  437.  */
  438.  
  439. void read_char_xy(int x, int y, int *c, int *a)
  440. {
  441. #ifdef __OS2__
  442.   unsigned char s[3];
  443.   USHORT BufLen = sizeof(s);
  444.  
  445.   VioReadCellStr(s, &BufLen, y + topline, x, 0);
  446.   *c = (int) s[0];
  447.   *a = (int) s[1];
  448. #else
  449.   union REGS r;
  450.   int xx,yy;
  451.  
  452.   xx=WhereX(); yy=WhereY();
  453.   movecsr(x,y);
  454.   *c=0; *a=0;
  455.   r.h.ah = 0x08;
  456.   r.h.bh = 0;
  457.   int86(0x10, &r, &r);
  458.   *c=r.h.al;
  459.   *a=r.h.ah;
  460.   movecsr(xx,yy);
  461. #endif
  462. }
  463.  
  464. /****************************************************************************/
  465.  
  466. /*
  467.  * Sets screen attribute at screen pos x,y to attribute contained in a.
  468.  */
  469.  
  470. void set_attr_xy(int x, int y, int a)
  471. {
  472. #ifdef __OS2__
  473.   BYTE Attrib = a;
  474.  
  475.   VioWrtNAttr(&Attrib, 1, y + topline, x, 0);
  476. #else
  477.   union REGS r;
  478.   int xx,yy,oc,oa;
  479.  
  480.   xx=WhereX(); yy=WhereY();
  481.   read_char_xy(x,y,&oc,&oa);
  482.   movecsr(x,y);
  483.   r.h.ah=0x09;
  484.   r.h.al=(unsigned char)(oc);
  485.   r.h.bh=0;
  486.   r.h.bl=(unsigned char)(a);
  487.   r.x.cx=1;
  488.   int86(0x10, &r, &r);
  489.   movecsr(xx,yy);
  490. #endif
  491. }
  492.  
  493. /****************************************************************************/
  494.  
  495. /*
  496.  * Allows selection of a name to "chat as". Returns selected string in *s.
  497.  */
  498.  
  499. void select_chat_name(unsigned char *s)
  500. {
  501.   int un,rc;
  502.   userrec tu;
  503.  
  504.   pr_Wait(1);
  505.   savescreen(&screensave);
  506.   strcpy(s,syscfg.sysopname);
  507.   curatr=sysinfo.chat_select_color;
  508.   makewindow(20,5,43,3);
  509.   movecsr(22,6);
  510.   outs(get_string(1009));
  511.   movecsr(31,6);
  512.   curatr=sysinfo.editline_color;
  513.   outs(charstr(30,32));
  514.   movecsr(31,6);
  515.   editline(s,30,ALL,&rc,s);
  516.   if (rc!=ABORTED) {
  517.     trimstr(s);
  518.     un=(unsigned short) atoi(s);
  519.     if ((un>0) && (un<=syscfg.maxusers)) {
  520.       read_user(un,&tu);
  521.       strcpy(s,nam(&tu,un));
  522.     } else {
  523.       if (!s[0])
  524.         strcpy(s,syscfg.sysopname);
  525.     }
  526.   } else
  527.     strcpy(s,"");
  528.   restorescreen(&screensave);
  529.   pr_Wait(0);
  530. }
  531.  
  532. /****************************************************************************/
  533.  
  534. int x1,y1,x2,y2,cp0,cp1;
  535.  
  536. /*
  537.  * Allows two-way chatting until sysop aborts/exits chat.
  538.  */
  539.  
  540. #define MAXLEN 160
  541. #define MAXLINES_SIDE 13
  542.  
  543. static char (*side0)[MAXLEN], (*side1)[MAXLEN];
  544.  
  545. void two_way_chat(char *s, char *rollover, int maxlen, int crend, unsigned char *sysopname)
  546. {
  547.   char s2[100],temp1[100];
  548.   int side,cnt,cntr;
  549.   int i,i1,done,cm,begx;
  550.   char s1[255];
  551.   unsigned char ch;
  552.  
  553.   cm=chatting;
  554.   begx=WhereX();
  555.   if (rollover[0]!=0) {
  556.     if (charbufferpointer) {
  557.       strcpy(s1,rollover);
  558.       strcat(s1,&charbuffer[charbufferpointer]);
  559.       strcpy(&charbuffer[1],s1);
  560.       charbufferpointer=1;
  561.     } else {
  562.       strcpy(&charbuffer[1],rollover);
  563.       charbufferpointer=1;
  564.     }
  565.     rollover[0]=0;
  566.   }
  567.  
  568.   done=0;
  569.   side = 0;
  570.   do {
  571.     ch=getkey();
  572.       if (lastcon) {
  573.         if (WhereY() == 11) {
  574.           outstr("\x1b[12;1H");
  575.           ansic(3);
  576.           for (cnt=0;cnt<thisuser.screenchars;cnt++)
  577.             s2[cnt]=205;
  578.           sprintf(temp1,get_stringx(1,93),sysopname,nam(&thisuser,usernum));
  579.           cnt=(((thisuser.screenchars-strlen(stripcolors(temp1)))/2));
  580.           if (cnt)
  581.             strncpy(&s2[cnt-1],temp1,(strlen(temp1)));
  582.           else
  583.             strcpy(s2,charstr(205,thisuser.screenchars-1));
  584.           s2[thisuser.screenchars]=0;
  585.           outstr(s2);
  586.           s2[0]=0;
  587.           temp1[0]=0;
  588.           for (cntr=1;cntr<12;cntr++) {
  589.             sprintf(s2,"\x1b[%d;%dH",cntr,1);
  590.             outstr(s2);
  591.             if ((cntr>=0) && (cntr<5)) {
  592.               ansic(1);
  593.               outstr(side0[cntr+6]);
  594.             }
  595.             outstr("\x1b[K");
  596.             s2[0]=0;
  597.           }
  598.           sprintf(s2,"\x1b[%d;%dH",5,1);
  599.           outstr(s2);
  600.           s2[0]=0;
  601.         } else
  602.           if (WhereY()>11) {
  603.             x2=(WhereX()+1);
  604.             y2=(WhereY()+1);
  605.             sprintf(s2,"\x1b[%d;%dH",y1,x1);
  606.             outstr(s2);
  607.             s2[0]=0;
  608.           }
  609.         side = 0;
  610.         ansic(1);
  611.       } else {
  612.         if (WhereY()>=23) {
  613.           for (cntr=13;cntr<25;cntr++) {
  614.             sprintf(s2,"\x1b[%d;%dH",cntr,1);
  615.             outstr(s2);
  616.             if ((cntr>=13) && (cntr<17)) {
  617.               ansic(5);
  618.               outstr(side1[cntr-7]);
  619.             }
  620.             outstr("\x1b[K");
  621.             s2[0]=0;
  622.           }
  623.           sprintf(s2,"\x1b[%d;%dH",17,1);
  624.           outstr(s2);
  625.           s2[0]=0;
  626.         } else
  627.           if ((WhereY()<12) && (side==0)) {
  628.             x1=(WhereX()+1);
  629.             y1=(WhereY()+1);
  630.             sprintf(s2,"\x1b[%d;%dH",y2,x2);
  631.             outstr(s2);
  632.             s2[0]=0;
  633.           }
  634.         side=1;
  635.         ansic(5);
  636.       }
  637.       if (cm)
  638.         if (chatting==0)
  639.           ch=13;
  640.       if ((ch>=32)) {
  641.         if (side==0) {
  642.           if ((WhereX()<(thisuser.screenchars-1)) && (cp0<maxlen)) {
  643.             if (WhereY()<11) {
  644.               side0[WhereY()][cp0++]=ch;
  645.               outchr(ch);
  646.             } else {
  647.               side0[WhereY()][cp0++]=ch;
  648.               side0[WhereY()][cp0]=0;
  649.               for (cntr=0;cntr<12;cntr++) {
  650.                 sprintf(s2,"\x1b[%d;%dH",cntr,1);
  651.                 outstr(s2);
  652.                 if ((cntr>=0) && (cntr<6)) {
  653.                   ansic(1);
  654.                   outstr(side0[cntr+6]);
  655.                   y1=WhereY()+1;
  656.                   x1=WhereX()+1;
  657.                 }
  658.                 outstr("\x1b[K");
  659.                 s2[0]=0;
  660.               }
  661.               sprintf(s2,"\x1b[%d;%dH",y1,x1);
  662.               outstr(s2);
  663.               s2[0]=0;
  664.             }
  665.             if (WhereX()==(thisuser.screenchars-1))
  666.               done=1;
  667.           } else {
  668.             if (WhereX()>=(thisuser.screenchars-1))
  669.               done=1;
  670.           }
  671.         } else {
  672.           if ((WhereX()<(thisuser.screenchars-1)) && (cp1<maxlen)) {
  673.             if (WhereY()<23) {
  674.               side1[WhereY()-13][cp1++]=ch;
  675.               outchr(ch);
  676.             } else {
  677.               side1[WhereY()-13][cp1++]=ch;
  678.               side1[WhereY()-13][cp1]=0;
  679.               for (cntr=13;cntr<25;cntr++) {
  680.                 sprintf(s2,"\x1b[%d;%dH",cntr,1);
  681.                 outstr(s2);
  682.                 if ((cntr>=13) && (cntr<18)) {
  683.                   ansic(5);
  684.                   outstr(side1[cntr-7]);
  685.                   y2=WhereY()+1;
  686.                   x2=WhereX()+1;
  687.                 }
  688.                 outstr("\x1b[K");
  689.                 s2[0]=0;
  690.               }
  691.               sprintf(s2,"\x1b[%d;%dH",y2,x2);
  692.               outstr(s2);
  693.               s2[0]=0;
  694.             }
  695.             if (WhereX()==(thisuser.screenchars-1))
  696.               done=1;
  697.           } else {
  698.             if (WhereX()>=(thisuser.screenchars-1))
  699.               done=1;
  700.           }
  701.         }
  702.       } else
  703.         switch(ch) {
  704.           case 7:
  705.             if ((chatting) && (outcom))
  706.               outcomch(7);
  707.             break;
  708.           case 13: /* C/R */
  709.             if (side == 0)
  710.               side0[WhereY()][cp0]=0;
  711.             else
  712.               side1[WhereY()-13][cp1]=0;
  713.             done=1;
  714.             break;
  715.           case 8:  /* Backspace */
  716.             if (side==0) {
  717.               if (cp0) {
  718.                 if (side0[WhereY()][cp0-2]==3) {
  719.                   cp0-=2;
  720.                   ansic(0);
  721.                 } else
  722.                   if (side0[WhereY()][cp0-1]==8) {
  723.                     cp0--;
  724.                     outchr(32);
  725.                   } else {
  726.                     cp0--;
  727.                     backspace();
  728.                   }
  729.               }
  730.             } else
  731.               if (cp1) {
  732.                 if (side1[WhereY()-13][cp1-2]==3) {
  733.                   cp1-=2;
  734.                   ansic(0);
  735.                 } else
  736.                   if (side1[WhereY()-13][cp1-1]==8) {
  737.                     cp1--;
  738.                     outchr(32);
  739.                   } else {
  740.                     cp1--;
  741.                     backspace();
  742.                   }
  743.               }
  744.             break;
  745.           case 24: /* Ctrl-X */
  746.             while (WhereX()>begx) {
  747.               backspace();
  748.               if (side==0)
  749.                 cp0=0;
  750.               else
  751.                 cp1=0;
  752.             }
  753.             ansic(0);
  754.             break;
  755.           case 23: /* Ctrl-W */
  756.             if (side==0) {
  757.               if (cp0) {
  758.                 do {
  759.                   if (side0[WhereY()][cp0-2]==3) {
  760.                     cp0-=2;
  761.                     ansic(0);
  762.                   } else
  763.                     if (side0[WhereY()][cp0-1]==8) {
  764.                       cp0--;
  765.                       outchr(32);
  766.                     } else {
  767.                       cp0--;
  768.                       backspace();
  769.                     }
  770.                 } while ((cp0) && (side0[WhereY()][cp0-1]!=32) &&
  771.                        (side0[WhereY()][cp0-1]!=8) &&
  772.                        (side0[WhereY()][cp0-2]!=3));
  773.               }
  774.             } else {
  775.               if (cp1) {
  776.                 do {
  777.                   if (side1[WhereY()-13][cp1-2]==3) {
  778.                     cp1-=2;
  779.                     ansic(0);
  780.                   } else
  781.                     if (side1[WhereY()-13][cp1-1]==8) {
  782.                       cp1--;
  783.                       outchr(32);
  784.                     } else {
  785.                       cp1--;
  786.                       backspace();
  787.                     }
  788.                 } while ((cp1) && (side1[WhereY()-13][cp1-1]!=32) &&
  789.                        (side1[WhereY()-13][cp1-1]!=8) &&
  790.                        (side1[WhereY()-13][cp1-2]));
  791.               }
  792.             }
  793.             break;
  794.           case 14: /* Ctrl-N */
  795.             if (side == 0) {
  796.               if ((WhereX()) && (cp0<maxlen)) {
  797.                 outchr(8);
  798.                 side0[WhereY()][cp0++]=8;
  799.               }
  800.             } else
  801.               if ((WhereX()) && (cp1<maxlen)) {
  802.                 outchr(8);
  803.                 side1[WhereY()-13][cp1++]=8;
  804.               }
  805.             break;
  806.           case 16: /* Ctrl-P */
  807.             if (side==0) {
  808.               if (cp0<maxlen-1) {
  809.                 ch=getkey();
  810.                 if ((ch>='0') && (ch<='9')) {
  811.                   side0[WhereY()][cp0++]=3;
  812.                   side0[WhereY()][cp0++]=ch;
  813.                   ansic(ch-'0');
  814.                 }
  815.               }
  816.             } else {
  817.               if (cp1<maxlen-1) {
  818.                 ch=getkey();
  819.                 if ((ch>='0') && (ch<='9')) {
  820.                   side1[WhereY()-13][cp1++]=3;
  821.                   side1[WhereY()-13][cp1++]=ch;
  822.                   ansic(ch-'0');
  823.                 }
  824.               }
  825.             }
  826.             break;
  827.           case 9:  /* Tab */
  828.             if (side==0) {
  829.               i=5-(cp0 % 5);
  830.               if (((cp0+i)<maxlen) && ((WhereX()+i)<thisuser.screenchars)) {
  831.                 i=5-((WhereX()+1) % 5);
  832.                 for (i1=0; i1<i; i1++) {
  833.                   side0[WhereY()][cp0++]=32;
  834.                   outchr(32);
  835.                 }
  836.               }
  837.             } else {
  838.               i=5-(cp1 % 5);
  839.               if (((cp1+i)<maxlen) && ((WhereX()+i)<thisuser.screenchars)) {
  840.                 i=5-((WhereX()+1) % 5);
  841.                 for (i1=0; i1<i; i1++) {
  842.                   side1[WhereY()-13][cp1++]=32;
  843.                   outchr(32);
  844.                 }
  845.               }
  846.             }
  847.             break;
  848.         }
  849.   } while ((done==0) && (hangup==0));
  850.  
  851.   if (ch!=13) {
  852.     if (side==0) {
  853.       i=cp0-1;
  854.       while ((i>0) && (side0[WhereY()][i]!=32) &&
  855.              (side0[WhereY()][i]!=8) || (side0[WhereY()][i-1]==3))
  856.         i--;
  857.       if ((i>(WhereX()/2)) && (i!=(cp0-1))) {
  858.         i1=cp0-i-1;
  859.         for (i=0; i<i1; i++)
  860.           outchr(8);
  861.         for (i=0; i<i1; i++)
  862.           outchr(32);
  863.         for (i=0; i<i1; i++)
  864.           rollover[i]=side0[WhereY()][cp0-i1+i];
  865.         rollover[i1]=0;
  866.         cp0 -= i1;
  867.       }
  868.       side0[WhereY()][cp0]=0;
  869.     } else {
  870.       i=cp1-1;
  871.       while ((i>0) && (side1[WhereY()-13][i]!=32) &&
  872.              (side1[WhereY()-13][i]!=8) || (side1[WhereY()-13][i-1]==3))
  873.         i--;
  874.       if ((i>(WhereX()/2)) && (i!=(cp1-1))) {
  875.         i1=cp1-i-1;
  876.         for (i=0; i<i1; i++)
  877.           outchr(8);
  878.         for (i=0; i<i1; i++)
  879.           outchr(32);
  880.         for (i=0; i<i1; i++)
  881.           rollover[i]=side1[WhereY()-13][cp1-i1+i];
  882.         rollover[i1]=0;
  883.         cp1 -= i1;
  884.       }
  885.       side1[WhereY()-13][cp1]=0;
  886.     }
  887.   }
  888.   if ((crend) && (WhereY() != 11) && (WhereY()<23))
  889.     nl();
  890.   if (side==0)
  891.     cp0=0;
  892.   else
  893.     cp1=0;
  894.   s[0]=0;
  895. }
  896.  
  897. /****************************************************************************/
  898.  
  899. /*
  900.  * High-level chat function, calls two_way_chat() if appropriate, else
  901.  * uses normal TTY chat.
  902.  */
  903.  
  904. void chat1(char *chatline, int two_way)
  905. {
  906.   int tempdata, cnt, otag;
  907.   char cl[81],xl[81],s[161],s1[161],atr[81],s2[81],cc,sn[81];
  908.   int cf,oe;
  909.   double tc;
  910.  
  911.   select_chat_name(sn);
  912.   if (sn[0]==0)
  913.     return;
  914.  
  915.   otag=tagging;
  916.   tagging=0;
  917.  
  918.   chatcall=0;
  919.   if (two_way) {
  920.     write_inst(INST_LOC_CHAT2,0,INST_FLAGS_NONE);
  921.     chatting=2;
  922.   } else {
  923.     write_inst(INST_LOC_CHAT,0,INST_FLAGS_NONE);
  924.     chatting=1;
  925.   }
  926.   tc=timer();
  927.   cf=0;
  928.  
  929.   savel(cl,atr,xl,&cc);
  930.   s1[0]=0;
  931.  
  932.   oe=echo;
  933.   echo=1;
  934.   nln(2);
  935.   tempdata=topdata;
  936.   if (!okansi())
  937.     two_way=0;
  938.   if (modem_speed==300)
  939.     two_way=0;
  940.  
  941.   if (syscfg.sysconfig & sysconfig_two_color)
  942.     two_color=1;
  943.  
  944.   if (menu_on()) {
  945.     printmenu(314);
  946.     cleared = NEEDCLEAR;
  947.   }
  948.  
  949.   if (two_way) {
  950.     clrscrb();
  951.     cp0=0;
  952.     cp1=0;
  953.     if (defscreenbottom==24) {
  954.       topdata=0;
  955.       topscreen();
  956.     }
  957.     outstr("\x1b[2J");
  958.     x2=1;
  959.     y2=13;
  960.     outstr("\x1b[1;1H");
  961.     x1=WhereX();
  962.     y1=WhereY();
  963.     outstr("\x1b[12;1H");
  964.     ansic(3);
  965.     for (cnt=0;cnt<thisuser.screenchars;cnt++)
  966.       outchr(205);
  967.     sprintf(s,get_stringx(1,93),sn,nam(&thisuser,usernum));
  968.     cnt=((thisuser.screenchars-strlen(stripcolors(s)))/2);
  969.     sprintf(s1,"\x1b[12;%dH",cnt);
  970.     outstr(s1);
  971.     ansic(4);
  972.     outstr(s);
  973.     outstr("\x1b[1;1H");
  974.     s[0]=0;
  975.     s1[0]=0;
  976.     s2[0]=0;
  977.   }
  978.  
  979.   ansic(7);
  980.   outstr(sn);
  981.   pl(get_string(927));
  982.   nl();
  983.   strcpy(s1,chatline);
  984.  
  985.   if (two_way) {
  986.     side0 = malloca(MAXLEN*MAXLINES_SIDE);
  987.     side1 = malloca(MAXLEN*MAXLINES_SIDE);
  988.     if (!side0 || !side1)
  989.       two_way=0;
  990.   }
  991.  
  992.   do {
  993.     if (two_way)
  994.       two_way_chat(s,s1,MAXLEN,1,sn);
  995.     else
  996.       inli(s,s1,160,1);
  997.     if ((chat_file) && (!two_way)) {
  998.       if (cf==0) {
  999.         if (!two_way)
  1000.           outs(get_stringx(1,94));
  1001.         sprintf(s2,"%sCHAT.TXT",syscfg.gfilesdir);
  1002.         cf=sh_open(s2,O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  1003.         sh_lseek(cf,0L,SEEK_END);
  1004.         sprintf(s2,get_stringx(1,95),date(),times());
  1005.         sh_write(cf,(void *)s2,strlen(s2));
  1006.         strcpy(s2,get_stringx(1,96));
  1007.         sh_write(cf,(void *)s2,strlen(s2));
  1008.       }
  1009.       strcat(s,"\r\n");
  1010.       sh_write(cf,(void *)s,strlen(s));
  1011.     } else
  1012.       if (cf) {
  1013.         sh_close(cf);
  1014.         cf=0;
  1015.         if (!two_way)
  1016.           outs(get_stringx(1,97));
  1017.       }
  1018.     if (hangup)
  1019.       chatting=0;
  1020.   } while (chatting);
  1021.   if (chat_file) {
  1022.     sh_close(cf);
  1023.     chat_file=0;
  1024.   }
  1025.  
  1026.   if (side0) {
  1027.     bbsfree(side0);
  1028.     side0=NULL;
  1029.   }
  1030.   if (side1) {
  1031.     bbsfree(side1);
  1032.     side1=NULL;
  1033.   }
  1034.  
  1035.   ansic(0);
  1036.   two_color=0;
  1037.  
  1038.   if (two_way)
  1039.     outstr("\x1b[2J");
  1040.  
  1041.   nl();
  1042.   ansic(7);
  1043.   pl(get_string(928));
  1044.   nl();
  1045.   chatting=0;
  1046.   tc=timer()-tc;
  1047.   if (tc<0)
  1048.     tc += 86400.0;
  1049.   extratimecall += tc;
  1050.   topdata=tempdata;
  1051.   if (useron)
  1052.     topscreen();
  1053.   echo=oe;
  1054.   restorel(cl,atr,xl,&cc);
  1055.  
  1056.   tagging=otag;
  1057.   if (rip_on())
  1058.     comstr("|10//CLS^m\r ");
  1059.   if (okansi())
  1060.     outstr("\x1b[K");
  1061. }
  1062.  
  1063. /****************************************************************************/
  1064.