1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek *
6eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek *
10eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek */
18eda6f593SDavid van Moolenbroek
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek
21eda6f593SDavid van Moolenbroek #ifdef HAVE_CURSES_H
22eda6f593SDavid van Moolenbroek #include <curses.h>
23eda6f593SDavid van Moolenbroek #else
24eda6f593SDavid van Moolenbroek #include <ncurses.h>
25eda6f593SDavid van Moolenbroek #endif
26eda6f593SDavid van Moolenbroek #include <fnmatch.h>
27eda6f593SDavid van Moolenbroek #include <stdlib.h>
28eda6f593SDavid van Moolenbroek #include <string.h>
29eda6f593SDavid van Moolenbroek #include <term.h>
30eda6f593SDavid van Moolenbroek
31eda6f593SDavid van Moolenbroek #include "tmux.h"
32eda6f593SDavid van Moolenbroek
33eda6f593SDavid van Moolenbroek void tty_term_override(struct tty_term *, const char *);
34eda6f593SDavid van Moolenbroek char *tty_term_strip(const char *);
35eda6f593SDavid van Moolenbroek
36eda6f593SDavid van Moolenbroek struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms);
37eda6f593SDavid van Moolenbroek
38eda6f593SDavid van Moolenbroek const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
39eda6f593SDavid van Moolenbroek { TTYC_ACSC, TTYCODE_STRING, "acsc" },
40eda6f593SDavid van Moolenbroek { TTYC_AX, TTYCODE_FLAG, "AX" },
41eda6f593SDavid van Moolenbroek { TTYC_BEL, TTYCODE_STRING, "bel" },
42eda6f593SDavid van Moolenbroek { TTYC_BLINK, TTYCODE_STRING, "blink" },
43eda6f593SDavid van Moolenbroek { TTYC_BOLD, TTYCODE_STRING, "bold" },
44eda6f593SDavid van Moolenbroek { TTYC_CIVIS, TTYCODE_STRING, "civis" },
45eda6f593SDavid van Moolenbroek { TTYC_CLEAR, TTYCODE_STRING, "clear" },
46eda6f593SDavid van Moolenbroek { TTYC_CNORM, TTYCODE_STRING, "cnorm" },
47eda6f593SDavid van Moolenbroek { TTYC_COLORS, TTYCODE_NUMBER, "colors" },
48eda6f593SDavid van Moolenbroek { TTYC_CR, TTYCODE_STRING, "Cr" },
49*0a6a1f1dSLionel Sambuc { TTYC_CS, TTYCODE_STRING, "Cs" },
50eda6f593SDavid van Moolenbroek { TTYC_CSR, TTYCODE_STRING, "csr" },
51eda6f593SDavid van Moolenbroek { TTYC_CUB, TTYCODE_STRING, "cub" },
52eda6f593SDavid van Moolenbroek { TTYC_CUB1, TTYCODE_STRING, "cub1" },
53eda6f593SDavid van Moolenbroek { TTYC_CUD, TTYCODE_STRING, "cud" },
54eda6f593SDavid van Moolenbroek { TTYC_CUD1, TTYCODE_STRING, "cud1" },
55eda6f593SDavid van Moolenbroek { TTYC_CUF, TTYCODE_STRING, "cuf" },
56eda6f593SDavid van Moolenbroek { TTYC_CUF1, TTYCODE_STRING, "cuf1" },
57eda6f593SDavid van Moolenbroek { TTYC_CUP, TTYCODE_STRING, "cup" },
58eda6f593SDavid van Moolenbroek { TTYC_CUU, TTYCODE_STRING, "cuu" },
59eda6f593SDavid van Moolenbroek { TTYC_CUU1, TTYCODE_STRING, "cuu1" },
60eda6f593SDavid van Moolenbroek { TTYC_DCH, TTYCODE_STRING, "dch" },
61eda6f593SDavid van Moolenbroek { TTYC_DCH1, TTYCODE_STRING, "dch1" },
62eda6f593SDavid van Moolenbroek { TTYC_DIM, TTYCODE_STRING, "dim" },
63eda6f593SDavid van Moolenbroek { TTYC_DL, TTYCODE_STRING, "dl" },
64eda6f593SDavid van Moolenbroek { TTYC_DL1, TTYCODE_STRING, "dl1" },
65*0a6a1f1dSLionel Sambuc { TTYC_E3, TTYCODE_STRING, "E3" },
66*0a6a1f1dSLionel Sambuc { TTYC_ECH, TTYCODE_STRING, "ech" },
67eda6f593SDavid van Moolenbroek { TTYC_EL, TTYCODE_STRING, "el" },
68eda6f593SDavid van Moolenbroek { TTYC_EL1, TTYCODE_STRING, "el1" },
69eda6f593SDavid van Moolenbroek { TTYC_ENACS, TTYCODE_STRING, "enacs" },
70eda6f593SDavid van Moolenbroek { TTYC_FSL, TTYCODE_STRING, "fsl" },
71eda6f593SDavid van Moolenbroek { TTYC_HOME, TTYCODE_STRING, "home" },
72eda6f593SDavid van Moolenbroek { TTYC_HPA, TTYCODE_STRING, "hpa" },
73eda6f593SDavid van Moolenbroek { TTYC_ICH, TTYCODE_STRING, "ich" },
74eda6f593SDavid van Moolenbroek { TTYC_ICH1, TTYCODE_STRING, "ich1" },
75eda6f593SDavid van Moolenbroek { TTYC_IL, TTYCODE_STRING, "il" },
76eda6f593SDavid van Moolenbroek { TTYC_IL1, TTYCODE_STRING, "il1" },
77eda6f593SDavid van Moolenbroek { TTYC_INVIS, TTYCODE_STRING, "invis" },
78eda6f593SDavid van Moolenbroek { TTYC_IS1, TTYCODE_STRING, "is1" },
79eda6f593SDavid van Moolenbroek { TTYC_IS2, TTYCODE_STRING, "is2" },
80eda6f593SDavid van Moolenbroek { TTYC_IS3, TTYCODE_STRING, "is3" },
81eda6f593SDavid van Moolenbroek { TTYC_KCBT, TTYCODE_STRING, "kcbt" },
82eda6f593SDavid van Moolenbroek { TTYC_KCUB1, TTYCODE_STRING, "kcub1" },
83eda6f593SDavid van Moolenbroek { TTYC_KCUD1, TTYCODE_STRING, "kcud1" },
84eda6f593SDavid van Moolenbroek { TTYC_KCUF1, TTYCODE_STRING, "kcuf1" },
85eda6f593SDavid van Moolenbroek { TTYC_KCUU1, TTYCODE_STRING, "kcuu1" },
86eda6f593SDavid van Moolenbroek { TTYC_KDC2, TTYCODE_STRING, "kDC" },
87eda6f593SDavid van Moolenbroek { TTYC_KDC3, TTYCODE_STRING, "kDC3" },
88eda6f593SDavid van Moolenbroek { TTYC_KDC4, TTYCODE_STRING, "kDC4" },
89eda6f593SDavid van Moolenbroek { TTYC_KDC5, TTYCODE_STRING, "kDC5" },
90eda6f593SDavid van Moolenbroek { TTYC_KDC6, TTYCODE_STRING, "kDC6" },
91eda6f593SDavid van Moolenbroek { TTYC_KDC7, TTYCODE_STRING, "kDC7" },
92eda6f593SDavid van Moolenbroek { TTYC_KDCH1, TTYCODE_STRING, "kdch1" },
93eda6f593SDavid van Moolenbroek { TTYC_KDN2, TTYCODE_STRING, "kDN" },
94eda6f593SDavid van Moolenbroek { TTYC_KDN3, TTYCODE_STRING, "kDN3" },
95eda6f593SDavid van Moolenbroek { TTYC_KDN4, TTYCODE_STRING, "kDN4" },
96eda6f593SDavid van Moolenbroek { TTYC_KDN5, TTYCODE_STRING, "kDN5" },
97eda6f593SDavid van Moolenbroek { TTYC_KDN6, TTYCODE_STRING, "kDN6" },
98eda6f593SDavid van Moolenbroek { TTYC_KDN7, TTYCODE_STRING, "kDN7" },
99eda6f593SDavid van Moolenbroek { TTYC_KEND, TTYCODE_STRING, "kend" },
100eda6f593SDavid van Moolenbroek { TTYC_KEND2, TTYCODE_STRING, "kEND" },
101eda6f593SDavid van Moolenbroek { TTYC_KEND3, TTYCODE_STRING, "kEND3" },
102eda6f593SDavid van Moolenbroek { TTYC_KEND4, TTYCODE_STRING, "kEND4" },
103eda6f593SDavid van Moolenbroek { TTYC_KEND5, TTYCODE_STRING, "kEND5" },
104eda6f593SDavid van Moolenbroek { TTYC_KEND6, TTYCODE_STRING, "kEND6" },
105eda6f593SDavid van Moolenbroek { TTYC_KEND7, TTYCODE_STRING, "kEND7" },
106eda6f593SDavid van Moolenbroek { TTYC_KF1, TTYCODE_STRING, "kf1" },
107eda6f593SDavid van Moolenbroek { TTYC_KF10, TTYCODE_STRING, "kf10" },
108eda6f593SDavid van Moolenbroek { TTYC_KF11, TTYCODE_STRING, "kf11" },
109eda6f593SDavid van Moolenbroek { TTYC_KF12, TTYCODE_STRING, "kf12" },
110eda6f593SDavid van Moolenbroek { TTYC_KF13, TTYCODE_STRING, "kf13" },
111eda6f593SDavid van Moolenbroek { TTYC_KF14, TTYCODE_STRING, "kf14" },
112eda6f593SDavid van Moolenbroek { TTYC_KF15, TTYCODE_STRING, "kf15" },
113eda6f593SDavid van Moolenbroek { TTYC_KF16, TTYCODE_STRING, "kf16" },
114eda6f593SDavid van Moolenbroek { TTYC_KF17, TTYCODE_STRING, "kf17" },
115eda6f593SDavid van Moolenbroek { TTYC_KF18, TTYCODE_STRING, "kf18" },
116eda6f593SDavid van Moolenbroek { TTYC_KF19, TTYCODE_STRING, "kf19" },
117eda6f593SDavid van Moolenbroek { TTYC_KF2, TTYCODE_STRING, "kf2" },
118eda6f593SDavid van Moolenbroek { TTYC_KF20, TTYCODE_STRING, "kf20" },
119eda6f593SDavid van Moolenbroek { TTYC_KF3, TTYCODE_STRING, "kf3" },
120eda6f593SDavid van Moolenbroek { TTYC_KF4, TTYCODE_STRING, "kf4" },
121eda6f593SDavid van Moolenbroek { TTYC_KF5, TTYCODE_STRING, "kf5" },
122eda6f593SDavid van Moolenbroek { TTYC_KF6, TTYCODE_STRING, "kf6" },
123eda6f593SDavid van Moolenbroek { TTYC_KF7, TTYCODE_STRING, "kf7" },
124eda6f593SDavid van Moolenbroek { TTYC_KF8, TTYCODE_STRING, "kf8" },
125eda6f593SDavid van Moolenbroek { TTYC_KF9, TTYCODE_STRING, "kf9" },
126eda6f593SDavid van Moolenbroek { TTYC_KHOM2, TTYCODE_STRING, "kHOM" },
127eda6f593SDavid van Moolenbroek { TTYC_KHOM3, TTYCODE_STRING, "kHOM3" },
128eda6f593SDavid van Moolenbroek { TTYC_KHOM4, TTYCODE_STRING, "kHOM4" },
129eda6f593SDavid van Moolenbroek { TTYC_KHOM5, TTYCODE_STRING, "kHOM5" },
130eda6f593SDavid van Moolenbroek { TTYC_KHOM6, TTYCODE_STRING, "kHOM6" },
131eda6f593SDavid van Moolenbroek { TTYC_KHOM7, TTYCODE_STRING, "kHOM7" },
132eda6f593SDavid van Moolenbroek { TTYC_KHOME, TTYCODE_STRING, "khome" },
133eda6f593SDavid van Moolenbroek { TTYC_KIC2, TTYCODE_STRING, "kIC" },
134eda6f593SDavid van Moolenbroek { TTYC_KIC3, TTYCODE_STRING, "kIC3" },
135eda6f593SDavid van Moolenbroek { TTYC_KIC4, TTYCODE_STRING, "kIC4" },
136eda6f593SDavid van Moolenbroek { TTYC_KIC5, TTYCODE_STRING, "kIC5" },
137eda6f593SDavid van Moolenbroek { TTYC_KIC6, TTYCODE_STRING, "kIC6" },
138eda6f593SDavid van Moolenbroek { TTYC_KIC7, TTYCODE_STRING, "kIC7" },
139eda6f593SDavid van Moolenbroek { TTYC_KICH1, TTYCODE_STRING, "kich1" },
140eda6f593SDavid van Moolenbroek { TTYC_KLFT2, TTYCODE_STRING, "kLFT" },
141eda6f593SDavid van Moolenbroek { TTYC_KLFT3, TTYCODE_STRING, "kLFT3" },
142eda6f593SDavid van Moolenbroek { TTYC_KLFT4, TTYCODE_STRING, "kLFT4" },
143eda6f593SDavid van Moolenbroek { TTYC_KLFT5, TTYCODE_STRING, "kLFT5" },
144eda6f593SDavid van Moolenbroek { TTYC_KLFT6, TTYCODE_STRING, "kLFT6" },
145eda6f593SDavid van Moolenbroek { TTYC_KLFT7, TTYCODE_STRING, "kLFT7" },
146eda6f593SDavid van Moolenbroek { TTYC_KMOUS, TTYCODE_STRING, "kmous" },
147eda6f593SDavid van Moolenbroek { TTYC_KNP, TTYCODE_STRING, "knp" },
148eda6f593SDavid van Moolenbroek { TTYC_KNXT2, TTYCODE_STRING, "kNXT" },
149eda6f593SDavid van Moolenbroek { TTYC_KNXT3, TTYCODE_STRING, "kNXT3" },
150eda6f593SDavid van Moolenbroek { TTYC_KNXT4, TTYCODE_STRING, "kNXT4" },
151eda6f593SDavid van Moolenbroek { TTYC_KNXT5, TTYCODE_STRING, "kNXT5" },
152eda6f593SDavid van Moolenbroek { TTYC_KNXT6, TTYCODE_STRING, "kNXT6" },
153eda6f593SDavid van Moolenbroek { TTYC_KNXT7, TTYCODE_STRING, "kNXT7" },
154eda6f593SDavid van Moolenbroek { TTYC_KPP, TTYCODE_STRING, "kpp" },
155eda6f593SDavid van Moolenbroek { TTYC_KPRV2, TTYCODE_STRING, "kPRV" },
156eda6f593SDavid van Moolenbroek { TTYC_KPRV3, TTYCODE_STRING, "kPRV3" },
157eda6f593SDavid van Moolenbroek { TTYC_KPRV4, TTYCODE_STRING, "kPRV4" },
158eda6f593SDavid van Moolenbroek { TTYC_KPRV5, TTYCODE_STRING, "kPRV5" },
159eda6f593SDavid van Moolenbroek { TTYC_KPRV6, TTYCODE_STRING, "kPRV6" },
160eda6f593SDavid van Moolenbroek { TTYC_KPRV7, TTYCODE_STRING, "kPRV7" },
161eda6f593SDavid van Moolenbroek { TTYC_KRIT2, TTYCODE_STRING, "kRIT" },
162eda6f593SDavid van Moolenbroek { TTYC_KRIT3, TTYCODE_STRING, "kRIT3" },
163eda6f593SDavid van Moolenbroek { TTYC_KRIT4, TTYCODE_STRING, "kRIT4" },
164eda6f593SDavid van Moolenbroek { TTYC_KRIT5, TTYCODE_STRING, "kRIT5" },
165eda6f593SDavid van Moolenbroek { TTYC_KRIT6, TTYCODE_STRING, "kRIT6" },
166eda6f593SDavid van Moolenbroek { TTYC_KRIT7, TTYCODE_STRING, "kRIT7" },
167eda6f593SDavid van Moolenbroek { TTYC_KUP2, TTYCODE_STRING, "kUP" },
168eda6f593SDavid van Moolenbroek { TTYC_KUP3, TTYCODE_STRING, "kUP3" },
169eda6f593SDavid van Moolenbroek { TTYC_KUP4, TTYCODE_STRING, "kUP4" },
170eda6f593SDavid van Moolenbroek { TTYC_KUP5, TTYCODE_STRING, "kUP5" },
171eda6f593SDavid van Moolenbroek { TTYC_KUP6, TTYCODE_STRING, "kUP6" },
172eda6f593SDavid van Moolenbroek { TTYC_KUP7, TTYCODE_STRING, "kUP7" },
173eda6f593SDavid van Moolenbroek { TTYC_MS, TTYCODE_STRING, "Ms" },
174eda6f593SDavid van Moolenbroek { TTYC_OP, TTYCODE_STRING, "op" },
175eda6f593SDavid van Moolenbroek { TTYC_REV, TTYCODE_STRING, "rev" },
176eda6f593SDavid van Moolenbroek { TTYC_RI, TTYCODE_STRING, "ri" },
177eda6f593SDavid van Moolenbroek { TTYC_RMACS, TTYCODE_STRING, "rmacs" },
178eda6f593SDavid van Moolenbroek { TTYC_RMCUP, TTYCODE_STRING, "rmcup" },
179eda6f593SDavid van Moolenbroek { TTYC_RMKX, TTYCODE_STRING, "rmkx" },
180*0a6a1f1dSLionel Sambuc { TTYC_SE, TTYCODE_STRING, "Se" },
181eda6f593SDavid van Moolenbroek { TTYC_SETAB, TTYCODE_STRING, "setab" },
182eda6f593SDavid van Moolenbroek { TTYC_SETAF, TTYCODE_STRING, "setaf" },
183eda6f593SDavid van Moolenbroek { TTYC_SGR0, TTYCODE_STRING, "sgr0" },
184eda6f593SDavid van Moolenbroek { TTYC_SITM, TTYCODE_STRING, "sitm" },
185eda6f593SDavid van Moolenbroek { TTYC_SMACS, TTYCODE_STRING, "smacs" },
186eda6f593SDavid van Moolenbroek { TTYC_SMCUP, TTYCODE_STRING, "smcup" },
187eda6f593SDavid van Moolenbroek { TTYC_SMKX, TTYCODE_STRING, "smkx" },
188eda6f593SDavid van Moolenbroek { TTYC_SMSO, TTYCODE_STRING, "smso" },
189eda6f593SDavid van Moolenbroek { TTYC_SMUL, TTYCODE_STRING, "smul" },
190*0a6a1f1dSLionel Sambuc { TTYC_SS, TTYCODE_STRING, "Ss" },
191eda6f593SDavid van Moolenbroek { TTYC_TSL, TTYCODE_STRING, "tsl" },
192eda6f593SDavid van Moolenbroek { TTYC_VPA, TTYCODE_STRING, "vpa" },
193eda6f593SDavid van Moolenbroek { TTYC_XENL, TTYCODE_FLAG, "xenl" },
194eda6f593SDavid van Moolenbroek { TTYC_XT, TTYCODE_FLAG, "XT" },
195eda6f593SDavid van Moolenbroek };
196eda6f593SDavid van Moolenbroek
197eda6f593SDavid van Moolenbroek char *
tty_term_strip(const char * s)198eda6f593SDavid van Moolenbroek tty_term_strip(const char *s)
199eda6f593SDavid van Moolenbroek {
200eda6f593SDavid van Moolenbroek const char *ptr;
201eda6f593SDavid van Moolenbroek static char buf[BUFSIZ];
202eda6f593SDavid van Moolenbroek size_t len;
203eda6f593SDavid van Moolenbroek
204eda6f593SDavid van Moolenbroek /* Ignore strings with no padding. */
205eda6f593SDavid van Moolenbroek if (strchr(s, '$') == NULL)
206eda6f593SDavid van Moolenbroek return (xstrdup(s));
207eda6f593SDavid van Moolenbroek
208eda6f593SDavid van Moolenbroek len = 0;
209eda6f593SDavid van Moolenbroek for (ptr = s; *ptr != '\0'; ptr++) {
210eda6f593SDavid van Moolenbroek if (*ptr == '$' && *(ptr + 1) == '<') {
211eda6f593SDavid van Moolenbroek while (*ptr != '\0' && *ptr != '>')
212eda6f593SDavid van Moolenbroek ptr++;
213eda6f593SDavid van Moolenbroek if (*ptr == '>')
214eda6f593SDavid van Moolenbroek ptr++;
215eda6f593SDavid van Moolenbroek }
216eda6f593SDavid van Moolenbroek
217eda6f593SDavid van Moolenbroek buf[len++] = *ptr;
218eda6f593SDavid van Moolenbroek if (len == (sizeof buf) - 1)
219eda6f593SDavid van Moolenbroek break;
220eda6f593SDavid van Moolenbroek }
221eda6f593SDavid van Moolenbroek buf[len] = '\0';
222eda6f593SDavid van Moolenbroek
223eda6f593SDavid van Moolenbroek return (xstrdup(buf));
224eda6f593SDavid van Moolenbroek }
225eda6f593SDavid van Moolenbroek
226eda6f593SDavid van Moolenbroek void
tty_term_override(struct tty_term * term,const char * overrides)227eda6f593SDavid van Moolenbroek tty_term_override(struct tty_term *term, const char *overrides)
228eda6f593SDavid van Moolenbroek {
229eda6f593SDavid van Moolenbroek const struct tty_term_code_entry *ent;
230eda6f593SDavid van Moolenbroek struct tty_code *code;
231eda6f593SDavid van Moolenbroek char *termnext, *termstr;
232eda6f593SDavid van Moolenbroek char *entnext, *entstr;
233eda6f593SDavid van Moolenbroek char *s, *ptr, *val;
234eda6f593SDavid van Moolenbroek const char *errstr;
235eda6f593SDavid van Moolenbroek u_int i;
236eda6f593SDavid van Moolenbroek int n, removeflag;
237eda6f593SDavid van Moolenbroek
238eda6f593SDavid van Moolenbroek s = xstrdup(overrides);
239eda6f593SDavid van Moolenbroek
240eda6f593SDavid van Moolenbroek termnext = s;
241eda6f593SDavid van Moolenbroek while ((termstr = strsep(&termnext, ",")) != NULL) {
242eda6f593SDavid van Moolenbroek entnext = termstr;
243eda6f593SDavid van Moolenbroek
244eda6f593SDavid van Moolenbroek entstr = strsep(&entnext, ":");
245eda6f593SDavid van Moolenbroek if (entstr == NULL || entnext == NULL)
246eda6f593SDavid van Moolenbroek continue;
247eda6f593SDavid van Moolenbroek if (fnmatch(entstr, term->name, 0) != 0)
248eda6f593SDavid van Moolenbroek continue;
249eda6f593SDavid van Moolenbroek while ((entstr = strsep(&entnext, ":")) != NULL) {
250eda6f593SDavid van Moolenbroek if (*entstr == '\0')
251eda6f593SDavid van Moolenbroek continue;
252eda6f593SDavid van Moolenbroek
253eda6f593SDavid van Moolenbroek val = NULL;
254eda6f593SDavid van Moolenbroek removeflag = 0;
255eda6f593SDavid van Moolenbroek if ((ptr = strchr(entstr, '=')) != NULL) {
256eda6f593SDavid van Moolenbroek *ptr++ = '\0';
257eda6f593SDavid van Moolenbroek val = xstrdup(ptr);
258eda6f593SDavid van Moolenbroek if (strunvis(val, ptr) == -1) {
259*0a6a1f1dSLionel Sambuc free(val);
260eda6f593SDavid van Moolenbroek val = xstrdup(ptr);
261eda6f593SDavid van Moolenbroek }
262eda6f593SDavid van Moolenbroek } else if (entstr[strlen(entstr) - 1] == '@') {
263eda6f593SDavid van Moolenbroek entstr[strlen(entstr) - 1] = '\0';
264eda6f593SDavid van Moolenbroek removeflag = 1;
265eda6f593SDavid van Moolenbroek } else
266eda6f593SDavid van Moolenbroek val = xstrdup("");
267eda6f593SDavid van Moolenbroek
268*0a6a1f1dSLionel Sambuc log_debug("%s override: %s %s",
269*0a6a1f1dSLionel Sambuc term->name, entstr, removeflag ? "@" : val);
270eda6f593SDavid van Moolenbroek for (i = 0; i < NTTYCODE; i++) {
271eda6f593SDavid van Moolenbroek ent = &tty_term_codes[i];
272eda6f593SDavid van Moolenbroek if (strcmp(entstr, ent->name) != 0)
273eda6f593SDavid van Moolenbroek continue;
274eda6f593SDavid van Moolenbroek code = &term->codes[ent->code];
275eda6f593SDavid van Moolenbroek
276eda6f593SDavid van Moolenbroek if (removeflag) {
277eda6f593SDavid van Moolenbroek code->type = TTYCODE_NONE;
278eda6f593SDavid van Moolenbroek continue;
279eda6f593SDavid van Moolenbroek }
280eda6f593SDavid van Moolenbroek switch (ent->type) {
281eda6f593SDavid van Moolenbroek case TTYCODE_NONE:
282eda6f593SDavid van Moolenbroek break;
283eda6f593SDavid van Moolenbroek case TTYCODE_STRING:
284eda6f593SDavid van Moolenbroek if (code->type == TTYCODE_STRING)
285*0a6a1f1dSLionel Sambuc free(code->value.string);
286eda6f593SDavid van Moolenbroek code->value.string = xstrdup(val);
287eda6f593SDavid van Moolenbroek code->type = ent->type;
288eda6f593SDavid van Moolenbroek break;
289eda6f593SDavid van Moolenbroek case TTYCODE_NUMBER:
290eda6f593SDavid van Moolenbroek n = strtonum(val, 0, INT_MAX, &errstr);
291eda6f593SDavid van Moolenbroek if (errstr != NULL)
292eda6f593SDavid van Moolenbroek break;
293eda6f593SDavid van Moolenbroek code->value.number = n;
294eda6f593SDavid van Moolenbroek code->type = ent->type;
295eda6f593SDavid van Moolenbroek break;
296eda6f593SDavid van Moolenbroek case TTYCODE_FLAG:
297eda6f593SDavid van Moolenbroek code->value.flag = 1;
298eda6f593SDavid van Moolenbroek code->type = ent->type;
299eda6f593SDavid van Moolenbroek break;
300eda6f593SDavid van Moolenbroek }
301eda6f593SDavid van Moolenbroek }
302eda6f593SDavid van Moolenbroek
303*0a6a1f1dSLionel Sambuc free(val);
304eda6f593SDavid van Moolenbroek }
305eda6f593SDavid van Moolenbroek }
306eda6f593SDavid van Moolenbroek
307*0a6a1f1dSLionel Sambuc free(s);
308eda6f593SDavid van Moolenbroek }
309eda6f593SDavid van Moolenbroek
310eda6f593SDavid van Moolenbroek struct tty_term *
tty_term_find(char * name,int fd,const char * overrides,char ** cause)311eda6f593SDavid van Moolenbroek tty_term_find(char *name, int fd, const char *overrides, char **cause)
312eda6f593SDavid van Moolenbroek {
313eda6f593SDavid van Moolenbroek struct tty_term *term;
314eda6f593SDavid van Moolenbroek const struct tty_term_code_entry *ent;
315eda6f593SDavid van Moolenbroek struct tty_code *code;
316eda6f593SDavid van Moolenbroek u_int i;
317eda6f593SDavid van Moolenbroek int n, error;
318eda6f593SDavid van Moolenbroek char *s;
319eda6f593SDavid van Moolenbroek const char *acs;
320eda6f593SDavid van Moolenbroek
321eda6f593SDavid van Moolenbroek LIST_FOREACH(term, &tty_terms, entry) {
322eda6f593SDavid van Moolenbroek if (strcmp(term->name, name) == 0) {
323eda6f593SDavid van Moolenbroek term->references++;
324eda6f593SDavid van Moolenbroek return (term);
325eda6f593SDavid van Moolenbroek }
326eda6f593SDavid van Moolenbroek }
327eda6f593SDavid van Moolenbroek
328eda6f593SDavid van Moolenbroek log_debug("new term: %s", name);
329eda6f593SDavid van Moolenbroek term = xmalloc(sizeof *term);
330eda6f593SDavid van Moolenbroek term->name = xstrdup(name);
331eda6f593SDavid van Moolenbroek term->references = 1;
332eda6f593SDavid van Moolenbroek term->flags = 0;
333eda6f593SDavid van Moolenbroek memset(term->codes, 0, sizeof term->codes);
334eda6f593SDavid van Moolenbroek LIST_INSERT_HEAD(&tty_terms, term, entry);
335eda6f593SDavid van Moolenbroek
336eda6f593SDavid van Moolenbroek /* Set up curses terminal. */
337eda6f593SDavid van Moolenbroek if (setupterm(name, fd, &error) != OK) {
338eda6f593SDavid van Moolenbroek switch (error) {
339eda6f593SDavid van Moolenbroek case 1:
340eda6f593SDavid van Moolenbroek xasprintf(
341eda6f593SDavid van Moolenbroek cause, "can't use hardcopy terminal: %s", name);
342eda6f593SDavid van Moolenbroek break;
343eda6f593SDavid van Moolenbroek case 0:
344eda6f593SDavid van Moolenbroek xasprintf(
345eda6f593SDavid van Moolenbroek cause, "missing or unsuitable terminal: %s", name);
346eda6f593SDavid van Moolenbroek break;
347eda6f593SDavid van Moolenbroek case -1:
348eda6f593SDavid van Moolenbroek xasprintf(cause, "can't find terminfo database");
349eda6f593SDavid van Moolenbroek break;
350eda6f593SDavid van Moolenbroek default:
351eda6f593SDavid van Moolenbroek xasprintf(cause, "unknown error");
352eda6f593SDavid van Moolenbroek break;
353eda6f593SDavid van Moolenbroek }
354eda6f593SDavid van Moolenbroek goto error;
355eda6f593SDavid van Moolenbroek }
356eda6f593SDavid van Moolenbroek
357eda6f593SDavid van Moolenbroek /* Fill in codes. */
358eda6f593SDavid van Moolenbroek for (i = 0; i < NTTYCODE; i++) {
359eda6f593SDavid van Moolenbroek ent = &tty_term_codes[i];
360eda6f593SDavid van Moolenbroek
361eda6f593SDavid van Moolenbroek code = &term->codes[ent->code];
362eda6f593SDavid van Moolenbroek code->type = TTYCODE_NONE;
363eda6f593SDavid van Moolenbroek switch (ent->type) {
364eda6f593SDavid van Moolenbroek case TTYCODE_NONE:
365eda6f593SDavid van Moolenbroek break;
366eda6f593SDavid van Moolenbroek case TTYCODE_STRING:
367eda6f593SDavid van Moolenbroek s = tigetstr(ent->name);
368eda6f593SDavid van Moolenbroek if (s == NULL || s == (char *) -1)
369eda6f593SDavid van Moolenbroek break;
370eda6f593SDavid van Moolenbroek code->type = TTYCODE_STRING;
371eda6f593SDavid van Moolenbroek code->value.string = tty_term_strip(s);
372eda6f593SDavid van Moolenbroek break;
373eda6f593SDavid van Moolenbroek case TTYCODE_NUMBER:
374eda6f593SDavid van Moolenbroek n = tigetnum(ent->name);
375eda6f593SDavid van Moolenbroek if (n == -1 || n == -2)
376eda6f593SDavid van Moolenbroek break;
377eda6f593SDavid van Moolenbroek code->type = TTYCODE_NUMBER;
378eda6f593SDavid van Moolenbroek code->value.number = n;
379eda6f593SDavid van Moolenbroek break;
380eda6f593SDavid van Moolenbroek case TTYCODE_FLAG:
381eda6f593SDavid van Moolenbroek n = tigetflag(ent->name);
382eda6f593SDavid van Moolenbroek if (n == -1)
383eda6f593SDavid van Moolenbroek break;
384eda6f593SDavid van Moolenbroek code->type = TTYCODE_FLAG;
385eda6f593SDavid van Moolenbroek code->value.number = n;
386eda6f593SDavid van Moolenbroek break;
387eda6f593SDavid van Moolenbroek }
388eda6f593SDavid van Moolenbroek }
389eda6f593SDavid van Moolenbroek tty_term_override(term, overrides);
390eda6f593SDavid van Moolenbroek
391eda6f593SDavid van Moolenbroek /* Delete curses data. */
392*0a6a1f1dSLionel Sambuc #if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
393*0a6a1f1dSLionel Sambuc (NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6)
394eda6f593SDavid van Moolenbroek del_curterm(cur_term);
395eda6f593SDavid van Moolenbroek #endif
396eda6f593SDavid van Moolenbroek
397eda6f593SDavid van Moolenbroek /* These are always required. */
398eda6f593SDavid van Moolenbroek if (!tty_term_has(term, TTYC_CLEAR)) {
399eda6f593SDavid van Moolenbroek xasprintf(cause, "terminal does not support clear");
400eda6f593SDavid van Moolenbroek goto error;
401eda6f593SDavid van Moolenbroek }
402eda6f593SDavid van Moolenbroek if (!tty_term_has(term, TTYC_CUP)) {
403eda6f593SDavid van Moolenbroek xasprintf(cause, "terminal does not support cup");
404eda6f593SDavid van Moolenbroek goto error;
405eda6f593SDavid van Moolenbroek }
406eda6f593SDavid van Moolenbroek
407eda6f593SDavid van Moolenbroek /* These can be emulated so one of the two is required. */
408eda6f593SDavid van Moolenbroek if (!tty_term_has(term, TTYC_CUD1) && !tty_term_has(term, TTYC_CUD)) {
409eda6f593SDavid van Moolenbroek xasprintf(cause, "terminal does not support cud1 or cud");
410eda6f593SDavid van Moolenbroek goto error;
411eda6f593SDavid van Moolenbroek }
412eda6f593SDavid van Moolenbroek
413*0a6a1f1dSLionel Sambuc /* Figure out if we have 256. */
414eda6f593SDavid van Moolenbroek if (tty_term_number(term, TTYC_COLORS) == 256)
415eda6f593SDavid van Moolenbroek term->flags |= TERM_256COLOURS;
416eda6f593SDavid van Moolenbroek
417eda6f593SDavid van Moolenbroek /*
418eda6f593SDavid van Moolenbroek * Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1
419eda6f593SDavid van Moolenbroek * rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1).
420eda6f593SDavid van Moolenbroek *
421eda6f593SDavid van Moolenbroek * This is irritating, most notably because it is impossible to write
422eda6f593SDavid van Moolenbroek * to the very bottom-right of the screen without scrolling.
423eda6f593SDavid van Moolenbroek *
424eda6f593SDavid van Moolenbroek * Flag the terminal here and apply some workarounds in other places to
425eda6f593SDavid van Moolenbroek * do the best possible.
426eda6f593SDavid van Moolenbroek */
427eda6f593SDavid van Moolenbroek if (!tty_term_flag(term, TTYC_XENL))
428eda6f593SDavid van Moolenbroek term->flags |= TERM_EARLYWRAP;
429eda6f593SDavid van Moolenbroek
430eda6f593SDavid van Moolenbroek /* Generate ACS table. If none is present, use nearest ASCII. */
431eda6f593SDavid van Moolenbroek memset(term->acs, 0, sizeof term->acs);
432eda6f593SDavid van Moolenbroek if (tty_term_has(term, TTYC_ACSC))
433eda6f593SDavid van Moolenbroek acs = tty_term_string(term, TTYC_ACSC);
434eda6f593SDavid van Moolenbroek else
435eda6f593SDavid van Moolenbroek acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~.";
436eda6f593SDavid van Moolenbroek for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
437eda6f593SDavid van Moolenbroek term->acs[(u_char) acs[0]][0] = acs[1];
438eda6f593SDavid van Moolenbroek
439eda6f593SDavid van Moolenbroek /* On terminals with xterm titles (XT), fill in tsl and fsl. */
440eda6f593SDavid van Moolenbroek if (tty_term_flag(term, TTYC_XT) &&
441eda6f593SDavid van Moolenbroek !tty_term_has(term, TTYC_TSL) &&
442eda6f593SDavid van Moolenbroek !tty_term_has(term, TTYC_FSL)) {
443eda6f593SDavid van Moolenbroek code = &term->codes[TTYC_TSL];
444eda6f593SDavid van Moolenbroek code->value.string = xstrdup("\033]0;");
445eda6f593SDavid van Moolenbroek code->type = TTYCODE_STRING;
446eda6f593SDavid van Moolenbroek code = &term->codes[TTYC_FSL];
447eda6f593SDavid van Moolenbroek code->value.string = xstrdup("\007");
448eda6f593SDavid van Moolenbroek code->type = TTYCODE_STRING;
449eda6f593SDavid van Moolenbroek }
450eda6f593SDavid van Moolenbroek
451eda6f593SDavid van Moolenbroek return (term);
452eda6f593SDavid van Moolenbroek
453eda6f593SDavid van Moolenbroek error:
454eda6f593SDavid van Moolenbroek tty_term_free(term);
455eda6f593SDavid van Moolenbroek return (NULL);
456eda6f593SDavid van Moolenbroek }
457eda6f593SDavid van Moolenbroek
458eda6f593SDavid van Moolenbroek void
tty_term_free(struct tty_term * term)459eda6f593SDavid van Moolenbroek tty_term_free(struct tty_term *term)
460eda6f593SDavid van Moolenbroek {
461eda6f593SDavid van Moolenbroek u_int i;
462eda6f593SDavid van Moolenbroek
463eda6f593SDavid van Moolenbroek if (--term->references != 0)
464eda6f593SDavid van Moolenbroek return;
465eda6f593SDavid van Moolenbroek
466eda6f593SDavid van Moolenbroek LIST_REMOVE(term, entry);
467eda6f593SDavid van Moolenbroek
468eda6f593SDavid van Moolenbroek for (i = 0; i < NTTYCODE; i++) {
469eda6f593SDavid van Moolenbroek if (term->codes[i].type == TTYCODE_STRING)
470*0a6a1f1dSLionel Sambuc free(term->codes[i].value.string);
471eda6f593SDavid van Moolenbroek }
472*0a6a1f1dSLionel Sambuc free(term->name);
473*0a6a1f1dSLionel Sambuc free(term);
474eda6f593SDavid van Moolenbroek }
475eda6f593SDavid van Moolenbroek
476eda6f593SDavid van Moolenbroek int
tty_term_has(struct tty_term * term,enum tty_code_code code)477eda6f593SDavid van Moolenbroek tty_term_has(struct tty_term *term, enum tty_code_code code)
478eda6f593SDavid van Moolenbroek {
479eda6f593SDavid van Moolenbroek return (term->codes[code].type != TTYCODE_NONE);
480eda6f593SDavid van Moolenbroek }
481eda6f593SDavid van Moolenbroek
482eda6f593SDavid van Moolenbroek const char *
tty_term_string(struct tty_term * term,enum tty_code_code code)483eda6f593SDavid van Moolenbroek tty_term_string(struct tty_term *term, enum tty_code_code code)
484eda6f593SDavid van Moolenbroek {
485eda6f593SDavid van Moolenbroek if (!tty_term_has(term, code))
486eda6f593SDavid van Moolenbroek return ("");
487eda6f593SDavid van Moolenbroek if (term->codes[code].type != TTYCODE_STRING)
488eda6f593SDavid van Moolenbroek log_fatalx("not a string: %d", code);
489eda6f593SDavid van Moolenbroek return (term->codes[code].value.string);
490eda6f593SDavid van Moolenbroek }
491eda6f593SDavid van Moolenbroek
492eda6f593SDavid van Moolenbroek /* No vtparm. Fucking curses. */
493eda6f593SDavid van Moolenbroek const char *
tty_term_string1(struct tty_term * term,enum tty_code_code code,int a)494eda6f593SDavid van Moolenbroek tty_term_string1(struct tty_term *term, enum tty_code_code code, int a)
495eda6f593SDavid van Moolenbroek {
496eda6f593SDavid van Moolenbroek return (tparm(tty_term_string(term, code), a, 0, 0, 0, 0, 0, 0, 0, 0));
497eda6f593SDavid van Moolenbroek }
498eda6f593SDavid van Moolenbroek
499eda6f593SDavid van Moolenbroek const char *
tty_term_string2(struct tty_term * term,enum tty_code_code code,int a,int b)500eda6f593SDavid van Moolenbroek tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
501eda6f593SDavid van Moolenbroek {
502eda6f593SDavid van Moolenbroek return (tparm(tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
503eda6f593SDavid van Moolenbroek }
504eda6f593SDavid van Moolenbroek
505eda6f593SDavid van Moolenbroek const char *
tty_term_ptr1(struct tty_term * term,enum tty_code_code code,const void * a)506eda6f593SDavid van Moolenbroek tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
507eda6f593SDavid van Moolenbroek {
508*0a6a1f1dSLionel Sambuc return (tparm(tty_term_string(term, code), (intptr_t)a, 0, 0, 0, 0, 0, 0, 0, 0));
509eda6f593SDavid van Moolenbroek }
510eda6f593SDavid van Moolenbroek
511eda6f593SDavid van Moolenbroek const char *
tty_term_ptr2(struct tty_term * term,enum tty_code_code code,const void * a,const void * b)512eda6f593SDavid van Moolenbroek tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b)
513eda6f593SDavid van Moolenbroek {
514*0a6a1f1dSLionel Sambuc return (tparm(tty_term_string(term, code), (intptr_t)a, (intptr_t)b, 0, 0, 0, 0, 0, 0, 0));
515eda6f593SDavid van Moolenbroek }
516eda6f593SDavid van Moolenbroek
517eda6f593SDavid van Moolenbroek int
tty_term_number(struct tty_term * term,enum tty_code_code code)518eda6f593SDavid van Moolenbroek tty_term_number(struct tty_term *term, enum tty_code_code code)
519eda6f593SDavid van Moolenbroek {
520eda6f593SDavid van Moolenbroek if (!tty_term_has(term, code))
521eda6f593SDavid van Moolenbroek return (0);
522eda6f593SDavid van Moolenbroek if (term->codes[code].type != TTYCODE_NUMBER)
523eda6f593SDavid van Moolenbroek log_fatalx("not a number: %d", code);
524eda6f593SDavid van Moolenbroek return (term->codes[code].value.number);
525eda6f593SDavid van Moolenbroek }
526eda6f593SDavid van Moolenbroek
527eda6f593SDavid van Moolenbroek int
tty_term_flag(struct tty_term * term,enum tty_code_code code)528eda6f593SDavid van Moolenbroek tty_term_flag(struct tty_term *term, enum tty_code_code code)
529eda6f593SDavid van Moolenbroek {
530eda6f593SDavid van Moolenbroek if (!tty_term_has(term, code))
531eda6f593SDavid van Moolenbroek return (0);
532eda6f593SDavid van Moolenbroek if (term->codes[code].type != TTYCODE_FLAG)
533eda6f593SDavid van Moolenbroek log_fatalx("not a flag: %d", code);
534eda6f593SDavid van Moolenbroek return (term->codes[code].value.flag);
535eda6f593SDavid van Moolenbroek }
536