3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
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 $";
14 #include <sys/types.h>
15 #include <sys/queue.h>
18 #include <bitstring.h>
26 #include "../common/common.h"
27 #include "../ex/script.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
*));
40 * Return a single event.
42 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
45 ip_event(sp
, evp
, flags
, ms
)
52 struct timeval t
, *tp
;
54 if (LF_ISSET(EC_INTERRUPT
)) { /* XXX */
55 evp
->e_event
= E_TIMEOUT
;
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
);
73 t
.tv_usec
= (ms
% 1000) * 1000;
77 /* Read input events. */
79 switch (ip_read(sp
, ipp
, tp
)) {
81 if (!ip_trans(sp
, ipp
, evp
))
91 evp
->e_event
= E_TIMEOUT
;
103 * Read characters from the input.
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.
132 FD_SET(ipp
->i_fd
, &rdfd
);
133 switch (select(ipp
->i_fd
+ 1,
134 &rdfd
, NULL
, NULL
, tp
== NULL
? &poll
: tp
)) {
136 return (INP_TIMEOUT
);
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
);
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
)) {
170 if (!FD_ISSET(ipp
->i_fd
, &rdfd
)) {
180 switch (nr
= read(ipp
->i_fd
, bp
, blen
)) {
184 case -1: /* Error or interrupt. */
186 msgq(sp
, M_SYSERR
, "input");
188 default: /* Input characters. */
198 * Translate messages into events.
201 ip_trans(sp
, ipp
, evp
)
206 u_int32_t val1
, val2
;
208 switch (ipp
->ibuf
[0]) {
214 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
)
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
;
236 evp
->e_event
= E_IPCOMMAND
;
237 evp
->e_ipcom
= ipp
->ibuf
[0];
238 ipp
->iskip
= IPO_CODE_LEN
;
241 evp
->e_event
= E_IPCOMMAND
;
242 evp
->e_ipcom
= ipp
->ibuf
[0];
243 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
* 2)
245 memcpy(&val1
, ipp
->ibuf
+ IPO_CODE_LEN
, IPO_INT_LEN
);
246 evp
->e_flags
= ntohl(val1
);
248 ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
, IPO_INT_LEN
);
250 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
* 2 + val1
)
252 ipp
->iskip
= IPO_CODE_LEN
+ IPO_INT_LEN
* 2 + val1
;
253 evp
->e_csp
= ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
* 2;
260 evp
->e_event
= E_IPCOMMAND
;
261 evp
->e_ipcom
= ipp
->ibuf
[0];
264 evp
->e_event
= E_EOF
;
265 ipp
->iskip
= IPO_CODE_LEN
;
268 evp
->e_event
= E_ERR
;
269 ipp
->iskip
= IPO_CODE_LEN
;
272 evp
->e_event
= E_INTERRUPT
;
273 ipp
->iskip
= IPO_CODE_LEN
;
276 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
* 2)
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
);
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;
288 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
* 2)
290 evp
->e_event
= E_WRESIZE
;
291 memcpy(&val1
, ipp
->ibuf
+ IPO_CODE_LEN
, IPO_INT_LEN
);
294 ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
, IPO_INT_LEN
);
296 ip_resize(sp
, val1
, val2
);
297 ipp
->iskip
= IPO_CODE_LEN
+ IPO_INT_LEN
* 2;
300 evp
->e_event
= E_SIGHUP
;
301 ipp
->iskip
= IPO_CODE_LEN
;
304 evp
->e_event
= E_SIGTERM
;
305 ipp
->iskip
= IPO_CODE_LEN
;
308 evp
->e_event
= E_STRING
;
309 string
: if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
)
311 memcpy(&val1
, ipp
->ibuf
+ IPO_CODE_LEN
, IPO_INT_LEN
);
313 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
+ val1
)
315 ipp
->iskip
= IPO_CODE_LEN
+ IPO_INT_LEN
+ val1
;
316 evp
->e_csp
= ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
;
321 * XXX: Protocol is out of sync?
330 * Reset the options for a resize event.
333 ip_resize(sp
, lines
, columns
)
335 u_int32_t lines
, columns
;
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.
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
;
353 rval
= api_opts_set(sp
, "lines", NULL
, lines
, 0);
354 if (api_opts_set(sp
, "columns", NULL
, columns
, 0))