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 / BDSC / BDSC-2 / TELED12.CQ / TELED12.C
Text File  |  2000-06-30  |  20KB  |  910 lines

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