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

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

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