home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / pico / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-23  |  13.4 KB  |  481 lines

  1. /*
  2.  * Program:    Buffer management routines
  3.  *
  4.  * Modifier:    Michael Seibel
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: mikes@cac.washington.edu
  11.  *
  12.  * Date:    19 Jan 1991
  13.  * Last Edited:    6 Jan 1992
  14.  *
  15.  * Copyright 1991 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. /*
  36.  * Buffer management.
  37.  * Some of the functions are internal,
  38.  * and some are actually attached to user
  39.  * keys. Like everyone else, they set hints
  40.  * for the display system.
  41.  */
  42. #include        <stdio.h>
  43. #include    "estruct.h"
  44. #include        "pico.h"
  45. #include        "edef.h"
  46.  
  47.  
  48. zotbuf(bp)    /* kill the buffer pointed to by bp */
  49.  
  50. register BUFFER *bp;
  51.  
  52. {
  53.         register BUFFER *bp1;
  54.         register BUFFER *bp2;
  55.         register int    s;
  56.  
  57.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  58.                 mlwrite("Buffer is being displayed");
  59.                 return (FALSE);
  60.         }
  61.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  62.                 return (s);
  63.         free((char *) bp->b_linep);             /* Release header line. */
  64.         bp1 = NULL;                             /* Find the header.     */
  65.         bp2 = bheadp;
  66.         while (bp2 != bp) {
  67.                 bp1 = bp2;
  68.                 bp2 = bp2->b_bufp;
  69.         }
  70.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  71.         if (bp1 == NULL)                        /* Unlink it.           */
  72.                 bheadp = bp2;
  73.         else
  74.                 bp1->b_bufp = bp2;
  75.         free((char *) bp);                      /* Release buffer block */
  76.         return (TRUE);
  77. }
  78.  
  79. namebuffer(f,n)        /*    Rename the current buffer    */
  80.  
  81. int f, n;        /* default Flag & Numeric arg */
  82.  
  83. {
  84.     register BUFFER *bp;    /* pointer to scan through all buffers */
  85.     char bufn[NBUFN];    /* buffer to hold buffer name */
  86.  
  87.     /* prompt for and get the new buffer name */
  88. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN, QNORML) != TRUE)
  89.         return(FALSE);
  90.  
  91.     /* and check for duplicates */
  92.     bp = bheadp;
  93.     while (bp != NULL) {
  94.         if (bp != curbp) {
  95.             /* if the names the same */
  96.             if (strcmp(bufn, bp->b_bname) == 0)
  97.                 goto ask;  /* try again */
  98.         }
  99.         bp = bp->b_bufp;    /* onward */
  100.     }
  101.  
  102.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  103.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  104.     mlerase();
  105. }
  106.  
  107.  
  108.  
  109. itoa(buf, width, num)
  110. register char   buf[];
  111. register int    width;
  112. register int    num;
  113. {
  114.         buf[width] = 0;                         /* End of string.       */
  115.         while (num >= 10) {                     /* Conditional digits.  */
  116.                 buf[--width] = (num%10) + '0';
  117.                 num /= 10;
  118.         }
  119.         buf[--width] = num + '0';               /* Always 1 digit.      */
  120.         while (width != 0)                      /* Pad with blanks.     */
  121.                 buf[--width] = ' ';
  122. }
  123.  
  124. /*
  125.  * The argument "text" points to
  126.  * a string. Append this line to the
  127.  * buffer list buffer. Handcraft the EOL
  128.  * on the end. Return TRUE if it worked and
  129.  * FALSE if you ran out of room.
  130.  */
  131. addline(text)
  132. char    *text;
  133. {
  134.         register LINE   *lp;
  135.         register int    i;
  136.         register int    ntext;
  137.  
  138.         ntext = strlen(text);
  139.         if ((lp=lalloc(ntext)) == NULL)
  140.                 return (FALSE);
  141.         for (i=0; i<ntext; ++i)
  142.                 lputc(lp, i, text[i]);
  143.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  144.         lp->l_bp = blistp->b_linep->l_bp;
  145.         blistp->b_linep->l_bp = lp;
  146.         lp->l_fp = blistp->b_linep;
  147.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  148.                 blistp->b_dotp = lp;            /* move it to new line  */
  149.         return (TRUE);
  150. }
  151.  
  152. /*
  153.  * Look through the list of
  154.  * buffers. Return TRUE if there
  155.  * are any changed buffers. Buffers
  156.  * that hold magic internal stuff are
  157.  * not considered; who cares if the
  158.  * list of buffer names is hacked.
  159.  * Return FALSE if no buffers
  160.  * have been changed.
  161.  */
  162. anycb()
  163. {
  164.         register BUFFER *bp;
  165.  
  166.         bp = bheadp;
  167.         while (bp != NULL) {
  168.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  169.                         return (TRUE);
  170.                 bp = bp->b_bufp;
  171.         }
  172.         return (FALSE);
  173. }
  174.  
  175. /*
  176.  * Find a buffer, by name. Return a pointer
  177.  * to the BUFFER structure associated with it. If
  178.  * the named buffer is found, but is a TEMP buffer (like
  179.  * the buffer list) conplain. If the buffer is not found
  180.  * and the "cflag" is TRUE, create it. The "bflag" is
  181.  * the settings for the flags in in buffer.
  182.  */
  183. BUFFER  *
  184. bfind(bname, cflag, bflag)
  185. register char   *bname;
  186. {
  187.         register BUFFER *bp;
  188.     register BUFFER *sb;    /* buffer to insert after */
  189.         register LINE   *lp;
  190.     char *malloc();
  191.  
  192.         bp = bheadp;
  193.         while (bp != NULL) {
  194.                 if (strcmp(bname, bp->b_bname) == 0) {
  195.                         if ((bp->b_flag&BFTEMP) != 0) {
  196.                                 mlwrite("Cannot select builtin buffer");
  197.                                 return (NULL);
  198.                         }
  199.                         return (bp);
  200.                 }
  201.                 bp = bp->b_bufp;
  202.         }
  203.         if (cflag != FALSE) {
  204.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  205.                         return (NULL);
  206.                 if ((lp=lalloc(0)) == NULL) {
  207.                         free((char *) bp);
  208.                         return (NULL);
  209.                 }
  210.         /* find the place in the list to insert this buffer */
  211.         if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  212.             /* insert at the begining */
  213.                     bp->b_bufp = bheadp;
  214.                     bheadp = bp;
  215.             } else {
  216.             sb = bheadp;
  217.             while (sb->b_bufp != NULL) {
  218.                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  219.                     break;
  220.                 sb = sb->b_bufp;
  221.             }
  222.  
  223.             /* and insert it */
  224.                    bp->b_bufp = sb->b_bufp;
  225.                 sb->b_bufp = bp;
  226.                }
  227.  
  228.         /* and set up the other buffer fields */
  229.         bp->b_active = TRUE;
  230.                 bp->b_dotp  = lp;
  231.                 bp->b_doto  = 0;
  232.                 bp->b_markp = NULL;
  233.                 bp->b_marko = 0;
  234.                 bp->b_flag  = bflag;
  235.         bp->b_mode  = gmode;
  236.                 bp->b_nwnd  = 0;
  237.                 bp->b_linep = lp;
  238.                 strcpy(bp->b_fname, "");
  239.                 strcpy(bp->b_bname, bname);
  240.                 lp->l_fp = lp;
  241.                 lp->l_bp = lp;
  242.         }
  243.         return (bp);
  244. }
  245.  
  246. /*
  247.  * This routine blows away all of the text
  248.  * in a buffer. If the buffer is marked as changed
  249.  * then we ask if it is ok to blow it away; this is
  250.  * to save the user the grief of losing text. The
  251.  * window chain is nearly always wrong if this gets
  252.  * called; the caller must arrange for the updates
  253.  * that are required. Return TRUE if everything
  254.  * looks good.
  255.  */
  256. bclear(bp)
  257. register BUFFER *bp;
  258. {
  259.         register LINE   *lp;
  260.         register int    s = FALSE;
  261.  
  262.     if(Pmaster){
  263.         if ((bp->b_flag&BFTEMP) == 0     /* Not scratch buffer.  */
  264.         && (bp->b_flag&BFCHG) != 0){    /* Something changed    */
  265.         emlwrite("buffer lines not freed.");
  266.         return (s);
  267.         }
  268.     }
  269.     else{
  270.         if ((bp->b_flag&BFTEMP) == 0    /* Not scratch buffer.  */
  271.         && (bp->b_flag&BFCHG) != 0    /* Something changed    */
  272.         && (s=mlyesno("Discard changes", -1)) != TRUE){
  273.         return (s);
  274.         }
  275.     }
  276.  
  277.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  278.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  279.                 lfree(lp);
  280.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  281.         bp->b_doto  = 0;
  282.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  283.         bp->b_marko = 0;
  284.         return (TRUE);
  285. }
  286.  
  287.  
  288. /*
  289.  * packbuf - will pack up the main buffer in the buffer provided 
  290.  *           to be returned to the program that called pico.
  291.  *         if need be, allocate memory for the new message. 
  292.  *           will also free the memory associated with the editor
  293.  *           buffer, by calling zotedit.
  294.  */
  295. packbuf(buf, blen, lcrlf)
  296. char    **buf;
  297. int    *blen;
  298. int    lcrlf;                /* EOLs are local or CRLF */
  299. {
  300.     register int    s;
  301.     register int    i = 0;
  302.     register LINE   *lp;
  303.     register int    nline;
  304.     register int    retval = 0;
  305.     register char   *bufp;
  306.     register char   *eobuf;
  307.  
  308.     if(anycb() != FALSE){
  309.  
  310.         lp = lforw(curbp->b_linep);
  311.         do{                    /* how many chars? */
  312.             i += llength(lp);
  313.         /*
  314.          * add extra for new lines to be inserted later
  315.          */
  316.         i += 2;
  317.         lp = lforw(lp);
  318.         }
  319.         while(lp != curbp->b_linep);
  320.  
  321.         if(i > *blen){                /* new buffer ? */
  322.             /*
  323.              * don't forget to add one for the null terminator!!!
  324.              */
  325.         if((bufp = (char *)malloc((i+1)*sizeof(char))) == NULL){
  326.                     zotedit();            /* bag it! */
  327.             return(COMP_FAILED);
  328.         }
  329.             free(*buf);
  330.         *buf = bufp;
  331.         *blen = i;
  332.         }
  333.         else{
  334.             bufp = *buf;
  335.         }
  336.     
  337.         eobuf = bufp + *blen;
  338.         lp = lforw(curbp->b_linep);             /* First line.          */
  339.         nline = 0;                              /* Number of lines.     */
  340.         do {
  341.         for (i = 0; i < llength(lp); i++){    /* copy into buffer */
  342.             if((bufp+1) < eobuf){
  343.             *bufp++ = (lp->l_text[i] & 0xFF);
  344.             }
  345.             else{
  346.             /*
  347.              * the idea is to malloc enough space for the new
  348.              * buffer...
  349.              */
  350.             *bufp = '\0';
  351.                     zotedit();
  352.             return(BUF_CHANGED|COMP_FAILED);
  353.             }
  354.         }
  355.         if(lcrlf){
  356.         *bufp++ = '\n';            /* EOLs use local convention */
  357.         }
  358.         else{
  359.         *bufp++ = 0x0D;            /* EOLs use net standard */
  360.         *bufp++ = 0x0A;
  361.         }
  362.             ++nline;
  363.             lp = lforw(lp);
  364.         }
  365.         while (lp != curbp->b_linep);
  366.     if(lcrlf)
  367.       *--bufp = '\0';
  368.     else
  369.       *bufp = '\0';
  370.         retval = BUF_CHANGED;
  371.     }
  372.  
  373.     zotedit();
  374.     return(retval);
  375. }
  376.  
  377.  
  378. /*
  379.  * readbuf - reads in a buffer.
  380.  */
  381. readbuf(buf)
  382. char    **buf;
  383. {
  384.         register LINE   *lp1;
  385.         register LINE   *lp2;
  386.         register BUFFER *bp;
  387.         register WINDOW *wp;
  388.         register int    i;
  389.         register int    s;
  390.         register int    nline;
  391.         char   *sptr;          /* pointer into buffer string */
  392.         int        nbytes;
  393.         int             lflag;          /* any lines longer than allowed?*/
  394.         char            line[NLINE];
  395.  
  396.     bp = curbp;
  397.         bp->b_flag &= ~(BFTEMP|BFCHG);
  398.     sptr = *buf;
  399.         nline = 0;
  400.         lflag = FALSE;
  401.  
  402.         while ((s=sgetline(&sptr,&nbytes,line,NLINE)) == FIOSUC || s == FIOLNG){
  403.  
  404.                 if (s == FIOLNG)
  405.                         lflag = TRUE;
  406.  
  407.                 if ((lp1=lalloc(nbytes)) == NULL) {
  408.                         s = FIOERR;             /* Keep message on the  */
  409.                         break;                  /* display.             */
  410.                 }
  411.                 lp2 = lback(curbp->b_linep);
  412.                 lp2->l_fp = lp1;
  413.                 lp1->l_fp = curbp->b_linep;
  414.                 lp1->l_bp = lp2;
  415.                 curbp->b_linep->l_bp = lp1;
  416.                 for (i=0; i<nbytes; ++i)
  417.                         lputc(lp1, i, line[i]);
  418.                 ++nline;
  419.         }
  420.  
  421.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  422.                 if (wp->w_bufp == curbp) {
  423.                         wheadp->w_linep = lforw(curbp->b_linep);
  424.                         wheadp->w_dotp  = lback(curbp->b_linep);
  425.                         wheadp->w_doto  = 0;
  426.                         wheadp->w_markp = NULL;
  427.                         wheadp->w_marko = 0;
  428.                         wheadp->w_flag |= WFHARD;
  429.                 }
  430.         }
  431.  
  432.     strcpy(bp->b_bname, "main");
  433.     strcpy(bp->b_fname, "");
  434.  
  435.     bp->b_dotp = bp->b_linep;
  436.     bp->b_doto = 0;
  437. }
  438.  
  439.  
  440. /*
  441.  * sgetline - copy characters from ibuf to obuf, ending at the first 
  442.  *            newline.  return with ibuf pointing to first char after
  443.  *            newline.
  444.  */
  445. sgetline(ibuf, nchars, obuf, blen)
  446. char    **ibuf;
  447. int    *nchars;
  448. char    *obuf;
  449. int    blen;
  450. {
  451.     register char     *len;
  452.     register char     *cbuf = *ibuf;
  453.     register char     *bufp = obuf;
  454.     register int     retval = FIOSUC;
  455. #define CR '\015'
  456. #define LF '\012'
  457.  
  458.     *nchars = 0;
  459.     if(*cbuf == '\0'){
  460.     retval = FIOEOF;
  461.     }
  462.     else{
  463.     len = obuf + blen;
  464.     while (*cbuf != CR && *cbuf != LF && *cbuf != '\0'){
  465.         if(bufp < len){
  466.         *bufp++ = *cbuf++;
  467.         (*nchars)++;
  468.         }
  469.         else{
  470.         *bufp = '\0';
  471.         retval = FIOLNG;
  472.         break;
  473.         }
  474.     }
  475.     }
  476.     *bufp = '\0';            /* end retured line */
  477.     *ibuf = (*cbuf == CR) ? ++cbuf : cbuf;
  478.     *ibuf = (*cbuf == LF) ? ++cbuf : cbuf;
  479.     return(retval);
  480. }
  481.