1 | /* $NetBSD: chared.c,v 1.29 2010/08/28 15:44:59 christos 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 | #if !defined(lint) && !defined(SCCSID)
|
---|
37 | #if 0
|
---|
38 | static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
|
---|
39 | #else
|
---|
40 | __RCSID("$NetBSD: chared.c,v 1.29 2010/08/28 15:44:59 christos Exp $");
|
---|
41 | #endif
|
---|
42 | #endif /* not lint && not SCCSID */
|
---|
43 |
|
---|
44 | /*
|
---|
45 | * chared.c: Character editor utilities
|
---|
46 | */
|
---|
47 | #include <stdlib.h>
|
---|
48 | #include "el.h"
|
---|
49 |
|
---|
50 | private void ch__clearmacro (EditLine *);
|
---|
51 |
|
---|
52 | /* value to leave unused in line buffer */
|
---|
53 | #define EL_LEAVE 2
|
---|
54 |
|
---|
55 | /* cv_undo():
|
---|
56 | * Handle state for the vi undo command
|
---|
57 | */
|
---|
58 | protected void
|
---|
59 | cv_undo(EditLine *el)
|
---|
60 | {
|
---|
61 | c_undo_t *vu = &el->el_chared.c_undo;
|
---|
62 | c_redo_t *r = &el->el_chared.c_redo;
|
---|
63 | size_t size;
|
---|
64 |
|
---|
65 | /* Save entire line for undo */
|
---|
66 | size = el->el_line.lastchar - el->el_line.buffer;
|
---|
67 | vu->len = size;
|
---|
68 | vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
|
---|
69 | (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
|
---|
70 |
|
---|
71 | /* save command info for redo */
|
---|
72 | r->count = el->el_state.doingarg ? el->el_state.argument : 0;
|
---|
73 | r->action = el->el_chared.c_vcmd.action;
|
---|
74 | r->pos = r->buf;
|
---|
75 | r->cmd = el->el_state.thiscmd;
|
---|
76 | r->ch = el->el_state.thisch;
|
---|
77 | }
|
---|
78 |
|
---|
79 | /* cv_yank():
|
---|
80 | * Save yank/delete data for paste
|
---|
81 | */
|
---|
82 | protected void
|
---|
83 | cv_yank(EditLine *el, const Char *ptr, int size)
|
---|
84 | {
|
---|
85 | c_kill_t *k = &el->el_chared.c_kill;
|
---|
86 |
|
---|
87 | (void)memcpy(k->buf, ptr, size * sizeof(*k->buf));
|
---|
88 | k->last = k->buf + size;
|
---|
89 | }
|
---|
90 |
|
---|
91 |
|
---|
92 | /* c_insert():
|
---|
93 | * Insert num characters
|
---|
94 | */
|
---|
95 | protected void
|
---|
96 | c_insert(EditLine *el, int num)
|
---|
97 | {
|
---|
98 | Char *cp;
|
---|
99 |
|
---|
100 | if (el->el_line.lastchar + num >= el->el_line.limit) {
|
---|
101 | if (!ch_enlargebufs(el, (size_t)num))
|
---|
102 | return; /* can't go past end of buffer */
|
---|
103 | }
|
---|
104 |
|
---|
105 | if (el->el_line.cursor < el->el_line.lastchar) {
|
---|
106 | /* if I must move chars */
|
---|
107 | for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
|
---|
108 | cp[num] = *cp;
|
---|
109 | }
|
---|
110 | el->el_line.lastchar += num;
|
---|
111 | }
|
---|
112 |
|
---|
113 |
|
---|
114 | /* c_delafter():
|
---|
115 | * Delete num characters after the cursor
|
---|
116 | */
|
---|
117 | protected void
|
---|
118 | c_delafter(EditLine *el, int num)
|
---|
119 | {
|
---|
120 |
|
---|
121 | if (el->el_line.cursor + num > el->el_line.lastchar)
|
---|
122 | num = (int)(el->el_line.lastchar - el->el_line.cursor);
|
---|
123 |
|
---|
124 | if (el->el_map.current != el->el_map.emacs) {
|
---|
125 | cv_undo(el);
|
---|
126 | cv_yank(el, el->el_line.cursor, num);
|
---|
127 | }
|
---|
128 |
|
---|
129 | if (num > 0) {
|
---|
130 | Char *cp;
|
---|
131 |
|
---|
132 | for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
|
---|
133 | *cp = cp[num];
|
---|
134 |
|
---|
135 | el->el_line.lastchar -= num;
|
---|
136 | }
|
---|
137 | }
|
---|
138 |
|
---|
139 |
|
---|
140 | /* c_delafter1():
|
---|
141 | * Delete the character after the cursor, do not yank
|
---|
142 | */
|
---|
143 | protected void
|
---|
144 | c_delafter1(EditLine *el)
|
---|
145 | {
|
---|
146 | Char *cp;
|
---|
147 |
|
---|
148 | for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
|
---|
149 | *cp = cp[1];
|
---|
150 |
|
---|
151 | el->el_line.lastchar--;
|
---|
152 | }
|
---|
153 |
|
---|
154 |
|
---|
155 | /* c_delbefore():
|
---|
156 | * Delete num characters before the cursor
|
---|
157 | */
|
---|
158 | protected void
|
---|
159 | c_delbefore(EditLine *el, int num)
|
---|
160 | {
|
---|
161 |
|
---|
162 | if (el->el_line.cursor - num < el->el_line.buffer)
|
---|
163 | num = (int)(el->el_line.cursor - el->el_line.buffer);
|
---|
164 |
|
---|
165 | if (el->el_map.current != el->el_map.emacs) {
|
---|
166 | cv_undo(el);
|
---|
167 | cv_yank(el, el->el_line.cursor - num, num);
|
---|
168 | }
|
---|
169 |
|
---|
170 | if (num > 0) {
|
---|
171 | Char *cp;
|
---|
172 |
|
---|
173 | for (cp = el->el_line.cursor - num;
|
---|
174 | cp <= el->el_line.lastchar;
|
---|
175 | cp++)
|
---|
176 | *cp = cp[num];
|
---|
177 |
|
---|
178 | el->el_line.lastchar -= num;
|
---|
179 | }
|
---|
180 | }
|
---|
181 |
|
---|
182 |
|
---|
183 | /* c_delbefore1():
|
---|
184 | * Delete the character before the cursor, do not yank
|
---|
185 | */
|
---|
186 | protected void
|
---|
187 | c_delbefore1(EditLine *el)
|
---|
188 | {
|
---|
189 | Char *cp;
|
---|
190 |
|
---|
191 | for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
|
---|
192 | *cp = cp[1];
|
---|
193 |
|
---|
194 | el->el_line.lastchar--;
|
---|
195 | }
|
---|
196 |
|
---|
197 |
|
---|
198 | /* ce__isword():
|
---|
199 | * Return if p is part of a word according to emacs
|
---|
200 | */
|
---|
201 | protected int
|
---|
202 | ce__isword(Int p)
|
---|
203 | {
|
---|
204 | return (Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL);
|
---|
205 | }
|
---|
206 |
|
---|
207 |
|
---|
208 | /* cv__isword():
|
---|
209 | * Return if p is part of a word according to vi
|
---|
210 | */
|
---|
211 | protected int
|
---|
212 | cv__isword(Int p)
|
---|
213 | {
|
---|
214 | if (Isalnum(p) || p == '_')
|
---|
215 | return 1;
|
---|
216 | if (Isgraph(p))
|
---|
217 | return 2;
|
---|
218 | return 0;
|
---|
219 | }
|
---|
220 |
|
---|
221 |
|
---|
222 | /* cv__isWord():
|
---|
223 | * Return if p is part of a big word according to vi
|
---|
224 | */
|
---|
225 | protected int
|
---|
226 | cv__isWord(Int p)
|
---|
227 | {
|
---|
228 | return (!Isspace(p));
|
---|
229 | }
|
---|
230 |
|
---|
231 |
|
---|
232 | /* c__prev_word():
|
---|
233 | * Find the previous word
|
---|
234 | */
|
---|
235 | protected Char *
|
---|
236 | c__prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
|
---|
237 | {
|
---|
238 | p--;
|
---|
239 |
|
---|
240 | while (n--) {
|
---|
241 | while ((p >= low) && !(*wtest)(*p))
|
---|
242 | p--;
|
---|
243 | while ((p >= low) && (*wtest)(*p))
|
---|
244 | p--;
|
---|
245 | }
|
---|
246 |
|
---|
247 | /* cp now points to one character before the word */
|
---|
248 | p++;
|
---|
249 | if (p < low)
|
---|
250 | p = low;
|
---|
251 | /* cp now points where we want it */
|
---|
252 | return (p);
|
---|
253 | }
|
---|
254 |
|
---|
255 |
|
---|
256 | /* c__next_word():
|
---|
257 | * Find the next word
|
---|
258 | */
|
---|
259 | protected Char *
|
---|
260 | c__next_word(Char *p, Char *high, int n, int (*wtest)(Int))
|
---|
261 | {
|
---|
262 | while (n--) {
|
---|
263 | while ((p < high) && !(*wtest)(*p))
|
---|
264 | p++;
|
---|
265 | while ((p < high) && (*wtest)(*p))
|
---|
266 | p++;
|
---|
267 | }
|
---|
268 | if (p > high)
|
---|
269 | p = high;
|
---|
270 | /* p now points where we want it */
|
---|
271 | return (p);
|
---|
272 | }
|
---|
273 |
|
---|
274 | /* cv_next_word():
|
---|
275 | * Find the next word vi style
|
---|
276 | */
|
---|
277 | protected Char *
|
---|
278 | cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(Int))
|
---|
279 | {
|
---|
280 | int test;
|
---|
281 |
|
---|
282 | while (n--) {
|
---|
283 | test = (*wtest)(*p);
|
---|
284 | while ((p < high) && (*wtest)(*p) == test)
|
---|
285 | p++;
|
---|
286 | /*
|
---|
287 | * vi historically deletes with cw only the word preserving the
|
---|
288 | * trailing whitespace! This is not what 'w' does..
|
---|
289 | */
|
---|
290 | if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
|
---|
291 | while ((p < high) && Isspace(*p))
|
---|
292 | p++;
|
---|
293 | }
|
---|
294 |
|
---|
295 | /* p now points where we want it */
|
---|
296 | if (p > high)
|
---|
297 | return (high);
|
---|
298 | else
|
---|
299 | return (p);
|
---|
300 | }
|
---|
301 |
|
---|
302 |
|
---|
303 | /* cv_prev_word():
|
---|
304 | * Find the previous word vi style
|
---|
305 | */
|
---|
306 | protected Char *
|
---|
307 | cv_prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
|
---|
308 | {
|
---|
309 | int test;
|
---|
310 |
|
---|
311 | p--;
|
---|
312 | while (n--) {
|
---|
313 | while ((p > low) && Isspace(*p))
|
---|
314 | p--;
|
---|
315 | test = (*wtest)(*p);
|
---|
316 | while ((p >= low) && (*wtest)(*p) == test)
|
---|
317 | p--;
|
---|
318 | }
|
---|
319 | p++;
|
---|
320 |
|
---|
321 | /* p now points where we want it */
|
---|
322 | if (p < low)
|
---|
323 | return (low);
|
---|
324 | else
|
---|
325 | return (p);
|
---|
326 | }
|
---|
327 |
|
---|
328 |
|
---|
329 | #ifdef notdef
|
---|
330 | /* c__number():
|
---|
331 | * Ignore character p points to, return number appearing after that.
|
---|
332 | * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
|
---|
333 | * Return p pointing to last char used.
|
---|
334 | */
|
---|
335 | protected Char *
|
---|
336 | c__number(
|
---|
337 | Char *p, /* character position */
|
---|
338 | int *num, /* Return value */
|
---|
339 | int dval) /* dval is the number to subtract from like $-3 */
|
---|
340 | {
|
---|
341 | int i;
|
---|
342 | int sign = 1;
|
---|
343 |
|
---|
344 | if (*++p == '^') {
|
---|
345 | *num = 1;
|
---|
346 | return (p);
|
---|
347 | }
|
---|
348 | if (*p == '$') {
|
---|
349 | if (*++p != '-') {
|
---|
350 | *num = 0x7fffffff; /* Handle $ */
|
---|
351 | return (--p);
|
---|
352 | }
|
---|
353 | sign = -1; /* Handle $- */
|
---|
354 | ++p;
|
---|
355 | }
|
---|
356 | /* XXX: this assumes ASCII compatible digits */
|
---|
357 | for (i = 0; Isdigit(*p); i = 10 * i + *p++ - '0')
|
---|
358 | continue;
|
---|
359 | *num = (sign < 0 ? dval - i : i);
|
---|
360 | return (--p);
|
---|
361 | }
|
---|
362 | #endif
|
---|
363 |
|
---|
364 | /* cv_delfini():
|
---|
365 | * Finish vi delete action
|
---|
366 | */
|
---|
367 | protected void
|
---|
368 | cv_delfini(EditLine *el)
|
---|
369 | {
|
---|
370 | int size;
|
---|
371 | int action = el->el_chared.c_vcmd.action;
|
---|
372 |
|
---|
373 | if (action & INSERT)
|
---|
374 | el->el_map.current = el->el_map.key;
|
---|
375 |
|
---|
376 | if (el->el_chared.c_vcmd.pos == 0)
|
---|
377 | /* sanity */
|
---|
378 | return;
|
---|
379 |
|
---|
380 | size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
|
---|
381 | if (size == 0)
|
---|
382 | size = 1;
|
---|
383 | el->el_line.cursor = el->el_chared.c_vcmd.pos;
|
---|
384 | if (action & YANK) {
|
---|
385 | if (size > 0)
|
---|
386 | cv_yank(el, el->el_line.cursor, size);
|
---|
387 | else
|
---|
388 | cv_yank(el, el->el_line.cursor + size, -size);
|
---|
389 | } else {
|
---|
390 | if (size > 0) {
|
---|
391 | c_delafter(el, size);
|
---|
392 | re_refresh_cursor(el);
|
---|
393 | } else {
|
---|
394 | c_delbefore(el, -size);
|
---|
395 | el->el_line.cursor += size;
|
---|
396 | }
|
---|
397 | }
|
---|
398 | el->el_chared.c_vcmd.action = NOP;
|
---|
399 | }
|
---|
400 |
|
---|
401 |
|
---|
402 | #ifdef notdef
|
---|
403 | /* ce__endword():
|
---|
404 | * Go to the end of this word according to emacs
|
---|
405 | */
|
---|
406 | protected Char *
|
---|
407 | ce__endword(Char *p, Char *high, int n)
|
---|
408 | {
|
---|
409 | p++;
|
---|
410 |
|
---|
411 | while (n--) {
|
---|
412 | while ((p < high) && Isspace(*p))
|
---|
413 | p++;
|
---|
414 | while ((p < high) && !Isspace(*p))
|
---|
415 | p++;
|
---|
416 | }
|
---|
417 |
|
---|
418 | p--;
|
---|
419 | return (p);
|
---|
420 | }
|
---|
421 | #endif
|
---|
422 |
|
---|
423 |
|
---|
424 | /* cv__endword():
|
---|
425 | * Go to the end of this word according to vi
|
---|
426 | */
|
---|
427 | protected Char *
|
---|
428 | cv__endword(Char *p, Char *high, int n, int (*wtest)(Int))
|
---|
429 | {
|
---|
430 | int test;
|
---|
431 |
|
---|
432 | p++;
|
---|
433 |
|
---|
434 | while (n--) {
|
---|
435 | while ((p < high) && Isspace(*p))
|
---|
436 | p++;
|
---|
437 |
|
---|
438 | test = (*wtest)(*p);
|
---|
439 | while ((p < high) && (*wtest)(*p) == test)
|
---|
440 | p++;
|
---|
441 | }
|
---|
442 | p--;
|
---|
443 | return (p);
|
---|
444 | }
|
---|
445 |
|
---|
446 | /* ch_init():
|
---|
447 | * Initialize the character editor
|
---|
448 | */
|
---|
449 | protected int
|
---|
450 | ch_init(EditLine *el)
|
---|
451 | {
|
---|
452 | c_macro_t *ma = &el->el_chared.c_macro;
|
---|
453 |
|
---|
454 | el->el_line.buffer = el_malloc(EL_BUFSIZ *
|
---|
455 | sizeof(*el->el_line.buffer));
|
---|
456 | if (el->el_line.buffer == NULL)
|
---|
457 | return (-1);
|
---|
458 |
|
---|
459 | (void) memset(el->el_line.buffer, 0, EL_BUFSIZ *
|
---|
460 | sizeof(*el->el_line.buffer));
|
---|
461 | el->el_line.cursor = el->el_line.buffer;
|
---|
462 | el->el_line.lastchar = el->el_line.buffer;
|
---|
463 | el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
|
---|
464 |
|
---|
465 | el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ *
|
---|
466 | sizeof(*el->el_chared.c_undo.buf));
|
---|
467 | if (el->el_chared.c_undo.buf == NULL)
|
---|
468 | return (-1);
|
---|
469 | (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ *
|
---|
470 | sizeof(*el->el_chared.c_undo.buf));
|
---|
471 | el->el_chared.c_undo.len = -1;
|
---|
472 | el->el_chared.c_undo.cursor = 0;
|
---|
473 | el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ *
|
---|
474 | sizeof(*el->el_chared.c_redo.buf));
|
---|
475 | if (el->el_chared.c_redo.buf == NULL)
|
---|
476 | return (-1);
|
---|
477 | el->el_chared.c_redo.pos = el->el_chared.c_redo.buf;
|
---|
478 | el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ;
|
---|
479 | el->el_chared.c_redo.cmd = ED_UNASSIGNED;
|
---|
480 |
|
---|
481 | el->el_chared.c_vcmd.action = NOP;
|
---|
482 | el->el_chared.c_vcmd.pos = el->el_line.buffer;
|
---|
483 |
|
---|
484 | el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ *
|
---|
485 | sizeof(*el->el_chared.c_kill.buf));
|
---|
486 | if (el->el_chared.c_kill.buf == NULL)
|
---|
487 | return (-1);
|
---|
488 | (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ *
|
---|
489 | sizeof(*el->el_chared.c_kill.buf));
|
---|
490 | el->el_chared.c_kill.mark = el->el_line.buffer;
|
---|
491 | el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
|
---|
492 | el->el_chared.c_resizefun = NULL;
|
---|
493 | el->el_chared.c_resizearg = NULL;
|
---|
494 |
|
---|
495 | el->el_map.current = el->el_map.key;
|
---|
496 |
|
---|
497 | el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
|
---|
498 | el->el_state.doingarg = 0;
|
---|
499 | el->el_state.metanext = 0;
|
---|
500 | el->el_state.argument = 1;
|
---|
501 | el->el_state.lastcmd = ED_UNASSIGNED;
|
---|
502 |
|
---|
503 | ma->level = -1;
|
---|
504 | ma->offset = 0;
|
---|
505 | ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
|
---|
506 | if (ma->macro == NULL)
|
---|
507 | return (-1);
|
---|
508 | return (0);
|
---|
509 | }
|
---|
510 |
|
---|
511 | /* ch_reset():
|
---|
512 | * Reset the character editor
|
---|
513 | */
|
---|
514 | protected void
|
---|
515 | ch_reset(EditLine *el, int mclear)
|
---|
516 | {
|
---|
517 | el->el_line.cursor = el->el_line.buffer;
|
---|
518 | el->el_line.lastchar = el->el_line.buffer;
|
---|
519 |
|
---|
520 | el->el_chared.c_undo.len = -1;
|
---|
521 | el->el_chared.c_undo.cursor = 0;
|
---|
522 |
|
---|
523 | el->el_chared.c_vcmd.action = NOP;
|
---|
524 | el->el_chared.c_vcmd.pos = el->el_line.buffer;
|
---|
525 |
|
---|
526 | el->el_chared.c_kill.mark = el->el_line.buffer;
|
---|
527 |
|
---|
528 | el->el_map.current = el->el_map.key;
|
---|
529 |
|
---|
530 | el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
|
---|
531 | el->el_state.doingarg = 0;
|
---|
532 | el->el_state.metanext = 0;
|
---|
533 | el->el_state.argument = 1;
|
---|
534 | el->el_state.lastcmd = ED_UNASSIGNED;
|
---|
535 |
|
---|
536 | el->el_history.eventno = 0;
|
---|
537 |
|
---|
538 | if (mclear)
|
---|
539 | ch__clearmacro(el);
|
---|
540 | }
|
---|
541 |
|
---|
542 | private void
|
---|
543 | ch__clearmacro(EditLine *el)
|
---|
544 | {
|
---|
545 | c_macro_t *ma = &el->el_chared.c_macro;
|
---|
546 | while (ma->level >= 0)
|
---|
547 | el_free((ptr_t)ma->macro[ma->level--]);
|
---|
548 | }
|
---|
549 |
|
---|
550 | /* ch_enlargebufs():
|
---|
551 | * Enlarge line buffer to be able to hold twice as much characters.
|
---|
552 | * Returns 1 if successful, 0 if not.
|
---|
553 | */
|
---|
554 | protected int
|
---|
555 | ch_enlargebufs(EditLine *el, size_t addlen)
|
---|
556 | {
|
---|
557 | size_t sz, newsz;
|
---|
558 | Char *newbuffer, *oldbuf, *oldkbuf;
|
---|
559 |
|
---|
560 | sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
|
---|
561 | newsz = sz * 2;
|
---|
562 | /*
|
---|
563 | * If newly required length is longer than current buffer, we need
|
---|
564 | * to make the buffer big enough to hold both old and new stuff.
|
---|
565 | */
|
---|
566 | if (addlen > sz) {
|
---|
567 | while(newsz - sz < addlen)
|
---|
568 | newsz *= 2;
|
---|
569 | }
|
---|
570 |
|
---|
571 | /*
|
---|
572 | * Reallocate line buffer.
|
---|
573 | */
|
---|
574 | newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
|
---|
575 | if (!newbuffer)
|
---|
576 | return 0;
|
---|
577 |
|
---|
578 | /* zero the newly added memory, leave old data in */
|
---|
579 | (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
|
---|
580 |
|
---|
581 | oldbuf = el->el_line.buffer;
|
---|
582 |
|
---|
583 | el->el_line.buffer = newbuffer;
|
---|
584 | el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
|
---|
585 | el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
|
---|
586 | /* don't set new size until all buffers are enlarged */
|
---|
587 | el->el_line.limit = &newbuffer[sz - EL_LEAVE];
|
---|
588 |
|
---|
589 | /*
|
---|
590 | * Reallocate kill buffer.
|
---|
591 | */
|
---|
592 | newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * sizeof(*newbuffer));
|
---|
593 | if (!newbuffer)
|
---|
594 | return 0;
|
---|
595 |
|
---|
596 | /* zero the newly added memory, leave old data in */
|
---|
597 | (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
|
---|
598 |
|
---|
599 | oldkbuf = el->el_chared.c_kill.buf;
|
---|
600 |
|
---|
601 | el->el_chared.c_kill.buf = newbuffer;
|
---|
602 | el->el_chared.c_kill.last = newbuffer +
|
---|
603 | (el->el_chared.c_kill.last - oldkbuf);
|
---|
604 | el->el_chared.c_kill.mark = el->el_line.buffer +
|
---|
605 | (el->el_chared.c_kill.mark - oldbuf);
|
---|
606 |
|
---|
607 | /*
|
---|
608 | * Reallocate undo buffer.
|
---|
609 | */
|
---|
610 | newbuffer = el_realloc(el->el_chared.c_undo.buf,
|
---|
611 | newsz * sizeof(*newbuffer));
|
---|
612 | if (!newbuffer)
|
---|
613 | return 0;
|
---|
614 |
|
---|
615 | /* zero the newly added memory, leave old data in */
|
---|
616 | (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
|
---|
617 | el->el_chared.c_undo.buf = newbuffer;
|
---|
618 |
|
---|
619 | newbuffer = el_realloc(el->el_chared.c_redo.buf,
|
---|
620 | newsz * sizeof(*newbuffer));
|
---|
621 | if (!newbuffer)
|
---|
622 | return 0;
|
---|
623 | el->el_chared.c_redo.pos = newbuffer +
|
---|
624 | (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
|
---|
625 | el->el_chared.c_redo.lim = newbuffer +
|
---|
626 | (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
|
---|
627 | el->el_chared.c_redo.buf = newbuffer;
|
---|
628 |
|
---|
629 | if (!hist_enlargebuf(el, sz, newsz))
|
---|
630 | return 0;
|
---|
631 |
|
---|
632 | /* Safe to set enlarged buffer size */
|
---|
633 | el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE];
|
---|
634 | if (el->el_chared.c_resizefun)
|
---|
635 | (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
|
---|
636 | return 1;
|
---|
637 | }
|
---|
638 |
|
---|
639 | /* ch_end():
|
---|
640 | * Free the data structures used by the editor
|
---|
641 | */
|
---|
642 | protected void
|
---|
643 | ch_end(EditLine *el)
|
---|
644 | {
|
---|
645 | el_free((ptr_t) el->el_line.buffer);
|
---|
646 | el->el_line.buffer = NULL;
|
---|
647 | el->el_line.limit = NULL;
|
---|
648 | el_free((ptr_t) el->el_chared.c_undo.buf);
|
---|
649 | el->el_chared.c_undo.buf = NULL;
|
---|
650 | el_free((ptr_t) el->el_chared.c_redo.buf);
|
---|
651 | el->el_chared.c_redo.buf = NULL;
|
---|
652 | el->el_chared.c_redo.pos = NULL;
|
---|
653 | el->el_chared.c_redo.lim = NULL;
|
---|
654 | el->el_chared.c_redo.cmd = ED_UNASSIGNED;
|
---|
655 | el_free((ptr_t) el->el_chared.c_kill.buf);
|
---|
656 | el->el_chared.c_kill.buf = NULL;
|
---|
657 | ch_reset(el, 1);
|
---|
658 | el_free((ptr_t) el->el_chared.c_macro.macro);
|
---|
659 | el->el_chared.c_macro.macro = NULL;
|
---|
660 | }
|
---|
661 |
|
---|
662 |
|
---|
663 | /* el_insertstr():
|
---|
664 | * Insert string at cursorI
|
---|
665 | */
|
---|
666 | public int
|
---|
667 | FUN(el,insertstr)(EditLine *el, const Char *s)
|
---|
668 | {
|
---|
669 | size_t len;
|
---|
670 |
|
---|
671 | if ((len = Strlen(s)) == 0)
|
---|
672 | return (-1);
|
---|
673 | if (el->el_line.lastchar + len >= el->el_line.limit) {
|
---|
674 | if (!ch_enlargebufs(el, len))
|
---|
675 | return (-1);
|
---|
676 | }
|
---|
677 |
|
---|
678 | c_insert(el, (int)len);
|
---|
679 | while (*s)
|
---|
680 | *el->el_line.cursor++ = *s++;
|
---|
681 | return (0);
|
---|
682 | }
|
---|
683 |
|
---|
684 |
|
---|
685 | /* el_deletestr():
|
---|
686 | * Delete num characters before the cursor
|
---|
687 | */
|
---|
688 | public void
|
---|
689 | el_deletestr(EditLine *el, int n)
|
---|
690 | {
|
---|
691 | if (n <= 0)
|
---|
692 | return;
|
---|
693 |
|
---|
694 | if (el->el_line.cursor < &el->el_line.buffer[n])
|
---|
695 | return;
|
---|
696 |
|
---|
697 | c_delbefore(el, n); /* delete before dot */
|
---|
698 | el->el_line.cursor -= n;
|
---|
699 | if (el->el_line.cursor < el->el_line.buffer)
|
---|
700 | el->el_line.cursor = el->el_line.buffer;
|
---|
701 | }
|
---|
702 |
|
---|
703 | /* c_gets():
|
---|
704 | * Get a string
|
---|
705 | */
|
---|
706 | protected int
|
---|
707 | c_gets(EditLine *el, Char *buf, const Char *prompt)
|
---|
708 | {
|
---|
709 | Char ch;
|
---|
710 | ssize_t len;
|
---|
711 | Char *cp = el->el_line.buffer;
|
---|
712 |
|
---|
713 | if (prompt) {
|
---|
714 | len = Strlen(prompt);
|
---|
715 | (void)memcpy(cp, prompt, len * sizeof(*cp));
|
---|
716 | cp += len;
|
---|
717 | }
|
---|
718 | len = 0;
|
---|
719 |
|
---|
720 | for (;;) {
|
---|
721 | el->el_line.cursor = cp;
|
---|
722 | *cp = ' ';
|
---|
723 | el->el_line.lastchar = cp + 1;
|
---|
724 | re_refresh(el);
|
---|
725 |
|
---|
726 | if (FUN(el,getc)(el, &ch) != 1) {
|
---|
727 | ed_end_of_file(el, 0);
|
---|
728 | len = -1;
|
---|
729 | break;
|
---|
730 | }
|
---|
731 |
|
---|
732 | switch (ch) {
|
---|
733 |
|
---|
734 | case 0010: /* Delete and backspace */
|
---|
735 | case 0177:
|
---|
736 | if (len == 0) {
|
---|
737 | len = -1;
|
---|
738 | break;
|
---|
739 | }
|
---|
740 | cp--;
|
---|
741 | continue;
|
---|
742 |
|
---|
743 | case 0033: /* ESC */
|
---|
744 | case '\r': /* Newline */
|
---|
745 | case '\n':
|
---|
746 | buf[len] = ch;
|
---|
747 | break;
|
---|
748 |
|
---|
749 | default:
|
---|
750 | if (len >= EL_BUFSIZ - 16)
|
---|
751 | term_beep(el);
|
---|
752 | else {
|
---|
753 | buf[len++] = ch;
|
---|
754 | *cp++ = ch;
|
---|
755 | }
|
---|
756 | continue;
|
---|
757 | }
|
---|
758 | break;
|
---|
759 | }
|
---|
760 |
|
---|
761 | el->el_line.buffer[0] = '\0';
|
---|
762 | el->el_line.lastchar = el->el_line.buffer;
|
---|
763 | el->el_line.cursor = el->el_line.buffer;
|
---|
764 | return (int)len;
|
---|
765 | }
|
---|
766 |
|
---|
767 |
|
---|
768 | /* c_hpos():
|
---|
769 | * Return the current horizontal position of the cursor
|
---|
770 | */
|
---|
771 | protected int
|
---|
772 | c_hpos(EditLine *el)
|
---|
773 | {
|
---|
774 | Char *ptr;
|
---|
775 |
|
---|
776 | /*
|
---|
777 | * Find how many characters till the beginning of this line.
|
---|
778 | */
|
---|
779 | if (el->el_line.cursor == el->el_line.buffer)
|
---|
780 | return (0);
|
---|
781 | else {
|
---|
782 | for (ptr = el->el_line.cursor - 1;
|
---|
783 | ptr >= el->el_line.buffer && *ptr != '\n';
|
---|
784 | ptr--)
|
---|
785 | continue;
|
---|
786 | return (int)(el->el_line.cursor - ptr - 1);
|
---|
787 | }
|
---|
788 | }
|
---|
789 |
|
---|
790 | protected int
|
---|
791 | ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
|
---|
792 | {
|
---|
793 | el->el_chared.c_resizefun = f;
|
---|
794 | el->el_chared.c_resizearg = a;
|
---|
795 | return 0;
|
---|
796 | }
|
---|