Annotation of src/lib/libedit/eln.c, Revision 1.34
1.34 ! christos 1: /* $NetBSD: eln.c,v 1.33 2016/04/11 18:56:31 christos Exp $ */
1.1 christos 2:
3: /*-
4: * Copyright (c) 2009 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28: #include "config.h"
29: #if !defined(lint) && !defined(SCCSID)
1.34 ! christos 30: __RCSID("$NetBSD: eln.c,v 1.33 2016/04/11 18:56:31 christos Exp $");
1.1 christos 31: #endif /* not lint && not SCCSID */
32:
1.22 christos 33: #include <errno.h>
1.1 christos 34: #include <stdarg.h>
35: #include <stdio.h>
1.2 christos 36: #include <stdlib.h>
1.1 christos 37:
1.25 christos 38: #include "el.h"
39:
1.33 christos 40: int
1.1 christos 41: el_getc(EditLine *el, char *cp)
42: {
43: int num_read;
44: wchar_t wc = 0;
45:
1.22 christos 46: num_read = el_wgetc(el, &wc);
47: *cp = '\0';
48: if (num_read <= 0)
49: return num_read;
1.30 christos 50: num_read = wctob(wc);
1.22 christos 51: if (num_read == EOF) {
52: errno = ERANGE;
53: return -1;
54: } else {
55: *cp = (char)num_read;
56: return 1;
57: }
1.1 christos 58: }
59:
60:
1.33 christos 61: void
1.1 christos 62: el_push(EditLine *el, const char *str)
63: {
64: /* Using multibyte->wide string decoding works fine under single-byte
65: * character sets too, and Does The Right Thing. */
66: el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
67: }
68:
69:
1.33 christos 70: const char *
1.1 christos 71: el_gets(EditLine *el, int *nread)
72: {
1.6 christos 73: const wchar_t *tmp;
74:
75: tmp = el_wgets(el, nread);
1.19 christos 76: if (tmp != NULL) {
1.21 christos 77: int i;
1.19 christos 78: size_t nwread = 0;
1.21 christos 79:
80: for (i = 0; i < *nread; i++)
1.19 christos 81: nwread += ct_enc_width(tmp[i]);
82: *nread = (int)nwread;
83: }
1.6 christos 84: return ct_encode_string(tmp, &el->el_lgcyconv);
1.1 christos 85: }
86:
87:
1.33 christos 88: int
1.1 christos 89: el_parse(EditLine *el, int argc, const char *argv[])
90: {
91: int ret;
92: const wchar_t **wargv;
93:
1.34 ! christos 94: wargv = (void *)ct_decode_argv(argc, argv, &el->el_lgcyconv);
1.1 christos 95: if (!wargv)
96: return -1;
97: ret = el_wparse(el, argc, wargv);
1.30 christos 98: el_free(wargv);
1.1 christos 99:
100: return ret;
101: }
102:
103:
1.33 christos 104: int
1.1 christos 105: el_set(EditLine *el, int op, ...)
106: {
107: va_list ap;
108: int ret;
109:
110: if (!el)
111: return -1;
112: va_start(ap, op);
113:
114: switch (op) {
115: case EL_PROMPT: /* el_pfunc_t */
116: case EL_RPROMPT: {
117: el_pfunc_t p = va_arg(ap, el_pfunc_t);
118: ret = prompt_set(el, p, 0, op, 0);
119: break;
120: }
121:
1.8 christos 122: case EL_RESIZE: {
123: el_zfunc_t p = va_arg(ap, el_zfunc_t);
124: void *arg = va_arg(ap, void *);
125: ret = ch_resizefun(el, p, arg);
126: break;
127: }
128:
1.17 christos 129: case EL_ALIAS_TEXT: {
130: el_afunc_t p = va_arg(ap, el_afunc_t);
131: void *arg = va_arg(ap, void *);
132: ret = ch_aliasfun(el, p, arg);
133: break;
134: }
135:
1.15 christos 136: case EL_PROMPT_ESC:
137: case EL_RPROMPT_ESC: {
138: el_pfunc_t p = va_arg(ap, el_pfunc_t);
139: int c = va_arg(ap, int);
140:
141: ret = prompt_set(el, p, c, op, 0);
142: break;
143: }
144:
1.1 christos 145: case EL_TERMINAL: /* const char * */
146: ret = el_wset(el, op, va_arg(ap, char *));
147: break;
148:
1.5 christos 149: case EL_EDITOR: /* const wchar_t * */
150: ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
151: &el->el_lgcyconv));
152: break;
153:
1.1 christos 154: case EL_SIGNAL: /* int */
155: case EL_EDITMODE:
156: case EL_UNBUFFERED:
157: case EL_PREP_TERM:
158: ret = el_wset(el, op, va_arg(ap, int));
159: break;
160:
161: case EL_BIND: /* const char * list -> const wchar_t * list */
162: case EL_TELLTC:
163: case EL_SETTC:
164: case EL_ECHOTC:
165: case EL_SETTY: {
166: const char *argv[20];
167: int i;
168: const wchar_t **wargv;
1.16 christos 169: for (i = 1; i < (int)__arraycount(argv) - 1; ++i)
170: if ((argv[i] = va_arg(ap, const char *)) == NULL)
1.1 christos 171: break;
1.16 christos 172: argv[0] = argv[i] = NULL;
1.34 ! christos 173: wargv = (void *)ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
1.1 christos 174: if (!wargv) {
175: ret = -1;
176: goto out;
177: }
178: /*
179: * AFAIK we can't portably pass through our new wargv to
180: * el_wset(), so we have to reimplement the body of
181: * el_wset() for these ops.
182: */
183: switch (op) {
184: case EL_BIND:
1.31 christos 185: wargv[0] = L"bind";
1.1 christos 186: ret = map_bind(el, i, wargv);
187: break;
188: case EL_TELLTC:
1.31 christos 189: wargv[0] = L"telltc";
1.11 christos 190: ret = terminal_telltc(el, i, wargv);
1.1 christos 191: break;
192: case EL_SETTC:
1.31 christos 193: wargv[0] = L"settc";
1.11 christos 194: ret = terminal_settc(el, i, wargv);
1.1 christos 195: break;
196: case EL_ECHOTC:
1.31 christos 197: wargv[0] = L"echotc";
1.11 christos 198: ret = terminal_echotc(el, i, wargv);
1.1 christos 199: break;
200: case EL_SETTY:
1.31 christos 201: wargv[0] = L"setty";
1.1 christos 202: ret = tty_stty(el, i, wargv);
203: break;
204: default:
205: ret = -1;
206: }
1.30 christos 207: el_free(wargv);
1.1 christos 208: break;
209: }
210:
211: /* XXX: do we need to change el_func_t too? */
212: case EL_ADDFN: { /* const char *, const char *, el_func_t */
213: const char *args[2];
214: el_func_t func;
215: wchar_t **wargv;
216:
217: args[0] = va_arg(ap, const char *);
218: args[1] = va_arg(ap, const char *);
219: func = va_arg(ap, el_func_t);
220:
221: wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
222: if (!wargv) {
223: ret = -1;
224: goto out;
225: }
1.23 christos 226: /* XXX: The two strdup's leak */
1.31 christos 227: ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]),
1.4 christos 228: func);
1.30 christos 229: el_free(wargv);
1.1 christos 230: break;
231: }
232: case EL_HIST: { /* hist_fun_t, const char * */
233: hist_fun_t fun = va_arg(ap, hist_fun_t);
1.12 christos 234: void *ptr = va_arg(ap, void *);
1.2 christos 235: ret = hist_set(el, fun, ptr);
1.9 christos 236: el->el_flags |= NARROW_HISTORY;
1.1 christos 237: break;
238: }
1.15 christos 239:
1.1 christos 240: case EL_GETCFN: /* el_rfunc_t */
241: ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
242: break;
1.15 christos 243:
1.1 christos 244: case EL_CLIENTDATA: /* void * */
245: ret = el_wset(el, op, va_arg(ap, void *));
246: break;
1.15 christos 247:
1.1 christos 248: case EL_SETFP: { /* int, FILE * */
249: int what = va_arg(ap, int);
250: FILE *fp = va_arg(ap, FILE *);
251: ret = el_wset(el, op, what, fp);
252: break;
253: }
1.15 christos 254:
255: case EL_REFRESH:
256: re_clear_display(el);
257: re_refresh(el);
258: terminal__flush(el);
259: ret = 0;
1.1 christos 260: break;
1.15 christos 261:
1.1 christos 262: default:
263: ret = -1;
264: break;
265: }
266:
267: out:
268: va_end(ap);
269: return ret;
270: }
271:
272:
1.33 christos 273: int
1.1 christos 274: el_get(EditLine *el, int op, ...)
275: {
276: va_list ap;
277: int ret;
278:
279: if (!el)
280: return -1;
281:
282: va_start(ap, op);
283:
284: switch (op) {
285: case EL_PROMPT: /* el_pfunc_t * */
286: case EL_RPROMPT: {
287: el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
1.2 christos 288: ret = prompt_get(el, p, 0, op);
1.1 christos 289: break;
290: }
291:
292: case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
293: case EL_RPROMPT_ESC: {
294: el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
295: char *c = va_arg(ap, char *);
1.10 mrg 296: wchar_t wc = 0;
1.2 christos 297: ret = prompt_get(el, p, &wc, op);
1.13 christos 298: *c = (char)wc;
1.1 christos 299: break;
300: }
301:
302: case EL_EDITOR: {
303: const char **p = va_arg(ap, const char **);
304: const wchar_t *pw;
305: ret = el_wget(el, op, &pw);
306: *p = ct_encode_string(pw, &el->el_lgcyconv);
307: if (!el->el_lgcyconv.csize)
308: ret = -1;
309: break;
310: }
311:
312: case EL_TERMINAL: /* const char ** */
313: ret = el_wget(el, op, va_arg(ap, const char **));
314: break;
315:
316: case EL_SIGNAL: /* int * */
317: case EL_EDITMODE:
318: case EL_UNBUFFERED:
319: case EL_PREP_TERM:
320: ret = el_wget(el, op, va_arg(ap, int *));
321: break;
322:
323: case EL_GETTC: {
324: char *argv[20];
325: static char gettc[] = "gettc";
326: int i;
327: for (i = 1; i < (int)__arraycount(argv); ++i)
328: if ((argv[i] = va_arg(ap, char *)) == NULL)
329: break;
330: argv[0] = gettc;
1.11 christos 331: ret = terminal_gettc(el, i, argv);
1.1 christos 332: break;
333: }
334:
335: case EL_GETCFN: /* el_rfunc_t */
336: ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
337: break;
338:
339: case EL_CLIENTDATA: /* void ** */
340: ret = el_wget(el, op, va_arg(ap, void **));
341: break;
342:
343: case EL_GETFP: { /* int, FILE ** */
344: int what = va_arg(ap, int);
345: FILE **fpp = va_arg(ap, FILE **);
346: ret = el_wget(el, op, what, fpp);
347: break;
348: }
349:
350: default:
351: ret = -1;
352: break;
353: }
354:
355: va_end(ap);
356: return ret;
357: }
358:
359:
360: const LineInfo *
361: el_line(EditLine *el)
362: {
363: const LineInfoW *winfo = el_wline(el);
364: LineInfo *info = &el->el_lgcylinfo;
1.7 christos 365: size_t offset;
1.32 christos 366: const wchar_t *p;
1.1 christos 367:
368: info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
1.7 christos 369:
370: offset = 0;
371: for (p = winfo->buffer; p < winfo->cursor; p++)
372: offset += ct_enc_width(*p);
373: info->cursor = info->buffer + offset;
374:
375: offset = 0;
376: for (p = winfo->buffer; p < winfo->lastchar; p++)
377: offset += ct_enc_width(*p);
378: info->lastchar = info->buffer + offset;
379:
1.1 christos 380: return info;
381: }
382:
383:
384: int
385: el_insertstr(EditLine *el, const char *str)
386: {
387: return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
388: }
CVSweb <webmaster@jp.NetBSD.org>