home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 21 / emacsrc / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-05-14  |  13.0 KB  |  400 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8.  
  9. #include        "ed.h"
  10.  
  11. /*
  12.  * Get next regular buffer; assume bp != NULL
  13.  * The next buffer got can be the [List].
  14.  */
  15. BUFFER *
  16. nextbuffer()
  17. {
  18.   register  BUFFER *bp;
  19.   bp = curbp->b_bufp;
  20.   if (bp == blistp) bp = bp->b_bufp;
  21.   if (bp == NULL) bp = bheadp;
  22.   return(bp);
  23. }
  24.  
  25. /*
  26.  * Attach a buffer to a window. The
  27.  * values of dot and mark come from the buffer
  28.  * if the use count is 0. Otherwise, they come
  29.  * from some other window.
  30.  */
  31. usebuffer(f, n)
  32. {
  33.         register BUFFER *bp;
  34.         register WINDOW *wp;
  35.         register int    s;
  36.         char            bufn[NBUFN];
  37.  
  38.         s=mlreply("Use [next] buffer: ", bufn, NBUFN);
  39.     if (s == ABORT)      return(ABORT);
  40.     if (s == TRUE) {
  41.       if ((bp = bfind(bufn, TRUE, 0)) == NULL) return(FALSE);
  42.     }
  43.     else bp = nextbuffer();
  44.     return(switchbuffer(bp));
  45. }
  46.  
  47. switchbuffer(bp)
  48. register BUFFER *bp;
  49. {
  50.         register WINDOW *wp;
  51.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  52.                 curbp->b_dotp  = curwp->w_dotp;
  53.                 curbp->b_doto  = curwp->w_doto;
  54.                 curbp->b_markp = curwp->w_markp;
  55.                 curbp->b_marko = curwp->w_marko;
  56.         }
  57.         curbp = bp;                             /* Switch.              */
  58.         curwp->w_bufp  = bp;
  59.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  60.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  61.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  62.                 curwp->w_dotp  = bp->b_dotp;
  63.                 curwp->w_doto  = bp->b_doto;
  64.                 curwp->w_markp = bp->b_markp;
  65.                 curwp->w_marko = bp->b_marko;
  66.                 return (TRUE);
  67.         }
  68.         wp = wheadp;                            /* Look for old.        */
  69.         while (wp != NULL) {
  70.                 if (wp!=curwp && wp->w_bufp==bp) {
  71.                         curwp->w_dotp  = wp->w_dotp;
  72.                         curwp->w_doto  = wp->w_doto;
  73.                         curwp->w_markp = wp->w_markp;
  74.                         curwp->w_marko = wp->w_marko;
  75.                         break;
  76.                 }
  77.                 wp = wp->w_wndp;
  78.         }
  79.         return (TRUE);
  80. }
  81.  
  82. /*
  83.  * Dispose of a buffer, by name.
  84.  * Ask for the name. Look it up (don't get too
  85.  * upset if it isn't there at all!). Get quite upset
  86.  * if the buffer is being displayed. Clear the buffer (ask
  87.  * if the buffer has been changed). Then free the header
  88.  * line and the buffer header. Bound to "C-X K".
  89.  * Default buffer to kill added by -pm
  90.  */
  91. killbuffer(f, n)
  92. {
  93.         register BUFFER *bp;
  94.         register BUFFER *bp1;
  95.         register BUFFER *bp2;
  96.         register int    s;
  97.         char            bufn[NBUFN];
  98.  
  99.         s=mlreply("Kill [current] buffer: ", bufn, NBUFN);
  100.     if (s == ABORT)      return(ABORT);
  101.     bp = (s == FALSE? curbp : bfind(bufn, FALSE, 0));
  102.     if (bp == NULL || bp == blistp) return (TRUE);
  103.     if (bp->b_nwnd > 1) {
  104.       mlwrite("Buffer is being multiply displayed"); 
  105.       return (FALSE);
  106.     }
  107.         if (bp->b_nwnd == 1) {
  108.       bp1 = nextbuffer();
  109.       if (bp1 == bp) bp1 = blistp;
  110.       switchbuffer(bp1);
  111.         }
  112.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  113.                 return (s);
  114.         free((char *) bp->b_linep);             /* Release header line. */
  115.         bp1 = NULL;                             /* Find the header.     */
  116.         bp2 = bheadp;
  117.         while (bp2 != bp) {
  118.                 bp1 = bp2;
  119.                 bp2 = bp2->b_bufp;
  120.         }
  121.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  122.         if (bp1 == NULL)                        /* Unlink it.           */
  123.                 bheadp = bp2;
  124.         else
  125.                 bp1->b_bufp = bp2;
  126.         free((char *) bp);                      /* Release buffer block */
  127.     mlerase();        /* pm */
  128.         return (TRUE);
  129. }
  130.  
  131. /*
  132.  * List all of the active
  133.  * buffers. First update the special
  134.  * buffer that holds the list. Next make
  135.  * sure at least 1 window is displaying the
  136.  * buffer list, splitting the screen if this
  137.  * is what it takes. Lastly, repaint all of
  138.  * the windows that are displaying the
  139.  * list. Bound to "C-X C-B".
  140.  */
  141. listbuffers(f, n)
  142. {
  143.         register WINDOW *wp;
  144.         register BUFFER *bp;
  145.         register int    s;
  146.  
  147.         if ((s=makelist()) != TRUE)
  148.                 return (s);
  149.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  150.                 if ((wp=wpopup()) == NULL)
  151.                         return (FALSE);
  152.                 bp = wp->w_bufp;
  153.                 if (--bp->b_nwnd == 0) {
  154.                         bp->b_dotp  = wp->w_dotp;
  155.                         bp->b_doto  = wp->w_doto;
  156.                         bp->b_markp = wp->w_markp;
  157.                         bp->b_marko = wp->w_marko;
  158.                 }
  159.                 wp->w_bufp  = blistp;
  160.                 ++blistp->b_nwnd;
  161.         }
  162.         wp = wheadp;
  163.         while (wp != NULL) {
  164.                 if (wp->w_bufp == blistp) {
  165.                         wp->w_linep = lforw(blistp->b_linep);
  166.                         wp->w_dotp  = lforw(blistp->b_linep);
  167.                         wp->w_doto  = 0;
  168.                         wp->w_markp = NULL;
  169.                         wp->w_marko = 0;
  170.                         wp->w_flag |= WFMODE|WFHARD;
  171.                 }
  172.                 wp = wp->w_wndp;
  173.         }
  174.         return (TRUE);
  175. }
  176.  
  177. /*
  178.  * This routine rebuilds the
  179.  * text in the special secret buffer
  180.  * that holds the buffer list. It is called
  181.  * by the list buffers command. Return TRUE
  182.  * if everything works. Return FALSE if there
  183.  * is an error (if there is no memory).
  184.  */
  185. static
  186. makelist()
  187. {
  188.         register char   *cp1;
  189.         register char   *cp2;
  190.         register int    c;
  191.         register BUFFER *bp;
  192.         register LINE   *lp;
  193.         register long   nbytes;
  194.         register int    s;
  195.         register int    type;
  196.         char            b[12+1];
  197.         char            line[128];
  198.  
  199.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  200.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  201.                 return (s);
  202.         strcpy(blistp->b_fname, "");
  203.         if (addline("C         Size Buffer           File") == FALSE
  204.         ||  addline("-   ---------- ------           ----") == FALSE)
  205.                 return (FALSE);
  206.         bp = bheadp;                            /* For all buffers      */
  207.         while (bp != NULL) {
  208. /*                if ((bp->b_flag&BFTEMP) != 0) { */ /* Skip magic ones.     */
  209. /*                        bp = bp->b_bufp;*/
  210. /*                        continue;*/
  211. /*                }*/
  212.                 cp1 = &line[0];                 /* Start at left edge   */
  213.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  214.                         *cp1++ = '*';
  215.                 else
  216.                         *cp1++ = ' ';
  217.                 *cp1++ = ' ';                   /* Gap.                 */
  218.                 nbytes = 0;                     /* Count bytes in buf.  */
  219.                 lp = lforw(bp->b_linep);
  220.                 while (lp != bp->b_linep) {
  221.                         nbytes += llength(lp)+
  222. #ifdef    ST520
  223.                 2;        /* On ST, cr+lf        */
  224. #else
  225.                 1;        /* most os, just a \n    */
  226. #endif
  227.                         lp = lforw(lp);
  228.                 }
  229.                 itoa(cp1, 12, nbytes);             /* 12 digit buffer size. */
  230.         cp1 += 12;
  231.                 *cp1++ = ' ';                   /* Gap.                 */
  232.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  233.                 while (*cp1++ = *cp2++);
  234.         cp1 --;
  235.                 cp2 = &bp->b_fname[0];          /* File name            */
  236.                 if (*cp2 != 0) {
  237.                         while (cp1 < &line[1+1+12+1+NBUFN+1])
  238.                                 *cp1++ = ' ';           
  239.                         while ((c = *cp2++) != 0) {
  240.                                 if (cp1 < &line[128-1])
  241.                                         *cp1++ = c;
  242.                         }
  243.                 }
  244.                 *cp1 = 0;
  245.                 if (addline(line) == FALSE)    /* Add to the buffer.   */
  246.                         return (FALSE);
  247.                 bp = bp->b_bufp;
  248.         }
  249.         return (TRUE);                          /* All done             */
  250. }
  251.  
  252. static
  253. itoa(buf, width, num)
  254. register char   buf[];
  255. register int    width;
  256. register long   num;
  257. {
  258.         while (num >= 10) {                     /* Conditional digits.  */
  259.                 buf[--width] = (num%10) + '0';
  260.                 num /= 10;
  261.         }
  262.         buf[--width] = num + '0';               /* Always 1 digit.      */
  263.         while (width != 0)                      /* Pad with blanks.     */
  264.                 buf[--width] = ' ';
  265. }
  266.  
  267. /*
  268.  * The argument "text" points to
  269.  * a string. Append this line to the
  270.  * buffer list buffer. Handcraft the EOL
  271.  * on the end. Return TRUE if it worked and
  272.  * FALSE if you ran out of room.
  273.  */
  274. static
  275. addline(text)
  276. char    *text;
  277. {
  278.         register LINE   *lp;
  279.         register int    i;
  280.         register int    ntext;
  281.  
  282.         ntext = strlen(text);
  283.         if ((lp=lalloc(ntext)) == NULL)
  284.                 return (FALSE);
  285.         for (i=0; i<ntext; ++i)
  286.                 lputc(lp, i, text[i]);
  287.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  288.         lp->l_bp = blistp->b_linep->l_bp;
  289.         blistp->b_linep->l_bp = lp;
  290.         lp->l_fp = blistp->b_linep;
  291.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  292.                 blistp->b_dotp = lp;            /* move it to new line  */
  293.         return (TRUE);
  294. }
  295.  
  296. /*
  297.  * Look through the list of
  298.  * buffers. Return TRUE if there
  299.  * are any changed buffers. Buffers
  300.  * that hold magic internal stuff are
  301.  * not considered; who cares if the
  302.  * list of buffer names is hacked.
  303.  * Return FALSE if no buffers
  304.  * have been changed.
  305.  */
  306. anycb()
  307. {
  308.         register BUFFER *bp;
  309.  
  310.         bp = bheadp;
  311.         while (bp != NULL) {
  312.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  313.                         return (TRUE);
  314.                 bp = bp->b_bufp;
  315.         }
  316.         return (FALSE);
  317. }
  318.  
  319. /*
  320.  * Find a buffer, by name. Return a pointer
  321.  * to the BUFFER structure associated with it. If
  322.  * the named buffer is found, but is a TEMP buffer (like
  323.  * the buffer list) conplain. If the buffer is not found
  324.  * and the "cflag" is TRUE, create it. The "bflag" is
  325.  * the settings for the flags in in buffer.
  326.  */
  327. BUFFER  *
  328. bfind(bname, cflag, bflag)
  329. register char   *bname;
  330. {
  331.         register BUFFER *bp;
  332.         register LINE   *lp;
  333.  
  334.         bp = bheadp;
  335.         while (bp != NULL) {
  336.                 if (strcmp(bname, bp->b_bname) == 0) {
  337.                         if ((bp->b_flag&BFTEMP) != 0) {
  338.                                 mlwrite("Cannot select builtin buffer");
  339.                                 return (NULL);
  340.                         }
  341.                         return (bp);
  342.                 }
  343.                 bp = bp->b_bufp;
  344.         }
  345.         if (cflag != FALSE) {
  346.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  347.                         return (NULL);
  348.                 if ((lp=lalloc(0)) == NULL) {
  349.                         free((char *) bp);
  350.                         return (NULL);
  351.                 }
  352.                 bp->b_bufp  = bheadp;
  353.                 bheadp = bp;
  354.                 bp->b_dotp  = lp;
  355.                 bp->b_doto  = 0;
  356.                 bp->b_markp = NULL;
  357.                 bp->b_marko = 0;
  358.                 bp->b_flag  = bflag;
  359.                 bp->b_nwnd  = 0;
  360.                 bp->b_linep = lp;
  361.                 strcpy(bp->b_fname, "");
  362.                 strcpy(bp->b_bname, bname);
  363.                 lp->l_fp = lp;
  364.                 lp->l_bp = lp;
  365.         }
  366.         return (bp);
  367. }
  368.  
  369. /*
  370.  * This routine blows away all of the text
  371.  * in a buffer. If the buffer is marked as changed
  372.  * then we ask if it is ok to blow it away; this is
  373.  * to save the user the grief of losing text. The
  374.  * window chain is nearly always wrong if this gets
  375.  * called; the caller must arrange for the updates
  376.  * that are required. Return TRUE if everything
  377.  * looks good.
  378.  */
  379. bclear(bp)
  380. register BUFFER *bp;
  381. {
  382.         register LINE   *lp;
  383.         register int    s;
  384.         
  385.         if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  386.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  387.         && (s=mlyesno("Discard changes")) != TRUE)
  388.                 return (s);
  389.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  390.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  391.                 lfree(lp);
  392.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  393.         bp->b_doto  = 0;
  394.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  395.         bp->b_marko = 0;
  396.         return (TRUE);
  397. }
  398.  
  399. /* -eof- */
  400.