home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / text_ed / elv16b2 / st / input.c < prev    next >
C/C++ Source or Header  |  1992-05-13  |  17KB  |  868 lines

  1. /* input.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the input() function, which implements vi's INPUT mode.
  12.  * It also contains the code that supports digraphs.
  13.  */
  14.  
  15. #include "config.h"
  16. #include "ctype.h"
  17. #include "vi.h"
  18.  
  19.  
  20. #ifndef NO_DIGRAPH
  21. static struct _DIG
  22. {
  23.     struct _DIG    *next;
  24.     char        key1;
  25.     char        key2;
  26.     char        dig;
  27.     char        save;
  28. } *digs;
  29.  
  30. char digraph(key1, key2)
  31.     int    key1;    /* the underlying character */
  32.     int    key2;    /* the second character */
  33. {
  34.     int        newkey;
  35.     REG struct _DIG    *dp;
  36.  
  37.     /* if digraphs are disabled, then just return the new char */
  38.     if (!*o_digraph)
  39.     {
  40.         return key2;
  41.     }
  42.  
  43.     /* remember the new key, so we can return it if this isn't a digraph */
  44.     newkey = key2;
  45.  
  46.     /* sort key1 and key2, so that their original order won't matter */
  47.     if (key1 > key2)
  48.     {
  49.         key2 = key1;
  50.         key1 = newkey;
  51.     }
  52.  
  53.     /* scan through the digraph chart */
  54.     for (dp = digs;
  55.          dp && (dp->key1 != key1 || dp->key2 != key2);
  56.          dp = dp->next)
  57.     {
  58.     }
  59.  
  60.     /* if this combination isn't in there, just use the new key */
  61.     if (!dp)
  62.     {
  63.         return newkey;
  64.     }
  65.  
  66.     /* else use the digraph key */
  67.     return dp->dig;
  68. }
  69.  
  70. /* this function lists or defines digraphs */
  71. void do_digraph(bang, extra)
  72.     int    bang;
  73.     char    extra[];
  74. {
  75.     int        dig;
  76.     REG struct _DIG    *dp;
  77.     struct _DIG    *prev;
  78.     static int    user_defined = FALSE; /* boolean: are all later digraphs user-defined? */
  79.     char        listbuf[8];
  80.  
  81.     /* if "extra" is NULL, then we've reached the end of the built-ins */
  82.     if (!extra)
  83.     {
  84.         user_defined = TRUE;
  85.         return;
  86.     }
  87.  
  88.     /* if no args, then display the existing digraphs */
  89.     if (*extra < ' ')
  90.     {
  91.         listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
  92.         listbuf[7] = '\0';
  93.         for (dig = 0, dp = digs; dp; dp = dp->next)
  94.         {
  95.             if (dp->save || bang)
  96.             {
  97.                 dig += 7;
  98.                 if (dig >= COLS)
  99.                 {
  100.                     addch('\n');
  101.                     exrefresh();
  102.                     dig = 7;
  103.                 }
  104.                 listbuf[3] = dp->key1;
  105.                 listbuf[4] = dp->key2;
  106.                 listbuf[6] = dp->dig;
  107.                 qaddstr(listbuf);
  108.             }
  109.         }
  110.         addch('\n');
  111.         exrefresh();
  112.         return;
  113.     }
  114.  
  115.     /* make sure we have at least two characters */
  116.     if (!extra[1])
  117.     {
  118.         msg("Digraphs must be composed of two characters");
  119.         return;
  120.     }
  121.  
  122.     /* sort key1 and key2, so that their original order won't matter */
  123.     if (extra[0] > extra[1])
  124.     {
  125.         dig = extra[0];
  126.         extra[0] = extra[1];
  127.         extra[1] = dig;
  128.     }
  129.  
  130.     /* locate the new digraph character */
  131.     for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
  132.     {
  133.     }
  134.     dig = extra[dig];
  135.     if (!bang && dig)
  136.     {
  137.         dig |= 0x80;
  138.     }
  139.  
  140.     /* search for the digraph */
  141.     for (prev = (struct _DIG *)0, dp = digs;
  142.          dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
  143.          prev = dp, dp = dp->next)
  144.     {
  145.     }
  146.  
  147.     /* deleting the digraph? */
  148.     if (!dig)
  149.     {
  150.         if (!dp)
  151.         {
  152. #ifndef CRUNCH
  153.             msg("%c%c not a digraph", extra[0], extra[1]);
  154. #endif
  155.             return;
  156.         }
  157.         if (prev)
  158.             prev->next = dp->next;
  159.         else
  160.             digs = dp->next;
  161.         _free_(dp);
  162.         return;
  163.     }
  164.  
  165.     /* if necessary, create a new digraph struct for the new digraph */
  166.     if (dig && !dp)
  167.     {
  168.         dp = (struct _DIG *)malloc(sizeof *dp);
  169.         if (!dp)
  170.         {
  171.             msg("Out of space in the digraph table");
  172.             return;
  173.         }
  174.         if (prev)
  175.             prev->next = dp;
  176.         else
  177.             digs = dp;
  178.         dp->next = (struct _DIG *)0;
  179.     }
  180.  
  181.     /* assign it the new digraph value */
  182.     dp->key1 = extra[0];
  183.     dp->key2 = extra[1];
  184.     dp->dig = dig;
  185.     dp->save = user_defined;
  186. }
  187.  
  188. # ifndef NO_MKEXRC
  189. void savedigs(fd)
  190.     int        fd;
  191. {
  192.     static char    buf[] = "digraph! XX Y\n";
  193.     REG struct _DIG    *dp;
  194.  
  195.     for (dp = digs; dp; dp = dp->next)
  196.     {
  197.         if (dp->save)
  198.         {
  199.             buf[9] = dp->key1;
  200.             buf[10] = dp->key2;
  201.             buf[12] = dp->dig;
  202.             write(fd, buf, (unsigned)14);
  203.         }
  204.     }
  205. }
  206. # endif
  207. #endif
  208.  
  209.  
  210. /* This function allows the user to replace an existing (possibly zero-length)
  211.  * chunk of text with typed-in text.  It returns the MARK of the last character
  212.  * that the user typed in.
  213.  */
  214. MARK input(from, to, when, delta)
  215.     MARK    from;    /* where to start inserting text */
  216.     MARK    to;    /* extent of text to delete */
  217.     int    when;    /* either WHEN_VIINP or WHEN_VIREP */
  218.     int    delta;    /* 1 to take indent from lower line, -1 for upper, 0 for none */
  219. {
  220.     char    key[2];    /* key char followed by '\0' char */
  221.     char    *build;    /* used in building a newline+indent string */
  222.     char    *scan;    /* used while looking at the indent chars of a line */
  223.     MARK    m;    /* some place in the text */
  224. #ifndef NO_EXTENSIONS
  225.     int    quit = FALSE;    /* boolean: are we exiting after this? */
  226.     int    inchg;    /* boolean: have we done a "beforedo()" yet? */
  227. #endif
  228.  
  229. #ifdef DEBUG
  230.     /* if "from" and "to" are reversed, complain */
  231.     if (from > to)
  232.     {
  233.         msg("ERROR: input(%ld:%d, %ld:%d)",
  234.             markline(from), markidx(from),
  235.             markline(to), markidx(to));
  236.         return MARK_UNSET;
  237.     }
  238. #endif
  239.  
  240.     key[1] = 0;
  241.  
  242.     /* if we're replacing text with new text, save the old stuff */
  243.     /* (Alas, there is no easy way to save text for replace mode) */
  244.     if (from != to)
  245.     {
  246.         cut(from, to);
  247.     }
  248.  
  249.     /* if doing a dot command, then reuse the previous text */
  250.     if (doingdot)
  251.     {
  252.         ChangeText
  253.         {
  254.             /* delete the text that's there now */
  255.             if (from != to)
  256.             {
  257.                 delete(from, to);
  258.             }
  259.  
  260.             /* insert the previous text */
  261.             cutname('.');
  262.             cursor = paste(from, FALSE, TRUE) + 1L;
  263.         }
  264.     }
  265.     else /* interactive version */
  266.     {
  267.         /* assume that whoever called this already did a beforedo() */
  268. #ifndef NO_EXTENSIONS
  269.         inchg = TRUE;
  270. #endif
  271.  
  272.         /* if doing a change within the line... */
  273.         if (from != to && markline(from) == markline(to))
  274.         {
  275.             /* mark the end of the text with a "$" */
  276.             change(to - 1, to, "$");
  277.         }
  278.         else
  279.         {
  280.             /* delete the old text right off */
  281.             if (from != to)
  282.             {
  283.                 delete(from, to);
  284.             }
  285.             to = from;
  286.         }
  287.  
  288.         /* handle autoindent of the first line, maybe */
  289.         cursor = from;
  290.         m = cursor + MARK_AT_LINE(delta);
  291.         if (delta != 0 && *o_autoindent && markidx(m) == 0
  292.          && markline(m) >= 1L && markline(m) <= nlines)
  293.         {
  294.             /* Only autoindent blank lines. */
  295.             pfetch(markline(cursor));
  296.             if (plen == 0)
  297.             {
  298.                 /* Okay, we really want to autoindent */
  299.                 pfetch(markline(m));
  300.                 for (scan = ptext, build = tmpblk.c;
  301.                      *scan == ' ' || *scan == '\t';
  302.                      )
  303.                 {
  304.                     *build++ = *scan++;
  305.                 }
  306.                 if (build > tmpblk.c)
  307.                 {
  308.                     *build = '\0';
  309.                     add(cursor, tmpblk.c);
  310.                     cursor += (int)(build - tmpblk.c);
  311.                     if (cursor > to)
  312.                         to = cursor;
  313.                 }
  314.             }
  315.         }
  316.  
  317.         /* repeatedly add characters from the user */
  318.         for (;;)
  319.         {
  320.             /* Get a character */
  321.             redraw(cursor, TRUE);
  322. #ifdef DEBUG2
  323.             msg("cursor=%ld.%d, to=%ld.%d",
  324.                 markline(cursor), markidx(cursor),
  325.                 markline(to), markidx(to));
  326. #endif
  327. #ifndef NO_ABBR
  328.             pfetch(markline(cursor));
  329.             build = ptext;
  330.             if (pline == markline(from))
  331.                 build += markidx(from);
  332.             for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
  333.             {
  334.             }
  335.             scan++;
  336.             key[0] = getabkey(when, scan, (int)(ptext + markidx(cursor) - scan));
  337. #else
  338.             key[0] = getkey(when);
  339. #endif
  340. #ifndef NO_VISIBLE
  341. #if 0
  342.             /* hmm :-)  -nox */
  343.             if (key[0] != '\0' && V_from != MARK_UNSET)
  344. #else
  345.             if (*key && *key != ctrl('O') && V_from != MARK_UNSET)
  346. #endif
  347.             {
  348.                 msg("Can't modify text during a selection");
  349.                 beep();
  350.                 continue;
  351.             }
  352. #endif
  353.  
  354. #ifndef NO_EXTENSIONS
  355.             if (key[0] == ctrl('O'))
  356.             {
  357.                 if (inchg)
  358.                 {
  359.                     if (cursor < to)
  360.                     {
  361.                         delete(cursor, to);
  362.                         redraw(cursor, TRUE);
  363.                     }
  364.                     afterdo();
  365.                     inchg = FALSE;
  366.                 }
  367.             }
  368.             else if (key[0] != ctrl('['))
  369.             {
  370.                 if (!inchg)
  371.                 {
  372.                     beforedo(FALSE);
  373.                     inchg = TRUE;
  374.                 }
  375.             }
  376. #endif
  377.  
  378. #ifndef CRUNCH
  379.             /* if wrapmargin is set & we're past the
  380.              * warpmargin, then change the last whitespace
  381.              * characters on line into a newline
  382.              */
  383.             if (*o_wrapmargin != 0)
  384.             {
  385.                 pfetch(markline(cursor));
  386.                 if (plen == idx2col(cursor, ptext, TRUE)
  387.                  && plen > COLS - (*o_wrapmargin & 0xff))
  388.                 {
  389.                     build = tmpblk.c;
  390.                     *build++ = '\n';
  391.                     if (*o_autoindent)
  392.                     {
  393.                         /* figure out indent for next line */
  394.                         for (scan = ptext; *scan == ' ' || *scan == '\t'; )
  395.                         {
  396.                             *build++ = *scan++;
  397.                         }
  398.                     }
  399.                     *build = '\0';
  400.  
  401.                     scan = ptext + plen;
  402.                     m = cursor & ~(BLKSIZE - 1);
  403.                     while (ptext < scan)
  404.                     {
  405.                         scan--;
  406.                         if (*scan != ' ' && *scan != '\t')
  407.                             continue;
  408.  
  409.                         /*break up line, and we do autoindent if needed*/
  410.                         change(m + (int)(scan - ptext), m + (int)(scan - ptext) + 1, tmpblk.c);
  411.  
  412.                         /* NOTE: for some reason, MSC 5.10 doesn't
  413.                          * like for these lines to be combined!!!
  414.                          */
  415.                         cursor = (cursor & ~(BLKSIZE - 1));
  416.                         cursor += BLKSIZE;
  417.                         cursor += strlen(tmpblk.c) - 1;
  418.                         cursor += plen - (int)(scan - ptext) - 1;
  419.  
  420.                         /*remove trailing spaces on previous line*/
  421.                         pfetch(markline(m));
  422.                         scan = ptext + plen;
  423.                         while (ptext < scan)
  424.                         {
  425.                             scan--;
  426.                             if (*scan != ' ' && *scan != '\t')
  427.                                 break;
  428.                         }
  429.                         delete(m + (int)(scan - ptext) + 1, m + plen);
  430.  
  431.                         break;
  432.                     }
  433.                 }
  434.             }
  435. #endif /* !CRUNCH */
  436.  
  437.             /* process it */
  438.             switch (*key)
  439.             {
  440. #ifndef NO_EXTENSIONS
  441.               case ctrl('O'): /* special movement mapped keys */
  442.                 *key = getkey(0);
  443.                 switch (*key)
  444.                 {
  445.                   case 'h':    m = m_left(cursor, 0L);        break;
  446.                   case 'j':
  447.                   case 'k':    m = m_updnto(cursor, 0L, *key);    break;
  448.                   case 'l':    m = cursor + 1;            break;
  449.                   case 'B':
  450.                   case 'b':    m = m_bword(cursor, 0L, *key);    break;
  451.                   case 'W':
  452.                   case 'w':    m = m_fword(cursor, 0L, *key, '\0');    break;
  453.                   case '^':    m = m_front(cursor, 0L);    break;
  454.                   case '$':    m = m_rear(cursor, 0L);        break;
  455.                   case ctrl('B'):
  456.                   case ctrl('F'):
  457.                         m = m_scroll(cursor, 0L, *key); break;
  458.                   case 'x':
  459. #ifndef NO_VISIBLE
  460.                         if (V_from)
  461.                             beep();
  462.                         else
  463. #endif
  464.                         ChangeText
  465.                         {
  466.                             m = v_xchar(cursor, 0L, 'x');
  467.                         }
  468.                         break;
  469.                   case 'i':    m = to = from = cursor;
  470.                         when = WHEN_VIINP + WHEN_VIREP - when;
  471.                                         break;
  472.                   case 'K':
  473.                     pfetch(markline(cursor));
  474.                     changes++; /* <- after this, we can alter ptext */
  475.                     ptext[markidx(cursor)] = 0;
  476.                     for (scan = ptext + markidx(cursor) - 1;
  477.                          scan >= ptext && isalnum(*scan);
  478.                          scan--)
  479.                     {
  480.                     }
  481.                     scan++;
  482.                     m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
  483.                     break;
  484.  
  485. # ifndef NO_VISIBLE
  486.                   case 'v':
  487.                   case 'V':
  488.                     if (V_from)
  489.                         V_from = MARK_UNSET;
  490.                     else
  491.                         V_from = cursor;
  492.                     m = from = to = cursor;
  493.                     V_linemd = (*key == 'V');
  494.                     break;
  495.  
  496.                   case 'd':
  497.                   case 'y':
  498.                   case '\\':
  499.                     /* do nothing if unmarked */
  500.                     if (!V_from)
  501.                     {
  502.                         msg("You must mark the text first");
  503.                         beep();
  504.                         break;
  505.                     }
  506.  
  507.                     /* "from" must come before "to" */
  508.                     if (V_from < cursor)
  509.                     {
  510.                         from = V_from;
  511.                         to = cursor;
  512.                     }
  513.                     else
  514.                     {
  515.                         from = cursor;
  516.                         to = V_from;
  517.                     }
  518.  
  519.                     /* we don't need V_from anymore */
  520.                     V_from = MARK_UNSET;
  521.  
  522.                     if (V_linemd)
  523.                     {
  524.                         /* adjust for line mode */
  525.                         from &= ~(BLKSIZE - 1);
  526.                         to |= (BLKSIZE - 1);
  527.                     }
  528.                     else
  529.                     {
  530.                         /* in character mode, we must
  531.                          * worry about deleting the newline
  532.                          * at the end of the last line
  533.                          */
  534.                         pfetch(markline(to));
  535.                         if (markidx(to) == plen)
  536.                             to |= (BLKSIZE - 1);
  537.                     }
  538.                     to++;
  539.  
  540.                     switch (*key)
  541.                     {
  542.                       case 'y':
  543.                         cut(from, to);
  544.                         break;
  545.  
  546.                       case 'd':
  547.                         ChangeText
  548.                         {
  549.                             cut(from, to);
  550.                             delete(from, to);
  551.                         }
  552.                         cursor = from;
  553.                         break;
  554.  
  555. #ifndef NO_POPUP
  556.                       case '\\':
  557.                         ChangeText
  558.                         {
  559.                             cursor = v_popup(from, to);
  560.                         }
  561.                         break;
  562. #endif
  563.                     }
  564.                     m = from = to = cursor;
  565.                     break;
  566.  
  567.                   case 'p':
  568.                   case 'P':
  569.                     V_from = MARK_UNSET;
  570.                     ChangeText
  571.                     {
  572.                         m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
  573.                     }
  574.                     break;
  575. # endif /* !NO_VISIBLE */
  576.                   default:    m = MARK_UNSET;
  577.                 }
  578.  
  579.                 /* adjust the moved cursor */
  580.                 if (m != cursor)
  581.                 {
  582.                     m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? NCOL|FINL : FINL));
  583. #if 0
  584.                     /* try typing characters after <cursor right> on an empty line :-)  -nox */
  585.                     if (*key == '$' || (*key == 'l' && m <= cursor))
  586. #else
  587.                     if (plen && (*key == '$' || (*key == 'l' && m <= cursor)))
  588. #endif
  589.                     {
  590.                         m++;
  591.                     }
  592.                 }
  593.  
  594.                 /* if the cursor is reasonable, use it */
  595.                 if (m == MARK_UNSET)
  596.                 {
  597.                     beep();
  598.                 }
  599.                 else
  600.                 {
  601.                     from = to = cursor = m;
  602.                 }
  603.                 break;
  604.  
  605.               case ctrl('Z'):
  606.                 if (getkey(0) == ctrl('Z'))
  607.                 {
  608.                     quit = TRUE;
  609.                     goto BreakBreak;
  610.                 }
  611.                 break;
  612. #endif
  613.  
  614.               case ctrl('['):
  615.                 /* if last line contains only whitespace, then remove whitespace */
  616.                 if (*o_autoindent)
  617.                 {
  618.                     pfetch(markline(cursor));
  619.                     for (scan = ptext; isspace(*scan); scan++)
  620.                     {
  621.                     }
  622.                     if (scan > ptext && !*scan)
  623.                     {
  624.                         cursor &= ~(BLKSIZE - 1L);
  625.                         if (to < cursor + plen)
  626.                         {
  627.                             to = cursor + plen;
  628.                         }
  629.                     }
  630.                 }
  631.                 goto BreakBreak;
  632.  
  633.               case ctrl('U'):
  634.                 if (markline(cursor) == markline(from))
  635.                 {
  636.                     cursor = from;
  637.                 }
  638.                 else
  639.                 {
  640.                     cursor &= ~(BLKSIZE - 1);
  641.                 }
  642.                 break;
  643.  
  644.               case ctrl('D'):
  645.               case ctrl('T'):
  646.                 if (to > cursor)
  647.                 {
  648.                     delete(cursor, to);
  649.                 }
  650.                 mark[27] = cursor;
  651.                 cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
  652.                 if (mark[27])
  653.                 {
  654.                     cursor = mark[27];
  655.                 }
  656.                 else
  657.                 {
  658.                     cursor = m_front(cursor, 0L);
  659.                 }
  660.                 to = cursor;
  661.                 break;
  662.  
  663.               case '\b':
  664.                 if (cursor <= from)
  665.                 {
  666.                     beep();
  667.                 }
  668.                 else if (markidx(cursor) == 0)
  669.                 {
  670.                     cursor -= BLKSIZE;
  671.                     pfetch(markline(cursor));
  672.                     cursor += plen;
  673.                 }
  674.                 else
  675.                 {
  676.                     cursor--;
  677.                 }
  678.                 break;
  679.  
  680.               case ctrl('W'):
  681.                 m = m_bword(cursor, 1L, 'b');
  682.                 if (markline(m) == markline(cursor) && m >= from)
  683.                 {
  684.                     cursor = m;
  685.                     if (from > cursor)
  686.                     {
  687.                         from = cursor;
  688.                     }
  689.                 }
  690.                 else
  691.                 {
  692.                     beep();
  693.                 }
  694.                 break;
  695.  
  696.               case '\n':
  697. #if OSK
  698.               case '\l':
  699. #else                  
  700.               case '\r':
  701. #endif
  702.                 build = tmpblk.c;
  703.                 *build++ = '\n';
  704.                 if (*o_autoindent)
  705.                 {
  706.                     /* figure out indent for next line */
  707.                     pfetch(markline(cursor));
  708.                     for (scan = ptext; *scan == ' ' || *scan == '\t'; )
  709.                     {
  710.                         *build++ = *scan++;
  711.                     }
  712.  
  713.                     /* remove indent from this line, if blank */
  714.                     if ((int)(scan - ptext) >= markidx(cursor) && plen > 0)
  715.                     {
  716.                         to = cursor &= ~(BLKSIZE - 1);
  717.                         delete(cursor, cursor + (int)(scan - ptext));
  718.                     }
  719.                 }
  720.                 *build = 0;
  721.                 if (cursor >= to && when != WHEN_VIREP)
  722.                 {
  723.                     add(cursor, tmpblk.c);
  724.                 }
  725.                 else
  726.                 {
  727.                     change(cursor, to, tmpblk.c);
  728.                 }
  729.                 redraw(cursor, TRUE);
  730.                 to = cursor = (cursor & ~(BLKSIZE - 1))
  731.                         + BLKSIZE
  732.                         + (int)(build - tmpblk.c) - 1;
  733.                 break;
  734.  
  735.               case ctrl('A'):
  736.               case ctrl('P'):
  737.                 if (cursor < to)
  738.                 {
  739.                     delete(cursor, to);
  740.                 }
  741.                 if (*key == ctrl('A'))
  742.                 {
  743.                     cutname('.');
  744.                 }
  745.                 to = cursor = paste(cursor, FALSE, TRUE) + 1L;
  746.                 break;
  747.  
  748.               case ctrl('V'):
  749.                 if (cursor >= to && when != WHEN_VIREP)
  750.                 {
  751.                     add(cursor, "^");
  752.                 }
  753.                 else
  754.                 {
  755.                     change(cursor, to, "^");
  756.                     to = cursor + 1;
  757.                 }
  758.                 redraw(cursor, TRUE);
  759.                 *key = getkey(0);
  760.                 if (*key == '\n')
  761.                 {
  762.                     /* '\n' too hard to handle */
  763. #if OSK
  764.                     *key = '\l';
  765. #else
  766.                     *key = '\r';
  767. #endif
  768.                 }
  769.                 change(cursor, cursor + 1, key);
  770.                 cursor++;
  771.                 if (cursor > to)
  772.                 {
  773.                     to = cursor;
  774.                 }
  775.                 break;
  776.  
  777.               case ctrl('L'):
  778.               case ctrl('R'):
  779.                 redraw(MARK_UNSET, FALSE);
  780.                 break;
  781.  
  782.               default:
  783.                 if (cursor >= to && when != WHEN_VIREP)
  784.                 {
  785.                     add(cursor, key);
  786.                     cursor++;
  787.                     to = cursor;
  788.                 }
  789.                 else
  790.                 {
  791.                     pfetch(markline(cursor));
  792.                     if (markidx(cursor) == plen)
  793.                     {
  794.                         add(cursor, key);
  795.                     }
  796.                     else
  797.                     {
  798. #ifndef NO_DIGRAPH
  799.                         *key = digraph(ptext[markidx(cursor)], *key);
  800. #endif
  801.                         change(cursor, cursor + 1, key);
  802.                     }
  803.                     cursor++;
  804.                 }
  805. #ifndef NO_SHOWMATCH
  806.                 /* show matching "({[" if necessary */
  807.                 if (*o_showmatch && strchr(")}]", *key))
  808.                 {
  809.                     redraw(cursor, TRUE);
  810.                     m = m_match(cursor - 1, 0L);
  811.                     if (markline(m) >= topline
  812.                      && markline(m) <= botline)
  813.                     {
  814.                         redraw(m, TRUE);
  815.                         refresh();
  816.                         sleep(1);
  817.                     }
  818.                 }
  819. #endif
  820.             } /* end switch(*key) */
  821.         } /* end for(;;) */
  822. BreakBreak:;
  823.         /* delete any excess characters */
  824.         if (cursor < to)
  825.         {
  826. #ifndef NO_EXTENSIONS
  827.             /* if we aren't in the middle of a change, start one! */
  828.             if (!inchg)
  829.             {
  830.                 beforedo(FALSE);
  831.                 inchg = TRUE;
  832.             }
  833. #endif
  834.             delete(cursor, to);
  835.         }
  836.  
  837.     } /* end if doingdot else */
  838.  
  839.     /* put the new text into a cut buffer for possible reuse */
  840.     if (!doingdot)
  841.     {
  842.         blksync();
  843.         cutname('.');
  844.         cut(from, cursor);
  845.     }
  846.  
  847.     /* move to last char that we inputted, unless it was newline */
  848.     if (markidx(cursor) != 0)
  849.     {
  850.         cursor--;
  851.     }
  852.     redraw(cursor, FALSE);
  853.  
  854. #ifndef NO_EXTENSIONS
  855.     if (quit)
  856.     {
  857.         /* if this is a nested "do", then cut it short */
  858.         abortdo();
  859.  
  860.         /* exit, unless we can't write out the file */
  861.         cursor = v_xit(cursor, 0L, 'Z');
  862.     }
  863. #endif
  864.  
  865.     rptlines = 0L;
  866.     return cursor;
  867. }
  868.