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 / EDITC80 / ED3.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  13KB  |  709 lines

  1. /*
  2.  * Screen editor:  command mode commands -- enhanced
  3.  *
  4.  * Source: ed3.c
  5.  * Version: December 20, 1981.
  6.  * Transliteration of small-C version of September 5, 1981
  7.  *
  8.  */
  9.  
  10. /* define globals */
  11.  
  12. #include ed1.h
  13.  
  14. /* data global to these routines */
  15.  
  16. /* comment out -----
  17. char filename [SYSFNMAX];
  18. ----- end comment out */
  19.  
  20.  
  21. /* append command.
  22.  * load a file into main buffer at current location.
  23.  * this command does NOT change the current file name.
  24.  */
  25.  
  26. append(args) char *args;
  27. {
  28. char buffer [MAXLEN];        /* disk line buffer */
  29. int file;
  30. int n;
  31. int topline;
  32. char locfn [SYSFNMAX];        /* local file name */
  33.     /* get file name which follows command */
  34.     if (name1(args,locfn) == ERR) {
  35.         return;
  36.     }
  37.     if (locfn [0] == EOS) {
  38.         message("no file argument");
  39.         return;
  40.     }
  41.     /* open the new file */
  42.     if ((file=sysopen(locfn,"r")) == ERR) {
  43.         message("file not found");
  44.         return;
  45.     }
  46.     /* read the file into the buffer */
  47.     while ((n=readline(file,buffer,MAXLEN)) >= 0) {
  48.         if (n > MAXLEN) {
  49.             message("line truncated");
  50.             n=MAXLEN;
  51.         }
  52.         if (bufins(buffer,n) == ERR) {
  53.             break;
  54.         }
  55.         if (bufdn() == ERR) {
  56.             break;
  57.         }
  58.     }
  59.     /* close the file */
  60.     sysclose(file);
  61.     /* redraw the screen so topline will be at top
  62.      * of the screen after command() does a CR/LF.
  63.      */
  64.     topline=max(1,bufln()-SCRNL2);
  65.     bufout(topline,2,SCRNL2);
  66.     bufgo(topline);
  67. }
  68.  
  69. /* global change command */
  70.  
  71. change(args) char *args;
  72. {
  73. char oldline [MAXLEN1];        /* reserve space for EOS */
  74. char newline [MAXLEN1];
  75. char oldpat [MAXLEN1];
  76. char newpat [MAXLEN1];
  77. int from, to, col, n, k;
  78.     if (get2args(args,ffrom,fto) == ERR) {
  79.         return;
  80.     }
  81.     /* get search and change masks into oldpat, newpat */
  82.     fmtsout("search mask ?  ",0);
  83.     getcmnd(oldpat,15);
  84.     fmtcrlf();
  85.     if (oldpat [0] == EOS) {
  86.         return;
  87.     }
  88.     pmtline();
  89.     fmtsout("change mask ?  ",0);
  90.     getcmnd(newpat,15);
  91.     fmtcrlf();
  92.     /* make substitution for lines between from, to */
  93.     while (from <= to) {
  94.         if (chkkey() == YES) {
  95.             break;
  96.         }
  97.         if (bufgo(from++) == ERR) {
  98.             break;
  99.         }
  100.         if (bufatbot() == YES) {
  101.             break;
  102.         }
  103.         n=bufgetln(oldline,MAXLEN);
  104.         n=min(n,MAXLEN);
  105.         oldline [n]=EOS;
  106.         /* '^' anchors search */
  107.         if (oldpat [0] == '^') {
  108.             if (amatch(oldline,oldpat+1,0) == YES) {
  109.                 k=replace(oldline,newline,
  110.                     oldpat+1,newpat,0);
  111.                 if (k == ERR) {
  112.                     return;
  113.                 }
  114.                 fmtcrlf();
  115.                 putdec(bufln(),5);
  116.                 fmtsout(newline,5);
  117.                 outdeol();
  118.                 bufrepl(newline,k);
  119.             }
  120.             continue;
  121.         }
  122.         /* search oldline for oldpat */
  123.         col=0;
  124.         while (col < n) {
  125.             if (amatch(oldline,oldpat,col++) == YES){
  126.                 k=replace(oldline,newline,
  127.                     oldpat,newpat,col-1);
  128.                 if (k == ERR) {
  129.                     return;
  130.                 }
  131.                 fmtcrlf();
  132.                 putdec(bufln(),5);
  133.                 fmtsout(newline,5);
  134.                 outdeol();
  135.                 bufrepl(newline,k);
  136.                 break;
  137.             }
  138.         }
  139.     }
  140.     fmtcrlf();
  141. }
  142.  
  143. /* clear main buffer and file name */
  144.  
  145. clear()
  146. {
  147.     /* make sure it is ok to clear buffer */
  148.     if (chkbuf() == YES) {
  149.         filename [0]=0;
  150.         pmtfile("");
  151.         outclr();
  152.         outxy(0,SCRNL1);
  153.         bufnew();
  154.         message("buffer cleared");
  155.     }
  156. }
  157.  
  158. /* multiple line delete command */
  159.  
  160. delete(args) char *args;
  161. {
  162. int from, to;
  163.     if (get2args(args,ffrom,fto) == ERR) {
  164.         return;
  165.     }
  166.     if (from > to) {
  167.         return;
  168.     }
  169.     /* go to first line to be deleted */
  170.     if (bufgo(from) == ERR) {
  171.         return;
  172.     }
  173.     /* delete all line between from and to */
  174.     if (bufdeln(to-from+1) == ERR) {
  175.         return;
  176.     }
  177.     /* redraw the screen */
  178.     bufout(bufln(),1,SCRNL1);
  179. }
  180.  
  181. /* search all lines below the current line for a pattern
  182.  * return -1 if pattern not found.
  183.  * otherwise, return column number of start of pattern.
  184.  */
  185.  
  186. find()
  187. {
  188.     return(search1(bufln()+1,HUGE,YES));
  189. }
  190.  
  191. /* list lines to list device */
  192.  
  193. list(args) char *args;
  194. {
  195. char linebuf [MAXLEN1];
  196. int n;
  197. int from, to, line, oldline;
  198.     /* save the buffer's current line */
  199.     oldline=bufln();
  200.     /* get starting, ending lines to print */
  201.     if (get2args(args,ffrom,fto) == ERR) {
  202.         return;
  203.     }
  204.     /* print lines one at a time to list device */
  205.     line=from;
  206.     while (line <= to) {
  207.         /* make sure prompt goes to console */
  208.         fmtassn(NO);
  209.         /* check for interrupt */
  210.         if (chkkey() == YES) {
  211.             break;
  212.         }
  213.         /* print line to list device */
  214.         fmtassn(YES);
  215.         if (bufgo(line++) != OK) {
  216.             break;
  217.         }
  218.         if (bufatbot()) {
  219.             break;
  220.         }
  221.         n=bufgetln(linebuf,MAXLEN1);
  222.         n=min(n,MAXLEN);
  223.         linebuf [n]=CR;
  224.         fmtsout(linebuf,0);
  225.         fmtcrlf();
  226.     }
  227.     /* redirect output to console */
  228.     fmtassn(NO);
  229.     /* restore cursor */
  230.     bufgo(oldline);
  231. }
  232.  
  233. /* load file into buffer */
  234.  
  235. load (args) char *args;
  236. {
  237. char buffer [MAXLEN];    /* disk line buffer */
  238. char locfn  [SYSFNMAX];  /* file name until we check it */
  239. int n;
  240. int file;
  241. int topline;
  242.     /* get filename following command */
  243.     if (name1(args,locfn) == ERR) {
  244.         return;
  245.     }
  246.     if (locfn [0] == EOS) {
  247.         message("no file argument");
  248.         return;
  249.     }
  250.     /* give user a chance to save the buffer */
  251.     if (chkbuf() == NO) {
  252.         return;
  253.     }
  254.     /* open the new file */
  255.     if ((file=sysopen(locfn,"r")) == ERR) {
  256.         message("file not found");
  257.         return;
  258.     }
  259.     /* update file name */
  260.     syscopfn(locfn, filename);
  261.     pmtfile(filename);
  262.     /* clear the buffer */
  263.     bufnew();
  264.     /* read the file into the buffer */
  265.     while ((n=readline(file,buffer,MAXLEN)) >= 0) {
  266.         if (n > MAXLEN) {
  267.             message("line truncated");
  268.             n=MAXLEN;
  269.         }
  270.         if (bufins(buffer,n) == ERR) {
  271.             break;
  272.         }
  273.         if (bufdn() == ERR) {
  274.             break;
  275.         }
  276.     }
  277.     /* close the file */
  278.     sysclose(file);
  279.     /* indicate that the buffer is fresh */
  280.     bufsaved();
  281.     /* set current line to line 1 */
  282.     bufgo(1);
  283.     /* redraw the screen so that topline will be
  284.      * on line 1 after command() does a CR/LF.
  285.      */
  286.     topline=max(1,bufln()-SCRNL2);
  287.     bufout(topline,2,SCRNL2);
  288.     bufgo(topline);
  289. }
  290.  
  291. /* change current file name */
  292.  
  293. name(args) char *args;
  294. {
  295.     name1(args,filename);
  296.     pmtfile(filename);
  297. }
  298.  
  299. /* check syntax of args.
  300.  * copy to filename.
  301.  * return OK if the name is valid.
  302.  */
  303.  
  304. name1(args,filename) char *args, *filename;
  305. {
  306.     /* skip command */
  307.     args=skiparg(args);
  308.     args=skipbl(args);
  309.     /* check file name syntax */
  310.     if (syschkfn(args) == ERR) {
  311.         return(ERR);
  312.     }
  313.     /* copy filename */
  314.     syscopfn(args,filename);
  315.     return(OK);
  316. }
  317.  
  318. /* save the buffer in an already existing file */
  319.  
  320. resave()
  321. {
  322. char linebuf [MAXLEN];
  323. int file, n, oldline;
  324.     /* make sure file has a name */
  325.     if (filename [0] == EOS) {
  326.         message("file not named");
  327.         return;
  328.     }
  329.     /* the file must exist for resave */
  330.     if ((file=sysopen(filename,"r")) == ERR) {
  331.         message("file not found");
  332.         return;
  333.     }
  334.     if (sysclose(file) == ERR) {
  335.         return;
  336.     }
  337.     /* open the file for writing */
  338.     if ((file=sysopen(filename,"w")) == ERR) {
  339.         return;
  340.     }
  341.     /* save the current position of file */
  342.     oldline=bufln();
  343.     /* write out the whole file */
  344.     if (bufgo(1) == ERR) {
  345.         sysclose(file);
  346.         return;
  347.     }
  348.     while (bufatbot() == NO) {
  349.         n=bufgetln(linebuf,MAXLEN);
  350.         n=min(n,MAXLEN);
  351.         if (pushline(file,linebuf,n) == ERR) {
  352.             break;
  353.         }
  354.         if (bufdn() == ERR) {
  355.             break;
  356.         }
  357.     }
  358.     /* indicate if all buffer was saved */
  359.     if (bufatbot()){
  360.         bufsaved();
  361.     }
  362.     /* close file and restore line number */
  363.     sysclose(file);
  364.     bufgo(oldline);
  365. }
  366.  
  367. /* save the buffer in a new file */
  368.  
  369. save()
  370. {
  371. char linebuf [MAXLEN];
  372. int file, n, oldline;
  373.     /* make sure the file is named */
  374.     if (filename [0] == EOS) {
  375.         message("file not named");
  376.         return;
  377.     }
  378.     /* file must NOT exist for save */
  379.     if ((file=sysopen(filename,"r")) != ERR) {
  380.         sysclose(file);
  381.         message("file exists");
  382.         return;
  383.     }
  384.     /* open file for writing */
  385.     if ((file=sysopen(filename,"w")) == ERR) {
  386.         return;
  387.     }
  388.     /* remember current line */
  389.     oldline=bufln();
  390.     /* write entire buffer to file */
  391.     if (bufgo(1) == ERR) {
  392.         sysclose(file);
  393.         return;
  394.     }
  395.     while (bufatbot() == NO) {
  396.         n=bufgetln(linebuf,MAXLEN);
  397.         n=min(n,MAXLEN);
  398.         if (pushline(file,linebuf,n) == ERR) {
  399.             break;
  400.         }
  401.         if (bufdn() == ERR) {
  402.             break;
  403.         }
  404.     }
  405.     /* indicate buffer saved if good write */
  406.     if (bufatbot()) {
  407.         bufsaved();
  408.     }
  409.     /* restore line and close file */
  410.     bufgo(oldline);
  411.     sysclose(file);
  412. }
  413.  
  414. /* global search command */
  415.  
  416. search(args) char *args;
  417. {
  418. int from, to;
  419.  
  420.     if (get2args(args,ffrom,fto) == ERR) {
  421.         return;
  422.     }
  423.     search1(from, to, NO);
  424. }
  425.  
  426. /* search lines for a pattern.
  427.  * if flag  ==  YES: stop at the first match.
  428.  *                 return -1 if no match.
  429.  *                 otherwise return column number of match.
  430.  * if flag  ==  NO:  print all matches found.
  431.  */
  432.  
  433. search1(from, to, flag) int from, to, flag;
  434. {
  435. char pat   [MAXLEN1];        /* reserve space for EOS */
  436. char line  [MAXLEN1];
  437. int col, n;
  438.     /* get search mask into pat */
  439.     fmtsout("search mask ?  ",0);
  440.     getcmnd(pat,15);
  441.     fmtcrlf();
  442.     if (pat [0] == EOS) {
  443.         return;
  444.     }
  445.     /* search all lines between from and to for pat */
  446.     while (from <= to) {
  447.         if (chkkey() == YES) {
  448.             break;
  449.         }
  450.         if (bufgo(from++) == ERR) {
  451.             break;
  452.         }
  453.         if (bufatbot() == YES) {
  454.             break;
  455.         }
  456.         n=bufgetln(line,MAXLEN);
  457.         n=min(n,MAXLEN);
  458.         line [n]=EOS;
  459.         /* ^ anchors search */
  460.         if (pat [0] == '^') {
  461.             if (amatch(line,pat+1,0) == YES) {
  462.                 if (flag == NO) {
  463.                     fmtcrlf();
  464.                     putdec(bufln(),5);
  465.                     fmtsout(line,5);
  466.                     outdeol();
  467.                 }
  468.                 else {
  469.                     return(0);
  470.                 }
  471.             }
  472.             continue;
  473.         }
  474.         /* search whole line for match */
  475.         col=0;
  476.         while (col < n) {
  477.             if (amatch(line,pat,col++) == YES) {
  478.                 if (flag == NO) {
  479.                     fmtcrlf();
  480.                     putdec(bufln(),5);
  481.                     fmtsout(line,5);
  482.                     outdeol();
  483.                     break;
  484.                 }
  485.                 else {
  486.                     return(col-1);
  487.                 }
  488.             }
  489.         }
  490.     }
  491.     /* all searching is finished */
  492.     if (flag == YES) {
  493.         return(-1);
  494.     }
  495.     else {
  496.         fmtcrlf();
  497.     }
  498. }
  499.  
  500. /* set tab stops for fmt routines */
  501.  
  502. tabs(args) char *args;
  503. {
  504. int n, junk;
  505.     if (get2args(args,fn,fjunk) == ERR) {
  506.         return;
  507.     }
  508.     fmtset(n);
  509. }
  510.  
  511. /* return YES if buffer may be drastically changed */
  512.  
  513. chkbuf()
  514. {
  515.     if (bufchng() == NO) {
  516.         /* buffer not changed. no problem */
  517.         return(YES);
  518.     }
  519.     fmtsout("buffer not saved. proceed ?  ",0);
  520.     pmtline();
  521.     if (tolower(syscout(syscin())) != 'y') {
  522.         fmtcrlf();
  523.         message("cancelled");
  524.         return(NO);
  525.     }
  526.     else {
  527.         fmtcrlf();
  528.         return(YES);
  529.     }
  530. }
  531.  
  532. /* print message from a command */
  533.  
  534. message(s) char *s;
  535. {
  536.     fmtsout(s,0);
  537.     fmtcrlf();
  538. }
  539.  
  540. /* get two arguments the argument line args.
  541.  * no arguments imply 1 HUGE.
  542.  * one argument implies both args the same.
  543.  */
  544.  
  545. get2args(args,val1,val2) char *args; int *val1, *val2;
  546. {
  547.     /* skip over the command */
  548.     args=skiparg(args);
  549.     args=skipbl(args);
  550.     if (*args == EOS) {
  551.         *val1=1;
  552.         *val2=HUGE;
  553.         return(OK);
  554.     }
  555.     /* check first argument */
  556.     if (number(args,val1) == NO) {
  557.         message("bad argument");
  558.         return(ERR);
  559.     }
  560.     /* skip over first argument */
  561.     args=skiparg(args);
  562.     args=skipbl(args);
  563.     /* 1 arg: arg 2 is HUGE */
  564.     if (*args == EOS) {
  565.         *val2=HUGE;
  566.         return(OK);
  567.     }
  568.     /* check second argument */
  569.     if (number(args,val2) == NO) {
  570.         message("bad argument");
  571.         return(ERR);
  572.     }
  573.     else {
  574.         return(OK);
  575.     }
  576. }
  577.  
  578. /* skip over all except EOS, and blanks */
  579.  
  580. skiparg(args) char *args;
  581. {
  582.     while (*args != EOS ff *args!=' ') {
  583.         args++;
  584.     }
  585.     return(args);
  586. }
  587.  
  588. /* skip over all blanks */
  589.  
  590. skipbl(args) char *args;
  591. {
  592.     while (*args == ' ') {
  593.         args++;
  594.     }
  595.     return(args);
  596. }
  597.  
  598. /* return YES if the user has pressed any key.
  599.  * blanks cause a transparent pause.
  600.  */
  601. chkkey()
  602. {
  603. int c;
  604.     c=syscstat();
  605.     if (c == 0) {
  606.         /* no character at keyboard */
  607.         return(NO);
  608.     }
  609.     else if (c == ' ') {
  610.         /* pause.  another blank ends pause */
  611.         pmtline();
  612.         if (syscin() == ' ') {
  613.             return(NO);
  614.         }
  615.     }
  616.     /* we got a nonblank character */
  617.     return(YES);
  618. }
  619.  
  620. /* anchored search for pattern in text line at column col.
  621.  * return YES if the pattern starts at col.
  622.  */
  623.  
  624. amatch(line,pat,col) char *line, *pat; int col;
  625. {
  626. int k;
  627.     k=0;
  628.     while (pat [k] != EOS) {
  629.         if (pat [k] == line[col]) {
  630.             k++;
  631.             col++;
  632.         }
  633.         else if (pat [k] == '?' ff line[col] != EOS) {
  634.             /* question mark matches any char */
  635.             k++;
  636.             col++;
  637.         }
  638.         else {
  639.             return(NO);
  640.         }
  641.     }
  642.     /* the entire pattern matches */
  643.     return(YES);
  644. }
  645.  
  646. /* replace oldpat in oldline by newpat starting at col.
  647.  * put result in newline.
  648.  * return number of characters in newline.
  649.  */
  650.  
  651. replace(oldline,newline,oldpat,newpat,col)
  652. char *oldline, *newline, *oldpat, *newpat; int col;
  653. {
  654. int k;
  655. char *tail, *pat;
  656.     /* copy oldline preceding col to newline */
  657.     k=0;
  658.     while (k < col) {
  659.         newline [k++]= *oldline++;
  660.     }
  661.     /* remember where end of oldpat in oldline is */
  662.     tail=oldline;
  663.     pat=oldpat;
  664.     while (*pat++ != EOS) {
  665.         tail++;
  666.     }
  667.     /* copy newpat to newline.
  668.      * use oldline and oldpat to resolve question marks
  669.      * in newpat.
  670.      */
  671.     while (*newpat != EOS) {
  672.         if (k > MAXLEN-1) {
  673.             message("new line too long");
  674.             return(ERR);
  675.         }
  676.         if (*newpat != '?') {
  677.             /* copy newpat to newline */
  678.             newline [k++]= *newpat++;
  679.             continue;
  680.         }
  681.         /* scan for '?' in oldpat */
  682.         while (*oldpat != '?') {
  683.             if (*oldpat == EOS) {
  684.                 message(
  685.                 "too many ?'s in change mask"
  686.                 );
  687.                 return(ERR);
  688.             }
  689.             oldpat++;
  690.             oldline++;
  691.         }
  692.         /* copy char from oldline to newline */
  693.         newline [k++]= *oldline++;
  694.         oldpat++;
  695.         newpat++;
  696.     }
  697.     /* copy oldline after oldpat to newline */
  698.     while (*tail != EOS) {
  699.         if (k >= MAXLEN-1) {
  700.             message("new line too long");
  701.             return(ERR);
  702.         }
  703.         newline [k++]= *tail++;
  704.     }
  705.     newline [k]=EOS;
  706.     return(k);
  707. }
  708.  
  709.