home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / HEATH / TELEDT.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  18KB  |  997 lines

  1. /*
  2.     TELEDIT.C    v1.1        (see TELEDIT.DOC)
  3.  
  4.     A telecommunications program using Ward Christensen's
  5.     "MODEM" File Transfer Protocol.
  6.  
  7.      Modified by Nigel Harrison and Leor Zolman from XMODEM.C,
  8.     which was written by:  Jack M. Wierda,
  9.                modified by Roderick W. Hart and William D. Earnest
  10.  
  11.     Note that Modem port numbers, masks, etc., are taken from BDSCIO.H,
  12.     which must have the correct values for your system.    
  13. */
  14.  
  15. /*
  16.     Converted to HDOS by Al Bolduc
  17. */
  18.  
  19. #include    console.h
  20. #include    printf.h
  21.  
  22. /*
  23.     The following three defines must be customized by the user:
  24. */
  25. #define HC    "\33H*"            /* Home cursor and print a "*"    */
  26. #define    SPECIAL    '^'-0x40        /* Gets out of terminal mode    */
  27. #define    CPUCLK    2            /* CPU clock rate, in MHz     */
  28.  
  29. /*
  30.     The rest of the defines need not be modified
  31. */
  32.  
  33. #define    EOF    -1
  34. #define    NULL    0
  35. #define    TRUE    1
  36. #define    FALSE    0
  37. #define    ERROR    -1
  38. #define    BUFSIZ    256
  39. #define    CPMEOF    0X1A
  40. #define    MDATA    0330
  41. #define    MSTAT    0335
  42. #define    CLEARS    "\033E"
  43. #define    SECSIZ    128
  44. #define    NSECTS    2
  45. #define    MAXLINE    100
  46. #define    SOH 1
  47. #define    EOT 4
  48. #define    ACK 6
  49. #define    ERRORMAX 10
  50. #define    RETRYMAX 10
  51. #define    LF 10
  52. #define    CR 13
  53. #define    SPS 1500                   /*loops per second */
  54. #define    NAK 21
  55. #define    TIMEOUT -1
  56. #define    TBFSIZ NSECTS*SECSIZ
  57. #define    ML 1000                /* maximum source lines */
  58.  
  59. char linebuf[MAXLINE];            /* string buffer */
  60. char fnambuf[50];            /* name of file for text collection */
  61. int nlines, nl;                /* number of lines    */
  62. int linect;                /* current line    */
  63. char fflg;                /* text collection file flag */
  64. char echoflg;                /* whether to echo        */
  65. char sflg;                /* transmit flag        */
  66. char    *textbuf;            /* Text buffer            */
  67. char    *textend;            /* End of text buffer        */
  68. unsigned    textind;        /* Index into text buffer    */
  69. int    baud = 300;            /* Baudrate (set to default)    */
  70.  
  71. int moready()    /* return TRUE if the modem is ready for output */
  72. {
  73.     return(in(MSTAT) & 040);
  74. }
  75.  
  76. int miready()     /* return TRUE if input is present on the modem */
  77. {
  78.     return (in(MSTAT) & 01);
  79. }
  80.  
  81. send(data)    /* send char to modem */
  82. char data;
  83. {
  84.     while(!moready())
  85.         ;
  86.     out(data,MDATA);
  87. }
  88.  
  89. main(argc,argv)
  90. char *argv[];
  91. {
  92.     int i, j, k, l;            /* scratch integers */
  93.     char *lineptr[ML];        /* allow ML source lines */
  94.     char *inl[ML];            /* inserted line pointers */
  95.     char *p;            /* scratch pointer */
  96.     int    fdes;            /* I/O file descriptor */
  97.     int  inchar;            /* collect characters at inchar */
  98.     char *alloc();            /* storage allocator */
  99.     char *getm();            /* memory procuror */
  100.  
  101.     linect = nlines = i = 0;
  102.     fflg = echoflg = FALSE;
  103.     lineptr[i] = (char *)NULL;
  104.     init();
  105.  
  106.     while(1)
  107.     {
  108.         lnmode();
  109.         printf(CLEARS);
  110.         printf("Teledit ver 1.1\n\n");
  111.  
  112.         printf("\tT: Terminal mode - no text collection\n");
  113.         printf("\tX: terminal mode with teXt collection\n");
  114.         printf("\t\tIn terminal mode:\n");
  115.         printf("\t\tSPECIAL (control-^): return to menu\n");
  116.         printf("\t\tcontrol-E: enter editor\n");
  117.         printf("\tB: Baudrate (currently set to: %d)\n",baud);
  118.         printf("\tG: toGgle echo mode (currently set to: %secho)\n",
  119.         echoflg ? "" : "no ");
  120.         printf("\tE: Edit collected text\n");
  121.         printf("\tF: Flush text buffer to text collection file\n");
  122.         printf("\tS: Send a file, MODEM protocol\n");
  123.         printf("\tR: Receive a file, MODEM protocol\n");   
  124.         printf("\tQ: quit\n");
  125.         printf("\tSPECIAL: send SPECIAL char to modem\n");
  126.         printf("\nCommand: ");
  127.         chmode();
  128.  
  129.         inchar = 0XDF & getchar();
  130.         putchar(inchar);
  131.         putchar('\n');
  132.  
  133.         switch(inchar)
  134.         {
  135.         case SPECIAL:
  136.             send(SPECIAL);
  137.             break;
  138.         case 'T':
  139.             rawmode();
  140.             terminal();
  141.             break;
  142.         case 'X':
  143.             if (fflg)
  144.     printf("Text collection already in effect (filename '%s')\n", fnambuf);
  145.             else
  146.             {
  147.                 printf("Collection text filename = ");
  148.                 gets(fnambuf);
  149.  
  150.                 printf("Wait...");
  151.                 if((fdes = fopen(fnambuf,"r")) != NULL)
  152.                 {    
  153.                     fclose(fdes);
  154.                     printf("\nFile already exists; do you want to ");
  155.                     if(!ask("overwrite it"))       
  156.                         break;
  157.                 }
  158.                 else
  159.                     fclose(fdes);
  160.                 if((fdes = fopen(fnambuf, "w")) == NULL)
  161.                 {    
  162.                     printf("\nCan't create %s", fnambuf);
  163.                     break;
  164.                 }
  165.  
  166.                 fflg = TRUE;    
  167.             }
  168.             printf("\nReady\n");
  169.  
  170.             rawmode();    
  171.             while(1)    
  172.             {    
  173.                 if(miready())
  174.                 {    
  175.                     putchar (inchar = 0177 & in(MDATA));
  176.  
  177.                     if(i > (MAXLINE + 5))
  178.                         inchar = CR;
  179.                     if(inchar >= ' ')
  180.                         linebuf[i++] = inchar;
  181.                     else
  182.                     {    
  183.                         if(inchar == CR)
  184.                         {    
  185.                             linebuf[i++] = '\n';
  186.                             linebuf[i] = NULL;
  187.                             p = getm(linebuf);
  188.                             if(p == NULL) continue;
  189.                             lineptr[nlines++] = p;
  190.                             lineptr[nlines] = NULL;
  191.                             if(nlines > 500) putchar('\7');
  192.                             i = 0;
  193.                         }
  194.                         else if(inchar == '\t' || in == '\f')
  195.                             linebuf[i++] = inchar;
  196.                         else
  197.                             continue;
  198.                     }
  199.                 }
  200.                 if(inchar = chrdy())
  201.                 {
  202.                     if(echoflg)
  203.                         putchar(inchar);
  204.  
  205.                     if(inchar == SPECIAL)
  206.                         break;
  207.                     else if(inchar == ('E' & 037))
  208.                     {
  209.                         chmode();
  210.                         ed(lineptr);
  211.                         printf("Terminal mode:\n\n");
  212.                         rawmode();
  213.                     }
  214.                     else
  215.                         send(inchar);
  216.                 }
  217.             }
  218.             break;
  219.         
  220.         case 'S':
  221.         case 'R':
  222.             printf("File to %s = ", (inchar == 'S') ? "send" : "receive");
  223.             gets(linebuf);
  224.  
  225.             if(inchar == 'R')
  226.                 readfile(linebuf);
  227.             else
  228.             {
  229.                 if((fdes = fopen(linebuf, "r")) == NULL)
  230.                 {    
  231.                     printf("\7Teledit: can't open %s\n", linebuf);
  232.                     break;
  233.                 }
  234.                 sendfile(linebuf);
  235.             }
  236.             putchar(7);            /* beep when done */
  237.             sleep(15);
  238.             break;
  239.         
  240.         case 'E':
  241.             ed(lineptr);
  242.             break;
  243.         
  244.         case 'F':
  245.             dump(lineptr,fdes);
  246.             break;
  247.  
  248.         case 'B':
  249.             printf("Baudrate: ");
  250.             gets(linebuf);
  251.             baud = atoi(linebuf);
  252.             if(baud < 300 || baud > 9600)
  253.                 baud = 300;
  254.             initmod();
  255.             break;
  256.  
  257.         case 'G':
  258.             echoflg = !echoflg;
  259.             break;
  260.  
  261.         case 'Q':
  262.             if (fflg) {
  263.                 printf("\nSave file \"%s\" to ",fnambuf);
  264.                 if (ask("disk"))
  265.                 {    
  266.                     dump(lineptr,fdes);
  267.                     fclose(fdes);
  268.                 }
  269.             }
  270.             lnmode();
  271.             out(0,MDATA + 4);
  272.             exit();
  273.         }
  274.     }
  275. }
  276.  
  277. init() {    /* Initialize modem and allocate memory */
  278.     unsigned    size;
  279.  
  280.     size = 0XFF00 & (szofram() - 1000);
  281.     textbuf = alloc(size);
  282.     textend = textbuf + size;
  283.     textind = 0;
  284.            initmod();
  285. }
  286.  
  287. initmod() {    /* Initialize modem port */
  288.     int    tmp;
  289.  
  290.     tmp = 11520 / (baud / 10);
  291. #asm
  292.     DI
  293. #endasm
  294.     out(0,MDATA + 1);        /* Disable interupts    */
  295.     out(0200,MDATA + 3);        /* Divisor latch access    */
  296.     out(tmp & 0377,MDATA);        /* LSB            */
  297.     out((tmp >> 8) & 0377,MDATA + 1);  /* MSB        */
  298.     out(3,MDATA + 3);        /* * bits        */
  299.     out(1,MDATA + 4);        /* Turn on DTR        */
  300.     in(MDATA);            /* Clear USART        */
  301. #asm
  302.     EI
  303. #endasm
  304. }
  305.  
  306. dump(lineptr,fdes)    /* dump text buffer    */
  307. char *lineptr[];
  308. int    fdes;
  309. {
  310.     int i;
  311.  
  312.     for(i = 0; lineptr[i] != NULL; i++)
  313.         if(fprintf(fdes,lineptr[i]) == ERROR)
  314.             printf("\n\7Error writing txt, disk full?\n");
  315.  
  316.     lineptr[0] = linect = nlines = textind = 0;
  317. }
  318.  
  319. ed(lineptr)    /* editor */
  320. char **lineptr;
  321. {
  322.     char inchar, *inl[ML], *p;
  323.     int i, j, k, l,fdes;
  324.  
  325.     if(!fflg)
  326.     {    
  327.         printf("\n\7No text buffer to edit.\n");
  328.         return;
  329.     }
  330.     
  331.     printf("\nedit\n*");
  332.     nl = 22;
  333.  
  334.     while (inchar = getchar()) {
  335.         putchar(inchar);
  336.         switch (tolower(inchar)) {
  337.         case 'a':
  338.             printf("Filename to yank = ");
  339.             gets(linebuf);
  340.             if((fdes = fopen(linebuf, "r")) == NULL) {
  341.                 printf ("\r  Cannot open %s.\r*", linebuf);
  342.                 continue;
  343.             }
  344.  
  345.             for(i = 0; fgets(linebuf,fdes); i++) {
  346.                 inl[i] = getm(linebuf);
  347.                 if(inl[i] == NULL) break;
  348.             }
  349.  
  350.             inl[i] = NULL;
  351.             iblock(lineptr, inl, linect);
  352.             show (lineptr, linect, nl);
  353.             continue;
  354.         case 'b':
  355.             linect = 0;
  356.             show (lineptr, linect, nl);
  357.             continue;
  358.         case 'q':
  359.             printf(CLEARS);
  360.             return;
  361.         case 'f':
  362.             gets(linebuf);
  363.             if((i = find(lineptr, linect)) >= 0) {
  364.                 linect = i;
  365.                 show (lineptr, linect, nl);
  366.             }
  367.             else if((i = find(lineptr, 0)) >= 0) {
  368.                 linect = i;
  369.                 show (lineptr, linect, nl);
  370.             }
  371.             else
  372.             {    
  373.                 printf(HC);
  374.                 printf("  not found\r*");
  375.             }
  376.             continue;
  377.         case 'i':
  378.             j = min(linect, 5);
  379.             if(j == 0)
  380.                 printf(CLEARS);
  381.             else {
  382.                 show(lineptr, (linect - j), j);
  383.                 j++;
  384.                 printf("\b ");
  385.                 for(; j; j--)
  386.                     putchar('\n');
  387.             }
  388.             while(1) {
  389.                 gets(linebuf);
  390.                 for(i = 0; linebuf[i]; i++)  
  391.                     if(linebuf[i] == EOF)  
  392.                         break;
  393.                 if(linebuf[i] == EOF) break;
  394.                 linebuf[i++] = '\n';
  395.                 linebuf[i] = NULL;
  396.                 inl[j++] = getm(linebuf);
  397.             }
  398.             inl[j] = NULL;
  399.             iblock(lineptr, inl, linect);
  400.             show (lineptr, linect, nl);
  401.             continue;
  402.         case 'k':
  403.             putchar('\n');
  404.             show1(lineptr, linect);
  405.             kill(lineptr, linect, 1);
  406.             continue;
  407.         case 'l':
  408.             gets(linebuf);
  409.             if((i = lfind(lineptr, linect)) >= 0) {
  410.                 linect = i;
  411.                 show(lineptr, linect, nl);
  412.             }
  413.             else if((i = lfind(lineptr, 0)) >= 0) {
  414.                 linect = i;
  415.                 show(lineptr, linect, nl);
  416.             }
  417.             else {
  418.                 printf(HC);
  419.                 printf("  not found\r*");
  420.             }
  421.             continue;
  422.         case 'o':
  423.             putchar('\n');
  424.             i = linect;
  425.             while(gets(linebuf)) {
  426.                 for(j = 0; linebuf[j]; j++)
  427.                     if(linebuf[j] == EOF) break;
  428.                 if(linebuf[j] == EOF) break;
  429.                 linebuf[j++] = '\n';
  430.                 linebuf[j] = NULL;
  431. /*
  432.                 if(lineptr[i])
  433.                     free(lineptr[i]);
  434.  
  435. */
  436.                 lineptr[i++] = getm(linebuf);
  437.                 if(i > nlines) lineptr[++nlines] = NULL;
  438.             }
  439.             show (lineptr, linect, nl);
  440.             continue;
  441.         case 'p':
  442.             linect = min((linect + nl), nlines);
  443.             show (lineptr, linect, nl);
  444.             continue;
  445.         case 's':
  446.             gets(linebuf);
  447.             nl = max((atoi(linebuf)), 1);
  448.             show (lineptr, linect, nl);
  449.             continue;
  450.         case 'z':
  451.             linect = nlines;
  452.             show(lineptr, linect, nl);
  453.             continue;
  454.         case '1': 
  455.         case '2': 
  456.         case '3': 
  457.         case '4': 
  458.         case '5':
  459.         case '6': 
  460.         case '7': 
  461.         case '8': 
  462.         case '9': 
  463.         case '-':
  464.             linebuf[0] = inchar;
  465.             for (i = 1; (isdigit(inchar = getchar())); i++)
  466.                 linebuf[i] = inchar;
  467.             linebuf[i] = NULL;
  468.             i = atoi(linebuf);
  469.             if (i < 0)
  470.                 j = max((linect + i), 0);
  471.             else
  472.                 j = min((linect + i), nlines);
  473.             inchar = tolower(inchar);
  474.             if(j > linect && inchar == 'k')
  475.                 kill(lineptr, linect, (j - linect));
  476.             else
  477.                 linect = j;
  478.             if (inchar == 'p') linect = max((linect-nl), 0);
  479.             show (lineptr, linect, nl);
  480.             continue;
  481.         case '#':
  482.             printf (" of lines: %d\r*", nlines);
  483.             continue;
  484.         case '\n':
  485.             if (lineptr[linect] != NULL) {
  486.                 show1(lineptr, linect);
  487.                 linect++;
  488.             }
  489.             else
  490.                 printf (HC);
  491.             continue;
  492.         case ' ':
  493.             if(linect)
  494.                 linect--;
  495.             show(lineptr, linect, nl);
  496.             continue;
  497.         case ('E'&037):
  498.             send(inchar);
  499.             printf("\n^E sent\n");
  500.             return;
  501.         default:
  502.             printf(" ?\r*");
  503.         }
  504.     }
  505. }
  506.  
  507. shocrt(sec,try,tot)
  508. int sec,try,tot;
  509. {
  510.     if(sflg)
  511.         printf("Sending #%d (Try=%d Errs=%d)  \r", sec, try, tot);
  512.     else
  513.         printf("Awaiting #%d (Try=%d, Errs=%d)  \r", sec, try, tot);
  514.  
  515.     if(try && tot) putchar('\n');
  516. }
  517.  
  518. receive(seconds)
  519. int seconds;
  520.     int lpc,seccnt;
  521.     for (lpc = 0; lpc < CPUCLK; lpc++)
  522.     { 
  523.         seccnt = seconds * SPS;
  524.         while (!miready() && seccnt--);
  525.         if(seccnt >= 0)
  526.         { 
  527.             return(in(MDATA));   
  528.         }
  529.     }
  530.     return(TIMEOUT);
  531. }
  532.  
  533. purgeline()
  534.     while (miready())
  535.         in(MDATA);    /* purge the receive register    */
  536. }
  537.  
  538. readfile(file)
  539. char *file;
  540.     int j, firstchar, sectnum, sectcurr, sectcomp, errors;
  541.     int toterr,checksum;
  542.     int errorflag, fd;
  543.     int bufctr;
  544.     char buffer[BUFSIZ];
  545.  
  546.     sflg = FALSE;
  547.     fd = fopen(file,"w");
  548.  
  549.     if(fd == NULL)
  550.     {    
  551.         printf("Teledit: cannot create %s\n", file);
  552.         exit(1);
  553.     }
  554.  
  555.     printf("\nReady to receive %s\n", file);
  556.     sectnum = 0;
  557.     errors = 0;
  558.     toterr = 0;
  559.     bufctr = 0;
  560.     purgeline();
  561.     shocrt(0,0,0);
  562.     send(NAK);
  563.     do
  564.         { 
  565.         errorflag = FALSE;
  566.         do
  567.             firstchar = receive (10);
  568.         while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
  569.  
  570.         if(firstchar == TIMEOUT)
  571.             errorflag = TRUE;
  572.         if(firstchar == SOH)
  573.         { 
  574.             sectcurr = receive (1);
  575.             sectcomp = receive (1);
  576.             if((sectcurr + sectcomp) == 255)
  577.             { 
  578.                 if(sectcurr == sectnum + 1)
  579.                 { 
  580.                     checksum = 0;
  581.                     for(j = bufctr;j < (bufctr + SECSIZ);j++)
  582.                     { 
  583.                         buffer[j] = receive (1);
  584.                         checksum = (checksum + buffer[j]) & 0xff;
  585.                     }
  586.                     if(checksum == receive (1))
  587.                     { 
  588.                         errors = 0;
  589.                         sectnum = sectcurr;
  590.                         bufctr = bufctr + SECSIZ;
  591.                         if(bufctr == TBFSIZ)
  592.                         { 
  593.                             bufctr = 0;
  594.                             write(fd, buffer, TBFSIZ);
  595.                         }
  596.                         shocrt(sectnum,errors,toterr);
  597.                         send(ACK);
  598.                     }
  599.                     else
  600.                         errorflag = TRUE;
  601.                 }
  602.                 else
  603.                     if(sectcurr == sectnum)
  604.                     { 
  605.                         do;
  606.                         while(receive (1) != TIMEOUT) 
  607.                             ;
  608.                         send(ACK);
  609.                     }
  610.                     else
  611.                         errorflag = TRUE;
  612.             }
  613.             else
  614.                 errorflag = TRUE;
  615.         }
  616.         if(errorflag == TRUE)
  617.         { 
  618.             errors++;
  619.             if(sectnum)
  620.                 toterr++;
  621.             while(receive (1) != TIMEOUT);
  622.             shocrt(sectnum,errors,toterr);
  623.             send(NAK);
  624.         }
  625.     }
  626.     while(firstchar != EOT && errors != ERRORMAX);
  627.  
  628.     if((firstchar == EOT) && (errors < ERRORMAX))
  629.     { 
  630.         send(ACK);
  631.         while(bufctr < TBFSIZ)
  632.             buffer[bufctr++] = 0;
  633.         write(fd, buffer, TBFSIZ);
  634.         printf("\nDone -- returning to menu:\n");
  635.     }
  636.     else
  637.         printf("\n\7Aborting\n\n");
  638.     fclose(fd);
  639. }
  640.  
  641. sendfile(file)
  642. char *file;
  643.     char *npnt;
  644.     int j, sectnum, sectors, attempts;
  645.     int toterr,checksum;
  646.     int bufctr, fd;
  647.     char buffer[BUFSIZ];
  648.  
  649.     sflg = TRUE;
  650.     fd = fopen(file,"r");
  651.  
  652.     if(fd == NULL)
  653.     { 
  654.         printf("\nTeledit: %s not found\n", file);
  655.         return;
  656.     }
  657. /*
  658.     else
  659.         printf("\nFile is %d sectors long.\n",rcfsiz(fd));
  660. */
  661.  
  662.     purgeline();
  663.     attempts=0;
  664.     toterr = 0;
  665.     shocrt(0,0,0);
  666.  
  667.     while((receive (10) != NAK) && (attempts != 8))
  668.     { 
  669.         attempts++;
  670.         shocrt(0,attempts,0);
  671.     }
  672.     if (attempts == 8)
  673.     { 
  674.         printf("\nTimed out awaiting initial NAK\n");
  675.         exit();
  676.     }
  677.     attempts = 0;
  678.     sectnum = 1;
  679.         
  680.     while((sectors = read(fd, buffer, BUFSIZ)) && (attempts != RETRYMAX))
  681.     { 
  682.         if(sectors == -1)
  683.         { 
  684.             printf("\nFile read error.\n");
  685.             break;
  686.         }
  687.         else
  688.         { 
  689.             sectors /= SECSIZ;
  690.             bufctr = 0;
  691.             do
  692.                 { 
  693.                 attempts = 0;
  694.                 do
  695.                     { 
  696.                     shocrt(sectnum,attempts,toterr);
  697.                     send(SOH);
  698.                     send(sectnum);
  699.                     send(-sectnum-1);
  700.                     checksum = 0;
  701.                     for(j = bufctr;j < (bufctr + SECSIZ);j++)
  702.                     { 
  703.                         send(buffer[j]);
  704.                         checksum = (checksum + buffer[j]) & 0xff;
  705.                     }
  706.                     send(checksum);
  707.                     purgeline();
  708.                     attempts++;
  709.                     toterr++;
  710.                 }
  711.                 while((receive (10) != ACK) && (attempts != RETRYMAX));
  712.                 bufctr = bufctr + SECSIZ;
  713.                 sectnum++;
  714.                 sectors--;
  715.                 toterr--;
  716.             }
  717.             while((sectors != 0) && (attempts != RETRYMAX));
  718.         }
  719.     }
  720.     if(attempts == RETRYMAX)
  721.         printf("\nNo ACK on sector, aborting\n");
  722.     else
  723.     { 
  724.         attempts = 0;
  725.         do
  726.             { 
  727.             send(EOT);
  728.             purgeline();
  729.             attempts++;
  730.         }
  731.         while((receive (10) != ACK) && (attempts != RETRYMAX));
  732.         if(attempts == RETRYMAX)
  733.             printf("\nNo ACK on EOT, aborting\n");
  734.     } 
  735.     fclose(fd);
  736.     printf("\nDone -- Returning to menu:\n");
  737. }
  738.  
  739. ask(s)
  740. char *s;
  741. {
  742.  
  743.     char c;
  744.  
  745. again:    
  746.     printf("%s (y/n)? ", s);
  747.     c = 0XDF & getchar();
  748.     putchar(c);
  749.     if(c == 'Y') {
  750.         printf("es\n");
  751.         return 1;
  752.     }
  753.  
  754.     else if(c == 'N')
  755.         printf("o\n");
  756.     else
  757.     {
  758.         printf("  \7Yes or no, please...\n");
  759.         goto again;
  760.     }
  761.     return 0;
  762. }
  763.  
  764. find(lineptr, linect)    /*Find a line having the pattern in linebuf        */
  765. char *lineptr[];
  766. int linect;
  767. {
  768.     int i;
  769.  
  770.     for(i = linect; lineptr[i] != NULL; i++)
  771.         if(pat(lineptr[i], linebuf) >= 0)
  772.             return(i);
  773.     return(-1);
  774. }
  775.  
  776. kill(lineptr, linect, nl)    /* erase lines */
  777. char *lineptr[];
  778. int linect, nl;
  779. {
  780.     int i, j;
  781.  
  782.     for (i = linect; lineptr[i] != NULL && nl > 0; i++, nl--) {
  783. /*
  784.         free(lineptr[i]);
  785. */
  786.         nlines--;
  787.     }
  788.     lineptr[linect] = NULL;
  789.     if(lineptr[i] != NULL) {
  790.         j = (nlines - linect) * 2;
  791.         movmem(&lineptr[i], &lineptr[linect], j + 2); 
  792.     }
  793. }
  794.  
  795. lfind(lineptr, linect)         /* find pattern at beginning of a line */
  796. char *lineptr[];
  797. int linect;
  798. {
  799.     int i, j;
  800.     char line[MAXLINE];
  801.  
  802.     j = strlen(linebuf);
  803.     for (i = linect; lineptr[i] != NULL; i++) {
  804.         strcpy(line, lineptr[i]);
  805.         line[j] = NULL;
  806.         if(strcmp(line, linebuf) == 0)
  807.             return i;
  808.     }
  809.     return -1;
  810. }
  811.  
  812.  
  813. pat(s, t)    /* pattern match..*/
  814. char s[], t[];
  815. {
  816.     int i, j, k;
  817.  
  818.     for(i = 0; s[i] != '\0'; i++)
  819.     {
  820.         for(j = i, k=0; t[k] != '\0' && s[j] == t[k]; j++, k++)
  821.             ;
  822.         if(t[k] == '\0')
  823.             return(i);
  824.     }
  825.     return(-1);
  826. }
  827.  
  828. show (lineptr, linect, nl)    /* screen current frame */
  829. char *lineptr[];
  830. int linect, nl;
  831. {
  832.     int i;
  833.  
  834.     printf (CLEARS);
  835.     putchar('\n');
  836.  
  837.     for (i = linect; i < (linect+nl) && lineptr[i] != NULL; i++)
  838.         printf("%s", lineptr[i]);
  839.     printf (HC);
  840.     return(i);
  841. }
  842.  
  843. show1(lineptr, linect)
  844. char **lineptr;
  845. int linect;
  846. {
  847.     int i;
  848.  
  849.     for(i = 0; i < nl; i++)
  850.         putchar('\n');
  851.  
  852.     if((linect + nl) >= nlines)
  853.         putchar('\n');
  854.     else
  855.         printf("%s", lineptr[linect+nl]);
  856.  
  857.     printf(HC);
  858.  
  859.     for(i = 0; i < 78; i++)
  860.         putchar(' ');
  861.  
  862.     printf("\r*");
  863. }
  864.  
  865. terminal()    /* terminal mode, no text */
  866. {
  867.     int inchar;
  868.  
  869.     while(1)
  870.     {
  871.         if(miready())
  872.             putchar(in(MDATA));
  873.         if(inchar = chrdy())
  874.         {
  875.             if(echoflg)
  876.                 putchar(inchar);
  877.  
  878.             if(inchar == SPECIAL)
  879.                 return;
  880.             else
  881.                 send(inchar);
  882.         }
  883.     }
  884. }
  885.  
  886. char *getm(line)    /* get memory for line, store it, return pointer */
  887. char line[];
  888. {
  889.     int    strsiz;
  890.     char    *p;
  891.  
  892.     strsiz = strlen(line) + 1;
  893.     if((textbuf + textind + strsiz) < textend) {
  894.         p = textbuf + textind;
  895.         textind += strsiz;
  896.         strcpy(p, line);
  897.     } else
  898.         p = 0;
  899.     return(p);
  900. }
  901.  
  902. iblock(rb, ib, cl)        /* insert block ib into rb at cl */
  903. char *rb[], *ib[];
  904. int cl;
  905. {
  906.     int i, j;
  907.  
  908.     j = 0;
  909.     if (rb[cl]) {
  910.         for (i = 0; ib[i]; i++)
  911.             ;
  912.         j = (nlines - cl) * 2;
  913.         movmem (&rb[cl], &rb[cl+i], j + 2);
  914.     }
  915.     for (i = 0; ib[i]; i++, cl++)
  916.         rb[cl] = ib[i];
  917.     if(!j) rb[cl] = NULL;
  918.     nlines += i;
  919.     return cl;    /* return new current line */
  920. }
  921.  
  922. gets(str)    /* Get a string from the console */
  923. char    *str; {
  924.  
  925.     lnmode();
  926.     while((*str = getchar()) != '\n')
  927.         str++;
  928.     *str = 0;
  929.     chmode();
  930. }
  931.  
  932. fgets(str,fdes)    /* Get a string from a file */
  933. char    *str;
  934. int    fdes; {
  935.  
  936.     while((*str = getc(fdes)) != '\n' && *str != EOF)
  937.         str++;
  938.     if(*str == EOF)
  939.         return(NULL);
  940.     else {
  941.         *str++ = '\n';
  942.         *str = 0;
  943.         return(str);
  944.     }
  945. }
  946.  
  947. sleep(seconds)
  948. int    seconds; {
  949.     int    i;
  950.  
  951.     while(seconds--)
  952.         for(i = 0 ; i < SPS ; i++)
  953.             ;
  954. }
  955.  
  956. tolower(c)    /* Convert c to lower case */
  957. char    c; {
  958.  
  959.     if(c >= 'A' && c <= 'Z')
  960.         c += 040;
  961.     return(c);
  962. }
  963.  
  964. isdigit(c)    /* Test if c is a digit */
  965. char    c; {
  966.  
  967.     if(c >= '0' && c <= '9')
  968.         return(1);
  969.     else
  970.         return(0);
  971. }
  972.  
  973. max(a,b)    /* Return Maximum */
  974. int    a,b; {
  975.  
  976.     return( (a > b) ? a : b);
  977. }
  978.  
  979. min(a,b)    /* Return minimum */
  980. int    a,b; {
  981.  
  982.     return( (a < b) ? a : b);
  983.  
  984. }
  985.  
  986. movmem(add1,add2,count)        /* Move memory */
  987. char    *add1,*add2;
  988. int    count; {
  989.  
  990.     while(count--)
  991.         *add2++ = *add1++;
  992. }
  993.