OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [readline/] [vi_mode.c] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.