1*baff8195SBaptiste Daroussin /* $NetBSD: read.c,v 1.108 2022/10/30 19:11:31 christos Exp $ */
2d0ef721eSBaptiste Daroussin
3d0ef721eSBaptiste Daroussin /*-
4d0ef721eSBaptiste Daroussin * Copyright (c) 1992, 1993
5d0ef721eSBaptiste Daroussin * The Regents of the University of California. All rights reserved.
6d0ef721eSBaptiste Daroussin *
7d0ef721eSBaptiste Daroussin * This code is derived from software contributed to Berkeley by
8d0ef721eSBaptiste Daroussin * Christos Zoulas of Cornell University.
9d0ef721eSBaptiste Daroussin *
10d0ef721eSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
11d0ef721eSBaptiste Daroussin * modification, are permitted provided that the following conditions
12d0ef721eSBaptiste Daroussin * are met:
13d0ef721eSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright
14d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
15d0ef721eSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright
16d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
17d0ef721eSBaptiste Daroussin * documentation and/or other materials provided with the distribution.
18d0ef721eSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors
19d0ef721eSBaptiste Daroussin * may be used to endorse or promote products derived from this software
20d0ef721eSBaptiste Daroussin * without specific prior written permission.
21d0ef721eSBaptiste Daroussin *
22d0ef721eSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23d0ef721eSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24d0ef721eSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25d0ef721eSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26d0ef721eSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27d0ef721eSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28d0ef721eSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29d0ef721eSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30d0ef721eSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31d0ef721eSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32d0ef721eSBaptiste Daroussin * SUCH DAMAGE.
33d0ef721eSBaptiste Daroussin */
34d0ef721eSBaptiste Daroussin
35d0ef721eSBaptiste Daroussin #include "config.h"
36d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
37d0ef721eSBaptiste Daroussin #if 0
38d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
39d0ef721eSBaptiste Daroussin #else
40*baff8195SBaptiste Daroussin __RCSID("$NetBSD: read.c,v 1.108 2022/10/30 19:11:31 christos Exp $");
41d0ef721eSBaptiste Daroussin #endif
42d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
43d0ef721eSBaptiste Daroussin
44d0ef721eSBaptiste Daroussin /*
45d0ef721eSBaptiste Daroussin * read.c: Terminal read functions
46d0ef721eSBaptiste Daroussin */
47d0ef721eSBaptiste Daroussin #include <ctype.h>
48d0ef721eSBaptiste Daroussin #include <errno.h>
49d0ef721eSBaptiste Daroussin #include <fcntl.h>
50d0ef721eSBaptiste Daroussin #include <limits.h>
51d0ef721eSBaptiste Daroussin #include <stdlib.h>
52d0ef721eSBaptiste Daroussin #include <string.h>
53d0ef721eSBaptiste Daroussin #include <unistd.h>
54d0ef721eSBaptiste Daroussin
55d0ef721eSBaptiste Daroussin #include "el.h"
56d0ef721eSBaptiste Daroussin #include "fcns.h"
57d0ef721eSBaptiste Daroussin #include "read.h"
58d0ef721eSBaptiste Daroussin
59d0ef721eSBaptiste Daroussin #define EL_MAXMACRO 10
60d0ef721eSBaptiste Daroussin
61d0ef721eSBaptiste Daroussin struct macros {
62d0ef721eSBaptiste Daroussin wchar_t **macro;
63d0ef721eSBaptiste Daroussin int level;
64d0ef721eSBaptiste Daroussin int offset;
65d0ef721eSBaptiste Daroussin };
66d0ef721eSBaptiste Daroussin
67d0ef721eSBaptiste Daroussin struct el_read_t {
68d0ef721eSBaptiste Daroussin struct macros macros;
69d0ef721eSBaptiste Daroussin el_rfunc_t read_char; /* Function to read a character. */
70d0ef721eSBaptiste Daroussin int read_errno;
71d0ef721eSBaptiste Daroussin };
72d0ef721eSBaptiste Daroussin
73d0ef721eSBaptiste Daroussin static int read__fixio(int, int);
74d0ef721eSBaptiste Daroussin static int read_char(EditLine *, wchar_t *);
75d0ef721eSBaptiste Daroussin static int read_getcmd(EditLine *, el_action_t *, wchar_t *);
76d0ef721eSBaptiste Daroussin static void read_clearmacros(struct macros *);
77d0ef721eSBaptiste Daroussin static void read_pop(struct macros *);
78d0ef721eSBaptiste Daroussin static const wchar_t *noedit_wgets(EditLine *, int *);
79d0ef721eSBaptiste Daroussin
80d0ef721eSBaptiste Daroussin /* read_init():
81d0ef721eSBaptiste Daroussin * Initialize the read stuff
82d0ef721eSBaptiste Daroussin */
83d0ef721eSBaptiste Daroussin libedit_private int
read_init(EditLine * el)84d0ef721eSBaptiste Daroussin read_init(EditLine *el)
85d0ef721eSBaptiste Daroussin {
86d0ef721eSBaptiste Daroussin struct macros *ma;
87d0ef721eSBaptiste Daroussin
88d0ef721eSBaptiste Daroussin if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL)
89d0ef721eSBaptiste Daroussin return -1;
90d0ef721eSBaptiste Daroussin
91d0ef721eSBaptiste Daroussin ma = &el->el_read->macros;
92*baff8195SBaptiste Daroussin if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL)
93*baff8195SBaptiste Daroussin goto out;
94d0ef721eSBaptiste Daroussin ma->level = -1;
95d0ef721eSBaptiste Daroussin ma->offset = 0;
96d0ef721eSBaptiste Daroussin
97d0ef721eSBaptiste Daroussin /* builtin read_char */
98d0ef721eSBaptiste Daroussin el->el_read->read_char = read_char;
99d0ef721eSBaptiste Daroussin return 0;
100*baff8195SBaptiste Daroussin out:
101*baff8195SBaptiste Daroussin read_end(el);
102*baff8195SBaptiste Daroussin return -1;
103d0ef721eSBaptiste Daroussin }
104d0ef721eSBaptiste Daroussin
105d0ef721eSBaptiste Daroussin /* el_read_end():
106d0ef721eSBaptiste Daroussin * Free the data structures used by the read stuff.
107d0ef721eSBaptiste Daroussin */
108d0ef721eSBaptiste Daroussin libedit_private void
read_end(EditLine * el)109*baff8195SBaptiste Daroussin read_end(EditLine *el)
110d0ef721eSBaptiste Daroussin {
111*baff8195SBaptiste Daroussin
112*baff8195SBaptiste Daroussin read_clearmacros(&el->el_read->macros);
113*baff8195SBaptiste Daroussin el_free(el->el_read->macros.macro);
114*baff8195SBaptiste Daroussin el->el_read->macros.macro = NULL;
115*baff8195SBaptiste Daroussin el_free(el->el_read);
116*baff8195SBaptiste Daroussin el->el_read = NULL;
117d0ef721eSBaptiste Daroussin }
118d0ef721eSBaptiste Daroussin
119d0ef721eSBaptiste Daroussin /* el_read_setfn():
120d0ef721eSBaptiste Daroussin * Set the read char function to the one provided.
121d0ef721eSBaptiste Daroussin * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
122d0ef721eSBaptiste Daroussin */
123d0ef721eSBaptiste Daroussin libedit_private int
el_read_setfn(struct el_read_t * el_read,el_rfunc_t rc)124d0ef721eSBaptiste Daroussin el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc)
125d0ef721eSBaptiste Daroussin {
126d0ef721eSBaptiste Daroussin el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
127d0ef721eSBaptiste Daroussin return 0;
128d0ef721eSBaptiste Daroussin }
129d0ef721eSBaptiste Daroussin
130d0ef721eSBaptiste Daroussin
131d0ef721eSBaptiste Daroussin /* el_read_getfn():
132d0ef721eSBaptiste Daroussin * return the current read char function, or EL_BUILTIN_GETCFN
133d0ef721eSBaptiste Daroussin * if it is the default one
134d0ef721eSBaptiste Daroussin */
135d0ef721eSBaptiste Daroussin libedit_private el_rfunc_t
el_read_getfn(struct el_read_t * el_read)136d0ef721eSBaptiste Daroussin el_read_getfn(struct el_read_t *el_read)
137d0ef721eSBaptiste Daroussin {
138d0ef721eSBaptiste Daroussin return el_read->read_char == read_char ?
139d0ef721eSBaptiste Daroussin EL_BUILTIN_GETCFN : el_read->read_char;
140d0ef721eSBaptiste Daroussin }
141d0ef721eSBaptiste Daroussin
142d0ef721eSBaptiste Daroussin
143d0ef721eSBaptiste Daroussin /* read__fixio():
144d0ef721eSBaptiste Daroussin * Try to recover from a read error
145d0ef721eSBaptiste Daroussin */
146d0ef721eSBaptiste Daroussin /* ARGSUSED */
147d0ef721eSBaptiste Daroussin static int
read__fixio(int fd,int e)148d0ef721eSBaptiste Daroussin read__fixio(int fd __attribute__((__unused__)), int e)
149d0ef721eSBaptiste Daroussin {
150d0ef721eSBaptiste Daroussin
151d0ef721eSBaptiste Daroussin switch (e) {
152d0ef721eSBaptiste Daroussin case -1: /* Make sure that the code is reachable */
153d0ef721eSBaptiste Daroussin
154d0ef721eSBaptiste Daroussin #ifdef EWOULDBLOCK
155d0ef721eSBaptiste Daroussin case EWOULDBLOCK:
156d0ef721eSBaptiste Daroussin #ifndef TRY_AGAIN
157d0ef721eSBaptiste Daroussin #define TRY_AGAIN
158d0ef721eSBaptiste Daroussin #endif
159d0ef721eSBaptiste Daroussin #endif /* EWOULDBLOCK */
160d0ef721eSBaptiste Daroussin
161d0ef721eSBaptiste Daroussin #if defined(POSIX) && defined(EAGAIN)
162d0ef721eSBaptiste Daroussin #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
163d0ef721eSBaptiste Daroussin case EAGAIN:
164d0ef721eSBaptiste Daroussin #ifndef TRY_AGAIN
165d0ef721eSBaptiste Daroussin #define TRY_AGAIN
166d0ef721eSBaptiste Daroussin #endif
167d0ef721eSBaptiste Daroussin #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
168d0ef721eSBaptiste Daroussin #endif /* POSIX && EAGAIN */
169d0ef721eSBaptiste Daroussin
170d0ef721eSBaptiste Daroussin e = 0;
171d0ef721eSBaptiste Daroussin #ifdef TRY_AGAIN
172d0ef721eSBaptiste Daroussin #if defined(F_SETFL) && defined(O_NDELAY)
173d0ef721eSBaptiste Daroussin if ((e = fcntl(fd, F_GETFL, 0)) == -1)
174d0ef721eSBaptiste Daroussin return -1;
175d0ef721eSBaptiste Daroussin
176d0ef721eSBaptiste Daroussin if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
177d0ef721eSBaptiste Daroussin return -1;
178d0ef721eSBaptiste Daroussin else
179d0ef721eSBaptiste Daroussin e = 1;
180d0ef721eSBaptiste Daroussin #endif /* F_SETFL && O_NDELAY */
181d0ef721eSBaptiste Daroussin
182d0ef721eSBaptiste Daroussin #ifdef FIONBIO
183d0ef721eSBaptiste Daroussin {
184d0ef721eSBaptiste Daroussin int zero = 0;
185d0ef721eSBaptiste Daroussin
186d0ef721eSBaptiste Daroussin if (ioctl(fd, FIONBIO, &zero) == -1)
187d0ef721eSBaptiste Daroussin return -1;
188d0ef721eSBaptiste Daroussin else
189d0ef721eSBaptiste Daroussin e = 1;
190d0ef721eSBaptiste Daroussin }
191d0ef721eSBaptiste Daroussin #endif /* FIONBIO */
192d0ef721eSBaptiste Daroussin
193d0ef721eSBaptiste Daroussin #endif /* TRY_AGAIN */
194d0ef721eSBaptiste Daroussin return e ? 0 : -1;
195d0ef721eSBaptiste Daroussin
196d0ef721eSBaptiste Daroussin case EINTR:
197d0ef721eSBaptiste Daroussin return 0;
198d0ef721eSBaptiste Daroussin
199d0ef721eSBaptiste Daroussin default:
200d0ef721eSBaptiste Daroussin return -1;
201d0ef721eSBaptiste Daroussin }
202d0ef721eSBaptiste Daroussin }
203d0ef721eSBaptiste Daroussin
204d0ef721eSBaptiste Daroussin
205d0ef721eSBaptiste Daroussin /* el_push():
206d0ef721eSBaptiste Daroussin * Push a macro
207d0ef721eSBaptiste Daroussin */
208d0ef721eSBaptiste Daroussin void
el_wpush(EditLine * el,const wchar_t * str)209d0ef721eSBaptiste Daroussin el_wpush(EditLine *el, const wchar_t *str)
210d0ef721eSBaptiste Daroussin {
211d0ef721eSBaptiste Daroussin struct macros *ma = &el->el_read->macros;
212d0ef721eSBaptiste Daroussin
213d0ef721eSBaptiste Daroussin if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
214d0ef721eSBaptiste Daroussin ma->level++;
215d0ef721eSBaptiste Daroussin if ((ma->macro[ma->level] = wcsdup(str)) != NULL)
216d0ef721eSBaptiste Daroussin return;
217d0ef721eSBaptiste Daroussin ma->level--;
218d0ef721eSBaptiste Daroussin }
219d0ef721eSBaptiste Daroussin terminal_beep(el);
220d0ef721eSBaptiste Daroussin terminal__flush(el);
221d0ef721eSBaptiste Daroussin }
222d0ef721eSBaptiste Daroussin
223d0ef721eSBaptiste Daroussin
224d0ef721eSBaptiste Daroussin /* read_getcmd():
225d0ef721eSBaptiste Daroussin * Get next command from the input stream,
226d0ef721eSBaptiste Daroussin * return 0 on success or -1 on EOF or error.
227d0ef721eSBaptiste Daroussin * Character values > 255 are not looked up in the map, but inserted.
228d0ef721eSBaptiste Daroussin */
229d0ef721eSBaptiste Daroussin static int
read_getcmd(EditLine * el,el_action_t * cmdnum,wchar_t * ch)230d0ef721eSBaptiste Daroussin read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch)
231d0ef721eSBaptiste Daroussin {
232d0ef721eSBaptiste Daroussin static const wchar_t meta = (wchar_t)0x80;
233d0ef721eSBaptiste Daroussin el_action_t cmd;
234d0ef721eSBaptiste Daroussin
235d0ef721eSBaptiste Daroussin do {
236d0ef721eSBaptiste Daroussin if (el_wgetc(el, ch) != 1)
237d0ef721eSBaptiste Daroussin return -1;
238d0ef721eSBaptiste Daroussin
239d0ef721eSBaptiste Daroussin #ifdef KANJI
240d0ef721eSBaptiste Daroussin if ((*ch & meta)) {
241d0ef721eSBaptiste Daroussin el->el_state.metanext = 0;
242d0ef721eSBaptiste Daroussin cmd = CcViMap[' '];
243d0ef721eSBaptiste Daroussin break;
244d0ef721eSBaptiste Daroussin } else
245d0ef721eSBaptiste Daroussin #endif /* KANJI */
246d0ef721eSBaptiste Daroussin
247d0ef721eSBaptiste Daroussin if (el->el_state.metanext) {
248d0ef721eSBaptiste Daroussin el->el_state.metanext = 0;
249d0ef721eSBaptiste Daroussin *ch |= meta;
250d0ef721eSBaptiste Daroussin }
251d0ef721eSBaptiste Daroussin if (*ch >= N_KEYS)
252d0ef721eSBaptiste Daroussin cmd = ED_INSERT;
253d0ef721eSBaptiste Daroussin else
254d0ef721eSBaptiste Daroussin cmd = el->el_map.current[(unsigned char) *ch];
255d0ef721eSBaptiste Daroussin if (cmd == ED_SEQUENCE_LEAD_IN) {
256d0ef721eSBaptiste Daroussin keymacro_value_t val;
257d0ef721eSBaptiste Daroussin switch (keymacro_get(el, ch, &val)) {
258d0ef721eSBaptiste Daroussin case XK_CMD:
259d0ef721eSBaptiste Daroussin cmd = val.cmd;
260d0ef721eSBaptiste Daroussin break;
261d0ef721eSBaptiste Daroussin case XK_STR:
262d0ef721eSBaptiste Daroussin el_wpush(el, val.str);
263d0ef721eSBaptiste Daroussin break;
264d0ef721eSBaptiste Daroussin case XK_NOD:
265d0ef721eSBaptiste Daroussin return -1;
266d0ef721eSBaptiste Daroussin default:
267d0ef721eSBaptiste Daroussin EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
268d0ef721eSBaptiste Daroussin break;
269d0ef721eSBaptiste Daroussin }
270d0ef721eSBaptiste Daroussin }
271d0ef721eSBaptiste Daroussin } while (cmd == ED_SEQUENCE_LEAD_IN);
272d0ef721eSBaptiste Daroussin *cmdnum = cmd;
273d0ef721eSBaptiste Daroussin return 0;
274d0ef721eSBaptiste Daroussin }
275d0ef721eSBaptiste Daroussin
276d0ef721eSBaptiste Daroussin /* read_char():
277d0ef721eSBaptiste Daroussin * Read a character from the tty.
278d0ef721eSBaptiste Daroussin */
279d0ef721eSBaptiste Daroussin static int
read_char(EditLine * el,wchar_t * cp)280d0ef721eSBaptiste Daroussin read_char(EditLine *el, wchar_t *cp)
281d0ef721eSBaptiste Daroussin {
282d0ef721eSBaptiste Daroussin ssize_t num_read;
28391f76417SBaptiste Daroussin int tried = (el->el_flags & FIXIO) == 0;
284d0ef721eSBaptiste Daroussin char cbuf[MB_LEN_MAX];
285d0ef721eSBaptiste Daroussin size_t cbp = 0;
286d0ef721eSBaptiste Daroussin int save_errno = errno;
287d0ef721eSBaptiste Daroussin
288d0ef721eSBaptiste Daroussin again:
289d0ef721eSBaptiste Daroussin el->el_signal->sig_no = 0;
290d0ef721eSBaptiste Daroussin while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) {
291d0ef721eSBaptiste Daroussin int e = errno;
292d0ef721eSBaptiste Daroussin switch (el->el_signal->sig_no) {
293d0ef721eSBaptiste Daroussin case SIGCONT:
294d0ef721eSBaptiste Daroussin el_wset(el, EL_REFRESH);
295d0ef721eSBaptiste Daroussin /*FALLTHROUGH*/
296d0ef721eSBaptiste Daroussin case SIGWINCH:
297d0ef721eSBaptiste Daroussin sig_set(el);
298d0ef721eSBaptiste Daroussin goto again;
299d0ef721eSBaptiste Daroussin default:
300d0ef721eSBaptiste Daroussin break;
301d0ef721eSBaptiste Daroussin }
302d0ef721eSBaptiste Daroussin if (!tried && read__fixio(el->el_infd, e) == 0) {
303d0ef721eSBaptiste Daroussin errno = save_errno;
304d0ef721eSBaptiste Daroussin tried = 1;
305d0ef721eSBaptiste Daroussin } else {
306d0ef721eSBaptiste Daroussin errno = e;
307d0ef721eSBaptiste Daroussin *cp = L'\0';
308d0ef721eSBaptiste Daroussin return -1;
309d0ef721eSBaptiste Daroussin }
310d0ef721eSBaptiste Daroussin }
311d0ef721eSBaptiste Daroussin
312d0ef721eSBaptiste Daroussin /* Test for EOF */
313d0ef721eSBaptiste Daroussin if (num_read == 0) {
314d0ef721eSBaptiste Daroussin *cp = L'\0';
315d0ef721eSBaptiste Daroussin return 0;
316d0ef721eSBaptiste Daroussin }
317d0ef721eSBaptiste Daroussin
318d0ef721eSBaptiste Daroussin for (;;) {
319d0ef721eSBaptiste Daroussin mbstate_t mbs;
320d0ef721eSBaptiste Daroussin
321d0ef721eSBaptiste Daroussin ++cbp;
322d0ef721eSBaptiste Daroussin /* This only works because UTF8 is stateless. */
323d0ef721eSBaptiste Daroussin memset(&mbs, 0, sizeof(mbs));
324d0ef721eSBaptiste Daroussin switch (mbrtowc(cp, cbuf, cbp, &mbs)) {
325d0ef721eSBaptiste Daroussin case (size_t)-1:
326d0ef721eSBaptiste Daroussin if (cbp > 1) {
327d0ef721eSBaptiste Daroussin /*
328d0ef721eSBaptiste Daroussin * Invalid sequence, discard all bytes
329d0ef721eSBaptiste Daroussin * except the last one.
330d0ef721eSBaptiste Daroussin */
331d0ef721eSBaptiste Daroussin cbuf[0] = cbuf[cbp - 1];
332d0ef721eSBaptiste Daroussin cbp = 0;
333d0ef721eSBaptiste Daroussin break;
334d0ef721eSBaptiste Daroussin } else {
335d0ef721eSBaptiste Daroussin /* Invalid byte, discard it. */
336d0ef721eSBaptiste Daroussin cbp = 0;
337d0ef721eSBaptiste Daroussin goto again;
338d0ef721eSBaptiste Daroussin }
339d0ef721eSBaptiste Daroussin case (size_t)-2:
340d0ef721eSBaptiste Daroussin if (cbp >= MB_LEN_MAX) {
341d0ef721eSBaptiste Daroussin errno = EILSEQ;
342d0ef721eSBaptiste Daroussin *cp = L'\0';
343d0ef721eSBaptiste Daroussin return -1;
344d0ef721eSBaptiste Daroussin }
345d0ef721eSBaptiste Daroussin /* Incomplete sequence, read another byte. */
346d0ef721eSBaptiste Daroussin goto again;
347d0ef721eSBaptiste Daroussin default:
348d0ef721eSBaptiste Daroussin /* Valid character, process it. */
349d0ef721eSBaptiste Daroussin return 1;
350d0ef721eSBaptiste Daroussin }
351d0ef721eSBaptiste Daroussin }
352d0ef721eSBaptiste Daroussin }
353d0ef721eSBaptiste Daroussin
354d0ef721eSBaptiste Daroussin /* read_pop():
355d0ef721eSBaptiste Daroussin * Pop a macro from the stack
356d0ef721eSBaptiste Daroussin */
357d0ef721eSBaptiste Daroussin static void
read_pop(struct macros * ma)358d0ef721eSBaptiste Daroussin read_pop(struct macros *ma)
359d0ef721eSBaptiste Daroussin {
360d0ef721eSBaptiste Daroussin int i;
361d0ef721eSBaptiste Daroussin
362d0ef721eSBaptiste Daroussin el_free(ma->macro[0]);
363d0ef721eSBaptiste Daroussin for (i = 0; i < ma->level; i++)
364d0ef721eSBaptiste Daroussin ma->macro[i] = ma->macro[i + 1];
365d0ef721eSBaptiste Daroussin ma->level--;
366d0ef721eSBaptiste Daroussin ma->offset = 0;
367d0ef721eSBaptiste Daroussin }
368d0ef721eSBaptiste Daroussin
369d0ef721eSBaptiste Daroussin static void
read_clearmacros(struct macros * ma)370d0ef721eSBaptiste Daroussin read_clearmacros(struct macros *ma)
371d0ef721eSBaptiste Daroussin {
372d0ef721eSBaptiste Daroussin while (ma->level >= 0)
373d0ef721eSBaptiste Daroussin el_free(ma->macro[ma->level--]);
374d0ef721eSBaptiste Daroussin ma->offset = 0;
375d0ef721eSBaptiste Daroussin }
376d0ef721eSBaptiste Daroussin
377d0ef721eSBaptiste Daroussin /* el_wgetc():
378d0ef721eSBaptiste Daroussin * Read a wide character
379d0ef721eSBaptiste Daroussin */
380d0ef721eSBaptiste Daroussin int
el_wgetc(EditLine * el,wchar_t * cp)381d0ef721eSBaptiste Daroussin el_wgetc(EditLine *el, wchar_t *cp)
382d0ef721eSBaptiste Daroussin {
383d0ef721eSBaptiste Daroussin struct macros *ma = &el->el_read->macros;
384d0ef721eSBaptiste Daroussin int num_read;
385d0ef721eSBaptiste Daroussin
386d0ef721eSBaptiste Daroussin terminal__flush(el);
387d0ef721eSBaptiste Daroussin for (;;) {
388d0ef721eSBaptiste Daroussin if (ma->level < 0)
389d0ef721eSBaptiste Daroussin break;
390d0ef721eSBaptiste Daroussin
391d0ef721eSBaptiste Daroussin if (ma->macro[0][ma->offset] == '\0') {
392d0ef721eSBaptiste Daroussin read_pop(ma);
393d0ef721eSBaptiste Daroussin continue;
394d0ef721eSBaptiste Daroussin }
395d0ef721eSBaptiste Daroussin
396d0ef721eSBaptiste Daroussin *cp = ma->macro[0][ma->offset++];
397d0ef721eSBaptiste Daroussin
398d0ef721eSBaptiste Daroussin if (ma->macro[0][ma->offset] == '\0') {
399d0ef721eSBaptiste Daroussin /* Needed for QuoteMode On */
400d0ef721eSBaptiste Daroussin read_pop(ma);
401d0ef721eSBaptiste Daroussin }
402d0ef721eSBaptiste Daroussin
403d0ef721eSBaptiste Daroussin return 1;
404d0ef721eSBaptiste Daroussin }
405d0ef721eSBaptiste Daroussin
406d0ef721eSBaptiste Daroussin if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
407d0ef721eSBaptiste Daroussin return 0;
408d0ef721eSBaptiste Daroussin
409d0ef721eSBaptiste Daroussin num_read = (*el->el_read->read_char)(el, cp);
410d0ef721eSBaptiste Daroussin
411d0ef721eSBaptiste Daroussin /*
412d0ef721eSBaptiste Daroussin * Remember the original reason of a read failure
413d0ef721eSBaptiste Daroussin * such that el_wgets() can restore it after doing
414d0ef721eSBaptiste Daroussin * various cleanup operation that might change errno.
415d0ef721eSBaptiste Daroussin */
416d0ef721eSBaptiste Daroussin if (num_read < 0)
417d0ef721eSBaptiste Daroussin el->el_read->read_errno = errno;
418d0ef721eSBaptiste Daroussin
419d0ef721eSBaptiste Daroussin return num_read;
420d0ef721eSBaptiste Daroussin }
421d0ef721eSBaptiste Daroussin
422d0ef721eSBaptiste Daroussin libedit_private void
read_prepare(EditLine * el)423d0ef721eSBaptiste Daroussin read_prepare(EditLine *el)
424d0ef721eSBaptiste Daroussin {
425d0ef721eSBaptiste Daroussin if (el->el_flags & HANDLE_SIGNALS)
426d0ef721eSBaptiste Daroussin sig_set(el);
427d0ef721eSBaptiste Daroussin if (el->el_flags & NO_TTY)
428d0ef721eSBaptiste Daroussin return;
429d0ef721eSBaptiste Daroussin if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
430d0ef721eSBaptiste Daroussin tty_rawmode(el);
431d0ef721eSBaptiste Daroussin
432d0ef721eSBaptiste Daroussin /* This is relatively cheap, and things go terribly wrong if
433d0ef721eSBaptiste Daroussin we have the wrong size. */
434d0ef721eSBaptiste Daroussin el_resize(el);
435d0ef721eSBaptiste Daroussin re_clear_display(el); /* reset the display stuff */
436d0ef721eSBaptiste Daroussin ch_reset(el);
437d0ef721eSBaptiste Daroussin re_refresh(el); /* print the prompt */
438d0ef721eSBaptiste Daroussin
439d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED)
440d0ef721eSBaptiste Daroussin terminal__flush(el);
441d0ef721eSBaptiste Daroussin }
442d0ef721eSBaptiste Daroussin
443d0ef721eSBaptiste Daroussin libedit_private void
read_finish(EditLine * el)444d0ef721eSBaptiste Daroussin read_finish(EditLine *el)
445d0ef721eSBaptiste Daroussin {
446d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0)
447d0ef721eSBaptiste Daroussin (void) tty_cookedmode(el);
448d0ef721eSBaptiste Daroussin if (el->el_flags & HANDLE_SIGNALS)
449d0ef721eSBaptiste Daroussin sig_clr(el);
450d0ef721eSBaptiste Daroussin }
451d0ef721eSBaptiste Daroussin
452d0ef721eSBaptiste Daroussin static const wchar_t *
noedit_wgets(EditLine * el,int * nread)453d0ef721eSBaptiste Daroussin noedit_wgets(EditLine *el, int *nread)
454d0ef721eSBaptiste Daroussin {
455d0ef721eSBaptiste Daroussin el_line_t *lp = &el->el_line;
456d0ef721eSBaptiste Daroussin int num;
457d0ef721eSBaptiste Daroussin
458d0ef721eSBaptiste Daroussin while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) {
459d0ef721eSBaptiste Daroussin if (lp->lastchar + 1 >= lp->limit &&
460d0ef721eSBaptiste Daroussin !ch_enlargebufs(el, (size_t)2))
461d0ef721eSBaptiste Daroussin break;
462d0ef721eSBaptiste Daroussin lp->lastchar++;
463d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED ||
464d0ef721eSBaptiste Daroussin lp->lastchar[-1] == '\r' ||
465d0ef721eSBaptiste Daroussin lp->lastchar[-1] == '\n')
466d0ef721eSBaptiste Daroussin break;
467d0ef721eSBaptiste Daroussin }
468d0ef721eSBaptiste Daroussin if (num == -1 && errno == EINTR)
469d0ef721eSBaptiste Daroussin lp->lastchar = lp->buffer;
470d0ef721eSBaptiste Daroussin lp->cursor = lp->lastchar;
471d0ef721eSBaptiste Daroussin *lp->lastchar = '\0';
472d0ef721eSBaptiste Daroussin *nread = (int)(lp->lastchar - lp->buffer);
473d0ef721eSBaptiste Daroussin return *nread ? lp->buffer : NULL;
474d0ef721eSBaptiste Daroussin }
475d0ef721eSBaptiste Daroussin
476d0ef721eSBaptiste Daroussin const wchar_t *
el_wgets(EditLine * el,int * nread)477d0ef721eSBaptiste Daroussin el_wgets(EditLine *el, int *nread)
478d0ef721eSBaptiste Daroussin {
479d0ef721eSBaptiste Daroussin int retval;
480d0ef721eSBaptiste Daroussin el_action_t cmdnum = 0;
481d0ef721eSBaptiste Daroussin int num; /* how many chars we have read at NL */
482d0ef721eSBaptiste Daroussin wchar_t ch;
483d0ef721eSBaptiste Daroussin int nrb;
484d0ef721eSBaptiste Daroussin
485d0ef721eSBaptiste Daroussin if (nread == NULL)
486d0ef721eSBaptiste Daroussin nread = &nrb;
487d0ef721eSBaptiste Daroussin *nread = 0;
488d0ef721eSBaptiste Daroussin el->el_read->read_errno = 0;
489d0ef721eSBaptiste Daroussin
490d0ef721eSBaptiste Daroussin if (el->el_flags & NO_TTY) {
491d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer;
492d0ef721eSBaptiste Daroussin return noedit_wgets(el, nread);
493d0ef721eSBaptiste Daroussin }
494d0ef721eSBaptiste Daroussin
495d0ef721eSBaptiste Daroussin #ifdef FIONREAD
496d0ef721eSBaptiste Daroussin if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) {
497d0ef721eSBaptiste Daroussin int chrs = 0;
498d0ef721eSBaptiste Daroussin
499d0ef721eSBaptiste Daroussin (void) ioctl(el->el_infd, FIONREAD, &chrs);
500d0ef721eSBaptiste Daroussin if (chrs == 0) {
501d0ef721eSBaptiste Daroussin if (tty_rawmode(el) < 0) {
502d0ef721eSBaptiste Daroussin errno = 0;
503d0ef721eSBaptiste Daroussin *nread = 0;
504d0ef721eSBaptiste Daroussin return NULL;
505d0ef721eSBaptiste Daroussin }
506d0ef721eSBaptiste Daroussin }
507d0ef721eSBaptiste Daroussin }
508d0ef721eSBaptiste Daroussin #endif /* FIONREAD */
509d0ef721eSBaptiste Daroussin
510d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0)
511d0ef721eSBaptiste Daroussin read_prepare(el);
512d0ef721eSBaptiste Daroussin
513d0ef721eSBaptiste Daroussin if (el->el_flags & EDIT_DISABLED) {
514d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0)
515d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer;
516d0ef721eSBaptiste Daroussin terminal__flush(el);
517d0ef721eSBaptiste Daroussin return noedit_wgets(el, nread);
518d0ef721eSBaptiste Daroussin }
519d0ef721eSBaptiste Daroussin
520d0ef721eSBaptiste Daroussin for (num = -1; num == -1;) { /* while still editing this line */
521d0ef721eSBaptiste Daroussin /* if EOF or error */
522d0ef721eSBaptiste Daroussin if (read_getcmd(el, &cmdnum, &ch) == -1)
523d0ef721eSBaptiste Daroussin break;
524d0ef721eSBaptiste Daroussin if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */
525d0ef721eSBaptiste Daroussin continue; /* try again */
526d0ef721eSBaptiste Daroussin /* now do the real command */
527d0ef721eSBaptiste Daroussin /* vi redo needs these way down the levels... */
528d0ef721eSBaptiste Daroussin el->el_state.thiscmd = cmdnum;
529d0ef721eSBaptiste Daroussin el->el_state.thisch = ch;
530d0ef721eSBaptiste Daroussin if (el->el_map.type == MAP_VI &&
531d0ef721eSBaptiste Daroussin el->el_map.current == el->el_map.key &&
532d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
533d0ef721eSBaptiste Daroussin if (cmdnum == VI_DELETE_PREV_CHAR &&
534d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
535d0ef721eSBaptiste Daroussin && iswprint(el->el_chared.c_redo.pos[-1]))
536d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos--;
537d0ef721eSBaptiste Daroussin else
538d0ef721eSBaptiste Daroussin *el->el_chared.c_redo.pos++ = ch;
539d0ef721eSBaptiste Daroussin }
540d0ef721eSBaptiste Daroussin retval = (*el->el_map.func[cmdnum]) (el, ch);
541d0ef721eSBaptiste Daroussin
542d0ef721eSBaptiste Daroussin /* save the last command here */
543d0ef721eSBaptiste Daroussin el->el_state.lastcmd = cmdnum;
544d0ef721eSBaptiste Daroussin
545d0ef721eSBaptiste Daroussin /* use any return value */
546d0ef721eSBaptiste Daroussin switch (retval) {
547d0ef721eSBaptiste Daroussin case CC_CURSOR:
548d0ef721eSBaptiste Daroussin re_refresh_cursor(el);
549d0ef721eSBaptiste Daroussin break;
550d0ef721eSBaptiste Daroussin
551d0ef721eSBaptiste Daroussin case CC_REDISPLAY:
552d0ef721eSBaptiste Daroussin re_clear_lines(el);
553d0ef721eSBaptiste Daroussin re_clear_display(el);
554d0ef721eSBaptiste Daroussin /* FALLTHROUGH */
555d0ef721eSBaptiste Daroussin
556d0ef721eSBaptiste Daroussin case CC_REFRESH:
557d0ef721eSBaptiste Daroussin re_refresh(el);
558d0ef721eSBaptiste Daroussin break;
559d0ef721eSBaptiste Daroussin
560d0ef721eSBaptiste Daroussin case CC_REFRESH_BEEP:
561d0ef721eSBaptiste Daroussin re_refresh(el);
562d0ef721eSBaptiste Daroussin terminal_beep(el);
563d0ef721eSBaptiste Daroussin break;
564d0ef721eSBaptiste Daroussin
565d0ef721eSBaptiste Daroussin case CC_NORM: /* normal char */
566d0ef721eSBaptiste Daroussin break;
567d0ef721eSBaptiste Daroussin
568d0ef721eSBaptiste Daroussin case CC_ARGHACK: /* Suggested by Rich Salz */
569d0ef721eSBaptiste Daroussin /* <rsalz@pineapple.bbn.com> */
570d0ef721eSBaptiste Daroussin continue; /* keep going... */
571d0ef721eSBaptiste Daroussin
572d0ef721eSBaptiste Daroussin case CC_EOF: /* end of file typed */
573d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0)
574d0ef721eSBaptiste Daroussin num = 0;
575d0ef721eSBaptiste Daroussin else if (num == -1) {
576d0ef721eSBaptiste Daroussin *el->el_line.lastchar++ = CONTROL('d');
577d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar;
578d0ef721eSBaptiste Daroussin num = 1;
579d0ef721eSBaptiste Daroussin }
580d0ef721eSBaptiste Daroussin break;
581d0ef721eSBaptiste Daroussin
582d0ef721eSBaptiste Daroussin case CC_NEWLINE: /* normal end of line */
583d0ef721eSBaptiste Daroussin num = (int)(el->el_line.lastchar - el->el_line.buffer);
584d0ef721eSBaptiste Daroussin break;
585d0ef721eSBaptiste Daroussin
586d0ef721eSBaptiste Daroussin case CC_FATAL: /* fatal error, reset to known state */
587d0ef721eSBaptiste Daroussin /* put (real) cursor in a known place */
588d0ef721eSBaptiste Daroussin re_clear_display(el); /* reset the display stuff */
589d0ef721eSBaptiste Daroussin ch_reset(el); /* reset the input pointers */
590d0ef721eSBaptiste Daroussin read_clearmacros(&el->el_read->macros);
591d0ef721eSBaptiste Daroussin re_refresh(el); /* print the prompt again */
592d0ef721eSBaptiste Daroussin break;
593d0ef721eSBaptiste Daroussin
594d0ef721eSBaptiste Daroussin case CC_ERROR:
595d0ef721eSBaptiste Daroussin default: /* functions we don't know about */
596d0ef721eSBaptiste Daroussin terminal_beep(el);
597d0ef721eSBaptiste Daroussin terminal__flush(el);
598d0ef721eSBaptiste Daroussin break;
599d0ef721eSBaptiste Daroussin }
600d0ef721eSBaptiste Daroussin el->el_state.argument = 1;
601d0ef721eSBaptiste Daroussin el->el_state.doingarg = 0;
602d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP;
603d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED)
604d0ef721eSBaptiste Daroussin break;
605d0ef721eSBaptiste Daroussin }
606d0ef721eSBaptiste Daroussin
607d0ef721eSBaptiste Daroussin terminal__flush(el); /* flush any buffered output */
608d0ef721eSBaptiste Daroussin /* make sure the tty is set up correctly */
609d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) {
610d0ef721eSBaptiste Daroussin read_finish(el);
611d0ef721eSBaptiste Daroussin *nread = num != -1 ? num : 0;
612d0ef721eSBaptiste Daroussin } else
613d0ef721eSBaptiste Daroussin *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
614d0ef721eSBaptiste Daroussin
615d0ef721eSBaptiste Daroussin if (*nread == 0) {
616d0ef721eSBaptiste Daroussin if (num == -1) {
617d0ef721eSBaptiste Daroussin *nread = -1;
618d0ef721eSBaptiste Daroussin if (el->el_read->read_errno)
619d0ef721eSBaptiste Daroussin errno = el->el_read->read_errno;
620d0ef721eSBaptiste Daroussin }
621d0ef721eSBaptiste Daroussin return NULL;
622d0ef721eSBaptiste Daroussin } else
623d0ef721eSBaptiste Daroussin return el->el_line.buffer;
624d0ef721eSBaptiste Daroussin }
625