home *** CD-ROM | disk | FTP | other *** search
/ TopWare Tools / TOOLS.iso / tools / top1242 / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-06  |  21.4 KB  |  979 lines

  1. /*
  2. *       Buffer handling.
  3. */
  4.  
  5. #include    "def.h"
  6.  
  7. bool    onebuf ();
  8. bool    killablebufs ();
  9. bool    _yankbuffer ();
  10. char    next_buf ();
  11. bool    bclear ();
  12. bool    addline ();
  13. char    makelist ();
  14. bool    popblist ();
  15. char    listbuffers ();
  16. char    _killbuffer ();
  17. bool    _usebuffer ();
  18.  
  19. extern  ROW_FMT text_fmt;
  20. extern    char    MSG_use_b[];
  21. extern    char    MSG_kill_b[];
  22. extern    char    MSG_not_fnd[];
  23. extern    char    MSG_no_del_m[];
  24. extern    char    MSG_buf_disp[];
  25. extern    char    MSG_main[];
  26. extern    char    MSG_l_buf_h[];
  27. extern    char    MSG_l_buf_h1[];
  28. extern    char    MSG_no_chg[];
  29. extern    char    MSG_yank_b[];
  30. extern    char    MSG_no_buf[];
  31. extern    char    MSG_no_s_yank[];
  32. extern    char    MSG_buf_nam[];
  33. extern    char    MSG_bad_l[];
  34. extern    char    MSG_pick[];
  35. extern    char    MSG_siz_chg[];
  36. extern    char    MSG_no_siz_chg[];
  37. extern    char    MSG_up_arrow[];
  38. extern    char    MSG_null[];
  39. extern    char    MSG_save_buf[];
  40. extern    char    MSG_cnt_al_b[];
  41. extern    char    MSG_ins_cnt[];
  42.  
  43. BUFFER    sav_buf;
  44. LINE    sav_line_h;
  45. /*
  46. * Attach a buffer to a window. The
  47. * values of dot and mark come from the buffer
  48. * if the use count is 0. Otherwise, they come
  49. * from some other window.
  50. *
  51. * plus hacks for prev/next buffer and use-buffer-split  (jam)
  52. * functions (like in file.c)
  53. */
  54. char    usebuffer ()
  55. {
  56.  
  57.     char    bufn[NBUFN];
  58.     register char   s;
  59.  
  60.     if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  61.         return (s);
  62.     return (_usebuffer (bufn));
  63. }
  64.  
  65. /* use buffer, split window first
  66. */
  67. char    use_buffer ()
  68. {
  69.     char    bufn[NBUFN];
  70.     register char   s;
  71.  
  72.     if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  73.         return (s);
  74.     splitwind ();
  75.     return (_usebuffer (bufn));
  76. }
  77.  
  78. /* does all the work for changing to a new buffer for use-buffer,
  79. * use-buffer-split and prev-buff & next-buff
  80. */
  81. bool _usebuffer (bufn)
  82. char   *bufn;
  83. {
  84.     register    BUFFER * bp;
  85.     register    WINDOW * wp;
  86.  
  87.     if (strcmp (MSG_kill_b, bufn) == 0)/* hack! */
  88.         bp = blistp;
  89.     else
  90.         if ((bp = bfind (bufn, TRUE)) == NULL)
  91.             return (FALSE);
  92.  
  93.     /* if current buffer is special and new buffer is normal */
  94.     /* set to hex byte mode */
  95.     if ((curbp == blistp) && (R_TYPE(curwp) == TEXT))
  96.     {
  97.         dispsize1 ();
  98.         hexmode ();
  99.     }
  100.  
  101.     if (--curbp -> b_nwnd == 0)
  102.     {
  103.         /* Last use.         */
  104.         curbp -> b_dotp = curwp -> w_dotp;
  105.         curbp -> b_doto = curwp -> w_doto;
  106.         curbp -> b_unit_offset = curwp -> w_unit_offset;/* pvr */
  107.         curbp -> b_markp = curwp -> w_markp;
  108.         curbp -> b_marko = curwp -> w_marko;
  109.     }
  110.     curbp = bp;                 /* Switch.       */
  111.     curwp -> w_bufp = bp;
  112.     curwp -> w_linep = bp -> b_linep;/* For macros, ignored.     */
  113.     curwp -> w_loff = 0; /* pvr */
  114.     curwp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  115.     /* Quite nasty.      */
  116.     if (bp -> b_nwnd++ == 0)
  117.     {
  118.         /* First use.        */
  119.         curwp -> w_dotp = bp -> b_dotp;
  120.         curwp -> w_doto = bp -> b_doto;
  121.         curwp -> w_unit_offset = 0;     /* pvr */
  122.         curwp -> w_markp = bp -> b_markp;
  123.         curwp -> w_marko = bp -> b_marko;
  124.         wind_on_dot (curwp);
  125.         /* if we are in the funny TEXT mode then goto standard HEX mode */
  126.         if (R_TYPE(curwp) == TEXT)
  127.             hexmode ();
  128.         return (TRUE);
  129.     }
  130.     wp = wheadp;                /* Look for old.     */
  131.     while (wp != NULL)
  132.     {
  133.         if (wp != curwp && wp -> w_bufp == bp)
  134.         {
  135.             curwp -> w_dotp = wp -> w_dotp;
  136.             curwp -> w_doto = wp -> w_doto;
  137.             curwp -> w_unit_offset = wp -> w_unit_offset;/* pvr */
  138.             curwp -> w_markp = wp -> w_markp;
  139.             curwp -> w_marko = wp -> w_marko;
  140.             break;
  141.         }
  142.         wp = wp -> w_wndp;
  143.     }
  144.     wind_on_dot (curwp);
  145.     /* if we are in the funny TEXT mode then goto standard HEX mode */
  146.     if (R_TYPE(curwp) == TEXT)
  147.         hexmode ();
  148.     return (TRUE);
  149. }
  150.  
  151.  
  152. /*
  153. * Dispose of a buffer, by name.
  154. * Ask for the name. Look it up (don't get too
  155. * upset if it isn't there at all!). Get quite upset
  156. * if the buffer is being displayed. Clear the buffer (ask
  157. * if the buffer has been changed). Then free the header
  158. * line and the buffer header. Bound to "C-X K".
  159. */
  160. char    killbuffer ()
  161. {
  162.     register char   s;
  163.     char    bufn[NBUFN];
  164.  
  165.     if ((s = ereply (MSG_kill_b, bufn, NBUFN, 0)) != TRUE)
  166.         return (s);
  167.     if (s = _killbuffer (bufn))
  168.         writ_echo (okmsg);             /* verbose-ness (jam) */
  169.     return (s);
  170. }
  171.  
  172.  
  173. char    _killbuffer (bufn)
  174. char   *bufn;
  175. {
  176.     register    BUFFER * bp,
  177.     *bp1,
  178.     *bp2;
  179.     register char   s,
  180.     x = 0;
  181.  
  182.     if (((bp = bfind (bufn, FALSE)) == NULL) ||
  183.         !strcmp (bufn, MSG_save_buf))
  184.     {
  185.         writ_echo (MSG_not_fnd);
  186.         return (FALSE);
  187.     }
  188.  
  189.  
  190.     if (killablebufs (bp))      /* can't kill '?' if no other buffers */
  191.     {
  192.         writ_echo (MSG_no_del_m);
  193.         return (FALSE);
  194.     }
  195.  
  196.     /* see if the buffer to be killed is in a window */
  197.     bp1 = bp;
  198.     if (curbp == blistp && onebuf (bp))/* Hack ! */
  199.     {
  200.         next_buf ();
  201.         onlywind ();
  202.         update ();
  203.     }
  204.  
  205.     if (bp -> b_nwnd > 0)
  206.     {
  207.         if ((s = eyesno (MSG_buf_disp)) != TRUE)
  208.             return (s);
  209.  
  210.         /* make the current window the only window if it is to die */
  211.         onlywind ();
  212.         if (curbp == bp)
  213.         {
  214.             next_buf ();
  215.             if (curbp == bp)
  216.                 x++;
  217.         }
  218.     }
  219.     if ((s = bclear (bp)) != TRUE)/* Blow text away.      */
  220.     {
  221.         if (bp1 == blistp)      /* special buffer */
  222.             curbp = bp1;
  223.         else
  224.             if (!x)
  225.                 _usebuffer (bp1 -> b_bname);
  226.         /* back to original buffer (jam) */
  227.         return (s);
  228.     }
  229.     if (x)
  230.     {
  231.         _usebuffer (MSG_main);
  232.         x++;
  233.     }
  234.  
  235.     free ((char *) bp -> b_linep);/* Release header line.         */
  236.     bp1 = NULL;                 /* Find the header.     */
  237.     bp2 = bheadp;
  238.     while (bp2 != bp)
  239.     {
  240.         bp1 = bp2;
  241.         bp2 = bp2 -> b_bufp;
  242.     }
  243.     bp2 = bp2 -> b_bufp;        /* Next one in chain.   */
  244.     if (bp1 == NULL)            /* Unlink it.           */
  245.         bheadp = bp2;
  246.     else
  247.         bp1 -> b_bufp = bp2;
  248.     free ((char *) bp);         /* Release buffer block         */
  249.     if (x)
  250.         update ();
  251.     /* update buffer display */
  252.     if ((blistp -> b_nwnd != 0) &&
  253.         (blistp -> b_type == BTLIST))
  254.         listbuffers ();
  255.     return (TRUE);
  256. }
  257.  
  258. /*
  259. * Display the buffer list. This is done
  260. * in two parts. The "makelist" routine figures out
  261. * the text, and puts it in the buffer whoses header is
  262. * pointed to by the external "blistp". The "popblist"
  263. * then pops the data onto the screen. Bound to
  264. * "C-X C-B".
  265. */
  266. char    listbuffers ()
  267. {
  268.     register char   s;
  269.  
  270.     if ((s = makelist ()) != TRUE)
  271.         return (s);
  272.     return (popblist ());
  273. }
  274. /*
  275. * Display the save buffer contents.
  276. * Bound to "Meta C-W".
  277. */
  278. char    showsavebuf ()
  279. {
  280.     WINDOW   *wp;
  281.  
  282.     if (sav_buf.b_nwnd == 0)
  283.     {
  284.         splitwind ();
  285.         _usebuffer (MSG_save_buf);
  286.     }
  287.     else
  288.     {
  289.         wp = wheadp;                /* Look for old.     */
  290.         while (wp != NULL)
  291.         {
  292.             if (wp -> w_bufp == &sav_buf)
  293.             {
  294.                 wp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  295.                 break;
  296.             }
  297.             wp = wp -> w_wndp;
  298.         }
  299.     }
  300.     return (TRUE);
  301. }
  302.  
  303. /*
  304. * Pop the special buffer whose
  305. * buffer header is pointed to by the external
  306. * variable "blistp" onto the screen. This is used
  307. * by the "listbuffers" routine (above) and by
  308. * some other packages. Returns a status.
  309. */
  310. bool popblist ()
  311. {
  312.     register    WINDOW * wp;
  313.     register    BUFFER * bp;
  314.  
  315.     if (blistp -> b_nwnd == 0)  /* Not on screen yet.    */
  316.     {
  317.         if ((wp = wpopup ()) == NULL)
  318.             return (FALSE);
  319.         bp = wp -> w_bufp;
  320.         if (--bp -> b_nwnd == 0)
  321.         {
  322.             bp -> b_dotp = wp -> w_dotp;
  323.             bp -> b_doto = wp -> w_doto;
  324.             bp -> b_unit_offset = wp -> w_unit_offset;/* pvr */
  325.             bp -> b_markp = wp -> w_markp;
  326.             bp -> b_marko = wp -> w_marko;
  327.         }
  328.         curwp = wp;
  329.         curbp = blistp;
  330.         wp -> w_bufp = blistp;
  331.         ++blistp -> b_nwnd;
  332.     }
  333.     wp = wheadp;
  334.     while (wp != NULL)
  335.     {
  336.         if (wp -> w_bufp == blistp)
  337.         {
  338.             wp -> w_linep = lforw (blistp -> b_linep);
  339.             wp -> w_loff = 0;
  340.             wp -> w_dotp = lforw (blistp -> b_linep);
  341.             wp -> w_doto = 0;
  342.             wp -> w_unit_offset = 0;
  343.             wp -> w_markp = NULL;
  344.             wp -> w_marko = 0;
  345.             wp -> w_disp_shift = 0;
  346.             wp -> w_intel_mode = FALSE;
  347.             wp -> w_fmt_ptr = &text_fmt;
  348.             wp -> w_flag |= WFMODE | WFHARD;
  349.         }
  350.         wp = wp -> w_wndp;
  351.     }
  352.     return (TRUE);
  353. }
  354.  
  355. /*
  356. * This routine rebuilds the
  357. * text in the special secret buffer
  358. * that holds the buffer list. It is called
  359. * by the list buffers command. Return TRUE
  360. * if everything works. Return FALSE if there
  361. * is an error (if there is no memory).
  362. */
  363. char    makelist ()
  364. {
  365.     register    char  *cp1;
  366.     register    char  *cp2;
  367.     register    int    c;
  368.     register    BUFFER * bp;
  369.     register    A32    nbytes;
  370.     register    char   s;
  371.     char    b[8 + 1];
  372.     char    line[128];
  373.  
  374.     blistp -> b_flag &= ~BFCHG; /* Blow away old.    */
  375.     if ((s = bclear (blistp)) != TRUE)
  376.         return (s);
  377.     blistp -> b_flag |= BFVIEW;
  378.     blistp -> b_type = BTLIST;
  379.     strcpy (blistp -> b_fname, MSG_up_arrow);
  380.     if (addline (MSG_l_buf_h) == FALSE
  381.         || addline (MSG_l_buf_h1) == FALSE)
  382.         return (FALSE);
  383.     bp = bheadp;                /* For all buffers   */
  384.     while (bp != NULL)
  385.     {
  386.         cp1 = &line[0];         /* Start at left edge    */
  387.         if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed    */
  388.             *cp1++ = '*';
  389.         else
  390.             if (bp -> b_flag & BFVIEW)/* jam */
  391.                 *cp1++ = 'R';   /* readonly */
  392.             else
  393.                 *cp1++ = ' ';
  394.         *cp1++ = ' ';           /* Gap. */
  395.         if ((bp -> b_flag & BFBAD) != 0)/* "?" if maybe trashed  */
  396.             *cp1++ = '?';
  397.         else
  398.             *cp1++ = ' ';
  399.         *cp1++ = ' ';           /* Gap. */
  400.         nbytes = bp -> b_linep -> l_bp -> l_file_offset +
  401.             bp -> b_linep -> l_bp -> l_used;
  402.         sprintf (b, "%8lx", nbytes); /* 8 digit buffer size.   */
  403.         cp2 = &b[0];
  404.         while ((c = *cp2++) != 0)
  405.             *cp1++ = c;
  406.         *cp1++ = ' ';           /* Gap.          */
  407.         cp2 = &bp -> b_bname[0];/* Buffer name       */
  408.         while ((c = *cp2++) != 0)
  409.             *cp1++ = c;
  410.         *cp1++ = ' ';           /* Gap.          */
  411.         *cp1++ = ' ';           /* Gap.          */
  412.         cp2 = &bp -> b_fname[0];/* File name         */
  413.         if (*cp2 != 0)
  414.         {
  415.             while (cp1 < &line[1 + 1 + 1 + 1 + 6 + 1 + NBUFN + 1])
  416.                 *cp1++ = ' ';
  417.             while ((c = *cp2++) != 0)
  418.             {
  419.                 if (cp1 < &line[128 - 1])
  420.                     *cp1++ = c;
  421.             }
  422.         }
  423.         while (cp1 < &line[80])   /* Fill out line to col 80 */
  424.             *cp1++ = ' ';
  425.  
  426.         *cp1 = 0;               /* Add to the buffer.    */
  427.         if (addline (line) == FALSE)
  428.             return (FALSE);
  429.         bp = bp -> b_bufp;
  430.     }
  431.     return (TRUE);              /* All done      */
  432. }
  433.  
  434. /*
  435. * The argument "text" points to
  436. * a string. Append this line to the
  437. * buffer list buffer.
  438. * Return TRUE if it worked and
  439. * FALSE if you ran out of room.
  440. */
  441. bool addline (text)
  442. char   *text;
  443. {
  444.     register    LINE    * lp;
  445.     register    int     i, allocsize;
  446.     register    int     ntext;
  447.  
  448.     ntext = strlen (text);
  449.     allocsize = 128;
  450.  
  451.     if ((lp = lalloc (allocsize)) == NULL)
  452.         return (FALSE);
  453.  
  454.     for (i = 0; i < ntext; ++i)
  455.         lputc (lp, i, text[i]);
  456.  
  457.     for (; i < allocsize; ++i)     /* fill out line with spaces */
  458.         lputc (lp, i, ' ');
  459.  
  460.     blistp -> b_linep -> l_bp -> l_fp = lp;/* Hook onto the end  */
  461.     lp -> l_bp = blistp -> b_linep -> l_bp;
  462.     blistp -> b_linep -> l_bp = lp;
  463.     lp -> l_fp = blistp -> b_linep;
  464.     lp -> l_size = allocsize;  /* line size is limited to 80 chars */
  465.     lp -> l_used = allocsize;
  466.     lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  467.     if (blistp -> b_dotp == blistp -> b_linep)/* If "." is at the end    */
  468.         blistp -> b_dotp = lp;  /* move it to new line   */
  469.     return (TRUE);
  470. }
  471.  
  472.  
  473. /*
  474. * Look through the list of
  475. * buffers. Return TRUE if there
  476. * are any changed buffers. Special buffers
  477. * like the buffer list buffer don't count, as
  478. * they are not in the list. Return FALSE if
  479. * there are no changed buffers.
  480. */
  481. bool anycb ()
  482. {
  483.     register    BUFFER * bp;
  484.  
  485.     bp = bheadp;
  486.     while (bp != NULL)
  487.     {
  488.  
  489.         if ((bp -> b_flag & BFCHG) != 0)
  490.             return (TRUE);
  491.         bp = bp -> b_bufp;
  492.     }
  493.     return (FALSE);
  494. }
  495.  
  496.  
  497. /*
  498. * Search for a buffer, by name.
  499. * If not found, and the "cflag" is TRUE,
  500. * create a buffer and put it in the list of
  501. * all buffers. Return pointer to the BUFFER
  502. * block for the buffer.
  503. */
  504. BUFFER * bfind (bname, cflag)
  505. register char  *bname;
  506. int cflag;
  507. {
  508.     register    BUFFER * bp;
  509.  
  510.     bp = bheadp;
  511.     while (bp != NULL)
  512.     {
  513.         if (strcmp (bname, bp -> b_bname) == 0)
  514.             return (bp);
  515.         bp = bp -> b_bufp;
  516.     }
  517.     if (cflag != FALSE && (bp = bcreate (bname)) != NULL)
  518.     {
  519.         bp -> b_bufp = bheadp;
  520.         bheadp = bp;
  521.     }
  522.     return (bp);
  523. }
  524.  
  525.  
  526. /*
  527. * Create a buffer, by name.
  528. * Return a pointer to the BUFFER header
  529. * block, or NULL if the buffer cannot
  530. * be created. The BUFFER is not put in the
  531. * list of all buffers; this is called by
  532. * "edinit" to create the buffer list
  533. * buffer.
  534. */
  535. BUFFER * bcreate (bname)
  536. register char  *bname;
  537. {
  538.  
  539.     register    BUFFER * bp;
  540.     register    LINE * lp;
  541.  
  542.     if ((bp = (BUFFER *) malloc (sizeof (BUFFER))) == NULL)
  543.     {
  544.         err_echo (MSG_cnt_al_b);
  545.         return (NULL);
  546.     }
  547.     if ((lp = lalloc (0)) == NULL)
  548.     {
  549.         free ((char *) bp);
  550.         return (NULL);
  551.     }
  552.     bp -> b_bufp = NULL;
  553.     bp -> b_dotp = lp;
  554.     bp -> b_doto = 0;
  555.     bp -> b_unit_offset = 0;    /* unit offset   pvr */
  556.     bp -> b_markp = NULL;
  557.     bp -> b_marko = 0;
  558.     bp -> b_flag = 0;
  559.     bp -> b_nwnd = 0;
  560.     bp -> b_linep = lp;
  561.     strcpy (bp -> b_fname, MSG_null);
  562.     strcpy (bp -> b_bname, bname);
  563.     lp -> l_fp = lp;
  564.     lp -> l_bp = lp;
  565.     lp -> l_file_offset = 0;    /* pvr */
  566.     lp -> l_used = 0;           /* pvr */
  567.     lp -> l_size = 0;           /* size of zero indicates the header line  pvr
  568.                                                         */
  569.     return (bp);
  570. }
  571.  
  572.  
  573. /*
  574. * This routine blows away all of the text
  575. * in a buffer. If the buffer is marked as changed
  576. * then we ask if it is ok to blow it away; this is
  577. * to save the user the grief of losing text. The
  578. * window chain is nearly always wrong if this gets
  579. * called; the caller must arrange for the updates
  580. * that are required. Return TRUE if everything
  581. * looks good.
  582. */
  583. bool bclear (bp)
  584. register    BUFFER * bp;
  585. {
  586.     register    LINE * lp;
  587.     register char   s;
  588.  
  589.     if ((bp -> b_flag & BFCHG) != 0/* Changed.       */
  590.     && (s = eyesno (MSG_no_chg)) != TRUE)
  591.         return (s);
  592.     bp -> b_flag &= ~BFCHG;     /* Not changed       */
  593.     while ((lp = lforw (bp -> b_linep)) != bp -> b_linep)
  594.         lfree (lp);
  595.     bp -> b_dotp = bp -> b_linep;/* Fix "."      */
  596.     bp -> b_doto = 0;
  597.     bp -> b_unit_offset = 0;    /* pvr */
  598.     bp -> b_markp = NULL;       /* Invalidate mark  */
  599.     bp -> b_marko = 0;
  600.     return (TRUE);
  601. }
  602.  
  603.  
  604. /* flip to next buffer in the list, wrap
  605. * to beginning if required (wrap around)
  606. * (skips buffers saved  by save-region)
  607. */
  608. char    next_buf ()
  609. {
  610.     register    BUFFER * bp;
  611.  
  612.     bp = curbp;
  613.     while (TRUE)
  614.     {
  615.         if (!(bp = bp -> b_bufp))
  616.             bp = bheadp;
  617.         if ((bp -> b_type == BTSAVE) ||
  618.             (bp -> b_type == BTLIST) ||
  619.             (bp -> b_type == BTHELP))
  620.             continue;
  621.         break;
  622.     }
  623.     _usebuffer (bp -> b_bname);
  624.     return (TRUE);
  625. }
  626.  
  627.  
  628. /* flip to prev buffer in the list, wrap
  629. * to end if required (wrap around)
  630. * (does NOT skip buffers saved by save-region)
  631. */
  632. char    prev_buf ()
  633. {
  634.     register    BUFFER * sp;
  635.  
  636.     if ((sp = curbp) == bheadp) /* front of list */
  637.     {
  638.         for (; sp -> b_bufp; sp = sp -> b_bufp)
  639.             ;
  640.     }
  641.     else /* cycle around */
  642.     {
  643.         for (sp = bheadp; sp -> b_bufp; sp = sp -> b_bufp)
  644.         {
  645.             if (sp -> b_bufp == curbp)
  646.                 break;
  647.         }
  648.     }
  649.     return (_usebuffer (sp -> b_bname));
  650. }
  651.  
  652.  
  653. /* yank a buffer into current buffer
  654. */
  655. char    yank_buffer ()
  656. {
  657.     char    bufn[NBUFN];
  658.  
  659.     if (ereply (MSG_yank_b, bufn, NBUFN, 0) != TRUE)
  660.         return (FALSE);
  661.     return (_yankbuffer (bufn));
  662. }
  663.  
  664.  
  665. bool _yankbuffer (bufn)
  666. char   *bufn;
  667. {
  668.     register    LINE * lp;
  669.     register    BUFFER * bp = curbp;
  670.     register int    s;
  671.     A32      cnt;
  672.     char        buf[NFILEN], buf1[NFILEN];
  673.  
  674.     if ((bp = bfind (bufn, FALSE)) == NULL)
  675.     {
  676.         writ_echo (MSG_no_buf);
  677.         return (FALSE);
  678.     }
  679.     if (strcmp (bp -> b_bname, curbp -> b_bname) == 0)
  680.     {
  681.         writ_echo (MSG_no_s_yank);
  682.         return (FALSE);
  683.     }
  684.     cnt = 0;
  685.     lp = lforw (bp -> b_linep);
  686.     while (TRUE)
  687.     {
  688.         cnt += lp -> l_used;
  689.         for (s = 0; s < lp -> l_used; s++)
  690.             if (linsert (1, lp -> l_text[s]) == FALSE)
  691.                 return (FALSE);
  692.  
  693.         if ((lp = lforw (lp)) == bp -> b_linep)
  694.         {
  695.             break;
  696.         }
  697.  
  698.         if ((cnt & 0x7ff) == 0)
  699.         {
  700.             sprintf (buf1, MSG_ins_cnt, R_POS_FMT(curwp));
  701.             sprintf (buf, buf1, cnt);
  702.             writ_echo (buf);
  703.             /* check if we should quit */
  704.             if (ttkeyready ())
  705.             {
  706.                 l_fix_up (lp -> l_bp);
  707.                 wind_on_dot_all();
  708.                 if (ttgetc () == CTL_G)  /* was it an abort key? */
  709.                     return (FALSE);
  710.             }
  711.         }
  712.     }
  713.     writ_echo (okmsg);
  714.     return (TRUE);
  715. }
  716.  
  717.  
  718. bool buffername ()
  719. {
  720.  
  721.     register    WINDOW * wp;
  722.     register char  *p;
  723.     register char   s;
  724.     char    bname[NBUFN + 1];
  725.  
  726.     if ((s = ereply (MSG_buf_nam, bname, NBUFN, 0)) == ABORT)
  727.         return (s);
  728.     for (p = bname; *p && *p != ' '; p++)
  729.         ;
  730.     *p = 0;                     /* no blanks */
  731.     strcpy (curbp -> b_bname, bname);
  732.     wp = wheadp;                /* Update mode lines.   */
  733.     while (wp != NULL)
  734.     {
  735.         if (wp -> w_bufp == curbp)
  736.             wp -> w_flag |= WFMODE;
  737.         wp = wp -> w_wndp;
  738.     }
  739.     if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  740.     (blistp -> b_type == BTLIST))
  741.         listbuffers ();
  742.     return (TRUE);
  743. }
  744.  
  745.  
  746. /* any killable buffers around ? (jam)
  747. */
  748. bool killablebufs (bp)
  749. register    BUFFER * bp;
  750. {
  751.     if (strcmp (bp -> b_bname, MSG_main) == 0)/* doomed buffer is 'empty' */
  752.         if (bheadp == bp)       /* and is only buffer in list */
  753.             if (bheadp -> b_bufp == 0)/* then there are no killable buffers */
  754.                 return (TRUE);
  755.     return (FALSE);
  756. }
  757.  
  758.  
  759. /* only 1 buffer around ?
  760. */
  761. bool onebuf (bp)
  762. register    BUFFER * bp;
  763. {
  764.     if (strcmp (bp -> b_bname, bheadp -> b_bname) == 0)
  765.         if (bheadp -> b_bufp == 0)
  766.             return (TRUE);
  767.     return (FALSE);
  768. }
  769.  
  770.  
  771. /* funky new name; real yukky!!!! (jam)
  772. */
  773. void funky_name (bname, n)
  774. register char  *bname;
  775. int     n;
  776. {
  777.     char    num[10];
  778.     register int    i;
  779.     register char  *p;
  780.  
  781.     for (i = 0; i < 10; i++)
  782.         num[i] = ' ';
  783.     for (p = bname; *p; p++)
  784.         *p = 0;
  785.     *bname++ = '#';
  786.     sprintf (num, "%lx", (long) n + 1);
  787.     for (p = num; *p; p++)
  788.         if (*p != ' ')
  789.             *bname++ = *p;
  790.     *bname = 0;
  791. }
  792.  
  793.  
  794. /* pick a buffer to goto/kill
  795. */
  796. #define BUFFEROFFSET (13)       /* depends on makelist !! */
  797.  
  798. bool pickone ()
  799. {
  800.     register int    s,
  801.     i,
  802.     c;
  803.     register    LINE * lp;
  804.     char    name[NBUFN + 1];
  805.     char    buf[3];
  806.     WINDOW  *wp;
  807.  
  808.     lp = curwp -> w_dotp;       /* get the buffer name from the line */
  809.  
  810.     i = 0;
  811.     if (!llength (lp))
  812.     {
  813.         writ_echo (MSG_bad_l);
  814.         return (FALSE);
  815.     }
  816.     for (s = BUFFEROFFSET; (c = lgetc (lp, s)) != ' '; s++)
  817.     {
  818.         name[i++] = c;
  819.         if (s >= llength (lp))
  820.             break;
  821.     }
  822.     name[i] = 0;
  823.     if (!bfind (name, FALSE))
  824.     {
  825.         writ_echo (MSG_bad_l);
  826.         return (FALSE);
  827.     }
  828. loop:
  829.     if ((s = ereply (MSG_pick, buf, 2, name)) != TRUE)
  830.         return (FALSE);
  831.     if (ISLOWER (buf[0]) != FALSE)
  832.         buf[0] = TOUPPER (buf[0]);
  833.     if (buf[0] == 'K')
  834.         _killbuffer (name);
  835.     else
  836.         if (buf[0] == 'G')
  837.             _usebuffer (name);
  838.         else
  839.             if (buf[0] == 'S')
  840.             {
  841.                 _usebuffer (name);
  842.                 /* goto this buffer, but don't show the user */
  843.                 filesave ();
  844.                 _usebuffer (MSG_kill_b);
  845.                 /* jump back to this window - HACK ! */
  846.                 listbuffers (); /* update the list */
  847.             }
  848.             else
  849.                 goto loop;
  850.     writ_echo (MSG_null);
  851.     return (TRUE);
  852. }
  853. /*
  854. *   Toggle the buffer size lock bit.
  855. */
  856. char bufsizlock ()
  857. {
  858.     if (curbp -> b_flag & BFSLOCK)
  859.     {
  860.         curbp -> b_flag &= ~BFSLOCK;
  861.         writ_echo (MSG_siz_chg);
  862.     }
  863.     else
  864.     {
  865.         if (insert_mode)
  866.             insert_toggle ();
  867.         curbp -> b_flag |= BFSLOCK;
  868.         writ_echo (MSG_no_siz_chg);
  869.     }
  870.     return (TRUE);
  871. }
  872.  
  873. /*
  874.  *   Append the given line to the end of the given buffer.
  875.  */
  876. void   b_append_l (buf_p, lp)
  877. BUFFER *buf_p;
  878. LINE   *lp;
  879. {
  880.     LINE   *h_lp;
  881.  
  882.     h_lp = buf_p -> b_linep;
  883.  
  884.     lp -> l_fp = h_lp;
  885.     lp -> l_bp = h_lp -> l_bp;
  886.     lp -> l_bp -> l_fp = lp;
  887.     h_lp -> l_bp = lp;
  888.     lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  889. }
  890. /*
  891.  *   Append the given line to the end of the given buffer.
  892.  */
  893. bool   b_append_c (buf_p, ch)
  894. BUFFER *buf_p;
  895. D8     ch;
  896. {
  897.     LINE   *lp;
  898.  
  899.     lp = buf_p -> b_linep -> l_bp;    /* get last line */
  900.     /* do I need to get a new line? */
  901.     if (lp -> l_size <= lp -> l_used)
  902.     {
  903.         if ((lp = lalloc (KBLOCK)) == NULL)
  904.             return (FALSE);
  905.  
  906.         lp -> l_fp = buf_p -> b_linep;
  907.         lp -> l_bp = buf_p -> b_linep -> l_bp;
  908.         lp -> l_bp -> l_fp = lp;
  909.         buf_p -> b_linep -> l_bp = lp;
  910.     }
  911.     lp -> l_text[lp -> l_used++] = ch;
  912.  
  913.     return (TRUE);
  914. }
  915.  
  916. /*
  917.  * Initialize the save buffer.
  918.  */
  919. void save_buf_init ()
  920. {
  921.     register    BUFFER * bp;
  922.  
  923.     sav_line_h.l_fp = &sav_line_h;
  924.     sav_line_h.l_bp = &sav_line_h;
  925.     sav_line_h.l_file_offset = 0;
  926.     sav_line_h.l_used = 0;
  927.     sav_line_h.l_size = 0;
  928.  
  929.     sav_buf.b_type = BTSAVE;
  930.     sav_buf.b_bufp = NULL;
  931.     sav_buf.b_dotp = &sav_line_h;
  932.     sav_buf.b_doto = 0;
  933.     sav_buf.b_unit_offset = 0;
  934.     sav_buf.b_markp = NULL;
  935.     sav_buf.b_marko = 0;
  936.     sav_buf.b_linep = &sav_line_h;
  937.     sav_buf.b_nwnd = 0;
  938.     sav_buf.b_flag = BFVIEW;
  939.     sav_buf.b_begin_addr = 0;
  940.     sav_buf.b_file_size = 0;
  941.     sav_buf.b_fname[0] = 0;
  942.     strcpy (sav_buf.b_bname, MSG_save_buf);
  943.  
  944.     /* put on end of chain */
  945.     bp = bheadp;
  946.     while ((bp -> b_bufp) != NULL)
  947.         bp = bp -> b_bufp;
  948.  
  949.     bp->b_bufp = &sav_buf;
  950.  
  951. }
  952.  
  953. /*
  954.  * Set the save buffer dot pointer to the begining.
  955.  */
  956. void save_buf_home ()
  957. {
  958.     sav_buf.b_dotp = sav_buf.b_linep -> l_fp;
  959.     sav_buf.b_doto = 0;
  960.     sav_buf.b_flag = BFVIEW;
  961. }
  962.  
  963. D16  get_save_char ()
  964. {
  965.     D8 ch;
  966.  
  967.     /* are we past the end of the buffer */
  968.     if (sav_buf.b_dotp == sav_buf.b_linep)
  969.         return (-1);
  970.     ch = sav_buf.b_dotp -> l_text[sav_buf.b_doto++];
  971.     if (sav_buf.b_doto >= sav_buf.b_dotp -> l_used)
  972.     {
  973.         sav_buf.b_doto = 0;
  974.         sav_buf.b_dotp = sav_buf.b_dotp -> l_fp;
  975.     }
  976.     return ((D16)ch);
  977. }
  978.  
  979.