MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eln.c
1 /* $NetBSD: eln.c,v 1.13 2011/08/16 16:25:15 christos Exp $ */
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)
37 #endif /* not lint && not SCCSID */
38 
39 #include "histedit.h"
40 #include "el.h"
41 #include "read.h"
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 
46 public int
47 el_getc(EditLine *el, char *cp)
48 {
49  int num_read;
50  wchar_t wc = 0;
51 
52  num_read = el_wgetc (el, &wc);
53 
54  if (num_read > 0)
55  *cp = (char)wc;
56  return num_read;
57 }
58 
59 
60 public void
61 el_push(EditLine *el, const char *str)
62 {
63  /* Using multibyte->wide string decoding works fine under single-byte
64  * character sets too, and Does The Right Thing. */
65  el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
66 }
67 
68 
69 public const char *
70 el_gets(EditLine *el, int *nread)
71 {
72  const wchar_t *tmp;
73 
74  tmp = el_wgets(el, nread);
75  return ct_encode_string(tmp, &el->el_lgcyconv);
76 }
77 
78 
79 public int
80 el_parse(EditLine *el, int argc, const char *argv[])
81 {
82  int ret;
83  const wchar_t **wargv;
84 
85  wargv = (const wchar_t **)
86  ct_decode_argv(argc, argv, &el->el_lgcyconv);
87  if (!wargv)
88  return -1;
89  ret = el_wparse(el, argc, wargv);
90  ct_free_argv(wargv);
91 
92  return ret;
93 }
94 
95 
96 public int
97 el_set(EditLine *el, int op, ...)
98 {
99  va_list ap;
100  int ret;
101 
102  if (!el)
103  return -1;
104  va_start(ap, op);
105 
106  switch (op) {
107  case EL_PROMPT: /* el_pfunc_t */
108  case EL_RPROMPT: {
109  el_pfunc_t p = va_arg(ap, el_pfunc_t);
110  ret = prompt_set(el, p, 0, op, 0);
111  break;
112  }
113 
114  case EL_RESIZE: {
115  el_zfunc_t p = va_arg(ap, el_zfunc_t);
116  void *arg = va_arg(ap, void *);
117  ret = ch_resizefun(el, p, arg);
118  break;
119  }
120 
121  case EL_TERMINAL: /* const char * */
122  ret = el_wset(el, op, va_arg(ap, char *));
123  break;
124 
125  case EL_EDITOR: /* const wchar_t * */
126  ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
127  &el->el_lgcyconv));
128  break;
129 
130  case EL_SIGNAL: /* int */
131  case EL_EDITMODE:
132  case EL_UNBUFFERED:
133  case EL_PREP_TERM:
134  ret = el_wset(el, op, va_arg(ap, int));
135  break;
136 
137  case EL_BIND: /* const char * list -> const wchar_t * list */
138  case EL_TELLTC:
139  case EL_SETTC:
140  case EL_ECHOTC:
141  case EL_SETTY: {
142  const char *argv[20];
143  int i;
144  const wchar_t **wargv;
145  for (i = 1; i < (int)__arraycount(argv); ++i)
146  if ((argv[i] = va_arg(ap, char *)) == NULL)
147  break;
148  argv[0] = NULL;
149  wargv = (const wchar_t **)
150  ct_decode_argv(i, argv, &el->el_lgcyconv);
151  if (!wargv) {
152  ret = -1;
153  goto out;
154  }
155  /*
156  * AFAIK we can't portably pass through our new wargv to
157  * el_wset(), so we have to reimplement the body of
158  * el_wset() for these ops.
159  */
160  switch (op) {
161  case EL_BIND:
162  wargv[0] = STR("bind");
163  ret = map_bind(el, i, wargv);
164  break;
165  case EL_TELLTC:
166  wargv[0] = STR("telltc");
167  ret = terminal_telltc(el, i, wargv);
168  break;
169  case EL_SETTC:
170  wargv[0] = STR("settc");
171  ret = terminal_settc(el, i, wargv);
172  break;
173  case EL_ECHOTC:
174  wargv[0] = STR("echotc");
175  ret = terminal_echotc(el, i, wargv);
176  break;
177  case EL_SETTY:
178  wargv[0] = STR("setty");
179  ret = tty_stty(el, i, wargv);
180  break;
181  default:
182  ret = -1;
183  }
184  ct_free_argv(wargv);
185  break;
186  }
187 
188  /* XXX: do we need to change el_func_t too? */
189  case EL_ADDFN: { /* const char *, const char *, el_func_t */
190  const char *args[2];
191  el_func_t func;
192  wchar_t **wargv;
193 
194  args[0] = va_arg(ap, const char *);
195  args[1] = va_arg(ap, const char *);
196  func = va_arg(ap, el_func_t);
197 
198  wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
199  if (!wargv) {
200  ret = -1;
201  goto out;
202  }
203  /* XXX: The two strdups leak. */
204  ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
205  func);
206  ct_free_argv(wargv);
207  break;
208  }
209  case EL_HIST: { /* hist_fun_t, const char * */
210  hist_fun_t fun = va_arg(ap, hist_fun_t);
211  void *ptr = va_arg(ap, void *);
212  ret = hist_set(el, fun, ptr);
213  el->el_flags |= NARROW_HISTORY;
214  break;
215  }
216  /* XXX: do we need to change el_rfunc_t? */
217  case EL_GETCFN: /* el_rfunc_t */
218  ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
219  el->el_flags |= NARROW_READ;
220  break;
221  case EL_CLIENTDATA: /* void * */
222  ret = el_wset(el, op, va_arg(ap, void *));
223  break;
224  case EL_SETFP: { /* int, FILE * */
225  int what = va_arg(ap, int);
226  FILE *fp = va_arg(ap, FILE *);
227  ret = el_wset(el, op, what, fp);
228  break;
229  }
230  case EL_PROMPT_ESC: /* el_pfunc_t, char */
231  case EL_RPROMPT_ESC: {
232  el_pfunc_t p = va_arg(ap, el_pfunc_t);
233  char c = (char)va_arg(ap, int);
234  ret = prompt_set(el, p, c, op, 0);
235  break;
236  }
237  default:
238  ret = -1;
239  break;
240  }
241 
242 out:
243  va_end(ap);
244  return ret;
245 }
246 
247 
248 public int
249 el_get(EditLine *el, int op, ...)
250 {
251  va_list ap;
252  int ret;
253 
254  if (!el)
255  return -1;
256 
257  va_start(ap, op);
258 
259  switch (op) {
260  case EL_PROMPT: /* el_pfunc_t * */
261  case EL_RPROMPT: {
262  el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
263  ret = prompt_get(el, p, 0, op);
264  break;
265  }
266 
267  case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
268  case EL_RPROMPT_ESC: {
269  el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
270  char *c = va_arg(ap, char *);
271  wchar_t wc = 0;
272  ret = prompt_get(el, p, &wc, op);
273  *c = (char)wc;
274  break;
275  }
276 
277  case EL_EDITOR: {
278  const char **p = va_arg(ap, const char **);
279  const wchar_t *pw;
280  ret = el_wget(el, op, &pw);
281  *p = ct_encode_string(pw, &el->el_lgcyconv);
282  if (!el->el_lgcyconv.csize)
283  ret = -1;
284  break;
285  }
286 
287  case EL_TERMINAL: /* const char ** */
288  ret = el_wget(el, op, va_arg(ap, const char **));
289  break;
290 
291  case EL_SIGNAL: /* int * */
292  case EL_EDITMODE:
293  case EL_UNBUFFERED:
294  case EL_PREP_TERM:
295  ret = el_wget(el, op, va_arg(ap, int *));
296  break;
297 
298  case EL_GETTC: {
299  char *argv[20];
300  static char gettc[] = "gettc";
301  int i;
302  for (i = 1; i < (int)__arraycount(argv); ++i)
303  if ((argv[i] = va_arg(ap, char *)) == NULL)
304  break;
305  argv[0] = gettc;
306  ret = terminal_gettc(el, i, argv);
307  break;
308  }
309 
310  /* XXX: do we need to change el_rfunc_t? */
311  case EL_GETCFN: /* el_rfunc_t */
312  ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
313  break;
314 
315  case EL_CLIENTDATA: /* void ** */
316  ret = el_wget(el, op, va_arg(ap, void **));
317  break;
318 
319  case EL_GETFP: { /* int, FILE ** */
320  int what = va_arg(ap, int);
321  FILE **fpp = va_arg(ap, FILE **);
322  ret = el_wget(el, op, what, fpp);
323  break;
324  }
325 
326  default:
327  ret = -1;
328  break;
329  }
330 
331  va_end(ap);
332  return ret;
333 }
334 
335 
336 const LineInfo *
337 el_line(EditLine *el)
338 {
339  const LineInfoW *winfo = el_wline(el);
340  LineInfo *info = &el->el_lgcylinfo;
341  size_t offset;
342  const Char *p;
343 
344  info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
345 
346  offset = 0;
347  for (p = winfo->buffer; p < winfo->cursor; p++)
348  offset += ct_enc_width(*p);
349  info->cursor = info->buffer + offset;
350 
351  offset = 0;
352  for (p = winfo->buffer; p < winfo->lastchar; p++)
353  offset += ct_enc_width(*p);
354  info->lastchar = info->buffer + offset;
355 
356  return info;
357 }
358 
359 
360 int
361 el_insertstr(EditLine *el, const char *str)
362 {
363  return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
364 }