home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1989 / 03 / stevens.lst < prev   
File List  |  1989-02-10  |  22KB  |  759 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* ------ smallcom.c ---------- */
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <mem.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <dos.h>
  13. #include <stdlib.h>
  14. #include "window.h"
  15. #include "editor.h"
  16. #include "menu.h"
  17. #include "entry.h"
  18. #include "serial.h"
  19. #include "modem.h"
  20. #include "help.h"
  21.  
  22. #define ANSWERTIMEOUT 60
  23. #define MAXSTRINGS 15
  24. #define carrier() (inp(MODEMSTATUS) & 0x80)
  25. #define LOGFILE  "smallcom.log"
  26. #define HELPFILE "smallcom.hlp"
  27. #define CFGFILE  "smallcom.cfg"
  28. #define ALT_P 153
  29. #define ALT_C 174
  30. #define CTRL_C 3
  31. #define WILDCARD '?'
  32. static union REGS rg;
  33. static FILE *logfp, *uploadfp, *downloadfp, *cfg;
  34. static int running=1,connected,answering,savebaud;
  35. int filecount;
  36. extern int direct_connection, TIMEOUT, inserting;
  37. extern char spaces[];
  38. extern struct wn wkw;
  39. extern MENU *mn;
  40. /* ---------- prototypes ----------- */
  41. void fileedit(char *);
  42. static void displaycount(void);
  43. static void smallmenu(int);
  44. static void logserial(int);
  45. static int upload(int, int);
  46. static int download(int, int);
  47. static int call(int, int);
  48. static int directory(int, int);
  49. static int comeditor(int, int);
  50. static answer(int, int);
  51. static directcon(int, int);
  52. static int loginput(int, int);
  53. static int hangup(int, int);
  54. static int quit(int, int);
  55. static int prm(int, int);
  56. static void loadp(void);
  57. static int savep(int, int);
  58. static void set_parameters(void);
  59. static int get_filename(char *);
  60. static void notice(char *);
  61. static void statusline(void);
  62. static void putch_window(int);
  63. void upload_ASCII(FILE *);
  64. void download_ASCII(FILE *);
  65. int keyhit(void);
  66. char *prompt_line(char *, int, char *);
  67. void reset_prompt(char *, int);
  68. static int testcarrier(void);
  69. static int waitforconnect(void);
  70. static void initcom(void);
  71. int waitforresult(void);
  72. int waitforstring(char **, int, int);
  73. static void waitforcall(void);
  74. static void resetline(void);
  75. /* ------- the hook to the phone directory ---------- */
  76. static void (*phone_directory)(void) = NULL;
  77. /* ------- the hook to script processors ---------- */
  78. void (*script_processor)(void); /* filled in by directory */
  79. /* ------- hooks to file transfer protocols --------- */
  80. static int (*select_transfer_protocol)(void) = NULL;
  81. /* ----- up to five upload function pointers ----- */
  82. static void (*up_protocol[5])(FILE *file_pointer) = {
  83.     upload_ASCII, NULL, NULL, NULL, NULL
  84. };
  85. /* ----- up to five download function pointers ----- */
  86. static void (*down_protocol[5])(FILE *file_pointer) = {
  87.     download_ASCII, NULL, NULL, NULL, NULL
  88. };
  89. /* --------- Files menu ------------ */
  90. static char *fselcs[] = {
  91.     "Log Input On/Off",
  92.     "Upload a File",
  93.     "Download a File",
  94.     "Quit",
  95.     NULL
  96. };
  97. static char *fhelps[] = {"log","upload","download","quitcom"};
  98. /* ----------- Connect menu -------------- */
  99. static char *cselcs[] = {
  100.     "Place Call",
  101.     "Answer Call",
  102.     "Hang up",
  103.     "Direct Connection",
  104.     NULL
  105. };
  106. static char *chelps[] = {"call","answer","hangup","direct"};
  107. /* ---------- Parameters menu --------------- */
  108. static char *pselcs[] = {
  109.     "Com Port:                       ",
  110.     "Baud Rate:                      ",
  111.     "Data Bits:                      ",
  112.     "Stop Bit(s):                    ",
  113.     "Parity:                         ",
  114.     "Mode of Dialing:                ",
  115.     "Write Parameters",
  116.     NULL
  117. };
  118. static char *phelps[] = {"port","baud","wordlen","stopbits",
  119.                          "parity","dialmode","writecfg"};
  120. /* ---------- menu selection function tables ----------- */
  121. static int (*ffuncs[])() = {loginput,upload,download,quit};
  122. static int (*cfuncs[])() = {call,answer,hangup,directcon};
  123. static int (*pfuncs[])() = {prm,prm,prm,prm,prm,prm,savep};
  124. static int (*efuncs[])() = {comeditor};
  125. static int (*dfuncs[])() = {directory};
  126. /* ------ horizontal prompt messages ---------- */
  127. char fdesc[]="Message File Operations";
  128. char cdesc[]="Connections to Remote Processor";
  129. char pdesc[]="Set Communications Parameters for Program Start";
  130. char edesc[]="Edit a Text File";
  131. char ddesc[]="The SMALLCOM Telephone Directory";
  132. /* ------- horizontal menu bar ----------- */
  133. static MENU cmn [] = {
  134.    {"File",       fdesc, fselcs, fhelps, "ludq",    ffuncs, 0},
  135.    {"Connect",    cdesc, cselcs, chelps, "pahd",    cfuncs, 0},
  136.    {"Parameters", pdesc, pselcs, phelps, "cbdspmw", pfuncs, 0},
  137.    {"Editor",     edesc, NULL,   NULL,   "e",       efuncs, 0},
  138.    {"Directory",  ddesc, NULL,   NULL,   "d",       dfuncs, 0},
  139.    {NULL}
  140. };
  141. /* ------ filename data entry template and buffer ------- */
  142. static char filename[65], filemask[65];
  143. static FIELD fn_template[] = {
  144.     {2,14,1,filename,filemask,NULL},
  145.     {0}
  146. };
  147. /* ------ modem result codes ------- */
  148. static char *results[] = {
  149.     "\r\nOK\r\n",
  150.     "\r\nCONNECT\r\n",
  151.     "\r\nRING\r\n",
  152.     "\r\nNO CARRIER\r\n",
  153.     "\r\nERROR\r\n",
  154.     "\r\nCONNECT 1200\r\n",
  155.     "\r\nNO DIALTONE\r\n",
  156.     "\r\nBUSY\r\n",
  157.     "\r\nNO ANSWER\r\n",
  158.     "\r\n\r\n",
  159.     "\r\nCONNECT 2400\r\n",
  160.     NULL
  161. };
  162. extern int COMPORT,PARITY,STOPBITS,WORDLEN,BAUD;
  163. extern char DIAL[], PHONENO[];
  164. /* ================ MAIN ================== */
  165. void main(void)
  166. {
  167.     int c;
  168.     char *mb;
  169.     inserting = FALSE;
  170.     load_help(HELPFILE);
  171.     loadp();
  172.     savebaud = BAUD;
  173.     set_parameters();
  174.     clear_screen();
  175.     mb = display_menubar(cmn);
  176.     establish_window(1,2,80,24,TEXTFG,TEXTBG,TRUE);
  177.     statusline();
  178.     initcom();
  179.     gotoxy(2,2);
  180.     while (running) {
  181.         set_help("smallcom");
  182.         testcarrier();
  183.         if (keyhit())   {
  184.             switch (c = getkey())  {
  185.                 case F10:   smallmenu(0); break;
  186.                 case ALT_F: smallmenu(1); break;
  187.                 case ALT_C: smallmenu(2); break;
  188.                 case ALT_P: smallmenu(3); break;
  189.                 case ALT_E: smallmenu(4); break;
  190.                 case ALT_D: smallmenu(5); break;
  191.                 case CTRL_C:clear_window();
  192.                             wkw.wx = wkw.wy = 0;
  193.                             gotoxy(2,2);
  194.                             break;
  195.                 case ESC:   quit(1,1);
  196.                             break;
  197.                 default:    if (!(c & 0x80) && connected)    {
  198.                                 if (answering
  199.                                         || direct_connection)
  200.                                     logserial(c=='\r'?'\n':c);
  201.                                 writecomm(c);
  202.                                 if (c == '\r')
  203.                                     writecomm('\n');
  204.                             }
  205.                             break;
  206.             }
  207.         }
  208.         if (input_char_ready()) {
  209.             logserial(c = readcomm());
  210.             if (answering)
  211.                 writecomm(c);
  212.         }
  213.     }
  214.     if (connected)
  215.         hangup(1,1);
  216.     release_modem();
  217.     restore_menubar(mb);
  218.     delete_window();
  219.     clear_screen();
  220. }
  221. /* ---------- execute the SMALLCOM menu --------- */
  222. static void smallmenu(int n)
  223. {
  224.     window(1,25,80,25);
  225.     gotoxy(1,1);
  226.     cprintf(spaces);
  227.     putch(' ');
  228.     current_window();
  229.     menu_select(cmn, n);
  230.     set_parameters();
  231.     statusline();
  232.     gotoxy(wkw.wx+2, wkw.wy+2);
  233. }
  234. /* ------ Call menu command ------ */
  235. static int call(hs, vs)
  236. {
  237.     if (!connected) {
  238.         notice("Dialing");
  239.         placecall();
  240.         sleep(4);
  241.         delete_window();
  242.         if ((connected = waitforconnect()) == FALSE)    {
  243.             statusline();
  244.             initmodem();
  245.         }
  246.         else if (script_processor)
  247.             (*script_processor)();
  248.     }
  249.     return TRUE;
  250. }
  251. /* --------- Direct Connection menu command --------- */
  252. static int directcon(hs, vs)
  253. {
  254.     direct_connection ^= 1;
  255.     connected |= direct_connection;
  256.     return TRUE;
  257. }
  258. /* ------- Hangup menu command ------- */
  259. static int hangup(hs, vs)
  260. {
  261.     if (connected)  {
  262.         notice("Hanging up");
  263.         resetline();
  264.         delete_window();
  265.     }
  266.     return TRUE;
  267. }
  268. /* --------- Quit menu command --------- */
  269. static int quit(hs, vs)
  270. {
  271.     int c = 0;
  272.     notice("Exit to DOS?  ");
  273.     c = getkey();
  274.     delete_window();
  275.     running = (tolower(c) != 'y');
  276.     return TRUE;
  277. }
  278. /* -------- Log Input menu command -------- */
  279. static int loginput(hs, vs)
  280. {
  281.     if (logfp == NULL)
  282.         logfp = fopen(LOGFILE, "ab");
  283.     else    {
  284.         fclose(logfp);
  285.         logfp = NULL;
  286.     }
  287.     return TRUE;
  288. }
  289. /* ---------- Upload file menu command ---------- */
  290. static int upload(hs, vs)
  291. {
  292.     int pr = 0;
  293.     if (!connected) {
  294.         error_message("Not connected");
  295.         return FALSE;
  296.     }
  297.     if (uploadfp == NULL)   {
  298.         setmem(filename, sizeof filename - 1, ' ');
  299.         setmem(filemask, sizeof filemask - 1, '_');
  300.         if (get_filename(" Upload what file? ") != ESC) {
  301.             if ((uploadfp = fopen(filename, "rb")) == NULL)
  302.                 error_message("Cannot open file");
  303.             else    {
  304.                 statusline();
  305.                 if (select_transfer_protocol)
  306.                     pr = (*select_transfer_protocol)();
  307.                 (*up_protocol[pr])(uploadfp);
  308.                 fclose(uploadfp);
  309.                 uploadfp = NULL;
  310.             }
  311.         }
  312.     }
  313.     return TRUE;
  314. }
  315. /* ------ upload a file with ASCII transfer protocol ----- */
  316. void upload_ASCII(FILE *fp)
  317. {
  318.     int c;
  319.     while ((c = fgetc(fp)) != EOF)  {
  320.         writecomm(c);
  321.         displaycount();
  322.         if (input_char_ready())
  323.             logserial(readcomm());
  324.         if (keyhit())
  325.             if (getch() == ESC)
  326.                 break;
  327.         if (!testcarrier())
  328.             break;
  329.     }
  330.     filecount = 0;
  331.     if (connected)
  332.         writecomm(EOF);
  333. }
  334. /* ---------- Download file menu command ---------- */
  335. static int download(hs, vs)
  336. {
  337.     int pr = 0, save_timeout;
  338.     if (!connected) {
  339.         error_message("Not connected");
  340.         return FALSE;
  341.     }
  342.     setmem(filename, sizeof filename - 1, ' ');
  343.     setmem(filemask, sizeof filemask - 1, '_');
  344.     if (get_filename(" Download what file? ") != ESC) {
  345.         downloadfp = fopen(filename, "wb");
  346.         statusline();
  347.         if (select_transfer_protocol)
  348.             pr = (*select_transfer_protocol)();
  349.         save_timeout = TIMEOUT;
  350.         TIMEOUT = 60;
  351.         (*down_protocol[pr])(downloadfp);
  352.         TIMEOUT = save_timeout;
  353.         fclose(downloadfp);
  354.         downloadfp = NULL;
  355.     }
  356.     return TRUE;
  357. }
  358. /* ----- download a file with ASCII transfer protocol ----- */
  359. void download_ASCII(FILE *fp)
  360. {
  361.     int c = 0;
  362.     while (TRUE)    {
  363.         if (keyhit())   {
  364.             if ((c = getkey()) == ESC)
  365.                 break;
  366.             writecomm(c);
  367.             if (!answering)
  368.                 logserial(readcomm());
  369.         }
  370.         c = readcomm() & 127;
  371.         if (c == 0 || c == 0x7f)
  372.             break;
  373.         fputc(c, fp);
  374.         displaycount();
  375.         if (!testcarrier())
  376.             break;
  377.     }
  378. }
  379. /* --- echo modem input and write to the log if selected --- */
  380. static void logserial(int c)
  381. {
  382.     putch_window(c);
  383.     if (logfp)
  384.         fputc(c, logfp);
  385. }
  386. /* -------- read a file name ------------- */
  387. static int get_filename(char *ttl)
  388. {
  389.     int rtn;
  390.     establish_window(1,23,80,25,ENTRYFG,ENTRYBG,TRUE);
  391.     window_title(ttl);
  392.     gotoxy(3,2);
  393.     cputs("File name:");
  394.     rtn = data_entry(fn_template, TRUE, 1);
  395.     delete_window();
  396.     return rtn;
  397. }
  398. /* -------- small message ------------ */
  399. static void notice(char *s)
  400. {
  401.     int lf = (80-strlen(s))/2-1;
  402.     int rt = lf+strlen(s)+2;
  403.     establish_window(lf,11,rt,13,HELPFG,HELPBG,TRUE);
  404.     gotoxy(2,2);
  405.     cputs(s);
  406. }
  407. /* ---- comm and modem parameter menu commands ----- */
  408. static int prm(hs, vs)
  409. {
  410.     switch (vs) {
  411.         case 1: COMPORT ^= 3;       /* flip between 1 and 2 */
  412.                 break;
  413.         case 2: BAUD *= 2;          /* 110,150,300,  */
  414.                 if (BAUD == 220)    /* 600,1200,2400 */
  415.                     BAUD = 150;
  416.                 if (BAUD == 4800)
  417.                     BAUD = 110;
  418.                 break;
  419.         case 3: WORDLEN ^= 0xf;     /* flip between 7 and 8 */
  420.                 break;
  421.         case 4: STOPBITS ^= 3;      /* flip between 1 and 2 */
  422.                 break;
  423.         case 5: if (++PARITY == 3)  /* 0, 1, 2              */
  424.                     PARITY = 0;
  425.                 break;
  426.         case 6: DIAL[3] = DIAL[3] == 'T' ? 'P' : 'T';
  427.                 break;
  428.         default:
  429.                 break;
  430.     }
  431.     set_parameters();
  432.     return FALSE;
  433. }
  434. /* ------ post the parameters into the menu display ------- */
  435. static void set_parameters(void)
  436. {
  437.     static char *pars[] = {"None", " Odd", "Even"};
  438.     static char *mode[] = {"Pulse", " Tone"};
  439.     pselcs[0][strlen(pselcs[0])-1] = '0' + COMPORT;
  440.     sprintf(&pselcs[1][strlen(pselcs[1])-4],"%4d",BAUD);
  441.     pselcs[2][strlen(pselcs[2])-1] = '0' + WORDLEN;
  442.     pselcs[3][strlen(pselcs[3])-1] = '0' + STOPBITS;
  443.     sprintf(&pselcs[4][strlen(pselcs[4])-4],"%s",pars[PARITY]);
  444.     sprintf(&pselcs[5][strlen(pselcs[5])-5],"%s",
  445.         mode[DIAL[3]=='T']);
  446. }
  447. /* ------- load the configuration file ---------- */
  448. static void loadp(void)
  449. {
  450.     if ((cfg = fopen(CFGFILE, "r")) != NULL)    {
  451.         fscanf(cfg,"%d %d %d %d %d %c %s",
  452.         &COMPORT,&PARITY,&STOPBITS,&WORDLEN,&BAUD,&DIAL[3],
  453.             &PHONENO[0]);
  454.         fclose(cfg);
  455.     }
  456. }
  457. /* ---------- Write Parameters menu command ---------- */
  458. static int savep(hs, vs)
  459. {
  460.     cfg = fopen(CFGFILE, "w");
  461.     fprintf(cfg, "%d %d %d %d %d %c %s",
  462.         COMPORT,PARITY,STOPBITS,WORDLEN,BAUD,DIAL[3],PHONENO);
  463.     fclose(cfg);
  464.     initcom();
  465.     return FALSE;
  466. }
  467. /* --------- Editor menu command --------------- */
  468. static int comeditor(hs, vs)
  469. {
  470.     extern int MAXLINES, inserting;
  471.     MAXLINES = 800;
  472.     mn = NULL;
  473.     fileedit("");
  474.     inserting = FALSE;
  475.     insert_line();
  476.     return TRUE;
  477. }
  478. /* --------- Directory menu command --------------- */
  479. static int directory(hs, vs)
  480. {
  481.     if (phone_directory)    {
  482.         mn = NULL;
  483.         (*phone_directory)();
  484.     }
  485.     return TRUE;
  486. }
  487. /* ----------- display a status line ----------- */
  488. static void statusline(void)
  489. {
  490.     char stat[81];
  491.     static char *st = NULL;
  492.     sprintf(stat,
  493.         " %s Line %s %s %s %-12.12s       %-14.14s F10:Menu",
  494.         (connected            ? " On"         : "Off"),
  495.         (direct_connection    ? "Direct"      : "      "),
  496.         (logfp                ? "Logging"     : "       "),
  497.         ((answering & !connected)
  498.                               ? "Answering  " :
  499.          uploadfp             ? "Uploading  " :
  500.          downloadfp           ? "Downloading" : "           "),
  501.         (uploadfp||downloadfp ? filename      : " "),
  502.          *PHONENO ? PHONENO : "No Phone #");
  503.     st = prompt_line(stat, 25, st);
  504. }
  505. /* ------- write the file count into the status line ------- */
  506. static void displaycount(void)
  507. {
  508.     filecount++;
  509.     if ((filecount % 10) == 0)  {
  510.         window(1,25,80,25);
  511.         textcolor(MENUFG);
  512.         textbackground(MENUBG);
  513.         gotoxy(50,1);
  514.         cprintf("%5d", filecount);
  515.         current_window();
  516.         gotoxy(wkw.wx+2, wkw.wy+2);
  517.     }
  518. }
  519. /* ----- write a one-liner prompt saving video memory ----- */
  520. char *prompt_line(char *s, int y, char *t)
  521. {
  522.     if (t == NULL)
  523.         if ((t = malloc(160)) != NULL)
  524.             gettext(1,y,80,y,t);
  525.     window(1,y,80,y);
  526.     textcolor(MENUFG);
  527.     textbackground(MENUBG);
  528.     gotoxy(1,1);
  529.     cprintf(spaces);
  530.     putch(' ');
  531.     gotoxy(1,1);
  532.     cprintf(s);
  533.     current_window();
  534.     return t;
  535. }
  536. /* ------- reset the one-liner prompt line --------- */
  537. void reset_prompt(char *s, int y)
  538. {
  539.     puttext(1,y,80,y,s);
  540.     free(s);
  541. }
  542. /* -------- write a character to the user's window -------- */
  543. static void putch_window(int c)
  544. {
  545.     gotoxy(wkw.wx+2, wkw.wy+2);
  546.     switch (c)  {
  547.         case '\t':  while (wkw.wx % 4)
  548.                         putch_window(' ');
  549.                     break;
  550.         case '\b':  if (wkw.wx)
  551.                         --wkw.wx;
  552.                     break;
  553.         default:    putch(c);
  554.                     wkw.wx++;
  555.                     if (wkw.wx < wkw.wd-2)
  556.                         break;
  557.         case '\n':  if (wkw.wy < wkw.ht-1)
  558.                         wkw.wy++;
  559.                     else    {
  560.                         scroll_window(1);
  561.                         writeline(2, wkw.wy+2, spaces+1);
  562.                     }
  563.         case '\r':  wkw.wx = 0;
  564.                     break;
  565.     }
  566.     gotoxy(wkw.wx+2, wkw.wy+2);
  567. }
  568. /* ------------ wait for a call ------------ */
  569. static void waitforcall(void)
  570. {
  571.     answercall();
  572.     if ((connected = answering = waitforconnect()) == FALSE) {
  573.         statusline();
  574.         initmodem();
  575.     }
  576. }
  577. /* ---- wait for a line connection, reset baud rate ---- */
  578. static int waitforconnect(void)
  579. {
  580.     extern int BAUD;
  581.     int baud = 0;
  582.     while (baud == 0)
  583.         switch (waitforresult())    {
  584.             case 1:     baud = 300;  break; /* CONNECT       */
  585.             case 5:     baud = 1200; break; /* CONNECT 1200  */
  586.             case 10:    baud = 2400; break; /* CONNECT 2400  */
  587.             case 0:                         /* OK            */
  588.             case 2:     break;              /* RING          */
  589.             case 3:                         /* NO CARRIER    */
  590.             case 4:                         /* ERROR         */
  591.             case 7:                         /* BUSY          */
  592.             case 8:                         /* NO ANSWER     */
  593.             case -1:    baud = -1;   break; /* time-out      */
  594.             default:    break;              /* anything else */
  595.         }
  596.     if (baud != -1 && baud != BAUD) {
  597.         savebaud = BAUD;
  598.         BAUD = baud;
  599.         initcomport();
  600.     }
  601.     return (baud != -1);
  602. }
  603. /* ---- wait for a modem result (0-10). -1 if timed out ---- */
  604. int waitforresult(void)
  605. {
  606.     return waitforstring(results, ANSWERTIMEOUT, 0);
  607. }
  608. /* --------- wait for a string from the serial port -------- */
  609. int waitforstring(char *tbl[], int wait, int wildcard)
  610. {
  611.     int c, i, done = FALSE;
  612.     char *sr[MAXSTRINGS];
  613.     for (i = 0; tbl[i] != NULL; i++)
  614.         sr[i] = tbl[i];
  615.     while (!done)   {
  616.         set_timer(wait);
  617.         while (!input_char_ready()) {
  618.             if (timed_out())
  619.                 return -1;
  620.             if (keyhit())
  621.                 if ((c = getkey()) == ESC)
  622.                     return -1;
  623.         }
  624.         logserial(c = readcomm());
  625.         for (i = 0; tbl[i] != NULL; i++)    {
  626.             if (c==*(sr[i]) ||
  627.                    (wildcard && *(sr[i])==wildcard))   {
  628.                 if (*(++(sr[i])) == '\0')   {
  629.                     done = TRUE;
  630.                     break;
  631.                 }
  632.             }
  633.             else
  634.                 sr[i] = tbl[i];
  635.         }
  636.     }
  637.     return i;
  638. }
  639. /* ----- initialize from serial and modem parameters ----- */
  640. static void initcom(void)
  641. {
  642.     notice("Initializing Modem");
  643.     initmodem();
  644.     delete_window();
  645. }
  646. /* ----- test carrier detect -------- */
  647. static int testcarrier(void)
  648. {
  649.     if (!direct_connection && connected && carrier() == FALSE)
  650.         resetline();
  651.     return connected;
  652. }
  653. /* ------ disconnect and reestablish the serial port ------ */
  654. static void resetline(void)
  655. {
  656.     answering = connected = FALSE;
  657.     statusline();
  658.     disconnect();
  659.     BAUD = savebaud;
  660.     initcomport();
  661. }
  662. /* --------- answer a call ----------- */
  663. static int answer(hs, vs)
  664. {
  665.     answering = 1;
  666.     statusline();
  667.     gotoxy(wkw.wx+2, wkw.wy+2);
  668.     waitforcall();
  669.     return TRUE;
  670. }
  671. #if COMPILER==TURBOC
  672. /* --------- use bios to test for a keystroke -------- */
  673. int keyhit(void)
  674. {
  675.     rg.h.ah = 1;
  676.     int86(0x16, &rg, &rg);
  677.     return ((rg.x.flags & 0x40) == 0);
  678. }
  679. #endif
  680.  
  681. [LISTING TWO]
  682.  
  683. smallcom (serial.h,modem.h,editor.h,window.h,menu.h,entry.h,help.h)
  684. editshel (editor.h, menu.h, entry.h, help.h, window.h)
  685. editor (editor.h, window.h)
  686. help (help.h, window.h)
  687. modem (serial.h, modem.h)
  688. serial (serial.h)
  689. entry (entry.h, window.h)
  690. menu (menu.h, window.h)
  691. window (window.h)
  692.  
  693.  
  694.  
  695. [LISTING THREE]
  696.  
  697. #
  698. #  SMALLCOM.MAK: make file for SMALLCOM.EXE with Microsoft C/MASM
  699. #
  700.  
  701. .c.obj:
  702.     cl /DMSOFT=1 /DTURBOC=2 /DCOMPILER=MSOFT -c -W3 -Gs -AC $*.c
  703.  
  704. smallcom.obj : smallcom.c serial.h modem.h menu.h entry.h \
  705.                 help.h window.h
  706.  
  707. modem.obj : modem.c serial.h modem.h
  708.  
  709. serial.obj : serial.c serial.h
  710.  
  711. entry.obj : entry.c entry.h window.h
  712.  
  713. menu.obj : menu.c menu.h window.h
  714.  
  715. help.obj : help.c help.h window.h
  716.  
  717. editshel.obj : editshel.c editor.h menu.h entry.h help.h \
  718.                 window.h
  719.  
  720. editor.obj : editor.c editor.h window.h
  721.  
  722. window.obj : window.c window.h
  723.  
  724. microsft.obj : microsft.c
  725.  
  726. vpeek.obj : vpeek.asm
  727.     masm /MX vpeek;
  728.  
  729. keyhit.obj : keyhit.asm
  730.     masm /MX keyhit;
  731.  
  732. smallcom.exe : smallcom.obj modem.obj serial.obj editor.obj \
  733.               editshel.obj entry.obj menu.obj help.obj \
  734.               window.obj keyhit.obj vpeek.obj microsft.obj 
  735.     link @smallcom.lnk
  736.  
  737.  
  738.  
  739.  
  740. [LISTING FOUR]
  741.  
  742. smallcom+
  743. modem+
  744. serial+
  745. entry+
  746. menu+
  747. editor+
  748. editshel+
  749. help+
  750. window+
  751. vpeek+
  752. keyhit+
  753. microsft
  754. smallcom
  755. nul
  756. \lib\clibce
  757.  
  758.  
  759.