home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LO241SRV.ZIP / terminal.c < prev    next >
Text File  |  1998-08-01  |  62KB  |  2,156 lines

  1.  
  2. // LoraBBS Version 2.41 Free Edition
  3. // Copyright (C) 1987-98 Marco Maccaferri
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <stdio.h>
  20. #include <dos.h>
  21. #include <conio.h>
  22. #include <time.h>
  23. #include <string.h>
  24. #include <alloc.h>
  25. #include <dir.h>
  26. #include <stdlib.h>
  27. #include <process.h>
  28. #include <ctype.h>
  29. #include <io.h>
  30. #include <fcntl.h>
  31. #include <sys\stat.h>
  32.  
  33. #define INCL_DOSPROCESS
  34. #include <os2.h>
  35.  
  36. #include <cxl\cxlvid.h>
  37. #include <cxl\cxlwin.h>
  38. #include <cxl\cxlkey.h>
  39. #include <cxl\cxlstr.h>
  40.  
  41. #include "lsetup.h"
  42. #include "sched.h"
  43. #include "msgapi.h"
  44. #include "externs.h"
  45. #include "prototyp.h"
  46. #include "exec.h"
  47. #include "zmodem.h"
  48.  
  49. typedef struct {
  50.    char name[36];
  51.    char location[30];
  52.    char phone[30];
  53.    char password[20];
  54.    char download[40];
  55.    char capture[40];
  56.    word speed;
  57.    bit  iemsi        :1;
  58.    bit  local_echo   :1;
  59.    bit  strip_high   :1;
  60.    bit  open_capture :1;
  61.    char filler[256];
  62. } DIALREC;
  63.  
  64. #define BITS_7          0x02
  65.  
  66. extern word serial_no;
  67. extern char *VNUM, serial_id[3];
  68.  
  69. void VioUpdate (void);
  70.  
  71. int spawn_program (int swapout, char *outstring);
  72. void idle_system (void);
  73. void clown_clear (void);
  74. int get_emsi_field (char *);
  75. void m_print2(char *format, ...);
  76. void general_external_protocol (char *name, char *path, int id, int global, int dl);
  77.  
  78. static FILE *open_capture (char *predefined);
  79. static void capture_closed (void);
  80. static void close_capture (FILE *fp_cap);
  81. static void keyboard_loop (void);
  82. static void pull_down_menu (void);
  83. static void set_selection (void);
  84. static void translate_ansibbs (void);
  85. static void translate_avatar (void);
  86. static int  exit_confirm (void);
  87. static void terminal_select_file (char *title, int upload, DIALREC *dialrec);
  88. static void terminal_iemsi_handshake (char *password);
  89. static void dial_entry (DIALREC *dialrec);
  90. static int  dialing_directory (DIALREC *dialrec);
  91. static void translate_phone (char *phone);
  92.  
  93. static char interpoint = ':', expand_cr = 0, local_echo = 0, doorway = 0;
  94. static int last_sel = -1, vx, vy, ansi_attr;
  95. static long online_elapsed = 0L, clocks = 0L;
  96.  
  97. void update_statusline (void)
  98. {
  99.    char string[90];
  100.  
  101.    if (doorway)
  102.       return;
  103.  
  104.    wactiv (status);
  105.    sprintf (string, "COM%d │ %6lu %s", com_port + 1, rate, "N81");
  106.    wprints (0, 23, LGREY|_BLUE, string);
  107.    wactiv (mainview);
  108. }
  109.  
  110. void change_baud (void)
  111. {
  112.    int m;
  113.  
  114.    hidecur ();
  115.  
  116.    wopen (6, 52, 17, 62, 3, LCYAN|_BLACK, CYAN|_BLACK);
  117.    wshadow (DGREY|_BLACK);
  118.    wtitle (" Speed ", TRIGHT, YELLOW|_BLUE);
  119.  
  120.    wmenubegc ();
  121.    wmenuitem (1, 1, "   300 ", 0,   300, 0, NULL, 0, 0);
  122.    wmenuitem (2, 1, "  1200 ", 0,  1200, 0, NULL, 0, 0);
  123.    wmenuitem (3, 1, "  2400 ", 0,  2400, 0, NULL, 0, 0);
  124.    wmenuitem (4, 1, "  4800 ", 0,  4800, 0, NULL, 0, 0);
  125.    wmenuitem (5, 1, "  9600 ", 0,  9600, 0, NULL, 0, 0);
  126.    wmenuitem (6, 1, " 19200 ", 0, 19200, 0, NULL, 0, 0);
  127.    wmenuitem (7, 1, " 38400 ", 0, 38400U, 0, NULL, 0, 0);
  128.    wmenuitem (8, 1, " 57600 ", 0, 57600U, 0, NULL, 0, 0);
  129.    wmenuend ((unsigned)rate, M_OMNI|M_SAVE, 0, 0, LGREY|_BLACK, LGREY|_BLACK, LGREY|_BLACK, BLUE|_LGREY);
  130.  
  131.    m = wmenuget ();
  132.    wclose ();
  133.  
  134.    if (m != -1) {
  135.       rate = m;
  136.       com_baud (rate);
  137.       update_statusline ();
  138.    }
  139.  
  140.    showcur ();
  141. }
  142.  
  143. int MODEM_AVAILABLE (void)
  144. {
  145.    long t;
  146.  
  147.    if (CHAR_AVAIL ())
  148.       return (CHAR_AVAIL ());
  149.  
  150.    t = timerset (10);
  151.    while (!timeup (t)) {
  152.       if (CHAR_AVAIL ())
  153.          return (CHAR_AVAIL ());
  154.    }
  155.  
  156.    return (CHAR_AVAIL ());
  157. }
  158.  
  159. static long get_phone_cost (char *phone, long online)
  160. {
  161.    int fd, dcost, dtime, cost_first, time_first, ora, wd, c1, c2, c3, c4, i;
  162.    char filename[80], rep, deftrasl[60];
  163.    long cost, tempo;
  164.    struct tm *tim;
  165.    ACCOUNT ai;
  166.  
  167.    dcost = dtime = cost_first = time_first = 0;
  168.    c1 = c2 = c3 = c4 = 0;
  169.    rep = 0;
  170.    deftrasl[0] = '\0';
  171.  
  172.    sprintf (filename, "%sCOST.DAT", config->net_info);
  173.    fd = sh_open (filename, SH_DENYNONE, O_RDONLY|O_BINARY, S_IREAD|S_IWRITE);
  174.  
  175.    while (read (fd, (char *)&ai, sizeof (ACCOUNT)) == sizeof (ACCOUNT)) {
  176.       if (!strncmp (phone, ai.search, strlen (ai.search))) {
  177.          tempo = time (NULL);
  178.          tim = localtime (&tempo);
  179.          ora = tim->tm_hour * 60 + tim->tm_sec;
  180.          wd = 1 << tim->tm_wday;
  181.  
  182.          for (i = 0; i < MAXCOST; i++)
  183.             if ((ai.cost[i].days & wd)) {
  184.                if (ai.cost[i].start < ai.cost[i].stop) {
  185.                   if (ora >= ai.cost[i].start && ora <= ai.cost[i].stop) {
  186.                      dcost = ai.cost[i].cost;
  187.                      dtime = ai.cost[i].time;
  188.                      cost_first = ai.cost[i].cost_first;
  189.                      time_first = ai.cost[i].time_first;
  190.                      break;
  191.                   }
  192.                }
  193.                else {
  194.                   if (ora >= ai.cost[i].start && ora <= 1439) {
  195.                      dcost = ai.cost[i].cost;
  196.                      dtime = ai.cost[i].time;
  197.                      cost_first = ai.cost[i].cost_first;
  198.                      time_first = ai.cost[i].time_first;
  199.                      break;
  200.                   }
  201.                   if (ora >= 0 && ora <= ai.cost[i].stop) {
  202.                      dcost = ai.cost[i].cost;
  203.                      dtime = ai.cost[i].time;
  204.                      cost_first = ai.cost[i].cost_first;
  205.                      time_first = ai.cost[i].time_first;
  206.                      break;
  207.                   }
  208.                }
  209.             }
  210.  
  211.          rep = 1;
  212.          break;
  213.       }
  214.       else if (!strcmp (ai.search, "/")) {
  215.          strcpy (deftrasl, ai.traslate);
  216.          c1 = ai.cost[i].cost;
  217.          c2 = ai.cost[i].time;
  218.          c3 = ai.cost[i].cost_first;
  219.          c4 = ai.cost[i].time_first;
  220.       }
  221.    }
  222.  
  223.    if (!rep && deftrasl[0]) {
  224.       dcost = c1;
  225.       dtime = c2;
  226.       cost_first = c3;
  227.       time_first = c4;
  228.    }
  229.  
  230.    close (fd);
  231.  
  232.    online *= 10L;
  233.  
  234.    if (time_first) {
  235.       if (online > (long)time_first) {
  236.          cost = (long)cost_first;
  237.          online -= (long)time_first;
  238.       }
  239.       else
  240.          cost = 0L;
  241.    }
  242.    else
  243.       cost = 0L;
  244.  
  245.    if (online <= 0L)
  246.       return (cost);
  247.  
  248.    if (dtime) {
  249.       cost += (online / (long)dtime) * (long)dcost;
  250.       if ((online % (long)dtime) != 0)
  251.          cost += (long)dcost;
  252.    }
  253.  
  254.    return (cost);
  255. }
  256.  
  257. void terminal_emulator ()
  258. {
  259.    FILE *fp_cap;
  260.    int i, relflag, cdflag = -1, *varr, *varr2, pos, m;
  261.    char string[90], c, *cmd, cmdname[60];
  262.    DIALREC dir;
  263.    long olc, origrate;
  264.  
  265.    setkbloop (NULL);
  266.    status_line ("+Starting terminal emulator");
  267.  
  268.    varr = ssave ();
  269.    clown_clear ();
  270.  
  271.    mainview = wopen (0, 0, 23, 79, 5, LGREY|_BLACK, LGREY|_BLACK);
  272.    wactiv (mainview);
  273.  
  274.    local_echo = expand_cr = 0;
  275.    com_baud (config->speed);
  276.    origrate = rate = config->speed;
  277.  
  278.    status = wopen (24, 0, 24, 79, 5, LGREY|_BLUE, LGREY|_BLUE);
  279.    wactiv (status);
  280.    sprintf (string, " ALT-Z for Menu      │ COM%d │ %6lu %s │    │          │       │            ", com_port + 1, rate, "N81");
  281.    wprints (0, 0, LGREY|_BLUE, string);
  282.    wprints (0, 48, LGREY|_BLUE, config->avatar ? "Ansi/Avt" : "Ansi");
  283.  
  284.    wactiv (mainview);
  285.    showcur ();
  286.  
  287.    memset (&dir, 0, sizeof (DIALREC));
  288.    fp_cap = NULL;
  289.    remote_capabilities = 0;
  290.    pos = 0;
  291.    caller = 0;
  292.    emulator = 1;
  293.    ansi_attr = 7;
  294.    keyboard_loop ();
  295.    mdm_sendcmd (config->term_init);
  296.  
  297.    XON_DISABLE ();
  298.    _BRK_DISABLE ();
  299.  
  300.    for (;;) {
  301.       relflag = 1;
  302.  
  303.       if ((Com_(0x03) & config->carrier_mask)) {
  304.          if (cdflag != 1) {
  305.             hidecur ();
  306.             prints (24, 67, LGREY|_BLUE, "Online 00:00");
  307.             online_elapsed = time (NULL);
  308.  
  309.             if (mdm_flags == NULL) {
  310.                status_line (msgtxt[M_READY_CONNECT], rate, "", "");
  311.                mdm_flags = "";
  312.             }
  313.             else
  314.                status_line (msgtxt[M_READY_CONNECT], rate, "/", mdm_flags);
  315.  
  316.             showcur ();
  317.             cdflag = 1;
  318.          }
  319.       }
  320.       else {
  321.          if (cdflag != 0) {
  322.             hidecur ();
  323.             prints (24, 0, LGREY|_BLUE, " ALT-Z for Menu      ");
  324.             prints (24, 67, LGREY|_BLUE, "  Offline   ");
  325.  
  326.             if (online_elapsed)
  327.                online_elapsed = time (NULL) - online_elapsed;
  328.  
  329.             if (online_elapsed) {
  330.                mdm_flags = NULL;
  331.  
  332.                if (dir.phone[0])
  333.                   olc = get_phone_cost (dir.phone, online_elapsed);
  334.                else
  335.                   olc = 0L;
  336.                status_line ("*Session with '%s' Time: %ld:%02ld, Cost: $%ld.%02ld", dir.phone[0] ? dir.name : "Unknown", online_elapsed / 60L, online_elapsed % 60L, olc / 100L, olc % 100L);
  337.  
  338.                wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  339.                wshadow (LGREY|_BLACK);
  340.                sprintf (string, "Connect time %ld:%02ld min.", online_elapsed / 60L, online_elapsed % 60L);
  341.                wcenters (1, LGREY|_BLACK, string);
  342.                timer (15);
  343.                wclose ();
  344.             }
  345.  
  346.             online_elapsed = 0L;
  347.             showcur ();
  348.             cdflag = 0;
  349.  
  350.             rate = origrate;
  351.             com_baud (rate);
  352.  
  353.             if (fp_cap != NULL) {
  354.                close_capture (fp_cap);
  355.                capture_closed ();
  356.             }
  357.  
  358.             update_statusline ();
  359.          }
  360.       }
  361.  
  362.       if (CHAR_AVAIL ()) {
  363.          relflag = 0;
  364.          m = 0;
  365.          while (MODEM_AVAILABLE ()) {
  366.             c = MODEM_IN ();
  367.             if (dir.strip_high)
  368.                c &= 0x7F;
  369.  
  370.             if (c == 0x1B)
  371.                translate_ansibbs ();
  372.             else if (c == CTRLV && config->avatar)
  373.                translate_avatar ();
  374.             else if (c == CTRLY && config->avatar) {
  375.                c = TIMED_READ (2);
  376.                i = TIMED_READ (2);
  377.                for (; i > 0; i--)
  378.                   wputc (c);
  379.             }
  380.             else if (c == CTRLG) {
  381.            DosBeep (1000, 30);
  382.             }
  383.             else if (c == CTRLL)
  384.                wclear ();
  385.             else {
  386.                if (fp_cap != NULL)
  387.                   fputc (c, fp_cap);
  388.  
  389.                wputc (c);
  390.                if (c == 0x0D && expand_cr)
  391.                  wputc ('\n');
  392.  
  393.                if (c != 0x0A) {
  394.                   string[pos++] = c;
  395.                   string[pos] = '\0';
  396.                }
  397.  
  398.                if (c == 0x0D) {
  399.                   if (config->autozmodem && strstr (string, "rz\r") != NULL) {
  400.                      get_emsi_id (string, 6);
  401.                      if (strstr (string, "**") != NULL) {
  402.                         if (dir.download[0])
  403.                            get_Zmodem (dir.download, NULL);
  404.                         else
  405.                            get_Zmodem (config->dl_path, NULL);
  406.                         XON_DISABLE ();
  407.                         _BRK_DISABLE ();
  408.                      }
  409.                   }
  410.                   else if (!stricmp (string, "**EMSI_IRQ8E08\r")) {
  411.                      if (dir.phone[0]) {
  412.                         if (dir.iemsi)
  413.                            terminal_iemsi_handshake (dir.password);
  414.                      }
  415.                      else if (config->iemsi_on)
  416.                         terminal_iemsi_handshake (NULL);
  417.                   }
  418.                   pos = 0;
  419.                }
  420.                else if (pos > 80)
  421.                   pos = 0;
  422.             }
  423.  
  424.             if (++m > (rate / 10))
  425.                break;
  426.          }
  427.       }
  428.       else
  429.      VioUpdate ();
  430.  
  431.       if (kbmhit ()) {
  432.          i = getxch ();
  433.          if (kbstat () & SCRLOCK) {
  434.             if (!(i & 0xFF)) {
  435.                SENDBYTE (0);
  436.                SENDBYTE ((i & 0xFF00) >> 8);
  437.             }
  438.             else
  439.                SENDBYTE (i & 0xFF);
  440.          }
  441.          else if ( !(i & 0xFF)) {
  442.             // ALT-X Uscita
  443.             if (i == 0x2D00) {
  444.                if (exit_confirm ())
  445.                   break;
  446.             }
  447.  
  448.             switch (i) {
  449.                // Alt-E Local echo
  450.                case 0x1200:
  451.                   local_echo = local_echo ? 0 : 1;
  452.                   break;
  453.  
  454.                // ALT-D Dialing directory
  455.                case 0x2000:
  456.                   if (dialing_directory (&dir) >= 0) {
  457.                      dial_entry (&dir);
  458.                      if (CARRIER) {
  459.                         if (dir.open_capture) {
  460.                            close_capture (fp_cap);
  461.                            fp_cap = open_capture (dir.capture);
  462.                         }
  463.  
  464.                         update_statusline ();
  465.                         sprintf (string, " %-19.19s", dir.name);
  466.                         prints (24, 0, LGREY|_BLUE, string);
  467.  
  468.                         if (!config->lock_baud)
  469.                            com_baud (rate);
  470.                      }
  471.                      else
  472.                         memset (&dir, 0, sizeof (DIALREC));
  473.                   }
  474.                   else
  475.                      memset (&dir, 0, sizeof (DIALREC));
  476.                   break;
  477.  
  478.                // ALT-B Change baud rate
  479.                case 0x3000:
  480.                   change_baud ();
  481.                   origrate = rate;
  482.                   break;
  483.  
  484.                // ALT-R Reset timer
  485.                case 0x1300:
  486.                   if (online_elapsed)
  487.                      online_elapsed = time (NULL);
  488.                   break;
  489.  
  490.                // ALT-C Cls
  491.                case 0x2E00:
  492.                   wclear ();
  493.                   break;
  494.  
  495.                // ALT-I Reinizializza il modem
  496.                case 0x1700:
  497.                   mdm_sendcmd (config->term_init);
  498.                   break;
  499.  
  500.                // ALT-L Capture ON/OFF
  501.                case 0x2600:
  502.                   if (fp_cap != NULL) {
  503.                      close_capture (fp_cap);
  504.                      capture_closed ();
  505.                      fp_cap = NULL;
  506.                   }
  507.                   else
  508.                      fp_cap = open_capture (NULL);
  509.                   break;
  510.  
  511.                // ALT-N Send user's name
  512.                case 0x3100:
  513.                   wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  514.                   wshadow (LGREY|_BLACK);
  515.  
  516.                   wcenters (1, LGREY|_BLACK, "Sending user name");
  517.                   m_print ("%s", config->sysop);
  518.  
  519.                   timer (20);
  520.                   wclose ();
  521.                   break;
  522.  
  523.                // ALT-S Send active password
  524.                case 0x1F00:
  525.                   if (dir.password[0]) {
  526.                      wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  527.                      wshadow (LGREY|_BLACK);
  528.  
  529.                      wcenters (1, LGREY|_BLACK, "Sending active password");
  530.                      m_print ("%s", dir.password);
  531.  
  532.                      timer (20);
  533.                      wclose ();
  534.                   }
  535.                   break;
  536.  
  537.                // ALT-Z Menu' pull-down
  538.                case 0x2C00:
  539.                   pull_down_menu ();
  540.                   break;
  541.  
  542.                // ALT-J DOS Shell
  543.                case 0x2400:
  544.                   getcwd (string, 79);
  545.                   cmd = getenv ("COMSPEC");
  546.                   strcpy (cmdname, (cmd == NULL) ? "command.com" : cmd);
  547.                   if ((varr2 = ssave ()) == NULL)
  548.                      break;
  549.                   clown_clear ();
  550.  
  551.                   gotoxy (1, 8);
  552.           printf (msgtxt[M_TYPE_EXIT], 0L);
  553.                   spawn_program (registered, cmdname);
  554.  
  555.                   setdisk (string[0] - 'A');
  556.                   chdir (string);
  557.                   srestore (varr2);
  558.                   clocks = 0L;
  559.                   break;
  560.  
  561.                // ALT-H Hangup
  562.                case 0x2300:
  563.                   wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  564.                   wshadow (LGREY|_BLACK);
  565.                   wcenters (1, LGREY|_BLACK, "Disconnecting modem");
  566.  
  567.                   modem_hangup ();
  568.  
  569.                   wclose ();
  570.                   break;
  571.  
  572.                // PgUp Upload file
  573.                case 0x4900:
  574.                   terminal_select_file ("UPLOAD", 1, &dir);
  575.                   XON_DISABLE ();
  576.                   _BRK_DISABLE ();
  577.                   break;
  578.  
  579.                // PgDn Download file
  580.                case 0x5100:
  581.                   terminal_select_file ("DOWNLOAD", 0, &dir);
  582.                   XON_DISABLE ();
  583.                   _BRK_DISABLE ();
  584.                   break;
  585.  
  586.                // Freccia in su
  587.                case 0x4800:
  588.                   SENDBYTE (0x1B);
  589.                   SENDBYTE ('[');
  590.                   SENDBYTE ('A');
  591.                   break;
  592.  
  593.                // Freccia in giu
  594.                case 0x5000:
  595.                   SENDBYTE (0x1B);
  596.                   SENDBYTE ('[');
  597.                   SENDBYTE ('B');
  598.                   break;
  599.  
  600.                // Freccia a sinistra
  601.                case 0x4D00:
  602.                   SENDBYTE (0x1B);
  603.                   SENDBYTE ('[');
  604.                   SENDBYTE ('D');
  605.                   break;
  606.  
  607.                // Freccia a destra
  608.                case 0x4B00:
  609.                   SENDBYTE (0x1B);
  610.                   SENDBYTE ('[');
  611.                   SENDBYTE ('C');
  612.                   break;
  613.  
  614.                // Home
  615.                case 0x4700:
  616.                   SENDBYTE (0x1B);
  617.                   SENDBYTE ('[');
  618.                   SENDBYTE ('H');
  619.                   break;
  620.  
  621.                // End
  622.                case 0x4F00:
  623.                   SENDBYTE (0x1B);
  624.                   SENDBYTE ('[');
  625.                   SENDBYTE ('K');
  626.                   break;
  627.             }
  628.          }
  629.          else {
  630.             i &= 0xFF;
  631.             SENDBYTE (i);
  632.  
  633.             if (dir.phone[0] && dir.local_echo) {
  634.                if (fp_cap != NULL)
  635.                   fputc (i, fp_cap);
  636.                wputc (i);
  637.            VioUpdate ();
  638.         }
  639.         else if (local_echo) {
  640.            if (fp_cap != NULL)
  641.           fputc (i, fp_cap);
  642.            wputc (i);
  643.            VioUpdate ();
  644.             }
  645.          }
  646.  
  647.          relflag = 0;
  648.       }
  649.  
  650.       keyboard_loop ();
  651.       if (relflag)
  652.          release_timeslice ();
  653.    }
  654.  
  655.    hidecur ();
  656.    wactiv (mainview);
  657.    wclose ();
  658.    wactiv (status);
  659.    wclose ();
  660.    srestore (varr);
  661.  
  662.    emulator = 0;
  663.    status_line (":Returning to mailer mode");
  664.  
  665.    com_baud (config->speed);
  666.    mdm_sendcmd (config->init);
  667. }
  668.  
  669. static void keyboard_loop ()
  670. {
  671.    char cmdname[40];
  672.    long t;
  673.    struct time timep;
  674.  
  675.  
  676.    if (!doorway && timeup (clocks)) {
  677.       clocks = timerset (98);
  678.  
  679.       gettime ((struct time *)&timep);
  680.       sprintf(cmdname, "%02d%c%02d", timep.ti_hour % 24, interpoint, timep.ti_min % 60);
  681.       prints (24, 59, LGREY|_BLUE, cmdname);
  682.  
  683.       if (online_elapsed) {
  684.          t = (time (NULL) - online_elapsed) / 60;
  685.          sprintf (cmdname, "%02ld%c%02ld", t / 60L, interpoint, t % 60L);
  686.          prints (24, 74, LGREY|_BLUE, cmdname);
  687.       }
  688.  
  689.       interpoint = (interpoint == ':') ? ' ' : ':';
  690.    }
  691. }
  692.  
  693. static void set_selection (void)
  694. {
  695.    struct _item_t *item;
  696.  
  697.    item = wmenuicurr ();
  698.    last_sel = item->tagid;
  699. }
  700.  
  701. static void terminal_select_file (char *title, int upload, DIALREC *dialrec)
  702. {
  703.    FILE *fp;
  704.    int fd, i, protocol, x = 0, taginit = -1;
  705.    char filename[80], *p, filetosend[80], *exts[100];
  706.    struct ffblk blk;
  707.    PROTOCOL prot;
  708.  
  709.    hidecur ();
  710.  
  711.    i = 0;
  712.    if (config->prot_zmodem)
  713.       i++;
  714.    if (config->prot_xmodem)
  715.       i++;
  716.    if (config->prot_1kxmodem)
  717.       i++;
  718.    if (config->prot_sealink)
  719.       i++;
  720.  
  721.    sprintf (filename, "%sPROTOCOL.DAT", config->sys_path);
  722.    fd = sh_open (filename, O_RDONLY|O_BINARY, SH_DENYWR, S_IREAD|S_IWRITE);
  723.    if (fd != -1) {
  724.       while (read (fd, &prot, sizeof (PROTOCOL)) == sizeof (PROTOCOL)) {
  725.          if (prot.active)
  726.             i++;
  727.       }
  728.    }
  729.  
  730.    wopen (3, 27, 4 + i, 70, 3, RED|_LGREY, BLUE|_LGREY);
  731.    wtitle (title, TLEFT, RED|_LGREY);
  732.    wshadow (DGREY|_BLACK);
  733.  
  734.    wmenubegc ();
  735.    i = 0;
  736.    if (config->prot_zmodem) {
  737.       if (taginit == -1)
  738.          taginit = 1;
  739.       wmenuitem (i++, 0, " Z - ZModem (internal) ", 'Z', 1, M_CLALL, set_selection, 0, 0);
  740.    }
  741.    if (config->prot_xmodem) {
  742.       if (taginit == -1)
  743.          taginit = 2;
  744.       wmenuitem (i++, 0, " X - XModem ", 'X', 2, M_CLALL, set_selection, 0, 0);
  745.    }
  746.    if (config->prot_1kxmodem) {
  747.       if (taginit == -1)
  748.          taginit = 3;
  749.       wmenuitem (i++, 0, " 1 - 1k-Xmodem ", '1', 3, M_CLALL, set_selection, 0, 0);
  750.    }
  751.    if (config->prot_sealink) {
  752.       if (taginit == -1)
  753.          taginit = 4;
  754.       wmenuitem (i++, 0, " S - SEAlink ", 'S', 4, M_CLALL, set_selection, 0, 0);
  755.    }
  756.  
  757.    x = 0;
  758.    if (fd != -1) {
  759.       lseek (fd, 0L, SEEK_SET);
  760.       while (read (fd, &prot, sizeof (PROTOCOL)) == sizeof (PROTOCOL))
  761.          if (prot.active) {
  762.             sprintf (filename, " %c - %s ", prot.hotkey, prot.name);
  763.             exts[x] = (char *)malloc (strlen (filename) + 1);
  764.             if (exts[x] == NULL)
  765.                continue;
  766.             strcpy (exts[x], filename);
  767.             if (taginit == -1)
  768.                taginit = x + 10;
  769.             wmenuitem (i++, 0, exts[x], prot.hotkey, x + 10, M_CLALL, set_selection, 0, 0);
  770.             x++;
  771.          }
  772.    }
  773.    close (fd);
  774.  
  775.    exts[x] = NULL;
  776.    wmenuend (taginit, M_VERT|M_SAVE, 42, 0, BLUE|_LGREY, WHITE|_LGREY, DGREY|_LGREY, YELLOW|_BLACK);
  777.  
  778.    if (wmenuget () == -1) {
  779.       wclose ();
  780.       for (x = 0; exts[x] != NULL; x++)
  781.          free (exts[x]);
  782.       showcur ();
  783.       return;
  784.    }
  785.    else
  786.       protocol = last_sel;
  787.  
  788.    for (x = 0; exts[x] != NULL; x++)
  789.       free (exts[x]);
  790.  
  791.    showcur ();
  792.  
  793.    if (upload || (protocol == 2 || protocol == 3)) {
  794.       wopen (11, 15, 13, 65, 3, LGREY|_BLACK, LCYAN|_BLACK);
  795.       wtitle (upload ? "UPLOAD FILES" : "DOWNLOAD FILES", TLEFT, LCYAN|_BLACK);
  796.  
  797.       wprints (0, 1, YELLOW|_BLACK, "File(s):");
  798.       winpbeg (BLACK|_LGREY, BLACK|_LGREY);
  799.       winpdef (0, 10, filename, "??????????????????????????????????????", 0, 0, NULL, 0);
  800.  
  801.       if ((i = winpread ()) == W_ESCPRESS) {
  802.          wclose ();
  803.          wclose ();
  804.          return;
  805.       }
  806.  
  807.       wclose ();
  808.  
  809.       strtrim (filename);
  810.       if (!filename[0]) {
  811.          wclose ();
  812.          return;
  813.       }
  814.    }
  815.  
  816.    wclose ();
  817.  
  818.    if (upload) {
  819.       i = 0;
  820.       fp = NULL;
  821.  
  822.       if (protocol >= 10) {
  823.          sprintf (filename, "%sEXTRN%d.LST", config->sys_path, line_offset);
  824.          fp = fopen (filename, "wt");
  825.       }
  826.  
  827.       do {
  828.          p = strtok (filename, " ");
  829.  
  830.          if (isalpha (filename[0]) && filename[1] == ':')
  831.             strcpy (filetosend, "");
  832.          else if (filename[0] == '\\')
  833.             strcpy (filetosend, "");
  834.          else
  835.             strcpy (filetosend, config->ul_path);
  836.          strcat (filetosend, filename);
  837.  
  838.          if (!findfirst (filetosend, &blk, 0))
  839.             do {
  840.                sprintf (filetosend, "%s%s", config->ul_path, blk.ff_name);
  841.                switch (protocol) {
  842.                   case 1:
  843.                      send_Zmodem (filetosend, NULL, i++, 0);
  844.                      break;
  845.  
  846.                   case 2:
  847.                      fsend (filetosend, 'X');
  848.                      break;
  849.  
  850.                   case 3:
  851.                      fsend (filetosend, 'Y');
  852.                      break;
  853.  
  854.                   case 4:
  855.                      fsend (filetosend, 'S');
  856.                      break;
  857.  
  858.                   default:
  859.                      if (fp != NULL)
  860.                         fprintf (fp, "%s%s\n", config->ul_path, blk.ff_name);
  861.                      break;
  862.                }
  863.             } while (!findnext (&blk));
  864.       } while (protocol != 2 && protocol != 3 && (p = strtok (NULL, " ")) != NULL);
  865.  
  866.       if (protocol >= 10 && fp != NULL)
  867.          fclose (fp);
  868.  
  869.       if (protocol == 1)
  870.          send_Zmodem (NULL, NULL, ((i) ? END_BATCH : NOTHING_TO_DO), 0);
  871.       else if (protocol == 4)
  872.          fsend (NULL, 'S');
  873.       else if (protocol >= 10) {
  874.          general_external_protocol (NULL, dialrec->download[0] ? dialrec->download : config->dl_path, protocol, 0, 1);
  875.          sprintf (filename, "%sEXTRN%d.LST", config->sys_path, line_offset);
  876.          unlink (filename);
  877.       }
  878.    }
  879.    else {
  880.       switch (protocol) {
  881.          case 1:
  882.             get_Zmodem (dialrec->download[0] ? dialrec->download : config->dl_path, NULL);
  883.             break;
  884.  
  885.          case 2:
  886.             who_is_he = 0;
  887.             overwrite = 0;
  888.             receive (dialrec->download[0] ? dialrec->download : config->dl_path, filename, 'X');
  889.             break;
  890.  
  891.          case 3:
  892.             who_is_he = 0;
  893.             overwrite = 0;
  894.             receive (dialrec->download[0] ? dialrec->download : config->dl_path, filename, 'Y');
  895.             break;
  896.  
  897.          case 4:
  898.             do {
  899.                who_is_he = 0;
  900.                overwrite = 0;
  901.                p = receive (dialrec->download[0] ? dialrec->download : config->dl_path, NULL, 'S');
  902.             } while (p != NULL);
  903.             break;
  904.       }
  905.  
  906.       if (protocol >= 10)
  907.          general_external_protocol (NULL, dialrec->download[0] ? dialrec->download : config->dl_path, protocol, 0, 0);
  908.    }
  909.  
  910.    setkbloop (NULL);
  911. }
  912.  
  913. static void addshadow (void)
  914. {
  915.    wshadow (DGREY|_BLACK);
  916. }
  917.  
  918. static void pull_down_menu ()
  919. {
  920.    setkbloop (keyboard_loop);
  921.    hidecur ();
  922.  
  923.    wmenubeg (0, 0, 0, 79, 5, BLACK|_LGREY, BLACK|_LGREY, NULL);
  924.    wmenuitem (0, 1, " File ", 'F', 100, M_HASPD, NULL, 0, 0);
  925.       wmenubeg (1, 1, 6, 29, 3, RED|_LGREY, BLUE|_LGREY, addshadow);
  926.       wmenuitem (0, 0, " Download files      PgDn  ", 0, 101, M_CLALL, set_selection, 0, 0);
  927.       wmenuitem (1, 0, " Upload files        PgUp  ", 0, 102, M_CLALL, set_selection, 0, 0);
  928.       wmenuitem (2, 0, " OS/2 Shell          Alt-J ", 0, 105, M_CLALL, set_selection, 0, 0);
  929.       wmenuitem (3, 0, " Leave Terminal      Alt-X ", 0, 106, M_CLALL, set_selection, 0, 0);
  930.       wmenuend (101, M_PD|M_SAVE, 0, 0, BLUE|_LGREY, WHITE|_LGREY, DGREY|_LGREY, YELLOW|_BLACK);
  931.    wmenuitem (0, 7, " Line ", 'L', 200, M_HASPD, NULL, 0, 0);
  932.       wmenubeg (1, 7, 6, 38, 3, RED|_LGREY, BLUE|_LGREY, addshadow);
  933.       wmenuitem (0, 0, " Change baud rate       Alt-B ", 0, 201, M_CLALL, set_selection, 0, 0);
  934.       wmenuitem (1, 0, " Expand CR to CR/LF           ", 0, 205, M_CLALL, set_selection, 0, 0);
  935.       wmenuitem (2, 0, " Local echo             Alt-E ", 0, 206, M_CLALL, set_selection, 0, 0);
  936.       wmenuitem (3, 0, " Auto-ZModem download         ", 0, 207, M_CLALL, set_selection, 0, 0);
  937.       wmenuend (201, M_PD|M_SAVE, 0, 0, BLUE|_LGREY, WHITE|_LGREY, DGREY|_LGREY, YELLOW|_BLACK);
  938.    wmenuitem (0, 13, " Session ", 'S', 300, M_HASPD, NULL, 0, 0);
  939.       wmenubeg (1, 13, 8, 41, 3, RED|_LGREY, BLUE|_LGREY, addshadow);
  940.       wmenuitem (0, 0, " Capture             Alt-L ", 0, 301, M_CLALL, set_selection, 0, 0);
  941.       wmenuitem (1, 0, " Hangup              Alt-H ", 0, 302, M_CLALL, set_selection, 0, 0);
  942.       wmenuitem (2, 0, " Initialize modem    Alt-I ", 0, 304, M_CLALL, set_selection, 0, 0);
  943.       wmenuitem (3, 0, " Reset timer         Alt-R ", 0, 305, M_CLALL, set_selection, 0, 0);
  944.       wmenuitem (4, 0, " Clear screen        Alt-C ", 0, 306, M_CLALL, set_selection, 0, 0);
  945.       wmenuitem (5, 0, " Dialing directory   Alt-D ", 0, 307, M_CLALL, set_selection, 0, 0);
  946.       wmenuend (301, M_PD|M_SAVE, 0, 0, BLUE|_LGREY, WHITE|_LGREY, DGREY|_LGREY, YELLOW|_BLACK);
  947.  
  948.    if (last_sel == -1)
  949.       last_sel = 100;
  950.    else
  951.       last_sel = (last_sel / 100) * 100;
  952.  
  953.    wmenuend (last_sel, M_HORZ, 0, 0, BLUE|_LGREY, WHITE|_LGREY, DGREY|_LGREY, YELLOW|_BLACK);
  954.  
  955.    kbput (0x1C0D);
  956.    if (wmenuget () != -1)
  957.       switch (last_sel) {
  958.          // PgDn - Download
  959.          case 101:
  960.             kbput (0x5100);
  961.             break;
  962.  
  963.          // PgUp - Upload
  964.          case 102:
  965.             kbput (0x4900);
  966.             break;
  967.  
  968.          // Alt-J Shell
  969.          case 105:
  970.             kbput (0x2400);
  971.             break;
  972.  
  973.          // Alt-X Exit
  974.          case 106:
  975.             kbput (0x2D00);
  976.             break;
  977.  
  978.          // Alt-B Baud rate
  979.          case 201:
  980.             kbput (0x3000);
  981.             break;
  982.  
  983.          // Expand CR to CR/LF
  984.          case 205:
  985.             expand_cr = expand_cr ? 0 : 1;
  986.             prints (24, 44, LGREY|_BLUE, expand_cr ? "T" : " ");
  987.             break;
  988.  
  989.          // Alt-E Local echo
  990.          case 206:
  991.             local_echo = local_echo ? 0 : 1;
  992.             break;
  993.  
  994.          // Auto-ZModem
  995.          case 207:
  996.             config->autozmodem = config->autozmodem ? 0 : 1;
  997.             break;
  998.  
  999.          // Alt-L
  1000.          case 301:
  1001.             kbput (0x2600);
  1002.             break;
  1003.  
  1004.          // Alt-H
  1005.          case 302:
  1006.             kbput (0x2300);
  1007.             break;
  1008.  
  1009.          // Alt-I
  1010.          case 304:
  1011.             kbput (0x1700);
  1012.             break;
  1013.  
  1014.          // Alt-R
  1015.          case 305:
  1016.             kbput (0x1300);
  1017.             break;
  1018.  
  1019.          // Alt-C
  1020.          case 306:
  1021.             kbput (0x2E00);
  1022.             break;
  1023.  
  1024.          // Alt-D
  1025.          case 307:
  1026.             kbput (0x2000);
  1027.             break;
  1028.       }
  1029.  
  1030.    setkbloop (NULL);
  1031.    showcur ();
  1032. }
  1033.  
  1034. #define  NORM   0x07
  1035. #define  BOLD   0x08
  1036. #define  FAINT  0xF7
  1037. #define  VBLINK 0x80
  1038. #define  REVRS  0x77
  1039.  
  1040. static void translate_ansibbs ()
  1041. {
  1042.    static char sx = 1, sy = 1;
  1043.    char c, str[15];
  1044.    int Pn[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  1045.    int i = 0, p = 0, v;
  1046.  
  1047.    wactiv (mainview);
  1048.    wreadcur (&vy, &vx);
  1049.  
  1050.    c = TIMED_READ (2);
  1051.    if (c != '[') {
  1052.       wputc (0x1B);
  1053.       wputc (c);
  1054.       return;
  1055.    }
  1056.  
  1057.    while (1) {
  1058.       c = TIMED_READ (2);
  1059.  
  1060.       if (isdigit (c))
  1061.          *(str + i++) = c;
  1062.       else {
  1063.          *(str + i) = '\0';
  1064.          i = 0;
  1065.          Pn[p++] = atoi (str);
  1066.  
  1067.          if (c == ';')
  1068.             continue;
  1069.          else
  1070.             switch(c) {
  1071.                /* (CUP) set cursor position  */
  1072.                case 'H':
  1073.                case 'F':
  1074.                case 'h':
  1075.                case 'f':
  1076.                   vy = Pn[0] ? Pn[0] : 1;
  1077.                   vx = Pn[1] ? Pn[1] : 1;
  1078.                   wgotoxy (vy - 1, vx - 1);
  1079.                   return;
  1080.                   /* (CUU) cursor up   */
  1081.                case 'A':
  1082.                   vy -= Pn[0] ? Pn[0] : 1;
  1083.                   if (vy < 1)
  1084.                      vy = 1;
  1085.                   wgotoxy (vy, vx);
  1086.                   return;
  1087.                   /* (CUD) cursor down */
  1088.                case 'B':
  1089.                   vy += Pn[0] ? Pn[0] : 1;
  1090.                   if (vy > 25)
  1091.                      vy = 25;
  1092.                   wgotoxy (vy, vx);
  1093.                   return;
  1094.                   /* (CUF) cursor forward */
  1095.                case 'C':
  1096.                   vx += Pn[0] ? Pn[0] : 1;
  1097.                   if (vx > 80)
  1098.                      vx = 80;
  1099.                   wgotoxy (vy, vx);
  1100.                   return;
  1101.                   /* (CUB) cursor backward   */
  1102.                case 'D':
  1103.                   vx -= Pn[0] ? Pn[0] : 1;
  1104.                   if (vx < 1)
  1105.                      vx = 1;
  1106.                   wgotoxy (vy, vx);
  1107.                   return;
  1108.                   /* (SCP) save cursor position */
  1109.                case 's':
  1110.                   sx = vx;
  1111.                   sy = vy;
  1112.                   return;
  1113.                   /* (RCP) restore cursor position */
  1114.                case 'u':
  1115.                   vx = sx;
  1116.                   vy = sy;
  1117.                   wgotoxy (vy, vx);
  1118.                   return;
  1119.                   /* clear screen   */
  1120.                case 'J':
  1121.                   if (Pn[0] == 2)
  1122.                      wclear ();
  1123.                   return;
  1124.                   /* (EL) erase line   */
  1125.                case 'K':
  1126.                   wclreol ();
  1127.                   return;
  1128.                   /* An attribute command is more elaborate than the    */
  1129.                   /* others because it may have many numeric parameters */
  1130.                case 'm':
  1131.                   for(i=0; i<p; i++) {
  1132.                      if (Pn[i] >= 30 && Pn[i] <= 37) {
  1133.                         ansi_attr &= 0xf8;
  1134.                         switch (Pn[i]) {
  1135.                            case 30:
  1136.                               ansi_attr |= BLACK;
  1137.                               break;
  1138.                            case 31:
  1139.                               ansi_attr |= RED;
  1140.                               break;
  1141.                            case 32:
  1142.                               ansi_attr |= GREEN;
  1143.                               break;
  1144.                            case 33:
  1145.                               ansi_attr |= BROWN;
  1146.                               break;
  1147.                            case 34:
  1148.                               ansi_attr |= BLUE;
  1149.                               break;
  1150.                            case 35:
  1151.                               ansi_attr |= MAGENTA;
  1152.                               break;
  1153.                            case 36:
  1154.                               ansi_attr |= CYAN;
  1155.                               break;
  1156.                            case 37:
  1157.                               ansi_attr |= LGREY;
  1158.                               break;
  1159.                         }
  1160.                      }
  1161.  
  1162.                      if (Pn[i] >= 40 && Pn[i] <= 47) {
  1163.                         ansi_attr &= 0x8f;
  1164.                         switch (Pn[i]) {
  1165.                            case 40:
  1166.                               ansi_attr |= _BLACK;
  1167.                               break;
  1168.                            case 41:
  1169.                               ansi_attr |= _RED;
  1170.                               break;
  1171.                            case 42:
  1172.                               ansi_attr |= _GREEN;
  1173.                               break;
  1174.                            case 43:
  1175.                               ansi_attr |= _BROWN;
  1176.                               break;
  1177.                            case 44:
  1178.                               ansi_attr |= _BLUE;
  1179.                               break;
  1180.                            case 45:
  1181.                               ansi_attr |= _MAGENTA;
  1182.                               break;
  1183.                            case 46:
  1184.                               ansi_attr |= _CYAN;
  1185.                               break;
  1186.                            case 47:
  1187.                               ansi_attr |= _LGREY;
  1188.                               break;
  1189.                         }
  1190.                      }
  1191.  
  1192.                      if (Pn[i] >= 0 && Pn[i] <= 7)
  1193.                         switch(Pn[i]) {
  1194.                            case 0:
  1195.                               ansi_attr = NORM;
  1196.                               break;
  1197.                            case 1:
  1198.                               ansi_attr |= BOLD;
  1199.                               break;
  1200.                            case 2:
  1201.                               ansi_attr &= FAINT;
  1202.                               break;
  1203.                            case 5:
  1204.                            case 6:
  1205.                               ansi_attr |= VBLINK;
  1206.                               break;
  1207.                            case 7:
  1208.                               ansi_attr ^= REVRS;
  1209.                               break;
  1210.                            default:
  1211.                               ansi_attr = NORM;
  1212.                               break;
  1213.                         }
  1214.                   }
  1215.  
  1216.                   wtextattr (ansi_attr);
  1217.                   return;
  1218.  
  1219.                case 'n':
  1220.                   if (Pn[0] == 6) {
  1221.                      sprintf (str, "\x1B[%d;%dR", vx + 1, vy + 1);
  1222.                      for (v = 0; str[v]; v++)
  1223.                         SENDBYTE (str[v]);
  1224.                   }
  1225.                   break;
  1226.  
  1227.                default:
  1228.                   return;
  1229.             }
  1230.       }
  1231.    }
  1232. }
  1233.  
  1234. static void translate_avatar (void)
  1235. {
  1236.    int c, i, m;
  1237.    char stringa[80], *p;
  1238.  
  1239.    wactiv (mainview);
  1240.    wreadcur (&vy, &vx);
  1241.  
  1242.    c = TIMED_READ (2);
  1243.    switch (c) {
  1244.       case CTRLA:
  1245.          c = TIMED_READ (2);
  1246.          ansi_attr = c;
  1247.          wtextattr (ansi_attr);
  1248.          break;
  1249.       /* (CUU) cursor up   */
  1250.       case CTRLC:
  1251.          if (vy)
  1252.             vy--;
  1253.          wgotoxy (vy, vx);
  1254.          return;
  1255.       /* (CUD) cursor down */
  1256.       case CTRLD:
  1257.          if (vy < 23)
  1258.             vy++;
  1259.          wgotoxy (vy, vx);
  1260.          return;
  1261.       /* (CUF) cursor forward */
  1262.       case CTRLF:
  1263.          if (vx < 79)
  1264.             vx++;
  1265.          wgotoxy (vy, vx);
  1266.          return;
  1267.       /* (CUB) cursor backward   */
  1268.       case CTRLE:
  1269.          if (vx)
  1270.             vx--;
  1271.          wgotoxy (vy, vx);
  1272.          return;
  1273.       /* (EL) erase line   */
  1274.       case CTRLG:
  1275.          wclreol ();
  1276.          return;
  1277.       case CTRLH:
  1278.          vy = TIMED_READ (2) & 0xFF;
  1279.          vx = TIMED_READ (2) & 0xFF;
  1280.          wgotoxy (vy - 1, vx - 1);
  1281.          return;
  1282.       case CTRLY:
  1283.          i = TIMED_READ (2);
  1284.          for (m = 0; m < i; m++)
  1285.             stringa[m] = TIMED_READ (2);
  1286.          stringa[m] = '\0';
  1287.          i = TIMED_READ (2);
  1288.          for (m = 0; m < i; m++) {
  1289.             p = stringa;
  1290.             while (*p) {
  1291.                if (*p == CTRLV) {
  1292.                   p++;
  1293.                   switch (*p) {
  1294.                      /* (CUU) cursor up   */
  1295.                      case CTRLC:
  1296.                         if (vy)
  1297.                            vy--;
  1298.                         wgotoxy (vy, vx);
  1299.                         break;
  1300.                      /* (CUD) cursor down */
  1301.                      case CTRLD:
  1302.                         if (vy < 23)
  1303.                            vy++;
  1304.                         wgotoxy (vy, vx);
  1305.                         break;
  1306.                      /* (CUF) cursor forward */
  1307.                      case CTRLF:
  1308.                         if (vx < 79)
  1309.                            vx++;
  1310.                         wgotoxy (vy, vx);
  1311.                         break;
  1312.                      /* (CUB) cursor backward   */
  1313.                      case CTRLE:
  1314.                         if (vx)
  1315.                            vx--;
  1316.                         wgotoxy (vy, vx);
  1317.                         break;
  1318.                      default:
  1319.                         wputc (*p);
  1320.                         break;
  1321.                   }
  1322.                   wreadcur (&vy, &vx);
  1323.                }
  1324.                else
  1325.                   wputc (*p);
  1326.                p++;
  1327.             }
  1328.          }
  1329.          return;
  1330.    }
  1331. }
  1332.  
  1333. static void close_capture (FILE *fp_cap)
  1334. {
  1335.    if (fp_cap != NULL) {
  1336.       fprintf (fp_cap, "───────────────────────────────────────────────────────────────────────────────\n\n");
  1337.       fprintf (fp_cap, "\n");
  1338.       fclose (fp_cap);
  1339.       prints (24, 43, LGREY|_BLUE, " ");
  1340.    }
  1341. }
  1342.  
  1343. static void capture_closed (void)
  1344. {
  1345.    wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  1346.    wshadow (LGREY|_BLACK);
  1347.  
  1348.    wcenters (1, LGREY|_BLACK, "Capture file closed");
  1349.  
  1350.    timer (20);
  1351.    wclose ();
  1352. }
  1353.  
  1354. static FILE *open_capture (char *predefined)
  1355. {
  1356.    FILE *fp;
  1357.    int wh;
  1358.    char string[80], cpath[80], *p;
  1359.    long t;
  1360.    struct tm *tim;
  1361.  
  1362.    if (predefined == NULL || *predefined == '\0') {
  1363.       getcwd (cpath, 78);
  1364.  
  1365.       wh = wopen (11, 7, 13, 73, 3, LGREY|_BLACK, LCYAN|_BLACK);
  1366.       wactiv (wh);
  1367.       wtitle ("OPEN CAPTURE", TLEFT, LCYAN|_BLACK);
  1368.  
  1369.       wprints (0, 1, YELLOW|_BLACK, "Filename");
  1370.       sprintf (string, "%s\\TERMINAL.CAP", cpath);
  1371.       winpbeg (BLACK|_LGREY, BLACK|_LGREY);
  1372.       winpdef (0, 10, string, "?????????????????????????????????????????????????????", 0, 2, NULL, 0);
  1373.  
  1374.       if (winpread () == W_ESCPRESS) {
  1375.          wclose ();
  1376.          return (NULL);
  1377.       }
  1378.  
  1379.       wclose ();
  1380.  
  1381.       p = strbtrim (string);
  1382.    }
  1383.    else
  1384.       p = predefined;
  1385.  
  1386.    if ((fp = fopen (p, "ab")) != NULL) {
  1387.       t = time (NULL);
  1388.       tim = localtime (&t);
  1389.  
  1390.       fprintf (fp, "                    Capture file opened %02d-%s-%d %2d:%02d\n", tim->tm_mday, mtext[tim->tm_mon], tim->tm_year, tim->tm_hour, tim->tm_min);
  1391.       fprintf (fp, "───────────────────────────────────────────────────────────────────────────────\n");
  1392.  
  1393.       if (fp != NULL)
  1394.          prints (24, 43, LGREY|_BLUE, "C");
  1395.    }
  1396.  
  1397.    return (fp);
  1398. }
  1399.  
  1400. static int exit_confirm ()
  1401. {
  1402.    int wh, i;
  1403.    char string[10];
  1404.  
  1405.    wh = wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  1406.    wactiv (wh);
  1407.    wshadow (LGREY|_BLACK);
  1408.  
  1409.    wcenters (1, LGREY|_BLACK, "Exit terminal mode (Y/n) ?  ");
  1410.  
  1411.    strcpy (string, "Y");
  1412.    winpbeg (LGREY|_BLACK, LGREY|_BLACK);
  1413.    winpdef (1, 30, string, "?", 0, 2, NULL, 0);
  1414.  
  1415.    i = winpread ();
  1416.    wclose ();
  1417.  
  1418.    if (i == W_ESCPRESS || toupper (string[0]) == 'N')
  1419.       return (0);
  1420.  
  1421.    return (1);
  1422. }
  1423.  
  1424. static void terminal_iemsi_handshake (char *password)
  1425. {
  1426.    int i, tries;
  1427.    unsigned long crc;
  1428.    char string[2048], addr[20], *p, id[40], name[40], location[40], operator[40], notice[70];
  1429.    long t1, t2;
  1430.  
  1431.    wopen (1, 40, 8, 76, 3, RED|_LGREY, BLUE|_LGREY);
  1432.    wshadow (DGREY|_BLACK);
  1433.    wtitle ("NEGOTIATING IEMSI", TLEFT, RED|_LGREY);
  1434.  
  1435.    wputs (" Received IEMSI request\n");
  1436.  
  1437.    strcpy (string, "{");
  1438.    strcat (string, config->sysop);
  1439.    strcat (string, "}{");
  1440.    strcat (string, config->iemsi_handle);
  1441.    strcat (string, "}{");
  1442.    strcat (string, config->location);
  1443.    strcat (string, "}{");
  1444.    strcat (string, config->phone);
  1445.    strcat (string, "}{}{");
  1446.    if (password != NULL && *password)
  1447.       strcat (string, password);
  1448.    else
  1449.       strcat (string, config->iemsi_pwd);
  1450.    strcat (string, "}{}{");
  1451.    if (config->avatar)
  1452.       strcat (string, "AVT0,");
  1453.    else
  1454.       strcat (string, "ANSI,");
  1455.    strcat (string, "24,80,0}{ZMO,SLK}{TAB,ASCII8}{");
  1456.    if (config->iemsi_news)
  1457.       strcat (string, "NEWS,");
  1458.    if (config->iemsi_newmail)
  1459.       strcat (string, "MAIL,");
  1460.    if (config->iemsi_newfiles)
  1461.       strcat (string, "FILE,");
  1462.    if (config->iemsi_hotkeys)
  1463.       strcat (string, "HOT,");
  1464.    if (config->iemsi_screenclr)
  1465.       strcat (string, "CLR,");
  1466.    if (config->iemsi_quiet)
  1467.       strcat (string, "HUSH,");
  1468.    if (config->iemsi_pausing)
  1469.       strcat (string, "MORE,");
  1470.    if (config->iemsi_editor)
  1471.       strcat (string, "FSED,");
  1472.    if (string[strlen (string) - 1] == ',')
  1473.       string[strlen (string) - 1] = '\0';
  1474.    strcat (string, "}{LoraBBS-OS/2,");
  1475.    strcat (string, VNUM);
  1476.    activation_key ();
  1477.    if (registered) {
  1478.       sprintf (addr, ",%s%05u}{", serial_id[0] ? serial_id : "", serial_no);
  1479.       strcat (string, addr);
  1480.    }
  1481.    else
  1482.       strcat (string, ",Demo}{");
  1483.    strcat (string, "}");
  1484.  
  1485.    sprintf (addr, "EMSI_ICI%04X", strlen (string));
  1486.    crc = 0xFFFFFFFFL;
  1487.    for (i = 0; i < strlen (addr); i++)
  1488.       crc = Z_32UpdateCRC (addr[i], crc);
  1489.  
  1490.    for (i = 0; i < strlen (string); i++)
  1491.       crc = Z_32UpdateCRC (string[i], crc);
  1492.  
  1493.    t1 = timerset (6000);
  1494.    tries = 1;
  1495.  
  1496.    for (;;) {
  1497.       if (tries++ > 4 || timeup (t1)) {
  1498.          wputs (" Too many errors\n");
  1499.          timer (5);
  1500.          wclose ();
  1501.          status_line ("!Trans. IEMSI/T failure");
  1502.          return;
  1503.       }
  1504.  
  1505.       wputs (" Sending Client packet\n");
  1506.  
  1507.       sprintf (addr, "**EMSI_ICI%04X", strlen (string));
  1508.       for (p = addr; *p; p++)
  1509.          BUFFER_BYTE (*p);
  1510.       for (p = string; *p; p++)
  1511.          BUFFER_BYTE (*p);
  1512.  
  1513.       UNBUFFER_BYTES ();
  1514.       CLEAR_INBOUND ();
  1515.  
  1516.       sprintf (addr, "%08lX\r", crc);
  1517.       for (p = addr; *p; p++)
  1518.          BUFFER_BYTE (*p);
  1519.       UNBUFFER_BYTES ();
  1520.  
  1521.       t2 = timerset (1000);
  1522.  
  1523.       while (!timeup (t1)) {
  1524.          if (timeup (t2))
  1525.             break;
  1526.  
  1527.          if (PEEKBYTE() == '*') {
  1528.             get_emsi_id (addr, 14);
  1529.             if (!strnicmp (addr, "**EMSI_ISI", 10))
  1530.                goto receive_isi;
  1531.          }
  1532.          else if (PEEKBYTE () != -1) {
  1533.             TIMED_READ (10);
  1534.             time_release ();
  1535.          }
  1536.       }
  1537.    }
  1538.  
  1539. receive_isi:
  1540.  
  1541.    wputs (" Receiving Server packet\n");
  1542.  
  1543.    tries = 0;
  1544.    t1 = timerset (1000);
  1545.    t2 = timerset (6000);
  1546.  
  1547. resend:
  1548.    if (tries++ > 6) {
  1549.       wclose ();
  1550.       status_line ("!IEMSI/T Error: too may tries");
  1551.       return;
  1552.    }
  1553.  
  1554.    if (!get_emsi_field (string))
  1555.       goto resend;
  1556.    if (strlen (string) > 39)
  1557.       string[39] = '\0';
  1558.    strcpy (id, string);
  1559.  
  1560.    if (!get_emsi_field (string))
  1561.       goto resend;
  1562.    if (strlen (string) > 39)
  1563.       string[39] = '\0';
  1564.    strcpy (name, string);
  1565.  
  1566.    if (!get_emsi_field (string))
  1567.       goto resend;
  1568.    if (strlen (string) > 39)
  1569.       string[39] = '\0';
  1570.    strcpy (location, string);
  1571.  
  1572.    if (!get_emsi_field (string))
  1573.       goto resend;
  1574.    if (strlen (string) > 39)
  1575.       string[39] = '\0';
  1576.    strcpy (operator, string);
  1577.  
  1578.    if (!get_emsi_field (string))
  1579.       goto resend;
  1580.    if (strlen (string) > 39)
  1581.       string[39] = '\0';
  1582.  
  1583.    if (!get_emsi_field (string))
  1584.       goto resend;
  1585.    if (strlen (string) > 69)
  1586.       string[39] = '\0';
  1587.    strcpy (notice, string);
  1588.  
  1589.    if (!get_emsi_field (string))
  1590.       goto resend;
  1591.    if (strlen (string) > 39)
  1592.       string[39] = '\0';
  1593.    if (!get_emsi_field (string))
  1594.       goto resend;
  1595.    if (strlen (string) > 39)
  1596.       string[39] = '\0';
  1597.  
  1598.    snooping = 0;
  1599.    timer (5);
  1600.    m_print2 ("**EMSI_ACKA490\r**EMSI_ACKA490\r");
  1601.    snooping = 1;
  1602.    wclose ();
  1603.    CLEAR_INBOUND ();
  1604.  
  1605.    wopen (3, 2, 13, 76, 3, RED|_LGREY, BLUE|_LGREY);
  1606.    wshadow (DGREY|_BLACK);
  1607.    wtitle ("IEMSI SERVER", TLEFT, RED|_LGREY);
  1608.  
  1609.    wprints (1, 1, BLACK|_LGREY, "You have reached :");
  1610.    wprints (3, 1, BLACK|_LGREY, "Id");
  1611.    wprints (4, 1, BLACK|_LGREY, "Name");
  1612.    wprints (5, 1, BLACK|_LGREY, "Location");
  1613.    wprints (6, 1, BLACK|_LGREY, "Operator");
  1614.    wprints (7, 1, BLACK|_LGREY, "Notice");
  1615.  
  1616.    wprints (3, 12, BLUE|_LGREY, id);
  1617.    wprints (4, 12, BLUE|_LGREY, name);
  1618.    wprints (5, 12, BLUE|_LGREY, location);
  1619.    wprints (6, 12, BLUE|_LGREY, operator);
  1620.    wprints (7, 12, BLUE|_LGREY, notice);
  1621.  
  1622.    timer (config->iemsi_infotime * 10);
  1623.    wclose ();
  1624. }
  1625.  
  1626. int pickstrw(int srow,int scol,int erow,int ecol,int btype,int bordattr,
  1627.              int winattr,int barattr,char *strarr[],int initelem,
  1628.              void (*open)(void),
  1629.              char *(*insert)(int),int (*delete)(char *,int),void (*edit)(int));
  1630.  
  1631. #define MAX_PHONES 100
  1632.  
  1633. static int numphones;
  1634. static char **list;
  1635. static DIALREC *dr;
  1636.  
  1637. void edit_single_entry (DIALREC *dr, char *title)
  1638. {
  1639.    int i;
  1640.    char string[50];
  1641.    DIALREC nd;
  1642.  
  1643.    memcpy (&nd, dr, sizeof (DIALREC));
  1644.  
  1645.    wopen (7, 13, 20, 68, 3, LCYAN|_BLACK, CYAN|_BLACK);
  1646.    wshadow (DGREY|_BLACK);
  1647.    wtitle (title, TRIGHT, YELLOW|_BLUE);
  1648.    i = 1;
  1649.  
  1650.    do {
  1651.       wclear ();
  1652.  
  1653.       wmenubegc ();
  1654.       wmenuitem ( 1,  1, " Name           ", 0,  1, 0, NULL, 0, 0);
  1655.       wmenuitem ( 2,  1, " Location       ", 0,  2, 0, NULL, 0, 0);
  1656.       wmenuitem ( 3,  1, " Phone          ", 0,  3, 0, NULL, 0, 0);
  1657.       wmenuitem ( 4,  1, " Password       ", 0,  4, 0, NULL, 0, 0);
  1658.       wmenuitem ( 5,  1, " Download path  ", 0,  5, 0, NULL, 0, 0);
  1659.       wmenuitem ( 6,  1, " Auto capture   ", 0,  6, 0, NULL, 0, 0);
  1660.       wmenuitem ( 7,  1, " └─ Capture     ", 0,  7, 0, NULL, 0, 0);
  1661.       wmenuitem ( 8,  1, " IEMSI          ", 0,  8, 0, NULL, 0, 0);
  1662.       wmenuitem ( 9,  1, " Local echo     ", 0,  9, 0, NULL, 0, 0);
  1663.       wmenuitem (10,  1, " Strip high bit ", 0, 10, 0, NULL, 0, 0);
  1664.       wmenuend (i, M_OMNI|M_SAVE, 0, 0, LGREY|_BLACK, LGREY|_BLACK, LGREY|_BLACK, BLUE|_LGREY);
  1665.  
  1666.       wprints (1, 18, CYAN|_BLACK, nd.name);
  1667.       wprints (2, 18, CYAN|_BLACK, nd.location);
  1668.       wprints (3, 18, CYAN|_BLACK, nd.phone);
  1669.       memset (string, '.', 20);
  1670.       string[strlen (nd.password)] = '\0';
  1671.       wprints (4, 18, CYAN|_BLACK, string);
  1672.       wprints (5, 18, CYAN|_BLACK, nd.download);
  1673.       wprints (6, 18, CYAN|_BLACK, nd.open_capture ? "Yes" : "No");
  1674.       wprints (7, 18, CYAN|_BLACK, nd.capture);
  1675.       wprints (8, 18, CYAN|_BLACK, nd.iemsi ? "Yes" : "No");
  1676.       wprints (9, 18, CYAN|_BLACK, nd.local_echo ? "Yes" : "No");
  1677.       wprints (10, 18, CYAN|_BLACK, nd.strip_high ? "Yes" : "No");
  1678.  
  1679.       i = wmenuget ();
  1680.  
  1681.       switch (i) {
  1682.          case 1:
  1683.             strcpy (string, nd.name);
  1684.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1685.             winpdef (1, 18, string, "???????????????????????????????????", 0, 2, NULL, 0);
  1686.             if (winpread () != W_ESCPRESS)
  1687.                strcpy (nd.name, strtrim (string));
  1688.             break;
  1689.  
  1690.          case 2:
  1691.             strcpy (string, nd.location);
  1692.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1693.             winpdef (2, 18, string, "?????????????????????????????", 0, 2, NULL, 0);
  1694.             if (winpread () != W_ESCPRESS)
  1695.                strcpy (nd.location, strtrim (string));
  1696.             break;
  1697.  
  1698.          case 3:
  1699.             strcpy (string, nd.phone);
  1700.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1701.             winpdef (3, 18, string, "?????????????????????????????", 0, 2, NULL, 0);
  1702.             if (winpread () != W_ESCPRESS)
  1703.                strcpy (nd.phone, strtrim (string));
  1704.             break;
  1705.  
  1706.          case 4:
  1707.             strcpy (string, nd.password);
  1708.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1709.             winpdef (4, 18, string, "???????????????????", 0, 2, NULL, 0);
  1710.             if (winpread () != W_ESCPRESS)
  1711.                strcpy (nd.password, strtrim (string));
  1712.             break;
  1713.  
  1714.          case 5:
  1715.             strcpy (string, nd.download);
  1716.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1717.             winpdef (5, 18, string, "???????????????????????????????????", 0, 2, NULL, 0);
  1718.             if (winpread () != W_ESCPRESS)
  1719.                strcpy (nd.download, strtrim (string));
  1720.             break;
  1721.  
  1722.          case 6:
  1723.             nd.open_capture ^= 1;
  1724.             break;
  1725.  
  1726.          case 7:
  1727.             strcpy (string, nd.capture);
  1728.             winpbeg (BLUE|_GREEN, BLUE|_GREEN);
  1729.             winpdef (7, 18, string, "???????????????????????????????????", 0, 2, NULL, 0);
  1730.             if (winpread () != W_ESCPRESS)
  1731.                strcpy (nd.capture, strtrim (string));
  1732.             break;
  1733.  
  1734.          case 8:
  1735.             nd.iemsi ^= 1;
  1736.             break;
  1737.  
  1738.          case 9:
  1739.             nd.local_echo ^= 1;
  1740.             break;
  1741.  
  1742.          case 10:
  1743.             nd.strip_high ^= 1;
  1744.             break;
  1745.       }
  1746.  
  1747.       hidecur ();
  1748.    } while (i != -1);
  1749.  
  1750.    wclose ();
  1751.    memcpy (dr, &nd, sizeof (DIALREC));
  1752. }
  1753.  
  1754. char *insert_entry (int n)
  1755. {
  1756.    int i;
  1757.    char string[50], *nlist;
  1758.    DIALREC nd;
  1759.  
  1760.    if (numphones < MAX_PHONES) {
  1761.       memset (&nd, 0, sizeof (DIALREC));
  1762.  
  1763.       edit_single_entry (&nd, " Add entry ");
  1764.  
  1765.       nlist = (char *)malloc (72);
  1766.       sprintf (nlist, " %2d  %-29.29s %-20.20s %-15.15s", n + 1, nd.name, nd.location, nd.phone);
  1767.  
  1768.       for (i = numphones; i >= n; i--)
  1769.          memcpy (&dr[i + 1], &dr[i], sizeof (DIALREC));
  1770.       memcpy (&dr[n], &nd, sizeof (DIALREC));
  1771.       numphones++;
  1772.  
  1773.       for (i = n; i < numphones - 1; i++) {
  1774.          sprintf (string, " %2d", i + 2);
  1775.          memcpy (list[i], string, 3);
  1776.       }
  1777.  
  1778.       return (nlist);
  1779.    }
  1780.  
  1781.    return (NULL);
  1782. }
  1783.  
  1784. void edit_entry (int n)
  1785. {
  1786.    edit_single_entry (&dr[n], " Edit entry ");
  1787.    sprintf (list[n], " %2d  %-29.29s %-20.20s %-15.15s", n + 1, dr[n].name, dr[n].location, dr[n].phone);
  1788. }
  1789.  
  1790. int delete_entry (char *str, int n)
  1791. {
  1792.    int i;
  1793.    char string[4];
  1794.  
  1795.    if (numphones == 0 || n >= numphones)
  1796.       return (0);
  1797.  
  1798.    wopen (10, 25, 14, 54, 3, BLACK|_LGREY, BLACK|_LGREY);
  1799.    wshadow (DGREY|_BLACK);
  1800.  
  1801.    wcenters (1, BLACK|_LGREY, "Are you sure (Y/n) ?  ");
  1802.  
  1803.    strcpy (string, "Y");
  1804.    winpbeg (BLACK|_LGREY, BLACK|_LGREY);
  1805.    winpdef (1, 24, string, "?", 0, 2, NULL, 0);
  1806.  
  1807.    i = winpread ();
  1808.    wclose ();
  1809.    hidecur ();
  1810.  
  1811.    if (i == W_ESCPRESS)
  1812.       return (0);
  1813.  
  1814.    if (toupper (string[0]) == 'Y') {
  1815.       for (i = n; i < numphones; i++) {
  1816.          memcpy (&dr[i], &dr[i + 1], sizeof (DIALREC));
  1817.          sprintf (string, " %2d", i);
  1818.          memcpy (list[i], string, 3);
  1819.       }
  1820.  
  1821.       free (str);
  1822.  
  1823.       numphones--;
  1824.       return (1);
  1825.    }
  1826.  
  1827.    return (0);
  1828. }
  1829.  
  1830. int dialing_directory (DIALREC *dialrec)
  1831. {
  1832.    int fd, i, res;
  1833.  
  1834.    setkbloop (keyboard_loop);
  1835.    hidecur ();
  1836.    numphones = 0;
  1837.  
  1838.    dr = (DIALREC *)malloc (MAX_PHONES * sizeof (DIALREC));
  1839.    memset (dr, 0, MAX_PHONES * sizeof (DIALREC));
  1840.  
  1841.    list = (char **)malloc (MAX_PHONES * sizeof (char *));
  1842.    memset (list, 0, MAX_PHONES * sizeof (char *));
  1843.  
  1844.    if ((fd = open ("PHONE.DAT", O_RDONLY|O_BINARY)) != -1) {
  1845.       numphones = (int)(filelength (fd) / sizeof (DIALREC));
  1846.       if (numphones > MAX_PHONES)
  1847.          numphones = MAX_PHONES;
  1848.       read (fd, dr, numphones * sizeof (DIALREC));
  1849.       close (fd);
  1850.    }
  1851.  
  1852.    for (i = 0; i < numphones; i++) {
  1853.       list[i] = (char *)malloc (72);
  1854.       sprintf (list[i], " %2d  %-29.29s %-20.20s %-15.15s", i + 1, dr[i].name, dr[i].location, dr[i].phone);
  1855.    }
  1856.  
  1857.    if (i < MAX_PHONES) {
  1858.       list[i] = (char *)malloc (72);
  1859.       memset (list[i], ' ', 71);
  1860.       list[i][71] = '\0';
  1861.    }
  1862.  
  1863.    wopen (4, 4, 21, 76, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  1864.    wshadow (DGREY|_BLACK);
  1865.    wprints (0, 0, LGREY|_BLACK, "  #  System name                   Location             Phone");
  1866.    whline (1, 0, 71, 2, BLUE|_BLACK);
  1867.    whline (14, 0, 71, 2, BLUE|_BLACK);
  1868.    wprints (15, 1, LGREY|_BLACK, "ESC-Exit  ENTER-Dial  INS-Add  E-Edit  DEL-Delete");
  1869.    wprints (15, 1, YELLOW|_BLACK, "ESC");
  1870.    wprints (15, 11, YELLOW|_BLACK, "ENTER");
  1871.    wprints (15, 23, YELLOW|_BLACK, "INS");
  1872.    wprints (15, 32, YELLOW|_BLACK, "E");
  1873.    wprints (15, 40, YELLOW|_BLACK, "DEL");
  1874.  
  1875.    res = pickstrw (7, 5, 18, 75, 5, LCYAN|_BLACK, LCYAN|_BLACK, BLACK|_LGREY, list, 0, NULL, insert_entry, delete_entry, edit_entry);
  1876.    wclose ();
  1877.  
  1878.    if (res >= 0 && dialrec != NULL)
  1879.       memcpy (dialrec, &dr[res], sizeof (DIALREC));
  1880.  
  1881.    if ((fd = open ("PHONE.DAT", O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE)) != -1) {
  1882.       write (fd, dr, sizeof (DIALREC) * numphones);
  1883.       close (fd);
  1884.    }
  1885.  
  1886.    for (i = 0; i < numphones; i++)
  1887.       free (list[i]);
  1888.    free (list[i]);
  1889.    free (list);
  1890.    free (dr);
  1891.  
  1892.    showcur ();
  1893.    setkbloop (NULL);
  1894.  
  1895.    return (res);
  1896. }
  1897.  
  1898. void dial_entry (DIALREC *dialrec)
  1899. {
  1900.    int i, ctry = 1, tout;
  1901.    char string[40], phone[60];
  1902.    long t;
  1903.  
  1904.    setkbloop (keyboard_loop);
  1905.    hidecur ();
  1906.  
  1907.    wopen (6, 10, 19, 70, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  1908.    wtitle (" Dial system ", TRIGHT, YELLOW|_BLUE);
  1909.    wshadow (DGREY|_BLACK);
  1910.    wprints (0, 1, LGREY|_BLACK, "Attempt #");
  1911.    whline (1, 0, 71, 2, BLUE|_BLACK);
  1912.  
  1913.    wprints (2, 1, LGREY|_BLACK, "Name       : ");
  1914.    wprints (3, 1, LGREY|_BLACK, "Location   : ");
  1915.    wprints (4, 1, LGREY|_BLACK, "Phone      : ");
  1916.  
  1917.    wprints (2, 14, CYAN|_BLACK, dialrec->name);
  1918.    wprints (3, 14, CYAN|_BLACK, dialrec->location);
  1919.    strcpy (phone, dialrec->phone);
  1920.    translate_phone (phone);
  1921.    wprints (4, 14, CYAN|_BLACK, phone);
  1922.  
  1923.    whline (5, 0, 71, 2, BLUE|_BLACK);
  1924.    wprints (6, 1, LGREY|_BLACK, "ESC-Abort  SPACE-Retry  A-Add 15 secs.");
  1925.    wprints (6, 1, YELLOW|_BLACK, "ESC");
  1926.    wprints (6, 12, YELLOW|_BLACK, "SPACE");
  1927.    wprints (6, 25, YELLOW|_BLACK, "A");
  1928.    whline (7, 0, 71, 2, BLUE|_BLACK);
  1929.  
  1930.    for (;;) {
  1931.       wprints (0, 15, LGREY|_BLACK, "         ");
  1932.       tout = config->dial_timeout;
  1933.  
  1934.       sprintf (string, "%d", ctry);
  1935.       wprints (0, 11, YELLOW|_BLACK, string);
  1936.  
  1937.       t = time (NULL);
  1938.       sprintf (string, "   Timeout %d seconds", tout);
  1939.       wrjusts (0, 57, LGREY|_BLACK, string);
  1940.       sprintf (string, "%d", tout);
  1941.       wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  1942.  
  1943. retry1:
  1944.       status_line (msgtxt[M_DIALING_NUMBER], phone);
  1945.       dial_number (0, phone);
  1946.  
  1947. retry3:
  1948.       while (tout) {
  1949.          if (time (NULL) != t) {
  1950.             tout--;
  1951.             t = time (NULL);
  1952.             sprintf (string, "   Timeout %d seconds", tout);
  1953.             wrjusts (0, 57, LGREY|_BLACK, string);
  1954.             sprintf (string, "%d", tout);
  1955.             wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  1956.          }
  1957.  
  1958.          release_timeslice ();
  1959.             if (kbmhit ())
  1960.                 break;
  1961.  
  1962.             if ((i = modem_response ()) != -1) {
  1963.                 switch (i) {
  1964.                     case 1:
  1965.                         rate = 300;
  1966.                         break;
  1967.                     case 5:
  1968.                         rate = 1200;
  1969.                         break;
  1970.                     case 11:
  1971.                         rate = 2400;
  1972.                         break;
  1973.                     case 18:
  1974.                         rate = 4800;
  1975.                         break;
  1976.                     case 16:
  1977.                         rate = 7200;
  1978.                         break;
  1979.                     case 12:
  1980.                         rate = 9600;
  1981.                         break;
  1982.                     case 17:
  1983.                         rate = 12000;
  1984.                         break;
  1985.                     case 15:
  1986.                         rate = 14400;
  1987.                         break;
  1988.                     case 19:
  1989.                         rate = 16800;
  1990.                         break;
  1991.                     case 13:
  1992.                         rate = 19200;
  1993.                         break;
  1994.                     case 14:
  1995.                         rate = 38400U;
  1996.                         break;
  1997.                     case 20:
  1998.                         rate = 57600U;
  1999.                         break;
  2000.                     case 21:
  2001.                         rate = 21600;
  2002.                         break;
  2003.                     case 22:
  2004.                         rate = 28800;
  2005.                         break;
  2006.                     case 28:
  2007.                         rate = 24000;
  2008.                         break;
  2009.                     case 29:
  2010.                         rate = 26400;
  2011.                         break;
  2012.                     case 30:
  2013.                         rate = 31200;
  2014.                         break;
  2015.                     case 31:
  2016.                         rate = 33600;
  2017.                         break;
  2018.                 }
  2019.  
  2020.                 switch (i) {
  2021.                     case 1:
  2022.                     case 5:
  2023.                     case 11:
  2024.                     case 18:
  2025.                     case 16:
  2026.                     case 12:
  2027.                     case 17:
  2028.                     case 15:
  2029.                     case 19:
  2030.                     case 13:
  2031.                     case 14:
  2032.                     case 20:
  2033.                     case 21:
  2034.                     case 22:
  2035.                     case 28:
  2036.                     case 29:
  2037.                     case 30:
  2038.                     case 31:
  2039.                     case 40:
  2040.                         wclose ();
  2041.                         setkbloop (NULL);
  2042.  
  2043.                         wopen (10, 22, 14, 57, 3, LCYAN|_BLACK, LCYAN|_BLACK);
  2044.                         wshadow (LGREY|_BLACK);
  2045.                         sprintf (string, "Connect at %u bps", rate);
  2046.                         wcenters (1, LGREY|_BLACK, string);
  2047.                         timer (15);
  2048.                         wclose ();
  2049.                         return;
  2050.                 }
  2051.  
  2052.                 break;
  2053.          }
  2054.       }
  2055.  
  2056.       if (kbmhit ()) {
  2057.          if ((i = getxch ()) == 0x011B)
  2058.             break;
  2059.          else if (i == 0x1E61 || i == 0x1E41) {
  2060.             tout += 15;
  2061.             sprintf (string, "   Timeout %d seconds", tout);
  2062.             wrjusts (0, 57, LGREY|_BLACK, string);
  2063.             sprintf (string, "%d", tout);
  2064.             wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  2065.             goto retry3;
  2066.          }
  2067.          else if (i != 0x3920)
  2068.             goto retry3;
  2069.       }
  2070.  
  2071.       tout = config->dial_pause;
  2072.  
  2073.       modem_hangup ();
  2074.       wprints (0, 15, LGREY|_BLACK, "(Pausing)");
  2075.  
  2076.       t = time (NULL);
  2077.       sprintf (string, "   Timeout %d seconds", tout);
  2078.       wrjusts (0, 57, LGREY|_BLACK, string);
  2079.       sprintf (string, "%d", tout);
  2080.       wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  2081.  
  2082. retry2:
  2083.       while (tout) {
  2084.          if (time (NULL) != t) {
  2085.             tout--;
  2086.             t = time (NULL);
  2087.             sprintf (string, "   Timeout %d seconds", tout);
  2088.             wrjusts (0, 57, LGREY|_BLACK, string);
  2089.             sprintf (string, "%d", tout);
  2090.             wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  2091.          }
  2092.  
  2093.          modem_response ();
  2094.          release_timeslice ();
  2095.  
  2096.          if (kbmhit ())
  2097.             break;
  2098.       }
  2099.  
  2100.       if (kbmhit ()) {
  2101.          if ((i = getxch ()) == 0x011B)
  2102.             break;
  2103.          else if (i == 0x1E61 || i == 0x1E41) {
  2104.             tout += 15;
  2105.             sprintf (string, "   Timeout %d seconds", tout);
  2106.             wrjusts (0, 57, LGREY|_BLACK, string);
  2107.             sprintf (string, "%d", tout);
  2108.             wprints (0, 50 - strlen (string), YELLOW|_BLACK, string);
  2109.             goto retry2;
  2110.          }
  2111.          else if (i != 0x3920)
  2112.             goto retry2;
  2113.       }
  2114.  
  2115.       ctry++;
  2116.    }
  2117.  
  2118.    wprints (0, 15, LGREY|_BLACK, "(Aborting)");
  2119.    modem_hangup ();
  2120.  
  2121.    wclose ();
  2122.    showcur ();
  2123.    setkbloop (NULL);
  2124. }
  2125.  
  2126. static void translate_phone (char *phone)
  2127. {
  2128.    int fd;
  2129.    char filename[80], deftrasl[60], rep = 0;
  2130.    ACCOUNT ai;
  2131.  
  2132.    deftrasl[0] = '\0';
  2133.  
  2134.    sprintf (filename, "%sCOST.DAT", config->net_info);
  2135.    fd = open (filename, O_RDONLY|O_BINARY);
  2136.  
  2137.    while (read (fd, (char *)&ai, sizeof (ACCOUNT)) == sizeof (ACCOUNT)) {
  2138.       if (!strncmp (phone, ai.search, strlen (ai.search))) {
  2139.          strisrep (phone, ai.search, ai.traslate);
  2140.          rep = 1;
  2141.          break;
  2142.       }
  2143.       else if (!strcmp (ai.search, "/"))
  2144.          strcpy (deftrasl, ai.traslate);
  2145.    }
  2146.  
  2147.    if (!rep && deftrasl[0]) {
  2148.       strcpy (filename, deftrasl);
  2149.       strcat (filename, phone);
  2150.       strcpy (phone, filename);
  2151.    }
  2152.  
  2153.    close (fd);
  2154. }
  2155.  
  2156.