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