home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / v / vim_src.zip / EDIT.C < prev    next >
C/C++ Source or Header  |  1993-01-12  |  16KB  |  788 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMitation
  4.  *
  5.  * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  6.  *                            Tim Thompson            twitch!tjt
  7.  *                            Tony Andrews            onecom!wldrdg!tony 
  8.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  9.  */
  10.  
  11. /*
  12.  * edit.c: functions for insert mode
  13.  */
  14.  
  15. #include "vim.h"
  16. #include "globals.h"
  17. #include "proto.h"
  18. #include "param.h"
  19. #include "ops.h"    /* for operator */
  20.  
  21. extern u_char *get_inserted();
  22. static void start_arrow __ARGS((void));
  23. static void stop_arrow __ARGS((void));
  24. static void stop_insert __ARGS((void));
  25.  
  26. int arrow_used;            /* Normally FALSE, set to TRUE after hitting
  27.                              * cursor key in insert mode. Used by vgetorpeek()
  28.                              * to decide when to call u_sync() */
  29. int restart_edit;        /* call edit when next command finished */
  30. static u_char    *last_insert = NULL;
  31.                             /* the text of the previous insert */
  32. static int        last_insert_skip;
  33.                             /* number of chars in front of the previous insert */
  34. static int        new_insert_skip;
  35.                             /* number of chars in front of the current insert */
  36.  
  37.     void
  38. edit(count)
  39.     long count;
  40. {
  41.     u_char         c;
  42.     u_char         cc;
  43.     u_char        *ptr;
  44.     linenr_t     lnum;
  45.     int          temp = 0, mode;
  46.     int             nextc = 0;
  47.  
  48. #ifdef DIGRAPHS
  49.     int             inserted = 0;        /* last 'normal' inserted char */
  50.     int             backspaced = 0;    /* last backspace char */
  51. #endif /* DIGRAPHS */
  52.  
  53.     if (restart_edit)
  54.     {
  55.         arrow_used = TRUE;
  56.         restart_edit = FALSE;
  57.     }
  58.     else
  59.         arrow_used = FALSE;
  60.  
  61. /*
  62.  * Get the current length of the redo buffer, those characters have to be
  63.  * skipped if we want to get to the inserted characters.
  64.  */
  65.  
  66.     ptr = get_inserted();
  67.     new_insert_skip = strlen((char *)ptr);
  68.     free(ptr);
  69.  
  70.     for (;;)
  71.     {
  72.         if (arrow_used)        /* don't repeat insert when arrow key used */
  73.             count = 0;
  74.  
  75.         cursupdate();        /* Figure out where the cursor is based on Curpos. */
  76.         setcursor();
  77.         if (nextc)            /* character remaining from CTRL-V */
  78.         {
  79.             c = nextc;
  80.             nextc = 0;
  81.         }
  82.         else
  83.             c = vgetc();
  84.  
  85. nextchar:
  86. #ifdef DIGRAPHS
  87.         if (p_dg)
  88.         {
  89.             if (backspaced)
  90.                 c = getdigraph(backspaced, c);
  91.             backspaced = 0;
  92.             if (c == BS && inserted)
  93.                 backspaced = inserted;
  94.             else
  95.                 inserted = c;
  96.         }
  97. #endif /* DIGRAPHS */
  98.  
  99.         if (c == CTRL('V'))
  100.         {
  101.                 outchar('^');
  102.                 AppendToRedobuff("\026");    /* CTRL-V */
  103.                 cursupdate();
  104.                 setcursor();
  105.  
  106.                 c = get_literal(&nextc);
  107.  
  108.             /* erase the '^' */
  109.                 if ((cc = gcharCurpos()) == NUL)
  110.                     outchar(' ');
  111.                 else
  112.                     outstrn(transchar(cc));
  113.  
  114.                 insertchar(c);
  115.                 continue;
  116.         }
  117.         switch (c)        /* handle character in insert mode */
  118.         {
  119.               case CTRL('O'):        /* execute one command */
  120.                   count = 0;
  121.                 restart_edit = TRUE;
  122.                 /*FALLTHROUGH*/
  123.  
  124.               case ESC: /* an escape ends input mode */
  125.         doESCkey:
  126.                 if (!arrow_used)
  127.                 {
  128.                     AppendToRedobuff(ESC_STR);
  129.  
  130.                     if (--count > 0)        /* repeat what was typed */
  131.                     {
  132.                             start_redo_ins();
  133.                             continue;
  134.                     }
  135.                     stop_insert();
  136.                 }
  137.                 set_want_col = TRUE;
  138.  
  139.                 /*
  140.                  * The cursor should end up on the last inserted character.
  141.                  */
  142.                 if (Curpos.col != 0 && (!restart_edit || gcharCurpos() == NUL))
  143.                     decCurpos();
  144.                 State = NORMAL;
  145.                 script_winsize_pp();    /* may need to put :winsize in script */
  146.                     /* inchar() may have deleted the "INSERT" message */
  147.                 if (Recording)
  148.                     showmode();
  149.                 else if (p_mo)
  150.                     msg("");
  151.                 return;
  152.  
  153.                   /*
  154.                  * Insert the previously inserted text.
  155.                  * Last_insert actually is a copy of the redo buffer, so we
  156.                  * first have to remove the command.
  157.                  * For ^@ the trailing ESC will end the insert.
  158.                  */
  159.               case K_ZERO:
  160.               case CTRL('A'):
  161.                 stuff_inserted(NUL, 1L, (c == CTRL('A')));
  162.                 break;
  163.  
  164.                   /*
  165.                  * insert the contents of a register
  166.                  */
  167.               case CTRL('B'):
  168.                   if (!insertbuf(vgetc()))
  169.                     beep();
  170.                 break;
  171.  
  172.                 /*
  173.                  * If the cursor is on an indent, ^T/^D insert/delete one
  174.                  * shiftwidth. Otherwise ^T/^D behave like a TAB/backspace.
  175.                  * This isn't completely compatible with
  176.                  * vi, but the difference isn't very noticeable and now you can
  177.                  * mix ^D/backspace and ^T/TAB without thinking about which one
  178.                  * must be used.
  179.                  */
  180.               case CTRL('T'):        /* make indent one shiftwidth greater */
  181.               case CTRL('D'):         /* make indent one shiftwidth smaller */
  182.                 stop_arrow();
  183.                 AppendToRedobuff(mkstr(c));
  184.  
  185.                     /* determine offset from first non-blank */
  186.                 temp = Curpos.col;
  187.                 beginline(TRUE);
  188.                 temp -= Curpos.col;
  189.  
  190.                   shift_line(c == CTRL('D'));
  191.  
  192.                     /* try to put cursor on same character */
  193.                 temp += Curpos.col;
  194.                 if (temp <= 0)
  195.                     Curpos.col = 0;
  196.                 else
  197.                     Curpos.col = temp;
  198.                 did_ai = FALSE;
  199.                 did_si = FALSE;
  200.                 can_si = FALSE;
  201.                   goto redraw;
  202.  
  203.               case BS:
  204.               case DEL:
  205. nextbs:
  206.                 mode = 0;
  207. dodel:
  208.                 /* can't backup past first character in buffer */
  209.                 /* can't backup past starting point unless "backspace" > 1 */
  210.                 /* can backup to a previous line if "backspace" == 0 */
  211.                 if ((Curpos.lnum == 1 && Curpos.col <= 0) ||
  212.                         (p_bs < 2 && (arrow_used ||
  213.                             (Curpos.lnum == Insstart.lnum &&
  214.                             Curpos.col <= Insstart.col) ||
  215.                             (Curpos.col <= 0 && p_bs == 0))))
  216.                 {
  217.                     beep();
  218.                     goto redraw;
  219.                 }
  220.  
  221.                 stop_arrow();
  222.                 if (Curpos.col <= 0)        /* delete newline! */
  223.                 {
  224.                     if (Curpos.lnum == Insstart.lnum)
  225.                     {
  226.                         if (!u_save((linenr_t)(Curpos.lnum - 2), (linenr_t)(Curpos.lnum + 1)))
  227.                             goto redraw;
  228.                         --Insstart.lnum;
  229.                         Insstart.col = 0;
  230.                     }
  231.                 /* in replace mode with 'repdel' off we only move the cursor */
  232.                     if (State != REPLACE || p_rd)
  233.                     {
  234.                         temp = gcharCurpos();        /* remember current char */
  235.                         --Curpos.lnum;
  236.                         dojoin(FALSE);
  237.                         if (temp == NUL)
  238.                             ++Curpos.col;
  239.                     }
  240.                     else
  241.                         decCurpos();
  242.                     did_ai = FALSE;
  243.                 }
  244.                 else
  245.                 {
  246.                     /* delete upto starting point, start of line or previous word */
  247.                     do
  248.                     {
  249.                         decCurpos();
  250.                                 /* start of word? */
  251.                         if (mode == 1 && !isspace(gcharCurpos()))
  252.                         {
  253.                             mode = 2;
  254.                             temp = isidchar(gcharCurpos());
  255.                         }
  256.                                 /* end of word? */
  257.                         if (mode == 2 && isidchar(gcharCurpos()) != temp)
  258.                         {
  259.                             incCurpos();
  260.                             break;
  261.                         }
  262.                         if (State != REPLACE || p_rd)
  263.                             delchar(TRUE);
  264.                         if (mode == 0)        /* just a single backspace */
  265.                             break;
  266.                     } while (Curpos.col > 0 && (Curpos.lnum != Insstart.lnum ||
  267.                             Curpos.col != Insstart.col));
  268.                 }
  269.                 did_si = FALSE;
  270.                 can_si = FALSE;
  271.                 if (Curpos.col <= 1)
  272.                     did_ai = FALSE;
  273.                 /*
  274.                  * It's a little strange to put backspaces into the redo
  275.                  * buffer, but it makes auto-indent a lot easier to deal
  276.                  * with.
  277.                  */
  278.                 AppendToRedobuff(mkstr(c));
  279.                 if (vpeekc() == BS)
  280.                 {
  281.                         c = vgetc();
  282.                         goto nextbs;    /* speedup multiple backspaces */
  283.                 }
  284. redraw:
  285.                 cursupdate();
  286.                 updateline();
  287.                 break;
  288.  
  289.               case CTRL('W'):
  290.                   /* delete word before cursor */
  291.                   mode = 1;
  292.                   goto dodel;
  293.  
  294.               case CTRL('U'):
  295.                 mode = 3;
  296.                   goto dodel;
  297.  
  298.               case K_LARROW:
  299.                   if (oneleft())
  300.                     start_arrow();
  301.                 else
  302.                     beep();
  303.                 break;
  304.  
  305.               case K_SLARROW:
  306.                   if (Curpos.lnum > 1 || Curpos.col > 0)
  307.                 {
  308.                     bck_word(1L, 0);
  309.                     start_arrow();
  310.                 }
  311.                 else
  312.                     beep();
  313.                 break;
  314.  
  315.               case K_RARROW:
  316.                 if (gcharCurpos() != NUL)
  317.                 {
  318.                     set_want_col = TRUE;
  319.                     start_arrow();
  320.                     ++Curpos.col;
  321.                 }
  322.                 else
  323.                     beep();
  324.                 break;
  325.  
  326.               case K_SRARROW:
  327.                   if (Curpos.lnum < line_count || gcharCurpos() != NUL)
  328.                 {
  329.                     fwd_word(1L, 0);
  330.                     start_arrow();
  331.                 }
  332.                 else
  333.                     beep();
  334.                 break;
  335.  
  336.               case K_UARROW:
  337.                   if (oneup(1L))
  338.                     start_arrow();
  339.                 else
  340.                     beep();
  341.                 break;
  342.  
  343.               case K_SUARROW:
  344.                   if (onepage(BACKWARD, 1L))
  345.                     start_arrow();
  346.                 else
  347.                     beep();
  348.                 break;
  349.  
  350.               case K_DARROW:
  351.                   if (onedown(1L))
  352.                     start_arrow();
  353.                 else
  354.                     beep();
  355.                 break;
  356.  
  357.               case K_SDARROW:
  358.                   if (onepage(FORWARD, 1L))
  359.                     start_arrow();
  360.                 else
  361.                     beep();
  362.                 break;
  363.  
  364.               case TAB:
  365.                   if (!p_et)
  366.                     goto normalchar;
  367.                                         /* expand a tab into spaces */
  368.                 stop_arrow();
  369.                 did_ai = FALSE;
  370.                 did_si = FALSE;
  371.                 can_si = FALSE;
  372.                 insstr("                " + 16 - (p_ts - Curpos.col % p_ts));
  373.                 AppendToRedobuff("\t");
  374.                 goto redraw;
  375.  
  376.               case CR:
  377.               case NL:
  378.                 stop_arrow();
  379.                 if (State == REPLACE)           /* DMT added, 12/89 */
  380.                     delchar(FALSE);
  381.                 AppendToRedobuff(NL_STR);
  382.                 if (!Opencmd(FORWARD, TRUE))
  383.                     goto doESCkey;        /* out of memory */
  384.                 break;
  385.  
  386.               case CTRL('R'):
  387.                 /*
  388.                  * addition by mool: copy from previous line
  389.                  */
  390.                 lnum = Curpos.lnum - 1;
  391.                 goto copychar;
  392.  
  393.               case CTRL('E'):
  394.                 lnum = Curpos.lnum + 1;
  395. copychar:
  396.                 if (lnum < 1 || lnum > line_count)
  397.                 {
  398.                     beep();
  399.                     break;
  400.                 }
  401.  
  402.                 /* try to advance to the cursor column */
  403.                 temp = 0;
  404.                 ptr = (u_char *)nr2ptr(lnum);
  405.                 while (temp < Cursvcol && *ptr)
  406.                         temp += chartabsize(*ptr++, temp);
  407.  
  408.                 if (temp > Cursvcol)
  409.                         --ptr;
  410.                 if ((c = *ptr) == NUL)
  411.                 {
  412.                     beep();
  413.                     break;
  414.                 }
  415.  
  416.                 /*FALLTHROUGH*/
  417.               default:
  418. normalchar:
  419.                 if (Curpos.col > 0 && ((can_si && c == '}') || (did_si && c == '{')))
  420.                     shift_line(TRUE);
  421.                 insertchar(c);
  422.                 break;
  423.             }
  424.     }
  425. }
  426.  
  427. /*
  428.  * Next character is interpreted literally.
  429.  * A one, two or three digit decimal number is interpreted as its byte value.
  430.  * If one or two digits are entered, *nextc is set to the next character.
  431.  */
  432.     int
  433. get_literal(nextc)
  434.     int *nextc;
  435. {
  436.     u_char         cc;
  437.     u_char         nc;
  438.     int             oldstate;
  439.     int             i;
  440.  
  441.     oldstate = State;
  442.     State = NOMAPPING;        /* next characters not mapped */
  443.  
  444.     cc = 0;
  445.     for (i = 0; i < 3; ++i)
  446.     {
  447.         nc = vgetc();
  448.         if (!isdigit(nc))
  449.             break;
  450.         cc = cc * 10 + nc - '0';
  451.         nc = 0;
  452.     }
  453.     if (i == 0)        /* no number entered */
  454.     {
  455.         cc = nc;
  456.         nc = 0;
  457.     }
  458.     else if (cc == 0)        /* NUL is stored as NL */
  459.         cc = '\n';
  460.  
  461.     State = oldstate;
  462.     *nextc = nc;
  463.     return cc;
  464. }
  465.  
  466. /*
  467.  * Special characters in this context are those that need processing other
  468.  * than the simple insertion that can be performed here. This includes ESC
  469.  * which terminates the insert, and CR/NL which need special processing to
  470.  * open up a new line. This routine tries to optimize insertions performed by
  471.  * the "redo", "undo" or "put" commands, so it needs to know when it should
  472.  * stop and defer processing to the "normal" mechanism.
  473.  */
  474. #define ISSPECIAL(c)    ((c) < ' ' || (c) >= DEL)
  475.  
  476.     void
  477. insertchar(c)
  478.     unsigned    c;
  479. {
  480.     int        must_redraw = FALSE;
  481.  
  482.     stop_arrow();
  483.     /*
  484.      * If the cursor is past 'textwidth' and we are inserting a non-space,
  485.      * try to break the line in two or more pieces. If c == NUL then we have
  486.      * been called to do formatting only.
  487.      */
  488.     if (c == NUL || !isspace(c))
  489.     {
  490.         while (Cursvcol >= p_tw)
  491.         {
  492.             int        startcol;        /* Cursor column at entry */
  493.             int        wantcol;        /* column at textwidth border */
  494.             int        foundcol;        /* column for start of word */
  495.             int        mincol;            /* minimum column for break */
  496.  
  497.             if ((startcol = Curpos.col) == 0)
  498.                 break;
  499.             coladvance((int)p_tw);    /* find column of textwidth border */
  500.             wantcol = Curpos.col;
  501.             beginline((int)p_ai);            /* find start of text */
  502.             mincol = Curpos.col;
  503.  
  504.             Curpos.col = startcol - 1;
  505.             foundcol = 0;
  506.             while (Curpos.col > mincol)    /* find position to break at */
  507.             {
  508.                 if (isspace(gcharCurpos()))
  509.                 {
  510.                     foundcol = Curpos.col + 1;
  511.                     while (Curpos.col > 1 && isspace(gcharCurpos()))
  512.                         --Curpos.col;
  513.                     if (Curpos.col < wantcol)
  514.                         break;
  515.                 }
  516.                 --Curpos.col;
  517.             }
  518.  
  519.             if (foundcol == 0)    /* no spaces, cannot break line */
  520.             {
  521.                 Curpos.col = startcol;
  522.                 break;
  523.             }
  524.             Curpos.col = foundcol;
  525.             startcol -= Curpos.col;
  526.             Opencmd(FORWARD, FALSE);
  527.             Curpos.col += startcol;
  528.             curs_columns();            /* update Cursvcol */
  529.             must_redraw = TRUE;
  530.         }
  531.         if (c == NUL)        /* formatting only */
  532.             return;
  533.         if (must_redraw)
  534.             updateScreen(CURSUPD);
  535.     }
  536.  
  537.     did_ai = FALSE;
  538.     did_si = FALSE;
  539.     can_si = FALSE;
  540.  
  541.     /*
  542.      * If there's any pending input, grab up to MAX_COLUMNS at once.
  543.      * This speeds up normal text input considerably.
  544.      */
  545.     if (vpeekc() != NUL && State != REPLACE)
  546.     {
  547.         char            p[MAX_COLUMNS + 1];
  548.         int             i;
  549.  
  550.         p[0] = c;
  551.         i = 1;
  552.         while ((c = vpeekc()) != NUL && !ISSPECIAL(c) && i < MAX_COLUMNS &&
  553.                     (Cursvcol += charsize(p[i - 1])) < p_tw)
  554.             p[i++] = vgetc();
  555.         p[i] = '\0';
  556.         insstr(p);
  557.         AppendToRedobuff(p);
  558.     }
  559.     else
  560.     {
  561.         inschar(c);
  562.         AppendToRedobuff(mkstr(c));
  563.     }
  564.  
  565.     updateline();
  566. }
  567.  
  568.  
  569. /*
  570.  * start_arrow() is called when an arrow key is used in insert mode.
  571.  * It resembles hitting the <ESC> key.
  572.  */
  573.     static void
  574. start_arrow()
  575. {
  576.     if (!arrow_used)        /* something has been inserted */
  577.     {
  578.         AppendToRedobuff(ESC_STR);
  579.         arrow_used = TRUE;        /* this means we stopped the current insert */
  580.         stop_insert();
  581.     }
  582. }
  583.  
  584. /*
  585.  * stop_arrow() is called before a change is made in insert mode.
  586.  * If an arrow key has been used, start a new insertion.
  587.  */
  588.     static void
  589. stop_arrow()
  590. {
  591.     if (arrow_used)
  592.     {
  593.         u_saveCurpos();            /* errors are ignored! */
  594.         Insstart = Curpos;        /* new insertion starts here */
  595.         ResetBuffers();
  596.         AppendToRedobuff("1i");    /* pretend we start an insertion */
  597.         arrow_used = FALSE;
  598.     }
  599. }
  600.  
  601. /*
  602.  * do a few things to stop inserting
  603.  */
  604.     static void
  605. stop_insert()
  606. {
  607.     stop_redo_ins();
  608.  
  609.     /*
  610.      * save the inserted text for later redo with ^@
  611.      */
  612.     free(last_insert);
  613.     last_insert = get_inserted();
  614.     last_insert_skip = new_insert_skip;
  615.  
  616.     /*
  617.      * If we just did an auto-indent, truncate the line, and put
  618.      * the cursor back.
  619.      */
  620.     if (did_ai && !arrow_used)
  621.     {
  622.         *nr2ptr(Curpos.lnum) = NUL;
  623.         canincrease(0);
  624.         Curpos.col = 0;
  625.     }
  626.     did_ai = FALSE;
  627.     did_si = FALSE;
  628.     can_si = FALSE;
  629. }
  630.  
  631. /*
  632.  * oneright oneleft onedown oneup
  633.  *
  634.  * Move one char {right,left,down,up}.    Return TRUE when sucessful, FALSE when
  635.  * we hit a boundary (of a line, or the file).
  636.  */
  637.  
  638.     int
  639. oneright()
  640. {
  641.     char *ptr;
  642.  
  643.     ptr = pos2ptr(&Curpos);
  644.     set_want_col = TRUE;
  645.  
  646.     if (*ptr++ == NUL || *ptr == NUL)
  647.         return FALSE;
  648.     ++Curpos.col;
  649.     return TRUE;
  650. }
  651.  
  652.     int
  653. oneleft()
  654. {
  655.     set_want_col = TRUE;
  656.  
  657.     if (Curpos.col == 0)
  658.         return FALSE;
  659.     --Curpos.col;
  660.     return TRUE;
  661. }
  662.  
  663.     void
  664. beginline(flag)
  665.     int            flag;
  666. {
  667.     Curpos.col = 0;
  668.     if (flag)
  669.     {
  670.         register char *ptr;
  671.  
  672.         for (ptr = nr2ptr(Curpos.lnum); isspace(*ptr); ++ptr)
  673.             ++Curpos.col;
  674.     }
  675.     set_want_col = TRUE;
  676. }
  677.  
  678.     int
  679. oneup(n)
  680.     long n;
  681. {
  682.     if (n != 0 && Curpos.lnum == 1)
  683.         return FALSE;
  684.     if (n >= Curpos.lnum)
  685.         Curpos.lnum = 1;
  686.     else
  687.         Curpos.lnum -= n;
  688.  
  689.     if (operator == NOP)
  690.         cursupdate();                /* make sure Topline is valid */
  691.  
  692.     /* try to advance to the column we want to be at */
  693.     coladvance(Curswant);
  694.     return TRUE;
  695. }
  696.  
  697.     int
  698. onedown(n)
  699.     long n;
  700. {
  701.     if (n != 0 && Curpos.lnum == line_count)
  702.         return FALSE;
  703.     Curpos.lnum += n;
  704.     if (Curpos.lnum > line_count)
  705.         Curpos.lnum = line_count;
  706.  
  707.     if (operator == NOP)
  708.         cursupdate();                /* make sure Topline is valid */
  709.  
  710.     /* try to advance to the column we want to be at */
  711.     coladvance(Curswant);
  712.     return TRUE;
  713. }
  714.  
  715.     int
  716. onepage(dir, count)
  717.     int        dir;
  718.     long    count;
  719. {
  720.     linenr_t        lp;
  721.     long            n;
  722.  
  723.     if (line_count == 1)    /* nothing to do */
  724.         return FALSE;
  725.     for ( ; count > 0; --count)
  726.     {
  727.         if (dir == FORWARD ? (Topline >= line_count - 1) : (Topline == 1))
  728.         {
  729.             beep();
  730.             return FALSE;
  731.         }
  732.         lp = Topline;
  733.         n = 0;
  734.         if (dir == BACKWARD)
  735.         {
  736.             if (lp < line_count)
  737.                 ++lp;
  738.             Curpos.lnum = lp;
  739.         }
  740.         while (n < Rows - 1 && lp >= 1 && lp <= line_count)
  741.         {
  742.             n += plines(lp);
  743.             lp += dir;
  744.         }
  745.         if (dir == FORWARD)
  746.         {
  747.             if (--lp > 1)
  748.                 --lp;
  749.             Topline = Curpos.lnum = lp;
  750.         }
  751.         else
  752.             Topline = lp + 1;
  753.     }
  754.     beginline(TRUE);
  755.     updateScreen(VALID);
  756.     return TRUE;
  757. }
  758.  
  759.     void
  760. stuff_inserted(c, count, no_esc)
  761.     int        c;
  762.     long    count;
  763.     int        no_esc;
  764. {
  765.     u_char        *esc_ptr = NULL;
  766.     u_char        *ptr;
  767.  
  768.     if (last_insert == NULL)
  769.     {
  770.         beep();
  771.         return;
  772.     }
  773.     if (c)
  774.         stuffReadbuff(mkstr(c));
  775.     if (no_esc && (esc_ptr = (u_char *)strrchr((char *)last_insert, 27)) != NULL)
  776.         *esc_ptr = NUL;        /* remove the ESC */
  777.  
  778.             /* skip the command */
  779.     ptr = last_insert + last_insert_skip;
  780.  
  781.     do
  782.         stuffReadbuff((char *)ptr);
  783.     while (--count > 0);
  784.  
  785.     if (no_esc && esc_ptr)
  786.         *esc_ptr = 27;        /* put the ESC back */
  787. }
  788.