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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [readline/] [vi_mode.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* 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, 1989, 1992 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 1, 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
   675 Mass Ave, Cambridge, MA 02139, 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 "readline.h"
55
#include "history.h"
56
 
57
#ifndef _rl_digit_p
58
#define _rl_digit_p(c)  ((c) >= '0' && (c) <= '9')
59
#endif
60
 
61
#ifndef _rl_digit_value
62
#define _rl_digit_value(c) ((c) - '0')
63
#endif
64
 
65
#ifndef member
66
#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
67
#endif
68
 
69
#ifndef isident
70
#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_'))
71
#endif
72
 
73
#ifndef exchange
74
#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
75
#endif
76
 
77
extern char *xmalloc (), *xrealloc ();
78
 
79
/* Variables imported from readline.c */
80
extern int rl_point, rl_end, rl_mark;
81
extern FILE *rl_instream;
82
extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
83
extern Keymap _rl_keymap;
84
extern char *rl_prompt;
85
extern char *rl_line_buffer;
86
extern int rl_arg_sign;
87
 
88
extern int _rl_doing_an_undo;
89
extern int _rl_undo_group_level;
90
 
91
extern void _rl_dispatch ();
92
extern int _rl_char_search_internal ();
93
 
94
extern void rl_extend_line_buffer ();
95
extern int rl_vi_check ();
96
 
97
/* Non-zero means enter insertion mode. */
98
static int _rl_vi_doing_insert;
99
 
100
/* Command keys which do movement for xxx_to commands. */
101
static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
102
 
103
/* Keymap used for vi replace characters.  Created dynamically since
104
   rarely used. */
105
static Keymap vi_replace_map;
106
 
107
/* The number of characters inserted in the last replace operation. */
108
static int vi_replace_count;
109
 
110
/* If non-zero, we have text inserted after a c[motion] command that put
111
   us implicitly into insert mode.  Some people want this text to be
112
   attached to the command so that it is `redoable' with `.'. */
113
static int vi_continued_command;
114
static char *vi_insert_buffer;
115
static int vi_insert_buffer_size;
116
 
117
static int _rl_vi_last_command = 'i';   /* default `.' puts you in insert mode */
118
static int _rl_vi_last_repeat = 1;
119
static int _rl_vi_last_arg_sign = 1;
120
static int _rl_vi_last_motion;
121
static int _rl_vi_last_search_char;
122
static int _rl_vi_last_replacement;
123
 
124
static int _rl_vi_last_key_before_insert;
125
 
126
static int vi_redoing;
127
 
128
/* Text modification commands.  These are the `redoable' commands. */
129
static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
130
 
131
/* Arrays for the saved marks. */
132
static int vi_mark_chars[27];
133
 
134
static int rl_digit_loop1 ();
135
 
136
void
137
_rl_vi_initialize_line ()
138
{
139
  register int i;
140
 
141
  for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
142
    vi_mark_chars[i] = -1;
143
}
144
 
145
void
146
_rl_vi_reset_last ()
147
{
148
  _rl_vi_last_command = 'i';
149
  _rl_vi_last_repeat = 1;
150
  _rl_vi_last_arg_sign = 1;
151
  _rl_vi_last_motion = 0;
152
}
153
 
154
void
155
_rl_vi_set_last (key, repeat, sign)
156
     int key, repeat, sign;
157
{
158
  _rl_vi_last_command = key;
159
  _rl_vi_last_repeat = repeat;
160
  _rl_vi_last_arg_sign = sign;
161
}
162
 
163
/* Is the command C a VI mode text modification command? */
164
int
165
_rl_vi_textmod_command (c)
166
     int c;
167
{
168
  return (member (c, vi_textmod));
169
}
170
 
171
static void
172
_rl_vi_stuff_insert (count)
173
     int count;
174
{
175
  rl_begin_undo_group ();
176
  while (count--)
177
    rl_insert_text (vi_insert_buffer);
178
  rl_end_undo_group ();
179
}
180
 
181
/* Bound to `.'.  Called from command mode, so we know that we have to
182
   redo a text modification command.  The default for _rl_vi_last_command
183
   puts you back into insert mode. */
184
int
185
rl_vi_redo (count, c)
186
     int count, c;
187
{
188
  if (!rl_explicit_arg)
189
    {
190
      rl_numeric_arg = _rl_vi_last_repeat;
191
      rl_arg_sign = _rl_vi_last_arg_sign;
192
    }
193
 
194
  vi_redoing = 1;
195
  /* If we're redoing an insert with `i', stuff in the inserted text
196
     and do not go into insertion mode. */
197
  if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
198
    {
199
      _rl_vi_stuff_insert (count);
200
      /* And back up point over the last character inserted. */
201
      if (rl_point > 0)
202
        rl_point--;
203
    }
204
  else
205
    _rl_dispatch (_rl_vi_last_command, _rl_keymap);
206
  vi_redoing = 0;
207
 
208
  return (0);
209
}
210
 
211
/* A placeholder for further expansion. */
212
int
213
rl_vi_undo (count, key)
214
     int count, key;
215
{
216
  return (rl_undo_command (count, key));
217
}
218
 
219
/* Yank the nth arg from the previous line into this line at point. */
220
int
221
rl_vi_yank_arg (count, key)
222
     int count, key;
223
{
224
  /* Readline thinks that the first word on a line is the 0th, while vi
225
     thinks the first word on a line is the 1st.  Compensate. */
226
  if (rl_explicit_arg)
227
    rl_yank_nth_arg (count - 1, 0);
228
  else
229
    rl_yank_nth_arg ('$', 0);
230
 
231
  return (0);
232
}
233
 
234
/* With an argument, move back that many history lines, else move to the
235
   beginning of history. */
236
int
237
rl_vi_fetch_history (count, c)
238
     int count, c;
239
{
240
  int wanted;
241
 
242
  /* Giving an argument of n means we want the nth command in the history
243
     file.  The command number is interpreted the same way that the bash
244
     `history' command does it -- that is, giving an argument count of 450
245
     to this command would get the command listed as number 450 in the
246
     output of `history'. */
247
  if (rl_explicit_arg)
248
    {
249
      wanted = history_base + where_history () - count;
250
      if (wanted <= 0)
251
        rl_beginning_of_history (0, 0);
252
      else
253
        rl_get_previous_history (wanted, c);
254
    }
255
  else
256
    rl_beginning_of_history (count, 0);
257
  return (0);
258
}
259
 
260
/* Search again for the last thing searched for. */
261
int
262
rl_vi_search_again (count, key)
263
     int count, key;
264
{
265
  switch (key)
266
    {
267
    case 'n':
268
      rl_noninc_reverse_search_again (count, key);
269
      break;
270
 
271
    case 'N':
272
      rl_noninc_forward_search_again (count, key);
273
      break;
274
    }
275
  return (0);
276
}
277
 
278
/* Do a vi style search. */
279
int
280
rl_vi_search (count, key)
281
     int count, key;
282
{
283
  switch (key)
284
    {
285
    case '?':
286
      rl_noninc_forward_search (count, key);
287
      break;
288
 
289
    case '/':
290
      rl_noninc_reverse_search (count, key);
291
      break;
292
 
293
    default:
294
      ding ();
295
      break;
296
    }
297
  return (0);
298
}
299
 
300
/* Completion, from vi's point of view. */
301
int
302
rl_vi_complete (ignore, key)
303
     int ignore, key;
304
{
305
  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
306
    {
307
      if (!whitespace (rl_line_buffer[rl_point + 1]))
308
        rl_vi_end_word (1, 'E');
309
      rl_point++;
310
    }
311
 
312
  if (key == '*')
313
    rl_complete_internal ('*'); /* Expansion and replacement. */
314
  else if (key == '=')
315
    rl_complete_internal ('?'); /* List possible completions. */
316
  else if (key == '\\')
317
    rl_complete_internal (TAB); /* Standard Readline completion. */
318
  else
319
    rl_complete (0, key);
320
 
321
  if (key == '*' || key == '\\')
322
    {
323
      _rl_vi_set_last (key, 1, rl_arg_sign);
324
      rl_vi_insertion_mode (1, key);
325
    }
326
  return (0);
327
}
328
 
329
/* Tilde expansion for vi mode. */
330
int
331
rl_vi_tilde_expand (ignore, key)
332
     int ignore, key;
333
{
334
  rl_tilde_expand (0, key);
335
  _rl_vi_set_last (key, 1, rl_arg_sign);        /* XXX */
336
  rl_vi_insertion_mode (1, key);
337
  return (0);
338
}
339
 
340
/* Previous word in vi mode. */
341
int
342
rl_vi_prev_word (count, key)
343
     int count, key;
344
{
345
  if (count < 0)
346
    return (rl_vi_next_word (-count, key));
347
 
348
  if (rl_point == 0)
349
    {
350
      ding ();
351
      return (0);
352
    }
353
 
354
  if (_rl_uppercase_p (key))
355
    rl_vi_bWord (count, key);
356
  else
357
    rl_vi_bword (count, key);
358
 
359
  return (0);
360
}
361
 
362
/* Next word in vi mode. */
363
int
364
rl_vi_next_word (count, key)
365
     int count, key;
366
{
367
  if (count < 0)
368
    return (rl_vi_prev_word (-count, key));
369
 
370
  if (rl_point >= (rl_end - 1))
371
    {
372
      ding ();
373
      return (0);
374
    }
375
 
376
  if (_rl_uppercase_p (key))
377
    rl_vi_fWord (count, key);
378
  else
379
    rl_vi_fword (count, key);
380
  return (0);
381
}
382
 
383
/* Move to the end of the ?next? word. */
384
int
385
rl_vi_end_word (count, key)
386
     int count, key;
387
{
388
  if (count < 0)
389
    {
390
      ding ();
391
      return -1;
392
    }
393
 
394
  if (_rl_uppercase_p (key))
395
    rl_vi_eWord (count, key);
396
  else
397
    rl_vi_eword (count, key);
398
  return (0);
399
}
400
 
401
/* Move forward a word the way that 'W' does. */
402
int
403
rl_vi_fWord (count, ignore)
404
     int count, ignore;
405
{
406
  while (count-- && rl_point < (rl_end - 1))
407
    {
408
      /* Skip until whitespace. */
409
      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
410
        rl_point++;
411
 
412
      /* Now skip whitespace. */
413
      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
414
        rl_point++;
415
    }
416
  return (0);
417
}
418
 
419
int
420
rl_vi_bWord (count, ignore)
421
     int count, ignore;
422
{
423
  while (count-- && rl_point > 0)
424
    {
425
      /* If we are at the start of a word, move back to whitespace so
426
         we will go back to the start of the previous word. */
427
      if (!whitespace (rl_line_buffer[rl_point]) &&
428
          whitespace (rl_line_buffer[rl_point - 1]))
429
        rl_point--;
430
 
431
      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
432
        rl_point--;
433
 
434
      if (rl_point > 0)
435
        {
436
          while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
437
          rl_point++;
438
        }
439
    }
440
  return (0);
441
}
442
 
443
int
444
rl_vi_eWord (count, ignore)
445
     int count, ignore;
446
{
447
  while (count-- && rl_point < (rl_end - 1))
448
    {
449
      if (!whitespace (rl_line_buffer[rl_point]))
450
        rl_point++;
451
 
452
      /* Move to the next non-whitespace character (to the start of the
453
         next word). */
454
      while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
455
 
456
      if (rl_point && rl_point < rl_end)
457
        {
458
          /* Skip whitespace. */
459
          while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
460
            rl_point++;
461
 
462
          /* Skip until whitespace. */
463
          while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
464
            rl_point++;
465
 
466
          /* Move back to the last character of the word. */
467
          rl_point--;
468
        }
469
    }
470
  return (0);
471
}
472
 
473
int
474
rl_vi_fword (count, ignore)
475
     int count, ignore;
476
{
477
  while (count-- && rl_point < (rl_end - 1))
478
    {
479
      /* Move to white space (really non-identifer). */
480
      if (isident (rl_line_buffer[rl_point]))
481
        {
482
          while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
483
            rl_point++;
484
        }
485
      else /* if (!whitespace (rl_line_buffer[rl_point])) */
486
        {
487
          while (!isident (rl_line_buffer[rl_point]) &&
488
                 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
489
            rl_point++;
490
        }
491
 
492
      /* Move past whitespace. */
493
      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
494
        rl_point++;
495
    }
496
  return (0);
497
}
498
 
499
int
500
rl_vi_bword (count, ignore)
501
     int count, ignore;
502
{
503
  while (count-- && rl_point > 0)
504
    {
505
      int last_is_ident;
506
 
507
      /* If we are at the start of a word, move back to whitespace
508
         so we will go back to the start of the previous word. */
509
      if (!whitespace (rl_line_buffer[rl_point]) &&
510
          whitespace (rl_line_buffer[rl_point - 1]))
511
        rl_point--;
512
 
513
      /* If this character and the previous character are `opposite', move
514
         back so we don't get messed up by the rl_point++ down there in
515
         the while loop.  Without this code, words like `l;' screw up the
516
         function. */
517
      last_is_ident = isident (rl_line_buffer[rl_point - 1]);
518
      if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
519
          (!isident (rl_line_buffer[rl_point]) && last_is_ident))
520
        rl_point--;
521
 
522
      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
523
        rl_point--;
524
 
525
      if (rl_point > 0)
526
        {
527
          if (isident (rl_line_buffer[rl_point]))
528
            while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
529
          else
530
            while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
531
                   !whitespace (rl_line_buffer[rl_point]));
532
          rl_point++;
533
        }
534
    }
535
  return (0);
536
}
537
 
538
int
539
rl_vi_eword (count, ignore)
540
     int count, ignore;
541
{
542
  while (count-- && rl_point < rl_end - 1)
543
    {
544
      if (!whitespace (rl_line_buffer[rl_point]))
545
        rl_point++;
546
 
547
      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
548
        rl_point++;
549
 
550
      if (rl_point < rl_end)
551
        {
552
          if (isident (rl_line_buffer[rl_point]))
553
            while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
554
          else
555
            while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
556
                   && !whitespace (rl_line_buffer[rl_point]));
557
        }
558
      rl_point--;
559
    }
560
  return (0);
561
}
562
 
563
int
564
rl_vi_insert_beg (count, key)
565
     int count, key;
566
{
567
  rl_beg_of_line (1, key);
568
  rl_vi_insertion_mode (1, key);
569
  return (0);
570
}
571
 
572
int
573
rl_vi_append_mode (count, key)
574
     int count, key;
575
{
576
  if (rl_point < rl_end)
577
    rl_point++;
578
  rl_vi_insertion_mode (1, key);
579
  return (0);
580
}
581
 
582
int
583
rl_vi_append_eol (count, key)
584
     int count, key;
585
{
586
  rl_end_of_line (1, key);
587
  rl_vi_append_mode (1, key);
588
  return (0);
589
}
590
 
591
/* What to do in the case of C-d. */
592
int
593
rl_vi_eof_maybe (count, c)
594
     int count, c;
595
{
596
  return (rl_newline (1, '\n'));
597
}
598
 
599
/* Insertion mode stuff. */
600
 
601
/* Switching from one mode to the other really just involves
602
   switching keymaps. */
603
int
604
rl_vi_insertion_mode (count, key)
605
     int count, key;
606
{
607
  _rl_keymap = vi_insertion_keymap;
608
  _rl_vi_last_key_before_insert = key;
609
  return (0);
610
}
611
 
612
static void
613
_rl_vi_save_insert (up)
614
      UNDO_LIST *up;
615
{
616
  int len, start, end;
617
 
618
  if (up == 0)
619
    {
620
      if (vi_insert_buffer_size >= 1)
621
        vi_insert_buffer[0] = '\0';
622
      return;
623
    }
624
 
625
  start = up->start;
626
  end = up->end;
627
  len = end - start + 1;
628
  if (len >= vi_insert_buffer_size)
629
    {
630
      vi_insert_buffer_size += (len + 32) - (len % 32);
631
      vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size);
632
    }
633
  strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
634
  vi_insert_buffer[len-1] = '\0';
635
}
636
 
637
void
638
_rl_vi_done_inserting ()
639
{
640
  if (_rl_vi_doing_insert)
641
    {
642
      rl_end_undo_group ();
643
      /* Now, the text between rl_undo_list->next->start and
644
         rl_undo_list->next->end is what was inserted while in insert
645
         mode.  It gets copied to VI_INSERT_BUFFER because it depends
646
         on absolute indices into the line which may change (though they
647
         probably will not). */
648
      _rl_vi_doing_insert = 0;
649
      _rl_vi_save_insert (rl_undo_list->next);
650
      vi_continued_command = 1;
651
    }
652
  else
653
    {
654
      if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
655
        _rl_vi_save_insert (rl_undo_list);
656
      /* XXX - Other keys probably need to be checked. */
657
      else if (_rl_vi_last_key_before_insert == 'C')
658
        rl_end_undo_group ();
659
      while (_rl_undo_group_level > 0)
660
        rl_end_undo_group ();
661
      vi_continued_command = 0;
662
    }
663
}
664
 
665
int
666
rl_vi_movement_mode (count, key)
667
     int count, key;
668
{
669
  if (rl_point > 0)
670
    rl_backward (1, key);
671
 
672
  _rl_keymap = vi_movement_keymap;
673
  _rl_vi_done_inserting ();
674
  return (0);
675
}
676
 
677
int
678
rl_vi_arg_digit (count, c)
679
     int count, c;
680
{
681
  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
682
    return (rl_beg_of_line (1, c));
683
  else
684
    return (rl_digit_argument (count, c));
685
}
686
 
687
int
688
rl_vi_change_case (count, ignore)
689
     int count, ignore;
690
{
691
  char c = 0;
692
 
693
  /* Don't try this on an empty line. */
694
  if (rl_point >= rl_end)
695
    return (0);
696
 
697
  while (count-- && rl_point < rl_end)
698
    {
699
      if (_rl_uppercase_p (rl_line_buffer[rl_point]))
700
        c = _rl_to_lower (rl_line_buffer[rl_point]);
701
      else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
702
        c = _rl_to_upper (rl_line_buffer[rl_point]);
703
      else
704
        {
705
          /* Just skip over characters neither upper nor lower case. */
706
          rl_forward (1, c);
707
          continue;
708
        }
709
 
710
      /* Vi is kind of strange here. */
711
      if (c)
712
        {
713
          rl_begin_undo_group ();
714
          rl_delete (1, c);
715
          rl_insert (1, c);
716
          rl_end_undo_group ();
717
          rl_vi_check ();
718
        }
719
      else
720
        rl_forward (1, c);
721
    }
722
  return (0);
723
}
724
 
725
int
726
rl_vi_put (count, key)
727
     int count, key;
728
{
729
  if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
730
    rl_point++;
731
 
732
  rl_yank (1, key);
733
  rl_backward (1, key);
734
  return (0);
735
}
736
 
737
int
738
rl_vi_check ()
739
{
740
  if (rl_point && rl_point == rl_end)
741
    rl_point--;
742
  return (0);
743
}
744
 
745
int
746
rl_vi_column (count, key)
747
     int count, key;
748
{
749
  if (count > rl_end)
750
    rl_end_of_line (1, key);
751
  else
752
    rl_point = count - 1;
753
  return (0);
754
}
755
 
756
int
757
rl_vi_domove (key, nextkey)
758
     int key, *nextkey;
759
{
760
  int c, save;
761
  int old_end;
762
 
763
  rl_mark = rl_point;
764
  c = rl_read_key ();
765
  *nextkey = c;
766
 
767
  if (!member (c, vi_motion))
768
    {
769
      if (_rl_digit_p (c))
770
        {
771
          save = rl_numeric_arg;
772
          rl_numeric_arg = _rl_digit_value (c);
773
          rl_digit_loop1 ();
774
          rl_numeric_arg *= save;
775
          c = rl_read_key ();   /* real command */
776
          *nextkey = c;
777
        }
778
      else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
779
        {
780
          rl_mark = rl_end;
781
          rl_beg_of_line (1, c);
782
          _rl_vi_last_motion = c;
783
          return (0);
784
        }
785
      else
786
        return (-1);
787
    }
788
 
789
  _rl_vi_last_motion = c;
790
 
791
  /* Append a blank character temporarily so that the motion routines
792
     work right at the end of the line. */
793
  old_end = rl_end;
794
  rl_line_buffer[rl_end++] = ' ';
795
  rl_line_buffer[rl_end] = '\0';
796
 
797
  _rl_dispatch (c, _rl_keymap);
798
 
799
  /* Remove the blank that we added. */
800
  rl_end = old_end;
801
  rl_line_buffer[rl_end] = '\0';
802
  if (rl_point > rl_end)
803
    rl_point = rl_end;
804
 
805
  /* No change in position means the command failed. */
806
  if (rl_mark == rl_point)
807
    return (-1);
808
 
809
  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
810
     word.  If we are not at the end of the line, and we are on a
811
     non-whitespace character, move back one (presumably to whitespace). */
812
  if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
813
      !whitespace (rl_line_buffer[rl_point]))
814
    rl_point--;
815
 
816
  /* If cw or cW, back up to the end of a word, so the behaviour of ce
817
     or cE is the actual result.  Brute-force, no subtlety. */
818
  if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
819
    {
820
      /* Don't move farther back than where we started. */
821
      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
822
        rl_point--;
823
 
824
      /* Posix.2 says that if cw or cW moves the cursor towards the end of
825
         the line, the character under the cursor should be deleted. */
826
      if (rl_point == rl_mark)
827
        rl_point++;
828
      else
829
        {
830
          /* Move past the end of the word so that the kill doesn't
831
             remove the last letter of the previous word.  Only do this
832
             if we are not at the end of the line. */
833
          if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
834
            rl_point++;
835
        }
836
    }
837
 
838
  if (rl_mark < rl_point)
839
    exchange (rl_point, rl_mark);
840
 
841
  return (0);
842
}
843
 
844
/* A simplified loop for vi. Don't dispatch key at end.
845
   Don't recognize minus sign? */
846
static int
847
rl_digit_loop1 ()
848
{
849
  int key, c;
850
 
851
  while (1)
852
    {
853
      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
854
      key = c = rl_read_key ();
855
 
856
      if (_rl_keymap[c].type == ISFUNC &&
857
          _rl_keymap[c].function == rl_universal_argument)
858
        {
859
          rl_numeric_arg *= 4;
860
          continue;
861
        }
862
 
863
      c = UNMETA (c);
864
      if (_rl_digit_p (c))
865
        {
866
          if (rl_explicit_arg)
867
            rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
868
          else
869
            rl_numeric_arg = _rl_digit_value (c);
870
          rl_explicit_arg = 1;
871
        }
872
      else
873
        {
874
          rl_clear_message ();
875
          rl_stuff_char (key);
876
          break;
877
        }
878
    }
879
  return (0);
880
}
881
 
882
int
883
rl_vi_delete_to (count, key)
884
     int count, key;
885
{
886
  int c;
887
 
888
  if (_rl_uppercase_p (key))
889
    rl_stuff_char ('$');
890
  else if (vi_redoing)
891
    rl_stuff_char (_rl_vi_last_motion);
892
 
893
  if (rl_vi_domove (key, &c))
894
    {
895
      ding ();
896
      return -1;
897
    }
898
 
899
  /* These are the motion commands that do not require adjusting the
900
     mark. */
901
  if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
902
    rl_mark++;
903
 
904
  rl_kill_text (rl_point, rl_mark);
905
  return (0);
906
}
907
 
908
int
909
rl_vi_change_to (count, key)
910
     int count, key;
911
{
912
  int c, start_pos;
913
 
914
  if (_rl_uppercase_p (key))
915
    rl_stuff_char ('$');
916
  else if (vi_redoing)
917
    rl_stuff_char (_rl_vi_last_motion);
918
 
919
  start_pos = rl_point;
920
 
921
  if (rl_vi_domove (key, &c))
922
    {
923
      ding ();
924
      return -1;
925
    }
926
 
927
  /* These are the motion commands that do not require adjusting the
928
     mark.  c[wW] are handled by special-case code in rl_vi_domove(),
929
     and already leave the mark at the correct location. */
930
  if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
931
    rl_mark++;
932
 
933
  /* The cursor never moves with c[wW]. */
934
  if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
935
    rl_point = start_pos;
936
 
937
  if (vi_redoing)
938
    {
939
      if (vi_insert_buffer && *vi_insert_buffer)
940
        rl_begin_undo_group ();
941
      rl_delete_text (rl_point, rl_mark);
942
      if (vi_insert_buffer && *vi_insert_buffer)
943
        {
944
          rl_insert_text (vi_insert_buffer);
945
          rl_end_undo_group ();
946
        }
947
    }
948
  else
949
    {
950
      rl_begin_undo_group ();           /* to make the `u' command work */
951
      rl_kill_text (rl_point, rl_mark);
952
      /* `C' does not save the text inserted for undoing or redoing. */
953
      if (_rl_uppercase_p (key) == 0)
954
        _rl_vi_doing_insert = 1;
955
      _rl_vi_set_last (key, count, rl_arg_sign);
956
      rl_vi_insertion_mode (1, key);
957
    }
958
 
959
  return (0);
960
}
961
 
962
int
963
rl_vi_yank_to (count, key)
964
     int count, key;
965
{
966
  int c, save = rl_point;
967
 
968
  if (_rl_uppercase_p (key))
969
    rl_stuff_char ('$');
970
 
971
  if (rl_vi_domove (key, &c))
972
    {
973
      ding ();
974
      return -1;
975
    }
976
 
977
  /* These are the motion commands that do not require adjusting the
978
     mark. */
979
  if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
980
    rl_mark++;
981
 
982
  rl_begin_undo_group ();
983
  rl_kill_text (rl_point, rl_mark);
984
  rl_end_undo_group ();
985
  rl_do_undo ();
986
  rl_point = save;
987
 
988
  return (0);
989
}
990
 
991
int
992
rl_vi_delete (count, key)
993
     int count, key;
994
{
995
  int end;
996
 
997
  if (rl_end == 0)
998
    {
999
      ding ();
1000
      return -1;
1001
    }
1002
 
1003
  end = rl_point + count;
1004
 
1005
  if (end >= rl_end)
1006
    end = rl_end;
1007
 
1008
  rl_kill_text (rl_point, end);
1009
 
1010
  if (rl_point > 0 && rl_point == rl_end)
1011
    rl_backward (1, key);
1012
  return (0);
1013
}
1014
 
1015
int
1016
rl_vi_back_to_indent (count, key)
1017
     int count, key;
1018
{
1019
  rl_beg_of_line (1, key);
1020
  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1021
    rl_point++;
1022
  return (0);
1023
}
1024
 
1025
int
1026
rl_vi_first_print (count, key)
1027
     int count, key;
1028
{
1029
  return (rl_vi_back_to_indent (1, key));
1030
}
1031
 
1032
int
1033
rl_vi_char_search (count, key)
1034
     int count, key;
1035
{
1036
  static char target;
1037
  static int orig_dir, dir;
1038
 
1039
  if (key == ';' || key == ',')
1040
    dir = key == ';' ? orig_dir : -orig_dir;
1041
  else
1042
    {
1043
      if (vi_redoing)
1044
        target = _rl_vi_last_search_char;
1045
      else
1046
        _rl_vi_last_search_char = target = rl_getc (rl_instream);
1047
 
1048
      switch (key)
1049
        {
1050
        case 't':
1051
          orig_dir = dir = FTO;
1052
          break;
1053
 
1054
        case 'T':
1055
          orig_dir = dir = BTO;
1056
          break;
1057
 
1058
        case 'f':
1059
          orig_dir = dir = FFIND;
1060
          break;
1061
 
1062
        case 'F':
1063
          orig_dir = dir = BFIND;
1064
          break;
1065
        }
1066
    }
1067
 
1068
  return (_rl_char_search_internal (count, dir, target));
1069
}
1070
 
1071
/* Match brackets */
1072
int
1073
rl_vi_match (ignore, key)
1074
     int ignore, key;
1075
{
1076
  int count = 1, brack, pos;
1077
 
1078
  pos = rl_point;
1079
  if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1080
    {
1081
      while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1082
             rl_point < rl_end - 1)
1083
        rl_forward (1, key);
1084
 
1085
      if (brack <= 0)
1086
        {
1087
          rl_point = pos;
1088
          ding ();
1089
          return -1;
1090
        }
1091
    }
1092
 
1093
  pos = rl_point;
1094
 
1095
  if (brack < 0)
1096
    {
1097
      while (count)
1098
        {
1099
          if (--pos >= 0)
1100
            {
1101
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
1102
              if (b == -brack)
1103
                count--;
1104
              else if (b == brack)
1105
                count++;
1106
            }
1107
          else
1108
            {
1109
              ding ();
1110
              return -1;
1111
            }
1112
        }
1113
    }
1114
  else
1115
    {                   /* brack > 0 */
1116
      while (count)
1117
        {
1118
          if (++pos < rl_end)
1119
            {
1120
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
1121
              if (b == -brack)
1122
                count--;
1123
              else if (b == brack)
1124
                count++;
1125
            }
1126
          else
1127
            {
1128
              ding ();
1129
              return -1;
1130
            }
1131
        }
1132
    }
1133
  rl_point = pos;
1134
  return (0);
1135
}
1136
 
1137
int
1138
rl_vi_bracktype (c)
1139
     int c;
1140
{
1141
  switch (c)
1142
    {
1143
    case '(': return  1;
1144
    case ')': return -1;
1145
    case '[': return  2;
1146
    case ']': return -2;
1147
    case '{': return  3;
1148
    case '}': return -3;
1149
    default:  return  0;
1150
    }
1151
}
1152
 
1153
int
1154
rl_vi_change_char (count, key)
1155
     int count, key;
1156
{
1157
  int c;
1158
 
1159
  if (vi_redoing)
1160
    c = _rl_vi_last_replacement;
1161
  else
1162
    _rl_vi_last_replacement = c = rl_getc (rl_instream);
1163
 
1164
  if (c == '\033' || c == CTRL ('C'))
1165
    return -1;
1166
 
1167
  while (count-- && rl_point < rl_end)
1168
    {
1169
      rl_begin_undo_group ();
1170
 
1171
      rl_delete (1, c);
1172
      rl_insert (1, c);
1173
      if (count == 0)
1174
        rl_backward (1, c);
1175
 
1176
      rl_end_undo_group ();
1177
    }
1178
  return (0);
1179
}
1180
 
1181
int
1182
rl_vi_subst (count, key)
1183
     int count, key;
1184
{
1185
  rl_begin_undo_group ();
1186
 
1187
  if (_rl_uppercase_p (key))
1188
    {
1189
      rl_beg_of_line (1, key);
1190
      rl_kill_line (1, key);
1191
    }
1192
  else
1193
    rl_delete_text (rl_point, rl_point+count);
1194
 
1195
  rl_end_undo_group ();
1196
 
1197
  _rl_vi_set_last (key, count, rl_arg_sign);
1198
 
1199
  if (vi_redoing)
1200
    {
1201
      int o = _rl_doing_an_undo;
1202
 
1203
      _rl_doing_an_undo = 1;
1204
      if (vi_insert_buffer && *vi_insert_buffer)
1205
        rl_insert_text (vi_insert_buffer);
1206
      _rl_doing_an_undo = o;
1207
    }
1208
  else
1209
    {
1210
      rl_begin_undo_group ();
1211
      _rl_vi_doing_insert = 1;
1212
      rl_vi_insertion_mode (1, key);
1213
    }
1214
 
1215
  return (0);
1216
}
1217
 
1218
int
1219
rl_vi_overstrike (count, key)
1220
     int count, key;
1221
{
1222
  int i;
1223
 
1224
  if (_rl_vi_doing_insert == 0)
1225
    {
1226
      _rl_vi_doing_insert = 1;
1227
      rl_begin_undo_group ();
1228
    }
1229
 
1230
  for (i = 0; i < count; i++)
1231
    {
1232
      vi_replace_count++;
1233
      rl_begin_undo_group ();
1234
 
1235
      if (rl_point < rl_end)
1236
        {
1237
          rl_delete (1, key);
1238
          rl_insert (1, key);
1239
        }
1240
      else
1241
        rl_insert (1, key);
1242
 
1243
      rl_end_undo_group ();
1244
    }
1245
  return (0);
1246
}
1247
 
1248
int
1249
rl_vi_overstrike_delete (count, key)
1250
     int count, key;
1251
{
1252
  int i, s;
1253
 
1254
  for (i = 0; i < count; i++)
1255
    {
1256
      if (vi_replace_count == 0)
1257
        {
1258
          ding ();
1259
          break;
1260
        }
1261
      s = rl_point;
1262
 
1263
      if (rl_do_undo ())
1264
        vi_replace_count--;
1265
 
1266
      if (rl_point == s)
1267
        rl_backward (1, key);
1268
    }
1269
 
1270
  if (vi_replace_count == 0 && _rl_vi_doing_insert)
1271
    {
1272
      rl_end_undo_group ();
1273
      rl_do_undo ();
1274
      _rl_vi_doing_insert = 0;
1275
    }
1276
  return (0);
1277
}
1278
 
1279
int
1280
rl_vi_replace (count, key)
1281
     int count, key;
1282
{
1283
  int i;
1284
 
1285
  vi_replace_count = 0;
1286
 
1287
  if (!vi_replace_map)
1288
    {
1289
      vi_replace_map = rl_make_bare_keymap ();
1290
 
1291
      for (i = ' '; i < KEYMAP_SIZE; i++)
1292
        vi_replace_map[i].function = rl_vi_overstrike;
1293
 
1294
      vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1295
      vi_replace_map[ESC].function = rl_vi_movement_mode;
1296
      vi_replace_map[RETURN].function = rl_newline;
1297
      vi_replace_map[NEWLINE].function = rl_newline;
1298
 
1299
      /* If the normal vi insertion keymap has ^H bound to erase, do the
1300
         same here.  Probably should remove the assignment to RUBOUT up
1301
         there, but I don't think it will make a difference in real life. */
1302
      if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1303
          vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1304
        vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1305
 
1306
    }
1307
  _rl_keymap = vi_replace_map;
1308
  return (0);
1309
}
1310
 
1311
#if 0
1312
/* Try to complete the word we are standing on or the word that ends with
1313
   the previous character.  A space matches everything.  Word delimiters are
1314
   space and ;. */
1315
int
1316
rl_vi_possible_completions()
1317
{
1318
  int save_pos = rl_point;
1319
 
1320
  if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1321
    {
1322
      while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1323
             rl_line_buffer[rl_point] != ';')
1324
        rl_point++;
1325
    }
1326
  else if (rl_line_buffer[rl_point - 1] == ';')
1327
    {
1328
      ding ();
1329
      return (0);
1330
    }
1331
 
1332
  rl_possible_completions ();
1333
  rl_point = save_pos;
1334
 
1335
  return (0);
1336
}
1337
#endif
1338
 
1339
/* Functions to save and restore marks. */
1340
int
1341
rl_vi_set_mark (count, key)
1342
     int count, key;
1343
{
1344
  int ch;
1345
 
1346
  ch = rl_read_key ();
1347
  if (_rl_lowercase_p (ch) == 0)
1348
    {
1349
      ding ();
1350
      return -1;
1351
    }
1352
  ch -= 'a';
1353
  vi_mark_chars[ch] = rl_point;
1354
  return 0;
1355
}
1356
 
1357
int
1358
rl_vi_goto_mark (count, key)
1359
     int count, key;
1360
{
1361
  int ch;
1362
 
1363
  ch = rl_read_key ();
1364
  if (ch == '`')
1365
    {
1366
      rl_point = rl_mark;
1367
      return 0;
1368
    }
1369
  else if (_rl_lowercase_p (ch) == 0)
1370
    {
1371
      ding ();
1372
      return -1;
1373
    }
1374
 
1375
  ch -= 'a';
1376
  if (vi_mark_chars[ch] == -1)
1377
    {
1378
      ding ();
1379
      return -1;
1380
    }
1381
  rl_point = vi_mark_chars[ch];
1382
  return 0;
1383
}
1384
 
1385
#endif /* VI_MODE */

powered by: WebSVN 2.1.0

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