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 / ED10.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  8KB  |  457 lines

  1. /* Screen editor:  buffer module
  2.  *                 C/80 version
  3.  *
  4.  * Source:  ed10.c
  5.  * Version: May 15, 1981.
  6.  */
  7.  
  8. /* define globals */
  9.  
  10. #include ed1.h
  11.  
  12. /* globals used by this module -----
  13.  
  14. int bufcflag;        main buffer changed flag
  15. char *bufp;        start of current line
  16. char *bufpmax;        end of last line
  17. char *buffer;        start of buffer
  18. char *bufend;        last byte of buffer
  19. int bufline;        current line number
  20. int bufmaxln;        number of lines in buffer
  21.  
  22. ----- */
  23.  
  24. /* This code is built around several invariant
  25.  * assumptions:
  26.  * First, the last line is always completely empty.
  27.  * When bufp points to the last line there is NO
  28.  * CR following it.
  29.  * Second, bufp points to the last line if and only if
  30.  * bufline==bufmaxln+1.
  31.  * Third, bufline is always greater than zero.
  32.  * Line zero exists only to make scanning for the
  33.  * start of line one easier.
  34.  */
  35.  
  36.  
  37. /* Clear the main buffer */
  38.  
  39. bufnew()
  40. {
  41. int k;
  42.     /* do initial allocation of memory */
  43.     if (buffer==0) {
  44.         k=60;
  45.         while ((buffer=alloc(k*1024))==-1)
  46.             k--;
  47.         bufend=buffer+k*1024;
  48.     }
  49.     /* point past line 0 */
  50.     bufp=bufpmax=buffer+1;
  51.     /* at line one. no lines in buffer */
  52.     bufline=1;
  53.     bufmaxln=0;
  54.     /* line zero is always a null line */
  55.     buffer[0]=CR;
  56.     /* indicate no need to save file yet */
  57.     bufcflag=NO;
  58. }
  59.  
  60. /* return current line number */
  61.  
  62. bufln()
  63. {
  64.     return(bufline);
  65. }
  66.  
  67. /* return YES if the buffer (i.e., file) has been
  68.  * changed since the last time the file was saved.
  69.  */
  70.  
  71. bufchng()
  72. {
  73.     return(bufcflag);
  74. }
  75.  
  76. /* the file has been saved.  clear bufcflag. */
  77.  
  78. bufsaved()
  79. {
  80.     bufcflag=NO;
  81. }
  82.  
  83. /* return number of bytes left in the buffer */
  84.  
  85. buffree()
  86. {
  87.     return(bufend-bufp);
  88. }
  89.  
  90. /* Position buffer pointers to start of indicated line */
  91.  
  92. bufgo(line) int line;
  93. {
  94.     /* put request into range. prevent extension */
  95.     line=min(bufmaxln+1,line);
  96.     line=max(1,line);
  97.     /* already at proper line? return. */
  98.     if (line==bufline) {
  99.         return(OK);
  100.     }
  101.     /* move through buffer one line at a time */
  102.     while (line<bufline) {
  103.         if (bufup()==ERR) {
  104.             return(ERR);
  105.         }
  106.     }
  107.     while (line>bufline) {
  108.         if (bufdn()==ERR) {
  109.             return(ERR);
  110.         }
  111.     }
  112.     /* we have reached the line we wanted */
  113.     return(OK);
  114. }
  115.  
  116. /* move one line closer to front of buffer, i.e.,
  117.  * set buffer pointers to start of previous line.
  118.  */
  119.  
  120. bufup()
  121. {
  122. char *oldbufp;
  123.     oldbufp=bufp;
  124.     /* can't move past line 1 */
  125.     if (bufattop()) {
  126.         return(OK);
  127.     }
  128.     /* move past CR of previous line */
  129.     if (*--bufp!=CR) {
  130.         syserr("bufup: missing CR");
  131.         bufp=oldbufp;
  132.         return(ERR);
  133.     }
  134.     /* move to start of previous line */
  135.     while (*--bufp!=CR) {
  136.         ;
  137.     }
  138.     bufp++;
  139.     /* make sure we haven't gone too far */
  140.     if (bufp<(buffer+1)) {
  141.         syserr("bufup: bufp underflow");
  142.         bufp=oldbufp;
  143.         return(ERR);
  144.     }
  145.     /* success!  we ARE at previous line */
  146.     bufline--;
  147.     return(OK);
  148. }
  149.  
  150. /* Move one line closer to end of buffer, i.e.,
  151.  * set buffer pointers to start of next line.
  152.  */
  153.  
  154. bufdn()
  155. {
  156. char *oldbufp;
  157.     oldbufp=bufp;
  158.     /* do nothing silly if at end of buffer */
  159.     if (bufatbot()) {
  160.         return(OK);
  161.     }
  162.     /* scan past current line and CR */
  163.     while (*bufp++!=CR) {
  164.         ;
  165.     }
  166.     /* make sure we haven't gone too far */
  167.     if (bufp>bufpmax) {
  168.         syserr("bufdn: bufp overflow");
  169.         bufp=oldbufp;
  170.         return(ERR);
  171.     }
  172.     /* success! we are at next line */
  173.     bufline++;
  174.     return(OK);
  175. }
  176.  
  177. /* Insert a line before the current line.
  178.  * p points to a line of length n to be inserted.
  179.  * Note: n does not include trailing CR.
  180.  */
  181.  
  182. bufins(p,n) char *p; int n;
  183. {
  184. int k;
  185.     /* make room in the buffer for the line */
  186.     if (bufext(n+1)==ERR) {
  187.         return(ERR);
  188.     }
  189.     /* put the line and CR into the buffer */
  190.     k=0;
  191.     while (k<n) {
  192.         *(bufp+k)= *(p+k);
  193.         k++;
  194.     }
  195.     *(bufp+k)=CR;
  196.     /* increase number of lines in buffer */
  197.     bufmaxln++;
  198.     /* special case: inserting a null line at
  199.      * end of file is not a significant change.
  200.      */
  201.     if ((n==0)ff(bufnrbot())) {
  202.         ;
  203.     }
  204.     else {
  205.         bufcflag=YES;
  206.     }
  207.     return(OK);
  208. }
  209.  
  210. /* delete the current line */
  211.  
  212. bufdel()
  213. {
  214.     return(bufdeln(1));
  215. }
  216.  
  217. /* delete n lines, starting with the current line */
  218.  
  219. bufdeln(n) int n;
  220. {
  221. int oldline;
  222. int k;
  223. char *oldbufp;
  224.     /* remember current buffer parameters */
  225.     oldline=bufline;
  226.     oldbufp=bufp;
  227.     /* scan for first line after deleted lines */
  228.     k=0;
  229.     while ((n--)>0) {
  230.         if (bufatbot()) {
  231.             break;
  232.         }
  233.         if (bufdn()==ERR) {
  234.             bufline=oldline;
  235.             oldbufp=bufp;
  236.             return(ERR);
  237.         }
  238.         k++;
  239.     }
  240.     /* compress buffer.  update pointers */
  241.     bufmovup(bufp,bufpmax-1,bufp-oldbufp);
  242.     bufpmax=bufpmax-(bufp-oldbufp);
  243.     bufp=oldbufp;
  244.     bufline=oldline;
  245.     bufmaxln=bufmaxln-k;
  246.     bufcflag=YES;
  247.     return(OK);
  248. }
  249.  
  250. /* replace current line with the line that
  251.  * p points to.  The new line is of length n.
  252.  */
  253.  
  254. bufrepl(p,n) char *p; int n;
  255. {
  256. int oldlen, k;
  257. char *nextp;
  258.     /* do not replace null line.  just insert */
  259.     if (bufatbot()) {
  260.         return(bufins(p,n));
  261.     }
  262.     /* point nextp at start of next line */
  263.     if (bufdn()==ERR) {
  264.         return(ERR);
  265.     }
  266.     nextp=bufp;
  267.     if (bufup()==ERR) {
  268.         return(ERR);
  269.     }
  270.     /* allow for CR at end */
  271.     n=n+1;
  272.     /* see how to move buffer below us;
  273.      * up, down, or not at all.
  274.      */
  275.     oldlen=nextp-bufp;
  276.     if (oldlen<n) {
  277.         /* move buffer down */
  278.         if (bufext(n-oldlen)==ERR) {
  279.             return(ERR);
  280.         }
  281.         bufpmax=bufpmax+n-oldlen;
  282.     }
  283.     else if (oldlen>n) {
  284.         /* move buffer up */
  285.         bufmovup(nextp,bufpmax-1,oldlen-n);
  286.         bufpmax=bufpmax-(oldlen-n);
  287.     }
  288.     /* put new line in the hole we just made */
  289.     k=0;
  290.     while (k<(n-1)) {
  291.         bufp[k]=p[k];
  292.         k++;
  293.     }
  294.     bufp[k]=CR;
  295.     bufcflag=YES;
  296.     return(OK);
  297. }
  298.  
  299. /* copy current line into buffer that p points to.
  300.  * the maximum size of that buffer is n.
  301.  * return k=length of line in the main buffer.
  302.  * if k>n then truncate n-k characters and only
  303.  * return n characters in the caller's buffer.
  304.  */
  305.  
  306. bufgetln(p,n) char *p; int n;
  307. {
  308. int k;
  309.     /* last line is always null */
  310.     if (bufatbot()) {
  311.         return(0);
  312.     }
  313.     /* copy line as long as it not too long */
  314.     k=0;
  315.     while (k<n) {
  316.         if (*(bufp+k)==CR) {
  317.             return(k);
  318.         }
  319.         *(p+k)= *(bufp+k);
  320.         k++;
  321.     }
  322.     /* count length but move no more chars */
  323.     while (*(bufp+k)!=CR) {
  324.         k++;
  325.     }
  326.     return(k);
  327. }
  328.  
  329. /* move buffer down (towards HIGH addresses) */
  330.  
  331. bufmovdn(from,to,length) char *from, *to; int length;
  332. {
  333.     /* this code needs to be very fast.
  334.      * use an assembly language routine.
  335.      */
  336.  
  337.     sysmovdn(to-from+1,from+length,from);
  338. }
  339.  
  340. /* the call to sysmovdn() is equivalent to the following code:
  341.  
  342. int k;
  343.     k=to-from+1;
  344.     while ((k--)>0) {
  345.         *(to+length)= *to;
  346.         to--;
  347.     }
  348.  
  349.  */
  350.  
  351. /* move buffer up (towards LOW addresses) */
  352.  
  353. bufmovup(from,to,length) char *from, *to; int length;
  354. {
  355.     /* this code must be very fast.
  356.      * use an assembly language routine.
  357.      */
  358.  
  359.     sysmovup(to-from+1,from-length,from);
  360. }
  361.  
  362. /* the call to sysmovup() is equivalent to the following code:
  363.  
  364. int k;
  365.     k=to-from+1;
  366.     while ((k--)>0) {
  367.         *(from-length)= *from;
  368.         from++;
  369.     }
  370.  
  371.  */
  372.  
  373. /* return true if at bottom of buffer.
  374.  * NOTE 1: the last line of the buffer is always null.
  375.  * NOTE 2: the last line number is always bufmaxln+1.
  376.  */
  377.  
  378. bufatbot()
  379. {
  380.     return(bufline>bufmaxln);
  381. }
  382.  
  383. /* return true if at bottom or at the last
  384.  * real line before the bottom.
  385.  */
  386.  
  387. bufnrbot()
  388. {
  389.     return(bufline>=bufmaxln);
  390. }
  391.  
  392. /* return true if at top of buffer */
  393.  
  394. bufattop()
  395. {
  396.     return(bufline==1);
  397. }
  398.  
  399. /* put nlines lines from buffer starting with
  400.  * line topline at position topy of the screen.
  401.  */
  402.  
  403. bufout(topline,topy,nlines) int topline, topy, nlines;
  404. {
  405. int l,p;
  406.     /* remember buffer's state */
  407.     l=bufline;
  408.     p=bufp;
  409.     /* write out one line at a time */
  410.     while ((nlines--)>0) {
  411.         outxy(0,topy++);
  412.         bufoutln(topline++);
  413.     }
  414.     /* restore buffer's state */
  415.     bufline=l;
  416.     bufp=p;
  417. }
  418.  
  419. /* print line of main buffer on screen */
  420.  
  421. bufoutln(line) int line;
  422. {
  423.     /* error message does NOT go on prompt line */
  424.     if (bufgo(line)==ERR) {
  425.         fmtsout("disk error: line deleted",0);
  426.         outdeol();
  427.         return;
  428.     }
  429.     /* blank out lines below last line of buffer */
  430.     if (bufatbot()) {
  431.         outdeol();
  432.     }
  433.     /* write one formatted line out */
  434.     else {
  435.         fmtsout(bufp,0);
  436.         outdeol();
  437.     }
  438. }
  439.  
  440. /* simple memory version of bufext.
  441.  * create a hole in buffer at current line.
  442.  * length is the size of the hole.
  443.  */
  444.  
  445. bufext(length) int length;
  446. {
  447.     /* make sure there is room for more */
  448.     if ((bufpmax+length)>=bufend) {
  449.         error("main buffer is full");
  450.         return(ERR);
  451.     }
  452.     /* move lines below current line down */
  453.     bufmovdn(bufp,bufpmax-1,length);
  454.     bufpmax=bufpmax+length;
  455.     return(OK);
  456. }
  457.