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