home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / UTIL / WWIVSOR / BBSUTL.C < prev    next >
C/C++ Source or Header  |  1996-12-01  |  21KB  |  870 lines

  1. /*****************************************************************************
  2.  
  3.                 WWIV Version 4
  4.                     Copyright (C) 1988-1995 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15. #include "vars.h"
  16.  
  17. #pragma hdrstop
  18.  
  19. #include <dir.h>
  20.  
  21. /****************************************************************************/
  22.  
  23. /*
  24.  * Attempts to allocate nbytes (+1) bytes on the heap, returns ptr to memory
  25.  * if successful.
  26.  */
  27.  
  28. void far *malloca(unsigned long nbytes)
  29. {
  30.   void *buf;
  31.   char s[160];
  32.  
  33.   buf=bbsmalloc(nbytes+1);
  34.   if (buf==NULL) {
  35.     nl();
  36.     npr(get_stringx(1,31),nbytes);
  37.     nl();
  38.     sprintf(s,get_stringx(1,32),nbytes);
  39.     sysoplog(s);
  40.   }
  41.   return(buf);
  42. }
  43.  
  44. /****************************************************************************/
  45.  
  46. static void stuff_in_num(char *s, char *fmt, int num)
  47. {
  48.   char temp[81];
  49.  
  50.   sprintf(temp, fmt, num);
  51.   strcat(s,temp);
  52. }
  53.  
  54. /*
  55.  * Replacable parameters:
  56.  *
  57.  *  Param     Description                       Example
  58.  *  ---------------------------------------------------------------------
  59.  *   %%       A single '%'                      "%"
  60.  *   %1-%5    Specified passed-in parameter
  61.  *   %B       Com port base address, in hex     "3f8"
  62.  *   %I       Com port irq, in decimal          "4"
  63.  *   %M       Modem baud rate                   "14400"
  64.  *   %S       Com port baud rate                "38400"
  65.  *   %P       Com port number                   "1"
  66.  *   %N       Instance number                   "1"
  67.  *   %T       Time remaining (min)              "30"
  68.  *   %C       chain.txt full pathname           "c:\wwiv\chain.txt"
  69.  *   %D       doorinfo full pathname            "c:\wwiv\dorinfo1.def"
  70.  *   %O       pcboard full pathname             "c:\wwiv\pcboard.sys"
  71.  *   %A       callinfo full pathname            "c:\wwiv\callinfo.bbs"
  72.  *   %R       door full pathname                "c:\wwiv\door.sys"
  73.  */
  74. void stuff_in(char *s, char *s1, char *f1, char *f2, char *f3, char *f4, char *f5)
  75. {
  76.   int r=0,w=0;
  77.   double d;
  78.  
  79.   while (s1[r]!=0) {
  80.     if (s1[r]=='%') {
  81.       ++r;
  82.       s[w]=0;
  83.       switch(upcase(s1[r])) {
  84.       /* used: %12345ABCDIMNOPRST */
  85.  
  86.       /* fixed strings */
  87.         case '%': strcat(s,"%s");                                       break;
  88.  
  89.       /* replacable parameters */
  90.         case '1': strcat(s,f1);                                         break;
  91.         case '2': strcat(s,f2);                                         break;
  92.         case '3': strcat(s,f3);                                         break;
  93.         case '4': strcat(s,f4);                                         break;
  94.         case '5': strcat(s,f5);                                         break;
  95.  
  96.       /* call-specific numbers */
  97.         case 'B': stuff_in_num(s, "%x", base);                          break;
  98.         case 'I': stuff_in_num(s, "%u", async_irq);                     break;
  99.         case 'M': stuff_in_num(s, "%u", modem_speed);                   break;
  100.         case 'P': stuff_in_num(s, "%u", incom?syscfgovr.primaryport:0); break;
  101.         case 'N': stuff_in_num(s, "%u", instance);                      break;
  102.         case 'S':
  103.           if ((com_speed==1) || (com_speed==49664))
  104.             strcat(s,"115200");
  105.           else
  106.             stuff_in_num(s, "%u", com_speed);
  107.           break;
  108.  
  109.         case 'T':
  110.           d=nsl();
  111.           if (d<0)
  112.             d += 24.0*3600.0;
  113.           stuff_in_num(s, "%u", (int)d/60);
  114.           break;
  115.  
  116.       /* chain.txt type filenames */
  117.         case 'C': create_filename(CHAINFILE_CHAIN, s+w);                break;
  118.         case 'D': create_filename(CHAINFILE_DORINFO, s+w);              break;
  119.         case 'O': create_filename(CHAINFILE_PCBOARD, s+w);              break;
  120.         case 'A': create_filename(CHAINFILE_CALLINFO, s+w);             break;
  121.         case 'R': create_filename(CHAINFILE_DOOR, s+w);                 break;
  122.  
  123.       }
  124.       w=strlen(s);
  125.       r++;
  126.     } else
  127.       s[w++]=s1[r++];
  128.   }
  129.   s[w]=0;
  130. }
  131.  
  132. /****************************************************************************/
  133.  
  134. void copy_line(char *s, char *b, long *ptr, long len)
  135. {
  136.   int i;
  137.   long l;
  138.  
  139.   if (*ptr>=len) {
  140.     s[0]=0;
  141.     return;
  142.   }
  143.   l=*ptr;
  144.   i=0;
  145.   while ((b[l]!='\r') && (b[l]!='\n') && (l<len)) {
  146.     s[i++]=b[l++];
  147.   }
  148.   s[i]=0;
  149.   if ((b[l]=='\r') && (l<len))
  150.     ++l;
  151.   if ((b[l]=='\n') && (l<len))
  152.     ++l;
  153.   *ptr=l;
  154. }
  155.  
  156. /****************************************************************************/
  157.  
  158. char *mmkey(int dl)
  159. {
  160.   static unsigned char cmd1[10],cmd2[81],ch;
  161.   int p,cp;
  162.  
  163.   do {
  164.     do {
  165.       ch=getkey();
  166.     } while ((((ch<' ') && (ch!=13)) || (ch>126)) && (hangup==0));
  167.     ch=upcase(ch);
  168.     outchr(ch);
  169.     if (ch==13)
  170.       cmd1[0]=0;
  171.     else
  172.       cmd1[0]=ch;
  173.     cmd1[1]=0;
  174.     p=0;
  175.     switch(dl) {
  176.  
  177.     case 1:
  178.       if (strchr(dtc,ch)!=NULL)
  179.         p=2;
  180.       else if (strchr(dcd,ch)!=NULL)
  181.         p=1;
  182.       break;
  183.     case 2:
  184.       if (strchr(odc,ch)!=NULL)
  185.         p=1;
  186.       break;
  187.     case 0:
  188.       if (strchr(tc,ch)!=NULL)
  189.         p=2;
  190.       else if (strchr(dc,ch)!=NULL)
  191.         p=1;
  192.       break;
  193.     }
  194.     if (p) {
  195.       cp=1;
  196.       do {
  197.         do {
  198.           ch=getkey();
  199.         } while ((((ch<' ') && (ch!=13) && (ch!=8)) || (ch>126)) && (hangup==0));
  200.         ch=upcase(ch);
  201.         if (ch==13) {
  202.           nl();
  203.           return(cmd1);
  204.         } else {
  205.           if (ch==8) {
  206.             backspace();
  207.             cmd1[--cp]=0;
  208.           } else {
  209.             cmd1[cp++]=ch;
  210.             cmd1[cp]=0;
  211.             outchr(ch);
  212.             if ((ch=='/') && (cmd1[0]=='/')) {
  213.               input(cmd2,50);
  214.               return(cmd2);
  215.             } else if (cp==p+1) {
  216.               nl();
  217.               return(cmd1);
  218.             }
  219.           }
  220.         }
  221.       } while (cp);
  222.     } else {
  223.       nl();
  224.       return(cmd1);
  225.     }
  226.   } while (hangup==0);
  227.   cmd1[0]=0;
  228.   return(cmd1);
  229. }
  230.  
  231. /****************************************************************************/
  232.  
  233. int inli2(char *s, char *rollover, int maxlen, int crend, int wb)
  234. {
  235.   int cp,i,i1,done,cm,begx;
  236.   char s1[255],s2[255],*ss;
  237.   unsigned char ch;
  238.  
  239.   cm=chatting;
  240.  
  241.   begx=WhereX();
  242.   if (rollover[0]!=0) {
  243.     ss=s2;
  244.     for (i=0; rollover[i]; i++) {
  245.       if ((rollover[i]==3) || (rollover[i]==15))
  246.         *ss++='P'-'@';
  247.       else
  248.         *ss++=rollover[i];
  249.  
  250.       /* Add a second ^P if we are working on RIP codes */
  251.       if (rollover[i]==15 && rollover[i+1]!=15 && rollover[i-1] !=15)
  252.         *ss++='P'-'@';
  253.     }
  254.     *ss=0;
  255.     if (charbufferpointer) {
  256.       strcpy(s1,s2);
  257.       strcat(s1,&charbuffer[charbufferpointer]);
  258.       strcpy(&charbuffer[1],s1);
  259.       charbufferpointer=1;
  260.     } else {
  261.       strcpy(&charbuffer[1],s2);
  262.       charbufferpointer=1;
  263.     }
  264.     rollover[0]=0;
  265.   }
  266.   cp=0;
  267.   done=0;
  268.   do {
  269.     ch=getkey();
  270.     if (two_color)
  271.       if (lastcon)
  272.     ansic(1);
  273.       else
  274.     ansic(0);
  275.     if (cm)
  276.       if (chatting==0)
  277.         ch=13;
  278.     if ((ch>=32)) {
  279.       if ((WhereX()<(thisuser.screenchars-1)) && (cp<maxlen)) {
  280.         s[cp++]=ch;
  281.         outchr(ch);
  282.         if (WhereX()==(thisuser.screenchars-1))
  283.           done=1;
  284.       } else {
  285.         if (WhereX()>=(thisuser.screenchars-1))
  286.           done=1;
  287.       }
  288.     } else
  289.         switch(ch) {
  290.       case 7:
  291.         if ((chatting) && (outcom))
  292.           outcomch(7);
  293.         break;
  294.           case 13: /* C/R */
  295.             s[cp]=0;
  296.             done=1;
  297.             break;
  298.           case 8:  /* Backspace */
  299.             if (cp) {
  300.               if (s[cp-2]==3) {
  301.                 cp-=2;
  302.                 ansic(0);
  303.               } else if (s[cp-2]==15) {
  304.                 for (i=strlen((char *)interpret(s[cp-1])); i>0; i--)
  305.                   backspace();
  306.                 cp-=2;
  307.                 if (s[cp-1]==15)
  308.                   cp--;
  309.               } else {
  310.                 if (s[cp-1]==8) {
  311.                   cp--;
  312.                   outchr(32);
  313.                 } else {
  314.                   cp--;
  315.                   backspace();
  316.                 }
  317.               }
  318.             } else
  319.               if (wb) {
  320.                 if (okansi()) {
  321.                   if (curdloads==1)
  322.                     outstr("\r\x1b[K");
  323.                   outstr("\x1b[1A");
  324.                 } else
  325.                   pl(get_string(1485));
  326.                 return(1);
  327.               }
  328.             break;
  329.           case 24: /* Ctrl-X */
  330.             while (WhereX()>begx) {
  331.               backspace();
  332.               cp=0;
  333.             }
  334.             ansic(0);
  335.             break;
  336.           case 23: /* Ctrl-W */
  337.             if (cp) {
  338.               do {
  339.                 if (s[cp-2]==3) {
  340.                   cp-=2;
  341.                   ansic(0);
  342.                 } else
  343.                   if (s[cp-1]==8) {
  344.                     cp--;
  345.                     outchr(32);
  346.                   } else {
  347.                     cp--;
  348.                     backspace();
  349.                   }
  350.               } while ((cp) && (s[cp-1]!=32) && (s[cp-1]!=8));
  351.             }
  352.             break;
  353.           case 14: /* Ctrl-N */
  354.             if ((WhereX()) && (cp<maxlen)) {
  355.               outchr(8);
  356.               s[cp++]=8;
  357.             }
  358.             break;
  359.           case 16: /* Ctrl-P */
  360.             if (cp<maxlen-1) {
  361.               ch=getkey();
  362.               if ((ch>='0') && (ch<='9')) {
  363.                 s[cp++]=3;
  364.                 s[cp++]=ch;
  365.                 ansic(ch-'0');
  366.               } else if ((ch==16) && (cp<maxlen-2)) {
  367.                 ch=getkey();
  368.  
  369.                 if (ch != 16) {     // RIP font style code
  370.                   s[cp++]=15;
  371.                   s[cp++]=15;
  372.                   s[cp++]=ch;
  373.                   outchr('\xf');
  374.                   outchr('\xf');
  375.                   outchr(ch);
  376.                 }
  377.               }
  378.             }
  379.             break;
  380.           case 9:  /* Tab */
  381.             i=5-(cp % 5);
  382.             if (((cp+i)<maxlen) && ((WhereX()+i)<thisuser.screenchars)) {
  383.               i=5-((WhereX()+1) % 5);
  384.               for (i1=0; i1<i; i1++) {
  385.                 s[cp++]=32;
  386.                 outchr(32);
  387.               }
  388.             }
  389.             break;
  390.         }
  391.   } while ((done==0) && (hangup==0));
  392.   if (ch!=13) {
  393.     i=cp-1;
  394.     while ((i>0) && (s[i]!=32) && (s[i]!=8))
  395.       i--;
  396.     if ((i>(WhereX()/2)) && (i!=(cp-1))) {
  397.       i1=cp-i-1;
  398.       for (i=0; i<i1; i++)
  399.         outchr(8);
  400.       for (i=0; i<i1; i++)
  401.         outchr(32);
  402.       for (i=0; i<i1; i++)
  403.         rollover[i]=s[cp-i1+i];
  404.       rollover[i1]=0;
  405.       cp -= i1;
  406.     }
  407.     s[cp++]=1;
  408.     s[cp]=0;
  409.   }
  410.   if (crend)
  411.     nl();
  412.   return(0);
  413. }
  414.  
  415. /****************************************************************************/
  416.  
  417. void inli(char *s, char *rollover, int maxlen, int crend)
  418. {
  419.   inli2(s,rollover,maxlen,crend,0);
  420. }
  421.  
  422. /****************************************************************************/
  423.  
  424. /*
  425.  * Returns 1 if current user has sysop access (permanent or temporary), else
  426.  * returns 0.
  427.  */
  428.  
  429. int so(void)
  430. {
  431.   if (actsl==255)
  432.     return(1);
  433.   else
  434.     return(0);
  435. }
  436.  
  437. /****************************************************************************/
  438.  
  439. /*
  440.  * Returns 1 if current user has co-sysop access (or better), else returns 0.
  441.  */
  442.  
  443. int cs(void)
  444. {
  445.   slrec ss;
  446.  
  447.   ss=syscfg.sl[actsl];
  448.   if (so())
  449.     return(1);
  450.   if (ss.ability & ability_cosysop)
  451.     return(1);
  452.   else
  453.     return(0);
  454. }
  455.  
  456. /****************************************************************************/
  457.  
  458. /*
  459.  * Returns 1 if current user has limited co-sysop access (or better), else
  460.  * returns 0.
  461.  */
  462.  
  463. int lcs(void)
  464. {
  465.   slrec ss;
  466.  
  467.   ss=syscfg.sl[actsl];
  468.   if (cs())
  469.     return(1);
  470.   if (ss.ability & ability_limited_cosysop) {
  471.     if (*qsc==999)
  472.       return(1);
  473.     if (*qsc==usub[cursub].subnum)
  474.       return(1);
  475.     else
  476.       return(0);
  477.   } else
  478.     return(0);
  479. }
  480.  
  481. /****************************************************************************/
  482.  
  483. /*
  484.  * Checks to see if user aborted whatever he/she was doing. Returns 1 in
  485.  * *next if control-N was hit, for zipping past messages quickly.
  486.  */
  487.  
  488. void checka(int *abort, int *next)
  489. {
  490.   char ch;
  491.  
  492.   while ((!empty()) && (!(*abort)) && (!hangup)) {
  493.     checkhangup();
  494.     ch=inkey();
  495.     if (!tagging || (thisuser.sysstatus & sysstatus_no_tag))
  496.       lines_listed=0;
  497.     switch(ch) {
  498.       case 14:
  499.         *next=1;
  500.       case 3:
  501.       case 32:
  502.       case 24:
  503.         *abort=1;
  504.         break;
  505.       case 'P':
  506.       case 'p':
  507.       case 19:
  508.         ch=getkey();
  509.         break;
  510.     }
  511.   }
  512. }
  513.  
  514. /****************************************************************************/
  515.  
  516. /*
  517.  * Prints an abortable string (contained in *s). Returns 1 in *abort if the
  518.  * string was aborted, else *abort should be zero.
  519.  */
  520.  
  521. void pla(char *s, int *abort)
  522. {
  523.   int i,next;
  524.  
  525.   i=0;
  526.   checkhangup();
  527.   if (hangup)
  528.     *abort=1;
  529.   checka(abort,&next);
  530.   while ((s[i]) && (!(*abort))) {
  531.     outchr(s[i++]);
  532.     checka(abort,&next);
  533.   }
  534.   if (!(*abort))
  535.     nl();
  536. }
  537.  
  538. /****************************************************************************/
  539.  
  540. void plal(char *s, int limit, int *abort)
  541. {
  542.   int i,next;
  543.  
  544.   i=0;
  545.   checkhangup();
  546.   if (hangup)
  547.     *abort=1;
  548.   checka(abort,&next);
  549.   limit+=strlen(s)-strlen(stripcolors(s));
  550.   while ((s[i]) && (!(*abort)) && (i<limit)) {
  551.     if((s[i]!='\r') && (s[i]!='\n'))
  552.       outchr(s[i++]);
  553.     else
  554.       i++;
  555.     checka(abort,&next);
  556.   }
  557.   if (!(*abort))
  558.     nl();
  559. }
  560.  
  561. /****************************************************************************/
  562.  
  563. /*
  564.  * Returns current time as string formatted like HH:MM:SS (01:13:00).
  565.  */
  566.  
  567. char *ctim(double d)
  568. {
  569.   static char ch[10];
  570.   long h,m,s;
  571.  
  572.   if (d<0)
  573.     d += 24.0*3600.0;
  574.   h=(long) (d/3600.0);
  575.   d-=(double) (h*3600);
  576.   m=(long) (d/60.0);
  577.   d-=(double) (m*60);
  578.   s=(long) (d);
  579.   sprintf(ch,"%02.2ld:%02.2ld:%02.2ld",h,m,s);
  580.  
  581.   return(ch);
  582. }
  583.  
  584. /*
  585.  * Returns 1 if sysop is "chattable", else returns 0. Takes into account
  586.  * current user's chat restriction (if any) and sysop high and low times,
  587.  * if any, as well as status of scroll-lock key.
  588.  */
  589.  
  590. int sysop2(void)
  591. {
  592.   int ok;
  593.  
  594.   ok=sysop1();
  595.   if (restrict_chat & thisuser.restrict)
  596.     ok=0;
  597.   if (syscfg.sysoplowtime != syscfg.sysophightime) {
  598.     if (syscfg.sysophightime>syscfg.sysoplowtime) {
  599.       if ((timer()<=(syscfg.sysoplowtime*60.0)) || (timer()>=(syscfg.sysophightime*60.0)))
  600.         ok=0;
  601.     } else {
  602.       if ((timer()<=(syscfg.sysoplowtime*60.0)) && (timer()>=(syscfg.sysophightime*60.0)))
  603.         ok=0;
  604.     }
  605.   }
  606.   return(ok);
  607. }
  608.  
  609. /****************************************************************************/
  610.  
  611. /*
  612.  * Returns 1 if computer type string in *s matches the current user's
  613.  * defined computer type, else returns 0.
  614.  */
  615.  
  616. int checkcomp(char *s)
  617. {
  618.   if (strstr(ctypes[thisuser.comp_type],s))
  619.     return(1);
  620.   else
  621.     return(0);
  622. }
  623.  
  624. /****************************************************************************/
  625.  
  626. /*
  627.  * Returns 1 if ANSI detected, or if local user, else returns 0. Uses the
  628.  * cursor position interrogation ANSI sequence for remote detection.
  629.  */
  630.  
  631. int check_ansi(void)
  632. {
  633.   long l;
  634.   char ch;
  635.  
  636.   if (!incom)
  637.     return(1);
  638.  
  639.   while (comhit())
  640.     get1c();
  641.  
  642.   pr1("\x1b[6n");
  643.  
  644.   l=timer1()+36;
  645.   if (modem_flag & flag_ec)
  646.     l += 18;
  647.  
  648.   while ((timer1()<l) && (!hangup)) {
  649.     checkhangup();
  650.     ch=get1c();
  651.     if (ch=='\x1b') {
  652.       l=timer1()+18;
  653.       while ((timer1()<l) && (!hangup)) {
  654.         if ((timer1()+1820)<l)
  655.           l=timer1()+18;
  656.         checkhangup();
  657.         ch=get1c();
  658.         if (ch) {
  659.           if (((ch<'0') || (ch>'9')) && (ch!=';') && (ch!='['))
  660.             return(1);
  661.         }
  662.       }
  663.       return(1);
  664.     } else if (ch=='N')
  665.       return(-1);
  666.     if ((timer1()+1820)<l)
  667.       l=timer1()+36;
  668.   }
  669.   return(0);
  670. }
  671.  
  672. /****************************************************************************/
  673.  
  674. /*
  675.  * Reads in menus and so forth in a messagerec array in memory, limited to
  676.  * maxary items in the array. The filename read in is contained in *fn, and
  677.  * the language dir for the current user is the dir used, if possible. The
  678.  * BBS will abort here if it cannot read the file into memory.
  679.  */
  680.  
  681. int read_in_file(char *fn, messagerec *m, int maxary)
  682. {
  683.   int i,i1,i2;
  684.   char *buf,s[81];
  685.   long l,l1;
  686.  
  687.   for (i=0; i<maxary; i++) {
  688.     m[i].stored_as=0L;
  689.     m[i].storage_type=255;
  690.   }
  691.   sprintf(s,"%s%s",languagedir,fn);
  692.   i=sh_open1(s,O_RDONLY | O_BINARY);
  693.   if (i<0) {
  694.     sprintf(s,"%s%s",syscfg.gfilesdir,fn);
  695.     i=sh_open1(s,O_RDONLY|O_BINARY);
  696.       if (i<0)
  697.         return(1);
  698.   }
  699.   l=filelength(i);
  700.   buf=(char *) malloca(l);
  701.   sh_lseek(i,0L,SEEK_SET);
  702.   if (buf==NULL) {
  703.     printf("NOT ENOUGH MEMORY.\n");
  704.     end_bbs(noklevel);
  705.   }
  706.   sh_read(i,(void *) buf,l);
  707.   sh_close(i);
  708.   i1=0;
  709.   for (l1=0; l1<l; l1++) {
  710.     if ((buf[l1]=='`') && ((l1==0) || (buf[l1-1]==10))) {
  711.       i1=1;
  712.       i2=0;
  713.     } else {
  714.       if (i1) {
  715.         if ((buf[l1]>='0') && (buf[l1]<='9')) {
  716.           i2*=10;
  717.           i2+=(buf[l1])-'0';
  718.         } else {
  719.           while ((l1<l) && (buf[l1]!=10))
  720.             ++l1;
  721.           ++l1;
  722.           if ((i2>=0) && (i2<maxary))
  723.             m[i2].stored_as=l1;
  724.           i1=0;
  725.         }
  726.       }
  727.     }
  728.   }
  729.   bbsfree((void *) buf);
  730.  
  731.   return(0);
  732. }
  733.  
  734. /****************************************************************************/
  735.  
  736. /*
  737.  * Sets current language to language index n, reads in menus and help files,
  738.  * and initializes stringfiles for that language. Returns 1 if problem,
  739.  * else returns 0.
  740.  */
  741.  
  742. int set_language_1(int n)
  743. {
  744.   int fail=0, idx;
  745.  
  746.   for (idx=0; idx<num_languages; idx++)
  747.     if (languages[idx].num==n)
  748.       break;
  749.  
  750.   if ((idx>=num_languages) && (n==0))
  751.     idx=0;
  752.  
  753.   if (idx>=num_languages)
  754.     return(1);
  755.  
  756.   cur_lang=n;
  757.   cur_lang_idx=idx;
  758.   cur_lang_name=languages[idx].name;
  759.   languagedir=languages[idx].dir;
  760.  
  761.   if (set_strings_fn(0, languagedir, "BBS.STR", 0)) {
  762.     printf("Couldn't open %sBBS.STR for language #%d\n",
  763.             languagedir, n);
  764.     if (n==0) {
  765.       printf("Copy ENGLISH.STR from the distribution archive to %sBBS.STR\n",
  766.              languagedir);
  767.     }
  768.     fail=1;
  769.   }
  770.  
  771.   if (n==0) {
  772.     if (set_strings_fn(1, languagedir, "SYSOPLOG.STR", 0)) {
  773.       printf("Couldn't open %sSYSOPLOG.STR for language #%d\n",
  774.              languagedir, n);
  775.       printf("Copy SYSOPLOG.STR from the distribution archive to %sSYSOPLOG.STR\n",
  776.               languagedir);
  777.       fail=1;
  778.     }
  779.   }
  780.  
  781.   if (fail)
  782.     return(fail);
  783.  
  784.   set_strings_fn(2, languagedir, "YES.STR", 0);
  785.   set_strings_fn(3, languagedir, "NO.STR", 0);
  786.  
  787.   strncpy(str_yes,"Yeppers", sizeof(str_yes)-1);
  788.   strncpy(str_no,"Noppers", sizeof(str_no)-1);
  789.   strncpy(str_quit,get_string(929), sizeof(str_quit)-1);
  790.   strncpy(str_pause,get_string(923), sizeof(str_pause)-1);
  791.   str_yes[0]=upcase(str_yes[0]);
  792.   str_no[0]=upcase(str_no[0]);
  793.   str_quit[0]=upcase(str_quit[0]);
  794.  
  795.   if (read_in_file("MENUS.MSG",menus,sizeof(menus)/sizeof(menus[0]))) {
  796.     printf("Couldn't open %sMENUS.MSG for language #%d\n",languagedir,n);
  797.     return(1);
  798.   }
  799.   if (read_in_file("HELP.MSG",helps,sizeof(helps)/sizeof(helps[0]))) {
  800.     printf("Couldn't open %sHELP.MSG for language #%d\n",languagedir,n);
  801.     return(1);
  802.   }
  803.   read_in_file("MENUSANS.MSG",menus1,sizeof(menus1)/sizeof(menus1[0]));
  804.   read_in_file("MENUS40.MSG",menus2,sizeof(menus2)/sizeof(menus2[0]));
  805.   rip_file("MENUSSOF.MSG",menus3,sizeof(menus3)/sizeof(menus3[0]));
  806.   rip_file("MENUSLCL.MSG",menusl,sizeof(menusl)/sizeof(menusl[0]));
  807.  
  808.   return(0);
  809. }
  810.  
  811. /****************************************************************************/
  812.  
  813. /*
  814.  * Sets language to language #n, returns 1 if a problem, else returns 0.
  815.  */
  816.  
  817. int set_language(int n)
  818. {
  819.   int pl;
  820.  
  821.   if (cur_lang==n)
  822.     return(0);
  823.  
  824.   pl=cur_lang;
  825.  
  826.   if (set_language_1(n)) {
  827.     if (pl>=0) {
  828.       if (set_language_1(pl))
  829.         set_language_1(0);
  830.     }
  831.     return(1);
  832.   }
  833.  
  834.   return(0);
  835. }
  836.  
  837. /****************************************************************************/
  838.  
  839. void cd_to(char *s)
  840. {
  841.   char s1[81];
  842.   int i,db;
  843.  
  844.   strcpy(s1,s);
  845.   i=strlen(s1)-1;
  846.   db=(s1[i]=='\\');
  847.   if (i==0)
  848.     db=0;
  849.   if ((i==2) && (s1[1]==':'))
  850.     db=0;
  851.   if (db)
  852.     s1[i]=0;
  853.   chdir(s1);
  854.   if (s[1]==':')
  855.     setdisk(s[0]-'A');
  856. }
  857.  
  858. void get_dir(char *s, int be)
  859. {
  860.   strcpy(s,"X:\\");
  861.   s[0]='A'+getdisk();
  862.   getcurdir(0,&(s[3]));
  863.   if (be) {
  864.     if (s[strlen(s)-1]!='\\')
  865.       strcat(s,"\\");
  866.   }
  867. }
  868.  
  869.  
  870.