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 / EDITOR / EDITOR.ARK / ED10.C < prev    next >
C/C++ Source or Header  |  1983-09-09  |  9KB  |  455 lines

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