~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to cmd-line-utils/libedit/vi.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: vi.c,v 1.28 2009/02/06 13:14:37 sketch Exp $   */
 
2
 
 
3
/*-
 
4
 * Copyright (c) 1992, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
6
 *
 
7
 * This code is derived from software contributed to Berkeley by
 
8
 * Christos Zoulas of Cornell University.
 
9
 *
 
10
 * Redistribution and use in source and binary forms, with or without
 
11
 * modification, are permitted provided that the following conditions
 
12
 * are met:
 
13
 * 1. Redistributions of source code must retain the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer.
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in the
 
17
 *    documentation and/or other materials provided with the distribution.
 
18
 * 3. Neither the name of the University nor the names of its contributors
 
19
 *    may be used to endorse or promote products derived from this software
 
20
 *    without specific prior written permission.
 
21
 *
 
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
32
 * SUCH DAMAGE.
 
33
 */
 
34
 
 
35
#include "config.h"
 
36
#include <stdlib.h>
 
37
#include <unistd.h>
 
38
#include <sys/wait.h>
 
39
 
 
40
#if !defined(lint) && !defined(SCCSID)
 
41
#if 0
 
42
static char sccsid[] = "@(#)vi.c        8.1 (Berkeley) 6/4/93";
 
43
#else
 
44
#endif
 
45
#endif /* not lint && not SCCSID */
 
46
 
 
47
/*
 
48
 * vi.c: Vi mode commands.
 
49
 */
 
50
#include "el.h"
 
51
 
 
52
private el_action_t     cv_action(EditLine *, int);
 
53
private el_action_t     cv_paste(EditLine *, int);
 
54
 
 
55
/* cv_action():
 
56
 *      Handle vi actions.
 
57
 */
 
58
private el_action_t
 
59
cv_action(EditLine *el, int c)
 
60
{
 
61
 
 
62
        if (el->el_chared.c_vcmd.action != NOP) {
 
63
                /* 'cc', 'dd' and (possibly) friends */
 
64
                if (c != el->el_chared.c_vcmd.action)
 
65
                        return CC_ERROR;
 
66
 
 
67
                if (!(c & YANK))
 
68
                        cv_undo(el);
 
69
                cv_yank(el, el->el_line.buffer,
 
70
                            el->el_line.lastchar - el->el_line.buffer);
 
71
                el->el_chared.c_vcmd.action = NOP;
 
72
                el->el_chared.c_vcmd.pos = 0;
 
73
                if (!(c & YANK)) {
 
74
                        el->el_line.lastchar = el->el_line.buffer;
 
75
                        el->el_line.cursor = el->el_line.buffer;
 
76
                }
 
77
                if (c & INSERT)
 
78
                        el->el_map.current = el->el_map.key;
 
79
 
 
80
                return (CC_REFRESH);
 
81
        }
 
82
        el->el_chared.c_vcmd.pos = el->el_line.cursor;
 
83
        el->el_chared.c_vcmd.action = c;
 
84
        return (CC_ARGHACK);
 
85
}
 
86
 
 
87
/* cv_paste():
 
88
 *      Paste previous deletion before or after the cursor
 
89
 */
 
90
private el_action_t
 
91
cv_paste(EditLine *el, int c)
 
92
{
 
93
        c_kill_t *k = &el->el_chared.c_kill;
 
94
        int len = k->last - k->buf;
 
95
 
 
96
        if (k->buf == NULL || len == 0)
 
97
                return (CC_ERROR);
 
98
#ifdef DEBUG_PASTE
 
99
        (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf);
 
100
#endif
 
101
 
 
102
        cv_undo(el);
 
103
 
 
104
        if (!c && el->el_line.cursor < el->el_line.lastchar)
 
105
                el->el_line.cursor++;
 
106
 
 
107
        c_insert(el, len);
 
108
        if (el->el_line.cursor + len > el->el_line.lastchar)
 
109
                return (CC_ERROR);
 
110
        (void) memcpy(el->el_line.cursor, k->buf, len +0u);
 
111
 
 
112
        return (CC_REFRESH);
 
113
}
 
114
 
 
115
 
 
116
/* vi_paste_next():
 
117
 *      Vi paste previous deletion to the right of the cursor
 
118
 *      [p]
 
119
 */
 
120
protected el_action_t
 
121
/*ARGSUSED*/
 
122
vi_paste_next(EditLine *el, int c __attribute__((__unused__)))
 
123
{
 
124
 
 
125
        return (cv_paste(el, 0));
 
126
}
 
127
 
 
128
 
 
129
/* vi_paste_prev():
 
130
 *      Vi paste previous deletion to the left of the cursor
 
131
 *      [P]
 
132
 */
 
133
protected el_action_t
 
134
/*ARGSUSED*/
 
135
vi_paste_prev(EditLine *el, int c __attribute__((__unused__)))
 
136
{
 
137
 
 
138
        return (cv_paste(el, 1));
 
139
}
 
140
 
 
141
 
 
142
/* vi_prev_big_word():
 
143
 *      Vi move to the previous space delimited word
 
144
 *      [B]
 
145
 */
 
146
protected el_action_t
 
147
/*ARGSUSED*/
 
148
vi_prev_big_word(EditLine *el, int c)
 
149
{
 
150
 
 
151
        if (el->el_line.cursor == el->el_line.buffer)
 
152
                return (CC_ERROR);
 
153
 
 
154
        el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 
155
            el->el_line.buffer,
 
156
            el->el_state.argument,
 
157
            cv__isWord);
 
158
 
 
159
        if (el->el_chared.c_vcmd.action != NOP) {
 
160
                cv_delfini(el);
 
161
                return (CC_REFRESH);
 
162
        }
 
163
        return (CC_CURSOR);
 
164
}
 
165
 
 
166
 
 
167
/* vi_prev_word():
 
168
 *      Vi move to the previous word
 
169
 *      [b]
 
170
 */
 
171
protected el_action_t
 
172
/*ARGSUSED*/
 
173
vi_prev_word(EditLine *el, int c __attribute__((__unused__)))
 
174
{
 
175
 
 
176
        if (el->el_line.cursor == el->el_line.buffer)
 
177
                return (CC_ERROR);
 
178
 
 
179
        el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 
180
            el->el_line.buffer,
 
181
            el->el_state.argument,
 
182
            cv__isword);
 
183
 
 
184
        if (el->el_chared.c_vcmd.action != NOP) {
 
185
                cv_delfini(el);
 
186
                return (CC_REFRESH);
 
187
        }
 
188
        return (CC_CURSOR);
 
189
}
 
190
 
 
191
 
 
192
/* vi_next_big_word():
 
193
 *      Vi move to the next space delimited word
 
194
 *      [W]
 
195
 */
 
196
protected el_action_t
 
197
/*ARGSUSED*/
 
198
vi_next_big_word(EditLine *el, int c)
 
199
{
 
200
 
 
201
        if (el->el_line.cursor >= el->el_line.lastchar - 1)
 
202
                return (CC_ERROR);
 
203
 
 
204
        el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
 
205
            el->el_line.lastchar, el->el_state.argument, cv__isWord);
 
206
 
 
207
        if (el->el_map.type == MAP_VI)
 
208
                if (el->el_chared.c_vcmd.action != NOP) {
 
209
                        cv_delfini(el);
 
210
                        return (CC_REFRESH);
 
211
                }
 
212
        return (CC_CURSOR);
 
213
}
 
214
 
 
215
 
 
216
/* vi_next_word():
 
217
 *      Vi move to the next word
 
218
 *      [w]
 
219
 */
 
220
protected el_action_t
 
221
/*ARGSUSED*/
 
222
vi_next_word(EditLine *el, int c __attribute__((__unused__)))
 
223
{
 
224
 
 
225
        if (el->el_line.cursor >= el->el_line.lastchar - 1)
 
226
                return (CC_ERROR);
 
227
 
 
228
        el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
 
229
            el->el_line.lastchar, el->el_state.argument, cv__isword);
 
230
 
 
231
        if (el->el_map.type == MAP_VI)
 
232
                if (el->el_chared.c_vcmd.action != NOP) {
 
233
                        cv_delfini(el);
 
234
                        return (CC_REFRESH);
 
235
                }
 
236
        return (CC_CURSOR);
 
237
}
 
238
 
 
239
 
 
240
/* vi_change_case():
 
241
 *      Vi change case of character under the cursor and advance one character
 
242
 *      [~]
 
243
 */
 
244
protected el_action_t
 
245
vi_change_case(EditLine *el, int c)
 
246
{
 
247
        int i;
 
248
 
 
249
        if (el->el_line.cursor >= el->el_line.lastchar)
 
250
                return (CC_ERROR);
 
251
        cv_undo(el);
 
252
        for (i = 0; i < el->el_state.argument; i++) {
 
253
 
 
254
                c = *(unsigned char *)el->el_line.cursor;
 
255
                if (isupper(c))
 
256
                        *el->el_line.cursor = tolower(c);
 
257
                else if (islower(c))
 
258
                        *el->el_line.cursor = toupper(c);
 
259
 
 
260
                if (++el->el_line.cursor >= el->el_line.lastchar) {
 
261
                        el->el_line.cursor--;
 
262
                        re_fastaddc(el);
 
263
                        break;
 
264
                }
 
265
                re_fastaddc(el);
 
266
        }
 
267
        return CC_NORM;
 
268
}
 
269
 
 
270
 
 
271
/* vi_change_meta():
 
272
 *      Vi change prefix command
 
273
 *      [c]
 
274
 */
 
275
protected el_action_t
 
276
/*ARGSUSED*/
 
277
vi_change_meta(EditLine *el, int c __attribute__((__unused__)))
 
278
{
 
279
 
 
280
        /*
 
281
         * Delete with insert == change: first we delete and then we leave in
 
282
         * insert mode.
 
283
         */
 
284
        return (cv_action(el, DELETE | INSERT));
 
285
}
 
286
 
 
287
 
 
288
/* vi_insert_at_bol():
 
289
 *      Vi enter insert mode at the beginning of line
 
290
 *      [I]
 
291
 */
 
292
protected el_action_t
 
293
/*ARGSUSED*/
 
294
vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__)))
 
295
{
 
296
 
 
297
        el->el_line.cursor = el->el_line.buffer;
 
298
        cv_undo(el);
 
299
        el->el_map.current = el->el_map.key;
 
300
        return (CC_CURSOR);
 
301
}
 
302
 
 
303
 
 
304
/* vi_replace_char():
 
305
 *      Vi replace character under the cursor with the next character typed
 
306
 *      [r]
 
307
 */
 
308
protected el_action_t
 
309
/*ARGSUSED*/
 
310
vi_replace_char(EditLine *el, int c __attribute__((__unused__)))
 
311
{
 
312
 
 
313
        if (el->el_line.cursor >= el->el_line.lastchar)
 
314
                return CC_ERROR;
 
315
 
 
316
        el->el_map.current = el->el_map.key;
 
317
        el->el_state.inputmode = MODE_REPLACE_1;
 
318
        cv_undo(el);
 
319
        return (CC_ARGHACK);
 
320
}
 
321
 
 
322
 
 
323
/* vi_replace_mode():
 
324
 *      Vi enter replace mode
 
325
 *      [R]
 
326
 */
 
327
protected el_action_t
 
328
/*ARGSUSED*/
 
329
vi_replace_mode(EditLine *el, int c __attribute__((__unused__)))
 
330
{
 
331
 
 
332
        el->el_map.current = el->el_map.key;
 
333
        el->el_state.inputmode = MODE_REPLACE;
 
334
        cv_undo(el);
 
335
        return (CC_NORM);
 
336
}
 
337
 
 
338
 
 
339
/* vi_substitute_char():
 
340
 *      Vi replace character under the cursor and enter insert mode
 
341
 *      [s]
 
342
 */
 
343
protected el_action_t
 
344
/*ARGSUSED*/
 
345
vi_substitute_char(EditLine *el, int c __attribute__((__unused__)))
 
346
{
 
347
 
 
348
        c_delafter(el, el->el_state.argument);
 
349
        el->el_map.current = el->el_map.key;
 
350
        return (CC_REFRESH);
 
351
}
 
352
 
 
353
 
 
354
/* vi_substitute_line():
 
355
 *      Vi substitute entire line
 
356
 *      [S]
 
357
 */
 
358
protected el_action_t
 
359
/*ARGSUSED*/
 
360
vi_substitute_line(EditLine *el, int c __attribute__((__unused__)))
 
361
{
 
362
 
 
363
        cv_undo(el);
 
364
        cv_yank(el, el->el_line.buffer,
 
365
                    el->el_line.lastchar - el->el_line.buffer);
 
366
        (void) em_kill_line(el, 0);
 
367
        el->el_map.current = el->el_map.key;
 
368
        return (CC_REFRESH);
 
369
}
 
370
 
 
371
 
 
372
/* vi_change_to_eol():
 
373
 *      Vi change to end of line
 
374
 *      [C]
 
375
 */
 
376
protected el_action_t
 
377
/*ARGSUSED*/
 
378
vi_change_to_eol(EditLine *el, int c __attribute__((__unused__)))
 
379
{
 
380
 
 
381
        cv_undo(el);
 
382
        cv_yank(el, el->el_line.cursor,
 
383
                    el->el_line.lastchar - el->el_line.cursor);
 
384
        (void) ed_kill_line(el, 0);
 
385
        el->el_map.current = el->el_map.key;
 
386
        return (CC_REFRESH);
 
387
}
 
388
 
 
389
 
 
390
/* vi_insert():
 
391
 *      Vi enter insert mode
 
392
 *      [i]
 
393
 */
 
394
protected el_action_t
 
395
/*ARGSUSED*/
 
396
vi_insert(EditLine *el, int c __attribute__((__unused__)))
 
397
{
 
398
 
 
399
        el->el_map.current = el->el_map.key;
 
400
        cv_undo(el);
 
401
        return (CC_NORM);
 
402
}
 
403
 
 
404
 
 
405
/* vi_add():
 
406
 *      Vi enter insert mode after the cursor
 
407
 *      [a]
 
408
 */
 
409
protected el_action_t
 
410
/*ARGSUSED*/
 
411
vi_add(EditLine *el, int c __attribute__((__unused__)))
 
412
{
 
413
        int ret;
 
414
 
 
415
        el->el_map.current = el->el_map.key;
 
416
        if (el->el_line.cursor < el->el_line.lastchar) {
 
417
                el->el_line.cursor++;
 
418
                if (el->el_line.cursor > el->el_line.lastchar)
 
419
                        el->el_line.cursor = el->el_line.lastchar;
 
420
                ret = CC_CURSOR;
 
421
        } else
 
422
                ret = CC_NORM;
 
423
 
 
424
        cv_undo(el);
 
425
 
 
426
        return (ret);
 
427
}
 
428
 
 
429
 
 
430
/* vi_add_at_eol():
 
431
 *      Vi enter insert mode at end of line
 
432
 *      [A]
 
433
 */
 
434
protected el_action_t
 
435
/*ARGSUSED*/
 
436
vi_add_at_eol(EditLine *el, int c __attribute__((__unused__)))
 
437
{
 
438
 
 
439
        el->el_map.current = el->el_map.key;
 
440
        el->el_line.cursor = el->el_line.lastchar;
 
441
        cv_undo(el);
 
442
        return (CC_CURSOR);
 
443
}
 
444
 
 
445
 
 
446
/* vi_delete_meta():
 
447
 *      Vi delete prefix command
 
448
 *      [d]
 
449
 */
 
450
protected el_action_t
 
451
/*ARGSUSED*/
 
452
vi_delete_meta(EditLine *el, int c __attribute__((__unused__)))
 
453
{
 
454
 
 
455
        return (cv_action(el, DELETE));
 
456
}
 
457
 
 
458
 
 
459
/* vi_end_big_word():
 
460
 *      Vi move to the end of the current space delimited word
 
461
 *      [E]
 
462
 */
 
463
protected el_action_t
 
464
/*ARGSUSED*/
 
465
vi_end_big_word(EditLine *el, int c)
 
466
{
 
467
 
 
468
        if (el->el_line.cursor == el->el_line.lastchar)
 
469
                return (CC_ERROR);
 
470
 
 
471
        el->el_line.cursor = cv__endword(el->el_line.cursor,
 
472
            el->el_line.lastchar, el->el_state.argument, cv__isWord);
 
473
 
 
474
        if (el->el_chared.c_vcmd.action != NOP) {
 
475
                el->el_line.cursor++;
 
476
                cv_delfini(el);
 
477
                return (CC_REFRESH);
 
478
        }
 
479
        return (CC_CURSOR);
 
480
}
 
481
 
 
482
 
 
483
/* vi_end_word():
 
484
 *      Vi move to the end of the current word
 
485
 *      [e]
 
486
 */
 
487
protected el_action_t
 
488
/*ARGSUSED*/
 
489
vi_end_word(EditLine *el, int c __attribute__((__unused__)))
 
490
{
 
491
 
 
492
        if (el->el_line.cursor == el->el_line.lastchar)
 
493
                return (CC_ERROR);
 
494
 
 
495
        el->el_line.cursor = cv__endword(el->el_line.cursor,
 
496
            el->el_line.lastchar, el->el_state.argument, cv__isword);
 
497
 
 
498
        if (el->el_chared.c_vcmd.action != NOP) {
 
499
                el->el_line.cursor++;
 
500
                cv_delfini(el);
 
501
                return (CC_REFRESH);
 
502
        }
 
503
        return (CC_CURSOR);
 
504
}
 
505
 
 
506
 
 
507
/* vi_undo():
 
508
 *      Vi undo last change
 
509
 *      [u]
 
510
 */
 
511
protected el_action_t
 
512
/*ARGSUSED*/
 
513
vi_undo(EditLine *el, int c __attribute__((__unused__)))
 
514
{
 
515
        c_undo_t un = el->el_chared.c_undo;
 
516
 
 
517
        if (un.len == -1)
 
518
                return CC_ERROR;
 
519
 
 
520
        /* switch line buffer and undo buffer */
 
521
        el->el_chared.c_undo.buf = el->el_line.buffer;
 
522
        el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
 
523
        el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer;
 
524
        el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
 
525
        el->el_line.buffer = un.buf;
 
526
        el->el_line.cursor = un.buf + un.cursor;
 
527
        el->el_line.lastchar = un.buf + un.len;
 
528
 
 
529
        return (CC_REFRESH);
 
530
}
 
531
 
 
532
 
 
533
/* vi_command_mode():
 
534
 *      Vi enter command mode (use alternative key bindings)
 
535
 *      [<ESC>]
 
536
 */
 
537
protected el_action_t
 
538
/*ARGSUSED*/
 
539
vi_command_mode(EditLine *el, int c __attribute__((__unused__)))
 
540
{
 
541
 
 
542
        /* [Esc] cancels pending action */
 
543
        el->el_chared.c_vcmd.action = NOP;
 
544
        el->el_chared.c_vcmd.pos = 0;
 
545
 
 
546
        el->el_state.doingarg = 0;
 
547
 
 
548
        el->el_state.inputmode = MODE_INSERT;
 
549
        el->el_map.current = el->el_map.alt;
 
550
#ifdef VI_MOVE
 
551
        if (el->el_line.cursor > el->el_line.buffer)
 
552
                el->el_line.cursor--;
 
553
#endif
 
554
        return (CC_CURSOR);
 
555
}
 
556
 
 
557
 
 
558
/* vi_zero():
 
559
 *      Vi move to the beginning of line
 
560
 *      [0]
 
561
 */
 
562
protected el_action_t
 
563
vi_zero(EditLine *el, int c)
 
564
{
 
565
 
 
566
        if (el->el_state.doingarg)
 
567
                return ed_argument_digit(el, c);
 
568
 
 
569
        el->el_line.cursor = el->el_line.buffer;
 
570
        if (el->el_chared.c_vcmd.action != NOP) {
 
571
                cv_delfini(el);
 
572
                return (CC_REFRESH);
 
573
        }
 
574
        return (CC_CURSOR);
 
575
}
 
576
 
 
577
 
 
578
/* vi_delete_prev_char():
 
579
 *      Vi move to previous character (backspace)
 
580
 *      [^H] in insert mode only
 
581
 */
 
582
protected el_action_t
 
583
/*ARGSUSED*/
 
584
vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
 
585
{
 
586
 
 
587
        if (el->el_line.cursor <= el->el_line.buffer)
 
588
                return (CC_ERROR);
 
589
 
 
590
        c_delbefore1(el);
 
591
        el->el_line.cursor--;
 
592
        return (CC_REFRESH);
 
593
}
 
594
 
 
595
 
 
596
/* vi_list_or_eof():
 
597
 *      Vi list choices for completion or indicate end of file if empty line
 
598
 *      [^D]
 
599
 */
 
600
protected el_action_t
 
601
/*ARGSUSED*/
 
602
vi_list_or_eof(EditLine *el, int c)
 
603
{
 
604
 
 
605
        if (el->el_line.cursor == el->el_line.lastchar) {
 
606
                if (el->el_line.cursor == el->el_line.buffer) {
 
607
                        term_writec(el, c);     /* then do a EOF */
 
608
                        return (CC_EOF);
 
609
                } else {
 
610
                        /*
 
611
                         * Here we could list completions, but it is an
 
612
                         * error right now
 
613
                         */
 
614
                        term_beep(el);
 
615
                        return (CC_ERROR);
 
616
                }
 
617
        } else {
 
618
#ifdef notyet
 
619
                re_goto_bottom(el);
 
620
                *el->el_line.lastchar = '\0';   /* just in case */
 
621
                return (CC_LIST_CHOICES);
 
622
#else
 
623
                /*
 
624
                 * Just complain for now.
 
625
                 */
 
626
                term_beep(el);
 
627
                return (CC_ERROR);
 
628
#endif
 
629
        }
 
630
}
 
631
 
 
632
 
 
633
/* vi_kill_line_prev():
 
634
 *      Vi cut from beginning of line to cursor
 
635
 *      [^U]
 
636
 */
 
637
protected el_action_t
 
638
/*ARGSUSED*/
 
639
vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__)))
 
640
{
 
641
        char *kp, *cp;
 
642
 
 
643
        cp = el->el_line.buffer;
 
644
        kp = el->el_chared.c_kill.buf;
 
645
        while (cp < el->el_line.cursor)
 
646
                *kp++ = *cp++;  /* copy it */
 
647
        el->el_chared.c_kill.last = kp;
 
648
        c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
 
649
        el->el_line.cursor = el->el_line.buffer;        /* zap! */
 
650
        return (CC_REFRESH);
 
651
}
 
652
 
 
653
 
 
654
/* vi_search_prev():
 
655
 *      Vi search history previous
 
656
 *      [?]
 
657
 */
 
658
protected el_action_t
 
659
/*ARGSUSED*/
 
660
vi_search_prev(EditLine *el, int c __attribute__((__unused__)))
 
661
{
 
662
 
 
663
        return (cv_search(el, ED_SEARCH_PREV_HISTORY));
 
664
}
 
665
 
 
666
 
 
667
/* vi_search_next():
 
668
 *      Vi search history next
 
669
 *      [/]
 
670
 */
 
671
protected el_action_t
 
672
/*ARGSUSED*/
 
673
vi_search_next(EditLine *el, int c __attribute__((__unused__)))
 
674
{
 
675
 
 
676
        return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
 
677
}
 
678
 
 
679
 
 
680
/* vi_repeat_search_next():
 
681
 *      Vi repeat current search in the same search direction
 
682
 *      [n]
 
683
 */
 
684
protected el_action_t
 
685
/*ARGSUSED*/
 
686
vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__)))
 
687
{
 
688
 
 
689
        if (el->el_search.patlen == 0)
 
690
                return (CC_ERROR);
 
691
        else
 
692
                return (cv_repeat_srch(el, el->el_search.patdir));
 
693
}
 
694
 
 
695
 
 
696
/* vi_repeat_search_prev():
 
697
 *      Vi repeat current search in the opposite search direction
 
698
 *      [N]
 
699
 */
 
700
/*ARGSUSED*/
 
701
protected el_action_t
 
702
vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__)))
 
703
{
 
704
 
 
705
        if (el->el_search.patlen == 0)
 
706
                return (CC_ERROR);
 
707
        else
 
708
                return (cv_repeat_srch(el,
 
709
                    el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
 
710
                    ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
 
711
}
 
712
 
 
713
 
 
714
/* vi_next_char():
 
715
 *      Vi move to the character specified next
 
716
 *      [f]
 
717
 */
 
718
protected el_action_t
 
719
/*ARGSUSED*/
 
720
vi_next_char(EditLine *el, int c __attribute__((__unused__)))
 
721
{
 
722
        return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
 
723
}
 
724
 
 
725
 
 
726
/* vi_prev_char():
 
727
 *      Vi move to the character specified previous
 
728
 *      [F]
 
729
 */
 
730
protected el_action_t
 
731
/*ARGSUSED*/
 
732
vi_prev_char(EditLine *el, int c __attribute__((__unused__)))
 
733
{
 
734
        return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
 
735
}
 
736
 
 
737
 
 
738
/* vi_to_next_char():
 
739
 *      Vi move up to the character specified next
 
740
 *      [t]
 
741
 */
 
742
protected el_action_t
 
743
/*ARGSUSED*/
 
744
vi_to_next_char(EditLine *el, int c __attribute__((__unused__)))
 
745
{
 
746
        return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
 
747
}
 
748
 
 
749
 
 
750
/* vi_to_prev_char():
 
751
 *      Vi move up to the character specified previous
 
752
 *      [T]
 
753
 */
 
754
protected el_action_t
 
755
/*ARGSUSED*/
 
756
vi_to_prev_char(EditLine *el, int c __attribute__((__unused__)))
 
757
{
 
758
        return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
 
759
}
 
760
 
 
761
 
 
762
/* vi_repeat_next_char():
 
763
 *      Vi repeat current character search in the same search direction
 
764
 *      [;]
 
765
 */
 
766
protected el_action_t
 
767
/*ARGSUSED*/
 
768
vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__)))
 
769
{
 
770
 
 
771
        return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
 
772
                el->el_state.argument, el->el_search.chatflg);
 
773
}
 
774
 
 
775
 
 
776
/* vi_repeat_prev_char():
 
777
 *      Vi repeat current character search in the opposite search direction
 
778
 *      [,]
 
779
 */
 
780
protected el_action_t
 
781
/*ARGSUSED*/
 
782
vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__)))
 
783
{
 
784
        el_action_t r;
 
785
        int dir = el->el_search.chadir;
 
786
 
 
787
        r = cv_csearch(el, -dir, el->el_search.chacha,
 
788
                el->el_state.argument, el->el_search.chatflg);
 
789
        el->el_search.chadir = dir;
 
790
        return r;
 
791
}
 
792
 
 
793
 
 
794
/* vi_match():
 
795
 *      Vi go to matching () {} or []
 
796
 *      [%]
 
797
 */
 
798
protected el_action_t
 
799
/*ARGSUSED*/
 
800
vi_match(EditLine *el, int c)
 
801
{
 
802
        const char match_chars[] = "()[]{}";
 
803
        char *cp;
 
804
        int delta, i, count;
 
805
        char o_ch, c_ch;
 
806
 
 
807
        *el->el_line.lastchar = '\0';           /* just in case */
 
808
 
 
809
        i = strcspn(el->el_line.cursor, match_chars);
 
810
        o_ch = el->el_line.cursor[i];
 
811
        if (o_ch == 0)
 
812
                return CC_ERROR;
 
813
        delta = strchr(match_chars, o_ch) - match_chars;
 
814
        c_ch = match_chars[delta ^ 1];
 
815
        count = 1;
 
816
        delta = 1 - (delta & 1) * 2;
 
817
 
 
818
        for (cp = &el->el_line.cursor[i]; count; ) {
 
819
                cp += delta;
 
820
                if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
 
821
                        return CC_ERROR;
 
822
                if (*cp == o_ch)
 
823
                        count++;
 
824
                else if (*cp == c_ch)
 
825
                        count--;
 
826
        }
 
827
 
 
828
        el->el_line.cursor = cp;
 
829
 
 
830
        if (el->el_chared.c_vcmd.action != NOP) {
 
831
                /* NB posix says char under cursor should NOT be deleted
 
832
                   for -ve delta - this is different to netbsd vi. */
 
833
                if (delta > 0)
 
834
                        el->el_line.cursor++;
 
835
                cv_delfini(el);
 
836
                return (CC_REFRESH);
 
837
        }
 
838
        return (CC_CURSOR);
 
839
}
 
840
 
 
841
/* vi_undo_line():
 
842
 *      Vi undo all changes to line
 
843
 *      [U]
 
844
 */
 
845
protected el_action_t
 
846
/*ARGSUSED*/
 
847
vi_undo_line(EditLine *el, int c)
 
848
{
 
849
 
 
850
        cv_undo(el);
 
851
        return hist_get(el);
 
852
}
 
853
 
 
854
/* vi_to_column():
 
855
 *      Vi go to specified column
 
856
 *      [|]
 
857
 * NB netbsd vi goes to screen column 'n', posix says nth character
 
858
 */
 
859
protected el_action_t
 
860
/*ARGSUSED*/
 
861
vi_to_column(EditLine *el, int c)
 
862
{
 
863
 
 
864
        el->el_line.cursor = el->el_line.buffer;
 
865
        el->el_state.argument--;
 
866
        return ed_next_char(el, 0);
 
867
}
 
868
 
 
869
/* vi_yank_end():
 
870
 *      Vi yank to end of line
 
871
 *      [Y]
 
872
 */
 
873
protected el_action_t
 
874
/*ARGSUSED*/
 
875
vi_yank_end(EditLine *el, int c)
 
876
{
 
877
 
 
878
        cv_yank(el, el->el_line.cursor,
 
879
                el->el_line.lastchar - el->el_line.cursor);
 
880
        return CC_REFRESH;
 
881
}
 
882
 
 
883
/* vi_yank():
 
884
 *      Vi yank
 
885
 *      [y]
 
886
 */
 
887
protected el_action_t
 
888
/*ARGSUSED*/
 
889
vi_yank(EditLine *el, int c)
 
890
{
 
891
 
 
892
        return cv_action(el, YANK);
 
893
}
 
894
 
 
895
/* vi_comment_out():
 
896
 *      Vi comment out current command
 
897
 *      [#]
 
898
 */
 
899
protected el_action_t
 
900
/*ARGSUSED*/
 
901
vi_comment_out(EditLine *el, int c)
 
902
{
 
903
 
 
904
        el->el_line.cursor = el->el_line.buffer;
 
905
        c_insert(el, 1);
 
906
        *el->el_line.cursor = '#';
 
907
        re_refresh(el);
 
908
        return ed_newline(el, 0);
 
909
}
 
910
 
 
911
/* vi_alias():
 
912
 *      Vi include shell alias
 
913
 *      [@]
 
914
 * NB: posix implies that we should enter insert mode, however
 
915
 * this is against historical precedent...
 
916
 */
 
917
#if defined(__weak_reference) && !defined(__FreeBSD__)
 
918
extern char *get_alias_text(const char *) __weak_reference(get_alias_text);
 
919
#endif
 
920
protected el_action_t
 
921
/*ARGSUSED*/
 
922
vi_alias(EditLine *el, int c)
 
923
{
 
924
#if defined(__weak_reference) && !defined(__FreeBSD__)
 
925
        char alias_name[3];
 
926
        char *alias_text;
 
927
 
 
928
        if (get_alias_text == 0) {
 
929
                return CC_ERROR;
 
930
        }
 
931
 
 
932
        alias_name[0] = '_';
 
933
        alias_name[2] = 0;
 
934
        if (el_getc(el, &alias_name[1]) != 1)
 
935
                return CC_ERROR;
 
936
 
 
937
        alias_text = get_alias_text(alias_name);
 
938
        if (alias_text != NULL)
 
939
                el_push(el, alias_text);
 
940
        return CC_NORM;
 
941
#else
 
942
        return CC_ERROR;
 
943
#endif
 
944
}
 
945
 
 
946
/* vi_to_history_line():
 
947
 *      Vi go to specified history file line.
 
948
 *      [G]
 
949
 */
 
950
protected el_action_t
 
951
/*ARGSUSED*/
 
952
vi_to_history_line(EditLine *el, int c)
 
953
{
 
954
        int sv_event_no = el->el_history.eventno;
 
955
        el_action_t rval;
 
956
 
 
957
 
 
958
        if (el->el_history.eventno == 0) {
 
959
                 (void) strncpy(el->el_history.buf, el->el_line.buffer,
 
960
                     EL_BUFSIZ);
 
961
                 el->el_history.last = el->el_history.buf +
 
962
                         (el->el_line.lastchar - el->el_line.buffer);
 
963
        }
 
964
 
 
965
        /* Lack of a 'count' means oldest, not 1 */
 
966
        if (!el->el_state.doingarg) {
 
967
                el->el_history.eventno = 0x7fffffff;
 
968
                hist_get(el);
 
969
        } else {
 
970
                /* This is brain dead, all the rest of this code counts
 
971
                 * upwards going into the past.  Here we need count in the
 
972
                 * other direction (to match the output of fc -l).
 
973
                 * I could change the world, but this seems to suffice.
 
974
                 */
 
975
                el->el_history.eventno = 1;
 
976
                if (hist_get(el) == CC_ERROR)
 
977
                        return CC_ERROR;
 
978
                el->el_history.eventno = 1 + el->el_history.ev.num 
 
979
                                        - el->el_state.argument;
 
980
                if (el->el_history.eventno < 0) {
 
981
                        el->el_history.eventno = sv_event_no;
 
982
                        return CC_ERROR;
 
983
                }
 
984
        }
 
985
        rval = hist_get(el);
 
986
        if (rval == CC_ERROR)
 
987
                el->el_history.eventno = sv_event_no;
 
988
        return rval;
 
989
}
 
990
 
 
991
/* vi_histedit():
 
992
 *      Vi edit history line with vi
 
993
 *      [v]
 
994
 */
 
995
protected el_action_t
 
996
/*ARGSUSED*/
 
997
vi_histedit(EditLine *el, int c)
 
998
{
 
999
        int fd;
 
1000
        pid_t pid;
 
1001
        int st;
 
1002
        char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
 
1003
        char *cp;
 
1004
 
 
1005
        if (el->el_state.doingarg) {
 
1006
                if (vi_to_history_line(el, 0) == CC_ERROR)
 
1007
                        return CC_ERROR;
 
1008
        }
 
1009
 
 
1010
        fd = mkstemp(tempfile);
 
1011
        if (fd < 0)
 
1012
                return CC_ERROR;
 
1013
        cp = el->el_line.buffer;
 
1014
        write(fd, cp, el->el_line.lastchar - cp +0u);
 
1015
        write(fd, "\n", 1);
 
1016
        pid = fork();
 
1017
        switch (pid) {
 
1018
        case -1:
 
1019
                close(fd);
 
1020
                unlink(tempfile);
 
1021
                return CC_ERROR;
 
1022
        case 0:
 
1023
                close(fd);
 
1024
                execlp("vi", "vi", tempfile, (char *)NULL);
 
1025
                exit(0);
 
1026
                /*NOTREACHED*/
 
1027
        default:
 
1028
                while (waitpid(pid, &st, 0) != pid)
 
1029
                        continue;
 
1030
                lseek(fd, 0ll, SEEK_SET);
 
1031
                st = read(fd, cp, el->el_line.limit - cp +0u);
 
1032
                if (st > 0 && cp[st - 1] == '\n')
 
1033
                        st--;
 
1034
                el->el_line.cursor = cp;
 
1035
                el->el_line.lastchar = cp + st;
 
1036
                break;
 
1037
        }
 
1038
 
 
1039
        close(fd);
 
1040
        unlink(tempfile);
 
1041
        /* return CC_REFRESH; */
 
1042
        return ed_newline(el, 0);
 
1043
}
 
1044
 
 
1045
/* vi_history_word():
 
1046
 *      Vi append word from previous input line
 
1047
 *      [_]
 
1048
 * Who knows where this one came from!
 
1049
 * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
 
1050
 */
 
1051
protected el_action_t
 
1052
/*ARGSUSED*/
 
1053
vi_history_word(EditLine *el, int c)
 
1054
{
 
1055
        const char *wp = HIST_FIRST(el);
 
1056
        const char *wep, *wsp;
 
1057
        int len;
 
1058
        char *cp;
 
1059
        const char *lim;
 
1060
 
 
1061
        if (wp == NULL)
 
1062
                return CC_ERROR;
 
1063
 
 
1064
        wep = wsp = 0;
 
1065
        do {
 
1066
                while (isspace((unsigned char)*wp))
 
1067
                        wp++;
 
1068
                if (*wp == 0)
 
1069
                        break;
 
1070
                wsp = wp;
 
1071
                while (*wp && !isspace((unsigned char)*wp))
 
1072
                        wp++;
 
1073
                wep = wp;
 
1074
        } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0);
 
1075
 
 
1076
        if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
 
1077
                return CC_ERROR;
 
1078
 
 
1079
        cv_undo(el);
 
1080
        len = wep - wsp;
 
1081
        if (el->el_line.cursor < el->el_line.lastchar)
 
1082
                el->el_line.cursor++;
 
1083
        c_insert(el, len + 1);
 
1084
        cp = el->el_line.cursor;
 
1085
        lim = el->el_line.limit;
 
1086
        if (cp < lim)
 
1087
                *cp++ = ' ';
 
1088
        while (wsp < wep && cp < lim)
 
1089
                *cp++ = *wsp++;
 
1090
        el->el_line.cursor = cp;
 
1091
 
 
1092
        el->el_map.current = el->el_map.key;
 
1093
        return CC_REFRESH;
 
1094
}
 
1095
 
 
1096
/* vi_redo():
 
1097
 *      Vi redo last non-motion command
 
1098
 *      [.]
 
1099
 */
 
1100
protected el_action_t
 
1101
/*ARGSUSED*/
 
1102
vi_redo(EditLine *el, int c)
 
1103
{
 
1104
        c_redo_t *r = &el->el_chared.c_redo;
 
1105
 
 
1106
        if (!el->el_state.doingarg && r->count) {
 
1107
                el->el_state.doingarg = 1;
 
1108
                el->el_state.argument = r->count;
 
1109
        }
 
1110
 
 
1111
        el->el_chared.c_vcmd.pos = el->el_line.cursor;
 
1112
        el->el_chared.c_vcmd.action = r->action;
 
1113
        if (r->pos != r->buf) {
 
1114
                if (r->pos + 1 > r->lim)
 
1115
                        /* sanity */
 
1116
                        r->pos = r->lim - 1;
 
1117
                r->pos[0] = 0;
 
1118
                el_push(el, r->buf);
 
1119
        }
 
1120
 
 
1121
        el->el_state.thiscmd = r->cmd;
 
1122
        el->el_state.thisch = r->ch;
 
1123
        return  (*el->el_map.func[r->cmd])(el, r->ch);
 
1124
}