home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / input.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  17KB  |  883 lines

  1. /* input.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    1500 SW Park #326
  6.  *    Portland OR, 97201
  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 && !isspace(*scan); )
  333.             {
  334.             }
  335.             scan++;
  336.             key[0] = getabkey(when, ptext, markidx(cursor));
  337. #else
  338.             key[0] = getkey(when);
  339. #endif
  340. #ifndef NO_VISIBLE
  341.             if (key[0] != ctrl('O') && V_from != MARK_UNSET)
  342.             {
  343.                 msg("Can't modify text during a selection");
  344.                 beep();
  345.                 continue;
  346.             }
  347. #endif
  348.  
  349. #ifndef NO_EXTENSIONS
  350.             if (key[0] == ctrl('O'))
  351.             {
  352.                 if (inchg)
  353.                 {
  354.                     if (cursor < to)
  355.                     {
  356.                         delete(cursor, to);
  357.                         redraw(cursor, TRUE);
  358.                     }
  359.                     afterdo();
  360.                     inchg = FALSE;
  361.                 }
  362.             }
  363.             else if (key[0] != ctrl('['))
  364.             {
  365.                 if (!inchg)
  366.                 {
  367.                     beforedo(FALSE);
  368.                     inchg = TRUE;
  369.                 }
  370.             }
  371. #endif
  372.  
  373. #ifndef CRUNCH
  374.             /* if wrapmargin is set & we're past the
  375.              * warpmargin, then change the last whitespace
  376.              * characters on line into a newline
  377.              */
  378.             if (*o_wrapmargin)
  379.             {
  380.                 pfetch(markline(cursor));
  381.                 if (!ptext[markidx(cursor)]
  382.                  && idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
  383.                 {
  384.                     build = tmpblk.c;
  385.                     *build++ = '\n';
  386.                     if (*o_autoindent)
  387.                     {
  388.                         /* figure out indent for next line */
  389.                         for (scan = ptext; *scan == ' ' || *scan == '\t'; )
  390.                         {
  391.                             *build++ = *scan++;
  392.                         }
  393.                     }
  394.                     *build = '\0';
  395.  
  396.                     scan = ptext + plen;
  397.                     m = cursor & ~(BLKSIZE - 1);
  398.                     while (ptext < scan)
  399.                     {
  400.                         scan--;
  401.                         if (*scan != ' ' && *scan != '\t')
  402.                             continue;
  403.  
  404.                         /*break up line, and we do autoindent if needed*/
  405.                         change(m + (int)(scan - ptext), m + (int)(scan - ptext) + 1, tmpblk.c);
  406.  
  407.                         /* NOTE: for some reason, MSC 5.10 doesn't
  408.                          * like for these lines to be combined!!!
  409.                          */
  410.                         cursor = (cursor & ~(BLKSIZE - 1));
  411.                         cursor += BLKSIZE;
  412.                         cursor += strlen(tmpblk.c) - 1;
  413.                         cursor += plen - (int)(scan - ptext) - 1;
  414.  
  415.                         /*remove trailing spaces on previous line*/
  416.                         pfetch(markline(m));
  417.                         scan = ptext + plen;
  418.                         while (ptext < scan)
  419.                         {
  420.                             scan--;
  421.                             if (*scan != ' ' && *scan != '\t')
  422.                                 break;
  423.                         }
  424.                         delete(m + (int)(scan - ptext) + 1, m + plen);
  425.  
  426.                         break;
  427.                     }
  428.                 }
  429.             }
  430. #endif /* !CRUNCH */
  431.  
  432.             /* process it */
  433.             switch (*key)
  434.             {
  435. #ifndef NO_EXTENSIONS
  436.               case ctrl('O'): /* special movement mapped keys */
  437.                 *key = getkey(0);
  438.                 switch (*key)
  439.                 {
  440.                   case 'h':    m = m_left(cursor, 0L);        break;
  441.                   case 'j':
  442.                   case 'k':    m = m_updnto(cursor, 0L, *key);    break;
  443.                   case 'l':    m = cursor + 1;            break;
  444.                   case 'B':
  445.                   case 'b':    m = m_bword(cursor, 0L, *key);    break;
  446.                   case 'W':
  447.                   case 'w':    m = m_fword(cursor, 0L, *key, '\0');    break;
  448.                   case '^':    m = m_front(cursor, 0L);    break;
  449.                   case '$':    m = m_rear(cursor, 0L);        break;
  450.                   case ctrl('B'):
  451.                   case ctrl('F'):
  452.                         m = m_scroll(cursor, 0L, *key); break;
  453.                   case 'x':
  454. #ifndef NO_VISIBLE
  455.                         if (V_from)
  456.                             beep();
  457.                         else
  458. #endif
  459.                         ChangeText
  460.                         {
  461.                             m = v_xchar(cursor, 0L, 'x');
  462.                         }
  463.                         break;
  464.                   case 'i':    m = to = from = cursor;
  465.                         when = WHEN_VIINP + WHEN_VIREP - when;
  466.                                         break;
  467.                   case 'K':
  468.                     pfetch(markline(cursor));
  469.                     changes++; /* <- after this, we can alter ptext */
  470.                     ptext[markidx(cursor)] = 0;
  471.                     for (scan = ptext + markidx(cursor) - 1;
  472.                          scan >= ptext && isalnum(*scan);
  473.                          scan--)
  474.                     {
  475.                     }
  476.                     scan++;
  477.                     m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
  478.                     break;
  479.  
  480. # ifndef NO_VISIBLE
  481.                   case 'v':
  482.                   case 'V':
  483.                     if (V_from)
  484.                         V_from = MARK_UNSET;
  485.                     else
  486.                         V_from = cursor;
  487.                     m = from = to = cursor;
  488.                     V_linemd = (*key == 'V');
  489.                     break;
  490.  
  491.                   case 'd':
  492.                   case 'y':
  493.                   case '\\':
  494.                     /* do nothing if unmarked */
  495.                     if (!V_from)
  496.                     {
  497.                         msg("You must mark the text first");
  498.                         beep();
  499.                         break;
  500.                     }
  501.  
  502.                     /* "from" must come before "to" */
  503.                     if (V_from < cursor)
  504.                     {
  505.                         from = V_from;
  506.                         to = cursor;
  507.                     }
  508.                     else
  509.                     {
  510.                         from = cursor;
  511.                         to = V_from;
  512.                     }
  513.  
  514.                     /* we don't need V_from anymore */
  515.                     V_from = MARK_UNSET;
  516.  
  517.                     if (V_linemd)
  518.                     {
  519.                         /* adjust for line mode */
  520.                         from &= ~(BLKSIZE - 1);
  521.                         to |= (BLKSIZE - 1);
  522.                     }
  523.                     else
  524.                     {
  525.                         /* in character mode, we must
  526.                          * worry about deleting the newline
  527.                          * at the end of the last line
  528.                          */
  529.                         pfetch(markline(to));
  530.                         if (markidx(to) == plen)
  531.                             to |= (BLKSIZE - 1);
  532.                     }
  533.                     to++;
  534.  
  535.                     switch (*key)
  536.                     {
  537.                       case 'y':
  538.                         cut(from, to);
  539.                         break;
  540.  
  541.                       case 'd':
  542.                         ChangeText
  543.                         {
  544.                             cut(from, to);
  545.                             delete(from, to);
  546.                         }
  547.                         cursor = from;
  548.                         break;
  549.  
  550. #ifndef NO_POPUP
  551.                       case '\\':
  552.                         ChangeText
  553.                         {
  554.                             cursor = v_popup(from, to);
  555.                         }
  556.                         break;
  557. #endif
  558.                     }
  559.                     m = from = to = cursor;
  560.                     break;
  561.  
  562.                   case 'p':
  563.                   case 'P':
  564.                     V_from = MARK_UNSET;
  565.                     ChangeText
  566.                     {
  567.                         m = paste(cursor, (*key == 'p'), FALSE);
  568.                     }
  569.                     break;
  570. # endif /* !NO_VISIBLE */
  571.                   default:    m = MARK_UNSET;
  572.                 }
  573.  
  574.                 /* adjust the moved cursor */
  575.                 if (m != cursor)
  576.                 {
  577.                     m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? NCOL|FINL|INPM : FINL|INPM));
  578. #if 0 /*!!!*/
  579.                     if (plen && (*key == '$' || (*key == 'l' && m <= cursor)))
  580.                     {
  581.                         m++;
  582.                     }
  583. #endif
  584.                 }
  585.  
  586.                 /* if the cursor is reasonable, use it */
  587.                 if (m == MARK_UNSET)
  588.                 {
  589.                     beep();
  590.                 }
  591.                 else
  592.                 {
  593.                     from = to = cursor = m;
  594.                 }
  595.                 break;
  596.  
  597.               case ctrl('Z'):
  598.                 if (getkey(0) == ctrl('Z'))
  599.                 {
  600.                     quit = TRUE;
  601.                     goto BreakBreak;
  602.                 }
  603.                 break;
  604. #endif
  605.  
  606.               case ctrl('['):
  607.                 /* if last line contains only whitespace, then remove whitespace */
  608.                 if (*o_autoindent)
  609.                 {
  610.                     pfetch(markline(cursor));
  611.                     for (scan = ptext; isspace(*scan); scan++)
  612.                     {
  613.                     }
  614.                     if (scan > ptext && !*scan)
  615.                     {
  616.                         cursor &= ~(BLKSIZE - 1L);
  617.                         if (to < cursor + plen)
  618.                         {
  619.                             to = cursor + plen;
  620.                         }
  621.                     }
  622.                 }
  623.                 goto BreakBreak;
  624.  
  625.               case ctrl('U'):
  626.                 if (markline(cursor) == markline(from))
  627.                 {
  628.                     cursor = from;
  629.                 }
  630.                 else
  631.                 {
  632.                     cursor &= ~(BLKSIZE - 1);
  633.                 }
  634.                 break;
  635.  
  636.               case ctrl('D'):
  637.               case ctrl('T'):
  638.                 if (to > cursor)
  639.                 {
  640.                     delete(cursor, to);
  641.                 }
  642.                 mark[27] = cursor;
  643.                 cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
  644.                 if (mark[27])
  645.                 {
  646.                     cursor = mark[27];
  647.                 }
  648.                 else
  649.                 {
  650.                     cursor = m_front(cursor, 0L);
  651.                 }
  652.                 to = cursor;
  653.                 break;
  654.  
  655.               case '\b':
  656.                 if (cursor <= from)
  657.                 {
  658.                     beep();
  659.                 }
  660.                 else if (markidx(cursor) == 0)
  661.                 {
  662.                     cursor -= BLKSIZE;
  663.                     pfetch(markline(cursor));
  664.                     cursor += plen;
  665.                 }
  666.                 else
  667.                 {
  668.                     cursor--;
  669.                 }
  670.                 break;
  671.  
  672.               case ctrl('W'):
  673.                 m = m_bword(cursor, 1L, 'b');
  674.                 if (markline(m) == markline(cursor) && m >= from)
  675.                 {
  676.                     cursor = m;
  677.                     if (from > cursor)
  678.                     {
  679.                         from = cursor;
  680.                     }
  681.                 }
  682.                 else
  683.                 {
  684.                     beep();
  685.                 }
  686.                 break;
  687.  
  688.               case '\n':
  689. #if OSK
  690.               case '\l':
  691. #else                  
  692.               case '\r':
  693. #endif
  694.                 build = tmpblk.c;
  695.                 *build++ = '\n';
  696.                 if (*o_autoindent)
  697.                 {
  698.                     /* figure out indent for next line */
  699.                     pfetch(markline(cursor));
  700.                     for (scan = ptext; *scan == ' ' || *scan == '\t'; )
  701.                     {
  702.                         *build++ = *scan++;
  703.                     }
  704.  
  705.                     /* remove indent from this line, if blank */
  706.                     if ((int)(scan - ptext) == markidx(cursor) && plen > 0)
  707.                     {
  708.                         to = cursor &= ~(BLKSIZE - 1);
  709. #if 1
  710.                         delete(cursor, cursor + (int)(scan - ptext));
  711. #else
  712.                         delete(cursor, cursor + plen);
  713. #endif
  714.                     }
  715.  
  716. #if 0
  717.                     /* Advance "to" past whitespace at the cursor.
  718.                      * This is done so that if we insert a newline
  719.                      * before whitespace, we can delete that whitespace
  720.                      * from the front of the new line when we add
  721.                      * the carefully calculated indent string to it.
  722.                      */
  723.                     if (to == cursor)
  724.                     {
  725.                         for (scan = ptext + markidx(cursor); *scan == ' ' || *scan == '\t'; scan++, to++)
  726.                         {
  727.                         }
  728.                     }
  729. #endif
  730.                 }
  731.                 *build = 0;
  732.                 if (cursor >= to && when != WHEN_VIREP)
  733.                 {
  734.                     add(cursor, tmpblk.c);
  735.                 }
  736.                 else
  737.                 {
  738.                     change(cursor, to, tmpblk.c);
  739.                 }
  740.                 redraw(cursor, TRUE);
  741.                 to = cursor = (cursor & ~(BLKSIZE - 1))
  742.                         + BLKSIZE
  743.                         + (int)(build - tmpblk.c) - 1;
  744.                 break;
  745.  
  746.               case ctrl('A'):
  747.               case ctrl('P'):
  748.                 if (cursor < to)
  749.                 {
  750.                     delete(cursor, to);
  751.                 }
  752.                 if (*key == ctrl('A'))
  753.                 {
  754.                     cutname('.');
  755.                 }
  756.                 m = paste(cursor, FALSE, TRUE);
  757.                 if (m != MARK_UNSET)
  758.                 {
  759.                     to = cursor = m + 1L;
  760.                 }
  761.                 break;
  762.  
  763.               case ctrl('V'):
  764.                 if (cursor >= to && when != WHEN_VIREP)
  765.                 {
  766.                     add(cursor, "^");
  767.                 }
  768.                 else
  769.                 {
  770.                     change(cursor, to, "^");
  771.                     to = cursor + 1;
  772.                 }
  773.                 redraw(cursor, TRUE);
  774.                 *key = getkey(0);
  775.                 if (*key == '\n')
  776.                 {
  777.                     /* '\n' too hard to handle */
  778. #if OSK
  779.                     *key = '\l';
  780. #else
  781.                     *key = '\r';
  782. #endif
  783.                 }
  784.                 change(cursor, cursor + 1, key);
  785.                 cursor++;
  786.                 if (cursor > to)
  787.                 {
  788.                     to = cursor;
  789.                 }
  790.                 break;
  791.  
  792.               case ctrl('L'):
  793.               case ctrl('R'):
  794.                 redraw(MARK_UNSET, FALSE);
  795.                 break;
  796.  
  797.               default:
  798.                 if (cursor >= to && when != WHEN_VIREP)
  799.                 {
  800.                     add(cursor, key);
  801.                     cursor++;
  802.                     to = cursor;
  803.                 }
  804.                 else
  805.                 {
  806.                     pfetch(markline(cursor));
  807.                     if (markidx(cursor) == plen)
  808.                     {
  809.                         add(cursor, key);
  810.                     }
  811.                     else
  812.                     {
  813. #ifndef NO_DIGRAPH
  814.                         *key = digraph(ptext[markidx(cursor)], *key);
  815. #endif
  816.                         change(cursor, cursor + 1, key);
  817.                     }
  818.                     cursor++;
  819.                 }
  820. #ifndef NO_SHOWMATCH
  821.                 /* show matching "({[" if necessary */
  822.                 if (*o_showmatch && strchr(")}]", *key))
  823.                 {
  824.                     redraw(cursor, TRUE);
  825.                     m = m_match(cursor - 1, 0L);
  826.                     if (markline(m) >= topline
  827.                      && markline(m) <= botline)
  828.                     {
  829.                         redraw(m, TRUE);
  830.                         refresh();
  831.                         sleep(1);
  832.                     }
  833.                 }
  834. #endif
  835.             } /* end switch(*key) */
  836.         } /* end for(;;) */
  837. BreakBreak:;
  838.         /* delete any excess characters */
  839.         if (cursor < to)
  840.         {
  841. #ifndef NO_EXTENSIONS
  842.             /* if we aren't in the middle of a change, start one! */
  843.             if (!inchg)
  844.             {
  845.                 beforedo(FALSE);
  846.                 inchg = TRUE;
  847.             }
  848. #endif
  849.             delete(cursor, to);
  850.         }
  851.  
  852.     } /* end if doingdot else */
  853.  
  854.     /* put the new text into a cut buffer for possible reuse */
  855.     if (!doingdot)
  856.     {
  857.         blksync();
  858.         cutname('.');
  859.         cut(from, cursor);
  860.     }
  861.  
  862.     /* move to last char that we inputted, unless it was newline */
  863.     if (markidx(cursor) != 0)
  864.     {
  865.         cursor--;
  866.     }
  867.     redraw(cursor, FALSE);
  868.  
  869. #ifndef NO_EXTENSIONS
  870.     if (quit)
  871.     {
  872.         /* if this is a nested "do", then cut it short */
  873.         abortdo();
  874.  
  875.         /* exit, unless we can't write out the file */
  876.         cursor = v_xit(cursor, 0L, 'Z');
  877.     }
  878. #endif
  879.  
  880.     rptlines = 0L;
  881.     return cursor;
  882. }
  883.