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