home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-09  |  13.7 KB  |  585 lines  |  [TEXT/Earl]

  1. /*
  2.  * Buffer management.  Some of the functions are internal, and some are
  3.  * actually attached to user keys.  Like everyone else, they set hints
  4.  * for the display system.
  5.  */
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "edef.h"
  9.  
  10. #if FINDER
  11. #include <packages.h>
  12. #endif
  13. /*
  14.  * Attach a buffer to a window.  The values of dot and mark come from the
  15.  * buffer if the use count is 0.  Otherwise, they come from some other
  16.  * window.
  17.  */
  18. usebuffer(f, n)
  19. {
  20.     register BUFFER *bp;
  21.     register int    s;
  22.     char        bufn[NBUFN];
  23.  
  24.     if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  25.         return (s);
  26.     if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  27.         return (FALSE);
  28.     return(swbuffer(bp));
  29. }
  30.  
  31. nextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  32.  
  33. int f, n;    /* default flag, numeric argument */
  34. {
  35.     register BUFFER *bp;    /* eligable buffer to switch to*/
  36.     register BUFFER *bbp;    /* eligable buffer to switch to*/
  37.  
  38.     /* make sure the arg is legit */
  39.     if (f == FALSE)
  40.         n = 1;
  41.     if (n < 1)
  42.         return(FALSE);
  43.  
  44.     bbp = curbp;
  45.     while (n-- > 0) {
  46.         /* advance to the next buffer */
  47.         bp = bbp->b_bufp;
  48.  
  49.         /* cycle through the buffers to find an eligable one */
  50.         while (bp == NULL || bp->b_flag & BFINVS) {
  51.             if (bp == NULL)
  52.                 bp = bheadp;
  53.             else
  54.                 bp = bp->b_bufp;
  55.  
  56.             /* don't get caught in an infinite loop! */
  57.             if (bp == bbp)
  58.                 return(FALSE);
  59.  
  60.         }        
  61.  
  62.         bbp = bp;
  63.     }
  64.  
  65.     return(swbuffer(bp));
  66. }
  67.  
  68. swbuffer(bp)    /* make buffer BP current */
  69.  
  70. BUFFER *bp;
  71.  
  72. {
  73.     register WINDOW *wp;
  74.  
  75.     if (--curbp->b_nwnd == 0) {        /* Last use.        */
  76.         curbp->b_dotp  = curwp->w_dotp;
  77.         curbp->b_doto  = curwp->w_doto;
  78.         curbp->b_markp = curwp->w_markp;
  79.         curbp->b_marko = curwp->w_marko;
  80.     }
  81.     curbp = bp;                /* Switch.        */
  82.     if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  83.         /* read it in and activate it */
  84. #if FINDER
  85.         _iovrefnum = bp->b_ioWDDirID;
  86. #endif
  87.         readin(curbp->b_fname, TRUE);
  88.         curbp->b_dotp = lforw(curbp->b_linep);
  89.         curbp->b_doto = 0;
  90.         curbp->b_active = TRUE;
  91.     }
  92.     curwp->w_bufp  = bp;
  93.     curwp->w_linep = bp->b_linep;        /* For macros, ignored. */
  94.     curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.     */
  95.     if (bp->b_nwnd++ == 0) {        /* First use.        */
  96.         curwp->w_dotp  = bp->b_dotp;
  97.         curwp->w_doto  = bp->b_doto;
  98.         curwp->w_markp = bp->b_markp;
  99.         curwp->w_marko = bp->b_marko;
  100.         return (TRUE);
  101.     }
  102.     wp = wheadp;                /* Look for old.    */
  103.     while (wp != NULL) {
  104.         if (wp!=curwp && wp->w_bufp==bp) {
  105.             curwp->w_dotp  = wp->w_dotp;
  106.             curwp->w_doto  = wp->w_doto;
  107.             curwp->w_markp = wp->w_markp;
  108.             curwp->w_marko = wp->w_marko;
  109.             break;
  110.         }
  111.         wp = wp->w_wndp;
  112.     }
  113.     return (TRUE);
  114. }
  115.  
  116. /*
  117.  * Dispose of a buffer, by name.  Ask for the name.  Look it up (don't
  118.  * get too upset if it isn't there at all!).  Get quite upset if the
  119.  * buffer is being displayed.  Clear the buffer (ask if the buffer has
  120.  * been changed).  Then free the header line and the buffer header.
  121.  * Bound to "C-X K".
  122.  */
  123. killbuffer(f, n)
  124.  
  125. {
  126.     register BUFFER *bp;
  127.     register int    s;
  128.     char bufn[NBUFN];
  129.     char prompt[NBUFN+15];
  130.  
  131.     strcpy(prompt,"Kill buffer: [");     /* Default to current. */
  132.     strcat(prompt,curbp->b_bname);
  133.     strcat(prompt,"]");
  134.     
  135.     if ((s=mlreply(prompt, bufn, NBUFN)) == ABORT)        /* CTRL 'G' */
  136.         return(s);
  137.     if(s == FALSE) strcpy(bufn,curbp->b_bname);         /* Default */
  138.     if ((bp=bfind(bufn, FALSE, 0)) == NULL)     /* Easy if unknown. */
  139.         return (TRUE);
  140.     if(bp->b_flag & BFINVS)     /* Deal with special buffers    */
  141.             return (TRUE);        /* by doing nothing.    */
  142.     return(zotbuf(bp));
  143. }
  144.  
  145. zotbuf(bp)    /* kill the buffer pointed to by bp */
  146.  
  147. register BUFFER *bp;
  148.  
  149. {
  150.     register BUFFER *bp1;
  151.     register BUFFER *bp2;
  152.     register WINDOW *wp;
  153.  
  154.     register int    s;
  155.  
  156.     if ((s=bclear(bp)) != TRUE)            /* Blow text away.        */
  157.         return (s);
  158.     if (bp->b_nwnd != 0) {              /* More work if on screen */
  159.         wp = curwp;
  160.         if(curbp == bp){        /* Current buffer is only 1 */
  161.             if(nextbuffer(FALSE,1) == FALSE){
  162.                 if(name_equal(bp->b_bname,"main") != 0){
  163.                     s = docmd("select-buffer main");
  164.                 }else{
  165.                     s = docmd("select-buffer Maine");
  166.                 }
  167.                 if(s != TRUE){      /* Should NEVER get here. */
  168.                     TTbeep();
  169.                     mlwrite("Trouble creating alternate buffer");
  170.                     return FALSE;
  171.                 }
  172.             }
  173.         }
  174.         while((nextwind(FALSE,1) != FALSE) && (curwp != wp)){
  175.             if(curbp == bp)     /* Undisplay buffer */
  176.                 (void)nextbuffer(FALSE,1);
  177.         }
  178.     }
  179.     free((char *) bp->b_linep);        /* Release header line. */
  180.     bp1 = NULL;                /* Find the header.    */
  181.     bp2 = bheadp;
  182.     while (bp2 != bp) {
  183.         bp1 = bp2;
  184.         bp2 = bp2->b_bufp;
  185.     }
  186.     bp2 = bp2->b_bufp;            /* Next one in chain.    */
  187.     if (bp1 == NULL)            /* Unlink it.        */
  188.         bheadp = bp2;
  189.     else
  190.         bp1->b_bufp = bp2;
  191.     free((char *) bp);            /* Release buffer block */
  192.     return (TRUE);
  193. }
  194.  
  195. namebuffer(f,n)     /*    Rename the current buffer    */
  196.  
  197. int f, n;        /* default Flag & Numeric arg */
  198.  
  199. {
  200.     register BUFFER *bp;    /* pointer to scan through all buffers */
  201.     char bufn[NBUFN];    /* buffer to hold buffer name */
  202.  
  203.     /* prompt for and get the new buffer name */
  204. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  205.         return(FALSE);
  206.  
  207.     /* and check for duplicates */
  208.     bp = bheadp;
  209.     while (bp != NULL) {
  210.         if (bp != curbp) {
  211.             /* if the names the same */
  212.             if (name_equal(bufn, bp->b_bname) == 0)
  213.                 goto ask;  /* try again */
  214.         }
  215.         bp = bp->b_bufp;    /* onward */
  216.     }
  217.  
  218.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  219.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  220.     mlerase();
  221.     return(TRUE);
  222. }
  223.  
  224. /*
  225.  * List all of the active buffers.  First update the special buffer that
  226.  * holds the list.  Next make sure at least 1 window is displaying the
  227.  * buffer list, splitting the screen if this is what it takes.    Lastly,
  228.  * repaint all of the windows that are displaying the list.  Bound to
  229.  * "C-X C-B".  A numeric argument forces it to list invisable buffers as
  230.  * well.
  231. */
  232.  
  233. listbuffers(f, n)
  234. {
  235.     register WINDOW *wp;
  236.     register BUFFER *bp;
  237.     register int    s;
  238.  
  239.     if ((s=makelist(f)) != TRUE)
  240.         return (s);
  241.     if (blistp->b_nwnd == 0) {        /* Not on screen yet.    */
  242.         if ((wp=wpopup()) == NULL)
  243.             return (FALSE);
  244.         bp = wp->w_bufp;
  245.         if (--bp->b_nwnd == 0) {
  246.             bp->b_dotp  = wp->w_dotp;
  247.             bp->b_doto  = wp->w_doto;
  248.             bp->b_markp = wp->w_markp;
  249.             bp->b_marko = wp->w_marko;
  250.         }
  251.         wp->w_bufp  = blistp;
  252.         ++blistp->b_nwnd;
  253.     }
  254.     wp = wheadp;
  255.     while (wp != NULL) {
  256.         if (wp->w_bufp == blistp) {
  257.             wp->w_linep = lforw(blistp->b_linep);
  258.             wp->w_dotp  = lforw(blistp->b_linep);
  259.             wp->w_doto  = 0;
  260.             wp->w_markp = NULL;
  261.             wp->w_marko = 0;
  262.             wp->w_flag |= WFMODE|WFHARD;
  263.         }
  264.         wp = wp->w_wndp;
  265.     }
  266.     return (TRUE);
  267. }
  268.  
  269. /*
  270.  * This routine rebuilds the text in the special secret buffer that holds
  271.  * the buffer list.  It is called by the list buffers command.    Return
  272.  * TRUE if everything works.  Return FALSE if there is an error (if there
  273.  * is no memory).  Iflag indecates weather to list hidden buffers.
  274.  */
  275. #define BUF_FIELD 16
  276.  
  277. makelist(iflag)
  278.  
  279. int iflag;    /* list hidden buffer flag */
  280.  
  281. {
  282.     register char    *cp1;
  283.     register char    *cp2;
  284.     register int    c;
  285.     register BUFFER *bp;
  286.     register LINE    *lp;
  287.     register int    s;
  288.     register int    i;
  289.     long nbytes;        /* # of bytes in current buffer */
  290.     char b[7+1];
  291.     char line[128];
  292.     int buf_name_len;
  293.  
  294.     blistp->b_flag &= ~BFCHG;        /* Don't complain!      */
  295.     if ((s=bclear(blistp)) != TRUE)     /* Blow old text away    */
  296.         return (s);
  297.     strcpy(blistp->b_fname, "");
  298. #if MAC
  299.     if (addline("ACT MODES        Size Buffer        File\011\011TYPECRTR") == FALSE
  300.     ||  addline("--- ---------    ---- ------        ----\011\011--------") == FALSE)
  301.         return (FALSE);
  302. #else
  303.     if (addline("ACT MODES        Size Buffer        File") == FALSE
  304.     ||  addline("--- ---------    ---- ------        ----") == FALSE)
  305.         return (FALSE);
  306. #endif
  307.     bp = bheadp;                /* For all buffers    */
  308.  
  309.     /* build line to report global mode settings */
  310.     cp1 = &line[0];
  311.     *cp1++ = ' ';
  312.     *cp1++ = ' ';
  313.     *cp1++ = ' ';
  314.     *cp1++ = ' ';
  315.  
  316.     /* output the mode codes */
  317.     for (i = 0; i < NUMMODES; i++)
  318.         if (gmode & (1 << i))
  319.             *cp1++ = modecode[i];
  320.         else
  321.             *cp1++ = '.';
  322.     strcpy(cp1, "         Global Modes");
  323.     if (addline(line) == FALSE)
  324.         return(FALSE);
  325.  
  326.     /* output the list of buffers */
  327.     while (bp != NULL) {
  328.         /* skip invisable buffers if iflag is false */
  329.         if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
  330.             bp = bp->b_bufp;
  331.             continue;
  332.         }
  333.         cp1 = &line[0];         /* Start at left edge    */
  334.  
  335.         /* output status of ACTIVE flag (has the file been read in? */
  336.         if (bp->b_active == TRUE)    /* "@" if activated       */
  337.             *cp1++ = '@';
  338.         else
  339.             *cp1++ = ' ';
  340.  
  341.         /* output status of changed flag */
  342.         if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed    */
  343.             *cp1++ = '*';
  344.         else
  345.             *cp1++ = ' ';
  346.  
  347.         /* report if the file is truncated */
  348.         if ((bp->b_flag&BFTRUNC) != 0)
  349.             *cp1++ = '#';
  350.         else
  351.             *cp1++ = ' ';
  352.  
  353.         *cp1++ = ' ';    /* space */
  354.  
  355.         /* output the mode codes */
  356.         for (i = 0; i < NUMMODES; i++) {
  357.             if (bp->b_mode & (1 << i))
  358.                 *cp1++ = modecode[i];
  359.             else
  360.                 *cp1++ = '.';
  361.         }
  362.         *cp1++ = ' ';            /* Gap.         */
  363.         nbytes = 0L;            /* Count bytes in buf.    */
  364.         lp = lforw(bp->b_linep);
  365.         while (lp != bp->b_linep) {
  366.             nbytes += (long)llength(lp)+1L;
  367.             lp = lforw(lp);
  368.         }
  369.         ltoa(b, 7, nbytes);        /* 6 digit buffer size. */
  370.         cp2 = &b[0];
  371.         buf_name_len = strlen(cp2) + 3;
  372.         if(buf_name_len < BUF_FIELD) buf_name_len = BUF_FIELD;
  373.         while ((c = *cp2++) != 0)
  374.             *cp1++ = c;
  375.         *cp1++ = ' ';            /* Gap.         */
  376.         cp2 = &bp->b_bname[0];        /* Buffer name        */
  377.         while ((c = *cp2++) != 0)
  378.             *cp1++ = c;
  379.         cp2 = &bp->b_fname[0];        /* File name        */
  380.         if (*cp2 != 0) {
  381.             while (cp1 < &line[3+1+5+1+6+4+buf_name_len])
  382.                 *cp1++ = ' ';
  383.             while ((c = *cp2++) != 0) {
  384.                 if (cp1 < &line[128-1])
  385.                     *cp1++ = c;
  386.             }
  387. #if MAC
  388.             if(cp1 < &line[118-1]){
  389.                 FInfo info;
  390.                 *cp1++ = 9;
  391.                 *cp1++ = 9;
  392.                 c2pstr(&bp->b_fname[0]);
  393.                 GetFInfo(&bp->b_fname[0],bp->b_ioWDDirID,&info);
  394.                 p2cstr(&bp->b_fname[0]);
  395.                 BlockMove(&info,cp1,8L);
  396.                 cp1 += 8;
  397.             }
  398. #endif
  399.         }
  400.         *cp1 = 0;            /* Add to the buffer.    */
  401.         if (addline(line) == FALSE)
  402.             return (FALSE);
  403.         bp = bp->b_bufp;
  404.     }
  405.     return (TRUE);                /* All done        */
  406. }
  407.  
  408. ltoa(buf, width, num)
  409.  
  410. char   buf[];
  411. int    width;
  412. long   num;
  413.  
  414. {
  415.     buf[width] = 0;             /* End of string.    */
  416.     while (num >= 10) {            /* Conditional digits.    */
  417.         buf[--width] = (int)(num%10L) + '0';
  418.         num /= 10L;
  419.     }
  420.     buf[--width] = (int)num + '0';        /* Always 1 digit.    */
  421.     while (width != 0)            /* Pad with blanks.    */
  422.         buf[--width] = ' ';
  423. }
  424.  
  425. /*
  426.  * The argument "text" points to a string.  Append this line to the
  427.  * buffer list buffer.    Handcraft the EOL on the end.  Return TRUE if it
  428.  * worked and FALSE if you ran out of room.
  429.  */
  430. addline(text)
  431. char    *text;
  432. {
  433.     register LINE    *lp;
  434.     register int    i;
  435.     register int    ntext;
  436.  
  437.     ntext = strlen(text);
  438.     if ((lp=lalloc(ntext)) == NULL)
  439.         return (FALSE);
  440.     for (i=0; i<ntext; ++i)
  441.         lputc(lp, i, text[i]);
  442.     blistp->b_linep->l_bp->l_fp = lp;    /* Hook onto the end    */
  443.     lp->l_bp = blistp->b_linep->l_bp;
  444.     blistp->b_linep->l_bp = lp;
  445.     lp->l_fp = blistp->b_linep;
  446.     if (blistp->b_dotp == blistp->b_linep)    /* If "." is at the end */
  447.         blistp->b_dotp = lp;        /* move it to new line    */
  448.     return (TRUE);
  449. }
  450.  
  451. /*
  452.  * Look through the list of buffers.  Return TRUE if there are any
  453.  * changed buffers.  Buffers that hold magic internal stuff are not
  454.  * considered; who cares if the list of buffer names is hacked.  Return
  455.  * FALSE if no buffers have been changed.
  456.  */
  457. anycb()
  458. {
  459.     register BUFFER *bp;
  460.  
  461.     bp = bheadp;
  462.     while (bp != NULL) {
  463.         if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  464.             return (TRUE);
  465.         bp = bp->b_bufp;
  466.     }
  467.     return (FALSE);
  468. }
  469. #if FINDER
  470. name_equal(a,b)
  471. char *a,*b;
  472. {
  473.     int result;
  474.     c2pstr(a);
  475.     c2pstr(b);
  476.     result = IUCompString(a,b);
  477.     p2cstr(a);
  478.     p2cstr(b);
  479.     return result;
  480. }
  481. #endif
  482. /*
  483.  * Find a buffer, by name.  Return a pointer to the BUFFER structure
  484.  * associated with it.    If the buffer is not found and the "cflag" is
  485.  * TRUE, create it.  The "bflag" is the settings for the flags in in
  486.  * buffer.
  487.  */
  488. BUFFER    *
  489. bfind(bname, cflag, bflag)
  490. register char    *bname;
  491. {
  492.     register BUFFER *bp;
  493.     register BUFFER *sb;    /* buffer to insert after */
  494.     register LINE    *lp;
  495.     char *malloc();
  496.  
  497.     bp = bheadp;
  498.     while (bp != NULL) {
  499.         if (name_equal(bname, bp->b_bname) == 0)
  500.             return (bp);
  501.         bp = bp->b_bufp;
  502.     }
  503.     if (cflag != FALSE) {
  504.         if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  505.             return (NULL);
  506.         if ((lp=lalloc(0)) == NULL) {
  507.             free((char *) bp);
  508.             return (NULL);
  509.         }
  510.         /* find the place in the list to insert this buffer */
  511.         if (bheadp == NULL || name_equal(bheadp->b_bname, bname) > 0) {
  512.             /* insert at the beginning */
  513.             bp->b_bufp = bheadp;
  514.             bheadp = bp;
  515.         } else {
  516.             sb = bheadp;
  517.             while (sb->b_bufp != NULL) {
  518.                 if (name_equal(sb->b_bufp->b_bname, bname) > 0)
  519.                     break;
  520.                 sb = sb->b_bufp;
  521.             }
  522.  
  523.             /* and insert it */
  524.             bp->b_bufp = sb->b_bufp;
  525.             sb->b_bufp = bp;
  526.         }
  527.  
  528.         /* and set up the other buffer fields */
  529.         bp->b_active = TRUE;
  530.         bp->b_dotp  = lp;
  531.         bp->b_doto  = 0;
  532.         bp->b_markp = NULL;
  533.         bp->b_marko = 0;
  534.         bp->b_flag  = bflag;
  535.         bp->b_mode  = gmode;
  536.         bp->b_nwnd  = 0;
  537.         bp->b_linep = lp;
  538.         strcpy(bp->b_fname, "");
  539.         strcpy(bp->b_bname, bname);
  540. #if    CRYPT
  541.         bp->b_key[0] = 0;
  542. #endif
  543.         lp->l_fp = lp;
  544.         lp->l_bp = lp;
  545.     }
  546.     return (bp);
  547. }
  548.  
  549. /*
  550.  * This routine blows away all of the text in a buffer.  If the buffer is
  551.  * marked as changed then we ask if it is ok to blow it away; this is to
  552.  * save the user the grief of losing text.  The window chain is nearly
  553.  * always wrong if this gets called; the caller must arrange for the
  554.  * updates that are required.  Return TRUE if everything looks good.
  555.  */
  556. bclear(bp)
  557. register BUFFER *bp;
  558. {
  559.     register LINE    *lp;
  560.     register int    s;
  561.  
  562.     if ((bp->b_flag&BFINVS) == 0        /* Not scratch buffer.    */
  563.     && (bp->b_flag&BFCHG) != 0        /* Something changed    */
  564.     && (s=mlyesno("Discard changes")) != TRUE)
  565.         return (s);
  566.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  567.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  568.         lfree(lp);
  569.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  570.     bp->b_doto  = 0;
  571.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  572.     bp->b_marko = 0;
  573.     return (TRUE);
  574. }
  575.  
  576. unmark(f, n)    /* unmark the current buffers change flag */
  577.  
  578. int f, n;    /* unused command arguments */
  579.  
  580. {
  581.     curbp->b_flag &= ~BFCHG;
  582.     curwp->w_flag |= WFMODE;
  583.     return(TRUE);
  584. }
  585.