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