GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libedit/common.c Lines: 0 269 0.0 %
Date: 2017-11-07 Branches: 0 212 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: common.c,v 1.22 2016/05/22 23:09:56 schwarze Exp $	*/
2
/*	$NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $	*/
3
4
/*-
5
 * Copyright (c) 1992, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Christos Zoulas of Cornell University.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include "config.h"
37
38
/*
39
 * common.c: Common Editor functions
40
 */
41
#include <ctype.h>
42
#include <string.h>
43
44
#include "el.h"
45
#include "common.h"
46
#include "fcns.h"
47
#include "parse.h"
48
#include "vi.h"
49
50
/* ed_end_of_file():
51
 *	Indicate end of file
52
 *	[^D]
53
 */
54
protected el_action_t
55
/*ARGSUSED*/
56
ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
57
{
58
59
	re_goto_bottom(el);
60
	*el->el_line.lastchar = '\0';
61
	return CC_EOF;
62
}
63
64
65
/* ed_insert():
66
 *	Add character to the line
67
 *	Insert a character [bound to all insert keys]
68
 */
69
protected el_action_t
70
ed_insert(EditLine *el, wint_t c)
71
{
72
	int count = el->el_state.argument;
73
74
	if (c == '\0')
75
		return CC_ERROR;
76
77
	if (el->el_line.lastchar + el->el_state.argument >=
78
	    el->el_line.limit) {
79
		/* end of buffer space, try to allocate more */
80
		if (!ch_enlargebufs(el, (size_t) count))
81
			return CC_ERROR;	/* error allocating more */
82
	}
83
84
	if (count == 1) {
85
		if (el->el_state.inputmode == MODE_INSERT
86
		    || el->el_line.cursor >= el->el_line.lastchar)
87
			c_insert(el, 1);
88
89
		*el->el_line.cursor++ = c;
90
		re_fastaddc(el);		/* fast refresh for one char. */
91
	} else {
92
		if (el->el_state.inputmode != MODE_REPLACE_1)
93
			c_insert(el, el->el_state.argument);
94
95
		while (count-- && el->el_line.cursor < el->el_line.lastchar)
96
			*el->el_line.cursor++ = c;
97
		re_refresh(el);
98
	}
99
100
	if (el->el_state.inputmode == MODE_REPLACE_1)
101
		return vi_command_mode(el, 0);
102
103
	return CC_NORM;
104
}
105
106
107
/* ed_delete_prev_word():
108
 *	Delete from beginning of current word to cursor
109
 *	[M-^?] [^W]
110
 */
111
protected el_action_t
112
/*ARGSUSED*/
113
ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
114
{
115
	wchar_t *cp, *p, *kp;
116
117
	if (el->el_line.cursor == el->el_line.buffer)
118
		return CC_ERROR;
119
120
	cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
121
	    el->el_state.argument, ce__isword);
122
123
	for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
124
		*kp++ = *p;
125
	el->el_chared.c_kill.last = kp;
126
127
	c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
128
	el->el_line.cursor = cp;
129
	if (el->el_line.cursor < el->el_line.buffer)
130
		el->el_line.cursor = el->el_line.buffer; /* bounds check */
131
	return CC_REFRESH;
132
}
133
134
135
/* ed_delete_next_char():
136
 *	Delete character under cursor
137
 *	[^D] [x]
138
 */
139
protected el_action_t
140
/*ARGSUSED*/
141
ed_delete_next_char(EditLine *el, wint_t c)
142
{
143
#ifdef notdef			/* XXX */
144
#define	EL	el->el_line
145
	(void) fprintf(el->el_errfile,
146
	    "\nD(b: %p(%ls)  c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
147
	    EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
148
	    EL.lastchar, EL.limit, EL.limit);
149
#endif
150
	if (el->el_line.cursor == el->el_line.lastchar) {
151
			/* if I'm at the end */
152
		if (el->el_map.type == MAP_VI) {
153
			if (el->el_line.cursor == el->el_line.buffer) {
154
				/* if I'm also at the beginning */
155
#ifdef KSHVI
156
				return CC_ERROR;
157
#else
158
				/* then do an EOF */
159
				terminal_writec(el, c);
160
				return CC_EOF;
161
#endif
162
			} else {
163
#ifdef KSHVI
164
				el->el_line.cursor--;
165
#else
166
				return CC_ERROR;
167
#endif
168
			}
169
		} else {
170
			if (el->el_line.cursor != el->el_line.buffer)
171
				el->el_line.cursor--;
172
			else
173
				return CC_ERROR;
174
		}
175
	}
176
	c_delafter(el, el->el_state.argument);	/* delete after dot */
177
	if (el->el_line.cursor >= el->el_line.lastchar &&
178
	    el->el_line.cursor > el->el_line.buffer)
179
			/* bounds check */
180
		el->el_line.cursor = el->el_line.lastchar - 1;
181
	return CC_REFRESH;
182
}
183
184
185
/* ed_kill_line():
186
 *	Cut to the end of line
187
 *	[^K] [^K]
188
 */
189
protected el_action_t
190
/*ARGSUSED*/
191
ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
192
{
193
	wchar_t *kp, *cp;
194
195
	cp = el->el_line.cursor;
196
	kp = el->el_chared.c_kill.buf;
197
	while (cp < el->el_line.lastchar)
198
		*kp++ = *cp++;	/* copy it */
199
	el->el_chared.c_kill.last = kp;
200
			/* zap! -- delete to end */
201
	el->el_line.lastchar = el->el_line.cursor;
202
	return CC_REFRESH;
203
}
204
205
206
/* ed_move_to_end():
207
 *	Move cursor to the end of line
208
 *	[^E] [^E]
209
 */
210
protected el_action_t
211
/*ARGSUSED*/
212
ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
213
{
214
215
	el->el_line.cursor = el->el_line.lastchar;
216
	if (el->el_map.type == MAP_VI) {
217
		if (el->el_chared.c_vcmd.action != NOP) {
218
			cv_delfini(el);
219
			return CC_REFRESH;
220
		}
221
#ifdef VI_MOVE
222
		el->el_line.cursor--;
223
#endif
224
	}
225
	return CC_CURSOR;
226
}
227
228
229
/* ed_move_to_beg():
230
 *	Move cursor to the beginning of line
231
 *	[^A] [^A]
232
 */
233
protected el_action_t
234
/*ARGSUSED*/
235
ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
236
{
237
238
	el->el_line.cursor = el->el_line.buffer;
239
240
	if (el->el_map.type == MAP_VI) {
241
			/* We want FIRST non space character */
242
		while (iswspace(*el->el_line.cursor))
243
			el->el_line.cursor++;
244
		if (el->el_chared.c_vcmd.action != NOP) {
245
			cv_delfini(el);
246
			return CC_REFRESH;
247
		}
248
	}
249
	return CC_CURSOR;
250
}
251
252
253
/* ed_transpose_chars():
254
 *	Exchange the character to the left of the cursor with the one under it
255
 *	[^T] [^T]
256
 */
257
protected el_action_t
258
ed_transpose_chars(EditLine *el, wint_t c)
259
{
260
261
	if (el->el_line.cursor < el->el_line.lastchar) {
262
		if (el->el_line.lastchar <= &el->el_line.buffer[1])
263
			return CC_ERROR;
264
		else
265
			el->el_line.cursor++;
266
	}
267
	if (el->el_line.cursor > &el->el_line.buffer[1]) {
268
		/* must have at least two chars entered */
269
		c = el->el_line.cursor[-2];
270
		el->el_line.cursor[-2] = el->el_line.cursor[-1];
271
		el->el_line.cursor[-1] = c;
272
		return CC_REFRESH;
273
	} else
274
		return CC_ERROR;
275
}
276
277
278
/* ed_next_char():
279
 *	Move to the right one character
280
 *	[^F] [^F]
281
 */
282
protected el_action_t
283
/*ARGSUSED*/
284
ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
285
{
286
	wchar_t *lim = el->el_line.lastchar;
287
288
	if (el->el_line.cursor >= lim ||
289
	    (el->el_line.cursor == lim - 1 &&
290
	    el->el_map.type == MAP_VI &&
291
	    el->el_chared.c_vcmd.action == NOP))
292
		return CC_ERROR;
293
294
	el->el_line.cursor += el->el_state.argument;
295
	if (el->el_line.cursor > lim)
296
		el->el_line.cursor = lim;
297
298
	if (el->el_map.type == MAP_VI)
299
		if (el->el_chared.c_vcmd.action != NOP) {
300
			cv_delfini(el);
301
			return CC_REFRESH;
302
		}
303
	return CC_CURSOR;
304
}
305
306
307
/* ed_prev_word():
308
 *	Move to the beginning of the current word
309
 *	[M-b] [b]
310
 */
311
protected el_action_t
312
/*ARGSUSED*/
313
ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
314
{
315
316
	if (el->el_line.cursor == el->el_line.buffer)
317
		return CC_ERROR;
318
319
	el->el_line.cursor = c__prev_word(el->el_line.cursor,
320
	    el->el_line.buffer,
321
	    el->el_state.argument,
322
	    ce__isword);
323
324
	if (el->el_map.type == MAP_VI)
325
		if (el->el_chared.c_vcmd.action != NOP) {
326
			cv_delfini(el);
327
			return CC_REFRESH;
328
		}
329
	return CC_CURSOR;
330
}
331
332
333
/* ed_prev_char():
334
 *	Move to the left one character
335
 *	[^B] [^B]
336
 */
337
protected el_action_t
338
/*ARGSUSED*/
339
ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
340
{
341
342
	if (el->el_line.cursor > el->el_line.buffer) {
343
		el->el_line.cursor -= el->el_state.argument;
344
		if (el->el_line.cursor < el->el_line.buffer)
345
			el->el_line.cursor = el->el_line.buffer;
346
347
		if (el->el_map.type == MAP_VI)
348
			if (el->el_chared.c_vcmd.action != NOP) {
349
				cv_delfini(el);
350
				return CC_REFRESH;
351
			}
352
		return CC_CURSOR;
353
	} else
354
		return CC_ERROR;
355
}
356
357
358
/* ed_quoted_insert():
359
 *	Add the next character typed verbatim
360
 *	[^V] [^V]
361
 */
362
protected el_action_t
363
ed_quoted_insert(EditLine *el, wint_t c)
364
{
365
	int num;
366
367
	tty_quotemode(el);
368
	num = el_wgetc(el, &c);
369
	tty_noquotemode(el);
370
	if (num == 1)
371
		return ed_insert(el, c);
372
	else
373
		return ed_end_of_file(el, 0);
374
}
375
376
377
/* ed_digit():
378
 *	Adds to argument or enters a digit
379
 */
380
protected el_action_t
381
ed_digit(EditLine *el, wint_t c)
382
{
383
384
	if (!iswdigit(c))
385
		return CC_ERROR;
386
387
	if (el->el_state.doingarg) {
388
			/* if doing an arg, add this in... */
389
		if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
390
			el->el_state.argument = c - '0';
391
		else {
392
			if (el->el_state.argument > 1000000)
393
				return CC_ERROR;
394
			el->el_state.argument =
395
			    (el->el_state.argument * 10) + (c - '0');
396
		}
397
		return CC_ARGHACK;
398
	}
399
400
	return ed_insert(el, c);
401
}
402
403
404
/* ed_argument_digit():
405
 *	Digit that starts argument
406
 *	For ESC-n
407
 */
408
protected el_action_t
409
ed_argument_digit(EditLine *el, wint_t c)
410
{
411
412
	if (!iswdigit(c))
413
		return CC_ERROR;
414
415
	if (el->el_state.doingarg) {
416
		if (el->el_state.argument > 1000000)
417
			return CC_ERROR;
418
		el->el_state.argument = (el->el_state.argument * 10) +
419
		    (c - '0');
420
	} else {		/* else starting an argument */
421
		el->el_state.argument = c - '0';
422
		el->el_state.doingarg = 1;
423
	}
424
	return CC_ARGHACK;
425
}
426
427
428
/* ed_unassigned():
429
 *	Indicates unbound character
430
 *	Bound to keys that are not assigned
431
 */
432
protected el_action_t
433
/*ARGSUSED*/
434
ed_unassigned(EditLine *el, wint_t c __attribute__((__unused__)))
435
{
436
437
	return CC_ERROR;
438
}
439
440
441
/* ed_ignore():
442
 *	Input characters that have no effect
443
 *	[^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
444
 */
445
protected el_action_t
446
/*ARGSUSED*/
447
ed_ignore(EditLine *el __attribute__((__unused__)),
448
	      wint_t c __attribute__((__unused__)))
449
{
450
451
	return CC_NORM;
452
}
453
454
455
/* ed_newline():
456
 *	Execute command
457
 *	[^J]
458
 */
459
protected el_action_t
460
/*ARGSUSED*/
461
ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
462
{
463
464
	re_goto_bottom(el);
465
	*el->el_line.lastchar++ = '\n';
466
	*el->el_line.lastchar = '\0';
467
	return CC_NEWLINE;
468
}
469
470
471
/* ed_delete_prev_char():
472
 *	Delete the character to the left of the cursor
473
 *	[^?]
474
 */
475
protected el_action_t
476
/*ARGSUSED*/
477
ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
478
{
479
480
	if (el->el_line.cursor <= el->el_line.buffer)
481
		return CC_ERROR;
482
483
	c_delbefore(el, el->el_state.argument);
484
	el->el_line.cursor -= el->el_state.argument;
485
	if (el->el_line.cursor < el->el_line.buffer)
486
		el->el_line.cursor = el->el_line.buffer;
487
	return CC_REFRESH;
488
}
489
490
491
/* ed_clear_screen():
492
 *	Clear screen leaving current line at the top
493
 *	[^L]
494
 */
495
protected el_action_t
496
/*ARGSUSED*/
497
ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
498
{
499
500
	terminal_clear_screen(el);	/* clear the whole real screen */
501
	re_clear_display(el);	/* reset everything */
502
	return CC_REFRESH;
503
}
504
505
506
/* ed_redisplay():
507
 *	Redisplay everything
508
 *	^R
509
 */
510
protected el_action_t
511
/*ARGSUSED*/
512
ed_redisplay(EditLine *el __attribute__((__unused__)),
513
	     wint_t c __attribute__((__unused__)))
514
{
515
516
	return CC_REDISPLAY;
517
}
518
519
520
/* ed_start_over():
521
 *	Erase current line and start from scratch
522
 *	[^G]
523
 */
524
protected el_action_t
525
/*ARGSUSED*/
526
ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
527
{
528
529
	ch_reset(el);
530
	return CC_REFRESH;
531
}
532
533
534
/* ed_sequence_lead_in():
535
 *	First character in a bound sequence
536
 *	Placeholder for external keys
537
 */
538
protected el_action_t
539
/*ARGSUSED*/
540
ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
541
		    wint_t c __attribute__((__unused__)))
542
{
543
544
	return CC_NORM;
545
}
546
547
548
/* ed_prev_history():
549
 *	Move to the previous history line
550
 *	[^P] [k]
551
 */
552
protected el_action_t
553
/*ARGSUSED*/
554
ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
555
{
556
	char beep = 0;
557
	int sv_event = el->el_history.eventno;
558
559
	el->el_chared.c_undo.len = -1;
560
	*el->el_line.lastchar = '\0';		/* just in case */
561
562
	if (el->el_history.eventno == 0) {	/* save the current buffer
563
						 * away */
564
		(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
565
		    EL_BUFSIZ);
566
		el->el_history.last = el->el_history.buf +
567
		    (el->el_line.lastchar - el->el_line.buffer);
568
	}
569
	el->el_history.eventno += el->el_state.argument;
570
571
	if (hist_get(el) == CC_ERROR) {
572
		if (el->el_map.type == MAP_VI) {
573
			el->el_history.eventno = sv_event;
574
		}
575
		beep = 1;
576
		/* el->el_history.eventno was fixed by first call */
577
		(void) hist_get(el);
578
	}
579
	if (beep)
580
		return CC_REFRESH_BEEP;
581
	return CC_REFRESH;
582
}
583
584
585
/* ed_next_history():
586
 *	Move to the next history line
587
 *	[^N] [j]
588
 */
589
protected el_action_t
590
/*ARGSUSED*/
591
ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
592
{
593
	el_action_t beep = CC_REFRESH, rval;
594
595
	el->el_chared.c_undo.len = -1;
596
	*el->el_line.lastchar = '\0';	/* just in case */
597
598
	el->el_history.eventno -= el->el_state.argument;
599
600
	if (el->el_history.eventno < 0) {
601
		el->el_history.eventno = 0;
602
		beep = CC_REFRESH_BEEP;
603
	}
604
	rval = hist_get(el);
605
	if (rval == CC_REFRESH)
606
		return beep;
607
	return rval;
608
609
}
610
611
612
/* ed_search_prev_history():
613
 *	Search previous in history for a line matching the current
614
 *	next search history [M-P] [K]
615
 */
616
protected el_action_t
617
/*ARGSUSED*/
618
ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
619
{
620
	const wchar_t *hp;
621
	int h;
622
	int found = 0;
623
624
	el->el_chared.c_vcmd.action = NOP;
625
	el->el_chared.c_undo.len = -1;
626
	*el->el_line.lastchar = '\0';	/* just in case */
627
	if (el->el_history.eventno < 0) {
628
#ifdef DEBUG_EDIT
629
		(void) fprintf(el->el_errfile,
630
		    "e_prev_search_hist(): eventno < 0;\n");
631
#endif
632
		el->el_history.eventno = 0;
633
		return CC_ERROR;
634
	}
635
	if (el->el_history.eventno == 0) {
636
		(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
637
		    EL_BUFSIZ);
638
		el->el_history.last = el->el_history.buf +
639
		    (el->el_line.lastchar - el->el_line.buffer);
640
	}
641
	if (el->el_history.ref == NULL)
642
		return CC_ERROR;
643
644
	hp = HIST_FIRST(el);
645
	if (hp == NULL)
646
		return CC_ERROR;
647
648
	c_setpat(el);		/* Set search pattern !! */
649
650
	for (h = 1; h <= el->el_history.eventno; h++)
651
		hp = HIST_NEXT(el);
652
653
	while (hp != NULL) {
654
#ifdef SDEBUG
655
		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
656
#endif
657
		if ((wcsncmp(hp, el->el_line.buffer, (size_t)
658
			    (el->el_line.lastchar - el->el_line.buffer)) ||
659
			hp[el->el_line.lastchar - el->el_line.buffer]) &&
660
		    c_hmatch(el, hp)) {
661
			found = 1;
662
			break;
663
		}
664
		h++;
665
		hp = HIST_NEXT(el);
666
	}
667
668
	if (!found) {
669
#ifdef SDEBUG
670
		(void) fprintf(el->el_errfile, "not found\n");
671
#endif
672
		return CC_ERROR;
673
	}
674
	el->el_history.eventno = h;
675
676
	return hist_get(el);
677
}
678
679
680
/* ed_search_next_history():
681
 *	Search next in history for a line matching the current
682
 *	[M-N] [J]
683
 */
684
protected el_action_t
685
/*ARGSUSED*/
686
ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
687
{
688
	const wchar_t *hp;
689
	int h;
690
	int found = 0;
691
692
	el->el_chared.c_vcmd.action = NOP;
693
	el->el_chared.c_undo.len = -1;
694
	*el->el_line.lastchar = '\0';	/* just in case */
695
696
	if (el->el_history.eventno == 0)
697
		return CC_ERROR;
698
699
	if (el->el_history.ref == NULL)
700
		return CC_ERROR;
701
702
	hp = HIST_FIRST(el);
703
	if (hp == NULL)
704
		return CC_ERROR;
705
706
	c_setpat(el);		/* Set search pattern !! */
707
708
	for (h = 1; h < el->el_history.eventno && hp; h++) {
709
#ifdef SDEBUG
710
		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
711
#endif
712
		if ((wcsncmp(hp, el->el_line.buffer, (size_t)
713
			    (el->el_line.lastchar - el->el_line.buffer)) ||
714
			hp[el->el_line.lastchar - el->el_line.buffer]) &&
715
		    c_hmatch(el, hp))
716
			found = h;
717
		hp = HIST_NEXT(el);
718
	}
719
720
	if (!found) {		/* is it the current history number? */
721
		if (!c_hmatch(el, el->el_history.buf)) {
722
#ifdef SDEBUG
723
			(void) fprintf(el->el_errfile, "not found\n");
724
#endif
725
			return CC_ERROR;
726
		}
727
	}
728
	el->el_history.eventno = found;
729
730
	return hist_get(el);
731
}
732
733
734
/* ed_prev_line():
735
 *	Move up one line
736
 *	Could be [k] [^p]
737
 */
738
protected el_action_t
739
/*ARGSUSED*/
740
ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
741
{
742
	wchar_t *ptr;
743
	int nchars = c_hpos(el);
744
745
	/*
746
         * Move to the line requested
747
         */
748
	if (*(ptr = el->el_line.cursor) == '\n')
749
		ptr--;
750
751
	for (; ptr >= el->el_line.buffer; ptr--)
752
		if (*ptr == '\n' && --el->el_state.argument <= 0)
753
			break;
754
755
	if (el->el_state.argument > 0)
756
		return CC_ERROR;
757
758
	/*
759
         * Move to the beginning of the line
760
         */
761
	for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
762
		continue;
763
764
	/*
765
         * Move to the character requested
766
         */
767
	for (ptr++;
768
	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
769
	    ptr++)
770
		continue;
771
772
	el->el_line.cursor = ptr;
773
	return CC_CURSOR;
774
}
775
776
777
/* ed_next_line():
778
 *	Move down one line
779
 *	Could be [j] [^n]
780
 */
781
protected el_action_t
782
/*ARGSUSED*/
783
ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
784
{
785
	wchar_t *ptr;
786
	int nchars = c_hpos(el);
787
788
	/*
789
         * Move to the line requested
790
         */
791
	for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
792
		if (*ptr == '\n' && --el->el_state.argument <= 0)
793
			break;
794
795
	if (el->el_state.argument > 0)
796
		return CC_ERROR;
797
798
	/*
799
         * Move to the character requested
800
         */
801
	for (ptr++;
802
	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
803
	    ptr++)
804
		continue;
805
806
	el->el_line.cursor = ptr;
807
	return CC_CURSOR;
808
}
809
810
811
/* ed_command():
812
 *	Editline extended command
813
 *	[M-X] [:]
814
 */
815
protected el_action_t
816
/*ARGSUSED*/
817
ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
818
{
819
	wchar_t tmpbuf[EL_BUFSIZ];
820
	int tmplen;
821
822
	tmplen = c_gets(el, tmpbuf, L"\n: ");
823
	terminal__putc(el, '\n');
824
825
	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
826
		terminal_beep(el);
827
828
	el->el_map.current = el->el_map.key;
829
	re_clear_display(el);
830
	return CC_REFRESH;
831
}