Annotation of embedaddon/readline/vi_mode.c, revision 1.1.1.1

1.1       misho       1: /* vi_mode.c -- A vi emulation mode for Bash.
                      2:    Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
                      3: 
                      4: /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
                      5: 
                      6:    This file is part of the GNU Readline Library (Readline), a library
                      7:    for reading lines of text with interactive input and history editing.      
                      8: 
                      9:    Readline is free software: you can redistribute it and/or modify
                     10:    it under the terms of the GNU General Public License as published by
                     11:    the Free Software Foundation, either version 3 of the License, or
                     12:    (at your option) any later version.
                     13: 
                     14:    Readline is distributed in the hope that it will be useful,
                     15:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17:    GNU General Public License for more details.
                     18: 
                     19:    You should have received a copy of the GNU General Public License
                     20:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
                     21: */
                     22: 
                     23: #define READLINE_LIBRARY
                     24: 
                     25: /* **************************************************************** */
                     26: /*                                                                 */
                     27: /*                     VI Emulation Mode                           */
                     28: /*                                                                 */
                     29: /* **************************************************************** */
                     30: #include "rlconf.h"
                     31: 
                     32: #if defined (VI_MODE)
                     33: 
                     34: #if defined (HAVE_CONFIG_H)
                     35: #  include <config.h>
                     36: #endif
                     37: 
                     38: #include <sys/types.h>
                     39: 
                     40: #if defined (HAVE_STDLIB_H)
                     41: #  include <stdlib.h>
                     42: #else
                     43: #  include "ansi_stdlib.h"
                     44: #endif /* HAVE_STDLIB_H */
                     45: 
                     46: #if defined (HAVE_UNISTD_H)
                     47: #  include <unistd.h>
                     48: #endif
                     49: 
                     50: #include <stdio.h>
                     51: 
                     52: /* Some standard library routines. */
                     53: #include "rldefs.h"
                     54: #include "rlmbutil.h"
                     55: 
                     56: #include "readline.h"
                     57: #include "history.h"
                     58: 
                     59: #include "rlprivate.h"
                     60: #include "xmalloc.h"
                     61: 
                     62: #ifndef member
                     63: #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
                     64: #endif
                     65: 
                     66: int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
                     67: 
                     68: _rl_vimotion_cxt *_rl_vimvcxt = 0;
                     69: 
                     70: /* Non-zero means enter insertion mode. */
                     71: static int _rl_vi_doing_insert;
                     72: 
                     73: /* Command keys which do movement for xxx_to commands. */
                     74: static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
                     75: 
                     76: /* Keymap used for vi replace characters.  Created dynamically since
                     77:    rarely used. */
                     78: static Keymap vi_replace_map;
                     79: 
                     80: /* The number of characters inserted in the last replace operation. */
                     81: static int vi_replace_count;
                     82: 
                     83: /* If non-zero, we have text inserted after a c[motion] command that put
                     84:    us implicitly into insert mode.  Some people want this text to be
                     85:    attached to the command so that it is `redoable' with `.'. */
                     86: static int vi_continued_command;
                     87: static char *vi_insert_buffer;
                     88: static int vi_insert_buffer_size;
                     89: 
                     90: static int _rl_vi_last_repeat = 1;
                     91: static int _rl_vi_last_arg_sign = 1;
                     92: static int _rl_vi_last_motion;
                     93: #if defined (HANDLE_MULTIBYTE)
                     94: static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
                     95: static int _rl_vi_last_search_mblen;
                     96: #else
                     97: static int _rl_vi_last_search_char;
                     98: #endif
                     99: static int _rl_vi_last_replacement;
                    100: 
                    101: static int _rl_vi_last_key_before_insert;
                    102: 
                    103: static int vi_redoing;
                    104: 
                    105: /* Text modification commands.  These are the `redoable' commands. */
                    106: static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
                    107: 
                    108: /* Arrays for the saved marks. */
                    109: static int vi_mark_chars['z' - 'a' + 1];
                    110: 
                    111: static void _rl_vi_replace_insert PARAMS((int));
                    112: static void _rl_vi_save_replace PARAMS((void));
                    113: static void _rl_vi_stuff_insert PARAMS((int));
                    114: static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
                    115: 
                    116: static void vi_save_insert_buffer PARAMS ((int, int));
                    117: 
                    118: static void _rl_vi_backup PARAMS((void));
                    119: 
                    120: static int _rl_vi_arg_dispatch PARAMS((int));
                    121: static int rl_digit_loop1 PARAMS((void));
                    122: 
                    123: static int _rl_vi_set_mark PARAMS((void));
                    124: static int _rl_vi_goto_mark PARAMS((void));
                    125: 
                    126: static void _rl_vi_append_forward PARAMS((int));
                    127: 
                    128: static int _rl_vi_callback_getchar PARAMS((char *, int));
                    129: 
                    130: #if defined (READLINE_CALLBACKS)
                    131: static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
                    132: static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
                    133: static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
                    134: static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
                    135: #endif
                    136: 
                    137: static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
                    138: static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
                    139: static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
                    140: 
                    141: static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
                    142: static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
                    143: static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
                    144: 
                    145: static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
                    146: 
                    147: void
                    148: _rl_vi_initialize_line ()
                    149: {
                    150:   register int i, n;
                    151: 
                    152:   n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
                    153:   for (i = 0; i < n; i++)
                    154:     vi_mark_chars[i] = -1;
                    155: 
                    156:   RL_UNSETSTATE(RL_STATE_VICMDONCE);
                    157: }
                    158: 
                    159: void
                    160: _rl_vi_reset_last ()
                    161: {
                    162:   _rl_vi_last_command = 'i';
                    163:   _rl_vi_last_repeat = 1;
                    164:   _rl_vi_last_arg_sign = 1;
                    165:   _rl_vi_last_motion = 0;
                    166: }
                    167: 
                    168: void
                    169: _rl_vi_set_last (key, repeat, sign)
                    170:      int key, repeat, sign;
                    171: {
                    172:   _rl_vi_last_command = key;
                    173:   _rl_vi_last_repeat = repeat;
                    174:   _rl_vi_last_arg_sign = sign;
                    175: }
                    176: 
                    177: /* A convenience function that calls _rl_vi_set_last to save the last command
                    178:    information and enters insertion mode. */
                    179: void
                    180: rl_vi_start_inserting (key, repeat, sign)
                    181:      int key, repeat, sign;
                    182: {
                    183:   _rl_vi_set_last (key, repeat, sign);
                    184:   rl_vi_insertion_mode (1, key);
                    185: }
                    186: 
                    187: /* Is the command C a VI mode text modification command? */
                    188: int
                    189: _rl_vi_textmod_command (c)
                    190:      int c;
                    191: {
                    192:   return (member (c, vi_textmod));
                    193: }
                    194: 
                    195: static void
                    196: _rl_vi_replace_insert (count)
                    197:      int count;
                    198: {
                    199:   int nchars;
                    200: 
                    201:   nchars = strlen (vi_insert_buffer);
                    202: 
                    203:   rl_begin_undo_group ();
                    204:   while (count--)
                    205:     /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
                    206:        to rl_delete_text */
                    207:     _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
                    208:   rl_end_undo_group ();
                    209: }
                    210: 
                    211: static void
                    212: _rl_vi_stuff_insert (count)
                    213:      int count;
                    214: {
                    215:   rl_begin_undo_group ();
                    216:   while (count--)
                    217:     rl_insert_text (vi_insert_buffer);
                    218:   rl_end_undo_group ();
                    219: }
                    220: 
                    221: /* Bound to `.'.  Called from command mode, so we know that we have to
                    222:    redo a text modification command.  The default for _rl_vi_last_command
                    223:    puts you back into insert mode. */
                    224: int
                    225: rl_vi_redo (count, c)
                    226:      int count, c;
                    227: {
                    228:   int r;
                    229: 
                    230:   if (rl_explicit_arg == 0)
                    231:     {
                    232:       rl_numeric_arg = _rl_vi_last_repeat;
                    233:       rl_arg_sign = _rl_vi_last_arg_sign;
                    234:     }
                    235: 
                    236:   r = 0;
                    237:   vi_redoing = 1;
                    238:   /* If we're redoing an insert with `i', stuff in the inserted text
                    239:      and do not go into insertion mode. */
                    240:   if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
                    241:     {
                    242:       _rl_vi_stuff_insert (count);
                    243:       /* And back up point over the last character inserted. */
                    244:       if (rl_point > 0)
                    245:        _rl_vi_backup ();
                    246:     }
                    247:   else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
                    248:     {
                    249:       _rl_vi_replace_insert (count);
                    250:       /* And back up point over the last character inserted. */
                    251:       if (rl_point > 0)
                    252:        _rl_vi_backup ();
                    253:     }
                    254:   /* Ditto for redoing an insert with `I', but move to the beginning of the
                    255:      line like the `I' command does. */
                    256:   else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
                    257:     {
                    258:       rl_beg_of_line (1, 'I');
                    259:       _rl_vi_stuff_insert (count);
                    260:       if (rl_point > 0)
                    261:        _rl_vi_backup ();
                    262:     }
                    263:   /* Ditto for redoing an insert with `a', but move forward a character first
                    264:      like the `a' command does. */
                    265:   else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
                    266:     {
                    267:       _rl_vi_append_forward ('a');
                    268:       _rl_vi_stuff_insert (count);
                    269:       if (rl_point > 0)
                    270:        _rl_vi_backup ();
                    271:     }
                    272:   /* Ditto for redoing an insert with `A', but move to the end of the line
                    273:      like the `A' command does. */
                    274:   else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
                    275:     {
                    276:       rl_end_of_line (1, 'A');
                    277:       _rl_vi_stuff_insert (count);
                    278:       if (rl_point > 0)
                    279:        _rl_vi_backup ();
                    280:     }
                    281:   else
                    282:     r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
                    283:   vi_redoing = 0;
                    284: 
                    285:   return (r);
                    286: }
                    287: 
                    288: /* A placeholder for further expansion. */
                    289: int
                    290: rl_vi_undo (count, key)
                    291:      int count, key;
                    292: {
                    293:   return (rl_undo_command (count, key));
                    294: }
                    295:     
                    296: /* Yank the nth arg from the previous line into this line at point. */
                    297: int
                    298: rl_vi_yank_arg (count, key)
                    299:      int count, key;
                    300: {
                    301:   /* Readline thinks that the first word on a line is the 0th, while vi
                    302:      thinks the first word on a line is the 1st.  Compensate. */
                    303:   if (rl_explicit_arg)
                    304:     rl_yank_nth_arg (count - 1, 0);
                    305:   else
                    306:     rl_yank_nth_arg ('$', 0);
                    307: 
                    308:   return (0);
                    309: }
                    310: 
                    311: /* With an argument, move back that many history lines, else move to the
                    312:    beginning of history. */
                    313: int
                    314: rl_vi_fetch_history (count, c)
                    315:      int count, c;
                    316: {
                    317:   int wanted;
                    318: 
                    319:   /* Giving an argument of n means we want the nth command in the history
                    320:      file.  The command number is interpreted the same way that the bash
                    321:      `history' command does it -- that is, giving an argument count of 450
                    322:      to this command would get the command listed as number 450 in the
                    323:      output of `history'. */
                    324:   if (rl_explicit_arg)
                    325:     {
                    326:       wanted = history_base + where_history () - count;
                    327:       if (wanted <= 0)
                    328:         rl_beginning_of_history (0, 0);
                    329:       else
                    330:         rl_get_previous_history (wanted, c);
                    331:     }
                    332:   else
                    333:     rl_beginning_of_history (count, 0);
                    334:   return (0);
                    335: }
                    336: 
                    337: /* Search again for the last thing searched for. */
                    338: int
                    339: rl_vi_search_again (count, key)
                    340:      int count, key;
                    341: {
                    342:   switch (key)
                    343:     {
                    344:     case 'n':
                    345:       rl_noninc_reverse_search_again (count, key);
                    346:       break;
                    347: 
                    348:     case 'N':
                    349:       rl_noninc_forward_search_again (count, key);
                    350:       break;
                    351:     }
                    352:   return (0);
                    353: }
                    354: 
                    355: /* Do a vi style search. */
                    356: int
                    357: rl_vi_search (count, key)
                    358:      int count, key;
                    359: {
                    360:   switch (key)
                    361:     {
                    362:     case '?':
                    363:       _rl_free_saved_history_line ();
                    364:       rl_noninc_forward_search (count, key);
                    365:       break;
                    366: 
                    367:     case '/':
                    368:       _rl_free_saved_history_line ();
                    369:       rl_noninc_reverse_search (count, key);
                    370:       break;
                    371: 
                    372:     default:
                    373:       rl_ding ();
                    374:       break;
                    375:     }
                    376:   return (0);
                    377: }
                    378: 
                    379: /* Completion, from vi's point of view. */
                    380: int
                    381: rl_vi_complete (ignore, key)
                    382:      int ignore, key;
                    383: {
                    384:   if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
                    385:     {
                    386:       if (!whitespace (rl_line_buffer[rl_point + 1]))
                    387:        rl_vi_end_word (1, 'E');
                    388:       rl_point++;
                    389:     }
                    390: 
                    391:   if (key == '*')
                    392:     rl_complete_internal ('*');        /* Expansion and replacement. */
                    393:   else if (key == '=')
                    394:     rl_complete_internal ('?');        /* List possible completions. */
                    395:   else if (key == '\\')
                    396:     rl_complete_internal (TAB);        /* Standard Readline completion. */
                    397:   else
                    398:     rl_complete (0, key);
                    399: 
                    400:   if (key == '*' || key == '\\')
                    401:     rl_vi_start_inserting (key, 1, rl_arg_sign);
                    402: 
                    403:   return (0);
                    404: }
                    405: 
                    406: /* Tilde expansion for vi mode. */
                    407: int
                    408: rl_vi_tilde_expand (ignore, key)
                    409:      int ignore, key;
                    410: {
                    411:   rl_tilde_expand (0, key);
                    412:   rl_vi_start_inserting (key, 1, rl_arg_sign);
                    413:   return (0);
                    414: }
                    415: 
                    416: /* Previous word in vi mode. */
                    417: int
                    418: rl_vi_prev_word (count, key)
                    419:      int count, key;
                    420: {
                    421:   if (count < 0)
                    422:     return (rl_vi_next_word (-count, key));
                    423: 
                    424:   if (rl_point == 0)
                    425:     {
                    426:       rl_ding ();
                    427:       return (0);
                    428:     }
                    429: 
                    430:   if (_rl_uppercase_p (key))
                    431:     rl_vi_bWord (count, key);
                    432:   else
                    433:     rl_vi_bword (count, key);
                    434: 
                    435:   return (0);
                    436: }
                    437: 
                    438: /* Next word in vi mode. */
                    439: int
                    440: rl_vi_next_word (count, key)
                    441:      int count, key;
                    442: {
                    443:   if (count < 0)
                    444:     return (rl_vi_prev_word (-count, key));
                    445: 
                    446:   if (rl_point >= (rl_end - 1))
                    447:     {
                    448:       rl_ding ();
                    449:       return (0);
                    450:     }
                    451: 
                    452:   if (_rl_uppercase_p (key))
                    453:     rl_vi_fWord (count, key);
                    454:   else
                    455:     rl_vi_fword (count, key);
                    456:   return (0);
                    457: }
                    458: 
                    459: /* Move to the end of the ?next? word. */
                    460: int
                    461: rl_vi_end_word (count, key)
                    462:      int count, key;
                    463: {
                    464:   if (count < 0)
                    465:     {
                    466:       rl_ding ();
                    467:       return -1;
                    468:     }
                    469: 
                    470:   if (_rl_uppercase_p (key))
                    471:     rl_vi_eWord (count, key);
                    472:   else
                    473:     rl_vi_eword (count, key);
                    474:   return (0);
                    475: }
                    476: 
                    477: /* Move forward a word the way that 'W' does. */
                    478: int
                    479: rl_vi_fWord (count, ignore)
                    480:      int count, ignore;
                    481: {
                    482:   while (count-- && rl_point < (rl_end - 1))
                    483:     {
                    484:       /* Skip until whitespace. */
                    485:       while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
                    486:        rl_point++;
                    487: 
                    488:       /* Now skip whitespace. */
                    489:       while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
                    490:        rl_point++;
                    491:     }
                    492:   return (0);
                    493: }
                    494: 
                    495: int
                    496: rl_vi_bWord (count, ignore)
                    497:      int count, ignore;
                    498: {
                    499:   while (count-- && rl_point > 0)
                    500:     {
                    501:       /* If we are at the start of a word, move back to whitespace so
                    502:         we will go back to the start of the previous word. */
                    503:       if (!whitespace (rl_line_buffer[rl_point]) &&
                    504:          whitespace (rl_line_buffer[rl_point - 1]))
                    505:        rl_point--;
                    506: 
                    507:       while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
                    508:        rl_point--;
                    509: 
                    510:       if (rl_point > 0)
                    511:        {
                    512:          while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
                    513:          rl_point++;
                    514:        }
                    515:     }
                    516:   return (0);
                    517: }
                    518: 
                    519: int
                    520: rl_vi_eWord (count, ignore)
                    521:      int count, ignore;
                    522: {
                    523:   while (count-- && rl_point < (rl_end - 1))
                    524:     {
                    525:       if (!whitespace (rl_line_buffer[rl_point]))
                    526:        rl_point++;
                    527: 
                    528:       /* Move to the next non-whitespace character (to the start of the
                    529:         next word). */
                    530:       while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
                    531:        rl_point++;
                    532: 
                    533:       if (rl_point && rl_point < rl_end)
                    534:        {
                    535:          /* Skip whitespace. */
                    536:          while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
                    537:            rl_point++;
                    538: 
                    539:          /* Skip until whitespace. */
                    540:          while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
                    541:            rl_point++;
                    542: 
                    543:          /* Move back to the last character of the word. */
                    544:          rl_point--;
                    545:        }
                    546:     }
                    547:   return (0);
                    548: }
                    549: 
                    550: int
                    551: rl_vi_fword (count, ignore)
                    552:      int count, ignore;
                    553: {
                    554:   while (count-- && rl_point < (rl_end - 1))
                    555:     {
                    556:       /* Move to white space (really non-identifer). */
                    557:       if (_rl_isident (rl_line_buffer[rl_point]))
                    558:        {
                    559:          while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
                    560:            rl_point++;
                    561:        }
                    562:       else /* if (!whitespace (rl_line_buffer[rl_point])) */
                    563:        {
                    564:          while (!_rl_isident (rl_line_buffer[rl_point]) &&
                    565:                 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
                    566:            rl_point++;
                    567:        }
                    568: 
                    569:       /* Move past whitespace. */
                    570:       while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
                    571:        rl_point++;
                    572:     }
                    573:   return (0);
                    574: }
                    575: 
                    576: int
                    577: rl_vi_bword (count, ignore)
                    578:      int count, ignore;
                    579: {
                    580:   while (count-- && rl_point > 0)
                    581:     {
                    582:       int last_is_ident;
                    583: 
                    584:       /* If we are at the start of a word, move back to whitespace
                    585:         so we will go back to the start of the previous word. */
                    586:       if (!whitespace (rl_line_buffer[rl_point]) &&
                    587:          whitespace (rl_line_buffer[rl_point - 1]))
                    588:        rl_point--;
                    589: 
                    590:       /* If this character and the previous character are `opposite', move
                    591:         back so we don't get messed up by the rl_point++ down there in
                    592:         the while loop.  Without this code, words like `l;' screw up the
                    593:         function. */
                    594:       last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
                    595:       if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
                    596:          (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
                    597:        rl_point--;
                    598: 
                    599:       while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
                    600:        rl_point--;
                    601: 
                    602:       if (rl_point > 0)
                    603:        {
                    604:          if (_rl_isident (rl_line_buffer[rl_point]))
                    605:            while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
                    606:          else
                    607:            while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
                    608:                   !whitespace (rl_line_buffer[rl_point]));
                    609:          rl_point++;
                    610:        }
                    611:     }
                    612:   return (0);
                    613: }
                    614: 
                    615: int
                    616: rl_vi_eword (count, ignore)
                    617:      int count, ignore;
                    618: {
                    619:   while (count-- && rl_point < rl_end - 1)
                    620:     {
                    621:       if (!whitespace (rl_line_buffer[rl_point]))
                    622:        rl_point++;
                    623: 
                    624:       while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
                    625:        rl_point++;
                    626: 
                    627:       if (rl_point < rl_end)
                    628:        {
                    629:          if (_rl_isident (rl_line_buffer[rl_point]))
                    630:            while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
                    631:          else
                    632:            while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
                    633:                   && !whitespace (rl_line_buffer[rl_point]));
                    634:        }
                    635:       rl_point--;
                    636:     }
                    637:   return (0);
                    638: }
                    639: 
                    640: int
                    641: rl_vi_insert_beg (count, key)
                    642:      int count, key;
                    643: {
                    644:   rl_beg_of_line (1, key);
                    645:   rl_vi_insert_mode (1, key);
                    646:   return (0);
                    647: }
                    648: 
                    649: static void
                    650: _rl_vi_append_forward (key)
                    651:      int key;
                    652: {
                    653:   int point;
                    654: 
                    655:   if (rl_point < rl_end)
                    656:     {
                    657:       if (MB_CUR_MAX == 1 || rl_byte_oriented)
                    658:        rl_point++;
                    659:       else
                    660:        {
                    661:          point = rl_point;
                    662: #if 0
                    663:          rl_forward_char (1, key);
                    664: #else
                    665:          rl_point = _rl_forward_char_internal (1);
                    666: #endif
                    667:          if (point == rl_point)
                    668:            rl_point = rl_end;
                    669:        }
                    670:     }
                    671: }
                    672: 
                    673: int
                    674: rl_vi_append_mode (count, key)
                    675:      int count, key;
                    676: {
                    677:   _rl_vi_append_forward (key);
                    678:   rl_vi_start_inserting (key, 1, rl_arg_sign);
                    679:   return (0);
                    680: }
                    681: 
                    682: int
                    683: rl_vi_append_eol (count, key)
                    684:      int count, key;
                    685: {
                    686:   rl_end_of_line (1, key);
                    687:   rl_vi_append_mode (1, key);
                    688:   return (0);
                    689: }
                    690: 
                    691: /* What to do in the case of C-d. */
                    692: int
                    693: rl_vi_eof_maybe (count, c)
                    694:      int count, c;
                    695: {
                    696:   return (rl_newline (1, '\n'));
                    697: }
                    698: 
                    699: /* Insertion mode stuff. */
                    700: 
                    701: /* Switching from one mode to the other really just involves
                    702:    switching keymaps. */
                    703: int
                    704: rl_vi_insertion_mode (count, key)
                    705:      int count, key;
                    706: {
                    707:   _rl_keymap = vi_insertion_keymap;
                    708:   _rl_vi_last_key_before_insert = key;
                    709:   if (_rl_show_mode_in_prompt)
                    710:     _rl_reset_prompt ();
                    711:   return (0);
                    712: }
                    713: 
                    714: int
                    715: rl_vi_insert_mode (count, key)
                    716:      int count, key;
                    717: {
                    718:   rl_vi_start_inserting (key, 1, rl_arg_sign);
                    719:   return (0);
                    720: }
                    721: 
                    722: static void
                    723: vi_save_insert_buffer (start, len)
                    724:      int start, len;
                    725: {
                    726:   /* Same code as _rl_vi_save_insert below */
                    727:   if (len >= vi_insert_buffer_size)
                    728:     {
                    729:       vi_insert_buffer_size += (len + 32) - (len % 32);
                    730:       vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
                    731:     }
                    732:   strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
                    733:   vi_insert_buffer[len-1] = '\0';
                    734: }
                    735: 
                    736: static void
                    737: _rl_vi_save_replace ()
                    738: {
                    739:   int len, start, end;
                    740:   UNDO_LIST *up;
                    741: 
                    742:   up = rl_undo_list;
                    743:   if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
                    744:     {
                    745:       if (vi_insert_buffer_size >= 1)
                    746:        vi_insert_buffer[0] = '\0';
                    747:       return;
                    748:     }
                    749:   /* Let's try it the quick and easy way for now.  This should essentially
                    750:      accommodate every UNDO_INSERT and save the inserted text to
                    751:      vi_insert_buffer */
                    752:   end = rl_point;
                    753:   start = end - vi_replace_count + 1;
                    754:   len = vi_replace_count + 1;
                    755: 
                    756:   vi_save_insert_buffer (start, len);  
                    757: }
                    758: 
                    759: static void
                    760: _rl_vi_save_insert (up)
                    761:       UNDO_LIST *up;
                    762: {
                    763:   int len, start, end;
                    764: 
                    765:   if (up == 0 || up->what != UNDO_INSERT)
                    766:     {
                    767:       if (vi_insert_buffer_size >= 1)
                    768:        vi_insert_buffer[0] = '\0';
                    769:       return;
                    770:     }
                    771: 
                    772:   start = up->start;
                    773:   end = up->end;
                    774:   len = end - start + 1;
                    775: 
                    776:   vi_save_insert_buffer (start, len);
                    777: }
                    778:     
                    779: void
                    780: _rl_vi_done_inserting ()
                    781: {
                    782:   if (_rl_vi_doing_insert)
                    783:     {
                    784:       /* The `C', `s', and `S' commands set this. */
                    785:       rl_end_undo_group ();
                    786:       /* Now, the text between rl_undo_list->next->start and
                    787:         rl_undo_list->next->end is what was inserted while in insert
                    788:         mode.  It gets copied to VI_INSERT_BUFFER because it depends
                    789:         on absolute indices into the line which may change (though they
                    790:         probably will not). */
                    791:       _rl_vi_doing_insert = 0;
                    792:       if (_rl_vi_last_key_before_insert == 'R')
                    793:        _rl_vi_save_replace ();         /* Half the battle */
                    794:       else
                    795:        _rl_vi_save_insert (rl_undo_list->next);
                    796:       vi_continued_command = 1;
                    797:     }
                    798:   else
                    799:     {
                    800:       if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
                    801:                           _rl_vi_last_key_before_insert == 'a' ||
                    802:                           _rl_vi_last_key_before_insert == 'I' ||
                    803:                           _rl_vi_last_key_before_insert == 'A'))
                    804:        _rl_vi_save_insert (rl_undo_list);
                    805:       /* XXX - Other keys probably need to be checked. */
                    806:       else if (_rl_vi_last_key_before_insert == 'C')
                    807:        rl_end_undo_group ();
                    808:       while (_rl_undo_group_level > 0)
                    809:        rl_end_undo_group ();
                    810:       vi_continued_command = 0;
                    811:     }
                    812: }
                    813: 
                    814: int
                    815: rl_vi_movement_mode (count, key)
                    816:      int count, key;
                    817: {
                    818:   if (rl_point > 0)
                    819:     rl_backward_char (1, key);
                    820: 
                    821:   _rl_keymap = vi_movement_keymap;
                    822:   _rl_vi_done_inserting ();
                    823: 
                    824:   /* This is how POSIX.2 says `U' should behave -- everything up until the
                    825:      first time you go into command mode should not be undone. */
                    826:   if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
                    827:     rl_free_undo_list ();
                    828: 
                    829:   if (_rl_show_mode_in_prompt)
                    830:     _rl_reset_prompt ();
                    831: 
                    832:   RL_SETSTATE (RL_STATE_VICMDONCE);
                    833:   return (0);
                    834: }
                    835: 
                    836: int
                    837: rl_vi_arg_digit (count, c)
                    838:      int count, c;
                    839: {
                    840:   if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
                    841:     return (rl_beg_of_line (1, c));
                    842:   else
                    843:     return (rl_digit_argument (count, c));
                    844: }
                    845: 
                    846: /* Change the case of the next COUNT characters. */
                    847: #if defined (HANDLE_MULTIBYTE)
                    848: static int
                    849: _rl_vi_change_mbchar_case (count)
                    850:      int count;
                    851: {
                    852:   wchar_t wc;
                    853:   char mb[MB_LEN_MAX+1];
                    854:   int mlen, p;
                    855:   size_t m;
                    856:   mbstate_t ps;
                    857: 
                    858:   memset (&ps, 0, sizeof (mbstate_t));
                    859:   if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
                    860:     count--;
                    861:   while (count-- && rl_point < rl_end)
                    862:     {
                    863:       m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
                    864:       if (MB_INVALIDCH (m))
                    865:        wc = (wchar_t)rl_line_buffer[rl_point];
                    866:       else if (MB_NULLWCH (m))
                    867:        wc = L'\0';
                    868:       if (iswupper (wc))
                    869:        wc = towlower (wc);
                    870:       else if (iswlower (wc))
                    871:        wc = towupper (wc);
                    872:       else
                    873:        {
                    874:          /* Just skip over chars neither upper nor lower case */
                    875:          rl_forward_char (1, 0);
                    876:          continue;
                    877:        }
                    878: 
                    879:       /* Vi is kind of strange here. */
                    880:       if (wc)
                    881:        {
                    882:          p = rl_point;
                    883:          mlen = wcrtomb (mb, wc, &ps);
                    884:          if (mlen >= 0)
                    885:            mb[mlen] = '\0';
                    886:          rl_begin_undo_group ();
                    887:          rl_vi_delete (1, 0);
                    888:          if (rl_point < p)     /* Did we retreat at EOL? */
                    889:            rl_point++; /* XXX - should we advance more than 1 for mbchar? */
                    890:          rl_insert_text (mb);
                    891:          rl_end_undo_group ();
                    892:          rl_vi_check ();
                    893:        }
                    894:       else
                    895:        rl_forward_char (1, 0);
                    896:     }
                    897: 
                    898:   return 0;
                    899: }
                    900: #endif
                    901: 
                    902: int
                    903: rl_vi_change_case (count, ignore)
                    904:      int count, ignore;
                    905: {
                    906:   int c, p;
                    907: 
                    908:   /* Don't try this on an empty line. */
                    909:   if (rl_point >= rl_end)
                    910:     return (0);
                    911: 
                    912:   c = 0;
                    913: #if defined (HANDLE_MULTIBYTE)
                    914:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    915:     return (_rl_vi_change_mbchar_case (count));
                    916: #endif
                    917: 
                    918:   while (count-- && rl_point < rl_end)
                    919:     {
                    920:       if (_rl_uppercase_p (rl_line_buffer[rl_point]))
                    921:        c = _rl_to_lower (rl_line_buffer[rl_point]);
                    922:       else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
                    923:        c = _rl_to_upper (rl_line_buffer[rl_point]);
                    924:       else
                    925:        {
                    926:          /* Just skip over characters neither upper nor lower case. */
                    927:          rl_forward_char (1, c);
                    928:          continue;
                    929:        }
                    930: 
                    931:       /* Vi is kind of strange here. */
                    932:       if (c)
                    933:        {
                    934:          p = rl_point;
                    935:          rl_begin_undo_group ();
                    936:          rl_vi_delete (1, c);
                    937:          if (rl_point < p)     /* Did we retreat at EOL? */
                    938:            rl_point++;
                    939:          _rl_insert_char (1, c);
                    940:          rl_end_undo_group ();
                    941:          rl_vi_check ();
                    942:        }
                    943:       else
                    944:        rl_forward_char (1, c);
                    945:     }
                    946:   return (0);
                    947: }
                    948: 
                    949: int
                    950: rl_vi_put (count, key)
                    951:      int count, key;
                    952: {
                    953:   if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
                    954:     rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
                    955: 
                    956:   while (count--)
                    957:     rl_yank (1, key);
                    958: 
                    959:   rl_backward_char (1, key);
                    960:   return (0);
                    961: }
                    962: 
                    963: static void
                    964: _rl_vi_backup ()
                    965: {
                    966:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    967:     rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
                    968:   else
                    969:     rl_point--;
                    970: }
                    971: 
                    972: int
                    973: rl_vi_check ()
                    974: {
                    975:   if (rl_point && rl_point == rl_end)
                    976:     {
                    977:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    978:        rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
                    979:       else
                    980:        rl_point--;
                    981:     }
                    982:   return (0);
                    983: }
                    984: 
                    985: int
                    986: rl_vi_column (count, key)
                    987:      int count, key;
                    988: {
                    989:   if (count > rl_end)
                    990:     rl_end_of_line (1, key);
                    991:   else
                    992:     rl_point = count - 1;
                    993:   return (0);
                    994: }
                    995: 
                    996: /* Process C as part of the current numeric argument.  Return -1 if the
                    997:    argument should be aborted, 0 if we should not read any more chars, and
                    998:    1 if we should continue to read chars. */
                    999: static int
                   1000: _rl_vi_arg_dispatch (c)
                   1001:      int c;
                   1002: {
                   1003:   int key;
                   1004: 
                   1005:   key = c;
                   1006:   if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
                   1007:     {
                   1008:       rl_numeric_arg *= 4;
                   1009:       return 1;
                   1010:     }
                   1011: 
                   1012:   c = UNMETA (c);
                   1013: 
                   1014:   if (_rl_digit_p (c))
                   1015:     {
                   1016:       if (rl_explicit_arg)
                   1017:        rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
                   1018:       else
                   1019:        rl_numeric_arg = _rl_digit_value (c);
                   1020:       rl_explicit_arg = 1;
                   1021:       return 1;                /* keep going */
                   1022:     }
                   1023:   else
                   1024:     {
                   1025:       rl_clear_message ();
                   1026:       rl_stuff_char (key);
                   1027:       return 0;                /* done */
                   1028:     }
                   1029: }
                   1030: 
                   1031: /* A simplified loop for vi. Don't dispatch key at end.
                   1032:    Don't recognize minus sign?
                   1033:    Should this do rl_save_prompt/rl_restore_prompt? */
                   1034: static int
                   1035: rl_digit_loop1 ()
                   1036: {
                   1037:   int c, r;
                   1038: 
                   1039:   while (1)
                   1040:     {
                   1041:       if (_rl_arg_overflow ())
                   1042:        return 1;
                   1043: 
                   1044:       c = _rl_arg_getchar ();
                   1045: 
                   1046:       r = _rl_vi_arg_dispatch (c);
                   1047:       if (r <= 0)
                   1048:        break;
                   1049:     }
                   1050: 
                   1051:   RL_UNSETSTATE(RL_STATE_NUMERICARG);
                   1052:   return (0);
                   1053: }
                   1054: 
                   1055: static void
                   1056: _rl_mvcxt_init (m, op, key)
                   1057:      _rl_vimotion_cxt *m;
                   1058:      int op, key;
                   1059: {
                   1060:   m->op = op;
                   1061:   m->state = m->flags = 0;
                   1062:   m->ncxt = 0;
                   1063:   m->numeric_arg = -1;
                   1064:   m->start = rl_point;
                   1065:   m->end = rl_end;
                   1066:   m->key = key;
                   1067:   m->motion = -1;
                   1068: }
                   1069: 
                   1070: static _rl_vimotion_cxt *
                   1071: _rl_mvcxt_alloc (op, key)
                   1072:      int op, key;
                   1073: {
                   1074:   _rl_vimotion_cxt *m;
                   1075: 
                   1076:   m = xmalloc (sizeof (_rl_vimotion_cxt));
                   1077:   _rl_mvcxt_init (m, op, key);
                   1078:   return m;
                   1079: }
                   1080: 
                   1081: static void
                   1082: _rl_mvcxt_dispose (m)
                   1083:      _rl_vimotion_cxt *m;
                   1084: {
                   1085:   xfree (m);
                   1086: }
                   1087: 
                   1088: static int
                   1089: rl_domove_motion_callback (m)
                   1090:      _rl_vimotion_cxt *m;
                   1091: {
                   1092:   int c, save, r;
                   1093:   int old_end;
                   1094: 
                   1095:   _rl_vi_last_motion = c = m->motion;
                   1096: 
                   1097:   /* Append a blank character temporarily so that the motion routines
                   1098:      work right at the end of the line. */
                   1099:   old_end = rl_end;
                   1100:   rl_line_buffer[rl_end++] = ' ';
                   1101:   rl_line_buffer[rl_end] = '\0';
                   1102: 
                   1103:   _rl_dispatch (c, _rl_keymap);
                   1104: 
                   1105:   /* Remove the blank that we added. */
                   1106:   rl_end = old_end;
                   1107:   rl_line_buffer[rl_end] = '\0';
                   1108:   if (rl_point > rl_end)
                   1109:     rl_point = rl_end;
                   1110: 
                   1111:   /* No change in position means the command failed. */
                   1112:   if (rl_mark == rl_point)
                   1113:     return (-1);
                   1114: 
                   1115:   /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
                   1116:      word.  If we are not at the end of the line, and we are on a
                   1117:      non-whitespace character, move back one (presumably to whitespace). */
                   1118:   if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
                   1119:       !whitespace (rl_line_buffer[rl_point]))
                   1120:     rl_point--;
                   1121: 
                   1122:   /* If cw or cW, back up to the end of a word, so the behaviour of ce
                   1123:      or cE is the actual result.  Brute-force, no subtlety. */
                   1124:   if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
                   1125:     {
                   1126:       /* Don't move farther back than where we started. */
                   1127:       while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
                   1128:        rl_point--;
                   1129: 
                   1130:       /* Posix.2 says that if cw or cW moves the cursor towards the end of
                   1131:         the line, the character under the cursor should be deleted. */
                   1132:       if (rl_point == rl_mark)
                   1133:        rl_point++;
                   1134:       else
                   1135:        {
                   1136:          /* Move past the end of the word so that the kill doesn't
                   1137:             remove the last letter of the previous word.  Only do this
                   1138:             if we are not at the end of the line. */
                   1139:          if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
                   1140:            rl_point++;
                   1141:        }
                   1142:     }
                   1143: 
                   1144:   if (rl_mark < rl_point)
                   1145:     SWAP (rl_point, rl_mark);
                   1146: 
                   1147: #if defined (READLINE_CALLBACKS)
                   1148:   if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1149:     (*rl_redisplay_function)();                /* make sure motion is displayed */
                   1150: #endif
                   1151: 
                   1152:   r = vidomove_dispatch (m);
                   1153: 
                   1154:   return (r);
                   1155: }
                   1156: 
                   1157: #define RL_VIMOVENUMARG()      (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
                   1158: 
                   1159: static int
                   1160: rl_domove_read_callback (m)
                   1161:      _rl_vimotion_cxt *m;
                   1162: {
                   1163:   int c, save;
                   1164: 
                   1165:   c = m->motion;
                   1166: 
                   1167:   if (member (c, vi_motion))
                   1168:     {
                   1169: #if defined (READLINE_CALLBACKS)
                   1170:       /* If we just read a vi-mode motion command numeric argument, turn off
                   1171:         the `reading numeric arg' state */
                   1172:       if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
                   1173:        RL_UNSETSTATE (RL_STATE_NUMERICARG);
                   1174: #endif
                   1175:       /* Should do everything, including turning off RL_STATE_VIMOTION */
                   1176:       return (rl_domove_motion_callback (m));
                   1177:     }
                   1178:   else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
                   1179:     {
                   1180:       rl_mark = rl_end;
                   1181:       rl_beg_of_line (1, c);
                   1182:       _rl_vi_last_motion = c;
                   1183:       RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1184:       return (vidomove_dispatch (m));
                   1185:     }
                   1186: #if defined (READLINE_CALLBACKS)
                   1187:   /* XXX - these need to handle rl_universal_argument bindings */
                   1188:   /* Reading vi motion char continuing numeric argument */
                   1189:   else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
                   1190:     {
                   1191:       return (_rl_vi_arg_dispatch (c));
                   1192:     }
                   1193:   /* Readine vi motion char starting numeric argument */
                   1194:   else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
                   1195:     {
                   1196:       RL_SETSTATE (RL_STATE_NUMERICARG);
                   1197:       return (_rl_vi_arg_dispatch (c));
                   1198:     }
                   1199: #endif
                   1200:   else if (_rl_digit_p (c))
                   1201:     {
                   1202:       /* This code path taken when not in callback mode */
                   1203:       save = rl_numeric_arg;
                   1204:       rl_numeric_arg = _rl_digit_value (c);
                   1205:       rl_explicit_arg = 1;
                   1206:       RL_SETSTATE (RL_STATE_NUMERICARG);
                   1207:       rl_digit_loop1 ();
                   1208:       rl_numeric_arg *= save;
                   1209:       c = rl_vi_domove_getchar (m);
                   1210:       if (c < 0)
                   1211:        {
                   1212:          m->motion = 0;
                   1213:          return -1;
                   1214:        }
                   1215:       m->motion = c;
                   1216:       return (rl_domove_motion_callback (m));
                   1217:     }
                   1218:   else
                   1219:     {
                   1220:       RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1221:       RL_UNSETSTATE (RL_STATE_NUMERICARG);
                   1222:       return (1);
                   1223:     }
                   1224: }
                   1225: 
                   1226: static int
                   1227: rl_vi_domove_getchar (m)
                   1228:      _rl_vimotion_cxt *m;
                   1229: {
                   1230:   int c;
                   1231: 
                   1232:   RL_SETSTATE(RL_STATE_MOREINPUT);
                   1233:   c = rl_read_key ();
                   1234:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   1235: 
                   1236:   return c;
                   1237: }
                   1238: 
                   1239: #if defined (READLINE_CALLBACKS)
                   1240: int
                   1241: _rl_vi_domove_callback (m)
                   1242:      _rl_vimotion_cxt *m;
                   1243: {
                   1244:   int c, r;
                   1245: 
                   1246:   m->motion = c = rl_vi_domove_getchar (m);
                   1247:   /* XXX - what to do if this returns -1?  Should we return 1 for eof to
                   1248:      callback code? */
                   1249:   r = rl_domove_read_callback (m);
                   1250: 
                   1251:   return ((r == 0) ? r : 1);   /* normalize return values */
                   1252: }
                   1253: #endif
                   1254: 
                   1255: /* This code path taken when not in callback mode. */
                   1256: int
                   1257: rl_vi_domove (x, ignore)
                   1258:      int x, *ignore;
                   1259: {
                   1260:   int r;
                   1261:   _rl_vimotion_cxt *m;
                   1262: 
                   1263:   m = _rl_vimvcxt;
                   1264:   *ignore = m->motion = rl_vi_domove_getchar (m);
                   1265: 
                   1266:   if (m->motion < 0)
                   1267:     {
                   1268:       m->motion = 0;
                   1269:       return -1;
                   1270:     }
                   1271: 
                   1272:   return (rl_domove_read_callback (m));
                   1273: }
                   1274: 
                   1275: static int
                   1276: vi_delete_dispatch (m)
                   1277:      _rl_vimotion_cxt *m;
                   1278: {
                   1279:   /* These are the motion commands that do not require adjusting the
                   1280:      mark. */
                   1281:   if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
                   1282:       (rl_mark < rl_end))
                   1283:     rl_mark++;
                   1284: 
                   1285:   rl_kill_text (rl_point, rl_mark);
                   1286:   return (0);
                   1287: }
                   1288: 
                   1289: int
                   1290: rl_vi_delete_to (count, key)
                   1291:      int count, key;
                   1292: {
                   1293:   int c, r;
                   1294: 
                   1295:   _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
                   1296:   _rl_vimvcxt->start = rl_point;
                   1297: 
                   1298:   rl_mark = rl_point;
                   1299:   if (_rl_uppercase_p (key))
                   1300:     {
                   1301:       _rl_vimvcxt->motion = '$';
                   1302:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1303:     }
                   1304:   else if (vi_redoing && _rl_vi_last_motion != 'd')    /* `dd' is special */
                   1305:     {
                   1306:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1307:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1308:     }
                   1309:   else if (vi_redoing)         /* handle redoing `dd' here */
                   1310:     {
                   1311:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1312:       rl_mark = rl_end;
                   1313:       rl_beg_of_line (1, key);
                   1314:       RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1315:       r = vidomove_dispatch (_rl_vimvcxt);
                   1316:     }
                   1317: #if defined (READLINE_CALLBACKS)
                   1318:   else if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1319:     {
                   1320:       RL_SETSTATE (RL_STATE_VIMOTION);
                   1321:       return (0);
                   1322:     }
                   1323: #endif
                   1324:   else
                   1325:     r = rl_vi_domove (key, &c);
                   1326: 
                   1327:   if (r < 0)
                   1328:     {
                   1329:       rl_ding ();
                   1330:       r = -1;
                   1331:     }
                   1332: 
                   1333:   _rl_mvcxt_dispose (_rl_vimvcxt);
                   1334:   _rl_vimvcxt = 0;
                   1335: 
                   1336:   return r;
                   1337: }
                   1338: 
                   1339: static int
                   1340: vi_change_dispatch (m)
                   1341:      _rl_vimotion_cxt *m;
                   1342: {
                   1343:   /* These are the motion commands that do not require adjusting the
                   1344:      mark.  c[wW] are handled by special-case code in rl_vi_domove(),
                   1345:      and already leave the mark at the correct location. */
                   1346:   if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
                   1347:       (rl_mark < rl_end))
                   1348:     rl_mark++;
                   1349: 
                   1350:   /* The cursor never moves with c[wW]. */
                   1351:   if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
                   1352:     rl_point = m->start;
                   1353: 
                   1354:   if (vi_redoing)
                   1355:     {
                   1356:       if (vi_insert_buffer && *vi_insert_buffer)
                   1357:        rl_begin_undo_group ();
                   1358:       rl_delete_text (rl_point, rl_mark);
                   1359:       if (vi_insert_buffer && *vi_insert_buffer)
                   1360:        {
                   1361:          rl_insert_text (vi_insert_buffer);
                   1362:          rl_end_undo_group ();
                   1363:        }
                   1364:     }
                   1365:   else
                   1366:     {
                   1367:       rl_begin_undo_group ();          /* to make the `u' command work */
                   1368:       rl_kill_text (rl_point, rl_mark);
                   1369:       /* `C' does not save the text inserted for undoing or redoing. */
                   1370:       if (_rl_uppercase_p (m->key) == 0)
                   1371:        _rl_vi_doing_insert = 1;
                   1372:       /* XXX -- TODO -- use m->numericarg? */
                   1373:       rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
                   1374:     }
                   1375: 
                   1376:   return (0);
                   1377: }
                   1378: 
                   1379: int
                   1380: rl_vi_change_to (count, key)
                   1381:      int count, key;
                   1382: {
                   1383:   int c, r;
                   1384: 
                   1385:   _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
                   1386:   _rl_vimvcxt->start = rl_point;
                   1387: 
                   1388:   rl_mark = rl_point;
                   1389:   if (_rl_uppercase_p (key))
                   1390:     {
                   1391:       _rl_vimvcxt->motion = '$';
                   1392:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1393:     }
                   1394:   else if (vi_redoing && _rl_vi_last_motion != 'c')    /* `cc' is special */
                   1395:     {
                   1396:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1397:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1398:     }
                   1399:   else if (vi_redoing)         /* handle redoing `cc' here */
                   1400:     {
                   1401:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1402:       rl_mark = rl_end;
                   1403:       rl_beg_of_line (1, key);
                   1404:       RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1405:       r = vidomove_dispatch (_rl_vimvcxt);
                   1406:     }
                   1407: #if defined (READLINE_CALLBACKS)
                   1408:   else if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1409:     {
                   1410:       RL_SETSTATE (RL_STATE_VIMOTION);
                   1411:       return (0);
                   1412:     }
                   1413: #endif
                   1414:   else
                   1415:     r = rl_vi_domove (key, &c);
                   1416: 
                   1417:   if (r < 0)
                   1418:     {
                   1419:       rl_ding ();
                   1420:       r = -1;  /* normalize return value */
                   1421:     }
                   1422: 
                   1423:   _rl_mvcxt_dispose (_rl_vimvcxt);
                   1424:   _rl_vimvcxt = 0;
                   1425: 
                   1426:   return r;
                   1427: }
                   1428: 
                   1429: static int
                   1430: vi_yank_dispatch (m)
                   1431:      _rl_vimotion_cxt *m;
                   1432: {
                   1433:   /* These are the motion commands that do not require adjusting the
                   1434:      mark. */
                   1435:   if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
                   1436:       (rl_mark < rl_end))
                   1437:     rl_mark++;
                   1438: 
                   1439:   rl_begin_undo_group ();
                   1440:   rl_kill_text (rl_point, rl_mark);
                   1441:   rl_end_undo_group ();
                   1442:   rl_do_undo ();
                   1443:   rl_point = m->start;
                   1444: 
                   1445:   return (0);
                   1446: }
                   1447: 
                   1448: int
                   1449: rl_vi_yank_to (count, key)
                   1450:      int count, key;
                   1451: {
                   1452:   int c, r;
                   1453: 
                   1454:   _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
                   1455:   _rl_vimvcxt->start = rl_point;
                   1456: 
                   1457:   rl_mark = rl_point;
                   1458:   if (_rl_uppercase_p (key))
                   1459:     {
                   1460:       _rl_vimvcxt->motion = '$';
                   1461:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1462:     }
                   1463:   else if (vi_redoing && _rl_vi_last_motion != 'y')    /* `yy' is special */
                   1464:     {
                   1465:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1466:       r = rl_domove_motion_callback (_rl_vimvcxt);
                   1467:     }
                   1468:   else if (vi_redoing)                 /* handle redoing `yy' here */
                   1469:     {
                   1470:       _rl_vimvcxt->motion = _rl_vi_last_motion;
                   1471:       rl_mark = rl_end;
                   1472:       rl_beg_of_line (1, key);
                   1473:       RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1474:       r = vidomove_dispatch (_rl_vimvcxt);
                   1475:     }
                   1476: #if defined (READLINE_CALLBACKS)
                   1477:   else if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1478:     {
                   1479:       RL_SETSTATE (RL_STATE_VIMOTION);
                   1480:       return (0);
                   1481:     }
                   1482: #endif
                   1483:   else
                   1484:     r = rl_vi_domove (key, &c);
                   1485: 
                   1486:   if (r < 0)
                   1487:     {
                   1488:       rl_ding ();
                   1489:       r = -1;
                   1490:     }
                   1491: 
                   1492:   _rl_mvcxt_dispose (_rl_vimvcxt);
                   1493:   _rl_vimvcxt = 0;
                   1494: 
                   1495:   return r;
                   1496: }
                   1497: 
                   1498: static int
                   1499: vidomove_dispatch (m)
                   1500:      _rl_vimotion_cxt *m;
                   1501: {
                   1502:   int r;
                   1503: 
                   1504:   switch (m->op)
                   1505:     {
                   1506:     case VIM_DELETE:
                   1507:       r = vi_delete_dispatch (m);
                   1508:       break;
                   1509:     case VIM_CHANGE:
                   1510:       r = vi_change_dispatch (m);
                   1511:       break;
                   1512:     case VIM_YANK:
                   1513:       r = vi_yank_dispatch (m);
                   1514:       break;
                   1515:     default:
                   1516:       _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
                   1517:       r = 1;
                   1518:       break;
                   1519:     }
                   1520: 
                   1521:   RL_UNSETSTATE (RL_STATE_VIMOTION);
                   1522:   return r;
                   1523: }
                   1524: 
                   1525: int
                   1526: rl_vi_rubout (count, key)
                   1527:      int count, key;
                   1528: {
                   1529:   int opoint;
                   1530: 
                   1531:   if (count < 0)
                   1532:     return (rl_vi_delete (-count, key));
                   1533: 
                   1534:   if (rl_point == 0)
                   1535:     {
                   1536:       rl_ding ();
                   1537:       return -1;
                   1538:     }
                   1539: 
                   1540:   opoint = rl_point;
                   1541:   if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1542:     rl_backward_char (count, key);
                   1543:   else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1544:     rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
                   1545:   else
                   1546:     rl_point -= count;
                   1547: 
                   1548:   if (rl_point < 0)
                   1549:     rl_point = 0;
                   1550: 
                   1551:   rl_kill_text (rl_point, opoint);
                   1552:   
                   1553:   return (0);
                   1554: }
                   1555: 
                   1556: int
                   1557: rl_vi_delete (count, key)
                   1558:      int count, key;
                   1559: {
                   1560:   int end;
                   1561: 
                   1562:   if (count < 0)
                   1563:     return (rl_vi_rubout (-count, key));
                   1564: 
                   1565:   if (rl_end == 0)
                   1566:     {
                   1567:       rl_ding ();
                   1568:       return -1;
                   1569:     }
                   1570: 
                   1571:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1572:     end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
                   1573:   else
                   1574:     end = rl_point + count;
                   1575: 
                   1576:   if (end >= rl_end)
                   1577:     end = rl_end;
                   1578: 
                   1579:   rl_kill_text (rl_point, end);
                   1580:   
                   1581:   if (rl_point > 0 && rl_point == rl_end)
                   1582:     rl_backward_char (1, key);
                   1583: 
                   1584:   return (0);
                   1585: }
                   1586: 
                   1587: int
                   1588: rl_vi_back_to_indent (count, key)
                   1589:      int count, key;
                   1590: {
                   1591:   rl_beg_of_line (1, key);
                   1592:   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
                   1593:     rl_point++;
                   1594:   return (0);
                   1595: }
                   1596: 
                   1597: int
                   1598: rl_vi_first_print (count, key)
                   1599:      int count, key;
                   1600: {
                   1601:   return (rl_vi_back_to_indent (1, key));
                   1602: }
                   1603: 
                   1604: static int _rl_cs_dir, _rl_cs_orig_dir;
                   1605: 
                   1606: #if defined (READLINE_CALLBACKS)
                   1607: static int
                   1608: _rl_vi_callback_char_search (data)
                   1609:      _rl_callback_generic_arg *data;
                   1610: {
                   1611:   int c;
                   1612: #if defined (HANDLE_MULTIBYTE)
                   1613:   c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
                   1614: #else
                   1615:   RL_SETSTATE(RL_STATE_MOREINPUT);
                   1616:   c = rl_read_key ();
                   1617:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   1618: #endif
                   1619: 
                   1620:   if (c <= 0)
                   1621:     return -1;
                   1622: 
                   1623: #if !defined (HANDLE_MULTIBYTE)
                   1624:   _rl_vi_last_search_char = c;
                   1625: #endif
                   1626: 
                   1627:   _rl_callback_func = 0;
                   1628:   _rl_want_redisplay = 1;
                   1629: 
                   1630: #if defined (HANDLE_MULTIBYTE)
                   1631:   return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
                   1632: #else
                   1633:   return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
                   1634: #endif  
                   1635: }
                   1636: #endif
                   1637: 
                   1638: int
                   1639: rl_vi_char_search (count, key)
                   1640:      int count, key;
                   1641: {
                   1642:   int c;
                   1643: #if defined (HANDLE_MULTIBYTE)
                   1644:   static char *target;
                   1645:   static int tlen;
                   1646: #else
                   1647:   static char target;
                   1648: #endif
                   1649: 
                   1650:   if (key == ';' || key == ',')
                   1651:     {
                   1652:       if (_rl_cs_orig_dir == 0)
                   1653:        return -1;
                   1654: #if defined (HANDLE_MULTIBYTE)
                   1655:       if (_rl_vi_last_search_mblen == 0)
                   1656:        return -1;
                   1657: #else
                   1658:       if (_rl_vi_last_search_char == 0)
                   1659:        return -1;
                   1660: #endif
                   1661:       _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
                   1662:     }
                   1663:   else
                   1664:     {
                   1665:       switch (key)
                   1666:        {
                   1667:        case 't':
                   1668:          _rl_cs_orig_dir = _rl_cs_dir = FTO;
                   1669:          break;
                   1670: 
                   1671:        case 'T':
                   1672:          _rl_cs_orig_dir = _rl_cs_dir = BTO;
                   1673:          break;
                   1674: 
                   1675:        case 'f':
                   1676:          _rl_cs_orig_dir = _rl_cs_dir = FFIND;
                   1677:          break;
                   1678: 
                   1679:        case 'F':
                   1680:          _rl_cs_orig_dir = _rl_cs_dir = BFIND;
                   1681:          break;
                   1682:        }
                   1683: 
                   1684:       if (vi_redoing)
                   1685:        {
                   1686:          /* set target and tlen below */
                   1687:        }
                   1688: #if defined (READLINE_CALLBACKS)
                   1689:       else if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1690:        {
                   1691:          _rl_callback_data = _rl_callback_data_alloc (count);
                   1692:          _rl_callback_data->i1 = _rl_cs_dir;
                   1693:          _rl_callback_func = _rl_vi_callback_char_search;
                   1694:          return (0);
                   1695:        }
                   1696: #endif
                   1697:       else
                   1698:        {
                   1699: #if defined (HANDLE_MULTIBYTE)
                   1700:          c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
                   1701:          if (c <= 0)
                   1702:            return -1;
                   1703:          _rl_vi_last_search_mblen = c;
                   1704: #else
                   1705:          RL_SETSTATE(RL_STATE_MOREINPUT);
                   1706:          c = rl_read_key ();
                   1707:          RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   1708:          if (c < 0)
                   1709:            return -1;
                   1710:          _rl_vi_last_search_char = c;
                   1711: #endif
                   1712:        }
                   1713:     }
                   1714: 
                   1715: #if defined (HANDLE_MULTIBYTE)
                   1716:   target = _rl_vi_last_search_mbchar;
                   1717:   tlen = _rl_vi_last_search_mblen;
                   1718: #else
                   1719:   target = _rl_vi_last_search_char;
                   1720: #endif
                   1721: 
                   1722: #if defined (HANDLE_MULTIBYTE)
                   1723:   return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
                   1724: #else
                   1725:   return (_rl_char_search_internal (count, _rl_cs_dir, target));
                   1726: #endif
                   1727: }
                   1728: 
                   1729: /* Match brackets */
                   1730: int
                   1731: rl_vi_match (ignore, key)
                   1732:      int ignore, key;
                   1733: {
                   1734:   int count = 1, brack, pos, tmp, pre;
                   1735: 
                   1736:   pos = rl_point;
                   1737:   if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
                   1738:     {
                   1739:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1740:        {
                   1741:          while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
                   1742:            {
                   1743:              pre = rl_point;
                   1744:              rl_forward_char (1, key);
                   1745:              if (pre == rl_point)
                   1746:                break;
                   1747:            }
                   1748:        }
                   1749:       else
                   1750:        while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
                   1751:                rl_point < rl_end - 1)
                   1752:          rl_forward_char (1, key);
                   1753: 
                   1754:       if (brack <= 0)
                   1755:        {
                   1756:          rl_point = pos;
                   1757:          rl_ding ();
                   1758:          return -1;
                   1759:        }
                   1760:     }
                   1761: 
                   1762:   pos = rl_point;
                   1763: 
                   1764:   if (brack < 0)
                   1765:     {
                   1766:       while (count)
                   1767:        {
                   1768:          tmp = pos;
                   1769:          if (MB_CUR_MAX == 1 || rl_byte_oriented)
                   1770:            pos--;
                   1771:          else
                   1772:            {
                   1773:              pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
                   1774:              if (tmp == pos)
                   1775:                pos--;
                   1776:            }
                   1777:          if (pos >= 0)
                   1778:            {
                   1779:              int b = rl_vi_bracktype (rl_line_buffer[pos]);
                   1780:              if (b == -brack)
                   1781:                count--;
                   1782:              else if (b == brack)
                   1783:                count++;
                   1784:            }
                   1785:          else
                   1786:            {
                   1787:              rl_ding ();
                   1788:              return -1;
                   1789:            }
                   1790:        }
                   1791:     }
                   1792:   else
                   1793:     {                  /* brack > 0 */
                   1794:       while (count)
                   1795:        {
                   1796:          if (MB_CUR_MAX == 1 || rl_byte_oriented)
                   1797:            pos++;
                   1798:          else
                   1799:            pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
                   1800: 
                   1801:          if (pos < rl_end)
                   1802:            {
                   1803:              int b = rl_vi_bracktype (rl_line_buffer[pos]);
                   1804:              if (b == -brack)
                   1805:                count--;
                   1806:              else if (b == brack)
                   1807:                count++;
                   1808:            }
                   1809:          else
                   1810:            {
                   1811:              rl_ding ();
                   1812:              return -1;
                   1813:            }
                   1814:        }
                   1815:     }
                   1816:   rl_point = pos;
                   1817:   return (0);
                   1818: }
                   1819: 
                   1820: int
                   1821: rl_vi_bracktype (c)
                   1822:      int c;
                   1823: {
                   1824:   switch (c)
                   1825:     {
                   1826:     case '(': return  1;
                   1827:     case ')': return -1;
                   1828:     case '[': return  2;
                   1829:     case ']': return -2;
                   1830:     case '{': return  3;
                   1831:     case '}': return -3;
                   1832:     default:  return  0;
                   1833:     }
                   1834: }
                   1835: 
                   1836: static int
                   1837: _rl_vi_change_char (count, c, mb)
                   1838:      int count, c;
                   1839:      char *mb;
                   1840: {
                   1841:   int p;
                   1842: 
                   1843:   if (c == '\033' || c == CTRL ('C'))
                   1844:     return -1;
                   1845: 
                   1846:   rl_begin_undo_group ();
                   1847:   while (count-- && rl_point < rl_end)
                   1848:     {
                   1849:       p = rl_point;
                   1850:       rl_vi_delete (1, c);
                   1851:       if (rl_point < p)                /* Did we retreat at EOL? */
                   1852:        rl_point++;
                   1853: #if defined (HANDLE_MULTIBYTE)
                   1854:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1855:        rl_insert_text (mb);
                   1856:       else
                   1857: #endif
                   1858:        _rl_insert_char (1, c);
                   1859:     }
                   1860: 
                   1861:   /* The cursor shall be left on the last character changed. */
                   1862:   rl_backward_char (1, c);
                   1863: 
                   1864:   rl_end_undo_group ();
                   1865: 
                   1866:   return (0);
                   1867: }
                   1868: 
                   1869: static int
                   1870: _rl_vi_callback_getchar (mb, mlen)
                   1871:      char *mb;
                   1872:      int mlen;
                   1873: {
                   1874:   int c;
                   1875: 
                   1876:   RL_SETSTATE(RL_STATE_MOREINPUT);
                   1877:   c = rl_read_key ();
                   1878:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   1879: 
                   1880:   if (c < 0)
                   1881:     return -1;
                   1882: 
                   1883: #if defined (HANDLE_MULTIBYTE)
                   1884:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1885:     c = _rl_read_mbstring (c, mb, mlen);
                   1886: #endif
                   1887: 
                   1888:   return c;
                   1889: }
                   1890: 
                   1891: #if defined (READLINE_CALLBACKS)
                   1892: static int
                   1893: _rl_vi_callback_change_char (data)
                   1894:      _rl_callback_generic_arg *data;
                   1895: {
                   1896:   int c;
                   1897:   char mb[MB_LEN_MAX];
                   1898: 
                   1899:   _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
                   1900: 
                   1901:   if (c < 0)
                   1902:     return -1;
                   1903: 
                   1904:   _rl_callback_func = 0;
                   1905:   _rl_want_redisplay = 1;
                   1906: 
                   1907:   return (_rl_vi_change_char (data->count, c, mb));
                   1908: }
                   1909: #endif
                   1910: 
                   1911: int
                   1912: rl_vi_change_char (count, key)
                   1913:      int count, key;
                   1914: {
                   1915:   int c;
                   1916:   char mb[MB_LEN_MAX];
                   1917: 
                   1918:   if (vi_redoing)
                   1919:     {
                   1920:       c = _rl_vi_last_replacement;
                   1921:       mb[0] = c;
                   1922:       mb[1] = '\0';
                   1923:     }
                   1924: #if defined (READLINE_CALLBACKS)
                   1925:   else if (RL_ISSTATE (RL_STATE_CALLBACK))
                   1926:     {
                   1927:       _rl_callback_data = _rl_callback_data_alloc (count);
                   1928:       _rl_callback_func = _rl_vi_callback_change_char;
                   1929:       return (0);
                   1930:     }
                   1931: #endif
                   1932:   else
                   1933:     _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
                   1934: 
                   1935:   if (c < 0)
                   1936:     return -1;
                   1937: 
                   1938:   return (_rl_vi_change_char (count, c, mb));
                   1939: }
                   1940: 
                   1941: int
                   1942: rl_vi_subst (count, key)
                   1943:      int count, key;
                   1944: {
                   1945:   /* If we are redoing, rl_vi_change_to will stuff the last motion char */
                   1946:   if (vi_redoing == 0)
                   1947:     rl_stuff_char ((key == 'S') ? 'c' : 'l');  /* `S' == `cc', `s' == `cl' */
                   1948: 
                   1949:   return (rl_vi_change_to (count, 'c'));
                   1950: }
                   1951: 
                   1952: int
                   1953: rl_vi_overstrike (count, key)
                   1954:      int count, key;
                   1955: {
                   1956:   if (_rl_vi_doing_insert == 0)
                   1957:     {
                   1958:       _rl_vi_doing_insert = 1;
                   1959:       rl_begin_undo_group ();
                   1960:     }
                   1961: 
                   1962:   if (count > 0)
                   1963:     {
                   1964:       _rl_overwrite_char (count, key);
                   1965:       vi_replace_count += count;
                   1966:     }
                   1967: 
                   1968:   return (0);
                   1969: }
                   1970: 
                   1971: int
                   1972: rl_vi_overstrike_delete (count, key)
                   1973:      int count, key;
                   1974: {
                   1975:   int i, s;
                   1976: 
                   1977:   for (i = 0; i < count; i++)
                   1978:     {
                   1979:       if (vi_replace_count == 0)
                   1980:        {
                   1981:          rl_ding ();
                   1982:          break;
                   1983:        }
                   1984:       s = rl_point;
                   1985: 
                   1986:       if (rl_do_undo ())
                   1987:        vi_replace_count--;
                   1988: 
                   1989:       if (rl_point == s)
                   1990:        rl_backward_char (1, key);
                   1991:     }
                   1992: 
                   1993:   if (vi_replace_count == 0 && _rl_vi_doing_insert)
                   1994:     {
                   1995:       rl_end_undo_group ();
                   1996:       rl_do_undo ();
                   1997:       _rl_vi_doing_insert = 0;
                   1998:     }
                   1999:   return (0);
                   2000: }
                   2001: 
                   2002: int
                   2003: rl_vi_replace (count, key)
                   2004:      int count, key;
                   2005: {
                   2006:   int i;
                   2007: 
                   2008:   vi_replace_count = 0;
                   2009: 
                   2010:   if (vi_replace_map == 0)
                   2011:     {
                   2012:       vi_replace_map = rl_make_bare_keymap ();
                   2013: 
                   2014:       for (i = 0; i < ' '; i++)
                   2015:        if (vi_insertion_keymap[i].type == ISFUNC)
                   2016:          vi_replace_map[i].function = vi_insertion_keymap[i].function;
                   2017: 
                   2018:       for (i = ' '; i < KEYMAP_SIZE; i++)
                   2019:        vi_replace_map[i].function = rl_vi_overstrike;
                   2020: 
                   2021:       vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
                   2022: 
                   2023:       /* Make sure these are what we want. */
                   2024:       vi_replace_map[ESC].function = rl_vi_movement_mode;
                   2025:       vi_replace_map[RETURN].function = rl_newline;
                   2026:       vi_replace_map[NEWLINE].function = rl_newline;
                   2027: 
                   2028:       /* If the normal vi insertion keymap has ^H bound to erase, do the
                   2029:         same here.  Probably should remove the assignment to RUBOUT up
                   2030:         there, but I don't think it will make a difference in real life. */
                   2031:       if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
                   2032:          vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
                   2033:        vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
                   2034: 
                   2035:     }
                   2036: 
                   2037:   rl_vi_start_inserting (key, 1, rl_arg_sign);
                   2038: 
                   2039:   _rl_vi_last_key_before_insert = key;
                   2040:   _rl_keymap = vi_replace_map;
                   2041: 
                   2042:   return (0);
                   2043: }
                   2044: 
                   2045: #if 0
                   2046: /* Try to complete the word we are standing on or the word that ends with
                   2047:    the previous character.  A space matches everything.  Word delimiters are
                   2048:    space and ;. */
                   2049: int
                   2050: rl_vi_possible_completions()
                   2051: {
                   2052:   int save_pos = rl_point;
                   2053: 
                   2054:   if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
                   2055:     {
                   2056:       while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
                   2057:             rl_line_buffer[rl_point] != ';')
                   2058:        rl_point++;
                   2059:     }
                   2060:   else if (rl_line_buffer[rl_point - 1] == ';')
                   2061:     {
                   2062:       rl_ding ();
                   2063:       return (0);
                   2064:     }
                   2065: 
                   2066:   rl_possible_completions ();
                   2067:   rl_point = save_pos;
                   2068: 
                   2069:   return (0);
                   2070: }
                   2071: #endif
                   2072: 
                   2073: /* Functions to save and restore marks. */
                   2074: static int
                   2075: _rl_vi_set_mark ()
                   2076: {
                   2077:   int ch;
                   2078: 
                   2079:   RL_SETSTATE(RL_STATE_MOREINPUT);
                   2080:   ch = rl_read_key ();
                   2081:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   2082: 
                   2083:   if (ch < 0 || ch < 'a' || ch > 'z')  /* make test against 0 explicit */
                   2084:     {
                   2085:       rl_ding ();
                   2086:       return -1;
                   2087:     }
                   2088:   ch -= 'a';
                   2089:   vi_mark_chars[ch] = rl_point;
                   2090:   return 0;
                   2091: }
                   2092: 
                   2093: #if defined (READLINE_CALLBACKS)
                   2094: static int
                   2095: _rl_vi_callback_set_mark (data)
                   2096:      _rl_callback_generic_arg *data;
                   2097: {
                   2098:   _rl_callback_func = 0;
                   2099:   _rl_want_redisplay = 1;
                   2100: 
                   2101:   return (_rl_vi_set_mark ());
                   2102: }
                   2103: #endif
                   2104: 
                   2105: int
                   2106: rl_vi_set_mark (count, key)
                   2107:      int count, key;
                   2108: {
                   2109: #if defined (READLINE_CALLBACKS)
                   2110:   if (RL_ISSTATE (RL_STATE_CALLBACK))
                   2111:     {
                   2112:       _rl_callback_data = 0;
                   2113:       _rl_callback_func = _rl_vi_callback_set_mark;
                   2114:       return (0);
                   2115:     }
                   2116: #endif
                   2117: 
                   2118:   return (_rl_vi_set_mark ());
                   2119: }
                   2120: 
                   2121: static int
                   2122: _rl_vi_goto_mark ()
                   2123: {
                   2124:   int ch;
                   2125: 
                   2126:   RL_SETSTATE(RL_STATE_MOREINPUT);
                   2127:   ch = rl_read_key ();
                   2128:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
                   2129: 
                   2130:   if (ch == '`')
                   2131:     {
                   2132:       rl_point = rl_mark;
                   2133:       return 0;
                   2134:     }
                   2135:   else if (ch < 0 || ch < 'a' || ch > 'z')     /* make test against 0 explicit */
                   2136:     {
                   2137:       rl_ding ();
                   2138:       return -1;
                   2139:     }
                   2140: 
                   2141:   ch -= 'a';
                   2142:   if (vi_mark_chars[ch] == -1)
                   2143:     {
                   2144:       rl_ding ();
                   2145:       return -1;
                   2146:     }
                   2147:   rl_point = vi_mark_chars[ch];
                   2148:   return 0;
                   2149: }
                   2150: 
                   2151: #if defined (READLINE_CALLBACKS)
                   2152: static int
                   2153: _rl_vi_callback_goto_mark (data)
                   2154:      _rl_callback_generic_arg *data;
                   2155: {
                   2156:   _rl_callback_func = 0;
                   2157:   _rl_want_redisplay = 1;
                   2158: 
                   2159:   return (_rl_vi_goto_mark ());
                   2160: }
                   2161: #endif
                   2162: 
                   2163: int
                   2164: rl_vi_goto_mark (count, key)
                   2165:      int count, key;
                   2166: {
                   2167: #if defined (READLINE_CALLBACKS)
                   2168:   if (RL_ISSTATE (RL_STATE_CALLBACK))
                   2169:     {
                   2170:       _rl_callback_data = 0;
                   2171:       _rl_callback_func = _rl_vi_callback_goto_mark;
                   2172:       return (0);
                   2173:     }
                   2174: #endif
                   2175: 
                   2176:   return (_rl_vi_goto_mark ());
                   2177: }
                   2178: #endif /* VI_MODE */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>