home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / W / WWIVSOR.ZIP / RIPOVL.C < prev    next >
Text File  |  1995-05-14  |  41KB  |  1,668 lines

  1. /* RIPspeed support functions, copyright (C) 1994 by Zachary G. Ives.   *
  2.  * All rights reserved.                                                 *
  3.  *                                                                      *
  4.  * Version 1.02, 6/6/94.                                                *
  5.  * Version 1.50, 6/20/94.                                               *
  6.  * For WWIV 4.24, 8/01/94.                                              */
  7.  
  8. #include "vars.h"
  9. #include "ripint.h"
  10.  
  11. #pragma hdrstop
  12.  
  13. #include <dir.h>
  14. #include <dos.h>
  15. #include <ctype.h>
  16.  
  17. int ex_line = 0;
  18. char icon_extension[4];
  19.  
  20. #define MIN(x,y) (((x) < (y)) ? (x) : (y))
  21.  
  22. /* Function: autodetect RIPscrip caller by sending out the RIP_VER code and
  23.    looking for "RIP" to be returned.  If nothing for 2 seconds, goes on and
  24.    assumes non-RIP caller.
  25.  */
  26. int rip_check(void)
  27. {
  28.   char c, verstr[10];
  29.   int pos;
  30.  
  31. #ifdef RIPDRIVE
  32.   if (localrip_detect()) {
  33.     ripdrive = -1;
  34.     puts(get_string(1608));
  35.   }
  36. #endif
  37.  
  38.   end_submenu = -1;
  39.   while (inkey() && (!hangup));
  40.   outstr(get_string(1459));
  41.   pl("!");
  42.   c = delaykey(2);
  43.   
  44.   if (c == 'R') {
  45.     if (delaykey(1) == 'I')
  46.       if (delaykey(1) == 'P') {     /* Check for the beginning of OPT_RIP */
  47.  
  48.         c = delaykey(1);
  49.                 for (pos = 0; (pos < 11) && (c != 0) && (!hangup); pos++) {
  50.           c = delaykey(1);
  51.           if (pos > 3)
  52.             verstr[pos - 4] = c;
  53.         }
  54.         if (pos == 11) {
  55.             verstr[pos - 4] = 0;
  56.             rip_ver = atoi(verstr);
  57.                         printf("%s %f\n", get_string(1638), rip_ver / 10000.0);
  58.             strcpy(icon_extension, "ICN");
  59.             if (rip_ver == 15450) {              /* Softerm has only */
  60.                 rip_subset = -1;                        /* partial support */
  61.                 pl(get_string(1440));
  62.                 pl(get_string(1441));
  63.                 user_menus = 2;
  64.             } else if (rip_ver < 15400) {
  65.                 pl(get_string(1463));
  66.                 rip_subset = -1;
  67.             } else {
  68.                 rip_subset = 0;
  69.  
  70.                 if (rip_ver == 15410)
  71.                   pl(get_string(1460));
  72.                 else if (rip_ver == 15420)
  73.                   pl(get_string(1461));
  74.                 else if (rip_ver == 15430) {
  75.                   pl(get_string(1609));
  76.                   rip_subset = -1;                        /* partial support */
  77.                   user_menus = 2;
  78.                 } else if (rip_ver == 15400)
  79.                   pl(get_string(1462));
  80.                 else if (rip_ver >= 20000) {
  81.                   pl(get_string(1610));
  82.                   strcpy(icon_extension,"BMP");
  83.                 }
  84.             }
  85.         }
  86.  
  87.         strcpy(sysinfo.ripdir,languagedir);
  88.         pos = strlen(sysinfo.ripdir) - 2;
  89.         while ((sysinfo.ripdir[--pos] != '\\') && pos >= 0);  /* Find first \ */
  90.         sysinfo.ripdir[++pos] = 0;
  91.         
  92.         //rip_ver = 15410;
  93.         strcat(sysinfo.ripdir, "RIPMENUS\\");
  94. #ifdef RIPDRIVE
  95.         if (ripdrive) {
  96.           topdata = 0;
  97.           puts(get_string(1608));
  98.           if (sysinfo.flags & OP_FLAGS_RIPDRIVE_ON)
  99.             localrip_activate(sysinfo.ripdir, sysinfo.ripdir);
  100.         }
  101. #endif
  102.  
  103.         return (-1);
  104.       }
  105.   }
  106.   ripdrive = 0;
  107.   return (0);
  108. }
  109.  
  110. /* Function: display instructions and allow user to download the menus.
  111.    Uses external PRESEND_.BAT and SEND_.BAT batch files.
  112.  */
  113. int transmit(char menutype)
  114. {
  115.         char f[67], ch, iconflag = 0;
  116.     char files[256][13];
  117.     int numfiles = 0;
  118.     int snd;
  119.     double pct;
  120.     FILE *namefile, *mfile;
  121. //    userrec tuser;
  122.  
  123.     if (rip_subset)
  124.       return 0;
  125.  
  126.     rip_cls();
  127.     sprintf(f, "%sNAME.MNU", sysinfo.ripdir);
  128.     if ((namefile = fopen(f, "w")) != NULL) {
  129.       if (rip_ver >= 20000) {
  130.         sprintf(f, "%sNAME.M%c", sysinfo.ripdir, menutype);
  131.  
  132.         if ((mfile = fopen(f, "r")) != NULL) {
  133.           fgets(f, 60, mfile);
  134.           fputs(f, namefile);
  135.           fclose(mfile);
  136.         }
  137.       }
  138.       fprintf(namefile, "!|T%s\n", syscfg.systemname);
  139.       fclose(namefile);
  140.     }
  141.     
  142.     tmp_disable_pause(1);
  143.     sprintf(f, "%sMENUS.TXT", sysinfo.ripdir);
  144.     printfile(f);
  145.     tmp_disable_pause(0);
  146.     rip_show("menu332.mn1");        // Pause
  147.     getkey();
  148.     if (hangup)
  149.       return 0;
  150.     rip_show("menu333.mn1");        // Clear
  151.  
  152.     sprintf(f, "MENU0.MN%c", menutype);
  153.     switch (current_menu(f)) {
  154.       case 1:
  155. //        pl(get_string(1611));
  156.         pl(get_string(1473));
  157.         if (yn() == 0) {
  158.             // Simply send them a new RIPEXT.MNU and NAME.MNU file
  159.             sprintf(f, "ripext.mn%c", menutype);
  160.             numfiles = todownload(files, 0, f, sysinfo.ripdir);
  161.             numfiles = todownload(files, numfiles, "name.mnu", sysinfo.ripdir);
  162.             if (numfiles) {
  163.               pl(get_string(1612));
  164.                           comstr("|920000<>\r\r");           /* Block transfer */
  165.               menuxfer(sysinfo.ripdir, files, 2, &snd, &pct);
  166.               delay(1);
  167.               out_cport(4);
  168.               out_cport(26);
  169.             }
  170.             return 1;
  171.         }
  172.         break;
  173.       case 0:
  174.         pl(get_string(1470));
  175.         break;
  176.       default:
  177.         break;
  178.     }
  179.  
  180.     printmenu(351);
  181.     do {
  182.       ch = toupper(delaykey(30));
  183.  
  184.       if (ch == 0)     /* After 30 seconds, default to Yes */
  185.         ch = 'Y';
  186.         } while ((ch != 'Y') && (ch != 'N') && (!hangup));
  187.     rip_cls();
  188.     
  189.     sprintf(f,"%siclose.%2.2s%c", sysinfo.ripdir, icon_extension, menutype);
  190.     if (exist(f) && ch != 'Y') {
  191.         pl(get_string(1442));
  192.         pl(get_string(1443));
  193.         pl(get_string(1444));
  194.  
  195.         if (yn()) {
  196.           iconflag = -1;
  197.           ch = 'Y';
  198.         }
  199.     }
  200.     rip_cls();
  201.     
  202.     if (ch == 'Y') {
  203.           //comstr("|920000<>\r\r");           /* Block transfer */
  204.       pl(get_string(1613));
  205.       if (iconflag == 0) {
  206.         sprintf(f, "*.mn%c", menutype);
  207.         numfiles = todownload(files, 0, f, sysinfo.ripdir);
  208.       }
  209.       numfiles = todownload(files, numfiles, "name.mnu", sysinfo.ripdir);
  210.       numfiles = todownload(files, numfiles, "ripterm.key", sysinfo.ripdir);
  211.       numfiles = todownload(files, numfiles, "*.icn", sysinfo.ripdir);
  212.       numfiles = todownload(files, numfiles, "*.hic", sysinfo.ripdir);
  213.       sprintf(f, "*.%2.2s%c", icon_extension, menutype);
  214.       numfiles = todownload(files, numfiles, f, sysinfo.ripdir);
  215.  
  216.       pl(get_string(1612));
  217.           comstr("|920000<>\r\r");           /* Block transfer */
  218.       menuxfer(sysinfo.ripdir, files, numfiles, &snd, &pct);
  219.       delay(1);
  220.       out_cport(4);
  221.       out_cport(26);
  222.  
  223.       if (iconflag)
  224.         return 2;
  225.       else
  226.         return 1;
  227.     } else {
  228.       // Send them a new RIPEXT.MNU and NAME.MNU file
  229.       sprintf(f, "ripext.mn%c", menutype);
  230.       numfiles = todownload(files, 0, f, sysinfo.ripdir);
  231.       numfiles = todownload(files, numfiles, "name.mnu", sysinfo.ripdir);
  232.       if (numfiles) {
  233.         pl(get_string(1612));
  234.                 comstr("|920000<>\r\r");           /* Block transfer */
  235.         menuxfer(sysinfo.ripdir, files, 2, &snd, &pct);
  236.         delay(1);
  237.         out_cport(4);
  238.         out_cport(26);
  239.       }
  240.  
  241.       sprintf(f,"|1F000000ICLOSE.IC%c|#\r\r", menutype);
  242.       comstr(f);    /* Check for an icon file */
  243.       ch = delaykey(1);
  244.       if (ch == '1') 
  245.         return 2;
  246.       else              /* User has no icons */
  247.         return 0;
  248.     }
  249. }
  250.  
  251. /* Function: set the RIP menu extension to ext.
  252.  */
  253. void setmenu(char *ext)
  254. {
  255.     strcpy(ripext, ext);
  256. }
  257.  
  258. /* Function: set the user name and phone info on his/her machine for auto-
  259.    entry on the next call.
  260.  */
  261. void set_name(void)
  262. {
  263.   char s[161];
  264.   pl(get_string(1446));
  265.   pl(get_string(1447));
  266.  
  267.   sprintf(s,"!|1D00500%s_ID,30:?%s%s|#\r", sysinfo.ripbbsid, get_string(1448), thisuser.name);
  268.   comstr(s);
  269.   if (rip_ver >= 20000)
  270.     sprintf(s,"!|1D00500PHONE,5:?%s%s|#\r", get_string(1449), &thisuser.phone[8]);
  271.   else
  272.     sprintf(s,"!|1D00700PHONE_LAST4,4:?%s%s|#\r", get_string(1449), &thisuser.phone[8]);
  273.   comstr(s);
  274. }
  275.  
  276. /* Function: allow the user to select a menu set, and then decide whether
  277.    he/she wants to download it.
  278.  */
  279. void choosemenu(void)
  280. {
  281.   char ext[4], ch = 0, s[67], quitflag = 0;
  282.   int xmit, oldstat;
  283.  
  284.   strcpy(ripext, "RIP");
  285.   oldstat = thisuser.sysstatus;
  286.   thisuser.sysstatus &= ~sysstatus_expert;
  287.   do {
  288.     printmenu(350);     /* Menu of choices */
  289.     rip_coff();
  290.     ch = delaykey(30);
  291.     rip_con();
  292.  
  293.     switch (ch) {
  294.       case '0':
  295.         rip_cls();
  296.         end_rip();
  297. #ifdef RIPDRIVE
  298.         if (rd_on())
  299.           localrip_deactivate();
  300. #endif
  301.         thisuser.sysstatus = oldstat;
  302.         return;
  303.       case 0:
  304.         ch = M_DEFAULT; /* Set menu to default if no keypress */
  305.       default:
  306.         rip_cls();
  307.          /* See if we have a menu set for this choice */
  308.         sprintf(s,"%smenu0.mn%c", sysinfo.ripdir, ch);
  309.         if (exist(s) == 0)
  310.           break;
  311.  
  312.         sprintf(ext, "MN%c", ch);
  313.  
  314.         rip_pause = pausecheck(1, ext);
  315.         
  316.         if ((xmit = transmit(ch)) == 1)
  317.           strcpy(ext,"REM");
  318.         else if (xmit == 0)       /* No icons on user's machine */
  319.           sprintf(ext, "MN%c", M_DEFAULT);
  320.  
  321.         delay(2);
  322.         out_cport(4);
  323.         delay(8);
  324.         rip_cls();
  325.                 while (inkey() && (!hangup));
  326.  
  327.         quitflag = -1;
  328.         break;
  329.       }
  330.     } while (quitflag == 0 && (hangup == 0));
  331.  
  332.     comstr("|*|w00122716|#\r\r");
  333.     setmenu(ext);
  334.     user_menus = ch;
  335.     thisuser.sysstatus = oldstat;
  336.     if (thisuser.sysstatus & sysstatus_expert)
  337.       pl (get_string(1614));
  338. }
  339.  
  340. /* Check for file fn on user's machine.  If doesn't exist, return -1; if
  341.    old, return 0, if current, return 1. */
  342. int current_menu(char *fn)
  343. {
  344.     char f[67], dat[9], ch;
  345.     int count;
  346.  
  347.         while (inkey() && (!hangup));
  348.     sprintf(f,"|1F030000%s|#\r\r", fn);
  349.     comstr(f);
  350.     ch = delaykey(1);
  351.     if (ch == '1') {
  352.       getkey();                                     /* Eat "." */
  353.       while (delaykey(1) != '.' && (hangup == 0));  /* Eat file size */
  354.  
  355.       count = 0;
  356.       while ((ch = delaykey(1)) != '.' && (hangup == 0))  /* Save up the date */
  357.         dat[count++] = ch;
  358.  
  359.          /* Eat file time */
  360.       while ((ch = getkey()) != 10 && ch != 13 && (hangup == 0)); 
  361.  
  362.       if (hangup)
  363.         return 0;
  364.  
  365.       if ( (dat[7] > sysinfo.ripmenudate[7] || dat[6] < '9') || (
  366.        (strncmp(dat, sysinfo.ripmenudate, 8) >= 0) && 
  367.        (dat[7] == sysinfo.ripmenudate[7]) ) )
  368.         return 1;
  369.       else
  370.         return 0;
  371.     } else
  372.       return -1;
  373. }
  374.  
  375. /* Function: main RIP initialization routine.  Check whether user has a
  376.    RIPEXT.MNU on his/her machine, and whether it is a current version.  If
  377.    not, allow the user to choose and download the latest menus, or just to
  378.    use them without downloading.
  379.  */
  380. void rip_menus(void)
  381. {
  382.         char ext[4], fn[13];
  383.  
  384.     if (rip_subset) {
  385.       rip_pause = -1;
  386.       return;
  387.     }
  388.  
  389.     /* Make sure ripmenudate has proper size, delimiters, etc. */
  390.     sysinfo.ripmenudate[8] = 0;
  391.     sysinfo.ripmenudate[2] = '/';
  392.     sysinfo.ripmenudate[5] = '/';
  393.  
  394.     switch (current_menu("RIPEXT.MNU")) {
  395.       case 1:
  396.         comstr("|1R00000000RIPEXT.MNU\r\r");   // Get user's menu extension
  397.         user_menus = delaykey(1);
  398.         sprintf(fn,"menu0.mn%c", user_menus);
  399.  
  400.         if (current_menu(fn) > 0) {
  401. //          pl(get_string(1615));
  402.           pl(get_string(1471));
  403.           setmenu("REM");                         /* Use remote files */
  404.           rip_pause = pausecheck(0, NULL);
  405.         } else {
  406. //          pl(get_string(1616));
  407.           pl(get_string(1472));
  408.           sprintf(ext,"MN%c", user_menus);
  409.           setmenu(ext);
  410.           rip_pause = pausecheck(1, ext);
  411.         }
  412.         return;
  413.       case 0:
  414.         nl();
  415.         pl(get_string(1450));
  416.         break;
  417.       case -1:
  418.         nl();
  419.         outstr(get_string(1451));
  420.         outstr(syscfg.systemname);
  421.         pl(get_string(1452));    
  422.         if (!rip_subset) {
  423.           pl(get_string(1453));  
  424.           set_name();
  425.           comstr(" ");
  426.           pausescr();
  427.         }
  428.         break;
  429.     }
  430.     choosemenu();
  431. }
  432.  
  433. /* Function: check pause-status indicator.  Certain menus which fill the
  434.    whole screen will obscure lists and other data, such as the subs list,
  435.    before the user can read them.  If a MENU334 file of > 10 bytes exists,
  436.    the pause-before-menu flag is set.  Also, MENU334 is then used as a
  437.    frame in which the next command's results are displayed.  (This allows
  438.    you to keep data within a certain border.)
  439.  */
  440. int pausecheck(int localflag, char *ext)
  441. {
  442.   char s[67], ch;
  443.   struct ffblk ffblock;
  444.  
  445.   if (localflag == 0) {
  446.     sprintf(s, "|1F020000MENU334.MN%c|#\r\r", user_menus);
  447.     comstr(s);    /* Check for pause flag */
  448.     ch = delaykey(1);
  449.     delaykey(1);
  450.     if (ch == '1') {                    /* File exists, as should be */
  451.       ch = delaykey(1);
  452.       if (ch != '0')                    /* Not zero-length */
  453.         if (delaykey(1) == '\r')        /* but is it < 10 bytes? */
  454.           ch = '0';
  455.         else
  456.                   while ((delaykey(1) != '\r') && (!hangup));  /* Eat up to CR */
  457.       return (ch != '0');
  458.     }
  459.   } else {
  460.     sprintf(s,"%sMENU334.%s", sysinfo.ripdir, ext);
  461.     if (findfirst(s, &ffblock, 0) == 0)
  462.       if (ffblock.ff_fsize > 0) {
  463.         return -1;
  464.       }
  465.   }
  466.   return 0;
  467. }
  468.  
  469. /* Function: turn off RIP support.
  470.  */
  471. void end_rip(void)
  472. {
  473.     rip = 0;
  474. }
  475.  
  476. /* Function: restore the proper RIP message-base menu.  If the user is
  477.    a co-sysop or above, menu 13 is used; otherwise menu 1 is used.
  478.  */
  479. void restore_msg_menu(void)
  480. {
  481.   if (rip_ver >= 20000)
  482.     return;
  483.   if (menu_on()) {
  484.     if (lcs())
  485.       printmenu(13);
  486.     else
  487.       printmenu(1);
  488.   }
  489. }
  490.  
  491. /* Function: create a text window for the message header info to be
  492.    displayed in.  The font size here is different from the regular text.
  493.  */
  494. void msgheader(int startat)
  495. {
  496.   unsigned char t; 
  497.   char s[80];
  498.  
  499.   if (rip_ver >= 20000)
  500.     return;
  501.   if (rip) {
  502.     t = (formery > '9') ? formery - 'A' + 10 : formery - '0';
  503.     t = t * 8 / 14 + startat;
  504.     t = (t < 9) ? t + '0' : t + 'A' - 10;
  505.     sprintf(s,"\n!|e|w050%c2D0M03|e|#\r\r", t);
  506.     comstr(s);
  507.   }
  508. }
  509.  
  510. /* Function: create the proper window size for the message text to be 
  511.    displayed in.  The title and header info uses a different font, so
  512.    we must compensate for that here.
  513.  */
  514. void setmsgview(int smallby)
  515. {
  516.   struct localrip_screeninfo r;
  517.   
  518.   if (rip_ver >= 20000)
  519.     return;
  520.   if (rip == 0) 
  521.     return;
  522.  
  523. #ifdef RIPDRIVE
  524.   if (rd_on()) {
  525.     localrip_textinfo(&r);    
  526.     formery = r.w_top;
  527.     formery = smally = formery + '0';
  528.   } else
  529. #endif
  530.   {
  531.         comstr("\n!|1""0000$TWY0$ |#\r\r");
  532.     formery = delaykey(1);          /* Get text window upper limit */
  533.     if (hangup == 0)
  534.     smally = delaykey(1);
  535.     if (smally == ' ')
  536.       smally = formery;
  537.     else {
  538.       formery = smally = (formery - '0') * 10 + smally;
  539.       if (hangup == 0)
  540.         delaykey(1);
  541.     }
  542.   }
  543.  
  544.   smally += smallby;
  545.   if (smally > '9')
  546.     smally += 'A' - '0' - 10;
  547.   if (formery > '9')
  548.     formery += 'A' - '0' - 10;
  549. }
  550.  
  551. /* Function: record a series of bytes, terminated when end_submenu is set to -1
  552.    by the input routine (on an ^I).
  553.  
  554.    Note that control codes are designated by a % followed by a letter, much
  555.    like the way they are ^ followed by a letter in RIP.  (We cannot use ^
  556.    since RIP already takes it.)
  557. */
  558. void submenu(void)
  559. {
  560.     char ch, macro[246];    /* Max of 245 chars */
  561.     char s[255];
  562.     int i = 0;
  563.     end_submenu = 0;           /* Begin recording */
  564.  
  565.     while (!end_submenu && i < 245 && (hangup == 0)) {/* Record keystrokes */
  566.         ch = getkey();
  567.         if (ch == '%') {    /* Special marker for control code */
  568.           ch = toupper(getkey());
  569.           switch (ch) {
  570.             case 'C':           /* Code = ^ */
  571.               macro[i++] = '^';
  572.               break;
  573.             case 'B':           /* Code = | */
  574.               macro[i++] = '|';
  575.               break;
  576.             case 'N':           /* Code = newline */
  577.               macro[i++] = '\n';
  578.               break;
  579.             case 'R':           /* Code = CR */
  580.               macro[i++] = '\r';
  581.               break;
  582.             case 'E':           /* Code = Exclamation */
  583.               macro[i++] = '!';
  584.               break;
  585.             case '(':           /* Code = < */
  586.               macro[i++] = '<';
  587.               break;
  588.             case ')':           /* Code = > */
  589.               macro[i++] = '>';
  590.               break;
  591.             case '[':           /* Code = Escape */
  592.               macro[i++] = 27;
  593.               break;
  594.             default:
  595.               macro[i++] = ch;
  596.               break;
  597.           }
  598.         } else if (ch != submenu_code)
  599.           macro[i++] = ch;
  600.     }
  601.     macro[i] = 0;
  602.     end_submenu = -1;
  603.  
  604.     sprintf(s,"|%s\r\r",macro);
  605.     comstr (s);             /* Play it back now */
  606. }
  607.  
  608. /* Function: read in a hypertext filename and then display the hypertext
  609.    file.
  610.  */
  611. void hypertext(void)
  612. {
  613.     char f[67], ch, s[67];
  614.     int i = 0;
  615.  
  616.         while ((ch = getkey()) != '\n' && ch != '\r' && (hangup == 0)) {
  617.       if (strchr(":\\/", ch) == NULL)       /* Don't allow path specifiers */
  618.         f[i++] = ch;
  619.           if (i>=(sizeof(f)-3))
  620.             return;
  621.         }
  622.  
  623.     if (hangup)
  624.       return;
  625.  
  626.     f[i] = 0;           /* Terminate the string */
  627.  
  628.         if (rd_on() == 0)
  629.       printf("[Hypertext image %s]\r", f);
  630.  
  631.     if (rip_subset)
  632.       ch = '0';
  633.     else {
  634.       sprintf(s, "|1F000000%s|#\r\r", f); /* Check for file on user's machine */
  635.       comstr(s);
  636.       ch = delaykey(2);
  637.     }
  638.     lines_listed = -50;
  639.     if (ch == '1') {                /* Exists on user's machine */
  640.       sprintf(s, "|1R00000000%s\r\r", f);
  641.       comstr(s);
  642.     } else {                        /* Try to print locally */
  643.       rip_show(f);
  644.     }
  645.     ripcode = 0;
  646.     lines_listed = 0;
  647.  
  648.     cleared = HYPCLEAR;     /* Signify hypertext image which may need cls */
  649. }
  650.  
  651. /* Function:  show all of the chains on the BBS.  If a file called 
  652.               DOORLST.RIP exists in the RIPMENUS directory, displays that;
  653.               otherwise, displays a pick list with all of the doors.
  654. */
  655. #ifdef OLD
  656. void rip_show_chains(int *mapp, int *map, int start)
  657. {
  658.   int abort,i;
  659.   char s[81];
  660.  
  661.   abort=0;
  662.   sprintf(s,"%s%s",sysinfo.ripdir,"doorlst.rip");
  663.   if (exist(s))
  664.     rip_show("doorlst.rip");
  665.   else {
  666.     if (rd_on() == 0)
  667.       printf("\n%s%s\n", syscfg.systemname, get_string(1454));
  668.     sprintf(s,"|1""0000((*%s%s::\\", syscfg.systemname,get_string(1454));
  669.     comstr(s);
  670.     if (start) {
  671.         if (rd_on() == 0)
  672.           printf("%s\n", get_string(1474));
  673.         sprintf(s,"%s\\", get_string(1475));
  674.         comstr(s);
  675.     }
  676.     for (i=start; (i<MIN(*mapp, start+18)) && (!abort) && (!hangup); i++) {
  677.       if (rd_on() == 0)
  678.         printf("%d> %s\n",i+1, chains[map[i]].description);
  679.       if ((i+1)*10 < *mapp)       /* Add any necessary CR */
  680.         sprintf(s,"%d^M@%s,\\",i+1, chains[map[i]].description);
  681.       else
  682.         sprintf(s,"%d@%s,\\",i+1, chains[map[i]].description);
  683.       comstr(s);
  684.     }
  685.     if (start+18 < *mapp) {
  686.         if (rd_on() == 0)
  687.           printf("%s\n", get_string(1476));
  688.                 sprintf(s,"%s\\", get_string(1477));
  689.         comstr(s);
  690.     }
  691.     comstr(get_string(1465));
  692.     remstr("\r\r");
  693.     if (rd_on() == 0)
  694.       printf("%s\n\n",get_string(1464));      
  695.   }
  696. }
  697. #else
  698. char *pos[14][2] = {
  699.  {"0D2P7B37", "4G2X"},
  700.  {"0D3J7B41", "4G3R"},
  701.  {"0D4D7B4V", "4G4L"},
  702.  {"0D577B5P", "4G5F"},
  703.  {"0D617B6J", "4G69"},
  704.  {"0D6V7B7D", "4G73"},
  705.  {"0D7P7B87", "4G7X"},
  706.  {"7T2PER37", "BW2X"},
  707.  {"7T3JER41", "BW3R"},
  708.  {"7T4DER4V", "BW4L"},
  709.  {"7T57ER5P", "BW5F"},
  710.  {"7T61ER6J", "BW69"},
  711.  {"7T6VER7D", "BW73"},
  712.  {"7T7PER87", "BW7X"}
  713. };
  714.  
  715. void rip_show_chains(int *mapp, int *map, int start)
  716. {
  717.   int abort,i;
  718.   char s[81];
  719.  
  720.   abort=0;
  721.   sprintf(s,"%s%s",sysinfo.ripdir,"doorlst.rip");
  722.   if (exist(s))
  723.     rip_show("doorlst.rip");
  724.   else {
  725.     printmenu(312);
  726.     sprintf(s,"|c09|@FO2MPage %d/%d|c0E", start / 14 + 1, (*mapp+13) / 14);
  727.     comr(s);
  728.     for (i=start; (i<MIN(*mapp, start+14)) && (!abort) && (!hangup); i++) {
  729.       if (rd_on() == 0)
  730.         printf("%d> %s\n",i+1, chains[map[i]].description);
  731.       if ((i+1)*10 < *mapp)     // Add any necessary CR
  732.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d^M", pos[i-start][0], 
  733.           i+1, chains[map[i]].description, i+1);
  734.       else
  735.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d", pos[i-start][0], 
  736.           i+1, chains[map[i]].description, i+1);
  737.       comr(s);
  738.       /*
  739.       read_user(chains_reg[map[i]].regby[0],&u);
  740.       sprintf(s,"|c0E|@%s%s", pos[i-start][1], 
  741.         (chains_reg[map[i]].regby[0]) ? u.name : get_string(315));
  742.       comr(s);
  743.       */
  744.     }
  745.   }
  746.   if (rip_ver >= 20000)         // Fix window in RIP 2.0
  747.     comr("|w0013271610");
  748. }
  749. #endif
  750.  
  751. /* Function: display the list of GFILES.  If there's a file called  
  752.    GFILELST.RIP, this will be shown as the list.  Otherwise a pick-list
  753.    is built up */
  754. #ifdef OLD
  755. void rip_list_gfiles(gfilerec *g, int nf, int start)
  756. {
  757.   int i;
  758.   char s[81];
  759.  
  760.   sprintf(s,"%s%s",sysinfo.ripdir,"gfilelst.rip");
  761.   if (exist(s))
  762.     rip_show("gfilelst.rip");
  763.   else {
  764.     if (rd_on() == 0)
  765.       printf("\n%s\n", get_string(1455));
  766.         sprintf(s,"|1""0000((*%s::\\", get_string(1455));
  767.     comstr(s);
  768.     if (start) {
  769.         if (rd_on() == 0)
  770.           printf("%s\n", get_string(1474));
  771.         sprintf(s,"%s\\", get_string(1475));
  772.         comstr(s);
  773.     }
  774.     for (i=start; (i<MIN(nf,start+18)) && (!hangup); i++) {
  775.       if (rd_on() == 0)
  776.         printf("%d> %s\n\\", i+1, g[i].description);
  777.       sprintf(s,"%d@%s,\\",i+1, g[i].description);
  778.       comstr(s);
  779.     }
  780.     if (start+18 < nf) {
  781.         if (rd_on() == 0)
  782.           printf("%s\n", get_string(1476));
  783.         sprintf(s,"%s\\", get_string(1477));
  784.         comstr(s);
  785.     }
  786.     comstr(get_string(1465));
  787.     remstr("\r\r");
  788.     if (rd_on() == 0)
  789.       printf("%s\n", get_string(1464)); 
  790.   }
  791. }
  792. #else
  793. void rip_list_gfiles(gfilerec *g, int nf, int start)
  794. {
  795.   int i;
  796.   char s[81];
  797.  
  798.   sprintf(s,"%s%s",sysinfo.ripdir,"gfilelst.rip");
  799.   if (exist(s))
  800.     rip_show("gfilelst.rip");
  801.   else {
  802.     if (rd_on() == 0)
  803.       printf("\n%s\n", get_string(1455));
  804.     printmenu(315);
  805.     sprintf(s,"|c09|@FO2MPage %d/%d|c0E", start / 14 + 1, (nf+13) / 14);
  806.     comr(s);
  807.     for (i=start; (i<MIN(nf,start+14)) && (!hangup); i++) {
  808.       if (rd_on() == 0)
  809.         printf("%d> %s\n", i+1, g[i].description);
  810.       if ((i+1)*10 < nf)     // Add any necessary CR
  811.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d^M", pos[i-start][0], 
  812.           i+1, g[i].description, i+1);
  813.       else
  814.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d", pos[i-start][0], 
  815.           i+1, g[i].description, i+1);
  816.       comr(s);
  817.     }
  818.     if (rd_on() == 0)
  819.       printf("%s\n", get_string(1464)); 
  820.   }
  821.   if (rip_ver >= 20000)         // Fix window in RIP 2.0
  822.     comr("|w0013271610");
  823. }
  824. #endif
  825.  
  826. #ifdef OLD
  827. /* Function: list the G-Files sections.  If a file called GSECLST.RIP is
  828.    available, will use this; otherwise creates a pick list */
  829. void rip_list_sec(int *map, int nmap, int start)
  830. {
  831.   int i;
  832.   char s[81];
  833.  
  834.   sprintf(s,"%s%s",sysinfo.ripdir,"gseclst.rip");
  835.   if (exist(s))
  836.     rip_show("gseclst.rip");
  837.   else {
  838.     if (rd_on() == 0)
  839.       printf("\n%s\n", get_string(1456));
  840.         sprintf(s,"|1""0000((*%s::\\", get_string(1456));
  841.     comstr(s);
  842.     if (start) {
  843.         if (rd_on() == 0)
  844.           printf("%s\n", get_string(1474));
  845.         sprintf(s, "%s\\",get_string(1475));
  846.         comstr(s);
  847.     }
  848.     for (i=start; (i<MIN(nmap,start+18)) && (!hangup); i++) {
  849.       if (rd_on() == 0)
  850.         printf("%d> %s\n", i+1, gfilesec[map[i]].name);
  851.       sprintf(s,"%d@%s,\\",i+1, gfilesec[map[i]].name);
  852.       comstr(s);
  853.     }
  854.     if (cs()) {
  855.       if (rd_on() == 0) {
  856.         printf("%s\n", get_string(50));
  857.         printf("%s\n", get_string(51));
  858.       }
  859.       sprintf(s,"%s\\",get_string(1466));
  860.       comstr(s);
  861.     }
  862.     if (start+18 < nmap) {
  863.         if (rd_on() == 0)
  864.           printf("%s\n", get_string(1476));
  865.         sprintf(s, "%s\\",get_string(1477));
  866.         comstr(s);
  867.     }
  868.     comstr(get_string(1465));
  869.     remstr("\r\r");
  870.     if (rd_on() == 0)
  871.       printf("%s\n", get_string(1464));       
  872.   }
  873. }
  874. #else
  875. void rip_list_sec(int *map, int nmap, int start)
  876. {
  877.   int i;
  878.   char s[81];
  879.  
  880.   sprintf(s,"%s%s",sysinfo.ripdir,"gseclst.rip");
  881.   if (exist(s))
  882.     rip_show("gseclst.rip");
  883.   else {
  884.     printmenu(317);
  885.     sprintf(s,"|c09|@FO2MPage %d/%d|c0E", start / 14 + 1, (nmap+13) / 14);
  886.     comr(s);
  887.     if (rd_on() == 0)
  888.       printf("\n%s\n", get_string(1456));
  889.     for (i=start; (i<MIN(nmap,start+14)) && (!hangup); i++) {
  890.       if (rd_on() == 0)
  891.         printf("%d> %s\n", i+1, gfilesec[map[i]].name);
  892.       if ((i+1)*10 < nmap)     // Add any necessary CR
  893.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d^M", pos[i-start][0], 
  894.           i+1, gfilesec[map[i]].name, i+1);
  895.       else
  896.         sprintf(s,"|1U%s0000<>[%d] %-36.36s<>%d", pos[i-start][0], 
  897.           i+1, gfilesec[map[i]].name, i+1);
  898.       comr(s);
  899.     }
  900.     if (rd_on() == 0)
  901.       printf("%s\n", get_string(1464));       
  902.   }
  903.   if (rip_ver >= 20000)         // Fix window in RIP 2.0
  904.     comr("|w0013271610");
  905. }
  906. #endif
  907.  
  908. /* Function: display the timebank with a RIP screen, and update the screen
  909.    to keep it current */
  910. void rip_timebank(void)
  911. {
  912.   char s[80],c;
  913.   int i,done=0;
  914.   double nsln;
  915.  
  916.   do {
  917.     printmenu(366);
  918.     sprintf(s,"|@7N54%d\r\r",thisuser.banktime);
  919.     comstr(s);
  920.     c=onek("QDW");
  921.     switch(c) {
  922.       case 'D':
  923.         rip_con();
  924.         input(s,3);
  925.         rip_coff();
  926.         i=atoi(s);
  927.         if (i>0) {
  928.           nsln=nsl();
  929.           if ((i+thisuser.banktime)>syscfg.sl[thisuser.sl].time_per_logon)
  930.             i=syscfg.sl[thisuser.sl].time_per_logon-thisuser.banktime;
  931.           if (i>(nsln/60.0))
  932.             i=(nsln/60.0);
  933.           thisuser.banktime+=i;
  934.           thisuser.extratime-=i*60.0;
  935.           tleft(0);
  936.         }
  937.         break;
  938.       case 'W':
  939.         if (!thisuser.banktime)
  940.           break;
  941.         rip_con();
  942.         input(s,3);
  943.         rip_coff();
  944.         i=atoi(s);
  945.         if (i>0) {
  946.           nsln=nsl();
  947.           if (i>thisuser.banktime)
  948.             i=thisuser.banktime;
  949.           thisuser.banktime-=i;
  950.           thisuser.extratime+=(i*60.0);
  951.           tleft(0);
  952.         }
  953.         break;
  954.       case 'Q':
  955.         done=1;
  956.         break;
  957.     }
  958.   } while (!done && !hangup);
  959.   cleared = NEEDCLEAR;
  960. }
  961.  
  962. /* Function: display Your Info in a RIP dialog screen */
  963. void rip_yourinfo(void)
  964. {
  965.   printmenu(326);
  966.   tmp_disable_pause(1);
  967.   rip_show("MENU326.LCL");          // Show the local overlay with the data
  968.   getkey();
  969.   if (hangup)
  970.       return;
  971.   tmp_disable_pause(0);
  972.   cleared = NEEDCLEAR;
  973. }
  974.  
  975. /* Function: display extended file info in a RIP dialog box */
  976. int rip_printfileinfo(uploadsrec *u, int dn)
  977. {
  978.   char s[81];
  979.   double d;
  980.   int abort;
  981.  
  982.   d=XFER_TIME(u->numbytes);
  983.  
  984.   rip_saveall();
  985.   printmenu(364);
  986.   
  987.   if (rd_on() == 0)
  988.     printf("%s",get_string(746)); 
  989.   comstr("|Y00000100|@5S2X\\");
  990. #ifdef RIPDRIVE
  991.   if (rd_on())
  992.     comr(stripfn(u->filename));
  993.   else
  994. #endif
  995.     pl(stripfn(u->filename));
  996.  
  997.   if (rd_on() == 0)
  998.     printf("%s",get_string(748)); 
  999.   comstr("|Y00000100|@CE39\\");
  1000. #ifdef RIPDRIVE
  1001.   if (rd_on()) {
  1002.     sprintf(s,"%ldk (%s)\r\n", bytes_to_k(u->numbytes), ctim(u->numbytes));
  1003.     comstr(s);
  1004.   } else
  1005. #endif
  1006.     npr("%ldk (%s)\r\n", bytes_to_k(u->numbytes), ctim(u->numbytes));
  1007.  
  1008.   if (rd_on() == 0)
  1009.     printf("%s",get_string(749)); 
  1010.   comstr("|@AO49\\");
  1011. #ifdef RIPDRIVE
  1012.   if (rd_on())
  1013.     comr(ctim(d));
  1014.   else
  1015. #endif
  1016.     pl(ctim(d));
  1017.  
  1018.   if (rd_on() == 0)
  1019.     printf("%s",get_string(750)); 
  1020.   comstr("|@6849\\");
  1021. #ifdef RIPDRIVE
  1022.   if (rd_on())
  1023.     comr(u->date);
  1024.   else
  1025. #endif
  1026.     pl(u->date);
  1027.  
  1028.   if (rd_on() == 0)
  1029.     printf("%s",get_string(751)); 
  1030.   comstr("|@5C3X\\");
  1031. #ifdef RIPDRIVE
  1032.   if (rd_on())
  1033.     comr(u->upby);
  1034.   else
  1035. #endif
  1036.     pl(u->upby);
  1037.  
  1038.   if (rd_on() == 0)
  1039.     printf("%s",get_string(752)); 
  1040.   comstr("|@CW3X\\");
  1041. #ifdef RIPDRIVE
  1042.   if (rd_on()) {
  1043.     sprintf(s, "%d", u->numdloads);
  1044.     comr(s);
  1045.   } else
  1046. #endif
  1047.     pln(u->numdloads);
  1048.  
  1049.   if (rd_on() == 0)
  1050.     sprintf(s,"%s%s",directories[dn].path,u->filename);
  1051.   comstr("|@5S39\\");
  1052.   if (!exist(s)) {
  1053.     comr(get_string(1457));
  1054.     if (rd_on() == 0)
  1055.       puts(get_string(754));
  1056.   } else
  1057.     comr(get_string(1458));  
  1058.  
  1059.   if (rd_on() == 0)
  1060.     printf("%s",get_string(747)); 
  1061.   comstr("|Y02000400|@2X51\\");
  1062. #ifdef RIPDRIVE
  1063.   if (rd_on())
  1064.     comr(u->description);
  1065.   else
  1066. #endif
  1067.     pl(u->description);
  1068.  
  1069.   abort=0;
  1070.   if (u->mask & mask_extended) {
  1071.         comr("|1""0000$SAVE1$");
  1072.     if (rd_on() == 0)
  1073.       puts(get_string(753));
  1074.     ex_line = 0;
  1075.     rip_print_extended(u->filename,&abort,sysinfo.max_extend_lines);
  1076.   }
  1077.  
  1078.   if (!exist(s))
  1079.     return(1);
  1080.  
  1081.   if (nsl()>=d)
  1082.     return(1);
  1083.   else
  1084.     return(0);
  1085. }
  1086.  
  1087. char *ex_p[10] = { "5N\\", "5Y\\", "69\\", "6K\\", "6V\\", "76\\", "7H\\", 
  1088.      "7S\\", "83\\", "8E\\"};
  1089.  
  1090. /* Function: print the extended description in the dialog box, in the
  1091.    correct places */
  1092. void rip_print_extended(char *fn, int *abort, unsigned char numlist)
  1093. {
  1094.   char *ss;
  1095.   int next=0;
  1096.   unsigned char numl=0;
  1097.   int cpos=0;
  1098.   char ch;
  1099.   char s2[4];
  1100.  
  1101.   strcpy(s2,"x\\");
  1102.   comr("|1""0000$RESTORE1$");
  1103.   ss=read_extended_description(fn);
  1104.   if (ss) {
  1105.     while ((numl < ex_line)) {
  1106.       while ((ss[cpos] != 10) && ss[cpos])
  1107.         cpos++;
  1108.       if (ss[cpos] == 0)
  1109.         break;
  1110.       else
  1111.         numl++;
  1112.       cpos++;  
  1113.     }
  1114.     comstr("|Y02000400|@2Z5C\\");
  1115.     while ((ss[cpos] != 0) && (!(*abort)) && (numl < MIN(ex_line+10, 
  1116.          numlist)) && (!hangup)) {
  1117.       ch=ss[cpos++];
  1118.       s2[0] = ch;
  1119.       if (cpos > strlen(ss))
  1120.         break;
  1121.       if (rd_on() == 0)
  1122.         outstr(s2);
  1123.       comstr(s2);
  1124.       if (ch==10) {
  1125.         ++numl;
  1126.         comr("");
  1127.         comstr("|@2Y\\");
  1128.         comstr(ex_p[numl-1-ex_line]);
  1129.       } else
  1130.         if ((ch!=13) && (WhereX()>=78)) {
  1131.           osan("\r",abort,&next);
  1132.           ch=10;
  1133.         }
  1134.     }
  1135.     if (WhereX())              
  1136.       comstr("\r");
  1137.     farfree(ss);
  1138.   }
  1139.   comstr("\r");
  1140.   if (ss[cpos]) {
  1141.     ex_line += 10;
  1142.   } else
  1143.     ex_line = 0;
  1144. }
  1145.  
  1146. void rip_detect(void)
  1147. {
  1148.       strcpy(ripext, "RIP");
  1149.       rip = rip_check();
  1150.       if (rip) {
  1151.         rip_pause = 0;
  1152.         rip_popup = -1;
  1153.         ripcode = rip;
  1154.       }
  1155. }
  1156.  
  1157. /* Interprets a code from the Ctrl-P Ctrl-P sequence, translating it
  1158.    into the correct string. */
  1159. char *interpret(char c)
  1160. {
  1161.   static char s[80];
  1162.  
  1163.   if (g_flags & g_flag_disable_mci)
  1164.     return("");
  1165.  
  1166.   switch (c) {
  1167.     case '@':                   // Dir name
  1168.       strcpy(s, directories[udir[curdir].subnum].name);
  1169.       break;
  1170.     case '~':                   // Total mails/feedbacks sent
  1171.       sprintf(s, "%u", thisuser.emailsent + thisuser.feedbacksent+thisuser.emailnet);
  1172.       break;
  1173.     case '/':                   // Today's date
  1174.       strcpy(s, date());
  1175.       break;
  1176.     case '%':                   // Time left today
  1177.       //sprintf(s, "%f", thisuser.extratime);
  1178.       sprintf(s, "%d", (int)(nsl()/60));
  1179.       break;
  1180.     case '#':                   // User's number
  1181.       sprintf(s, "%u", usernum);
  1182.       break;
  1183.     case '$':                   // File points
  1184.       sprintf(s, "%lu", thisuser.filepoints);
  1185.       break;
  1186.     case '*':                   // User reg num
  1187.       sprintf(s, "%lu", thisuser.wwiv_regnum);
  1188.       break;
  1189.     case '-':                   // Aggravation points
  1190.       sprintf(s, "%u", thisuser.ass_pts);
  1191.       break;
  1192.     case ':':                   // Sub number
  1193.       strcpy(s, usub[cursub].keys);
  1194.       break;
  1195.     case ';':                   // Directory number
  1196.       strcpy(s, udir[curdir].keys);
  1197.       break;
  1198.     case '!':                   // Built-in pause
  1199.       pausescr();
  1200.       break;
  1201.     case '&':                   // RIP/ANSI/ASCII mode
  1202.       if (rip)
  1203.         strcpy(s, "RIPspeed");
  1204.       else if (thisuser.sysstatus & sysstatus_ansi)
  1205.         strcpy(s, "ANSI");
  1206.       else
  1207.         strcpy(s, "ASCII");
  1208.       break;
  1209.     case 'A':                   // User's age
  1210.       sprintf(s, "%d", thisuser.age);
  1211.       break;
  1212.     case 'a':                   // User's language
  1213.       strcpy(s, cur_lang_name);
  1214.       break;
  1215.     case 'B':                   // User's birthday
  1216.       sprintf(s, "%d/%d/%d", thisuser.month, thisuser.day, thisuser.year);
  1217.       break;
  1218.     case 'b':                   // Minutes in bank
  1219.       sprintf(s, "%u", thisuser.banktime);
  1220.       break;
  1221.     case 'C':                   // User's city
  1222.       strcpy(s, thisuser.city);
  1223.       break;
  1224.     case 'c':                   // User's country
  1225.       strcpy(s, thisuser.country);
  1226.       break;
  1227.     case 'D':                   // Files downloaded
  1228.       sprintf(s, "%u", thisuser.downloaded);
  1229.       break;
  1230.     case 'd':                   // User's DSL
  1231.       sprintf(s, "%d", thisuser.dsl);
  1232.       break;
  1233.     case 'E':                   // E-mails sent
  1234.       sprintf(s, "%u", thisuser.emailsent);
  1235.       break;
  1236.     case 'e':                   // Net E-mails sent
  1237.       sprintf(s, "%u", thisuser.emailnet);
  1238.       break;
  1239.     case 'F':
  1240.       sprintf(s, "%u", thisuser.feedbacksent);
  1241.       break;
  1242.     case 'f':                   // First time user called
  1243.       strcpy(s, thisuser.firston);
  1244.       break;
  1245.     case 'G':                   // MessaGes read
  1246.       sprintf(s, "%lu", thisuser.msgread);
  1247.       break;
  1248.     case 'g':                   // Gold
  1249.       sprintf(s, "%f", thisuser.gold);
  1250.       break;
  1251.     case 'I':                   // User's call sIgn
  1252.       strcpy(s, thisuser.callsign);
  1253.       break;
  1254.     case 'i':                   // Illegal log-ons
  1255.       sprintf(s, "%u", thisuser.illegal);
  1256.       break;
  1257.     case 'J':                   // Message conference
  1258.       strcpy(s, subconfs[uconfsub[curconfsub].confnum].name);
  1259.       break;
  1260.     case 'j':                   // Transfer conference
  1261.       strcpy(s, dirconfs[uconfdir[curconfdir].confnum].name);
  1262.       break;
  1263.     case 'K':                   // Kb uploaded
  1264.       sprintf(s, "%lu", thisuser.uk);
  1265.       break;
  1266.     case 'k':                   // Kb downloaded
  1267.       sprintf(s, "%lu", thisuser.dk);
  1268.       break;
  1269.     case 'L':                   // Last call
  1270.       strcpy(s, thisuser.laston);
  1271.       break;
  1272.     case 'l':                   // Number of logons
  1273.       sprintf(s, "%u", thisuser.logons);
  1274.       break;
  1275.     case 'M':                   // Mail waiting
  1276.       sprintf(s, "%d", thisuser.waiting);
  1277.       break;
  1278.     case 'm':                   // Messages posted
  1279.       sprintf(s, "%u", thisuser.msgpost);
  1280.       break;
  1281.     case 'N':                   // User's name
  1282.       strcpy(s, thisuser.name);
  1283.       break;
  1284.     case 'n':                   // Sysop's note
  1285.       strcpy(s, thisuser.note);
  1286.       break;
  1287.     case 'O':                   // Times on today
  1288.       sprintf(s, "%d", thisuser.ontoday);
  1289.       break;
  1290.     case 'o':                   // Time on today
  1291.       //sprintf(s, "%f", thisuser.timeontoday);
  1292.       sprintf(s,"%ld",(long)((thisuser.timeon+timer()-timeon)/60.0));
  1293.       break;
  1294.     case 'P':                   // BBS phone
  1295.       strcpy(s, syscfg.systemphone);
  1296.       break;
  1297.     case 'p':                   // User's phone
  1298.       strcpy(s, thisuser.dataphone);
  1299.       break;
  1300.     case 'R':                   // User's real name
  1301.       strcpy(s, thisuser.realname);
  1302.       break;
  1303.     case 'r':                   // Last baud rate
  1304.       sprintf(s, "%d", thisuser.lastrate);
  1305.       break;
  1306.     case 'S':                   // User's SL
  1307.       sprintf(s, "%d", thisuser.sl);
  1308.       break;
  1309.     case 's':                   // User's street address
  1310.       strcpy(s, thisuser.street);
  1311.       break;
  1312.     case 'T':                   // User's sTate
  1313.       strcpy(s, thisuser.state);
  1314.       break;
  1315.     case 't':                   // Current time
  1316.       strcpy(s, times());
  1317.       break;
  1318.     case 'U':                   // Files uploaded
  1319.       sprintf(s, "%u", thisuser.uploaded);
  1320.       break;
  1321.     case 'u':                   // Current sub
  1322.       strcpy(s, subboards[usub[cursub].subnum].name);
  1323.       break;
  1324.     case 'W':                   // Total # of messages in sub
  1325.       sprintf(s, "%d", nummsgs);
  1326.       break;
  1327.     case 'X':                   // User's sex
  1328.       sprintf(s, "%c", thisuser.sex);
  1329.       break;
  1330.     case 'Y':                   // Your BBS name
  1331.       strcpy(s, syscfg.systemname);
  1332.       break;
  1333.     case 'y':                   // Computer type
  1334.       strcpy(s, ctypes[thisuser.comp_type]);
  1335.       break;
  1336.     case 'Z':                   // User's zip code
  1337.       strcpy(s, thisuser.zipcode);
  1338.       break;
  1339.     default:
  1340.       return "";
  1341.   }
  1342.  
  1343.   return s;
  1344. }
  1345.  
  1346. int todownload(char array[][13], int start, char *fspec, char *fpath)
  1347. {
  1348.   int f, qflag, count, pos=0;
  1349.   struct ffblk ffb;
  1350.   struct ftime tim;
  1351.   char fn[67];
  1352.   char s[80], s2[80], ch;
  1353.  
  1354.   count = start;
  1355.   strcpy(fn, fpath);
  1356.   strcat(fn, fspec);
  1357.   qflag = findfirst(fn, &ffb, FA_ARCH);
  1358.  
  1359.   npr("%s %s...\r\n", get_string(1637), fspec);
  1360.   while ((qflag==0) && (!hangup)) {
  1361.     strcpy(fn, fpath);
  1362.     strcat(fn, ffb.ff_name);
  1363.     f=sh_open1(fn,O_RDONLY | O_BINARY);
  1364.     getftime(f,&tim);
  1365.     sh_close(f);
  1366.  
  1367.     strcpy(fn, ffb.ff_name);
  1368.     if (strncmp(fn, "RIPEXT.MN", 9) == 0)
  1369.       fn[strlen(fn) - 1] = 'U';
  1370.  
  1371.     /* Adjust RIPscrip 2.0 BMP filenames so they will work */
  1372.     if (strncmp(&fn[strlen(fn)-3], "BM", 2) == 0) {
  1373.       fn[strlen(fn)-3] = 'I';
  1374.       fn[strlen(fn)-2] = 'C';
  1375.     }
  1376.  
  1377.     sprintf(s2,"|1F030000%s\r\n",fn);
  1378.     comstr(s2);
  1379.     pos = 0;
  1380.     ch = getkey();
  1381.     while ((ch != 13) && (!hangup)) {
  1382.       s[pos++] = ch;
  1383.       ch = getkey();
  1384.     }
  1385.     s[pos] = 0;
  1386.     sprintf(s2,"1.%ld.%02d/%02d/%02d.%02d:%02d:%02d", ffb.ff_fsize,
  1387.       tim.ft_month, tim.ft_day, tim.ft_year+80, tim.ft_hour,
  1388.       tim.ft_min, (tim.ft_tsec*2));
  1389.     if (strcmp(s,s2))    // Files match
  1390.       strncpy(array[count++], ffb.ff_name, 13);
  1391.     qflag = findnext(&ffb);
  1392.   }
  1393.   return count;
  1394. }
  1395.  
  1396. void menuxfer(char *fpath, char files[][13], int num, int *sent, double *percent)
  1397. {
  1398.   char bn,ch,s[81];
  1399.   int f,i,abort,terr,xx1,yy1;
  1400.   char fn[67];
  1401.   long cp,len;
  1402.   int ucrc;
  1403.   double tpb;
  1404.  
  1405.   int count = 0;
  1406.  
  1407.   abort=0;
  1408.  
  1409.   /* Trim the filename off, leaving the path intact */
  1410.   while ((count < num) && (!abort) && (!hangup)) {
  1411.     strcpy(fn, fpath);
  1412.     strcat(fn, files[count]);
  1413.     ucrc = 1;
  1414.     *percent = 0;
  1415.     *sent = 0;
  1416.     cp=0L;
  1417.     bn=1;
  1418.     terr=0;
  1419.  
  1420.     f=sh_open1(fn,O_RDONLY | O_BINARY);
  1421.     len=filelength(f);
  1422.     if (!len)
  1423.       len=1;
  1424.     tpb=(12.656) / ((double) (modem_speed));
  1425.  
  1426.     xx1=WhereX();
  1427.     yy1=WhereY();
  1428.     movecsr(52,0);
  1429.     outs(get_stringx(1,67));
  1430.     movecsr(52,1);
  1431.     outs(get_stringx(1,68));
  1432.     movecsr(52,2);
  1433.     outs(get_stringx(1,69));
  1434.     movecsr(52,3);
  1435.     outs(get_stringx(1,70));
  1436.     movecsr(52,4);
  1437.     outs(get_stringx(1,71));
  1438.     movecsr(52,5);
  1439.     outs(get_stringx(1,72));
  1440.     movecsr(52,6);
  1441.     outs(get_stringx(1,73));
  1442.     movecsr(65,0);
  1443.  
  1444.     strcpy(fn, files[count]);
  1445.     /* Adjust the menu extension and Hot icon file names */
  1446.     /* Do this by looking at three of the last four characters */
  1447.     /* And then setting the last character based on a match */
  1448.     if (strncmp(fn, "RIPEXT.MN", 9) == 0)
  1449.       fn[strlen(fn) - 1] = 'U';
  1450.  
  1451.     /* Adjust RIPscrip 2.0 BMP filenames so they will work */
  1452.     if (strncmp(&fn[strlen(fn)-3], "BM", 2) == 0) {
  1453.       fn[strlen(fn)-3] = 'I';
  1454.       fn[strlen(fn)-2] = 'C';
  1455.     }
  1456.  
  1457.     outs(stripfn(fn));
  1458.  
  1459.     sprintf(s,"%ld - %ldk", (len+127)/128, bytes_to_k(len));
  1460.     movecsr(65,2);
  1461.     outs(s);
  1462.  
  1463.     if (!okstart(&ucrc,&abort))
  1464.       abort=1;
  1465.     if ((!abort) && (!hangup)) {
  1466.       ch=send_b(f, len, 5, 0, &ucrc,fn,&terr,&abort);
  1467.       if (ch==24)
  1468.         abort=1;
  1469.       if (ch==21) {
  1470.         send_b(f,0L,3,0,&ucrc,fn,&terr,&abort);
  1471.         abort=1;
  1472.       }
  1473.     }
  1474.     while ((!hangup) && (!abort) && (cp<len)) {
  1475.       i=1;
  1476.       if ((len-cp)<768L)
  1477.         i=0;
  1478.       sprintf(s,"%ld - %ldk",
  1479.         cp/128+1,
  1480.         cp/1024+1);
  1481.       movecsr(65,3);
  1482.       outs(s);
  1483.       movecsr(65,1);
  1484.       outs(ctim(((double)(len-cp))*tpb));
  1485.       movecsr(69,4);
  1486.       outs("0");
  1487.  
  1488.       ch=send_b(f,cp,i,bn,&ucrc,fn,&terr,&abort);
  1489.       if (ch==24)
  1490.         abort=1;
  1491.       else
  1492.         if (ch==21) {
  1493.           wait1(18);
  1494.           dump();
  1495.           send_b(f,0L,3,0,&ucrc,fn,&terr,&abort);
  1496.           abort=1;
  1497.         } else {
  1498.           ++bn;
  1499.           if (i)
  1500.             cp+=1024;
  1501.           else
  1502.             cp+=128;
  1503.         }
  1504.     }
  1505.     if ((!hangup) && (!abort))
  1506.       send_b(f,0L,2,0,&ucrc,fn,&terr,&abort);
  1507.     if (!abort) {
  1508.       *sent=1;
  1509.       *percent=1.0;
  1510.     } else {
  1511.       *sent=0;
  1512.       if (i)
  1513.         cp+=1024;
  1514.       else
  1515.         cp+=128;
  1516.       if (cp>=len)
  1517.         *percent=1.0;
  1518.       else {
  1519.         if (i)
  1520.           cp-=1024;
  1521.         else
  1522.           cp-=128;
  1523.         *percent=((double)(cp))/((double)(len));
  1524.       }
  1525.     }
  1526.     sh_close(f);
  1527.     movecsr(xx1,yy1);
  1528.     count++;
  1529.   }
  1530. }
  1531.  
  1532. int rip_file(char *fn, ripmsgrec *m, int maxary)
  1533. {
  1534.   int i,i1,i2,cnt;
  1535.   char *buf,s[81];
  1536.   long l,l1;
  1537.  
  1538.   for (i=0; i<maxary; i++) {
  1539.     m[i].stored_as=-1L;
  1540.     m[i].storage_type=255;
  1541.     m[i].menu_num=0;
  1542.   }
  1543.   sprintf(s,"%s%s",languagedir,fn);
  1544.   i=sh_open1(s,O_RDONLY | O_BINARY);
  1545.   if (i<0) {
  1546.     return(1);
  1547.   }
  1548.   l=filelength(i);
  1549.   buf=(char *) malloca(l);
  1550.   sh_lseek(i,0L,SEEK_SET);
  1551.   if (buf==NULL) {
  1552.     printf(get_string(1617));
  1553.     end_bbs(noklevel);
  1554.   }
  1555.   sh_read(i,(void *) buf,l);
  1556.   sh_close(i);
  1557.   i1=cnt=0;
  1558.   for (l1=0; l1<l; l1++) {
  1559.     if ((buf[l1]=='`') && ((l1==0) || (buf[l1-1]==10))) {
  1560.       i1=1;
  1561.       i2=0;
  1562.     } else {
  1563.       if (i1) {
  1564.         if ((buf[l1]>='0') && (buf[l1]<='9')) {
  1565.           i2*=10;
  1566.           i2+=(buf[l1])-'0';
  1567.         } else {
  1568.           while ((l1<l) && (buf[l1]!=10))
  1569.             ++l1;
  1570.           ++l1;
  1571.           if ((i2>=0) && (cnt<maxary)) {
  1572.             m[cnt].stored_as=l1;
  1573.             m[cnt++].menu_num=i2;
  1574.           }
  1575.           i1=0;
  1576.         }
  1577.       }
  1578.     }
  1579.   }
  1580.   bbsfree((void *) buf);
  1581.  
  1582.   return(0);
  1583. }
  1584.  
  1585. void rd_disable(void)
  1586. {
  1587.   localrip_deactivate();
  1588.   defscreenbottom=(int) peekb(0x0000,0x0484);
  1589.   if (defscreenbottom<24)
  1590.     defscreenbottom=24;
  1591.   if (defscreenbottom>63)
  1592.     defscreenbottom=24;
  1593.   if ((defscreenbottom!=42) && (defscreenbottom!=49))
  1594.     defscreenbottom=24;
  1595.   screenlinest=defscreenbottom+1;
  1596.   screenbottom=defscreenbottom;
  1597.   screenlen=160*(screenbottom+1);
  1598. }
  1599.  
  1600. void rip_list_qscan(int start)
  1601. {
  1602.   int i,abort;
  1603.   char s[81];
  1604.   abort=0;
  1605.   printmenu(323);
  1606.   for (i=0;(start<num_subs)&& (i<thisuser.screenlines-5) &&
  1607.    (usub[start].subnum!=-1)&&(!abort) && (!hangup);start++,i++) {
  1608.         sprintf(s,"2%cDB",
  1609.     (qsc_q[usub[start].subnum/32]&
  1610.     (1L<<(usub[start].subnum%32)))?'*':' ');
  1611.     outstr(s);
  1612.   } 
  1613. }
  1614.  
  1615. void rip_config_qscan(void)
  1616. {
  1617.   char s[200], *k;
  1618.   int i,done,start=0;
  1619.   done=0;
  1620.   helpl=7;
  1621.   do {
  1622.     printmenu(323);
  1623.     sprintf(s,"|c09|@FO2MPage %d/%d|c0E", start / 14 + 1, (num_subs+13) / 14);
  1624.     comr(s);
  1625.         for (i=start; (i < MIN(num_subs, start+14)) && (usub[start].subnum != -1) &&
  1626.          (!hangup); i++) {
  1627.       if ((i+1)*10 < num_subs)     // Add any necessary CR
  1628.         sprintf(s,"|1U%s0000<>%c[%s] %-35.35s<>%s^M", pos[i-start][0], 
  1629.          (qsc_q[usub[i].subnum / 32] & (1L << (usub[i].subnum % 32))) ? 
  1630.          '*': ' ', usub[i].keys, subboards[usub[i].subnum].name, 
  1631.          usub[i].keys);
  1632.       else
  1633.         sprintf(s,"|1U%s0000<>%c[%s] %-35.35s<>%s", pos[i-start][0], 
  1634.          (qsc_q[usub[i].subnum / 32] & (1L << (usub[i].subnum % 32))) ? 
  1635.          '*': ' ', usub[i].keys, subboards[usub[i].subnum].name, 
  1636.          usub[i].keys);
  1637.       comr(s);
  1638.     } 
  1639.  
  1640.     if (rip_ver >= 20000)         // Fix window in RIP 2.0
  1641.       comr("|w0013271610");
  1642.  
  1643.     nl();
  1644.     outstr(get_string(1618));
  1645.     k=mmkey(0);
  1646.     switch (k[0]) {
  1647.       case 'Q':
  1648.         rip_cls();
  1649.         printmenu(320);
  1650.         return;
  1651.       case 'N':
  1652.         if (start+14 < num_subs)
  1653.           start += 14;
  1654.         break;
  1655.       case 'P':
  1656.         if (start >= 14)
  1657.           start -= 14;
  1658.         break;
  1659.       default:
  1660.                 for (i=0; (i < num_subs) && (usub[i].subnum != -1) && (!hangup); i++)
  1661.           if (strcmp(usub[i].keys, k) == 0)
  1662.             qsc_q[usub[i].subnum/32] ^= (1L << (usub[i].subnum % 32));
  1663.         break;
  1664.     }
  1665.   } while ((!done) && (!hangup));
  1666. }
  1667.  
  1668.