Annotation of src/lib/libedit/eln.c, Revision 1.17
1.17 ! christos 1: /* $NetBSD: eln.c,v 1.16 2014/05/20 15:05:08 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: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the NetBSD
18: * Foundation, Inc. and its contributors.
19: * 4. Neither the name of The NetBSD Foundation nor the names of its
20: * contributors may be used to endorse or promote products derived
21: * from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35: #include "config.h"
36: #if !defined(lint) && !defined(SCCSID)
1.17 ! christos 37: __RCSID("$NetBSD: eln.c,v 1.16 2014/05/20 15:05:08 christos Exp $");
1.1 christos 38: #endif /* not lint && not SCCSID */
39:
40: #include "histedit.h"
41: #include "el.h"
42: #include "read.h"
43: #include <stdarg.h>
44: #include <stdio.h>
1.2 christos 45: #include <stdlib.h>
1.1 christos 46:
47: public int
48: el_getc(EditLine *el, char *cp)
49: {
50: int num_read;
51: wchar_t wc = 0;
52:
1.7 christos 53: if (!(el->el_flags & CHARSET_IS_UTF8))
54: el->el_flags |= IGNORE_EXTCHARS;
1.1 christos 55: num_read = el_wgetc (el, &wc);
1.7 christos 56: if (!(el->el_flags & CHARSET_IS_UTF8))
57: el->el_flags &= ~IGNORE_EXTCHARS;
1.1 christos 58:
59: if (num_read > 0)
1.13 christos 60: *cp = (char)wc;
1.1 christos 61: return num_read;
62: }
63:
64:
65: public void
66: el_push(EditLine *el, const char *str)
67: {
68: /* Using multibyte->wide string decoding works fine under single-byte
69: * character sets too, and Does The Right Thing. */
70: el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
71: }
72:
73:
74: public const char *
75: el_gets(EditLine *el, int *nread)
76: {
1.6 christos 77: const wchar_t *tmp;
78:
1.1 christos 79: el->el_flags |= IGNORE_EXTCHARS;
1.6 christos 80: tmp = el_wgets(el, nread);
1.1 christos 81: el->el_flags &= ~IGNORE_EXTCHARS;
1.6 christos 82: return ct_encode_string(tmp, &el->el_lgcyconv);
1.1 christos 83: }
84:
85:
86: public int
87: el_parse(EditLine *el, int argc, const char *argv[])
88: {
89: int ret;
90: const wchar_t **wargv;
91:
92: wargv = (const wchar_t **)
93: ct_decode_argv(argc, argv, &el->el_lgcyconv);
94: if (!wargv)
95: return -1;
96: ret = el_wparse(el, argc, wargv);
1.2 christos 97: ct_free_argv(wargv);
1.1 christos 98:
99: return ret;
100: }
101:
102:
103: public int
104: el_set(EditLine *el, int op, ...)
105: {
106: va_list ap;
107: int ret;
108:
109: if (!el)
110: return -1;
111: va_start(ap, op);
112:
113: switch (op) {
114: case EL_PROMPT: /* el_pfunc_t */
115: case EL_RPROMPT: {
116: el_pfunc_t p = va_arg(ap, el_pfunc_t);
117: ret = prompt_set(el, p, 0, op, 0);
118: break;
119: }
120:
1.8 christos 121: case EL_RESIZE: {
122: el_zfunc_t p = va_arg(ap, el_zfunc_t);
123: void *arg = va_arg(ap, void *);
124: ret = ch_resizefun(el, p, arg);
125: break;
126: }
127:
1.17 ! christos 128: case EL_ALIAS_TEXT: {
! 129: el_afunc_t p = va_arg(ap, el_afunc_t);
! 130: void *arg = va_arg(ap, void *);
! 131: ret = ch_aliasfun(el, p, arg);
! 132: break;
! 133: }
! 134:
1.15 christos 135: case EL_PROMPT_ESC:
136: case EL_RPROMPT_ESC: {
137: el_pfunc_t p = va_arg(ap, el_pfunc_t);
138: int c = va_arg(ap, int);
139:
140: ret = prompt_set(el, p, c, op, 0);
141: break;
142: }
143:
1.1 christos 144: case EL_TERMINAL: /* const char * */
145: ret = el_wset(el, op, va_arg(ap, char *));
146: break;
147:
1.5 christos 148: case EL_EDITOR: /* const wchar_t * */
149: ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
150: &el->el_lgcyconv));
151: break;
152:
1.1 christos 153: case EL_SIGNAL: /* int */
154: case EL_EDITMODE:
155: case EL_UNBUFFERED:
156: case EL_PREP_TERM:
157: ret = el_wset(el, op, va_arg(ap, int));
158: break;
159:
160: case EL_BIND: /* const char * list -> const wchar_t * list */
161: case EL_TELLTC:
162: case EL_SETTC:
163: case EL_ECHOTC:
164: case EL_SETTY: {
165: const char *argv[20];
166: int i;
167: const wchar_t **wargv;
1.16 christos 168: for (i = 1; i < (int)__arraycount(argv) - 1; ++i)
169: if ((argv[i] = va_arg(ap, const char *)) == NULL)
1.1 christos 170: break;
1.16 christos 171: argv[0] = argv[i] = NULL;
1.1 christos 172: wargv = (const wchar_t **)
1.14 christos 173: 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:
185: wargv[0] = STR("bind");
186: ret = map_bind(el, i, wargv);
187: break;
188: case EL_TELLTC:
189: wargv[0] = STR("telltc");
1.11 christos 190: ret = terminal_telltc(el, i, wargv);
1.1 christos 191: break;
192: case EL_SETTC:
193: wargv[0] = STR("settc");
1.11 christos 194: ret = terminal_settc(el, i, wargv);
1.1 christos 195: break;
196: case EL_ECHOTC:
197: wargv[0] = STR("echotc");
1.11 christos 198: ret = terminal_echotc(el, i, wargv);
1.1 christos 199: break;
200: case EL_SETTY:
201: wargv[0] = STR("setty");
202: ret = tty_stty(el, i, wargv);
203: break;
204: default:
205: ret = -1;
206: }
1.2 christos 207: ct_free_argv(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.4 christos 226: // XXX: The two strdup's leak
227: ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
228: func);
1.2 christos 229: ct_free_argv(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: /* XXX: do we need to change el_rfunc_t? */
241: case EL_GETCFN: /* el_rfunc_t */
242: ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
1.3 christos 243: el->el_flags |= NARROW_READ;
1.1 christos 244: break;
1.15 christos 245:
1.1 christos 246: case EL_CLIENTDATA: /* void * */
247: ret = el_wset(el, op, va_arg(ap, void *));
248: break;
1.15 christos 249:
1.1 christos 250: case EL_SETFP: { /* int, FILE * */
251: int what = va_arg(ap, int);
252: FILE *fp = va_arg(ap, FILE *);
253: ret = el_wset(el, op, what, fp);
254: break;
255: }
1.15 christos 256:
257: case EL_REFRESH:
258: re_clear_display(el);
259: re_refresh(el);
260: terminal__flush(el);
261: ret = 0;
1.1 christos 262: break;
1.15 christos 263:
1.1 christos 264: default:
265: ret = -1;
266: break;
267: }
268:
269: out:
270: va_end(ap);
271: return ret;
272: }
273:
274:
275: public int
276: el_get(EditLine *el, int op, ...)
277: {
278: va_list ap;
279: int ret;
280:
281: if (!el)
282: return -1;
283:
284: va_start(ap, op);
285:
286: switch (op) {
287: case EL_PROMPT: /* el_pfunc_t * */
288: case EL_RPROMPT: {
289: el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
1.2 christos 290: ret = prompt_get(el, p, 0, op);
1.1 christos 291: break;
292: }
293:
294: case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
295: case EL_RPROMPT_ESC: {
296: el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
297: char *c = va_arg(ap, char *);
1.10 mrg 298: wchar_t wc = 0;
1.2 christos 299: ret = prompt_get(el, p, &wc, op);
1.13 christos 300: *c = (char)wc;
1.1 christos 301: break;
302: }
303:
304: case EL_EDITOR: {
305: const char **p = va_arg(ap, const char **);
306: const wchar_t *pw;
307: ret = el_wget(el, op, &pw);
308: *p = ct_encode_string(pw, &el->el_lgcyconv);
309: if (!el->el_lgcyconv.csize)
310: ret = -1;
311: break;
312: }
313:
314: case EL_TERMINAL: /* const char ** */
315: ret = el_wget(el, op, va_arg(ap, const char **));
316: break;
317:
318: case EL_SIGNAL: /* int * */
319: case EL_EDITMODE:
320: case EL_UNBUFFERED:
321: case EL_PREP_TERM:
322: ret = el_wget(el, op, va_arg(ap, int *));
323: break;
324:
325: case EL_GETTC: {
326: char *argv[20];
327: static char gettc[] = "gettc";
328: int i;
329: for (i = 1; i < (int)__arraycount(argv); ++i)
330: if ((argv[i] = va_arg(ap, char *)) == NULL)
331: break;
332: argv[0] = gettc;
1.11 christos 333: ret = terminal_gettc(el, i, argv);
1.1 christos 334: break;
335: }
336:
337: /* XXX: do we need to change el_rfunc_t? */
338: case EL_GETCFN: /* el_rfunc_t */
339: ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
340: break;
341:
342: case EL_CLIENTDATA: /* void ** */
343: ret = el_wget(el, op, va_arg(ap, void **));
344: break;
345:
346: case EL_GETFP: { /* int, FILE ** */
347: int what = va_arg(ap, int);
348: FILE **fpp = va_arg(ap, FILE **);
349: ret = el_wget(el, op, what, fpp);
350: break;
351: }
352:
353: default:
354: ret = -1;
355: break;
356: }
357:
358: va_end(ap);
359: return ret;
360: }
361:
362:
363: const LineInfo *
364: el_line(EditLine *el)
365: {
366: const LineInfoW *winfo = el_wline(el);
367: LineInfo *info = &el->el_lgcylinfo;
1.7 christos 368: size_t offset;
369: const Char *p;
1.1 christos 370:
371: info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
1.7 christos 372:
373: offset = 0;
374: for (p = winfo->buffer; p < winfo->cursor; p++)
375: offset += ct_enc_width(*p);
376: info->cursor = info->buffer + offset;
377:
378: offset = 0;
379: for (p = winfo->buffer; p < winfo->lastchar; p++)
380: offset += ct_enc_width(*p);
381: info->lastchar = info->buffer + offset;
382:
1.1 christos 383: return info;
384: }
385:
386:
387: int
388: el_insertstr(EditLine *el, const char *str)
389: {
390: return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
391: }
CVSweb <webmaster@jp.NetBSD.org>