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.16 1996/12/18 10:28:03 bostic Exp $ (Berkeley) $Date: 1996/12/18 10:28:03 $";
14 #include <sys/types.h>
15 #include <sys/queue.h>
18 #include <bitstring.h>
26 #include "../common/common.h"
27 #include "../ex/script.h"
28 #include "../ipc/ip.h"
31 extern GS
*__global_list
;
33 typedef enum { INP_OK
=0, INP_EOF
, INP_ERR
, INP_TIMEOUT
} input_t
;
35 static input_t ip_read
__P((SCR
*, IP_PRIVATE
*, struct timeval
*));
36 static int ip_resize
__P((SCR
*, u_int32_t
, u_int32_t
));
37 static int ip_trans
__P((SCR
*, IP_PRIVATE
*, EVENT
*));
41 * Return a single event.
43 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
46 ip_event(sp
, evp
, flags
, ms
)
53 struct timeval t
, *tp
;
55 if (LF_ISSET(EC_INTERRUPT
)) { /* XXX */
56 evp
->e_event
= E_TIMEOUT
;
60 ipp
= sp
== NULL
? GIPP(__global_list
) : IPP(sp
);
62 /* Discard the last command. */
63 if (ipp
->iskip
!= 0) {
64 ipp
->iblen
-= ipp
->iskip
;
65 memmove(ipp
->ibuf
, ipp
->ibuf
+ ipp
->iskip
, ipp
->iblen
);
74 t
.tv_usec
= (ms
% 1000) * 1000;
78 /* Read input events. */
80 switch (ip_read(sp
, ipp
, tp
)) {
82 if (!ip_trans(sp
, ipp
, evp
))
92 evp
->e_event
= E_TIMEOUT
;
104 * Read characters from the input.
121 gp
= sp
== NULL
? __global_list
: sp
->gp
;
122 bp
= ipp
->ibuf
+ ipp
->iblen
;
123 blen
= sizeof(ipp
->ibuf
) - ipp
->iblen
;
126 * 1: A read with an associated timeout, e.g., trying to complete
127 * a map sequence. If input exists, we fall into #2.
133 FD_SET(ipp
->i_fd
, &rdfd
);
134 switch (select(ipp
->i_fd
+ 1,
135 &rdfd
, NULL
, NULL
, tp
== NULL
? &poll
: tp
)) {
137 return (INP_TIMEOUT
);
148 * Select on the command input and scripting window file descriptors.
149 * It's ugly that we wait on scripting file descriptors here, but it's
150 * the only way to keep from locking out scripting windows.
152 if (sp
!= NULL
&& F_ISSET(gp
, G_SCRWIN
)) {
153 loop
: FD_ZERO(&rdfd
);
154 FD_SET(ipp
->i_fd
, &rdfd
);
156 for (tsp
= gp
->dq
.cqh_first
;
157 tsp
!= (void *)&gp
->dq
; tsp
= tsp
->q
.cqe_next
)
158 if (F_ISSET(sp
, SC_SCRIPT
)) {
159 FD_SET(sp
->script
->sh_master
, &rdfd
);
160 if (sp
->script
->sh_master
> maxfd
)
161 maxfd
= sp
->script
->sh_master
;
163 switch (select(maxfd
+ 1, &rdfd
, NULL
, NULL
, NULL
)) {
171 if (!FD_ISSET(ipp
->i_fd
, &rdfd
)) {
181 switch (nr
= read(ipp
->i_fd
, bp
, blen
)) {
185 case -1: /* Error or interrupt. */
187 msgq(sp
, M_SYSERR
, "input");
189 default: /* Input characters. */
199 * Translate messages into events.
202 ip_trans(sp
, ipp
, evp
)
210 switch (ipp
->ibuf
[0]) {
225 evp
->e_event
= E_IPCOMMAND
;
226 evp
->e_ipcom
= ipp
->ibuf
[0];
227 ipp
->iskip
= IPO_CODE_LEN
;
234 evp
->e_event
= E_IPCOMMAND
;
235 evp
->e_ipcom
= ipp
->ibuf
[0];
239 evp
->e_event
= E_IPCOMMAND
;
240 evp
->e_ipcom
= ipp
->ibuf
[0];
247 evp
->e_event
= E_IPCOMMAND
;
248 evp
->e_ipcom
= ipp
->ibuf
[0];
252 evp
->e_event
= E_IPCOMMAND
;
253 evp
->e_ipcom
= ipp
->ibuf
[0];
257 evp
->e_event
= E_EOF
;
258 ipp
->iskip
= IPO_CODE_LEN
;
261 evp
->e_event
= E_ERR
;
262 ipp
->iskip
= IPO_CODE_LEN
;
265 evp
->e_event
= E_INTERRUPT
;
266 ipp
->iskip
= IPO_CODE_LEN
;
271 evp
->e_event
= E_IPCOMMAND
;
272 evp
->e_ipcom
= ipp
->ibuf
[0];
276 evp
->e_event
= E_WRESIZE
;
280 evp
->e_event
= E_SIGHUP
;
281 ipp
->iskip
= IPO_CODE_LEN
;
284 evp
->e_event
= E_SIGTERM
;
285 ipp
->iskip
= IPO_CODE_LEN
;
288 evp
->e_event
= E_STRING
;
293 * XXX: Protocol is out of sync?
298 for (skip
= IPO_CODE_LEN
; *fmt
!= '\0'; ++fmt
)
302 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
304 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
314 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
316 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
319 if (ipp
->iblen
< skip
+ val
)
322 evp
->e_str1
= ipp
->ibuf
+ skip
;
325 evp
->e_str2
= ipp
->ibuf
+ skip
;
334 if (evp
->e_event
== E_WRESIZE
)
335 (void)ip_resize(sp
, evp
->e_val1
, evp
->e_val2
);
342 * Reset the options for a resize event.
345 ip_resize(sp
, lines
, columns
)
347 u_int32_t lines
, columns
;
354 * The IP screen has to know the lines and columns before anything
355 * else happens. So, we may not have a valid SCR pointer, and we
356 * have to deal with that.
360 OG_VAL(gp
, GO_LINES
) = OG_D_VAL(gp
, GO_LINES
) = lines
;
361 OG_VAL(gp
, GO_COLUMNS
) = OG_D_VAL(gp
, GO_COLUMNS
) = columns
;
365 rval
= api_opts_set(sp
, "lines", NULL
, lines
, 0);
366 if (api_opts_set(sp
, "columns", NULL
, columns
, 0))