1 /* $NetBSD: ip_read.c,v 1.7 2014/01/26 21:43:45 christos Exp $ */
4 * Keith Bostic. All rights reserved.
6 * See the LICENSE file for redistribution information.
11 #include <sys/cdefs.h>
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 ";
17 __RCSID("$NetBSD: ip_read.c,v 1.7 2014/01/26 21:43:45 christos Exp $");
20 #include <sys/types.h>
21 #include <sys/queue.h>
24 #include <bitstring.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. */
42 /* VI_C_BOTTOM 2 Cursor to bottom. */
44 /* VI_C_DEL 3 Cursor delete. */
46 /* VI_C_DOWN 4 Cursor down N lines: IPO_INT. */
48 /* VI_C_EOL 5 Cursor to end of line. */
50 /* VI_C_INSERT 6 Cursor: enter insert mode. */
52 /* VI_C_LEFT 7 Cursor left. */
54 /* VI_C_PGDOWN 8 Cursor down N pages: IPO_INT. */
56 /* VI_C_PGUP 9 Cursor up N lines: IPO_INT. */
58 /* VI_C_RIGHT 10 Cursor right. */
60 /* VI_C_SEARCH 11 Cursor: search: IPO_INT, IPO_STR. */
62 /* VI_C_SETTOP 12 Cursor: set screen top line: IPO_INT. */
64 /* VI_C_TOP 13 Cursor to top. */
66 /* VI_C_UP 14 Cursor up N lines: IPO_INT. */
68 /* VI_EDIT 15 Edit a file: IPO_STR. */
70 /* VI_EDITOPT 16 Edit option: 2 * IPO_STR, IPO_INT. */
72 /* VI_EDITSPLIT 17 Split to a file: IPO_STR. */
74 /* VI_EOF 18 End of input (NOT ^D). */
76 /* VI_ERR 19 Input error. */
78 /* VI_FLAGS 20 Flags */
80 /* VI_INTERRUPT 21 Interrupt. */
82 /* VI_MOUSE_MOVE 22 Mouse click move: IPO_INT, IPO_INT. */
84 /* VI_QUIT 23 Quit. */
86 /* VI_RESIZE 24 Screen resize: IPO_INT, IPO_INT. */
88 /* VI_SEL_END 25 Select end: IPO_INT, IPO_INT. */
90 /* VI_SEL_START 26 Select start: IPO_INT, IPO_INT. */
92 /* VI_SIGHUP 27 SIGHUP. */
94 /* VI_SIGTERM 28 SIGTERM. */
96 /* VI_STRING 29 Input string: IPO_STR. */
100 /* VI_TAGAS 31 Tag to a string: IPO_STR. */
102 /* VI_TAGSPLIT 32 Split to a tag. */
104 /* VI_UNDO 33 Undo. */
106 /* VI_WQ 34 Write and quit. */
108 /* VI_WRITE 35 Write. */
110 /* VI_WRITEAS 36 Write as another file: IPO_STR. */
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
*));
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
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
)
146 struct timeval t
, *tp
;
150 if (LF_ISSET(EC_INTERRUPT
)) { /* XXX */
151 evp
->e_event
= E_TIMEOUT
;
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
);
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
))
175 t
.tv_sec
= ms
/ 1000;
176 t
.tv_usec
= (ms
% 1000) * 1000;
180 /* Read input events. */
182 switch (ip_read(sp
, ipp
, tp
, termread
, &nr
)) {
185 evp
->e_csp
= ipp
->tbuf
;
187 evp
->e_event
= E_STRING
;
188 } else if (!ip_trans(sp
, ipp
, evp
))
192 evp
->e_event
= E_EOF
;
195 evp
->e_event
= E_ERR
;
198 evp
->e_event
= E_TIMEOUT
;
210 * Read characters from the input.
213 ip_read(SCR
*sp
, IP_PRIVATE
*ipp
, struct timeval
*tp
, int termread
, int *nr
)
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.
237 switch (select(fd
+ 1, &rdfd
, NULL
, NULL
, tp
)) {
239 return (INP_TIMEOUT
);
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
)) {
258 if (sscr_check_input(sp
, &rdfd
, maxfd
))
265 switch (*nr
= read(fd
, termread
? (char *)ipp
->tbuf
: bp
,
266 termread
? sizeof(ipp
->tbuf
)/sizeof(CHAR_T
)
271 case -1: /* Error or interrupt. */
273 msgq(sp
, M_SYSERR
, "input");
275 default: /* Input characters. */
279 "Can't convert input with NULL screen");
282 if (!termread
) ipp
->iblen
+= *nr
;
284 CHAR2INT(sp
, (char *)ipp
->tbuf
, *nr
, wp
, wlen
);
285 MEMMOVEW(ipp
->tbuf
, wp
, wlen
);
295 * Translate messages into events.
298 ip_trans(SCR
*sp
, IP_PRIVATE
*ipp
, EVENT
*evp
)
305 if (ipp
->ibuf
[0] == CODE_OOB
||
306 ipp
->ibuf
[0] >= VI_EVENT_SUP
)
309 * XXX: Protocol is out of sync?
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
)
321 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
323 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
333 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
335 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
338 if (ipp
->iblen
< skip
+ val
)
341 CHAR2INT(sp
, ipp
->ibuf
+ skip
, val
,
343 MEMCPYW(ipp
->tbuf
, wp
, wlen
);
344 evp
->e_str1
= ipp
->tbuf
;
347 CHAR2INT(sp
, ipp
->ibuf
+ skip
, val
,
349 MEMCPYW(ipp
->tbuf
, wp
, wlen
);
350 evp
->e_str2
= ipp
->tbuf
;
359 if (evp
->e_event
== E_WRESIZE
)
360 (void)ip_resize(sp
, evp
->e_val1
, evp
->e_val2
);
367 * Reset the options for a resize event.
370 ip_resize(SCR
*sp
, u_int32_t lines
, u_int32_t columns
)
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.
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
;
388 rval
= api_opts_set(sp
, L("lines"), NULL
, lines
, 0);
389 if (api_opts_set(sp
, L("columns"), NULL
, columns
, 0))