home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 223 / emacssrc / buffer.c next >
Encoding:
C/C++ Source or Header  |  1988-02-17  |  13.7 KB  |  620 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. #include    <stdio.h>
  9. #include    "ed.h"
  10.  
  11. extern int update();
  12. extern int ctrlg();
  13.  
  14. /* dal: return pointer to next buffer in chain */
  15. BUFFER *nxtbuf(bp)
  16.     BUFFER *bp;
  17.     {
  18.     register BUFFER *tp = bp;
  19.  
  20.     do
  21.         {
  22.         if ((tp = tp->b_bufp) == NULL)
  23.             tp = bheadp;
  24.         }
  25.         while((tp != bp) && (tp->b_flag & BFTEMP));
  26.     return(tp);
  27.     }
  28.  
  29. /* dal: return pointer to previous buffer in chain */
  30. BUFFER *prvbuf(bp)
  31.     BUFFER *bp;
  32.     {
  33.     register BUFFER *xp, *tp = bp;
  34.  
  35.     do
  36.         {
  37.         if (tp == bheadp)
  38.             tp = NULL;
  39.         for(xp=bheadp; xp->b_bufp!=tp; xp=xp->b_bufp)
  40.             ;
  41.         tp = xp;
  42.         }
  43.         while((tp != bp) && (tp->b_flag & BFTEMP));
  44.     return(tp);
  45.     }
  46.  
  47. /*
  48.  * Attach a buffer to a window. The values of dot and
  49.  * mark come from the buffer if the use count is 0.
  50.  * Otherwise, they come from some other window.
  51.  * mb: added the prompt, oldbp stuff; allow lowercase
  52.  * only in bufnames, and put the meat in gotobuf().
  53.  * dal: added +/- for scanning through buffer names.
  54.  */
  55. usebuffer(f, n)
  56.     {
  57.     register char    *p;
  58.     register char    c;
  59.     register BUFFER    *bp, *pbp;
  60.     int    s;
  61.     char    bufn[NBUFN];
  62.  
  63.     if ((pbp = (oldbp ? oldbp : prvbuf(curbp))) == curbp)
  64.         pbp = NULL;
  65.     for(;;)
  66.         {
  67.         p = (pbp ? pbp->b_bname : NULL);
  68.         if ((s=mlgets("Use buffer", p, bufn, NBUFN, "\r+-\n")) == ABORT)
  69.             return(s);
  70.         if ((s == '+') && pbp)        /* next buffer */
  71.             pbp = nxtbuf(pbp);
  72.         else if ((s == '-') && pbp)    /* previous buffer */
  73.             pbp = prvbuf(pbp);
  74.         else if (bufn[0] == '\0')    /* default string */
  75.             {
  76.             if (pbp != NULL)
  77.                 {
  78.                 strcpy(bufn, pbp->b_bname);
  79.                 break;
  80.                 }
  81.             else
  82.                 return(ctrlg());
  83.             }
  84.         else                /* normal input string */
  85.             break;
  86.         }
  87.     if ((bp=bfind(bufn, TRUE, BFEDIT)) == NULL)
  88.         return (FALSE);
  89.     gotobuf(bp);
  90.     curwp->w_linep = bp->b_linep;        /* For macros, ignored.    */
  91.     curwp->w_flag |= WFMODE|WFFORCE|WFHARD;    /* Quite nasty.        */
  92.     return(TRUE);
  93.     }
  94.  
  95. /* dal: short-cut jump to next buffer */
  96. jumpbuffer(f, n)
  97.     {
  98.     register BUFFER *bp;
  99.  
  100.     bp = nxtbuf(curbp);            /* jump forward.    */
  101.     if (bp == curbp)            /* only one buffer?    */
  102.         return (FALSE);
  103.     gotobuf(bp);
  104.     curwp->w_linep = bp->b_linep;        /* For macros, ignored.    */
  105.     curwp->w_flag |= WFMODE|WFFORCE|WFHARD;    /* Quite nasty.        */
  106.     return (TRUE);
  107.     }
  108.  
  109. /* mb: split off usebuf() */
  110. gotobuf(bp)
  111.     BUFFER *bp;
  112.     {
  113.     WINDOW    *wp;
  114.  
  115.     if (--curbp->b_nwnd == 0)        /* Last use.        */
  116.         {
  117.         curbp->b_dotp  = curwp->w_dotp;
  118.         curbp->b_doto  = curwp->w_doto;
  119.         curbp->b_markp = curwp->w_markp;
  120.         curbp->b_marko = curwp->w_marko;
  121.         }
  122.     if (bp != curbp)            /* jls: added        */
  123.         oldbp = curbp;            /* mb: added        */
  124.     curbp = bp;                /* Switch.        */
  125.     curwp->w_bufp  = bp;
  126.     if (bp->b_nwnd++ == 0)            /* First use.        */
  127.         {
  128.         curwp->w_dotp  = bp->b_dotp;
  129.         curwp->w_doto  = bp->b_doto;
  130.         curwp->w_markp = bp->b_markp;
  131.         curwp->w_marko = bp->b_marko;
  132.         curwp->w_force = 0;    /* mb: attempt frame to middle */
  133.         return;
  134.         }
  135.     wp = wheadp;                /* Look for old.    */
  136.     while (wp != NULL)
  137.         {
  138.         if (wp!=curwp && wp->w_bufp==bp)
  139.             {
  140.             curwp->w_dotp  = wp->w_dotp;
  141.             curwp->w_doto  = wp->w_doto;
  142.             curwp->w_markp = wp->w_markp;
  143.             curwp->w_marko = wp->w_marko;
  144.             break;
  145.             }
  146.         wp = wp->w_wndp;
  147.         }
  148.     return;
  149.     }
  150.  
  151. /*
  152.  * Dispose of a buffer, by name.
  153.  * Ask for the name. Look it up (don't get too
  154.  * upset if it isn't there at all!). Get quite upset
  155.  * if the buffer is being displayed. Clear the buffer (ask
  156.  * if the buffer has been changed). Then free the header
  157.  * line and the buffer header. Bound to "C-X K".
  158.  */
  159. killbuffer(f, n)
  160.     {
  161.     register BUFFER    *bp, *pbp;
  162.     register char    *p;
  163.     register int    s;
  164.     char        prompt[NBUFN+20];
  165.     char        bufn[NBUFN];
  166.  
  167.     pbp = NULL;
  168.     for(;;)
  169.         {
  170.         p = (pbp ? pbp->b_bname : NULL);
  171.         if ((s=mlgets("Buffer to kill", p, bufn, NBUFN, "\r+-\n")) 
  172.             == ABORT)
  173.             return (s);
  174.         if (s == '+')            /* next buffer */
  175.             pbp = nxtbuf(pbp?pbp:curbp);
  176.         else if (s == '-')        /* previous buffer */
  177.             pbp = prvbuf(pbp?pbp:curbp);
  178.         else if (bufn[0] == '\0')    /* default string */
  179.             {
  180.             if (pbp != NULL)
  181.                 {
  182.                 strcpy(bufn, pbp->b_bname);
  183.                 break;
  184.                 }
  185.             else
  186.                 return (ctrlg());
  187.             }
  188.         else                /* normal input string */
  189.             break;
  190.         }
  191.     if ((bp=bfind(bufn,FALSE,0))==NULL
  192.         || bp==blistp || bp==bhelpp || bp==bdirp)
  193.         {
  194.         mlwrite("Buffer not found");
  195.         return (FALSE);
  196.         }
  197.     if (bp->b_nwnd != 0)            /* Error if on screen.    */
  198.         {
  199.         mlwrite("Buffer is being displayed");
  200.         return (FALSE);
  201.         }
  202.     if (bclear(bp) != TRUE)
  203.         return (ctrlg());
  204.     freebuf(bp);
  205.     mlwrite("[killed]");
  206.     return (TRUE);
  207.     }
  208.  
  209. freebuf(bp)            /* must bclear() the text first! */
  210.     register BUFFER *bp;
  211.     {
  212.     register BUFFER *bp2;
  213.     register BUFFER *bp1;
  214.  
  215.     free((char *) bp->b_linep);        /* Release header line.    */
  216.     bp1 = NULL;                /* Find the header.    */
  217.     bp2 = bheadp;
  218.     while (bp2 != bp)
  219.         {
  220.         bp1 = bp2;
  221.         bp2 = bp2->b_bufp;
  222.         }
  223.     bp2 = bp2->b_bufp;            /* Next one in chain.    */
  224.     if (bp1 == NULL)            /* Unlink it.        */
  225.         bheadp = bp2;
  226.     else
  227.         bp1->b_bufp = bp2;
  228.     free((char *) bp);            /* Release buffer block    */
  229.     if (oldbp == bp)
  230.         oldbp = NULL;
  231.     return;
  232.     }
  233.  
  234. /* mb: added function to toggle edit/view */
  235.  
  236. int editog(f,n)
  237.     {
  238.     register WINDOW *wp;
  239.  
  240.     if (curbp->b_flag & BFEDIT)
  241.         {
  242.         mlwrite("[view only]");
  243.         curbp->b_flag &= ~BFEDIT;
  244.         }
  245.     else
  246.         {
  247.         mlwrite("[edit]");
  248.         curbp->b_flag |= BFEDIT;
  249.         }
  250.     wp = wheadp;
  251.     while (wp != NULL)
  252.         {
  253.         if (wp->w_bufp == curbp)
  254.             wp->w_flag |= WFMODE;
  255.         wp = wp->w_wndp;
  256.         }
  257.     return (TRUE);
  258.     }
  259.  
  260. /*
  261.  * Show a temporary buffer in a pop-up window.
  262.  * First update the temporary buffer, next make
  263.  * sure at least 1 window is displaying the
  264.  * buffer, splitting the screen if this is what
  265.  * it takes. Lastly, repaint all of the windows
  266.  * that are displaying it. (by mb:)
  267.  */
  268. make_popup(buffer, prepare, data)
  269.     BUFFER    *buffer;        /* which temp buffer    */
  270.     int    (*prepare)();        /* function pointer    */
  271.     char    *data[];             /* array of strings    */
  272.     {
  273.     register WINDOW    *wp;
  274.     register BUFFER    *bp;
  275.     register int    s;
  276.  
  277.     if ((s=(*prepare)(buffer, data)) != TRUE)
  278.         return (s);
  279.  
  280.     if (buffer->b_nwnd == 0)        /* Not on screen yet.    */
  281.         {
  282.         if ((wp=wpopup()) == NULL)
  283.             return (FALSE);
  284.         bp = wp->w_bufp;
  285.         if (--bp->b_nwnd == 0)
  286.             {
  287.             bp->b_dotp  = wp->w_dotp;
  288.             bp->b_doto  = wp->w_doto;
  289.             bp->b_markp = wp->w_markp;
  290.             bp->b_marko = wp->w_marko;
  291.             }
  292.         bp = buffer;
  293.         wp->w_bufp  = bp;
  294.         ++bp->b_nwnd;
  295.         }
  296.     bp = buffer;
  297.     wp = wheadp;
  298.     while (wp != NULL)
  299.         {
  300.         if (wp->w_bufp == bp)
  301.             {
  302.             wp->w_linep = lforw(bp->b_linep);
  303.             wp->w_dotp  = lforw(bp->b_linep);
  304.             wp->w_doto  = 0;
  305.             wp->w_markp = NULL;
  306.             wp->w_marko = 0;
  307.             wp->w_flag |= (WFMODE|WFHARD|WFFORCE);
  308.             }
  309.         wp = wp->w_wndp;
  310.         }
  311. #if AtST
  312.     mlwrite("[Alt-1 returns to one window]");
  313. #else
  314.     mlwrite("[^X 1 returns to one window]");
  315. #endif
  316.     return (TRUE);
  317.     }
  318.  
  319. /*
  320.  * This routine rebuilds the
  321.  * text in the special secret buffer
  322.  * that holds the buffer list. It is called
  323.  * by the list buffers command. Return TRUE
  324.  * if everything works. Return FALSE if there
  325.  * is an error (if there is no memory).
  326.  */
  327. makelist(buffer, data)
  328.     BUFFER    *buffer;
  329.     char    *data[];    /* not used */
  330.     {
  331.     register char    *cp1;
  332.     register char    *cp2;
  333.     register int    c;
  334.     register BUFFER    *bp;
  335.     register LINE    *lp;
  336.     register long    nbytes;        /* dal: use long rather than int */
  337.     register int    s;
  338.     register int    type;
  339.     char        b[6+1];
  340.     char        line[128];
  341.  
  342.     bp = buffer;
  343.     bbclear(bp);                /* Blow old text away    */
  344.     if (addline("\tC   Size Buffer           File", bp) == FALSE
  345.     ||  addline("\t-   ---- ------           ----", bp) == FALSE)
  346.         return (FALSE);
  347.     for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {  /* For all buffers    */
  348.         if (bp==blistp || bp==bhelpp || bp==bdirp)
  349.             continue;        /* mb: list other temps    */
  350.         nbytes = 0L;            /* Count bytes in buf.    */
  351.         lp = lforw(bp->b_linep);
  352.         while (lp != bp->b_linep)
  353.             {
  354.             nbytes += ((long) (llength(lp)+1));
  355.             lp = lforw(lp);
  356.             }
  357.         sprintf(line, "\t%c %6ld %-15s %s",
  358.             ((bp->b_flag & BFCHG) ? '*' : ' '),    /* changed ? */
  359.             nbytes,                    /* buf size */
  360.             bp->b_bname,                /* buf name */
  361.             bp->b_fname);                /* file name */
  362.         if (addline(line, buffer) == FALSE)
  363.             return (FALSE);
  364.         }
  365.     return (TRUE);                /* All done        */
  366.     }
  367.  
  368. #ifdef REMOVED
  369. itoa(buf, width, num)            /* dal: print *'s for overflow */
  370.     register char    buf[];
  371.     register int    width;
  372.     register int    num;
  373.     {
  374.     buf[width] = 0;                /* End of string.    */
  375.     while (width && (num >= 10))    /* Conditional digits.    */
  376.         {
  377.         buf[--width] = (num%10) + '0';
  378.         num /= 10;
  379.         }
  380.     if (width > 0)
  381.         buf[--width] = num + '0';    /* Always 1 digit.    */
  382.     else
  383.         while(buf[width])        /* *'s for overflow.    */
  384.             buf[width++] = '*';
  385.     while (width > 0)            /* Pad with blanks.    */
  386.         buf[--width] = ' ';
  387.     }
  388.  
  389. ltoa(buf, width, num)            /* dal: added */
  390.     register char    buf[];
  391.     register int    width;
  392.     register long    num;
  393.     {
  394.     buf[width] = 0;                /* End of string.    */
  395.     while (width && (num >= 10))    /* Conditional digits.    */
  396.         {
  397.         buf[--width] = (num%10) + '0';
  398.         num /= 10;
  399.         }
  400.     if (width > 0)
  401.         buf[--width] = num + '0';    /* Always 1 digit.    */
  402.     else
  403.         while(buf[width])        /* *'s for overflow.    */
  404.             buf[width++] = '*';
  405.     while (width > 0)            /* Pad with blanks.    */
  406.         buf[--width] = ' ';
  407.     }
  408. #endif
  409.  
  410. /*
  411.  * List all of the active buffers. Bound to "C-X ?".
  412.  */
  413. listbuffers(f, n)
  414.     {
  415.     return (make_popup(blistp, makelist, (long)NULL));
  416.     }
  417.  
  418.  
  419. /*
  420.  * The argument "text" points to a string.
  421.  * Append this line to the buffer *bp.
  422.  * Handcraft the EOL on the end.
  423.  * Return TRUE if it worked and
  424.  * FALSE if you ran out of room.
  425.  */
  426. addline(text, bp)
  427.     char *text;
  428.     register BUFFER    *bp;
  429.     {
  430.     register LINE    *lp;
  431.     register int    i;
  432.     register int    ntext;
  433.  
  434.     ntext = strlen(text);
  435.     if ((lp=lnalloc(ntext)) == NULL)
  436.         return (FALSE);
  437.     for (i=0; i<ntext; ++i)
  438.         lputc(lp, i, text[i]);
  439.     bp->b_linep->l_bp->l_fp = lp;        /* Hook onto the end    */
  440.     lp->l_bp = bp->b_linep->l_bp;
  441.     bp->b_linep->l_bp = lp;
  442.     lp->l_fp = bp->b_linep;
  443.     if (bp->b_dotp == bp->b_linep)        /* If "." is at the end    */
  444.         bp->b_dotp = lp;        /* move it to new line    */
  445.     return (TRUE);
  446.     }
  447.  
  448. /*
  449.  * Look through the list of
  450.  * buffers. Return TRUE if there
  451.  * are any changed buffers. Buffers
  452.  * that hold magic internal stuff are
  453.  * not considered; who cares if the
  454.  * list of buffer names is hacked.
  455.  * Return FALSE if no buffers
  456.  * have been changed.
  457.  */
  458. anycb()
  459.     {
  460.     register BUFFER    *bp;
  461.  
  462.     bp = bheadp;
  463.     while (bp != NULL)
  464.         {
  465.         if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  466.             return (TRUE);
  467.         bp = bp->b_bufp;
  468.         }
  469.     return (FALSE);
  470.     }
  471.  
  472. /*
  473.  * mb: delete the text of temporary buffers.
  474.  * Called by lnalloc() and enlrg_kbuf() if needed.
  475.  */
  476. dtmpbufs()
  477.     {
  478.     register BUFFER    *bp;
  479.  
  480.     bp = bheadp;
  481.     while (bp != NULL)
  482.         {
  483.         if (bp->b_flag&BFTEMP)
  484.             bbclear(bp);
  485.         bp = bp->b_bufp;
  486.         }
  487.     }
  488.  
  489. /*
  490.  * Find a buffer, by name. Return a pointer
  491.  * to the BUFFER structure associated with it. If
  492.  * the named buffer is found, but is a TEMP buffer (like
  493.  * the buffer list) conplain. If the buffer is not found
  494.  * and the "cflag" is TRUE, create it. The "bflag" is
  495.  * the settings for the flags in in buffer.
  496.  */
  497. BUFFER    *bfind(bname, cflag, bflag)
  498.     register char    *bname;
  499.     {
  500.     register BUFFER    *bp;
  501.     register LINE    *lp;
  502.  
  503.     bp = bheadp;
  504.     while (bp != NULL)
  505.         {
  506.         if (strcmp(bname, bp->b_bname) == 0)
  507.             return (bp);    /* mb: even if BFTEMP */
  508.         bp = bp->b_bufp;
  509.         }
  510.     if (cflag != FALSE)
  511.         {
  512.         if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  513.             return (NULL);
  514.         if ((lp=lnalloc(0)) == NULL)
  515.             {
  516.             free((char *) bp);
  517.             return (NULL);
  518.             }
  519.         bp->b_bufp  = bheadp;
  520.         bheadp = bp;
  521.         bp->b_dotp  = lp;
  522.         bp->b_doto  = 0;
  523.         bp->b_markp = NULL;
  524.         bp->b_marko = 0;
  525.         bp->b_flag  = bflag;
  526.         bp->b_nwnd  = 0;
  527.         bp->b_linep = lp;
  528.         strcpy(bp->b_fname, "");
  529.         strcpy(bp->b_bname, bname);
  530.         lp->l_fp = lp;
  531.         lp->l_bp = lp;
  532.         return (bp);
  533.         }
  534.     else
  535.         return (NULL);
  536.     }
  537.  
  538. /*
  539.  * This routine blows away all of the text
  540.  * in a buffer. If the buffer is marked as changed
  541.  * then we ask if it is ok to blow it away; this is
  542.  * to save the user the grief of losing text. The
  543.  * window chain is nearly always wrong if this gets
  544.  * called; the caller must arrange for the updates
  545.  * that are required. Return TRUE if everything
  546.  * looks good.
  547.  */
  548. bclear(bp)
  549.     register BUFFER    *bp;
  550.     {
  551.     register int    s;
  552.     
  553.     if ((bp->b_flag&BFTEMP) == 0        /* Not scratch buffer.    */
  554.      && (bp->b_flag&BFCHG) != 0        /* Something changed    */
  555.      && (s=mlyesno("Discard changes")) != TRUE)
  556.         {
  557.         mlwrite("[aborted]");
  558.         return (s);
  559.         }
  560.     bbclear(bp);
  561.     update();    /* mb: user feedback */
  562.     return (TRUE);
  563.     }
  564.  
  565. /*
  566.  * mb: separated from bclear()
  567.  */
  568. bbclear(bp)
  569.     register BUFFER    *bp;
  570.     {
  571.     register WINDOW    *wp;
  572.     register LINE    *lp;
  573.  
  574.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  575.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  576.         lfree(lp);
  577.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  578.     bp->b_doto  = 0;
  579.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  580.     bp->b_marko = 0;
  581.  
  582.     /* mb: added here - was in readin(): */
  583.  
  584.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp)
  585.         {
  586.         if (wp->w_bufp == bp)
  587.             {
  588.             wp->w_linep = bp->b_linep;
  589.             wp->w_dotp  = bp->b_linep;
  590.             wp->w_doto  = 0;
  591.             wp->w_flag |= (WFMODE|WFHARD|WFFORCE);
  592.             }
  593.         }
  594.     }
  595.  
  596. /*
  597.  * mb: added.
  598.  */
  599. renambuf(f, n)
  600.     {
  601.     register WINDOW    *wp;
  602.     register char    c;
  603.     register int    s;
  604.     char    bufn[NBUFN];
  605.  
  606.     if ((s=mlgets("New buffer name", NULL, bufn, NBUFN, CRLF)) == ABORT)
  607.         return (s);
  608.     curbp->b_flag &= (~BFTEMP);    /* not TEMP any more */
  609.     strlwr(bufn);
  610.     strcpy(curbp->b_bname, bufn);
  611.     wp = wheadp;
  612.     while (wp != NULL)
  613.         {
  614.         if (wp->w_bufp == curbp)
  615.             wp->w_flag |= WFMODE;
  616.         wp = wp->w_wndp;
  617.         }
  618.     return(TRUE);
  619.     }
  620.