home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elvis_1.4.tar.Z / elvis_1.4.tar / input.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  16KB  |  818 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 <ctype.h>
  16. #include "config.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.     char    key1;    /* the underlying character */
  32.     char    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. #ifndef NO_ABBR
  211. static struct _AB
  212. {
  213.     struct _AB    *next;
  214.     char        *large;        /* the expanded form */
  215.     char        small[1];    /* the abbreviated form (appended to struct) */
  216. }
  217.     *abbrev;
  218.  
  219. /* This functions lists or defines abbreviations */
  220. void do_abbr(extra)
  221.     char    *extra;
  222. {
  223.     int        smlen;    /* length of the small form */
  224.     int        lrg;    /* index of the start of the large form */
  225.     REG struct _AB    *ab;    /* used to move through the abbrev list */
  226.     struct _AB    *prev;
  227.  
  228.     /* no arguments? */
  229.     if (!*extra)
  230.     {
  231.         /* list all current abbreviations */
  232.         for (ab = abbrev; ab; ab = ab->next)
  233.         {
  234.             qaddstr("abbr ");
  235.             qaddstr(ab->small);
  236.             qaddch(' ');
  237.             qaddstr(ab->large);
  238.             addch('\n');
  239.             exrefresh();
  240.         }
  241.         return;
  242.     }
  243.  
  244.     /* else one or more arguments.  Parse the first & look up in abbrev[] */
  245.     for (smlen = 0; extra[smlen] && isalnum(extra[smlen]); smlen++)
  246.     {
  247.     }
  248.     for (prev = (struct _AB *)0, ab = abbrev; ab; prev = ab, ab = ab->next)
  249.     {
  250.         if (!strncmp(extra, ab->small, smlen) && !ab->small[smlen])
  251.         {
  252.             break;
  253.         }
  254.     }
  255.  
  256.     /* locate the start of the large form, if any */
  257.     for (lrg = smlen; extra[lrg] && isascii(extra[lrg]) && isspace(extra[lrg]); lrg++)
  258.     {
  259.     }
  260.  
  261.     /* only one arg? */
  262.     if (!extra[lrg])
  263.     {
  264.         /* trying to undo an abbreviation which doesn't exist? */
  265.         if (!ab)
  266.         {
  267. #ifndef CRUNCH
  268.             msg("\"%s\" not an abbreviation", extra);
  269. #endif
  270.             return;
  271.         }
  272.  
  273.         /* undo the abbreviation */
  274.         if (prev)
  275.             prev->next = ab->next;
  276.         else
  277.             abbrev = ab->next;
  278.         free(ab->large);
  279.         free(ab);
  280.  
  281.         return;
  282.     }
  283.  
  284.     /* multiple args - [re]define an abbreviation */
  285.     if (ab)
  286.     {
  287.         /* redefining - free the old large form */
  288.         free(ab->large);
  289.     }
  290.     else
  291.     {
  292.         /* adding a new definition - make a new struct */
  293.         ab = (struct _AB *)malloc((unsigned)(smlen + sizeof *ab));
  294. #ifndef CRUNCH
  295.         if (!ab)
  296.         {
  297.             msg("Out of memory -- Sorry");
  298.             return;
  299.         }
  300. #endif
  301.         strncpy(ab->small, extra, smlen);
  302.         ab->small[smlen] = '\0';
  303.         ab->next = (struct _AB *)0;
  304.         if (prev)
  305.             prev->next = ab;
  306.         else
  307.             abbrev = ab;
  308.     }
  309.  
  310.     /* store the new form */
  311.     ab->large = (char *)malloc((unsigned)(strlen(&extra[lrg]) + 1));
  312.     strcpy(ab->large, &extra[lrg]);
  313. }
  314.  
  315.  
  316. # ifndef NO_MKEXRC
  317. /* This function is called from cmd_mkexrc() to save the abbreviations */
  318. void saveabbr(fd)
  319.     int    fd;    /* fd to which the :abbr commands should be written */
  320. {
  321.     REG struct _AB    *ab;
  322.  
  323.     for (ab = abbrev; ab; ab = ab->next)
  324.     {
  325.         twrite(fd, "abbr ", 5);
  326.         twrite(fd, ab->small, strlen(ab->small));
  327.         twrite(fd, " ", 1);
  328.         twrite(fd, ab->large, strlen(ab->large));
  329.         twrite(fd, "\n", 1);
  330.     }
  331. }
  332. # endif
  333.  
  334. /* This function should be called before each char is inserted.  If the next
  335.  * char is non-alphanumeric and we're at the end of a word, then that word
  336.  * is checked against the abbrev[] array and expanded, if appropriate.  Upon
  337.  * returning from this function, the new char still must be inserted.
  338.  */
  339. static MARK expandabbr(m, ch)
  340.     MARK        m;    /* the cursor position */
  341.     int        ch;    /* the character to insert */
  342. {
  343.     char        *word;    /* where the word starts */
  344.     int        len;    /* length of the word */
  345.     REG struct _AB    *ab;
  346.  
  347.     /* if no abbreviations are in effect, or ch is aphanumeric, then
  348.      * don't do anything
  349.      */
  350.     if (!abbrev || !isascii(ch) || isalnum(ch))
  351.     {
  352.         return m;
  353.     }
  354.  
  355.     /* see where the preceding word starts */
  356.     pfetch(markline(m));
  357.     for (word = ptext + markidx(m), len = 0;
  358.          --word >= ptext && (!isascii(*word) || isalnum(*word));
  359.          len++)
  360.     {
  361.     }
  362.     word++;
  363.  
  364.     /* if zero-length, then it isn't a word, really -- so nothing */
  365.     if (len == 0)
  366.     {
  367.         return m;
  368.     }
  369.  
  370.     /* look it up in the abbrev list */
  371.     for (ab = abbrev; ab; ab = ab->next)
  372.     {
  373.         if (!strncmp(ab->small, word, len) && !ab->small[len])
  374.         {
  375.             break;
  376.         }
  377.     }
  378.  
  379.     /* not an abbreviation? then do nothing */
  380.     if (!ab)
  381.     {
  382.         return m;
  383.     }
  384.  
  385.     /* else replace the small form with the large form */
  386.     add(m, ab->large);
  387.     delete(m - len, m);
  388.  
  389.     /* return with the cursor after the end of the large form */
  390.     return m - len + strlen(ab->large);
  391. }
  392. #endif
  393.  
  394.         
  395. /* This function allows the user to replace an existing (possibly zero-length)
  396.  * chunk of text with typed-in text.  It returns the MARK of the last character
  397.  * that the user typed in.
  398.  */
  399. MARK input(from, to, when)
  400.     MARK    from;    /* where to start inserting text */
  401.     MARK    to;    /* extent of text to delete */
  402.     int    when;    /* either WHEN_VIINP or WHEN_VIREP */
  403. {
  404.     char    key[2];    /* key char followed by '\0' char */
  405.     char    *build;    /* used in building a newline+indent string */
  406.     char    *scan;    /* used while looking at the indent chars of a line */
  407.     MARK    m;    /* some place in the text */
  408. #ifndef NO_EXTENSIONS
  409.     int    quit = FALSE;    /* boolean: are we exiting after this? */
  410. #endif
  411.  
  412. #ifdef DEBUG
  413.     /* if "from" and "to" are reversed, complain */
  414.     if (from > to)
  415.     {
  416.         msg("ERROR: input(%ld:%d, %ld:%d)",
  417.             markline(from), markidx(from),
  418.             markline(to), markidx(to));
  419.         return MARK_UNSET;
  420.     }
  421. #endif
  422.  
  423.     key[1] = 0;
  424.  
  425.     /* if we're replacing text with new text, save the old stuff */
  426.     /* (Alas, there is no easy way to save text for replace mode) */
  427.     if (from != to)
  428.     {
  429.         cut(from, to);
  430.     }
  431.  
  432.     ChangeText
  433.     {
  434.         /* if doing a dot command, then reuse the previous text */
  435.         if (doingdot)
  436.         {
  437.             /* delete the text that's there now */
  438.             if (from != to)
  439.             {
  440.                 delete(from, to);
  441.             }
  442.  
  443.             /* insert the previous text */
  444.             cutname('.');
  445.             cursor = paste(from, FALSE, TRUE) + 1L;
  446.         }
  447.         else /* interactive version */
  448.         {
  449.             /* if doing a change within the line... */
  450.             if (from != to && markline(from) == markline(to))
  451.             {
  452.                 /* mark the end of the text with a "$" */
  453.                 change(to - 1, to, "$");
  454.             }
  455.             else
  456.             {
  457.                 /* delete the old text right off */
  458.                 if (from != to)
  459.                 {
  460.                     delete(from, to);
  461.                 }
  462.                 to = from;
  463.             }
  464.  
  465.             /* handle autoindent of the first line, maybe */
  466.             cursor = from;
  467.             if (*o_autoindent && markline(cursor) > 1L && markidx(cursor) == 0)
  468.             {
  469.                 /* Only autoindent blank lines. */
  470.                 pfetch(markline(cursor));
  471.                 if (plen == 0)
  472.                 {
  473.                     /* Okay, we really want to autoindent */
  474.                     pfetch(markline(cursor) - 1L);
  475.                     for (scan = ptext, build = tmpblk.c;
  476.                          *scan == ' ' || *scan == '\t';
  477.                          )
  478.                     {
  479.                         *build++ = *scan++;
  480.                     }
  481.                     if (build > tmpblk.c)
  482.                     {
  483.                         *build = '\0';
  484.                         add(cursor, tmpblk.c);
  485.                         cursor += (build - tmpblk.c);
  486.                     }
  487.                 }
  488.             }
  489.  
  490.             /* repeatedly add characters from the user */
  491.             for (;;)
  492.             {
  493.                 /* Get a character */
  494.                 redraw(cursor, TRUE);
  495. #ifdef DEBUG
  496.                 msg("cursor=%ld.%d, to=%ld.%d",
  497.                     markline(cursor), markidx(cursor),
  498.                     markline(to), markidx(to));
  499. #endif
  500.                 key[0] = getkey(when);
  501.  
  502.                 /* if whitespace & wrapmargin is set & we're
  503.                  * past the warpmargin, then change the
  504.                  * whitespace character into a newline
  505.                  */
  506.                 if ((*key == ' ' || *key == '\t')
  507.                  && *o_wrapmargin != 0)
  508.                 {
  509.                     pfetch(markline(cursor));
  510.                     if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
  511.                     {
  512.                         *key = '\n';
  513.                     }
  514.                 }
  515.  
  516.                 /* process it */
  517.                 switch (*key)
  518.                 {
  519. #ifndef NO_EXTENSIONS
  520.                   case 0: /* special movement mapped keys */
  521.                     *key = getkey(0);
  522.                     switch (*key)
  523.                     {
  524.                       case 'h':    m = m_left(cursor, 0L);        break;
  525.                       case 'j':
  526.                       case 'k':    m = m_updnto(cursor, 0L, *key);    break;
  527.                       case 'l':    m = cursor + 1;            break;
  528.                       case 'b':    m = m_bword(cursor, 0L);    break;
  529.                       case 'w':    m = m_fword(cursor, 0L);    break;
  530.                       case '^':    m = m_front(cursor, 0L);    break;
  531.                       case '$':    m = m_rear(cursor, 0L);        break;
  532.                       case ctrl('B'):
  533.                       case ctrl('F'):
  534.                             m = m_scroll(cursor, 0L, *key); break;
  535.                       case 'x':    m = v_xchar(cursor, 0L);    break;
  536.                       case 'i':    m = to = from = cursor;        break;
  537.                       default:    m = MARK_UNSET;            break;
  538.                     }
  539.                     /* adjust the moved cursor */
  540.                     m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
  541.                     if (*key == '$' || (*key == 'l' && m <= cursor))
  542.                     {
  543.                         m++;
  544.                     }
  545.                     /* if the cursor is reasonable, use it */
  546.                     if (m == MARK_UNSET)
  547.                     {
  548.                         beep();
  549.                     }
  550.                     else
  551.                     {
  552.                         if (to > cursor)
  553.                         {
  554.                             delete(cursor, to);
  555.                             redraw(cursor, TRUE);
  556.                         }
  557.                         from = to = cursor = m;
  558.                     }
  559.                     break;
  560.  
  561.                   case ctrl('Z'):
  562.                     if (getkey(0) == ctrl('Z'))
  563.                     {
  564.                         quit = TRUE;
  565.                         goto BreakBreak;
  566.                     }
  567.                     break;
  568. #endif
  569.  
  570.                   case ctrl('['):
  571. #ifndef NO_ABBR
  572.                     cursor = expandabbr(cursor, ctrl('['));
  573. #endif
  574.                     goto BreakBreak;
  575.  
  576.                   case ctrl('U'):
  577.                     if (markline(cursor) == markline(from))
  578.                     {
  579.                         cursor = from;
  580.                     }
  581.                     else
  582.                     {
  583.                         cursor &= ~(BLKSIZE - 1);
  584.                     }
  585.                     break;
  586.  
  587.                   case ctrl('D'):
  588.                   case ctrl('T'):
  589.                     if (to > cursor)
  590.                     {
  591.                         delete(cursor, to);
  592.                     }
  593.                     mark[27] = cursor;
  594.                     cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
  595.                     if (mark[27])
  596.                     {
  597.                         cursor = mark[27];
  598.                     }
  599.                     else
  600.                     {
  601.                         cursor = m_front(cursor, 0L);
  602.                     }
  603.                     to = cursor;
  604.                     break;
  605.  
  606.                   case '\b':
  607.                     if (cursor <= from)
  608.                     {
  609.                         beep();
  610.                     }
  611.                     else if (markidx(cursor) == 0)
  612.                     {
  613.                         cursor -= BLKSIZE;
  614.                         pfetch(markline(cursor));
  615.                         cursor += plen;
  616.                     }
  617.                     else
  618.                     {
  619.                         cursor--;
  620.                     }
  621.                     break;
  622.  
  623.                   case ctrl('W'):
  624.                     m = m_bword(cursor, 1L);
  625.                     if (markline(m) == markline(cursor) && m >= from)
  626.                     {
  627.                         cursor = m;
  628.                         if (from > cursor)
  629.                         {
  630.                             from = cursor;
  631.                         }
  632.                     }
  633.                     else
  634.                     {
  635.                         beep();
  636.                     }
  637.                     break;
  638.  
  639.                   case '\n':
  640. #if OSK
  641.                   case '\l':
  642. #else                  
  643.                   case '\r':
  644. #endif
  645. #ifndef NO_ABBR
  646.                     cursor = expandabbr(cursor, '\n');
  647. #endif
  648.                     build = tmpblk.c;
  649.                     *build++ = '\n';
  650.                     if (*o_autoindent)
  651.                     {
  652.                         /* figure out indent for next line */
  653.                         pfetch(markline(cursor));
  654.                         for (scan = ptext; *scan == ' ' || *scan == '\t'; )
  655.                         {
  656.                             *build++ = *scan++;
  657.                         }
  658.  
  659.                         /* remove indent from this line, if blank */
  660.                         if (!*scan && plen > 0)
  661.                         {
  662.                             to = cursor &= ~(BLKSIZE - 1);
  663.                             delete(cursor, cursor + plen);
  664.                         }
  665.                     }
  666.                     *build = 0;
  667.                     if (cursor >= to && when != WHEN_VIREP)
  668.                     {
  669.                         add(cursor, tmpblk.c);
  670.                     }
  671.                     else
  672.                     {
  673.                         change(cursor, to, tmpblk.c);
  674.                     }
  675.                     redraw(cursor, TRUE);
  676.                     to = cursor = (cursor & ~(BLKSIZE - 1))
  677.                             + BLKSIZE
  678.                             + (int)(build - tmpblk.c) - 1;
  679.                     break;
  680.  
  681.                   case ctrl('A'):
  682.                   case ctrl('P'):
  683.                     if (cursor < to)
  684.                     {
  685.                         delete(cursor, to);
  686.                     }
  687.                     if (*key == ctrl('A'))
  688.                     {
  689.                         cutname('.');
  690.                     }
  691.                     to = cursor = paste(cursor, FALSE, TRUE) + 1L;
  692.                     break;
  693.  
  694.                   case ctrl('V'):
  695.                     if (cursor >= to && when != WHEN_VIREP)
  696.                     {
  697.                         add(cursor, "^");
  698.                     }
  699.                     else
  700.                     {
  701.                         change(cursor, to, "^");
  702.                         to = cursor + 1;
  703.                     }
  704.                     redraw(cursor, TRUE);
  705.                     *key = getkey(0);
  706.                     if (*key == '\n')
  707.                     {
  708.                         /* '\n' too hard to handle */
  709. #if OSK
  710.                         *key = '\l';
  711. #else
  712.                         *key = '\r';
  713. #endif
  714.                     }
  715.                     change(cursor, cursor + 1, key);
  716.                     cursor++;
  717.                     if (cursor > to)
  718.                     {
  719.                         to = cursor;
  720.                     }
  721.                     break;
  722.  
  723.                   case ctrl('L'):
  724.                   case ctrl('R'):
  725.                     redraw(MARK_UNSET, FALSE);
  726.                     break;
  727.  
  728.                   default:
  729.                     if (cursor >= to && when != WHEN_VIREP)
  730.                     {
  731. #ifndef NO_ABBR
  732.                         cursor = expandabbr(cursor, *key);
  733. #endif
  734.                         add(cursor, key);
  735.                         cursor++;
  736.                         to = cursor;
  737.                     }
  738.                     else
  739.                     {
  740.                         pfetch(markline(cursor));
  741.                         if (markidx(cursor) == plen)
  742.                         {
  743. #ifndef NO_ABBR
  744.                             cursor = expandabbr(cursor, *key);
  745. #endif
  746.                             add(cursor, key);
  747.                         }
  748.                         else
  749.                         {
  750. #ifndef NO_DIGRAPH
  751.                             *key = digraph(ptext[markidx(cursor)], *key);
  752. #endif
  753. #ifndef NO_ABBR
  754.                             cursor = expandabbr(cursor, *key);
  755. #endif
  756.                             change(cursor, cursor + 1, key);
  757.                         }
  758.                         cursor++;
  759.                     }
  760. #ifndef NO_SHOWMATCH
  761.                     /* show matching "({[" if neceesary */
  762.                     if (*o_showmatch && strchr(")}]", *key))
  763.                     {
  764.                         redraw(cursor, TRUE);
  765.                         m = m_match(cursor - 1, 0L);
  766.                         if (markline(m) >= topline
  767.                          && markline(m) <= botline)
  768.                         {
  769.                             redraw(m, TRUE);
  770.                             refresh();
  771.                             sleep(1);
  772.                         }
  773.                     }
  774. #endif
  775.                 } /* end switch(*key) */
  776.             } /* end for(;;) */
  777. BreakBreak:;
  778.  
  779.             /* delete any excess characters */
  780.             if (cursor < to)
  781.             {
  782.                 delete(cursor, to);
  783.             }
  784.  
  785.         } /* end if doingdot else */
  786.  
  787.     } /* end ChangeText */
  788.  
  789.     /* put the new text into a cut buffer for possible reuse */
  790.     if (!doingdot)
  791.     {
  792.         blksync();
  793.         cutname('.');
  794.         cut(from, cursor);
  795.     }
  796.  
  797.     /* move to last char that we inputted, unless it was newline */
  798.     if (markidx(cursor) != 0)
  799.     {
  800.         cursor--;
  801.     }
  802.     redraw(cursor, FALSE);
  803.  
  804. #ifndef NO_EXTENSIONS
  805.     if (quit)
  806.     {
  807.         /* if this is a nested "do", then cut it short */
  808.         abortdo();
  809.  
  810.         /* exit, unless we can't write out the file */
  811.         cursor = v_xit(cursor, 0L, 'Z');
  812.     }
  813. #endif
  814.  
  815.     rptlines = 0L;
  816.     return cursor;
  817. }
  818.