Remove building with NOCRYPTO option
[minix3.git] / external / bsd / nvi / dist / ip / ip_read.c
blobb121fc87acc8c3196c594b0169d7edb0760523d2
1 /* $NetBSD: ip_read.c,v 1.7 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3 * Copyright (c) 1996
4 * Keith Bostic. All rights reserved.
6 * See the LICENSE file for redistribution information.
7 */
9 #include "config.h"
11 #include <sys/cdefs.h>
12 #if 0
13 #ifndef lint
14 static const char sccsid[] = "Id: ip_read.c,v 8.23 2001/06/25 15:19:24 skimo Exp (Berkeley) Date: 2001/06/25 15:19:24 ";
15 #endif /* not lint */
16 #else
17 __RCSID("$NetBSD: ip_read.c,v 1.7 2014/01/26 21:43:45 christos Exp $");
18 #endif
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
24 #include <bitstring.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <termios.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <netinet/in.h>
33 #include "../common/common.h"
34 #include "../ex/script.h"
35 #include "../ipc/ip.h"
37 extern GS *__global_list;
39 VIPFUNLIST const vipfuns[] = {
40 /* VI_C_BOL 1 Cursor to start of line. */
41 {"", E_IPCOMMAND},
42 /* VI_C_BOTTOM 2 Cursor to bottom. */
43 {"", E_IPCOMMAND},
44 /* VI_C_DEL 3 Cursor delete. */
45 {"", E_IPCOMMAND},
46 /* VI_C_DOWN 4 Cursor down N lines: IPO_INT. */
47 {"1", E_IPCOMMAND},
48 /* VI_C_EOL 5 Cursor to end of line. */
49 {"", E_IPCOMMAND},
50 /* VI_C_INSERT 6 Cursor: enter insert mode. */
51 {"", E_IPCOMMAND},
52 /* VI_C_LEFT 7 Cursor left. */
53 {"", E_IPCOMMAND},
54 /* VI_C_PGDOWN 8 Cursor down N pages: IPO_INT. */
55 {"1", E_IPCOMMAND},
56 /* VI_C_PGUP 9 Cursor up N lines: IPO_INT. */
57 {"1", E_IPCOMMAND},
58 /* VI_C_RIGHT 10 Cursor right. */
59 {"", E_IPCOMMAND},
60 /* VI_C_SEARCH 11 Cursor: search: IPO_INT, IPO_STR. */
61 {"a1", E_IPCOMMAND},
62 /* VI_C_SETTOP 12 Cursor: set screen top line: IPO_INT. */
63 {"1", E_IPCOMMAND},
64 /* VI_C_TOP 13 Cursor to top. */
65 {"", E_IPCOMMAND},
66 /* VI_C_UP 14 Cursor up N lines: IPO_INT. */
67 {"1", E_IPCOMMAND},
68 /* VI_EDIT 15 Edit a file: IPO_STR. */
69 {"a", E_IPCOMMAND},
70 /* VI_EDITOPT 16 Edit option: 2 * IPO_STR, IPO_INT. */
71 {"ab1", E_IPCOMMAND},
72 /* VI_EDITSPLIT 17 Split to a file: IPO_STR. */
73 {"a", E_IPCOMMAND},
74 /* VI_EOF 18 End of input (NOT ^D). */
75 {"", E_EOF},
76 /* VI_ERR 19 Input error. */
77 {"", E_ERR},
78 /* VI_FLAGS 20 Flags */
79 {"1", E_FLAGS},
80 /* VI_INTERRUPT 21 Interrupt. */
81 {"", E_INTERRUPT},
82 /* VI_MOUSE_MOVE 22 Mouse click move: IPO_INT, IPO_INT. */
83 {"12", E_IPCOMMAND},
84 /* VI_QUIT 23 Quit. */
85 {"", E_IPCOMMAND},
86 /* VI_RESIZE 24 Screen resize: IPO_INT, IPO_INT. */
87 {"12", E_WRESIZE},
88 /* VI_SEL_END 25 Select end: IPO_INT, IPO_INT. */
89 {"12", E_IPCOMMAND},
90 /* VI_SEL_START 26 Select start: IPO_INT, IPO_INT. */
91 {"12", E_IPCOMMAND},
92 /* VI_SIGHUP 27 SIGHUP. */
93 {"", E_SIGHUP},
94 /* VI_SIGTERM 28 SIGTERM. */
95 {"", E_SIGTERM},
96 /* VI_STRING 29 Input string: IPO_STR. */
97 {"a", E_STRING},
98 /* VI_TAG 30 Tag. */
99 {"", E_IPCOMMAND},
100 /* VI_TAGAS 31 Tag to a string: IPO_STR. */
101 {"a", E_IPCOMMAND},
102 /* VI_TAGSPLIT 32 Split to a tag. */
103 {"", E_IPCOMMAND},
104 /* VI_UNDO 33 Undo. */
105 {"", E_IPCOMMAND},
106 /* VI_WQ 34 Write and quit. */
107 {"", E_IPCOMMAND},
108 /* VI_WRITE 35 Write. */
109 {"", E_IPCOMMAND},
110 /* VI_WRITEAS 36 Write as another file: IPO_STR. */
111 {"a", E_IPCOMMAND},
112 /* VI_EVENT_SUP 37 */
115 typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
117 static input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *, int, int*));
118 static int ip_resize __P((SCR *, u_int32_t, u_int32_t));
119 static int ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
122 * ip_event --
123 * Return a single event.
125 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
128 ip_event(SCR *sp, EVENT *evp, u_int32_t flags, int ms)
130 return ip_wevent(sp->wp, sp, evp, flags, ms);
134 * XXX probably better to require new_window to send size
135 * so we never have to call ip_wevent with sp == NULL
137 * ip_wevent --
138 * Return a single event.
140 * PUBLIC: int ip_wevent __P((WIN *, SCR *, EVENT *, u_int32_t, int));
143 ip_wevent(WIN *wp, SCR *sp, EVENT *evp, u_int32_t flags, int ms)
145 IP_PRIVATE *ipp;
146 struct timeval t, *tp;
147 int termread;
148 int nr = 0;
150 if (LF_ISSET(EC_INTERRUPT)) { /* XXX */
151 evp->e_event = E_TIMEOUT;
152 return (0);
155 ipp = sp == NULL ? WIPP(wp) : IPP(sp);
157 /* Discard the last command. */
158 if (ipp->iskip != 0) {
159 ipp->iblen -= ipp->iskip;
160 memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen);
161 ipp->iskip = 0;
164 termread = F_ISSET(ipp, IP_IN_EX) ||
165 (sp && F_ISSET(sp, SC_SCR_EXWROTE));
167 /* Process possible remaining commands */
168 if (!termread && ipp->iblen >= IPO_CODE_LEN && ip_trans(sp, ipp, evp))
169 return 0;
171 /* Set timer. */
172 if (ms == 0)
173 tp = NULL;
174 else {
175 t.tv_sec = ms / 1000;
176 t.tv_usec = (ms % 1000) * 1000;
177 tp = &t;
180 /* Read input events. */
181 for (;;) {
182 switch (ip_read(sp, ipp, tp, termread, &nr)) {
183 case INP_OK:
184 if (termread) {
185 evp->e_csp = ipp->tbuf;
186 evp->e_len = nr;
187 evp->e_event = E_STRING;
188 } else if (!ip_trans(sp, ipp, evp))
189 continue;
190 break;
191 case INP_EOF:
192 evp->e_event = E_EOF;
193 break;
194 case INP_ERR:
195 evp->e_event = E_ERR;
196 break;
197 case INP_TIMEOUT:
198 evp->e_event = E_TIMEOUT;
199 break;
200 default:
201 abort();
203 break;
205 return (0);
209 * ip_read --
210 * Read characters from the input.
212 static input_t
213 ip_read(SCR *sp, IP_PRIVATE *ipp, struct timeval *tp, int termread, int *nr)
215 GS *gp;
216 fd_set rdfd;
217 input_t rval;
218 size_t blen;
219 int maxfd;
220 char *bp;
221 int fd;
222 const CHAR_T *wp;
223 size_t wlen;
225 gp = sp == NULL ? __global_list : sp->gp;
226 bp = ipp->ibuf + ipp->iblen;
227 blen = sizeof(ipp->ibuf) - ipp->iblen;
228 fd = termread ? ipp->t_fd : ipp->i_fd;
231 * 1: A read with an associated timeout, e.g., trying to complete
232 * a map sequence. If input exists, we fall into #2.
234 FD_ZERO(&rdfd);
235 if (tp != NULL) {
236 FD_SET(fd, &rdfd);
237 switch (select(fd + 1, &rdfd, NULL, NULL, tp)) {
238 case 0:
239 return (INP_TIMEOUT);
240 case -1:
241 goto err;
242 default:
243 break;
248 * 2: Wait for input.
250 * Select on the command input and scripting window file descriptors.
251 * It's ugly that we wait on scripting file descriptors here, but it's
252 * the only way to keep from locking out scripting windows.
254 if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
255 FD_ZERO(&rdfd);
256 FD_SET(fd, &rdfd);
257 maxfd = fd;
258 if (sscr_check_input(sp, &rdfd, maxfd))
259 goto err;
263 * 3: Read the input.
265 switch (*nr = read(fd, termread ? (char *)ipp->tbuf : bp,
266 termread ? sizeof(ipp->tbuf)/sizeof(CHAR_T)
267 : blen)) {
268 case 0: /* EOF. */
269 rval = INP_EOF;
270 break;
271 case -1: /* Error or interrupt. */
272 err: rval = INP_ERR;
273 msgq(sp, M_SYSERR, "input");
274 break;
275 default: /* Input characters. */
276 if (sp == NULL) {
277 rval = INP_ERR;
278 msgq(sp, M_SYSERR,
279 "Can't convert input with NULL screen");
280 break;
282 if (!termread) ipp->iblen += *nr;
283 else {
284 CHAR2INT(sp, (char *)ipp->tbuf, *nr, wp, wlen);
285 MEMMOVEW(ipp->tbuf, wp, wlen);
287 rval = INP_OK;
288 break;
290 return (rval);
294 * ip_trans --
295 * Translate messages into events.
297 static int
298 ip_trans(SCR *sp, IP_PRIVATE *ipp, EVENT *evp)
300 u_int32_t skip, val;
301 const char *fmt;
302 const CHAR_T *wp;
303 size_t wlen;
305 if (ipp->ibuf[0] == CODE_OOB ||
306 ipp->ibuf[0] >= VI_EVENT_SUP)
309 * XXX: Protocol is out of sync?
311 abort();
313 fmt = vipfuns[ipp->ibuf[0]-1].format;
314 evp->e_event = vipfuns[ipp->ibuf[0]-1].e_event;
315 evp->e_ipcom = ipp->ibuf[0];
317 for (skip = IPO_CODE_LEN; *fmt != '\0'; ++fmt)
318 switch (*fmt) {
319 case '1':
320 case '2':
321 if (ipp->iblen < skip + IPO_INT_LEN)
322 return (0);
323 memcpy(&val, ipp->ibuf + skip, IPO_INT_LEN);
324 val = ntohl(val);
325 if (*fmt == '1')
326 evp->e_val1 = val;
327 else
328 evp->e_val2 = val;
329 skip += IPO_INT_LEN;
330 break;
331 case 'a':
332 case 'b':
333 if (ipp->iblen < skip + IPO_INT_LEN)
334 return (0);
335 memcpy(&val, ipp->ibuf + skip, IPO_INT_LEN);
336 val = ntohl(val);
337 skip += IPO_INT_LEN;
338 if (ipp->iblen < skip + val)
339 return (0);
340 if (*fmt == 'a') {
341 CHAR2INT(sp, ipp->ibuf + skip, val,
342 wp, wlen);
343 MEMCPYW(ipp->tbuf, wp, wlen);
344 evp->e_str1 = ipp->tbuf;
345 evp->e_len1 = wlen;
346 } else {
347 CHAR2INT(sp, ipp->ibuf + skip, val,
348 wp, wlen);
349 MEMCPYW(ipp->tbuf, wp, wlen);
350 evp->e_str2 = ipp->tbuf;
351 evp->e_len2 = wlen;
353 skip += val;
354 break;
357 ipp->iskip = skip;
359 if (evp->e_event == E_WRESIZE)
360 (void)ip_resize(sp, evp->e_val1, evp->e_val2);
362 return (1);
366 * ip_resize --
367 * Reset the options for a resize event.
369 static int
370 ip_resize(SCR *sp, u_int32_t lines, u_int32_t columns)
372 GS *gp;
373 int rval;
376 * XXX
377 * The IP screen has to know the lines and columns before anything
378 * else happens. So, we may not have a valid SCR pointer, and we
379 * have to deal with that.
381 if (sp == NULL) {
382 gp = __global_list;
383 OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines;
384 OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns;
385 return (0);
388 rval = api_opts_set(sp, L("lines"), NULL, lines, 0);
389 if (api_opts_set(sp, L("columns"), NULL, columns, 0))
390 rval = 1;
391 return (rval);