Initialize buf->b_iodone to NULL during bufinit(9) stage.
[dragonfly.git] / lib / libedit / chared.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
1de703da
MD
35 *
36 * @(#)chared.c 8.1 (Berkeley) 6/4/93
660c873b 37 * $DragonFly: src/lib/libedit/chared.c,v 1.5 2004/10/25 19:38:45 drhodus Exp $
984263bc
MD
38 */
39
984263bc
MD
40/*
41 * chared.c: Character editor utilities
42 */
43#include "sys.h"
44
45#include <stdlib.h>
46#include "el.h"
47
48/* cv_undo():
49 * Handle state for the vi undo command
50 */
51protected void
52cv_undo(el, action, size, ptr)
53 EditLine *el;
54 int action, size;
55 char *ptr;
56{
57 c_undo_t *vu = &el->el_chared.c_undo;
58 vu->action = action;
59 vu->ptr = ptr;
60 vu->isize = size;
61 (void) memcpy(vu->buf, vu->ptr, size);
62#ifdef DEBUG_UNDO
63 (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
64 vu->ptr, vu->isize, vu->dsize);
65#endif
66}
67
68
69/* c_insert():
70 * Insert num characters
71 */
72protected void
73c_insert(el, num)
74 EditLine *el;
75 int num;
76{
77 char *cp;
78
79 if (el->el_line.lastchar + num >= el->el_line.limit)
80 return; /* can't go past end of buffer */
81
82 if (el->el_line.cursor < el->el_line.lastchar) {
83 /* if I must move chars */
84 for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
85 cp[num] = *cp;
86 }
87 el->el_line.lastchar += num;
88} /* end c_insert */
89
90
91/* c_delafter():
92 * Delete num characters after the cursor
93 */
94protected void
95c_delafter(el, num)
96 EditLine *el;
97 int num;
98{
99
100 if (el->el_line.cursor + num > el->el_line.lastchar)
101 num = el->el_line.lastchar - el->el_line.cursor;
102
103 if (num > 0) {
104 char *cp;
105
106 if (el->el_map.current != el->el_map.emacs)
107 cv_undo(el, INSERT, num, el->el_line.cursor);
108
109 for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
110 *cp = cp[num];
111
112 el->el_line.lastchar -= num;
113 }
114}
115
116
117/* c_delbefore():
118 * Delete num characters before the cursor
119 */
120protected void
121c_delbefore(el, num)
122 EditLine *el;
123 int num;
124{
125
126 if (el->el_line.cursor - num < el->el_line.buffer)
127 num = el->el_line.cursor - el->el_line.buffer;
128
129 if (num > 0) {
130 char *cp;
131
132 if (el->el_map.current != el->el_map.emacs)
133 cv_undo(el, INSERT, num, el->el_line.cursor - num);
134
135 for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
136 *cp = cp[num];
137
138 el->el_line.lastchar -= num;
139 }
140}
141
142
143/* ce__isword():
144 * Return if p is part of a word according to emacs
145 */
146protected int
147ce__isword(p)
148 int p;
149{
150 return isalpha((unsigned char) p) || isdigit((unsigned char) p) || strchr("*?_-.[]~=", p) != NULL;
151}
152
153
154/* cv__isword():
155 * Return type of word for p according to vi
156 */
157protected int
158cv__isword(p)
159 int p;
160{
161 if (isspace((unsigned char) p))
162 return 0;
163 if ((unsigned char) p == '_' || isalnum((unsigned char) p))
164 return 1;
165 return 2;
166}
167
168
169/* c___isword():
170 * Return if p is part of a space-delimited word (!isspace)
171 */
172protected int
173c___isword(p)
174 int p;
175{
176 return !isspace((unsigned char) p);
177}
178
179
180/* c__prev_word():
181 * Find the previous word
182 */
183protected char *
184c__prev_word(p, low, n, wtest)
660c873b
DR
185 char *p, *low;
186 int n;
064e1fb3 187 int (*wtest) (int);
984263bc
MD
188{
189 p--;
190
191 while (n--) {
192 while ((p >= low) && !(*wtest)((unsigned char) *p))
193 p--;
194 while ((p >= low) && (*wtest)((unsigned char) *p))
195 p--;
196 }
197
198 /* cp now points to one character before the word */
199 p++;
200 if (p < low)
201 p = low;
202 /* cp now points where we want it */
203 return p;
204}
205
206
207/* c__next_word():
208 * Find the next word
209 */
210protected char *
211c__next_word(p, high, n, wtest)
660c873b
DR
212 char *p, *high;
213 int n;
064e1fb3 214 int (*wtest) (int);
984263bc
MD
215{
216 while (n--) {
217 while ((p < high) && !(*wtest)((unsigned char) *p))
218 p++;
219 while ((p < high) && (*wtest)((unsigned char) *p))
220 p++;
221 }
222 if (p > high)
223 p = high;
224 /* p now points where we want it */
225 return p;
226}
227
228/* cv_next_word():
229 * Find the next word vi style
230 */
231protected char *
232cv_next_word(el, p, high, n, wtest)
233 EditLine *el;
660c873b
DR
234 char *p, *high;
235 int n;
064e1fb3 236 int (*wtest) (int);
984263bc
MD
237{
238 int test;
239
240 while (n--) {
241 test = (*wtest)((unsigned char) *p);
242 while ((p < high) && (*wtest)((unsigned char) *p) == test)
243 p++;
244 /*
245 * vi historically deletes with cw only the word preserving the
246 * trailing whitespace! This is not what 'w' does..
247 */
248 if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
249 while ((p < high) && isspace((unsigned char) *p))
250 p++;
251 }
252
253 /* p now points where we want it */
254 if (p > high)
255 return high;
256 else
257 return p;
258}
259
260
261/* cv_prev_word():
262 * Find the previous word vi style
263 */
264protected char *
265cv_prev_word(el, p, low, n, wtest)
266 EditLine *el;
660c873b
DR
267 char *p, *low;
268 int n;
064e1fb3 269 int (*wtest) (int);
984263bc
MD
270{
271 int test;
272
273 while (n--) {
274 p--;
275 /*
276 * vi historically deletes with cb only the word preserving the
277 * leading whitespace! This is not what 'b' does..
278 */
279 if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
280 while ((p > low) && isspace((unsigned char) *p))
281 p--;
282 test = (*wtest)((unsigned char) *p);
283 while ((p >= low) && (*wtest)((unsigned char) *p) == test)
284 p--;
285 p++;
286 while (isspace((unsigned char) *p))
287 p++;
288 }
289
290 /* p now points where we want it */
291 if (p < low)
292 return low;
293 else
294 return p;
295}
296
297
298#ifdef notdef
299/* c__number():
300 * Ignore character p points to, return number appearing after that.
301 * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
302 * Return p pointing to last char used.
303 */
304protected char *
305c__number(p, num, dval)
306 char *p; /* character position */
307 int *num; /* Return value */
308 int dval; /* dval is the number to subtract from like $-3 */
309{
660c873b
DR
310 int i;
311 int sign = 1;
984263bc
MD
312
313 if (*++p == '^') {
314 *num = 1;
315 return p;
316 }
317 if (*p == '$') {
318 if (*++p != '-') {
319 *num = 0x7fffffff; /* Handle $ */
320 return --p;
321 }
322 sign = -1; /* Handle $- */
323 ++p;
324 }
325 for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
326 continue;
327 *num = (sign < 0 ? dval - i : i);
328 return --p;
329}
330#endif
331
332/* cv_delfini():
333 * Finish vi delete action
334 */
335protected void
336cv_delfini(el)
337 EditLine *el;
338{
660c873b 339 int size;
984263bc
MD
340 int oaction;
341
342 if (el->el_chared.c_vcmd.action & INSERT)
343 el->el_map.current = el->el_map.key;
344
345 oaction = el->el_chared.c_vcmd.action;
346 el->el_chared.c_vcmd.action = NOP;
347
348 if (el->el_chared.c_vcmd.pos == 0)
349 return;
350
351
352 if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
353 size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
354 c_delbefore(el, size);
355 el->el_line.cursor = el->el_chared.c_vcmd.pos;
356 re_refresh_cursor(el);
357 }
358 else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
359 size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
360 c_delafter(el, size);
361 }
362 else {
363 size = 1;
364 c_delafter(el, size);
365 }
366 switch (oaction) {
367 case DELETE|INSERT:
368 el->el_chared.c_undo.action = DELETE|INSERT;
369 break;
370 case DELETE:
371 el->el_chared.c_undo.action = INSERT;
372 break;
373 case NOP:
374 case INSERT:
375 default:
376 abort();
377 break;
378 }
379
380
381 el->el_chared.c_undo.ptr = el->el_line.cursor;
382 el->el_chared.c_undo.dsize = size;
383}
384
385
386#ifdef notdef
387/* ce__endword():
388 * Go to the end of this word according to emacs
389 */
390protected char *
391ce__endword(p, high, n)
392 char *p, *high;
393 int n;
394{
395 p++;
396
397 while (n--) {
398 while ((p < high) && isspace((unsigned char) *p))
399 p++;
400 while ((p < high) && !isspace((unsigned char) *p))
401 p++;
402 }
403
404 p--;
405 return p;
406}
407#endif
408
409
410/* cv__endword():
411 * Go to the end of this word according to vi
412 */
413protected char *
414cv__endword(p, high, n)
415 char *p, *high;
416 int n;
417{
418 p++;
419
420 while (n--) {
421 while ((p < high) && isspace((unsigned char) *p))
422 p++;
423
424 if (isalnum((unsigned char) *p))
425 while ((p < high) && isalnum((unsigned char) *p))
426 p++;
427 else
428 while ((p < high) && !(isspace((unsigned char) *p) ||
429 isalnum((unsigned char) *p)))
430 p++;
431 }
432 p--;
433 return p;
434}
435
436/* ch_init():
437 * Initialize the character editor
438 */
439protected int
440ch_init(el)
441 EditLine *el;
442{
443 el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
444 (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
445 el->el_line.cursor = el->el_line.buffer;
446 el->el_line.lastchar = el->el_line.buffer;
447 el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2];
448
449 el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
450 (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
451 el->el_chared.c_undo.action = NOP;
452 el->el_chared.c_undo.isize = 0;
453 el->el_chared.c_undo.dsize = 0;
454 el->el_chared.c_undo.ptr = el->el_line.buffer;
455
456 el->el_chared.c_vcmd.action = NOP;
457 el->el_chared.c_vcmd.pos = el->el_line.buffer;
458 el->el_chared.c_vcmd.ins = el->el_line.buffer;
459
460 el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
461 (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
462 el->el_chared.c_kill.mark = el->el_line.buffer;
463 el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
464
465 el->el_map.current = el->el_map.key;
466
467 el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
468 el->el_state.doingarg = 0;
469 el->el_state.metanext = 0;
470 el->el_state.argument = 1;
471 el->el_state.lastcmd = ED_UNASSIGNED;
472
473 el->el_chared.c_macro.nline = NULL;
474 el->el_chared.c_macro.level = -1;
475 el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
476 sizeof(char *));
477 return 0;
478}
479
480/* ch_reset():
481 * Reset the character editor
482 */
483protected void
484ch_reset(el)
485 EditLine *el;
486{
487 el->el_line.cursor = el->el_line.buffer;
488 el->el_line.lastchar = el->el_line.buffer;
489
490 el->el_chared.c_undo.action = NOP;
491 el->el_chared.c_undo.isize = 0;
492 el->el_chared.c_undo.dsize = 0;
493 el->el_chared.c_undo.ptr = el->el_line.buffer;
494
495 el->el_chared.c_vcmd.action = NOP;
496 el->el_chared.c_vcmd.pos = el->el_line.buffer;
497 el->el_chared.c_vcmd.ins = el->el_line.buffer;
498
499 el->el_chared.c_kill.mark = el->el_line.buffer;
500
501 el->el_map.current = el->el_map.key;
502
503 el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
504 el->el_state.doingarg = 0;
505 el->el_state.metanext = 0;
506 el->el_state.argument = 1;
507 el->el_state.lastcmd = ED_UNASSIGNED;
508
509 el->el_chared.c_macro.level = -1;
510
511 el->el_history.eventno = 0;
512}
513
514
515/* ch_end():
516 * Free the data structures used by the editor
517 */
518protected void
519ch_end(el)
520 EditLine *el;
521{
522 el_free((ptr_t) el->el_line.buffer);
523 el->el_line.buffer = NULL;
524 el->el_line.limit = NULL;
525 el_free((ptr_t) el->el_chared.c_undo.buf);
526 el->el_chared.c_undo.buf = NULL;
527 el_free((ptr_t) el->el_chared.c_kill.buf);
528 el->el_chared.c_kill.buf = NULL;
529 el_free((ptr_t) el->el_chared.c_macro.macro);
530 el->el_chared.c_macro.macro = NULL;
531 ch_reset(el);
532}
533
534
535/* el_insertstr():
536 * Insert string at cursorI
537 */
538public int
539el_insertstr(el, s)
540 EditLine *el;
541 char *s;
542{
543 int len;
544
545 if ((len = strlen(s)) == 0)
546 return -1;
547 if (el->el_line.lastchar + len >= el->el_line.limit)
548 return -1;
549
550 c_insert(el, len);
551 while (*s)
552 *el->el_line.cursor++ = *s++;
553 return 0;
554}
555
556
557/* el_deletestr():
558 * Delete num characters before the cursor
559 */
560public void
561el_deletestr(el, n)
562 EditLine *el;
563 int n;
564{
565 if (n <= 0)
566 return;
567
568 if (el->el_line.cursor < &el->el_line.buffer[n])
569 return;
570
571 c_delbefore(el, n); /* delete before dot */
572 el->el_line.cursor -= n;
573 if (el->el_line.cursor < el->el_line.buffer)
574 el->el_line.cursor = el->el_line.buffer;
575}
576
577/* c_gets():
578 * Get a string
579 */
580protected int
581c_gets(el, buf)
582 EditLine *el;
583 char *buf;
584{
585 char ch;
586 int len = 0;
587
588 for (ch = 0; ch == 0;) {
589 if (el_getc(el, &ch) != 1)
590 return ed_end_of_file(el, 0);
591 switch (ch) {
592 case '\010': /* Delete and backspace */
593 case '\177':
594 if (len > 1) {
595 *el->el_line.cursor-- = '\0';
596 el->el_line.lastchar = el->el_line.cursor;
597 buf[len--] = '\0';
598 }
599 else {
600 el->el_line.buffer[0] = '\0';
601 el->el_line.lastchar = el->el_line.buffer;
602 el->el_line.cursor = el->el_line.buffer;
603 return CC_REFRESH;
604 }
605 re_refresh(el);
606 ch = 0;
607 break;
608
609 case '\033': /* ESC */
610 case '\r': /* Newline */
611 case '\n':
612 break;
613
614 default:
615 if (len >= EL_BUFSIZ)
616 term_beep(el);
617 else {
618 buf[len++] = ch;
619 *el->el_line.cursor++ = ch;
620 el->el_line.lastchar = el->el_line.cursor;
621 }
622 re_refresh(el);
623 ch = 0;
624 break;
625 }
626 }
627 buf[len] = ch;
628 return len;
629}
630
631
632/* c_hpos():
633 * Return the current horizontal position of the cursor
634 */
635protected int
636c_hpos(el)
637 EditLine *el;
638{
639 char *ptr;
640
641 /*
642 * Find how many characters till the beginning of this line.
643 */
644 if (el->el_line.cursor == el->el_line.buffer)
645 return 0;
646 else {
647 for (ptr = el->el_line.cursor - 1;
648 ptr >= el->el_line.buffer && *ptr != '\n';
649 ptr--)
650 continue;
651 return el->el_line.cursor - ptr - 1;
652 }
653}