1 /* $NetBSD: ip_read.c,v 1.6 2013/11/29 15:24:08 christos Exp $ */
4 * Keith Bostic. All rights reserved.
6 * See the LICENSE file for redistribution information.
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 ";
15 #include <sys/types.h>
16 #include <sys/queue.h>
19 #include <bitstring.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. */
37 /* VI_C_BOTTOM 2 Cursor to bottom. */
39 /* VI_C_DEL 3 Cursor delete. */
41 /* VI_C_DOWN 4 Cursor down N lines: IPO_INT. */
43 /* VI_C_EOL 5 Cursor to end of line. */
45 /* VI_C_INSERT 6 Cursor: enter insert mode. */
47 /* VI_C_LEFT 7 Cursor left. */
49 /* VI_C_PGDOWN 8 Cursor down N pages: IPO_INT. */
51 /* VI_C_PGUP 9 Cursor up N lines: IPO_INT. */
53 /* VI_C_RIGHT 10 Cursor right. */
55 /* VI_C_SEARCH 11 Cursor: search: IPO_INT, IPO_STR. */
57 /* VI_C_SETTOP 12 Cursor: set screen top line: IPO_INT. */
59 /* VI_C_TOP 13 Cursor to top. */
61 /* VI_C_UP 14 Cursor up N lines: IPO_INT. */
63 /* VI_EDIT 15 Edit a file: IPO_STR. */
65 /* VI_EDITOPT 16 Edit option: 2 * IPO_STR, IPO_INT. */
67 /* VI_EDITSPLIT 17 Split to a file: IPO_STR. */
69 /* VI_EOF 18 End of input (NOT ^D). */
71 /* VI_ERR 19 Input error. */
73 /* VI_FLAGS 20 Flags */
75 /* VI_INTERRUPT 21 Interrupt. */
77 /* VI_MOUSE_MOVE 22 Mouse click move: IPO_INT, IPO_INT. */
79 /* VI_QUIT 23 Quit. */
81 /* VI_RESIZE 24 Screen resize: IPO_INT, IPO_INT. */
83 /* VI_SEL_END 25 Select end: IPO_INT, IPO_INT. */
85 /* VI_SEL_START 26 Select start: IPO_INT, IPO_INT. */
87 /* VI_SIGHUP 27 SIGHUP. */
89 /* VI_SIGTERM 28 SIGTERM. */
91 /* VI_STRING 29 Input string: IPO_STR. */
95 /* VI_TAGAS 31 Tag to a string: IPO_STR. */
97 /* VI_TAGSPLIT 32 Split to a tag. */
99 /* VI_UNDO 33 Undo. */
101 /* VI_WQ 34 Write and quit. */
103 /* VI_WRITE 35 Write. */
105 /* VI_WRITEAS 36 Write as another file: IPO_STR. */
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
*));
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
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
)
141 struct timeval t
, *tp
;
145 if (LF_ISSET(EC_INTERRUPT
)) { /* XXX */
146 evp
->e_event
= E_TIMEOUT
;
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
);
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
))
170 t
.tv_sec
= ms
/ 1000;
171 t
.tv_usec
= (ms
% 1000) * 1000;
175 /* Read input events. */
177 switch (ip_read(sp
, ipp
, tp
, termread
, &nr
)) {
180 evp
->e_csp
= ipp
->tbuf
;
182 evp
->e_event
= E_STRING
;
183 } else if (!ip_trans(sp
, ipp
, evp
))
187 evp
->e_event
= E_EOF
;
190 evp
->e_event
= E_ERR
;
193 evp
->e_event
= E_TIMEOUT
;
205 * Read characters from the input.
208 ip_read(SCR
*sp
, IP_PRIVATE
*ipp
, struct timeval
*tp
, int termread
, int *nr
)
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.
232 switch (select(fd
+ 1, &rdfd
, NULL
, NULL
, tp
)) {
234 return (INP_TIMEOUT
);
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
)) {
253 if (sscr_check_input(sp
, &rdfd
, maxfd
))
260 switch (*nr
= read(fd
, termread
? (char *)ipp
->tbuf
: bp
,
261 termread
? sizeof(ipp
->tbuf
)/sizeof(CHAR_T
)
266 case -1: /* Error or interrupt. */
268 msgq(sp
, M_SYSERR
, "input");
270 default: /* Input characters. */
274 "Can't convert input with NULL screen");
277 if (!termread
) ipp
->iblen
+= *nr
;
279 CHAR2INT(sp
, (char *)ipp
->tbuf
, *nr
, wp
, wlen
);
280 MEMMOVEW(ipp
->tbuf
, wp
, wlen
);
290 * Translate messages into events.
293 ip_trans(SCR
*sp
, IP_PRIVATE
*ipp
, EVENT
*evp
)
300 if (ipp
->ibuf
[0] == CODE_OOB
||
301 ipp
->ibuf
[0] >= VI_EVENT_SUP
)
304 * XXX: Protocol is out of sync?
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
)
316 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
318 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
328 if (ipp
->iblen
< skip
+ IPO_INT_LEN
)
330 memcpy(&val
, ipp
->ibuf
+ skip
, IPO_INT_LEN
);
333 if (ipp
->iblen
< skip
+ val
)
336 CHAR2INT(sp
, ipp
->ibuf
+ skip
, val
,
338 MEMCPYW(ipp
->tbuf
, wp
, wlen
);
339 evp
->e_str1
= ipp
->tbuf
;
342 CHAR2INT(sp
, ipp
->ibuf
+ skip
, val
,
344 MEMCPYW(ipp
->tbuf
, wp
, wlen
);
345 evp
->e_str2
= ipp
->tbuf
;
354 if (evp
->e_event
== E_WRESIZE
)
355 (void)ip_resize(sp
, evp
->e_val1
, evp
->e_val2
);
362 * Reset the options for a resize event.
365 ip_resize(SCR
*sp
, u_int32_t lines
, u_int32_t columns
)
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.
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
;
383 rval
= api_opts_set(sp
, L("lines"), NULL
, lines
, 0);
384 if (api_opts_set(sp
, L("columns"), NULL
, columns
, 0))