from RAZ: ruler dialog box
[nvi.git] / ip / ip_read.c
blob5d1dfca605d898807e2843bc7d15eba3c9389c32
1 /*-
2 * Copyright (c) 1996
3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "$Id: ip_read.c,v 8.12 1996/12/13 12:22:54 bostic Exp $ (Berkeley) $Date: 1996/12/13 12:22:54 $";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
16 #include <sys/time.h>
18 #include <bitstring.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <termios.h>
23 #include <time.h>
24 #include <unistd.h>
26 #include "../common/common.h"
27 #include "../ex/script.h"
28 #include "ip.h"
30 extern GS *__global_list;
32 typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
34 static input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *));
35 static int ip_resize __P((SCR *, u_int32_t, u_int32_t));
36 static int ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
39 * ip_event --
40 * Return a single event.
42 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
44 int
45 ip_event(sp, evp, flags, ms)
46 SCR *sp;
47 EVENT *evp;
48 u_int32_t flags;
49 int ms;
51 IP_PRIVATE *ipp;
52 struct timeval t, *tp;
54 if (LF_ISSET(EC_INTERRUPT)) { /* XXX */
55 evp->e_event = E_TIMEOUT;
56 return (0);
59 ipp = sp == NULL ? GIPP(__global_list) : IPP(sp);
61 /* Discard the last command. */
62 if (ipp->iskip != 0) {
63 ipp->iblen -= ipp->iskip;
64 memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen);
65 ipp->iskip = 0;
68 /* Set timer. */
69 if (ms == 0)
70 tp = NULL;
71 else {
72 t.tv_sec = ms / 1000;
73 t.tv_usec = (ms % 1000) * 1000;
74 tp = &t;
77 /* Read input events. */
78 for (;;) {
79 switch (ip_read(sp, ipp, tp)) {
80 case INP_OK:
81 if (!ip_trans(sp, ipp, evp))
82 continue;
83 break;
84 case INP_EOF:
85 evp->e_event = E_EOF;
86 break;
87 case INP_ERR:
88 evp->e_event = E_ERR;
89 break;
90 case INP_TIMEOUT:
91 evp->e_event = E_TIMEOUT;
92 break;
93 default:
94 abort();
96 break;
98 return (0);
102 * ip_read --
103 * Read characters from the input.
105 static input_t
106 ip_read(sp, ipp, tp)
107 SCR *sp;
108 IP_PRIVATE *ipp;
109 struct timeval *tp;
111 struct timeval poll;
112 GS *gp;
113 SCR *tsp;
114 fd_set rdfd;
115 input_t rval;
116 size_t blen;
117 int maxfd, nr;
118 char *bp;
120 gp = sp == NULL ? __global_list : sp->gp;
121 bp = ipp->ibuf + ipp->iblen;
122 blen = sizeof(ipp->ibuf) - ipp->iblen;
125 * 1: A read with an associated timeout, e.g., trying to complete
126 * a map sequence. If input exists, we fall into #2.
128 FD_ZERO(&rdfd);
129 poll.tv_sec = 0;
130 poll.tv_usec = 0;
131 if (tp != NULL) {
132 FD_SET(ipp->i_fd, &rdfd);
133 switch (select(ipp->i_fd + 1,
134 &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
135 case 0:
136 return (INP_TIMEOUT);
137 case -1:
138 goto err;
139 default:
140 break;
145 * 2: Wait for input.
147 * Select on the command input and scripting window file descriptors.
148 * It's ugly that we wait on scripting file descriptors here, but it's
149 * the only way to keep from locking out scripting windows.
151 if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
152 loop: FD_ZERO(&rdfd);
153 FD_SET(ipp->i_fd, &rdfd);
154 maxfd = ipp->i_fd;
155 for (tsp = gp->dq.cqh_first;
156 tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
157 if (F_ISSET(sp, SC_SCRIPT)) {
158 FD_SET(sp->script->sh_master, &rdfd);
159 if (sp->script->sh_master > maxfd)
160 maxfd = sp->script->sh_master;
162 switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
163 case 0:
164 abort();
165 case -1:
166 goto err;
167 default:
168 break;
170 if (!FD_ISSET(ipp->i_fd, &rdfd)) {
171 if (sscr_input(sp))
172 return (INP_ERR);
173 goto loop;
178 * 3: Read the input.
180 switch (nr = read(ipp->i_fd, bp, blen)) {
181 case 0: /* EOF. */
182 rval = INP_EOF;
183 break;
184 case -1: /* Error or interrupt. */
185 err: rval = INP_ERR;
186 msgq(sp, M_SYSERR, "input");
187 break;
188 default: /* Input characters. */
189 ipp->iblen += nr;
190 rval = INP_OK;
191 break;
193 return (rval);
197 * ip_trans --
198 * Translate messages into events.
200 static int
201 ip_trans(sp, ipp, evp)
202 SCR *sp;
203 IP_PRIVATE *ipp;
204 EVENT *evp;
206 u_int32_t val1, val2;
208 switch (ipp->ibuf[0]) {
209 case VI_C_DOWN:
210 case VI_C_PGDOWN:
211 case VI_C_PGUP:
212 case VI_C_UP:
213 case VI_C_SETTOP:
214 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN)
215 return (0);
216 evp->e_event = E_IPCOMMAND;
217 evp->e_ipcom = ipp->ibuf[0];
218 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
219 evp->e_lno = ntohl(val1);
220 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN;
221 return (1);
222 case VI_C_BOL:
223 case VI_C_BOTTOM:
224 case VI_C_DEL:
225 case VI_C_EOL:
226 case VI_C_INSERT:
227 case VI_C_LEFT:
228 case VI_C_RIGHT:
229 case VI_C_TOP:
230 case VI_QUIT:
231 case VI_TAG:
232 case VI_TAGSPLIT:
233 case VI_UNDO:
234 case VI_WQ:
235 case VI_WRITE:
236 evp->e_event = E_IPCOMMAND;
237 evp->e_ipcom = ipp->ibuf[0];
238 ipp->iskip = IPO_CODE_LEN;
239 return (1);
240 case VI_C_SEARCH:
241 evp->e_event = E_IPCOMMAND;
242 evp->e_ipcom = ipp->ibuf[0];
243 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
244 return (0);
245 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
246 evp->e_flags = ntohl(val1);
247 memcpy(&val1,
248 ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
249 val1 = ntohl(val1);
250 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2 + val1)
251 return (0);
252 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2 + val1;
253 evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN * 2;
254 evp->e_len = val1;
255 return (1);
256 case VI_EDIT:
257 case VI_EDITSPLIT:
258 case VI_TAGAS:
259 case VI_WRITEAS:
260 evp->e_event = E_IPCOMMAND;
261 evp->e_ipcom = ipp->ibuf[0];
262 goto string;
263 case VI_EOF:
264 evp->e_event = E_EOF;
265 ipp->iskip = IPO_CODE_LEN;
266 return (1);
267 case VI_ERR:
268 evp->e_event = E_ERR;
269 ipp->iskip = IPO_CODE_LEN;
270 return (1);
271 case VI_INTERRUPT:
272 evp->e_event = E_INTERRUPT;
273 ipp->iskip = IPO_CODE_LEN;
274 return (1);
275 case VI_MOUSE_MOVE:
276 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
277 return (0);
278 evp->e_event = E_IPCOMMAND;
279 evp->e_ipcom = VI_MOUSE_MOVE;
280 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
281 evp->e_lno = ntohl(val1);
282 memcpy(&val2,
283 ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
284 evp->e_cno = ntohl(val2);
285 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2;
286 return (1);
287 case VI_RESIZE:
288 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
289 return (0);
290 evp->e_event = E_WRESIZE;
291 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
292 val1 = ntohl(val1);
293 memcpy(&val2,
294 ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
295 val2 = ntohl(val2);
296 ip_resize(sp, val1, val2);
297 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2;
298 return (1);
299 case VI_SIGHUP:
300 evp->e_event = E_SIGHUP;
301 ipp->iskip = IPO_CODE_LEN;
302 return (1);
303 case VI_SIGTERM:
304 evp->e_event = E_SIGTERM;
305 ipp->iskip = IPO_CODE_LEN;
306 return (1);
307 case VI_STRING:
308 evp->e_event = E_STRING;
309 string: if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN)
310 return (0);
311 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
312 val1 = ntohl(val1);
313 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN + val1)
314 return (0);
315 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN + val1;
316 evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN;
317 evp->e_len = val1;
318 return (1);
319 default:
321 * XXX: Protocol is out of sync?
323 abort();
325 /* NOTREACHED */
329 * ip_resize --
330 * Reset the options for a resize event.
332 static int
333 ip_resize(sp, lines, columns)
334 SCR *sp;
335 u_int32_t lines, columns;
337 GS *gp;
338 int rval;
341 * XXX
342 * The IP screen has to know the lines and columns before anything
343 * else happens. So, we may not have a valid SCR pointer, and we
344 * have to deal with that.
346 if (sp == NULL) {
347 gp = __global_list;
348 OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines;
349 OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns;
350 return (0);
353 rval = api_opts_set(sp, "lines", NULL, lines, 0);
354 if (api_opts_set(sp, "columns", NULL, columns, 0))
355 rval = 1;
356 return (rval);