tty.c revision 1.5 1 1.5 christos /* $NetBSD: tty.c,v 1.5 1997/10/09 19:16:04 christos Exp $ */
2 1.2 lukem
3 1.1 cgd /*-
4 1.1 cgd * Copyright (c) 1992, 1993
5 1.1 cgd * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * This code is derived from software contributed to Berkeley by
8 1.1 cgd * Christos Zoulas of Cornell University.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.1 cgd * 3. All advertising materials mentioning features or use of this software
19 1.1 cgd * must display the following acknowledgement:
20 1.1 cgd * This product includes software developed by the University of
21 1.1 cgd * California, Berkeley and its contributors.
22 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
23 1.1 cgd * may be used to endorse or promote products derived from this software
24 1.1 cgd * without specific prior written permission.
25 1.1 cgd *
26 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.1 cgd * SUCH DAMAGE.
37 1.1 cgd */
38 1.1 cgd
39 1.4 christos #include <sys/cdefs.h>
40 1.1 cgd #if !defined(lint) && !defined(SCCSID)
41 1.2 lukem #if 0
42 1.1 cgd static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
43 1.2 lukem #else
44 1.5 christos __RCSID("$NetBSD: tty.c,v 1.5 1997/10/09 19:16:04 christos Exp $");
45 1.2 lukem #endif
46 1.1 cgd #endif /* not lint && not SCCSID */
47 1.1 cgd
48 1.1 cgd /*
49 1.1 cgd * tty.c: tty interface stuff
50 1.1 cgd */
51 1.1 cgd #include "sys.h"
52 1.1 cgd #include "tty.h"
53 1.1 cgd #include "el.h"
54 1.1 cgd
55 1.1 cgd typedef struct ttymodes_t {
56 1.1 cgd char *m_name;
57 1.3 christos u_int m_value;
58 1.1 cgd int m_type;
59 1.1 cgd } ttymodes_t;
60 1.1 cgd
61 1.1 cgd typedef struct ttymap_t {
62 1.1 cgd int nch, och; /* Internal and termio rep of chars */
63 1.1 cgd el_action_t bind[3]; /* emacs, vi, and vi-cmd */
64 1.1 cgd } ttymap_t;
65 1.1 cgd
66 1.1 cgd
67 1.1 cgd private ttyperm_t ttyperm = {
68 1.1 cgd {
69 1.1 cgd { "iflag:", ICRNL, (INLCR|IGNCR) },
70 1.1 cgd { "oflag:", (OPOST|ONLCR), ONLRET },
71 1.1 cgd { "cflag:", 0, 0 },
72 1.1 cgd { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
73 1.1 cgd (NOFLSH|ECHONL|EXTPROC|FLUSHO) },
74 1.1 cgd { "chars:", 0, 0 },
75 1.1 cgd },
76 1.1 cgd {
77 1.1 cgd { "iflag:", (INLCR|ICRNL), IGNCR },
78 1.1 cgd { "oflag:", (OPOST|ONLCR), ONLRET },
79 1.1 cgd { "cflag:", 0, 0 },
80 1.1 cgd { "lflag:", ISIG,
81 1.1 cgd (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) },
82 1.1 cgd { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
83 1.1 cgd C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)|
84 1.1 cgd C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 }
85 1.1 cgd },
86 1.1 cgd {
87 1.1 cgd { "iflag:", 0, IXON | IXOFF },
88 1.1 cgd { "oflag:", 0, 0 },
89 1.1 cgd { "cflag:", 0, 0 },
90 1.1 cgd { "lflag:", 0, ISIG | IEXTEN },
91 1.1 cgd { "chars:", 0, 0 },
92 1.1 cgd }
93 1.1 cgd };
94 1.1 cgd
95 1.1 cgd private ttychar_t ttychar = {
96 1.1 cgd {
97 1.1 cgd CINTR, CQUIT, CERASE, CKILL,
98 1.1 cgd CEOF, CEOL, CEOL2, CSWTCH,
99 1.1 cgd CDSWTCH, CERASE2, CSTART, CSTOP,
100 1.1 cgd CWERASE, CSUSP, CDSUSP, CREPRINT,
101 1.1 cgd CDISCARD, CLNEXT, CSTATUS, CPAGE,
102 1.1 cgd CPGOFF, CKILL2, CBRK, CMIN,
103 1.1 cgd CTIME
104 1.1 cgd },
105 1.1 cgd {
106 1.1 cgd CINTR, CQUIT, CERASE, CKILL,
107 1.1 cgd _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
108 1.1 cgd _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
109 1.1 cgd _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
110 1.1 cgd CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
111 1.1 cgd _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
112 1.1 cgd 0
113 1.1 cgd },
114 1.1 cgd {
115 1.1 cgd 0, 0, 0, 0,
116 1.1 cgd 0, 0, 0, 0,
117 1.1 cgd 0, 0, 0, 0,
118 1.1 cgd 0, 0, 0, 0,
119 1.1 cgd 0, 0, 0, 0,
120 1.1 cgd 0, 0, 0, 0,
121 1.1 cgd 0
122 1.1 cgd }
123 1.1 cgd };
124 1.1 cgd
125 1.1 cgd private ttymap_t tty_map[] = {
126 1.1 cgd #ifdef VERASE
127 1.1 cgd { C_ERASE, VERASE,
128 1.1 cgd { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
129 1.1 cgd #endif /* VERASE */
130 1.1 cgd #ifdef VERASE2
131 1.1 cgd { C_ERASE2, VERASE2,
132 1.1 cgd { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
133 1.1 cgd #endif /* VERASE2 */
134 1.1 cgd #ifdef VKILL
135 1.1 cgd { C_KILL, VKILL,
136 1.1 cgd { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
137 1.1 cgd #endif /* VKILL */
138 1.1 cgd #ifdef VKILL2
139 1.1 cgd { C_KILL2, VKILL2,
140 1.1 cgd { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
141 1.1 cgd #endif /* VKILL2 */
142 1.1 cgd #ifdef VEOF
143 1.1 cgd { C_EOF, VEOF,
144 1.1 cgd { EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } },
145 1.1 cgd #endif /* VEOF */
146 1.1 cgd #ifdef VWERASE
147 1.1 cgd { C_WERASE, VWERASE,
148 1.1 cgd { ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } },
149 1.1 cgd #endif /* VWERASE */
150 1.1 cgd #ifdef VREPRINT
151 1.1 cgd { C_REPRINT, VREPRINT,
152 1.1 cgd { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
153 1.1 cgd #endif /* VREPRINT */
154 1.1 cgd #ifdef VLNEXT
155 1.1 cgd { C_LNEXT, VLNEXT,
156 1.1 cgd { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
157 1.1 cgd #endif /* VLNEXT */
158 1.1 cgd { -1, -1,
159 1.1 cgd { ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } }
160 1.1 cgd };
161 1.1 cgd
162 1.1 cgd private ttymodes_t ttymodes[] = {
163 1.1 cgd # ifdef IGNBRK
164 1.1 cgd { "ignbrk", IGNBRK, M_INP },
165 1.1 cgd # endif /* IGNBRK */
166 1.1 cgd # ifdef BRKINT
167 1.1 cgd { "brkint", BRKINT, M_INP },
168 1.1 cgd # endif /* BRKINT */
169 1.1 cgd # ifdef IGNPAR
170 1.1 cgd { "ignpar", IGNPAR, M_INP },
171 1.1 cgd # endif /* IGNPAR */
172 1.1 cgd # ifdef PARMRK
173 1.1 cgd { "parmrk", PARMRK, M_INP },
174 1.1 cgd # endif /* PARMRK */
175 1.1 cgd # ifdef INPCK
176 1.1 cgd { "inpck", INPCK, M_INP },
177 1.1 cgd # endif /* INPCK */
178 1.1 cgd # ifdef ISTRIP
179 1.1 cgd { "istrip", ISTRIP, M_INP },
180 1.1 cgd # endif /* ISTRIP */
181 1.1 cgd # ifdef INLCR
182 1.1 cgd { "inlcr", INLCR, M_INP },
183 1.1 cgd # endif /* INLCR */
184 1.1 cgd # ifdef IGNCR
185 1.1 cgd { "igncr", IGNCR, M_INP },
186 1.1 cgd # endif /* IGNCR */
187 1.1 cgd # ifdef ICRNL
188 1.1 cgd { "icrnl", ICRNL, M_INP },
189 1.1 cgd # endif /* ICRNL */
190 1.1 cgd # ifdef IUCLC
191 1.1 cgd { "iuclc", IUCLC, M_INP },
192 1.1 cgd # endif /* IUCLC */
193 1.1 cgd # ifdef IXON
194 1.1 cgd { "ixon", IXON, M_INP },
195 1.1 cgd # endif /* IXON */
196 1.1 cgd # ifdef IXANY
197 1.1 cgd { "ixany", IXANY, M_INP },
198 1.1 cgd # endif /* IXANY */
199 1.1 cgd # ifdef IXOFF
200 1.1 cgd { "ixoff", IXOFF, M_INP },
201 1.1 cgd # endif /* IXOFF */
202 1.1 cgd # ifdef IMAXBEL
203 1.1 cgd { "imaxbel",IMAXBEL,M_INP },
204 1.1 cgd # endif /* IMAXBEL */
205 1.1 cgd
206 1.1 cgd # ifdef OPOST
207 1.1 cgd { "opost", OPOST, M_OUT },
208 1.1 cgd # endif /* OPOST */
209 1.1 cgd # ifdef OLCUC
210 1.1 cgd { "olcuc", OLCUC, M_OUT },
211 1.1 cgd # endif /* OLCUC */
212 1.1 cgd # ifdef ONLCR
213 1.1 cgd { "onlcr", ONLCR, M_OUT },
214 1.1 cgd # endif /* ONLCR */
215 1.1 cgd # ifdef OCRNL
216 1.1 cgd { "ocrnl", OCRNL, M_OUT },
217 1.1 cgd # endif /* OCRNL */
218 1.1 cgd # ifdef ONOCR
219 1.1 cgd { "onocr", ONOCR, M_OUT },
220 1.1 cgd # endif /* ONOCR */
221 1.1 cgd # ifdef ONOEOT
222 1.1 cgd { "onoeot", ONOEOT, M_OUT },
223 1.1 cgd # endif /* ONOEOT */
224 1.1 cgd # ifdef ONLRET
225 1.1 cgd { "onlret", ONLRET, M_OUT },
226 1.1 cgd # endif /* ONLRET */
227 1.1 cgd # ifdef OFILL
228 1.1 cgd { "ofill", OFILL, M_OUT },
229 1.1 cgd # endif /* OFILL */
230 1.1 cgd # ifdef OFDEL
231 1.1 cgd { "ofdel", OFDEL, M_OUT },
232 1.1 cgd # endif /* OFDEL */
233 1.1 cgd # ifdef NLDLY
234 1.1 cgd { "nldly", NLDLY, M_OUT },
235 1.1 cgd # endif /* NLDLY */
236 1.1 cgd # ifdef CRDLY
237 1.1 cgd { "crdly", CRDLY, M_OUT },
238 1.1 cgd # endif /* CRDLY */
239 1.1 cgd # ifdef TABDLY
240 1.1 cgd { "tabdly", TABDLY, M_OUT },
241 1.1 cgd # endif /* TABDLY */
242 1.1 cgd # ifdef XTABS
243 1.1 cgd { "xtabs", XTABS, M_OUT },
244 1.1 cgd # endif /* XTABS */
245 1.1 cgd # ifdef BSDLY
246 1.1 cgd { "bsdly", BSDLY, M_OUT },
247 1.1 cgd # endif /* BSDLY */
248 1.1 cgd # ifdef VTDLY
249 1.1 cgd { "vtdly", VTDLY, M_OUT },
250 1.1 cgd # endif /* VTDLY */
251 1.1 cgd # ifdef FFDLY
252 1.1 cgd { "ffdly", FFDLY, M_OUT },
253 1.1 cgd # endif /* FFDLY */
254 1.1 cgd # ifdef PAGEOUT
255 1.1 cgd { "pageout",PAGEOUT,M_OUT },
256 1.1 cgd # endif /* PAGEOUT */
257 1.1 cgd # ifdef WRAP
258 1.1 cgd { "wrap", WRAP, M_OUT },
259 1.1 cgd # endif /* WRAP */
260 1.1 cgd
261 1.1 cgd # ifdef CIGNORE
262 1.1 cgd { "cignore",CIGNORE,M_CTL },
263 1.1 cgd # endif /* CBAUD */
264 1.1 cgd # ifdef CBAUD
265 1.1 cgd { "cbaud", CBAUD, M_CTL },
266 1.1 cgd # endif /* CBAUD */
267 1.1 cgd # ifdef CSTOPB
268 1.1 cgd { "cstopb", CSTOPB, M_CTL },
269 1.1 cgd # endif /* CSTOPB */
270 1.1 cgd # ifdef CREAD
271 1.1 cgd { "cread", CREAD, M_CTL },
272 1.1 cgd # endif /* CREAD */
273 1.1 cgd # ifdef PARENB
274 1.1 cgd { "parenb", PARENB, M_CTL },
275 1.1 cgd # endif /* PARENB */
276 1.1 cgd # ifdef PARODD
277 1.1 cgd { "parodd", PARODD, M_CTL },
278 1.1 cgd # endif /* PARODD */
279 1.1 cgd # ifdef HUPCL
280 1.1 cgd { "hupcl", HUPCL, M_CTL },
281 1.1 cgd # endif /* HUPCL */
282 1.1 cgd # ifdef CLOCAL
283 1.1 cgd { "clocal", CLOCAL, M_CTL },
284 1.1 cgd # endif /* CLOCAL */
285 1.1 cgd # ifdef LOBLK
286 1.1 cgd { "loblk", LOBLK, M_CTL },
287 1.1 cgd # endif /* LOBLK */
288 1.1 cgd # ifdef CIBAUD
289 1.1 cgd { "cibaud", CIBAUD, M_CTL },
290 1.1 cgd # endif /* CIBAUD */
291 1.1 cgd # ifdef CRTSCTS
292 1.1 cgd # ifdef CCTS_OFLOW
293 1.1 cgd { "ccts_oflow",CCTS_OFLOW,M_CTL },
294 1.1 cgd # else
295 1.1 cgd { "crtscts",CRTSCTS,M_CTL },
296 1.1 cgd # endif /* CCTS_OFLOW */
297 1.1 cgd # endif /* CRTSCTS */
298 1.1 cgd # ifdef CRTS_IFLOW
299 1.1 cgd { "crts_iflow",CRTS_IFLOW,M_CTL },
300 1.1 cgd # endif /* CRTS_IFLOW */
301 1.1 cgd # ifdef MDMBUF
302 1.1 cgd { "mdmbuf", MDMBUF, M_CTL },
303 1.1 cgd # endif /* MDMBUF */
304 1.1 cgd # ifdef RCV1EN
305 1.1 cgd { "rcv1en", RCV1EN, M_CTL },
306 1.1 cgd # endif /* RCV1EN */
307 1.1 cgd # ifdef XMT1EN
308 1.1 cgd { "xmt1en", XMT1EN, M_CTL },
309 1.1 cgd # endif /* XMT1EN */
310 1.1 cgd
311 1.1 cgd # ifdef ISIG
312 1.1 cgd { "isig", ISIG, M_LIN },
313 1.1 cgd # endif /* ISIG */
314 1.1 cgd # ifdef ICANON
315 1.1 cgd { "icanon", ICANON, M_LIN },
316 1.1 cgd # endif /* ICANON */
317 1.1 cgd # ifdef XCASE
318 1.1 cgd { "xcase", XCASE, M_LIN },
319 1.1 cgd # endif /* XCASE */
320 1.1 cgd # ifdef ECHO
321 1.1 cgd { "echo", ECHO, M_LIN },
322 1.1 cgd # endif /* ECHO */
323 1.1 cgd # ifdef ECHOE
324 1.1 cgd { "echoe", ECHOE, M_LIN },
325 1.1 cgd # endif /* ECHOE */
326 1.1 cgd # ifdef ECHOK
327 1.1 cgd { "echok", ECHOK, M_LIN },
328 1.1 cgd # endif /* ECHOK */
329 1.1 cgd # ifdef ECHONL
330 1.1 cgd { "echonl", ECHONL, M_LIN },
331 1.1 cgd # endif /* ECHONL */
332 1.1 cgd # ifdef NOFLSH
333 1.1 cgd { "noflsh", NOFLSH, M_LIN },
334 1.1 cgd # endif /* NOFLSH */
335 1.1 cgd # ifdef TOSTOP
336 1.1 cgd { "tostop", TOSTOP, M_LIN },
337 1.1 cgd # endif /* TOSTOP */
338 1.1 cgd # ifdef ECHOCTL
339 1.1 cgd { "echoctl",ECHOCTL,M_LIN },
340 1.1 cgd # endif /* ECHOCTL */
341 1.1 cgd # ifdef ECHOPRT
342 1.1 cgd { "echoprt",ECHOPRT,M_LIN },
343 1.1 cgd # endif /* ECHOPRT */
344 1.1 cgd # ifdef ECHOKE
345 1.1 cgd { "echoke", ECHOKE, M_LIN },
346 1.1 cgd # endif /* ECHOKE */
347 1.1 cgd # ifdef DEFECHO
348 1.1 cgd { "defecho",DEFECHO,M_LIN },
349 1.1 cgd # endif /* DEFECHO */
350 1.1 cgd # ifdef FLUSHO
351 1.1 cgd { "flusho", FLUSHO, M_LIN },
352 1.1 cgd # endif /* FLUSHO */
353 1.1 cgd # ifdef PENDIN
354 1.1 cgd { "pendin", PENDIN, M_LIN },
355 1.1 cgd # endif /* PENDIN */
356 1.1 cgd # ifdef IEXTEN
357 1.1 cgd { "iexten", IEXTEN, M_LIN },
358 1.1 cgd # endif /* IEXTEN */
359 1.1 cgd # ifdef NOKERNINFO
360 1.1 cgd { "nokerninfo",NOKERNINFO,M_LIN },
361 1.1 cgd # endif /* NOKERNINFO */
362 1.1 cgd # ifdef ALTWERASE
363 1.1 cgd { "altwerase",ALTWERASE,M_LIN },
364 1.1 cgd # endif /* ALTWERASE */
365 1.1 cgd # ifdef EXTPROC
366 1.1 cgd { "extproc",EXTPROC, M_LIN },
367 1.1 cgd # endif /* EXTPROC */
368 1.1 cgd
369 1.1 cgd # if defined(VINTR)
370 1.1 cgd { "intr", C_SH(C_INTR), M_CHAR },
371 1.1 cgd # endif /* VINTR */
372 1.1 cgd # if defined(VQUIT)
373 1.1 cgd { "quit", C_SH(C_QUIT), M_CHAR },
374 1.1 cgd # endif /* VQUIT */
375 1.1 cgd # if defined(VERASE)
376 1.1 cgd { "erase", C_SH(C_ERASE), M_CHAR },
377 1.1 cgd # endif /* VERASE */
378 1.1 cgd # if defined(VKILL)
379 1.1 cgd { "kill", C_SH(C_KILL), M_CHAR },
380 1.1 cgd # endif /* VKILL */
381 1.1 cgd # if defined(VEOF)
382 1.1 cgd { "eof", C_SH(C_EOF), M_CHAR },
383 1.1 cgd # endif /* VEOF */
384 1.1 cgd # if defined(VEOL)
385 1.1 cgd { "eol", C_SH(C_EOL), M_CHAR },
386 1.1 cgd # endif /* VEOL */
387 1.1 cgd # if defined(VEOL2)
388 1.1 cgd { "eol2", C_SH(C_EOL2), M_CHAR },
389 1.1 cgd # endif /* VEOL2 */
390 1.1 cgd # if defined(VSWTCH)
391 1.1 cgd { "swtch", C_SH(C_SWTCH), M_CHAR },
392 1.1 cgd # endif /* VSWTCH */
393 1.1 cgd # if defined(VDSWTCH)
394 1.1 cgd { "dswtch", C_SH(C_DSWTCH), M_CHAR },
395 1.1 cgd # endif /* VDSWTCH */
396 1.1 cgd # if defined(VERASE2)
397 1.1 cgd { "erase2", C_SH(C_ERASE2), M_CHAR },
398 1.1 cgd # endif /* VERASE2 */
399 1.1 cgd # if defined(VSTART)
400 1.1 cgd { "start", C_SH(C_START), M_CHAR },
401 1.1 cgd # endif /* VSTART */
402 1.1 cgd # if defined(VSTOP)
403 1.1 cgd { "stop", C_SH(C_STOP), M_CHAR },
404 1.1 cgd # endif /* VSTOP */
405 1.1 cgd # if defined(VWERASE)
406 1.1 cgd { "werase", C_SH(C_WERASE), M_CHAR },
407 1.1 cgd # endif /* VWERASE */
408 1.1 cgd # if defined(VSUSP)
409 1.1 cgd { "susp", C_SH(C_SUSP), M_CHAR },
410 1.1 cgd # endif /* VSUSP */
411 1.1 cgd # if defined(VDSUSP)
412 1.1 cgd { "dsusp", C_SH(C_DSUSP), M_CHAR },
413 1.1 cgd # endif /* VDSUSP */
414 1.1 cgd # if defined(VREPRINT)
415 1.1 cgd { "reprint", C_SH(C_REPRINT),M_CHAR },
416 1.1 cgd # endif /* VREPRINT */
417 1.1 cgd # if defined(VDISCARD)
418 1.1 cgd { "discard", C_SH(C_DISCARD),M_CHAR },
419 1.1 cgd # endif /* VDISCARD */
420 1.1 cgd # if defined(VLNEXT)
421 1.1 cgd { "lnext", C_SH(C_LNEXT), M_CHAR },
422 1.1 cgd # endif /* VLNEXT */
423 1.1 cgd # if defined(VSTATUS)
424 1.1 cgd { "status", C_SH(C_STATUS), M_CHAR },
425 1.1 cgd # endif /* VSTATUS */
426 1.1 cgd # if defined(VPAGE)
427 1.1 cgd { "page", C_SH(C_PAGE), M_CHAR },
428 1.1 cgd # endif /* VPAGE */
429 1.1 cgd # if defined(VPGOFF)
430 1.1 cgd { "pgoff", C_SH(C_PGOFF), M_CHAR },
431 1.1 cgd # endif /* VPGOFF */
432 1.1 cgd # if defined(VKILL2)
433 1.1 cgd { "kill2", C_SH(C_KILL2), M_CHAR },
434 1.1 cgd # endif /* VKILL2 */
435 1.1 cgd # if defined(VBRK)
436 1.1 cgd { "brk", C_SH(C_BRK), M_CHAR },
437 1.1 cgd # endif /* VBRK */
438 1.1 cgd # if defined(VMIN)
439 1.1 cgd { "min", C_SH(C_MIN), M_CHAR },
440 1.1 cgd # endif /* VMIN */
441 1.1 cgd # if defined(VTIME)
442 1.1 cgd { "time", C_SH(C_TIME), M_CHAR },
443 1.1 cgd # endif /* VTIME */
444 1.1 cgd { NULL, 0, -1 },
445 1.1 cgd };
446 1.1 cgd
447 1.1 cgd
448 1.1 cgd
449 1.1 cgd #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
450 1.1 cgd #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
451 1.1 cgd
452 1.1 cgd #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
453 1.1 cgd #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
454 1.1 cgd #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
455 1.1 cgd
456 1.1 cgd private void tty__getchar __P((struct termios *, unsigned char *));
457 1.1 cgd private void tty__setchar __P((struct termios *, unsigned char *));
458 1.1 cgd private speed_t tty__getspeed __P((struct termios *));
459 1.1 cgd private int tty_setup __P((EditLine *));
460 1.1 cgd
461 1.1 cgd #define t_qu t_ts
462 1.1 cgd
463 1.1 cgd
464 1.1 cgd /* tty_setup():
465 1.1 cgd * Get the tty parameters and initialize the editing state
466 1.1 cgd */
467 1.1 cgd private int
468 1.1 cgd tty_setup(el)
469 1.1 cgd EditLine *el;
470 1.1 cgd {
471 1.1 cgd int rst = 1;
472 1.1 cgd if (tty_getty(el, &el->el_tty.t_ed) == -1) {
473 1.1 cgd #ifdef DEBUG_TTY
474 1.1 cgd (void) fprintf(el->el_errfile,
475 1.1 cgd "tty_setup: tty_getty: %s\n", strerror(errno));
476 1.1 cgd #endif /* DEBUG_TTY */
477 1.1 cgd return(-1);
478 1.1 cgd }
479 1.1 cgd el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
480 1.1 cgd
481 1.1 cgd el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
482 1.1 cgd el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
483 1.1 cgd el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
484 1.1 cgd
485 1.1 cgd el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
486 1.1 cgd el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
487 1.1 cgd
488 1.1 cgd el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
489 1.1 cgd el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
490 1.1 cgd
491 1.1 cgd el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
492 1.1 cgd el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
493 1.1 cgd
494 1.1 cgd el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
495 1.1 cgd el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
496 1.1 cgd
497 1.1 cgd /*
498 1.1 cgd * Reset the tty chars to reasonable defaults
499 1.1 cgd * If they are disabled, then enable them.
500 1.1 cgd */
501 1.1 cgd if (rst) {
502 1.1 cgd if (tty__cooked_mode(&el->el_tty.t_ts)) {
503 1.1 cgd tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
504 1.1 cgd /*
505 1.1 cgd * Don't affect CMIN and CTIME for the editor mode
506 1.1 cgd */
507 1.1 cgd for (rst = 0; rst < C_NCC - 2; rst++)
508 1.1 cgd if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
509 1.1 cgd el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable)
510 1.1 cgd el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst];
511 1.1 cgd for (rst = 0; rst < C_NCC; rst++)
512 1.5 christos if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable)
513 1.1 cgd el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst];
514 1.1 cgd }
515 1.1 cgd tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
516 1.1 cgd if (tty_setty(el, &el->el_tty.t_ex) == -1) {
517 1.1 cgd #ifdef DEBUG_TTY
518 1.1 cgd (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
519 1.1 cgd strerror(errno));
520 1.1 cgd #endif /* DEBUG_TTY */
521 1.1 cgd return(-1);
522 1.1 cgd }
523 1.1 cgd }
524 1.1 cgd else
525 1.1 cgd tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
526 1.1 cgd
527 1.1 cgd el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
528 1.1 cgd el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
529 1.1 cgd
530 1.1 cgd el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
531 1.1 cgd el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
532 1.1 cgd
533 1.1 cgd el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
534 1.1 cgd el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
535 1.1 cgd
536 1.1 cgd el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
537 1.1 cgd el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
538 1.1 cgd
539 1.1 cgd tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
540 1.1 cgd return 0;
541 1.1 cgd }
542 1.1 cgd
543 1.1 cgd protected int
544 1.1 cgd tty_init(el)
545 1.1 cgd EditLine *el;
546 1.1 cgd {
547 1.1 cgd el->el_tty.t_mode = EX_IO;
548 1.1 cgd el->el_tty.t_vdisable = _POSIX_VDISABLE;
549 1.1 cgd (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
550 1.1 cgd (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
551 1.1 cgd return tty_setup(el);
552 1.1 cgd } /* end tty_init */
553 1.1 cgd
554 1.1 cgd
555 1.1 cgd /* tty_end():
556 1.1 cgd * Restore the tty to its original settings
557 1.1 cgd */
558 1.1 cgd protected void
559 1.1 cgd /*ARGSUSED*/
560 1.1 cgd tty_end(el)
561 1.1 cgd EditLine *el;
562 1.1 cgd {
563 1.1 cgd /* XXX: Maybe reset to an initial state? */
564 1.1 cgd }
565 1.1 cgd
566 1.1 cgd
567 1.1 cgd /* tty__getspeed():
568 1.1 cgd * Get the tty speed
569 1.1 cgd */
570 1.1 cgd private speed_t
571 1.1 cgd tty__getspeed(td)
572 1.1 cgd struct termios *td;
573 1.1 cgd {
574 1.1 cgd speed_t spd;
575 1.1 cgd
576 1.1 cgd if ((spd = cfgetispeed(td)) == 0)
577 1.1 cgd spd = cfgetospeed(td);
578 1.1 cgd return spd;
579 1.1 cgd } /* end tty__getspeed */
580 1.1 cgd
581 1.1 cgd
582 1.1 cgd /* tty__getchar():
583 1.1 cgd * Get the tty characters
584 1.1 cgd */
585 1.1 cgd private void
586 1.1 cgd tty__getchar(td, s)
587 1.1 cgd struct termios *td;
588 1.1 cgd unsigned char *s;
589 1.1 cgd {
590 1.1 cgd # ifdef VINTR
591 1.1 cgd s[C_INTR] = td->c_cc[VINTR];
592 1.1 cgd # endif /* VINTR */
593 1.1 cgd # ifdef VQUIT
594 1.1 cgd s[C_QUIT] = td->c_cc[VQUIT];
595 1.1 cgd # endif /* VQUIT */
596 1.1 cgd # ifdef VERASE
597 1.1 cgd s[C_ERASE] = td->c_cc[VERASE];
598 1.1 cgd # endif /* VERASE */
599 1.1 cgd # ifdef VKILL
600 1.1 cgd s[C_KILL] = td->c_cc[VKILL];
601 1.1 cgd # endif /* VKILL */
602 1.1 cgd # ifdef VEOF
603 1.1 cgd s[C_EOF] = td->c_cc[VEOF];
604 1.1 cgd # endif /* VEOF */
605 1.1 cgd # ifdef VEOL
606 1.1 cgd s[C_EOL] = td->c_cc[VEOL];
607 1.1 cgd # endif /* VEOL */
608 1.1 cgd # ifdef VEOL2
609 1.1 cgd s[C_EOL2] = td->c_cc[VEOL2];
610 1.1 cgd # endif /* VEOL2 */
611 1.1 cgd # ifdef VSWTCH
612 1.1 cgd s[C_SWTCH] = td->c_cc[VSWTCH];
613 1.1 cgd # endif /* VSWTCH */
614 1.1 cgd # ifdef VDSWTCH
615 1.1 cgd s[C_DSWTCH] = td->c_cc[VDSWTCH];
616 1.1 cgd # endif /* VDSWTCH */
617 1.1 cgd # ifdef VERASE2
618 1.1 cgd s[C_ERASE2] = td->c_cc[VERASE2];
619 1.1 cgd # endif /* VERASE2 */
620 1.1 cgd # ifdef VSTART
621 1.1 cgd s[C_START] = td->c_cc[VSTART];
622 1.1 cgd # endif /* VSTART */
623 1.1 cgd # ifdef VSTOP
624 1.1 cgd s[C_STOP] = td->c_cc[VSTOP];
625 1.1 cgd # endif /* VSTOP */
626 1.1 cgd # ifdef VWERASE
627 1.1 cgd s[C_WERASE] = td->c_cc[VWERASE];
628 1.1 cgd # endif /* VWERASE */
629 1.1 cgd # ifdef VSUSP
630 1.1 cgd s[C_SUSP] = td->c_cc[VSUSP];
631 1.1 cgd # endif /* VSUSP */
632 1.1 cgd # ifdef VDSUSP
633 1.1 cgd s[C_DSUSP] = td->c_cc[VDSUSP];
634 1.1 cgd # endif /* VDSUSP */
635 1.1 cgd # ifdef VREPRINT
636 1.1 cgd s[C_REPRINT]= td->c_cc[VREPRINT];
637 1.1 cgd # endif /* VREPRINT */
638 1.1 cgd # ifdef VDISCARD
639 1.1 cgd s[C_DISCARD]= td->c_cc[VDISCARD];
640 1.1 cgd # endif /* VDISCARD */
641 1.1 cgd # ifdef VLNEXT
642 1.1 cgd s[C_LNEXT] = td->c_cc[VLNEXT];
643 1.1 cgd # endif /* VLNEXT */
644 1.1 cgd # ifdef VSTATUS
645 1.1 cgd s[C_STATUS] = td->c_cc[VSTATUS];
646 1.1 cgd # endif /* VSTATUS */
647 1.1 cgd # ifdef VPAGE
648 1.1 cgd s[C_PAGE] = td->c_cc[VPAGE];
649 1.1 cgd # endif /* VPAGE */
650 1.1 cgd # ifdef VPGOFF
651 1.1 cgd s[C_PGOFF] = td->c_cc[VPGOFF];
652 1.1 cgd # endif /* VPGOFF */
653 1.1 cgd # ifdef VKILL2
654 1.1 cgd s[C_KILL2] = td->c_cc[VKILL2];
655 1.1 cgd # endif /* KILL2 */
656 1.1 cgd # ifdef VMIN
657 1.1 cgd s[C_MIN] = td->c_cc[VMIN];
658 1.1 cgd # endif /* VMIN */
659 1.1 cgd # ifdef VTIME
660 1.1 cgd s[C_TIME] = td->c_cc[VTIME];
661 1.1 cgd # endif /* VTIME */
662 1.1 cgd } /* tty__getchar */
663 1.1 cgd
664 1.1 cgd
665 1.1 cgd /* tty__setchar():
666 1.1 cgd * Set the tty characters
667 1.1 cgd */
668 1.1 cgd private void
669 1.1 cgd tty__setchar(td, s)
670 1.1 cgd struct termios *td;
671 1.1 cgd unsigned char *s;
672 1.1 cgd {
673 1.1 cgd # ifdef VINTR
674 1.1 cgd td->c_cc[VINTR] = s[C_INTR];
675 1.1 cgd # endif /* VINTR */
676 1.1 cgd # ifdef VQUIT
677 1.1 cgd td->c_cc[VQUIT] = s[C_QUIT];
678 1.1 cgd # endif /* VQUIT */
679 1.1 cgd # ifdef VERASE
680 1.1 cgd td->c_cc[VERASE] = s[C_ERASE];
681 1.1 cgd # endif /* VERASE */
682 1.1 cgd # ifdef VKILL
683 1.1 cgd td->c_cc[VKILL] = s[C_KILL];
684 1.1 cgd # endif /* VKILL */
685 1.1 cgd # ifdef VEOF
686 1.1 cgd td->c_cc[VEOF] = s[C_EOF];
687 1.1 cgd # endif /* VEOF */
688 1.1 cgd # ifdef VEOL
689 1.1 cgd td->c_cc[VEOL] = s[C_EOL];
690 1.1 cgd # endif /* VEOL */
691 1.1 cgd # ifdef VEOL2
692 1.1 cgd td->c_cc[VEOL2] = s[C_EOL2];
693 1.1 cgd # endif /* VEOL2 */
694 1.1 cgd # ifdef VSWTCH
695 1.1 cgd td->c_cc[VSWTCH] = s[C_SWTCH];
696 1.1 cgd # endif /* VSWTCH */
697 1.1 cgd # ifdef VDSWTCH
698 1.1 cgd td->c_cc[VDSWTCH] = s[C_DSWTCH];
699 1.1 cgd # endif /* VDSWTCH */
700 1.1 cgd # ifdef VERASE2
701 1.1 cgd td->c_cc[VERASE2] = s[C_ERASE2];
702 1.1 cgd # endif /* VERASE2 */
703 1.1 cgd # ifdef VSTART
704 1.1 cgd td->c_cc[VSTART] = s[C_START];
705 1.1 cgd # endif /* VSTART */
706 1.1 cgd # ifdef VSTOP
707 1.1 cgd td->c_cc[VSTOP] = s[C_STOP];
708 1.1 cgd # endif /* VSTOP */
709 1.1 cgd # ifdef VWERASE
710 1.1 cgd td->c_cc[VWERASE] = s[C_WERASE];
711 1.1 cgd # endif /* VWERASE */
712 1.1 cgd # ifdef VSUSP
713 1.1 cgd td->c_cc[VSUSP] = s[C_SUSP];
714 1.1 cgd # endif /* VSUSP */
715 1.1 cgd # ifdef VDSUSP
716 1.1 cgd td->c_cc[VDSUSP] = s[C_DSUSP];
717 1.1 cgd # endif /* VDSUSP */
718 1.1 cgd # ifdef VREPRINT
719 1.1 cgd td->c_cc[VREPRINT] = s[C_REPRINT];
720 1.1 cgd # endif /* VREPRINT */
721 1.1 cgd # ifdef VDISCARD
722 1.1 cgd td->c_cc[VDISCARD] = s[C_DISCARD];
723 1.1 cgd # endif /* VDISCARD */
724 1.1 cgd # ifdef VLNEXT
725 1.1 cgd td->c_cc[VLNEXT] = s[C_LNEXT];
726 1.1 cgd # endif /* VLNEXT */
727 1.1 cgd # ifdef VSTATUS
728 1.1 cgd td->c_cc[VSTATUS] = s[C_STATUS];
729 1.1 cgd # endif /* VSTATUS */
730 1.1 cgd # ifdef VPAGE
731 1.1 cgd td->c_cc[VPAGE] = s[C_PAGE];
732 1.1 cgd # endif /* VPAGE */
733 1.1 cgd # ifdef VPGOFF
734 1.1 cgd td->c_cc[VPGOFF] = s[C_PGOFF];
735 1.1 cgd # endif /* VPGOFF */
736 1.1 cgd # ifdef VKILL2
737 1.1 cgd td->c_cc[VKILL2] = s[C_KILL2];
738 1.1 cgd # endif /* VKILL2 */
739 1.1 cgd # ifdef VMIN
740 1.1 cgd td->c_cc[VMIN] = s[C_MIN];
741 1.1 cgd # endif /* VMIN */
742 1.1 cgd # ifdef VTIME
743 1.1 cgd td->c_cc[VTIME] = s[C_TIME];
744 1.1 cgd # endif /* VTIME */
745 1.1 cgd } /* tty__setchar */
746 1.1 cgd
747 1.1 cgd
748 1.1 cgd /* tty_bind_char():
749 1.1 cgd * Rebind the editline functions
750 1.1 cgd */
751 1.1 cgd protected void
752 1.1 cgd tty_bind_char(el, force)
753 1.1 cgd EditLine *el;
754 1.1 cgd int force;
755 1.1 cgd {
756 1.1 cgd unsigned char *t_n = el->el_tty.t_c[ED_IO];
757 1.1 cgd unsigned char *t_o = el->el_tty.t_ed.c_cc;
758 1.1 cgd char new[2], old[2];
759 1.1 cgd ttymap_t *tp;
760 1.1 cgd el_action_t *dmap, *dalt, *map, *alt;
761 1.1 cgd new[1] = old[1] = '\0';
762 1.1 cgd
763 1.1 cgd
764 1.1 cgd map = el->el_map.key;
765 1.1 cgd alt = el->el_map.alt;
766 1.1 cgd if (el->el_map.type == MAP_VI) {
767 1.1 cgd dmap = el->el_map.vii;
768 1.1 cgd dalt = el->el_map.vic;
769 1.1 cgd }
770 1.1 cgd else {
771 1.1 cgd dmap = el->el_map.emacs;
772 1.1 cgd dalt = NULL;
773 1.1 cgd }
774 1.1 cgd
775 1.1 cgd for (tp = tty_map; tp->nch != -1; tp++) {
776 1.1 cgd new[0] = t_n[tp->nch];
777 1.1 cgd old[0] = t_o[tp->och];
778 1.1 cgd if (new[0] == old[0] && !force)
779 1.1 cgd continue;
780 1.1 cgd /* Put the old default binding back, and set the new binding */
781 1.1 cgd key_clear(el, map, old);
782 1.1 cgd map[old[0]] = dmap[old[0]];
783 1.1 cgd key_clear(el, map, new);
784 1.1 cgd /* MAP_VI == 1, MAP_EMACS == 0... */
785 1.1 cgd map[new[0]] = tp->bind[el->el_map.type];
786 1.1 cgd if (dalt) {
787 1.1 cgd key_clear(el, alt, old);
788 1.1 cgd alt[old[0]] = dalt[old[0]];
789 1.1 cgd key_clear(el, alt, new);
790 1.1 cgd alt[new[0]] = tp->bind[el->el_map.type+1];
791 1.1 cgd }
792 1.1 cgd }
793 1.1 cgd }
794 1.1 cgd
795 1.1 cgd /* tty_rawmode():
796 1.1 cgd * Set terminal into 1 character at a time mode.
797 1.1 cgd */
798 1.1 cgd protected int
799 1.1 cgd tty_rawmode(el)
800 1.1 cgd EditLine *el;
801 1.1 cgd {
802 1.1 cgd if (el->el_tty.t_mode == ED_IO)
803 1.1 cgd return (0);
804 1.1 cgd
805 1.1 cgd if (tty_getty(el, &el->el_tty.t_ts) == -1) {
806 1.1 cgd #ifdef DEBUG_TTY
807 1.1 cgd (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
808 1.1 cgd #endif /* DEBUG_TTY */
809 1.1 cgd return(-1);
810 1.1 cgd }
811 1.1 cgd
812 1.1 cgd /*
813 1.1 cgd * We always keep up with the eight bit setting and the speed of the
814 1.1 cgd * tty. But only we only believe changes that are made to cooked mode!
815 1.1 cgd */
816 1.1 cgd el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
817 1.1 cgd el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
818 1.1 cgd
819 1.1 cgd if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
820 1.1 cgd tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
821 1.1 cgd (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
822 1.1 cgd (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
823 1.1 cgd (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
824 1.1 cgd (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
825 1.1 cgd }
826 1.1 cgd
827 1.1 cgd if (tty__cooked_mode(&el->el_tty.t_ts)) {
828 1.1 cgd if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
829 1.1 cgd el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag;
830 1.1 cgd el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
831 1.1 cgd el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
832 1.1 cgd
833 1.1 cgd el->el_tty.t_ed.c_cflag = el->el_tty.t_ts.c_cflag;
834 1.1 cgd el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
835 1.1 cgd el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
836 1.1 cgd }
837 1.1 cgd
838 1.1 cgd if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
839 1.1 cgd (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
840 1.1 cgd el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
841 1.1 cgd el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
842 1.1 cgd el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
843 1.1 cgd
844 1.1 cgd el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
845 1.1 cgd el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
846 1.1 cgd el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
847 1.1 cgd }
848 1.1 cgd
849 1.1 cgd if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
850 1.1 cgd (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
851 1.1 cgd el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
852 1.1 cgd el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
853 1.1 cgd el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
854 1.1 cgd
855 1.1 cgd el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
856 1.1 cgd el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
857 1.1 cgd el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
858 1.1 cgd }
859 1.1 cgd
860 1.1 cgd if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
861 1.1 cgd (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
862 1.1 cgd el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
863 1.1 cgd el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
864 1.1 cgd el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
865 1.1 cgd
866 1.1 cgd el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
867 1.1 cgd el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
868 1.1 cgd el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
869 1.1 cgd }
870 1.1 cgd
871 1.1 cgd if (tty__gettabs(&el->el_tty.t_ex) == 0)
872 1.1 cgd el->el_tty.t_tabs = 0;
873 1.1 cgd else
874 1.1 cgd el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
875 1.1 cgd
876 1.1 cgd {
877 1.1 cgd int i;
878 1.1 cgd
879 1.1 cgd tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
880 1.1 cgd /*
881 1.1 cgd * Check if the user made any changes.
882 1.1 cgd * If he did, then propagate the changes to the
883 1.1 cgd * edit and execute data structures.
884 1.1 cgd */
885 1.1 cgd for (i = 0; i < C_NCC; i++)
886 1.1 cgd if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
887 1.1 cgd break;
888 1.1 cgd
889 1.1 cgd if (i != C_NCC) {
890 1.1 cgd /*
891 1.1 cgd * Propagate changes only to the unprotected chars
892 1.1 cgd * that have been modified just now.
893 1.1 cgd */
894 1.1 cgd for (i = 0; i < C_NCC; i++) {
895 1.1 cgd if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i)))
896 1.1 cgd && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
897 1.1 cgd el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
898 1.1 cgd if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i))
899 1.1 cgd el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
900 1.1 cgd }
901 1.1 cgd tty_bind_char(el, 0);
902 1.1 cgd tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
903 1.1 cgd
904 1.1 cgd for (i = 0; i < C_NCC; i++) {
905 1.1 cgd if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i)))
906 1.1 cgd && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
907 1.1 cgd el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
908 1.1 cgd if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i))
909 1.1 cgd el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
910 1.1 cgd }
911 1.1 cgd tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
912 1.1 cgd }
913 1.1 cgd }
914 1.1 cgd }
915 1.1 cgd
916 1.1 cgd if (tty_setty(el, &el->el_tty.t_ed) == -1) {
917 1.1 cgd #ifdef DEBUG_TTY
918 1.1 cgd (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
919 1.1 cgd strerror(errno));
920 1.1 cgd #endif /* DEBUG_TTY */
921 1.1 cgd return -1;
922 1.1 cgd }
923 1.1 cgd el->el_tty.t_mode = ED_IO;
924 1.1 cgd return (0);
925 1.1 cgd } /* end tty_rawmode */
926 1.1 cgd
927 1.1 cgd
928 1.1 cgd /* tty_cookedmode():
929 1.1 cgd * Set the tty back to normal mode
930 1.1 cgd */
931 1.1 cgd protected int
932 1.1 cgd tty_cookedmode(el)
933 1.1 cgd EditLine *el;
934 1.1 cgd { /* set tty in normal setup */
935 1.1 cgd if (el->el_tty.t_mode == EX_IO)
936 1.1 cgd return (0);
937 1.1 cgd
938 1.1 cgd if (tty_setty(el, &el->el_tty.t_ex) == -1) {
939 1.1 cgd #ifdef DEBUG_TTY
940 1.1 cgd (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
941 1.1 cgd strerror(errno));
942 1.1 cgd #endif /* DEBUG_TTY */
943 1.1 cgd return -1;
944 1.1 cgd }
945 1.1 cgd el->el_tty.t_mode = EX_IO;
946 1.1 cgd return (0);
947 1.1 cgd } /* end tty_cookedmode */
948 1.1 cgd
949 1.1 cgd
950 1.1 cgd /* tty_quotemode():
951 1.1 cgd * Turn on quote mode
952 1.1 cgd */
953 1.1 cgd protected int
954 1.1 cgd tty_quotemode(el)
955 1.1 cgd EditLine *el;
956 1.1 cgd {
957 1.1 cgd if (el->el_tty.t_mode == QU_IO)
958 1.1 cgd return 0;
959 1.1 cgd
960 1.1 cgd el->el_tty.t_qu = el->el_tty.t_ed;
961 1.1 cgd
962 1.1 cgd el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask;
963 1.1 cgd el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][M_INP].t_setmask;
964 1.1 cgd
965 1.1 cgd el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask;
966 1.1 cgd el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][M_OUT].t_setmask;
967 1.1 cgd
968 1.1 cgd el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask;
969 1.1 cgd el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][M_CTL].t_setmask;
970 1.1 cgd
971 1.1 cgd el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask;
972 1.1 cgd el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][M_LIN].t_setmask;
973 1.1 cgd
974 1.1 cgd if (tty_setty(el, &el->el_tty.t_qu) == -1) {
975 1.1 cgd #ifdef DEBUG_TTY
976 1.1 cgd (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
977 1.1 cgd strerror(errno));
978 1.1 cgd #endif /* DEBUG_TTY */
979 1.1 cgd return -1;
980 1.1 cgd }
981 1.1 cgd el->el_tty.t_mode = QU_IO;
982 1.1 cgd return 0;
983 1.1 cgd } /* end tty_quotemode */
984 1.1 cgd
985 1.1 cgd
986 1.1 cgd /* tty_noquotemode():
987 1.1 cgd * Turn off quote mode
988 1.1 cgd */
989 1.1 cgd protected int
990 1.1 cgd tty_noquotemode(el)
991 1.1 cgd EditLine *el;
992 1.1 cgd {
993 1.1 cgd if (el->el_tty.t_mode != QU_IO)
994 1.1 cgd return 0;
995 1.1 cgd if (tty_setty(el, &el->el_tty.t_ed) == -1) {
996 1.1 cgd #ifdef DEBUG_TTY
997 1.1 cgd (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
998 1.1 cgd strerror(errno));
999 1.1 cgd #endif /* DEBUG_TTY */
1000 1.1 cgd return -1;
1001 1.1 cgd }
1002 1.1 cgd el->el_tty.t_mode = ED_IO;
1003 1.1 cgd return 0;
1004 1.1 cgd }
1005 1.1 cgd
1006 1.1 cgd /* tty_stty():
1007 1.1 cgd * Stty builtin
1008 1.1 cgd */
1009 1.1 cgd protected int
1010 1.1 cgd /*ARGSUSED*/
1011 1.1 cgd tty_stty(el, argc, argv)
1012 1.1 cgd EditLine *el;
1013 1.1 cgd int argc;
1014 1.1 cgd char **argv;
1015 1.1 cgd {
1016 1.1 cgd ttymodes_t *m;
1017 1.1 cgd char x, *d;
1018 1.1 cgd int aflag = 0;
1019 1.1 cgd char *s;
1020 1.1 cgd char *name;
1021 1.1 cgd int z = EX_IO;
1022 1.1 cgd
1023 1.1 cgd if (argv == NULL)
1024 1.1 cgd return -1;
1025 1.1 cgd name = *argv++;
1026 1.1 cgd
1027 1.1 cgd while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1028 1.1 cgd switch (argv[0][1]) {
1029 1.1 cgd case 'a':
1030 1.1 cgd aflag++;
1031 1.1 cgd argv++;
1032 1.1 cgd break;
1033 1.1 cgd case 'd':
1034 1.1 cgd argv++;
1035 1.1 cgd z = ED_IO;
1036 1.1 cgd break;
1037 1.1 cgd case 'x':
1038 1.1 cgd argv++;
1039 1.1 cgd z = EX_IO;
1040 1.1 cgd break;
1041 1.1 cgd case 'q':
1042 1.1 cgd argv++;
1043 1.1 cgd z = QU_IO;
1044 1.1 cgd break;
1045 1.1 cgd default:
1046 1.1 cgd (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
1047 1.1 cgd name, argv[0][1]);
1048 1.1 cgd return -1;
1049 1.1 cgd }
1050 1.1 cgd
1051 1.1 cgd if (!argv || !*argv) {
1052 1.1 cgd int i = -1;
1053 1.1 cgd int len = 0, st = 0, cu;
1054 1.1 cgd for (m = ttymodes; m->m_name; m++) {
1055 1.1 cgd if (m->m_type != i) {
1056 1.1 cgd (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
1057 1.1 cgd el->el_tty.t_t[z][m->m_type].t_name);
1058 1.1 cgd i = m->m_type;
1059 1.1 cgd st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
1060 1.1 cgd }
1061 1.1 cgd
1062 1.1 cgd x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
1063 1.1 cgd x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
1064 1.1 cgd
1065 1.1 cgd if (x != '\0' || aflag) {
1066 1.1 cgd
1067 1.1 cgd cu = strlen(m->m_name) + (x != '\0') + 1;
1068 1.1 cgd
1069 1.1 cgd if (len + cu >= el->el_term.t_size.h) {
1070 1.1 cgd (void) fprintf(el->el_outfile, "\n%*s", st, "");
1071 1.1 cgd len = st + cu;
1072 1.1 cgd }
1073 1.1 cgd else
1074 1.1 cgd len += cu;
1075 1.1 cgd
1076 1.1 cgd if (x != '\0')
1077 1.1 cgd (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
1078 1.1 cgd else
1079 1.1 cgd (void) fprintf(el->el_outfile, "%s ", m->m_name);
1080 1.1 cgd }
1081 1.1 cgd }
1082 1.1 cgd (void) fprintf(el->el_outfile, "\n");
1083 1.1 cgd return 0;
1084 1.1 cgd }
1085 1.1 cgd
1086 1.1 cgd while (argv && (s = *argv++)) {
1087 1.1 cgd switch (*s) {
1088 1.1 cgd case '+':
1089 1.1 cgd case '-':
1090 1.1 cgd x = *s++;
1091 1.1 cgd break;
1092 1.1 cgd default:
1093 1.1 cgd x = '\0';
1094 1.1 cgd break;
1095 1.1 cgd }
1096 1.1 cgd d = s;
1097 1.1 cgd for (m = ttymodes; m->m_name; m++)
1098 1.1 cgd if (strcmp(m->m_name, d) == 0)
1099 1.1 cgd break;
1100 1.1 cgd
1101 1.1 cgd if (!m->m_name) {
1102 1.1 cgd (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
1103 1.1 cgd name, d);
1104 1.1 cgd return -1;
1105 1.1 cgd }
1106 1.1 cgd
1107 1.1 cgd switch (x) {
1108 1.1 cgd case '+':
1109 1.1 cgd el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1110 1.1 cgd el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1111 1.1 cgd break;
1112 1.1 cgd case '-':
1113 1.1 cgd el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1114 1.1 cgd el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1115 1.1 cgd break;
1116 1.1 cgd default:
1117 1.1 cgd el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1118 1.1 cgd el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1119 1.1 cgd break;
1120 1.1 cgd }
1121 1.1 cgd }
1122 1.1 cgd return 0;
1123 1.1 cgd } /* end tty_stty */
1124 1.1 cgd
1125 1.1 cgd
1126 1.1 cgd #ifdef notyet
1127 1.1 cgd /* tty_printchar():
1128 1.1 cgd * DEbugging routine to print the tty characters
1129 1.1 cgd */
1130 1.1 cgd private void
1131 1.1 cgd tty_printchar(el, s)
1132 1.1 cgd EditLine *el;
1133 1.1 cgd unsigned char *s;
1134 1.1 cgd {
1135 1.1 cgd ttyperm_t *m;
1136 1.1 cgd int i;
1137 1.1 cgd
1138 1.1 cgd for (i = 0; i < C_NCC; i++) {
1139 1.1 cgd for (m = el->el_tty.t_t; m->m_name; m++)
1140 1.1 cgd if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
1141 1.1 cgd break;
1142 1.1 cgd if (m->m_name)
1143 1.1 cgd (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
1144 1.1 cgd if (i % 5 == 0)
1145 1.1 cgd (void) fprintf(el->el_errfile, "\n");
1146 1.1 cgd }
1147 1.1 cgd (void) fprintf(el->el_errfile, "\n");
1148 1.1 cgd }
1149 1.1 cgd #endif /* notyet */
1150