Merge commit '9992e6a682b1c35b4385c3b512db329ec8ab9ede'
[unleashed.git] / lib / libedit / eln.c
blobe7538e8ee5242b348c28b664b098bef331d4a896
1 /* $OpenBSD: eln.c,v 1.18 2016/04/11 21:17:29 schwarze Exp $ */
2 /* $NetBSD: eln.c,v 1.9 2010/11/04 13:53:12 christos Exp $ */
4 /*-
5 * Copyright (c) 2009 The NetBSD Foundation, Inc.
6 * All rights reserved.
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.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
29 #include "config.h"
31 #include <errno.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
36 #include "el.h"
38 int
39 el_getc(EditLine *el, char *cp)
41 int num_read;
42 wchar_t wc = 0;
44 num_read = el_wgetc(el, &wc);
45 *cp = '\0';
46 if (num_read <= 0)
47 return num_read;
48 num_read = wctob(wc);
49 if (num_read == EOF) {
50 errno = ERANGE;
51 return -1;
52 } else {
53 *cp = num_read;
54 return 1;
59 void
60 el_push(EditLine *el, const char *str)
62 /* Using multibyte->wide string decoding works fine under single-byte
63 * character sets too, and Does The Right Thing. */
64 el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
68 const char *
69 el_gets(EditLine *el, int *nread)
71 const wchar_t *tmp;
72 wchar_t *rd, *wr;
74 if ((tmp = el_wgets(el, nread)) == NULL)
75 return NULL;
78 * Temporary until the libedit audit is complete:
79 * Filter out all non-ASCII characters.
81 wr = (wchar_t *)tmp;
82 for (rd = wr; *rd != L'\0'; rd++) {
83 if (wr < rd)
84 *wr = *rd;
85 if (*rd < 128)
86 wr++;
88 *wr = L'\0';
89 *nread = wr - tmp;
91 return ct_encode_string(tmp, &el->el_lgcyconv);
95 int
96 el_parse(EditLine *el, int argc, const char *argv[])
98 int ret;
99 const wchar_t **wargv;
101 wargv = (const wchar_t **)
102 ct_decode_argv(argc, argv, &el->el_lgcyconv);
103 if (!wargv)
104 return -1;
105 ret = el_wparse(el, argc, wargv);
106 free(wargv);
108 return ret;
113 el_set(EditLine *el, int op, ...)
115 va_list ap;
116 int ret;
118 if (!el)
119 return -1;
120 va_start(ap, op);
122 switch (op) {
123 case EL_PROMPT: /* el_pfunc_t */
124 case EL_RPROMPT: {
125 el_pfunc_t p = va_arg(ap, el_pfunc_t);
126 ret = prompt_set(el, p, 0, op, 0);
127 break;
130 case EL_RESIZE: {
131 el_zfunc_t p = va_arg(ap, el_zfunc_t);
132 void *arg = va_arg(ap, void *);
133 ret = ch_resizefun(el, p, arg);
134 break;
137 case EL_TERMINAL: /* const char * */
138 ret = el_wset(el, op, va_arg(ap, char *));
139 break;
141 case EL_EDITOR: /* const wchar_t * */
142 ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
143 &el->el_lgcyconv));
144 break;
146 case EL_SIGNAL: /* int */
147 case EL_EDITMODE:
148 case EL_UNBUFFERED:
149 case EL_PREP_TERM:
150 ret = el_wset(el, op, va_arg(ap, int));
151 break;
153 case EL_BIND: /* const char * list -> const wchar_t * list */
154 case EL_TELLTC:
155 case EL_SETTC:
156 case EL_ECHOTC:
157 case EL_SETTY: {
158 const char *argv[21];
159 int i;
160 const wchar_t **wargv;
161 for (i = 1; i < (int)__arraycount(argv) - 1; ++i)
162 if ((argv[i] = va_arg(ap, char *)) == NULL)
163 break;
164 argv[0] = argv[i] = NULL;
165 wargv = (const wchar_t **)
166 ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
167 if (!wargv) {
168 ret = -1;
169 goto out;
172 * AFAIK we can't portably pass through our new wargv to
173 * el_wset(), so we have to reimplement the body of
174 * el_wset() for these ops.
176 switch (op) {
177 case EL_BIND:
178 wargv[0] = L"bind";
179 ret = map_bind(el, i, wargv);
180 break;
181 case EL_TELLTC:
182 wargv[0] = L"telltc";
183 ret = terminal_telltc(el, i, wargv);
184 break;
185 case EL_SETTC:
186 wargv[0] = L"settc";
187 ret = terminal_settc(el, i, wargv);
188 break;
189 case EL_ECHOTC:
190 wargv[0] = L"echotc";
191 ret = terminal_echotc(el, i, wargv);
192 break;
193 case EL_SETTY:
194 wargv[0] = L"setty";
195 ret = tty_stty(el, i, wargv);
196 break;
197 default:
198 ret = -1;
200 free(wargv);
201 break;
204 /* XXX: do we need to change el_func_t too? */
205 case EL_ADDFN: { /* const char *, const char *, el_func_t */
206 const char *args[2];
207 el_func_t func;
208 wchar_t **wargv;
210 args[0] = va_arg(ap, const char *);
211 args[1] = va_arg(ap, const char *);
212 func = va_arg(ap, el_func_t);
214 wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
215 if (!wargv) {
216 ret = -1;
217 goto out;
219 /* XXX: The two strdup's leak */
220 ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]),
221 func);
222 free(wargv);
223 break;
225 case EL_HIST: { /* hist_fun_t, const char * */
226 hist_fun_t fun = va_arg(ap, hist_fun_t);
227 void *ptr = va_arg(ap, void *);
228 ret = hist_set(el, fun, ptr);
229 el->el_flags |= NARROW_HISTORY;
230 break;
232 case EL_GETCFN: /* el_rfunc_t */
233 ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
234 break;
235 case EL_CLIENTDATA: /* void * */
236 ret = el_wset(el, op, va_arg(ap, void *));
237 break;
238 case EL_SETFP: { /* int, FILE * */
239 int what = va_arg(ap, int);
240 FILE *fp = va_arg(ap, FILE *);
241 ret = el_wset(el, op, what, fp);
242 break;
244 case EL_PROMPT_ESC: /* el_pfunc_t, char */
245 case EL_RPROMPT_ESC: {
246 el_pfunc_t p = va_arg(ap, el_pfunc_t);
247 char c = va_arg(ap, int);
248 ret = prompt_set(el, p, c, op, 0);
249 break;
251 default:
252 ret = -1;
253 break;
256 out:
257 va_end(ap);
258 return ret;
263 el_get(EditLine *el, int op, ...)
265 va_list ap;
266 int ret;
268 if (!el)
269 return -1;
271 va_start(ap, op);
273 switch (op) {
274 case EL_PROMPT: /* el_pfunc_t * */
275 case EL_RPROMPT: {
276 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
277 ret = prompt_get(el, p, 0, op);
278 break;
281 case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
282 case EL_RPROMPT_ESC: {
283 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
284 char *c = va_arg(ap, char *);
285 wchar_t wc = 0;
286 ret = prompt_get(el, p, &wc, op);
287 *c = (unsigned char)wc;
288 break;
291 case EL_EDITOR: {
292 const char **p = va_arg(ap, const char **);
293 const wchar_t *pw;
294 ret = el_wget(el, op, &pw);
295 *p = ct_encode_string(pw, &el->el_lgcyconv);
296 if (!el->el_lgcyconv.csize)
297 ret = -1;
298 break;
301 case EL_TERMINAL: /* const char ** */
302 ret = el_wget(el, op, va_arg(ap, const char **));
303 break;
305 case EL_SIGNAL: /* int * */
306 case EL_EDITMODE:
307 case EL_UNBUFFERED:
308 case EL_PREP_TERM:
309 ret = el_wget(el, op, va_arg(ap, int *));
310 break;
312 case EL_GETTC: {
313 char *argv[20];
314 static char gettc[] = "gettc";
315 int i;
316 for (i = 1; i < (int)__arraycount(argv); ++i)
317 if ((argv[i] = va_arg(ap, char *)) == NULL)
318 break;
319 argv[0] = gettc;
320 ret = terminal_gettc(el, i, argv);
321 break;
324 case EL_GETCFN: /* el_rfunc_t */
325 ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
326 break;
328 case EL_CLIENTDATA: /* void ** */
329 ret = el_wget(el, op, va_arg(ap, void **));
330 break;
332 case EL_GETFP: { /* int, FILE ** */
333 int what = va_arg(ap, int);
334 FILE **fpp = va_arg(ap, FILE **);
335 ret = el_wget(el, op, what, fpp);
336 break;
339 default:
340 ret = -1;
341 break;
344 va_end(ap);
345 return ret;
349 const LineInfo *
350 el_line(EditLine *el)
352 const LineInfoW *winfo = el_wline(el);
353 LineInfo *info = &el->el_lgcylinfo;
354 size_t offset;
355 const wchar_t *p;
357 info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
359 offset = 0;
360 for (p = winfo->buffer; p < winfo->cursor; p++)
361 offset += ct_enc_width(*p);
362 info->cursor = info->buffer + offset;
364 offset = 0;
365 for (p = winfo->buffer; p < winfo->lastchar; p++)
366 offset += ct_enc_width(*p);
367 info->lastchar = info->buffer + offset;
369 return info;
374 el_insertstr(EditLine *el, const char *str)
376 return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));