root/src/noitedit/el.c

Revision 5b6ccbe33a8c64fc04d428ee186befdbf4e5a378, 9.6 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

first hack at non-blocking support

  • Property mode set to 100644
Line 
1 /*      $NetBSD: el.c,v 1.21 2001/01/05 22:45:30 christos Exp $ */
2
3 /*-
4  * Copyright (c) 1992, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38
39 #include "compat.h"
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)el.c        8.2 (Berkeley) 1/3/94";
43 #else
44 __RCSID("$NetBSD: el.c,v 1.21 2001/01/05 22:45:30 christos Exp $");
45 #endif
46 #endif /* not lint && not SCCSID */
47
48 /*
49  * el.c: EditLine interface functions
50  */
51 #include "sys.h"
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #include <sys/types.h>
57 #if !_MSC_VER
58 #include <sys/param.h>
59 #endif
60 #include <string.h>
61 #include <stdlib.h>
62 #include <stdarg.h>
63 #include <pthread.h>
64 #include "el.h"
65
66 pthread_key_t tputs_hack;
67 public void
68 el_multi_init() {
69   pthread_key_create(&tputs_hack, NULL);
70 }
71
72 public void
73 el_multi_set_el(EditLine *el) {
74   pthread_setspecific(tputs_hack, el);
75 }
76
77 public EditLine *
78 el_multi_get_el() {
79   return (EditLine *)pthread_getspecific(tputs_hack);
80 }
81
82 /* el_init():
83  *      Initialize editline and set default parameters.
84  */
85 public EditLine *
86 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
87 {
88
89         EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
90 #ifdef DEBUG
91         char *tty;
92 #endif
93
94         if (el == NULL)
95                 return (NULL);
96
97         memset(el, 0, sizeof(EditLine));
98
99         el->el_infd = fileno(fin);
100         el->el_outfile = fout;
101         el->el_errfile = ferr;
102         el->el_prog = strdup(prog);
103
104         /*
105          * Initialize all the modules. Order is important!!!
106          */
107         el->el_flags = 0;
108
109         (void) term_init(el);
110         (void) key_init(el);
111         (void) map_init(el);
112         if (tty_init(el) == -1)
113                 el->el_flags |= NO_TTY;
114         (void) ch_init(el);
115         (void) search_init(el);
116         (void) hist_init(el);
117         (void) prompt_init(el);
118         (void) sig_init(el);
119
120         return (el);
121 }
122
123
124 /* el_end():
125  *      Clean up.
126  */
127 public void
128 el_end(EditLine *el)
129 {
130
131         if (el == NULL)
132                 return;
133
134         el_reset(el);
135
136         term_end(el);
137         key_end(el);
138         map_end(el);
139         tty_end(el);
140         ch_end(el);
141         search_end(el);
142         hist_end(el);
143         prompt_end(el);
144         sig_end(el);
145
146         el_free((ptr_t) el->el_prog);
147         el_free((ptr_t) el);
148 }
149
150
151 /* el_reset():
152  *      Reset the tty and the parser
153  */
154 public void
155 el_reset(EditLine *el)
156 {
157
158         tty_cookedmode(el);
159         ch_reset(el);           /* XXX: Do we want that? */
160 }
161
162
163 /* el_set():
164  *      set the editline parameters
165  */
166 public int
167 el_set(EditLine *el, int op, ...)
168 {
169         va_list va;
170         int rv;
171         va_start(va, op);
172
173         if (el == NULL)
174                 return (-1);
175         switch (op) {
176         case EL_PROMPT:
177         case EL_RPROMPT:
178                 rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
179                 break;
180
181         case EL_TERMINAL:
182                 rv = term_set(el, va_arg(va, char *));
183                 break;
184
185         case EL_EDITOR:
186                 rv = map_set_editor(el, va_arg(va, char *));
187                 break;
188
189         case EL_SIGNAL:
190                 if (va_arg(va, int))
191                         el->el_flags |= HANDLE_SIGNALS;
192                 else
193                         el->el_flags &= ~HANDLE_SIGNALS;
194                 rv = 0;
195                 break;
196
197         case EL_BIND:
198         case EL_TELLTC:
199         case EL_SETTC:
200         case EL_ECHOTC:
201         case EL_SETTY:
202         {
203                 char *argv[20];
204                 int i;
205
206                 for (i = 1; i < 20; i++)
207                         if ((argv[i] = va_arg(va, char *)) == NULL)
208                                 break;
209
210                 switch (op) {
211                 case EL_BIND:
212                         argv[0] = "bind";
213                         rv = map_bind(el, i, argv);
214                         break;
215
216                 case EL_TELLTC:
217                         argv[0] = "telltc";
218                         rv = term_telltc(el, i, argv);
219                         break;
220
221                 case EL_SETTC:
222                         argv[0] = "settc";
223                         rv = term_settc(el, i, argv);
224                         break;
225
226                 case EL_ECHOTC:
227                         argv[0] = "echotc";
228                         rv = term_echotc(el, i, argv);
229                         break;
230
231                 case EL_SETTY:
232                         argv[0] = "setty";
233                         rv = tty_stty(el, i, argv);
234                         break;
235
236                 default:
237                         rv = -1;
238                         EL_ABORT((el->el_errfile, "Bad op %d\n", op));
239                         break;
240                 }
241                 break;
242         }
243
244         case EL_ADDFN:
245         {
246                 char *name = va_arg(va, char *);
247                 char *help = va_arg(va, char *);
248                 el_func_t func = va_arg(va, el_func_t);
249
250                 rv = map_addfunc(el, name, help, func);
251                 break;
252         }
253
254         case EL_HIST:
255         {
256                 hist_fun_t func = va_arg(va, hist_fun_t);
257                 ptr_t ptr = va_arg(va, char *);
258
259                 rv = hist_set(el, func, ptr);
260                 break;
261         }
262
263         case EL_EDITMODE:
264                 if (va_arg(va, int))
265                         el->el_flags &= ~EDIT_DISABLED;
266                 else
267                         el->el_flags |= EDIT_DISABLED;
268                 rv = 0;
269                 break;
270
271         default:
272                 rv = -1;
273         }
274
275         va_end(va);
276         return (rv);
277 }
278
279
280 /* el_get():
281  *      retrieve the editline parameters
282  */
283 public int
284 el_get(EditLine *el, int op, void *ret)
285 {
286         int rv;
287         union {
288                 void *vptr;
289                 const char *cptr;
290                 el_pfunc_t elpf;
291         } vret;
292
293         vret.vptr = ret;
294         if (el == NULL || ret == NULL)
295                 return (-1);
296         switch (op) {
297         case EL_PROMPT:
298         case EL_RPROMPT:
299                 rv = prompt_get(el, &vret.elpf, op);
300                 break;
301
302         case EL_EDITOR:
303                 rv = map_get_editor(el, &vret.cptr);
304                 break;
305
306         case EL_SIGNAL:
307                 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
308                 rv = 0;
309                 break;
310
311         case EL_EDITMODE:
312                 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
313                 rv = 0;
314                 break;
315
316 #if 0                           /* XXX */
317         case EL_TERMINAL:
318                 rv = term_get(el, (const char *) &ret);
319                 break;
320
321         case EL_BIND:
322         case EL_TELLTC:
323         case EL_SETTC:
324         case EL_ECHOTC:
325         case EL_SETTY:
326         {
327                 char *argv[20];
328                 int i;
329
330                 for (i = 1; i < 20; i++)
331                         if ((argv[i] = va_arg(va, char *)) == NULL)
332                                 break;
333
334                 switch (op) {
335                 case EL_BIND:
336                         argv[0] = "bind";
337                         rv = map_bind(el, i, argv);
338                         break;
339
340                 case EL_TELLTC:
341                         argv[0] = "telltc";
342                         rv = term_telltc(el, i, argv);
343                         break;
344
345                 case EL_SETTC:
346                         argv[0] = "settc";
347                         rv = term_settc(el, i, argv);
348                         break;
349
350                 case EL_ECHOTC:
351                         argv[0] = "echotc";
352                         rv = term_echotc(el, i, argv);
353                         break;
354
355                 case EL_SETTY:
356                         argv[0] = "setty";
357                         rv = tty_stty(el, i, argv);
358                         break;
359
360                 default:
361                         rv = -1;
362                         EL_ABORT((el->errfile, "Bad op %d\n", op));
363                         break;
364                 }
365                 break;
366         }
367
368         case EL_ADDFN:
369         {
370                 char *name = va_arg(va, char *);
371                 char *help = va_arg(va, char *);
372                 el_func_t func = va_arg(va, el_func_t);
373
374                 rv = map_addfunc(el, name, help, func);
375                 break;
376         }
377
378         case EL_HIST:
379                 {
380                         hist_fun_t func = va_arg(va, hist_fun_t);
381                         ptr_t ptr = va_arg(va, char *);
382                         rv = hist_set(el, func, ptr);
383                 }
384                 break;
385 #endif /* XXX */
386
387         default:
388                 rv = -1;
389         }
390
391         return (rv);
392 }
393
394
395 /* el_line():
396  *      Return editing info
397  */
398 public const LineInfo *
399 el_line(EditLine *el)
400 {
401
402         return (const LineInfo *) (void *) &el->el_line;
403 }
404
405 static const char elpath[] = "/.editrc";
406
407 /* el_source():
408  *      Source a file
409  */
410 public int
411 el_source(EditLine *el, const char *fname)
412 {
413         FILE *fp;
414         size_t len;
415         char *ptr, path[MAXPATHLEN];
416
417         fp = NULL;
418         if (fname == NULL) {
419                 if (issetugid())
420                         return (-1);
421 #if _WIN32
422                 if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
423                         snprintf(path, sizeof(path), "%s%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"), elpath);
424                         fname = path;
425                 }
426 #else
427                 if ((ptr = getenv("HOME")) == NULL)
428                         return (-1);
429                 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
430                         return (-1);
431                 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
432                         return (-1);
433                 fname = path;
434 #endif
435         }
436         if (fname == NULL)
437                 return -1;
438         if (fp == NULL)
439                 fp = fopen(fname, "r");
440         if (fp == NULL) {
441                 return (-1);
442         }
443
444         while ((ptr = fgetln(fp, &len)) != NULL) {
445                 if (len > 0 && ptr[len - 1] == '\n')
446                         --len;
447                 ptr[len] = '\0';
448                 if (parse_line(el, ptr) == -1) {
449                         (void) fclose(fp);
450                         return (-1);
451                 }
452         }
453
454         (void) fclose(fp);
455         return (0);
456 }
457
458
459 /* el_resize():
460  *      Called from program when terminal is resized
461  */
462 public void
463 el_resize(EditLine *el)
464 {
465         int lins, cols;
466 #if !_MSC_VER
467         sigset_t oset, nset;
468
469         (void) sigemptyset(&nset);
470         (void) sigaddset(&nset, SIGWINCH);
471         (void) sigprocmask(SIG_BLOCK, &nset, &oset);
472 #endif
473
474         /* get the correct window size */
475         if (term_get_size(el, &lins, &cols))
476                 term_change_size(el, lins, cols);
477
478 #if !_MSC_VER
479         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
480 #endif
481 }
482
483
484 /* el_beep():
485  *      Called from the program to beep
486  */
487 public void
488 el_beep(EditLine *el)
489 {
490
491         term_beep(el);
492 }
493
494
495 /* el_editmode()
496  *      Set the state of EDIT_DISABLED from the `edit' command.
497  */
498 protected int
499 /*ARGSUSED*/
500 el_editmode(EditLine *el, int argc, char **argv)
501 {
502         const char *how;
503
504         if (argv == NULL || argc != 2 || argv[1] == NULL)
505                 return (-1);
506
507         how = argv[1];
508         if (strcmp(how, "on") == 0)
509                 el->el_flags &= ~EDIT_DISABLED;
510         else if (strcmp(how, "off") == 0)
511                 el->el_flags |= EDIT_DISABLED;
512         else {
513                 (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
514                 return (-1);
515         }
516         return (0);
517 }
Note: See TracBrowser for help on using the browser.