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