Merge from vendor branch CVS:
[dragonfly.git] / contrib / nvi / tk / tk_read.c
1 /*-
2  * Copyright (c) 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1993, 1994, 1995, 1996
5  *      Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9
10 #include "config.h"
11
12 #ifndef lint
13 static const char sccsid[] = "@(#)tk_read.c     8.12 (Berkeley) 9/24/96";
14 #endif /* not lint */
15
16 #include <sys/types.h>
17 #include <sys/queue.h>
18
19 #include <bitstring.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <termios.h>
27 #include <unistd.h>
28
29 #include "../common/common.h"
30 #include "../ex/script.h"
31 #include "tki.h"
32
33 static input_t  tk_read __P((SCR *, int));
34 static int      tk_resize __P((SCR *, size_t, size_t));
35
36
37 /*
38  * tk_event --
39  *      Return a single event.
40  *
41  * PUBLIC: int tk_event __P((SCR *, EVENT *, u_int32_t, int));
42  */
43 int
44 tk_event(sp, evp, flags, timeout)
45         SCR *sp;
46         EVENT *evp;
47         u_int32_t flags;
48         int timeout;
49 {
50         EVENT *tevp;
51         TK_PRIVATE *tkp;
52         size_t lines, columns;
53         int changed;
54
55         /*
56          * Queue signal based events.  We never clear SIGHUP or SIGTERM events,
57          * so that we just keep returning them until the editor dies.
58          */
59         tkp = TKP(sp);
60 sig:    if (LF_ISSET(EC_INTERRUPT) || F_ISSET(tkp, TK_SIGINT)) {
61                 if (F_ISSET(tkp, TK_SIGINT)) {
62                         F_CLR(tkp, TK_SIGINT);
63                         evp->e_event = E_INTERRUPT;
64                 } else
65                         evp->e_event = E_TIMEOUT;
66                 return (0);
67         }
68         if (F_ISSET(tkp, TK_SIGHUP | TK_SIGTERM | TK_SIGWINCH)) {
69                 if (F_ISSET(tkp, TK_SIGHUP)) {
70                         evp->e_event = E_SIGHUP;
71                         return (0);
72                 }
73                 if (F_ISSET(tkp, TK_SIGTERM)) {
74                         evp->e_event = E_SIGTERM;
75                         return (0);
76                 }
77                 if (F_ISSET(tkp, TK_SIGWINCH)) {
78                         F_CLR(tkp, TK_SIGWINCH);
79                         (void)tk_ssize(sp, 1, &lines, &columns, &changed);
80                         if (changed) {
81                                 (void)tk_resize(sp, lines, columns);
82                                 evp->e_event = E_WRESIZE;
83                                 return (0);
84                         }
85                         /* No change, so ignore the signal. */
86                 }
87         }
88
89         /* Queue special ops. */
90 ops:    if ((tevp = tkp->evq.tqh_first) != NULL) {
91                 *evp = *tevp;
92                 TAILQ_REMOVE(&tkp->evq, tevp, q);
93                 free(tevp);
94                 return (0);
95         }
96                 
97         /* Read input characters. */
98         switch (tk_read(sp, timeout)) {
99         case INP_OK:
100                 evp->e_csp = tkp->ibuf;
101                 evp->e_len = tkp->ibuf_cnt;
102                 evp->e_event = E_STRING;
103                 tkp->ibuf_cnt = 0;
104                 break;
105         case INP_EOF:
106                 evp->e_event = E_EOF;
107                 break;
108         case INP_ERR:
109                 evp->e_event = E_ERR;
110                 break;
111         case INP_INTR:
112                 goto sig;
113                 break;
114         case INP_TIMEOUT:
115                 /* May have returned because queued a special op. */
116                 if (tkp->evq.tqh_first != NULL)
117                         goto ops;
118
119                 /* Otherwise, we timed out. */
120                 evp->e_event = E_TIMEOUT;
121                 break;
122         default:
123                 abort();
124         }
125         return (0);
126 }
127
128 /*
129  * tk_read --
130  *      Read characters from the input.
131  */
132 static input_t
133 tk_read(sp, timeout)
134         SCR *sp;
135         int timeout;
136 {
137         TK_PRIVATE *tkp;
138         char buf[20];
139
140         /*
141          * Check scripting window file descriptors.  It's ugly that we wait
142          * on scripting file descriptors here, but it's the only way to keep
143          * from locking out scripting windows.
144          */
145         if (F_ISSET(sp->gp, G_SCRWIN) && sscr_input(sp))
146                 return (INP_ERR);
147
148         /* Read characters. */
149         tkp = TKP(sp);
150         (void)snprintf(buf, sizeof(buf), "%d", timeout);
151         (void)Tcl_VarEval(tkp->interp, "tk_key_wait ", buf, NULL);
152
153         return (tkp->ibuf_cnt == 0 ? INP_TIMEOUT : INP_OK);
154 }
155
156 /*
157  * tk_key --
158  *      Receive an input key.
159  *
160  * PUBLIC: int tk_key __P((ClientData, Tcl_Interp *, int, char *[]));
161  */
162 int
163 tk_key(clientData, interp, argc, argv)
164         ClientData clientData;
165         Tcl_Interp *interp;
166         int argc;
167         char *argv[];
168 {
169         TK_PRIVATE *tkp;
170         u_int8_t *p, *t;
171
172         tkp = (TK_PRIVATE *)clientData;
173         for (p =
174             tkp->ibuf + tkp->ibuf_cnt, t = argv[1]; (*p++ = *t++) != '\0';
175             ++tkp->ibuf_cnt); 
176         return (TCL_OK);
177 }
178
179 /* 
180  * tk_resize --
181  *      Reset the options for a resize event.
182  */
183 static int
184 tk_resize(sp, lines, columns)
185         SCR *sp;
186         size_t lines, columns;
187 {
188         ARGS *argv[2], a, b;
189         int rval;
190         char b1[1024];
191
192         a.bp = b1;
193         b.bp = NULL;
194         a.len = b.len = 0;
195         argv[0] = &a;
196         argv[1] = &b;
197
198         (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
199         a.len = strlen(b1);
200         if (opts_set(sp, argv, NULL))
201                 return (1);
202         (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
203         a.len = strlen(b1);
204         if (opts_set(sp, argv, NULL))
205                 return (1);
206         return (0);
207 }