home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / CON_HI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-13  |  23.6 KB  |  795 lines

  1. #line 1 "CON_HI.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include "sbbs.h"
  6.  
  7. extern char question[128];
  8.  
  9. char *mnestr;
  10.  
  11. /****************************************************************************/
  12. /* Waits for remote or local user to input a CR terminated string. 'length' */
  13. /* is the maximum number of characters that getstr will allow the user to   */
  14. /* input into the string. 'mode' specifies upper case characters are echoed */
  15. /* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */
  16. /* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */
  17. /* ^N non-destructive BS, ^V center line. Valid keys are echoed.            */
  18. /****************************************************************************/
  19. int getstr(char *strout, int maxlen, long mode)
  20. {
  21.     int i,l,x,z;    /* i=current position, l=length, j=printed chars */
  22.                     /* x&z=misc */
  23.     uchar ch,str1[256],str2[256],ins=0,atr;
  24.  
  25. console&=~CON_UPARROW;
  26. sys_status&=~SS_ABORT;
  27. if(mode&K_LINE && useron.misc&ANSI && !(mode&K_NOECHO)) {
  28.     attr(color[clr_inputline]);
  29.     for(i=0;i<maxlen;i++)
  30.         outchar(SP);
  31.     bprintf("\x1b[%dD",maxlen); }
  32. if(wordwrap[0]) {
  33.     strcpy(str1,wordwrap);
  34.     wordwrap[0]=0; }
  35. else str1[0]=0;
  36. if(mode&K_EDIT)
  37.     strcat(str1,strout);
  38. if(strlen(str1)>maxlen)
  39.     str1[maxlen]=0;
  40. atr=curatr;
  41. if(!(mode&K_NOECHO)) {
  42.     if(mode&K_AUTODEL && str1[0]) {
  43.         i=(color[clr_inputline]&0x77)<<4;
  44.         i|=(color[clr_inputline]&0x77)>>4;
  45.         attr(i); }
  46.     rputs(str1);
  47.     if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && useron.misc&ANSI)
  48.         bputs("\x1b[K");  /* destroy to eol */ }
  49.  
  50. i=l=strlen(str1);
  51. if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) {
  52.     ch=getkey(mode|K_GETSTR);
  53.     attr(atr);
  54.     if(isprint(ch) || ch==0x7f) {
  55.         for(i=0;i<l;i++)
  56.             bputs("\b \b");
  57.         i=l=0; }
  58.     else {
  59.         for(i=0;i<l;i++)
  60.             outchar(BS);
  61.         rputs(str1);
  62.         i=l; }
  63.     if(ch!=SP && ch!=TAB)
  64.         ungetkey(ch); }
  65.  
  66. while(!(sys_status&SS_ABORT) && (ch=getkey(mode|K_GETSTR))!=CR && online) {
  67.     if(sys_status&SS_ABORT)
  68.         break;
  69.     if(ch==LF) /* Ctrl-J same as CR */
  70.         break;
  71.     if(!i && mode&K_UPRLWR && (ch==SP || ch==TAB))
  72.         continue;    /* ignore beginning white space if upper/lower */
  73.     if(mode&K_E71DETECT && ch==(CR|0x80) && l>1) {
  74.         if(strstr(str1,"ìì")) {
  75.             bputs("\r\n\r\nYou must set your terminal to NO PARITY, "
  76.                 "8 DATA BITS, and 1 STOP BIT (N-8-1).\7\r\n");
  77.             return(0); } }
  78.     switch(ch) {
  79.         case 1: /* Ctrl-A for ANSI */
  80.             if(!(mode&K_MSG) || useron.rest&FLAG('A') || i>maxlen-3)
  81.                 break;
  82.             if(ins) {
  83.                 if(l<maxlen)
  84.                     l++;
  85.                 for(x=l;x>i;x--)
  86.                     str1[x]=str1[x-1];
  87.                 rprintf("%.*s",l-i,str1+i);
  88.                 rprintf("\x1b[%dD",l-i);
  89.                 if(i==maxlen-1)
  90.                     ins=0; }
  91.             outchar(str1[i++]=1);
  92.             break;
  93.         case 2: /* Ctrl-B Beginning of Line */
  94.             if(useron.misc&ANSI && i && !(mode&K_NOECHO)) {
  95.                 bprintf("\x1b[%dD",i);
  96.                 i=0; }
  97.             break;
  98.         case 4: /* Ctrl-D Delete word right */
  99.             if(i<l) {
  100.                 x=i;
  101.                 while(x<l && str1[x]!=SP) {
  102.                     outchar(SP);
  103.                     x++; }
  104.                 while(x<l && str1[x]==SP) {
  105.                     outchar(SP);
  106.                     x++; }
  107.                 bprintf("\x1b[%dD",x-i);   /* move cursor back */
  108.                 z=i;
  109.                 while(z<l-(x-i))  {             /* move chars in string */
  110.                     outchar(str1[z]=str1[z+(x-i)]);
  111.                     z++; }
  112.                 while(z<l) {                    /* write over extra chars */
  113.                     outchar(SP);
  114.                     z++; }
  115.                 bprintf("\x1b[%dD",z-i);
  116.                 l-=x-i; }                       /* l=new length */
  117.             break;
  118.         case 5: /* Ctrl-E End of line */
  119.             if(useron.misc&ANSI && i<l) {
  120.                 bprintf("\x1b[%dC",l-i);  /* move cursor to eol */
  121.                 i=l; }
  122.             break;
  123.         case 6: /* Ctrl-F move cursor forewards */
  124.             if(i<l && (useron.misc&ANSI)) {
  125.                 bputs("\x1b[C");   /* move cursor right one */
  126.                 i++; }
  127.             break;
  128.         case 7:
  129.             if(!(mode&K_MSG))
  130.                 break;
  131.             if(useron.rest&FLAG('B')) {
  132.                 if (i+6<maxlen) {
  133.                     if(ins) {
  134.                         for(x=l+6;x>i;x--)
  135.                             str1[x]=str1[x-6];
  136.                         if(l+5<maxlen)
  137.                             l+=6;
  138.                         if(i==maxlen-1)
  139.                             ins=0; }
  140.                     str1[i++]='(';
  141.                     str1[i++]='b';
  142.                     str1[i++]='e';
  143.                     str1[i++]='e';
  144.                     str1[i++]='p';
  145.                     str1[i++]=')';
  146.                     if(!(mode&K_NOECHO))
  147.                         bputs("(beep)"); }
  148.                 if(ins)
  149.                     redrwstr(str1,i,l,0);
  150.                 break; }
  151.              if(ins) {
  152.                 if(l<maxlen)
  153.                     l++;
  154.                 for(x=l;x>i;x--)
  155.                     str1[x]=str1[x-1];
  156.                 if(i==maxlen-1)
  157.                     ins=0; }
  158.              if(i<maxlen) {
  159.                 str1[i++]=7;
  160.                 if(!(mode&K_NOECHO))
  161.                     outchar(7); }
  162.              break;
  163.         case 14:    /* Ctrl-N Next word */
  164.             if(i<l && (useron.misc&ANSI)) {
  165.                 x=i;
  166.                 while(str1[i]!=SP && i<l)
  167.                     i++;
  168.                 while(str1[i]==SP && i<l)
  169.                     i++;
  170.                 bprintf("\x1b[%dC",i-x); }
  171.             break;
  172.         case 0x1c:    /* Ctrl-\ Previous word */
  173.             if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
  174.                 x=i;
  175.                 while(str1[i-1]==SP && i)
  176.                     i--;
  177.                 while(str1[i-1]!=SP && i)
  178.                     i--;
  179.                 bprintf("\x1b[%dD",x-i); }
  180.             break;
  181.         case 18:    /* Ctrl-R Redraw Line */
  182.             if(!(mode&K_NOECHO))
  183.                 redrwstr(str1,i,l,0);
  184.             break;
  185.         case TAB:
  186.             if(!(i%TABSIZE)) {
  187.                 if(ins) {
  188.                     if(l<maxlen)
  189.                         l++;
  190.                     for(x=l;x>i;x--)
  191.                         str1[x]=str1[x-1];
  192.                     if(i==maxlen-1)
  193.                         ins=0; }
  194.                 str1[i++]=SP;
  195.                 if(!(mode&K_NOECHO))
  196.                     outchar(SP); }
  197.             while(i<maxlen && i%TABSIZE) {
  198.                 if(ins) {
  199.                     if(l<maxlen)
  200.                         l++;
  201.                     for(x=l;x>i;x--)
  202.                         str1[x]=str1[x-1];
  203.                     if(i==maxlen-1)
  204.                         ins=0; }
  205.                 str1[i++]=SP;
  206.                 if(!(mode&K_NOECHO))
  207.                     outchar(SP); }
  208.             if(ins && !(mode&K_NOECHO))
  209.                 redrwstr(str1,i,l,0);
  210.             break;
  211.         case BS:
  212.             if(!i)
  213.                 break;
  214.             i--;
  215.             l--;
  216.             if(i!=l) {              /* Deleting char in middle of line */
  217.                 outchar(BS);
  218.                 z=i;
  219.                 while(z<l)  {       /* move the characters in the line */
  220.                     outchar(str1[z]=str1[z+1]);
  221.                     z++; }
  222.                 outchar(SP);        /* write over the last char */
  223.                 bprintf("\x1b[%dD",(l-i)+1); }
  224.             else if(!(mode&K_NOECHO))
  225.                 bputs("\b \b");
  226.             break;
  227.         case 22:    /* Ctrl-V   Center line */
  228.             str1[l]=0;
  229.             l=bstrlen(str1);
  230.             if(!l) break;
  231.             for(x=0;x<(maxlen-l)/2;x++)
  232.                 str2[x]=SP;
  233.             str2[x]=0;
  234.             strcat(str2,str1);
  235.             strcpy(strout,str2);
  236.             l=strlen(strout);
  237.             if(mode&K_NOECHO)
  238.                 return(l);
  239.             if(mode&K_MSG)
  240.                 redrwstr(strout,i,l,K_MSG);
  241.             else {
  242.                 while(i--)
  243.                     bputs("\b");
  244.                 bputs(strout);
  245.                 if(mode&K_LINE)
  246.                     attr(LIGHTGRAY); }
  247.             CRLF;
  248.             return(l);
  249.         case 23:    /* Ctrl-W   Delete word left */
  250.             if(i<l) {
  251.                 x=i;                            /* x=original offset */
  252.                 while(i && str1[i-1]==SP) {
  253.                     outchar(BS);
  254.                     i--; }
  255.                 while(i && str1[i-1]!=SP) {
  256.                     outchar(BS);
  257.                     i--; }
  258.                 z=i;                            /* i=z=new offset */
  259.                 while(z<l-(x-i))  {             /* move chars in string */
  260.                     outchar(str1[z]=str1[z+(x-i)]);
  261.                     z++; }
  262.                 while(z<l) {                    /* write over extra chars */
  263.                     outchar(SP);
  264.                     z++; }
  265.                 bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
  266.                 l-=x-i; }                       /* l=new length */
  267.             else {
  268.                 while(i && str1[i-1]==SP) {
  269.                     i--;
  270.                     l--;
  271.                     if(!(mode&K_NOECHO))
  272.                         bputs("\b \b"); }
  273.                 while(i && str1[i-1]!=SP) {
  274.                     i--;
  275.                     l--;
  276.                     if(!(mode&K_NOECHO))
  277.                         bputs("\b \b"); } }
  278.             break;
  279.         case 24:    /* Ctrl-X   Delete entire line */
  280.             if(mode&K_NOECHO)
  281.                 l=0;
  282.             else {
  283.                 while(i<l) {
  284.                     outchar(SP);
  285.                     i++; }
  286.                 while(l) {
  287.                     l--;
  288.                     bputs("\b \b"); } }
  289.             i=0;
  290.             break;
  291.         case 25:    /* Ctrl-Y   Delete to end of line */
  292.             if(useron.misc&ANSI && !(mode&K_NOECHO)) {
  293.                 bputs("\x1b[K");
  294.                 l=i; }
  295.             break;
  296.         case 31:    /* Ctrl-Minus       Toggles Insert/Overwrite */
  297.             if(!(useron.misc&ANSI) || mode&K_NOECHO)
  298.                 break;
  299.             if(ins) {
  300.                 ins=0;
  301.                 redrwstr(str1,i,l,0); }
  302.             else if(i<l) {
  303.                 ins=1;
  304.                 bprintf("\x1b[s\x1b[%dC",79-lclwx());    /* save pos  */
  305.                 z=curatr;                                /* and got to EOL */
  306.                 attr(z|BLINK|HIGH);
  307.                 outchar('░');
  308.                 attr(z);
  309.                 bputs("\x1b[u"); }  /* restore pos */
  310.             break;
  311.         case 0x1e:  /* Ctrl-^ */
  312.             if(!(mode&K_EDIT))
  313.                 break;
  314.             if(i>l)
  315.                 l=i;
  316.             str1[l]=0;
  317.             strcpy(strout,str1);
  318.             if((stripattr(strout) || ins) && !(mode&K_NOECHO))
  319.                 redrwstr(strout,i,l,K_MSG);
  320.             if(mode&K_LINE && !(mode&K_NOECHO))
  321.                 attr(LIGHTGRAY);
  322.             console|=CON_UPARROW;
  323.             return(l);
  324.         case 0x1d:  /* Ctrl-]  Reverse Cursor Movement */
  325.             if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
  326.                 bputs("\x1b[D");   /* move cursor left one */
  327.                 i--; }
  328.             break;
  329.         case 0x7f:  /* Ctrl-BkSpc (DEL) Delete current char */
  330.             if(i==l)
  331.                 break;
  332.             l--;
  333.             z=i;
  334.             while(z<l)  {       /* move the characters in the line */
  335.                 outchar(str1[z]=str1[z+1]);
  336.                 z++; }
  337.             outchar(SP);        /* write over the last char */
  338.             bprintf("\x1b[%dD",(l-i)+1);
  339.             break;
  340.         default:
  341.             if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
  342.                 str1[i]=0;
  343.                 if(ch==SP && !(mode&K_CHAT)) { /* don't wrap a space */ 
  344.                     strcpy(strout,str1);       /* as last char */
  345.                     if(stripattr(strout) && !(mode&K_NOECHO))
  346.                         redrwstr(strout,i,l,K_MSG);
  347.                     if(!(mode&K_NOECHO))
  348.                         CRLF;
  349.                     return(i); }
  350.                 x=i-1;
  351.                 z=1;
  352.                 wordwrap[0]=ch;
  353.                 while(str1[x]!=SP && x)
  354.                     wordwrap[z++]=str1[x--];
  355.                 if(x<(maxlen/2)) {
  356.                     wordwrap[1]=0;  /* only wrap one character */
  357.                     strcpy(strout,str1);
  358.                     if(stripattr(strout) && !(mode&K_NOECHO))
  359.                         redrwstr(strout,i,l,K_MSG);
  360.                     if(!(mode&K_NOECHO))
  361.                         CRLF;
  362.                     return(i); }
  363.                 wordwrap[z]=0;
  364.                 if(!(mode&K_NOECHO))
  365.                     while(z--) {
  366.                         bputs("\b \b");
  367.                         i--; }
  368.                 strrev(wordwrap);
  369.                 str1[x]=0;
  370.                 strcpy(strout,str1);
  371.                 if(stripattr(strout) && !(mode&K_NOECHO))
  372.                     redrwstr(strout,i,x,mode);
  373.                 if(!(mode&K_NOECHO))
  374.                     CRLF;
  375.                 return(x); }
  376.             if(i<maxlen && ch>=SP) {
  377.                 if(mode&K_UPRLWR)
  378.                     if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
  379.                         || str1[i-1]=='.' || str1[i-1]=='_')))
  380.                         ch=toupper(ch);
  381.                     else
  382.                         ch=tolower(ch);
  383.                 if(ins) {
  384.                     if(l<maxlen)    /* l<maxlen */
  385.                         l++;
  386.                     for(x=l;x>i;x--)
  387.                         str1[x]=str1[x-1];
  388.                     rprintf("%.*s",l-i,str1+i);
  389.                     rprintf("\x1b[%dD",l-i);
  390.                     if(i==maxlen-1) {
  391.                         bputs("  \b\b");
  392.                         ins=0; } }
  393.                 str1[i++]=ch;
  394.                 if(!(mode&K_NOECHO))
  395.                     outchar(ch); } }
  396.     if(i>l)
  397.         l=i;
  398.     if(mode&K_CHAT && !l)
  399.         return(0); }
  400. if(!online)
  401.     return(0);
  402. if(i>l)
  403.     l=i;
  404. str1[l]=0;
  405. if(!(sys_status&SS_ABORT)) {
  406.     strcpy(strout,str1);
  407.     if((stripattr(strout) || ins) && !(mode&K_NOECHO))
  408.         redrwstr(strout,i,l,K_MSG); }
  409. else
  410.     l=0;
  411. if(mode&K_LINE && !(mode&K_NOECHO)) attr(LIGHTGRAY);
  412. if(!(mode&(K_NOCRLF|K_NOECHO))) {
  413.     outchar(CR);
  414.     if(!(mode&K_MSG && sys_status&SS_ABORT))
  415.         outchar(LF);
  416.     lncntr=0; }
  417. return(l);
  418. }
  419.  
  420. /****************************************************************************/
  421. /* Hot keyed number input routine.                                          */
  422. /* Returns a valid number between 1 and max, 0 if no number entered, or -1  */
  423. /* if the user hit 'Q' or ctrl-c                                            */
  424. /****************************************************************************/
  425. long getnum(ulong max)
  426. {
  427.     uchar ch,n=0;
  428.     long i=0;
  429.  
  430. while(online) {
  431.     ch=getkey(K_UPPER);
  432.     if(ch>0x7f)
  433.         continue;
  434.     if(ch=='Q') {
  435.         outchar('Q');
  436.         if(useron.misc&COLDKEYS)
  437.             ch=getkey(K_UPPER);
  438.         if(ch==BS) {
  439.             bputs("\b \b");
  440.             continue; }
  441.         CRLF;
  442.         lncntr=0;
  443.         return(-1); }
  444.     else if(sys_status&SS_ABORT) {
  445.         CRLF;
  446.         lncntr=0;
  447.         return(-1); }
  448.     else if(ch==CR) {
  449.         CRLF;
  450.         lncntr=0;
  451.         return(i); }
  452.     else if(ch==BS && n) {
  453.         bputs("\b \b");
  454.         i/=10;
  455.         n--; }
  456.     else if(isdigit(ch) && (i*10L)+(ch&0xf)<=max && (ch!='0' || n)) {
  457.         i*=10L;
  458.         n++;
  459.         i+=ch&0xf;
  460.         outchar(ch);
  461.         if(i*10L>max && !(useron.misc&COLDKEYS)) {
  462.             CRLF;
  463.             lncntr=0;
  464.             return(i); } } }
  465. return(0);
  466. }
  467.  
  468. /*****************************************************************************/
  469. /* Displays or erases [WAIT] message                                         */
  470. /*****************************************************************************/
  471. void waitforsysop(char on)
  472. {
  473.     static saveatr;
  474.     int i,j;
  475.  
  476. if(on) {
  477.     saveatr=curatr;
  478.     bputs(text[Wait]);
  479.     lclatr(LIGHTGRAY);
  480.     return; }
  481. j=bstrlen(text[Wait]);
  482. attr(saveatr);
  483. for(i=0;i<j;i++)
  484.     bputs("\b \b");
  485. }
  486.  
  487. /****************************************************************************/
  488. /* Returns 1 if a is a valid ctrl-a code, 0 if it isn't.                    */
  489. /****************************************************************************/
  490. char validattr(char a)
  491. {
  492.  
  493. switch(toupper(a)) {
  494.     case '-':   /* clear        */
  495.     case '_':   /* clear        */
  496.     case 'B':   /* blue     fg  */
  497.     case 'C':   /* cyan     fg  */
  498.     case 'G':   /* green    fg  */
  499.     case 'H':   /* high     fg  */
  500.     case 'I':   /* blink        */
  501.     case 'K':   /* black    fg  */
  502.     case 'L':   /* cls          */
  503.     case 'M':   /* magenta  fg  */
  504.     case 'N':   /* normal       */
  505.     case 'P':   /* pause        */
  506.     case 'R':   /* red      fg  */
  507.     case 'W':   /* white    fg  */
  508.     case 'Y':   /* yellow   fg  */
  509.     case '0':   /* black    bg  */
  510.     case '1':   /* red      bg  */
  511.     case '2':   /* green    bg  */
  512.     case '3':   /* brown    bg  */
  513.     case '4':   /* blue     bg  */
  514.     case '5':   /* magenta  bg  */
  515.     case '6':   /* cyan     bg  */
  516.     case '7':   /* white    bg  */
  517.         return(1); }
  518. return(0);
  519. }
  520.  
  521. /****************************************************************************/
  522. /* Strips invalid Ctrl-Ax sequences from str                                */
  523. /* Returns number of ^A's in line                                           */
  524. /****************************************************************************/
  525. char stripattr(char *strin)
  526. {
  527.     uchar str[256];
  528.     uchar a,c,d,e;
  529.  
  530. e=strlen(strin);
  531. for(a=c=d=0;c<e;c++) {
  532.     if(strin[c]==1) {
  533.         a++;
  534.         if(!validattr(strin[c+1])) {
  535.             c++;
  536.             continue; } }
  537.     str[d++]=strin[c]; }
  538. str[d]=0;
  539. strcpy(strin,str);
  540. return(a);
  541. }
  542.  
  543. /****************************************************************************/
  544. /* Redraws str using i as current cursor position and l as length           */
  545. /****************************************************************************/
  546. void redrwstr(char *strin, int i, int l, char mode)
  547. {
  548.     char str[256],c;
  549.  
  550. sprintf(str,"%-*.*s",l,l,strin);
  551. c=i;
  552. while(c--)
  553.     outchar(BS);
  554. if(mode&K_MSG)
  555.     bputs(str);
  556. else
  557.     rputs(str);
  558. if(useron.misc&ANSI) {
  559.     bputs("\x1b[K");
  560.     if(i<l)
  561.         bprintf("\x1b[%dD",l-i); }
  562. else {
  563.     while(c<79) { /* clear to end of line */
  564.         outchar(SP);
  565.         c++; }
  566.     while(c>l) { /* back space to end of string */
  567.         outchar(BS);
  568.         c--; } }
  569. }
  570.  
  571. /****************************************************************************/
  572. /* Outputs a string highlighting characters preceeded by a tilde            */
  573. /****************************************************************************/
  574. void mnemonics(char *str)
  575. {
  576.     char *ctrl_a_codes;
  577.     long l;
  578.  
  579. if(!strchr(str,'~')) {
  580.     mnestr=str;
  581.     bputs(str);
  582.     return; }
  583. ctrl_a_codes=strchr(str,1);
  584. if(!ctrl_a_codes) {
  585.     if(str[0]=='@' && str[strlen(str)-1]=='@' && !strchr(str,SP)) {
  586.         mnestr=str;
  587.         bputs(str);
  588.         return; }
  589.     attr(color[clr_mnelow]); }
  590. l=0L;
  591. while(str[l]) {
  592.     if(str[l]=='~' && str[l+1]) {
  593.         if(!(useron.misc&ANSI))
  594.             outchar('(');
  595.         l++;
  596.         if(!ctrl_a_codes)
  597.             attr(color[clr_mnehigh]);
  598.         outchar(str[l]);
  599.         l++;
  600.         if(!(useron.misc&ANSI))
  601.             outchar(')');
  602.         if(!ctrl_a_codes)
  603.             attr(color[clr_mnelow]); }
  604.     else {
  605.         if(str[l]==1) {             /* ctrl-a */
  606.             ctrl_a(str[++l]);       /* skip the ctrl-a */
  607.             l++; }                  /* skip the attribute code */
  608.         else
  609.             outchar(str[l++]); } }
  610. if(!ctrl_a_codes)
  611.     attr(color[clr_mnecmd]);
  612. }
  613.  
  614. /****************************************************************************/
  615. /* Prompts user for Y or N (yes or no) and CR is interpreted as a Y         */
  616. /* Returns 1 for Y or 0 for N                                               */
  617. /* Called from quite a few places                                           */
  618. /****************************************************************************/
  619. char yesno(char *str)
  620. {
  621.     char ch;
  622.  
  623. strcpy(question,str);
  624. SYNC;
  625. if(useron.misc&WIP) {
  626.     strip_ctrl(question);
  627.     menu("YESNO"); }
  628. else
  629.     bprintf(text[YesNoQuestion],str);
  630. while(online) {
  631.     if(sys_status&SS_ABORT)
  632.         ch=text[YN][1];
  633.     else
  634.         ch=getkey(K_UPPER|K_COLD);
  635.     if(ch==text[YN][0] || ch==CR) {
  636.         if(bputs(text[Yes]))
  637.             CRLF;
  638.         lncntr=0;
  639.         return(1); }
  640.     if(ch==text[YN][1]) {
  641.         if(bputs(text[No]))
  642.             CRLF;
  643.         lncntr=0;
  644.         return(0); } }
  645. return(1);
  646. }
  647.  
  648. /****************************************************************************/
  649. /* Prompts user for N or Y (no or yes) and CR is interpreted as a N         */
  650. /* Returns 1 for N or 0 for Y                                               */
  651. /* Called from quite a few places                                           */
  652. /****************************************************************************/
  653. char noyes(char *str)
  654. {
  655.     char ch;
  656.  
  657. strcpy(question,str);
  658. SYNC;
  659. if(useron.misc&WIP) {
  660.     strip_ctrl(question);
  661.     menu("NOYES"); }
  662. else
  663.     bprintf(text[NoYesQuestion],str);
  664. while(online) {
  665.     if(sys_status&SS_ABORT)
  666.         ch=text[YN][1];
  667.     else
  668.         ch=getkey(K_UPPER|K_COLD);
  669.     if(ch==text[YN][1] || ch==CR) {
  670.         if(bputs(text[No]))
  671.             CRLF;
  672.         lncntr=0;
  673.         return(1); }
  674.     if(ch==text[YN][0]) {
  675.         if(bputs(text[Yes]))
  676.             CRLF;
  677.         lncntr=0;
  678.         return(0); } }
  679. return(1);
  680. }
  681.  
  682. /****************************************************************************/
  683. /* Waits for remote or local user to hit a key that is contained inside str.*/
  684. /* 'str' should contain uppercase characters only. When a valid key is hit, */
  685. /* it is echoed (upper case) and is the return value.                       */
  686. /* Called from quite a few functions                                        */
  687. /****************************************************************************/
  688. long getkeys(char *str, ulong max)
  689. {
  690.     uchar ch,n=0,c;
  691.     ulong i=0;
  692.  
  693. strupr(str);
  694. while(online) {
  695.     ch=getkey(K_UPPER);
  696.     if(max && ch>0x7f)  /* extended ascii chars are digits to isdigit() */
  697.         continue;
  698.     if(sys_status&SS_ABORT) {   /* return -1 if Ctrl-C hit */
  699.         attr(LIGHTGRAY);
  700.         CRLF;
  701.         lncntr=0;
  702.         return(-1); }
  703.     if(ch && !n && (strchr(str,ch))) {  /* return character if in string */
  704.         outchar(ch);
  705.         if(useron.misc&COLDKEYS && ch>SP) {
  706.             while(online && !(sys_status&SS_ABORT)) {
  707.                 c=getkey(0);
  708.                 if(c==CR || c==BS)
  709.                     break; }
  710.             if(sys_status&SS_ABORT) {
  711.                 CRLF;
  712.                 return(-1); }
  713.             if(c==BS) {
  714.                 bputs("\b \b");
  715.                 continue; } }
  716.         attr(LIGHTGRAY);
  717.         CRLF;
  718.         lncntr=0;
  719.         return(ch); }
  720.     if(ch==CR && max) {             /* return 0 if no number */
  721.         attr(LIGHTGRAY);
  722.         CRLF;
  723.         lncntr=0;
  724.         if(n)
  725.             return(i|0x80000000L);         /* return number plus high bit */
  726.         return(0); }
  727.     if(ch==BS && n) {
  728.         bputs("\b \b");
  729.         i/=10;
  730.         n--; }
  731.     else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
  732.         i*=10;
  733.         n++;
  734.         i+=ch&0xf;
  735.         outchar(ch);
  736.         if(i*10>max && !(useron.misc&COLDKEYS)) {
  737.             attr(LIGHTGRAY);
  738.             CRLF;
  739.             lncntr=0;
  740.             return(i|0x80000000L); } } }
  741. return(-1);
  742. }
  743.  
  744. void center(char *str)
  745. {
  746.      int i,j;
  747.  
  748. j=bstrlen(str);
  749. for(i=0;i<(80-j)/2;i++)
  750.     outchar(SP);
  751. bputs(str);
  752. CRLF;
  753. }
  754.  
  755.  
  756. int uselect(int add, int n, char *title, char *item, char *ar)
  757. {
  758.     static uint total,num[500];
  759.     char str[128];
  760.     int i,t;
  761.  
  762. if(add) {
  763.     if(ar && !chk_ar(ar,useron))
  764.         return(0);
  765.     if(!total)
  766.         bprintf(text[SelectItemHdr],title);
  767.     num[total++]=n;
  768.     bprintf(text[SelectItemFmt],total,item);
  769.     return(0); }
  770.  
  771. if(!total)
  772.     return(-1);
  773.  
  774. for(i=0;i<total;i++)
  775.     if(num[i]==n)
  776.         break;
  777. if(i==total)
  778.     i=0;
  779. sprintf(str,text[SelectItemWhich],i+1);
  780. mnemonics(str);
  781. i=getnum(total);
  782. t=total;
  783. total=0;
  784. if(i<0)
  785.     return(-1);
  786. if(!i) {                    /* User hit ENTER, use default */
  787.     for(i=0;i<t;i++)
  788.         if(num[i]==n)
  789.             return(num[i]);
  790.     if(n<t)
  791.         return(num[n]);
  792.     return(-1); }
  793. return(num[i-1]);
  794. }
  795.