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