1*527d0d53Snicm /* $OpenBSD: tty-term.c,v 1.102 2024/08/26 13:02:15 nicm Exp $ */ 2311827fbSnicm 3311827fbSnicm /* 498ca8272Snicm * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> 5311827fbSnicm * 6311827fbSnicm * Permission to use, copy, modify, and distribute this software for any 7311827fbSnicm * purpose with or without fee is hereby granted, provided that the above 8311827fbSnicm * copyright notice and this permission notice appear in all copies. 9311827fbSnicm * 10311827fbSnicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11311827fbSnicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12311827fbSnicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13311827fbSnicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14311827fbSnicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15311827fbSnicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16311827fbSnicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17311827fbSnicm */ 18311827fbSnicm 19311827fbSnicm #include <sys/types.h> 20311827fbSnicm 2191b93a69Snicm #include <curses.h> 225e07382cSnicm #include <fnmatch.h> 235e07382cSnicm #include <stdlib.h> 24311827fbSnicm #include <string.h> 25311827fbSnicm #include <term.h> 265e07382cSnicm #include <vis.h> 27311827fbSnicm 28311827fbSnicm #include "tmux.h" 29311827fbSnicm 309883b791Snicm static char *tty_term_strip(const char *); 31311827fbSnicm 320a271d7eSnicm struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms); 33311827fbSnicm 34361fb91cSnicm enum tty_code_type { 35361fb91cSnicm TTYCODE_NONE = 0, 36361fb91cSnicm TTYCODE_STRING, 37361fb91cSnicm TTYCODE_NUMBER, 38361fb91cSnicm TTYCODE_FLAG, 39311827fbSnicm }; 40311827fbSnicm 41361fb91cSnicm struct tty_code { 42361fb91cSnicm enum tty_code_type type; 43361fb91cSnicm union { 44361fb91cSnicm char *string; 45361fb91cSnicm int number; 46361fb91cSnicm int flag; 47361fb91cSnicm } value; 48361fb91cSnicm }; 49361fb91cSnicm 50361fb91cSnicm struct tty_term_code_entry { 51361fb91cSnicm enum tty_code_type type; 52361fb91cSnicm const char *name; 53361fb91cSnicm }; 54361fb91cSnicm 559883b791Snicm static const struct tty_term_code_entry tty_term_codes[] = { 56361fb91cSnicm [TTYC_ACSC] = { TTYCODE_STRING, "acsc" }, 57e636b826Snicm [TTYC_AM] = { TTYCODE_FLAG, "am" }, 58361fb91cSnicm [TTYC_AX] = { TTYCODE_FLAG, "AX" }, 59361fb91cSnicm [TTYC_BCE] = { TTYCODE_FLAG, "bce" }, 60361fb91cSnicm [TTYC_BEL] = { TTYCODE_STRING, "bel" }, 619a569e26Snicm [TTYC_BIDI] = { TTYCODE_STRING, "Bidi" }, 62361fb91cSnicm [TTYC_BLINK] = { TTYCODE_STRING, "blink" }, 63361fb91cSnicm [TTYC_BOLD] = { TTYCODE_STRING, "bold" }, 64361fb91cSnicm [TTYC_CIVIS] = { TTYCODE_STRING, "civis" }, 65361fb91cSnicm [TTYC_CLEAR] = { TTYCODE_STRING, "clear" }, 666763df04Snicm [TTYC_CLMG] = { TTYCODE_STRING, "Clmg" }, 676763df04Snicm [TTYC_CMG] = { TTYCODE_STRING, "Cmg" }, 68361fb91cSnicm [TTYC_CNORM] = { TTYCODE_STRING, "cnorm" }, 69361fb91cSnicm [TTYC_COLORS] = { TTYCODE_NUMBER, "colors" }, 70361fb91cSnicm [TTYC_CR] = { TTYCODE_STRING, "Cr" }, 71361fb91cSnicm [TTYC_CSR] = { TTYCODE_STRING, "csr" }, 7201cf4cccSnicm [TTYC_CS] = { TTYCODE_STRING, "Cs" }, 73361fb91cSnicm [TTYC_CUB1] = { TTYCODE_STRING, "cub1" }, 7401cf4cccSnicm [TTYC_CUB] = { TTYCODE_STRING, "cub" }, 75361fb91cSnicm [TTYC_CUD1] = { TTYCODE_STRING, "cud1" }, 7601cf4cccSnicm [TTYC_CUD] = { TTYCODE_STRING, "cud" }, 77361fb91cSnicm [TTYC_CUF1] = { TTYCODE_STRING, "cuf1" }, 7801cf4cccSnicm [TTYC_CUF] = { TTYCODE_STRING, "cuf" }, 79361fb91cSnicm [TTYC_CUP] = { TTYCODE_STRING, "cup" }, 80361fb91cSnicm [TTYC_CUU1] = { TTYCODE_STRING, "cuu1" }, 8101cf4cccSnicm [TTYC_CUU] = { TTYCODE_STRING, "cuu" }, 82361fb91cSnicm [TTYC_CVVIS] = { TTYCODE_STRING, "cvvis" }, 83361fb91cSnicm [TTYC_DCH1] = { TTYCODE_STRING, "dch1" }, 8401cf4cccSnicm [TTYC_DCH] = { TTYCODE_STRING, "dch" }, 85361fb91cSnicm [TTYC_DIM] = { TTYCODE_STRING, "dim" }, 86361fb91cSnicm [TTYC_DL1] = { TTYCODE_STRING, "dl1" }, 8701cf4cccSnicm [TTYC_DL] = { TTYCODE_STRING, "dl" }, 88dcf80b09Snicm [TTYC_DSEKS] = { TTYCODE_STRING, "Dseks" }, 89ed2e005dSnicm [TTYC_DSFCS] = { TTYCODE_STRING, "Dsfcs" }, 9080bd3d52Snicm [TTYC_DSBP] = { TTYCODE_STRING, "Dsbp" }, 916763df04Snicm [TTYC_DSMG] = { TTYCODE_STRING, "Dsmg" }, 92361fb91cSnicm [TTYC_E3] = { TTYCODE_STRING, "E3" }, 93361fb91cSnicm [TTYC_ECH] = { TTYCODE_STRING, "ech" }, 940bb7045cSnicm [TTYC_ED] = { TTYCODE_STRING, "ed" }, 95361fb91cSnicm [TTYC_EL1] = { TTYCODE_STRING, "el1" }, 9601cf4cccSnicm [TTYC_EL] = { TTYCODE_STRING, "el" }, 97361fb91cSnicm [TTYC_ENACS] = { TTYCODE_STRING, "enacs" }, 9880bd3d52Snicm [TTYC_ENBP] = { TTYCODE_STRING, "Enbp" }, 99dcf80b09Snicm [TTYC_ENEKS] = { TTYCODE_STRING, "Eneks" }, 100ed2e005dSnicm [TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" }, 1016763df04Snicm [TTYC_ENMG] = { TTYCODE_STRING, "Enmg" }, 102361fb91cSnicm [TTYC_FSL] = { TTYCODE_STRING, "fsl" }, 1032df6775cSnicm [TTYC_HLS] = { TTYCODE_STRING, "Hls" }, 104361fb91cSnicm [TTYC_HOME] = { TTYCODE_STRING, "home" }, 105361fb91cSnicm [TTYC_HPA] = { TTYCODE_STRING, "hpa" }, 106361fb91cSnicm [TTYC_ICH1] = { TTYCODE_STRING, "ich1" }, 10701cf4cccSnicm [TTYC_ICH] = { TTYCODE_STRING, "ich" }, 108361fb91cSnicm [TTYC_IL1] = { TTYCODE_STRING, "il1" }, 10901cf4cccSnicm [TTYC_IL] = { TTYCODE_STRING, "il" }, 110f0063641Snicm [TTYC_INDN] = { TTYCODE_STRING, "indn" }, 111361fb91cSnicm [TTYC_INVIS] = { TTYCODE_STRING, "invis" }, 112361fb91cSnicm [TTYC_KCBT] = { TTYCODE_STRING, "kcbt" }, 113361fb91cSnicm [TTYC_KCUB1] = { TTYCODE_STRING, "kcub1" }, 114361fb91cSnicm [TTYC_KCUD1] = { TTYCODE_STRING, "kcud1" }, 115361fb91cSnicm [TTYC_KCUF1] = { TTYCODE_STRING, "kcuf1" }, 116361fb91cSnicm [TTYC_KCUU1] = { TTYCODE_STRING, "kcuu1" }, 117361fb91cSnicm [TTYC_KDC2] = { TTYCODE_STRING, "kDC" }, 118361fb91cSnicm [TTYC_KDC3] = { TTYCODE_STRING, "kDC3" }, 119361fb91cSnicm [TTYC_KDC4] = { TTYCODE_STRING, "kDC4" }, 120361fb91cSnicm [TTYC_KDC5] = { TTYCODE_STRING, "kDC5" }, 121361fb91cSnicm [TTYC_KDC6] = { TTYCODE_STRING, "kDC6" }, 122361fb91cSnicm [TTYC_KDC7] = { TTYCODE_STRING, "kDC7" }, 123361fb91cSnicm [TTYC_KDCH1] = { TTYCODE_STRING, "kdch1" }, 12401cf4cccSnicm [TTYC_KDN2] = { TTYCODE_STRING, "kDN" }, /* not kDN2 */ 125361fb91cSnicm [TTYC_KDN3] = { TTYCODE_STRING, "kDN3" }, 126361fb91cSnicm [TTYC_KDN4] = { TTYCODE_STRING, "kDN4" }, 127361fb91cSnicm [TTYC_KDN5] = { TTYCODE_STRING, "kDN5" }, 128361fb91cSnicm [TTYC_KDN6] = { TTYCODE_STRING, "kDN6" }, 129361fb91cSnicm [TTYC_KDN7] = { TTYCODE_STRING, "kDN7" }, 130361fb91cSnicm [TTYC_KEND2] = { TTYCODE_STRING, "kEND" }, 131361fb91cSnicm [TTYC_KEND3] = { TTYCODE_STRING, "kEND3" }, 132361fb91cSnicm [TTYC_KEND4] = { TTYCODE_STRING, "kEND4" }, 133361fb91cSnicm [TTYC_KEND5] = { TTYCODE_STRING, "kEND5" }, 134361fb91cSnicm [TTYC_KEND6] = { TTYCODE_STRING, "kEND6" }, 135361fb91cSnicm [TTYC_KEND7] = { TTYCODE_STRING, "kEND7" }, 13601cf4cccSnicm [TTYC_KEND] = { TTYCODE_STRING, "kend" }, 137361fb91cSnicm [TTYC_KF10] = { TTYCODE_STRING, "kf10" }, 138361fb91cSnicm [TTYC_KF11] = { TTYCODE_STRING, "kf11" }, 139361fb91cSnicm [TTYC_KF12] = { TTYCODE_STRING, "kf12" }, 140361fb91cSnicm [TTYC_KF13] = { TTYCODE_STRING, "kf13" }, 141361fb91cSnicm [TTYC_KF14] = { TTYCODE_STRING, "kf14" }, 142361fb91cSnicm [TTYC_KF15] = { TTYCODE_STRING, "kf15" }, 143361fb91cSnicm [TTYC_KF16] = { TTYCODE_STRING, "kf16" }, 144361fb91cSnicm [TTYC_KF17] = { TTYCODE_STRING, "kf17" }, 145361fb91cSnicm [TTYC_KF18] = { TTYCODE_STRING, "kf18" }, 146361fb91cSnicm [TTYC_KF19] = { TTYCODE_STRING, "kf19" }, 14701cf4cccSnicm [TTYC_KF1] = { TTYCODE_STRING, "kf1" }, 148361fb91cSnicm [TTYC_KF20] = { TTYCODE_STRING, "kf20" }, 149361fb91cSnicm [TTYC_KF21] = { TTYCODE_STRING, "kf21" }, 150361fb91cSnicm [TTYC_KF22] = { TTYCODE_STRING, "kf22" }, 151361fb91cSnicm [TTYC_KF23] = { TTYCODE_STRING, "kf23" }, 152361fb91cSnicm [TTYC_KF24] = { TTYCODE_STRING, "kf24" }, 153361fb91cSnicm [TTYC_KF25] = { TTYCODE_STRING, "kf25" }, 154361fb91cSnicm [TTYC_KF26] = { TTYCODE_STRING, "kf26" }, 155361fb91cSnicm [TTYC_KF27] = { TTYCODE_STRING, "kf27" }, 156361fb91cSnicm [TTYC_KF28] = { TTYCODE_STRING, "kf28" }, 157361fb91cSnicm [TTYC_KF29] = { TTYCODE_STRING, "kf29" }, 15801cf4cccSnicm [TTYC_KF2] = { TTYCODE_STRING, "kf2" }, 159361fb91cSnicm [TTYC_KF30] = { TTYCODE_STRING, "kf30" }, 160361fb91cSnicm [TTYC_KF31] = { TTYCODE_STRING, "kf31" }, 161361fb91cSnicm [TTYC_KF32] = { TTYCODE_STRING, "kf32" }, 162361fb91cSnicm [TTYC_KF33] = { TTYCODE_STRING, "kf33" }, 163361fb91cSnicm [TTYC_KF34] = { TTYCODE_STRING, "kf34" }, 164361fb91cSnicm [TTYC_KF35] = { TTYCODE_STRING, "kf35" }, 165361fb91cSnicm [TTYC_KF36] = { TTYCODE_STRING, "kf36" }, 166361fb91cSnicm [TTYC_KF37] = { TTYCODE_STRING, "kf37" }, 167361fb91cSnicm [TTYC_KF38] = { TTYCODE_STRING, "kf38" }, 168361fb91cSnicm [TTYC_KF39] = { TTYCODE_STRING, "kf39" }, 16901cf4cccSnicm [TTYC_KF3] = { TTYCODE_STRING, "kf3" }, 170361fb91cSnicm [TTYC_KF40] = { TTYCODE_STRING, "kf40" }, 171361fb91cSnicm [TTYC_KF41] = { TTYCODE_STRING, "kf41" }, 172361fb91cSnicm [TTYC_KF42] = { TTYCODE_STRING, "kf42" }, 173361fb91cSnicm [TTYC_KF43] = { TTYCODE_STRING, "kf43" }, 174361fb91cSnicm [TTYC_KF44] = { TTYCODE_STRING, "kf44" }, 175361fb91cSnicm [TTYC_KF45] = { TTYCODE_STRING, "kf45" }, 176361fb91cSnicm [TTYC_KF46] = { TTYCODE_STRING, "kf46" }, 177361fb91cSnicm [TTYC_KF47] = { TTYCODE_STRING, "kf47" }, 178361fb91cSnicm [TTYC_KF48] = { TTYCODE_STRING, "kf48" }, 179361fb91cSnicm [TTYC_KF49] = { TTYCODE_STRING, "kf49" }, 18001cf4cccSnicm [TTYC_KF4] = { TTYCODE_STRING, "kf4" }, 181361fb91cSnicm [TTYC_KF50] = { TTYCODE_STRING, "kf50" }, 182361fb91cSnicm [TTYC_KF51] = { TTYCODE_STRING, "kf51" }, 183361fb91cSnicm [TTYC_KF52] = { TTYCODE_STRING, "kf52" }, 184361fb91cSnicm [TTYC_KF53] = { TTYCODE_STRING, "kf53" }, 185361fb91cSnicm [TTYC_KF54] = { TTYCODE_STRING, "kf54" }, 186361fb91cSnicm [TTYC_KF55] = { TTYCODE_STRING, "kf55" }, 187361fb91cSnicm [TTYC_KF56] = { TTYCODE_STRING, "kf56" }, 188361fb91cSnicm [TTYC_KF57] = { TTYCODE_STRING, "kf57" }, 189361fb91cSnicm [TTYC_KF58] = { TTYCODE_STRING, "kf58" }, 190361fb91cSnicm [TTYC_KF59] = { TTYCODE_STRING, "kf59" }, 19101cf4cccSnicm [TTYC_KF5] = { TTYCODE_STRING, "kf5" }, 192361fb91cSnicm [TTYC_KF60] = { TTYCODE_STRING, "kf60" }, 193361fb91cSnicm [TTYC_KF61] = { TTYCODE_STRING, "kf61" }, 194361fb91cSnicm [TTYC_KF62] = { TTYCODE_STRING, "kf62" }, 195361fb91cSnicm [TTYC_KF63] = { TTYCODE_STRING, "kf63" }, 19601cf4cccSnicm [TTYC_KF6] = { TTYCODE_STRING, "kf6" }, 197361fb91cSnicm [TTYC_KF7] = { TTYCODE_STRING, "kf7" }, 198361fb91cSnicm [TTYC_KF8] = { TTYCODE_STRING, "kf8" }, 199361fb91cSnicm [TTYC_KF9] = { TTYCODE_STRING, "kf9" }, 200361fb91cSnicm [TTYC_KHOM2] = { TTYCODE_STRING, "kHOM" }, 201361fb91cSnicm [TTYC_KHOM3] = { TTYCODE_STRING, "kHOM3" }, 202361fb91cSnicm [TTYC_KHOM4] = { TTYCODE_STRING, "kHOM4" }, 203361fb91cSnicm [TTYC_KHOM5] = { TTYCODE_STRING, "kHOM5" }, 204361fb91cSnicm [TTYC_KHOM6] = { TTYCODE_STRING, "kHOM6" }, 205361fb91cSnicm [TTYC_KHOM7] = { TTYCODE_STRING, "kHOM7" }, 206361fb91cSnicm [TTYC_KHOME] = { TTYCODE_STRING, "khome" }, 207361fb91cSnicm [TTYC_KIC2] = { TTYCODE_STRING, "kIC" }, 208361fb91cSnicm [TTYC_KIC3] = { TTYCODE_STRING, "kIC3" }, 209361fb91cSnicm [TTYC_KIC4] = { TTYCODE_STRING, "kIC4" }, 210361fb91cSnicm [TTYC_KIC5] = { TTYCODE_STRING, "kIC5" }, 211361fb91cSnicm [TTYC_KIC6] = { TTYCODE_STRING, "kIC6" }, 212361fb91cSnicm [TTYC_KIC7] = { TTYCODE_STRING, "kIC7" }, 213361fb91cSnicm [TTYC_KICH1] = { TTYCODE_STRING, "kich1" }, 21401cf4cccSnicm [TTYC_KIND] = { TTYCODE_STRING, "kind" }, 215361fb91cSnicm [TTYC_KLFT2] = { TTYCODE_STRING, "kLFT" }, 216361fb91cSnicm [TTYC_KLFT3] = { TTYCODE_STRING, "kLFT3" }, 217361fb91cSnicm [TTYC_KLFT4] = { TTYCODE_STRING, "kLFT4" }, 218361fb91cSnicm [TTYC_KLFT5] = { TTYCODE_STRING, "kLFT5" }, 219361fb91cSnicm [TTYC_KLFT6] = { TTYCODE_STRING, "kLFT6" }, 220361fb91cSnicm [TTYC_KLFT7] = { TTYCODE_STRING, "kLFT7" }, 221361fb91cSnicm [TTYC_KMOUS] = { TTYCODE_STRING, "kmous" }, 222361fb91cSnicm [TTYC_KNP] = { TTYCODE_STRING, "knp" }, 223361fb91cSnicm [TTYC_KNXT2] = { TTYCODE_STRING, "kNXT" }, 224361fb91cSnicm [TTYC_KNXT3] = { TTYCODE_STRING, "kNXT3" }, 225361fb91cSnicm [TTYC_KNXT4] = { TTYCODE_STRING, "kNXT4" }, 226361fb91cSnicm [TTYC_KNXT5] = { TTYCODE_STRING, "kNXT5" }, 227361fb91cSnicm [TTYC_KNXT6] = { TTYCODE_STRING, "kNXT6" }, 228361fb91cSnicm [TTYC_KNXT7] = { TTYCODE_STRING, "kNXT7" }, 229361fb91cSnicm [TTYC_KPP] = { TTYCODE_STRING, "kpp" }, 230361fb91cSnicm [TTYC_KPRV2] = { TTYCODE_STRING, "kPRV" }, 231361fb91cSnicm [TTYC_KPRV3] = { TTYCODE_STRING, "kPRV3" }, 232361fb91cSnicm [TTYC_KPRV4] = { TTYCODE_STRING, "kPRV4" }, 233361fb91cSnicm [TTYC_KPRV5] = { TTYCODE_STRING, "kPRV5" }, 234361fb91cSnicm [TTYC_KPRV6] = { TTYCODE_STRING, "kPRV6" }, 235361fb91cSnicm [TTYC_KPRV7] = { TTYCODE_STRING, "kPRV7" }, 236361fb91cSnicm [TTYC_KRIT2] = { TTYCODE_STRING, "kRIT" }, 237361fb91cSnicm [TTYC_KRIT3] = { TTYCODE_STRING, "kRIT3" }, 238361fb91cSnicm [TTYC_KRIT4] = { TTYCODE_STRING, "kRIT4" }, 239361fb91cSnicm [TTYC_KRIT5] = { TTYCODE_STRING, "kRIT5" }, 240361fb91cSnicm [TTYC_KRIT6] = { TTYCODE_STRING, "kRIT6" }, 241361fb91cSnicm [TTYC_KRIT7] = { TTYCODE_STRING, "kRIT7" }, 24201cf4cccSnicm [TTYC_KRI] = { TTYCODE_STRING, "kri" }, 24301cf4cccSnicm [TTYC_KUP2] = { TTYCODE_STRING, "kUP" }, /* not kUP2 */ 244361fb91cSnicm [TTYC_KUP3] = { TTYCODE_STRING, "kUP3" }, 245361fb91cSnicm [TTYC_KUP4] = { TTYCODE_STRING, "kUP4" }, 246361fb91cSnicm [TTYC_KUP5] = { TTYCODE_STRING, "kUP5" }, 247361fb91cSnicm [TTYC_KUP6] = { TTYCODE_STRING, "kUP6" }, 248361fb91cSnicm [TTYC_KUP7] = { TTYCODE_STRING, "kUP7" }, 249361fb91cSnicm [TTYC_MS] = { TTYCODE_STRING, "Ms" }, 250306ef605Snicm [TTYC_NOBR] = { TTYCODE_STRING, "Nobr" }, 251e9a14db2Snicm [TTYC_OL] = { TTYCODE_STRING, "ol" }, 252361fb91cSnicm [TTYC_OP] = { TTYCODE_STRING, "op" }, 253dd3a9cf8Snicm [TTYC_RECT] = { TTYCODE_STRING, "Rect" }, 254361fb91cSnicm [TTYC_REV] = { TTYCODE_STRING, "rev" }, 2552b41aa93Snicm [TTYC_RGB] = { TTYCODE_FLAG, "RGB" }, 256fa32c33cSnicm [TTYC_RIN] = { TTYCODE_STRING, "rin" }, 2576763df04Snicm [TTYC_RI] = { TTYCODE_STRING, "ri" }, 258361fb91cSnicm [TTYC_RMACS] = { TTYCODE_STRING, "rmacs" }, 259361fb91cSnicm [TTYC_RMCUP] = { TTYCODE_STRING, "rmcup" }, 260361fb91cSnicm [TTYC_RMKX] = { TTYCODE_STRING, "rmkx" }, 261361fb91cSnicm [TTYC_SETAB] = { TTYCODE_STRING, "setab" }, 262361fb91cSnicm [TTYC_SETAF] = { TTYCODE_STRING, "setaf" }, 263e9a14db2Snicm [TTYC_SETAL] = { TTYCODE_STRING, "setal" }, 264a680c33fSnicm [TTYC_SETRGBB] = { TTYCODE_STRING, "setrgbb" }, 265a680c33fSnicm [TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" }, 266bc174b93Snicm [TTYC_SETULC] = { TTYCODE_STRING, "Setulc" }, 2674620f414Snicm [TTYC_SETULC1] = { TTYCODE_STRING, "Setulc1" }, 26801cf4cccSnicm [TTYC_SE] = { TTYCODE_STRING, "Se" }, 269e0697ebcSnicm [TTYC_SXL] = { TTYCODE_FLAG, "Sxl" }, 270361fb91cSnicm [TTYC_SGR0] = { TTYCODE_STRING, "sgr0" }, 271361fb91cSnicm [TTYC_SITM] = { TTYCODE_STRING, "sitm" }, 272361fb91cSnicm [TTYC_SMACS] = { TTYCODE_STRING, "smacs" }, 273361fb91cSnicm [TTYC_SMCUP] = { TTYCODE_STRING, "smcup" }, 274361fb91cSnicm [TTYC_SMKX] = { TTYCODE_STRING, "smkx" }, 275d37269efSnicm [TTYC_SMOL] = { TTYCODE_STRING, "Smol" }, 276361fb91cSnicm [TTYC_SMSO] = { TTYCODE_STRING, "smso" }, 27742caa339Snicm [TTYC_SMULX] = { TTYCODE_STRING, "Smulx" }, 278361fb91cSnicm [TTYC_SMUL] = { TTYCODE_STRING, "smul" }, 2791779e050Snicm [TTYC_SMXX] = { TTYCODE_STRING, "smxx" }, 280361fb91cSnicm [TTYC_SS] = { TTYCODE_STRING, "Ss" }, 281989dfa67Snicm [TTYC_SWD] = { TTYCODE_STRING, "Swd" }, 282d89bc9f8Snicm [TTYC_SYNC] = { TTYCODE_STRING, "Sync" }, 283a4f3e970Snicm [TTYC_TC] = { TTYCODE_FLAG, "Tc" }, 284361fb91cSnicm [TTYC_TSL] = { TTYCODE_STRING, "tsl" }, 285e5a58dfcSnicm [TTYC_U8] = { TTYCODE_NUMBER, "U8" }, 28601cf4cccSnicm [TTYC_VPA] = { TTYCODE_STRING, "vpa" }, 2876763df04Snicm [TTYC_XT] = { TTYCODE_FLAG, "XT" } 288361fb91cSnicm }; 289361fb91cSnicm 290361fb91cSnicm u_int 291361fb91cSnicm tty_term_ncodes(void) 292361fb91cSnicm { 293361fb91cSnicm return (nitems(tty_term_codes)); 294361fb91cSnicm } 295361fb91cSnicm 2969883b791Snicm static char * 297311827fbSnicm tty_term_strip(const char *s) 298311827fbSnicm { 299311827fbSnicm const char *ptr; 3004512d27dSnicm static char buf[8192]; 301311827fbSnicm size_t len; 302311827fbSnicm 303311827fbSnicm /* Ignore strings with no padding. */ 304311827fbSnicm if (strchr(s, '$') == NULL) 305311827fbSnicm return (xstrdup(s)); 306311827fbSnicm 307311827fbSnicm len = 0; 308311827fbSnicm for (ptr = s; *ptr != '\0'; ptr++) { 309311827fbSnicm if (*ptr == '$' && *(ptr + 1) == '<') { 310311827fbSnicm while (*ptr != '\0' && *ptr != '>') 311311827fbSnicm ptr++; 312311827fbSnicm if (*ptr == '>') 313311827fbSnicm ptr++; 314493d2591Snicm if (*ptr == '\0') 315493d2591Snicm break; 316311827fbSnicm } 317311827fbSnicm 318311827fbSnicm buf[len++] = *ptr; 319311827fbSnicm if (len == (sizeof buf) - 1) 320311827fbSnicm break; 321311827fbSnicm } 322311827fbSnicm buf[len] = '\0'; 323311827fbSnicm 324311827fbSnicm return (xstrdup(buf)); 325311827fbSnicm } 326311827fbSnicm 32742caa339Snicm static char * 32842caa339Snicm tty_term_override_next(const char *s, size_t *offset) 32942caa339Snicm { 3304512d27dSnicm static char value[8192]; 33142caa339Snicm size_t n = 0, at = *offset; 33242caa339Snicm 33342caa339Snicm if (s[at] == '\0') 33442caa339Snicm return (NULL); 33542caa339Snicm 33642caa339Snicm while (s[at] != '\0') { 33742caa339Snicm if (s[at] == ':') { 33842caa339Snicm if (s[at + 1] == ':') { 33942caa339Snicm value[n++] = ':'; 34042caa339Snicm at += 2; 34142caa339Snicm } else 34242caa339Snicm break; 34342caa339Snicm } else { 34442caa339Snicm value[n++] = s[at]; 34542caa339Snicm at++; 34642caa339Snicm } 34742caa339Snicm if (n == (sizeof value) - 1) 34842caa339Snicm return (NULL); 34942caa339Snicm } 35042caa339Snicm if (s[at] != '\0') 35142caa339Snicm *offset = at + 1; 35242caa339Snicm else 35342caa339Snicm *offset = at; 35442caa339Snicm value[n] = '\0'; 35542caa339Snicm return (value); 35642caa339Snicm } 35742caa339Snicm 3585a160f88Snicm void 3595a160f88Snicm tty_term_apply(struct tty_term *term, const char *capabilities, int quiet) 360311827fbSnicm { 3619aab4fe6Snicm const struct tty_term_code_entry *ent; 3625e07382cSnicm struct tty_code *code; 36342caa339Snicm size_t offset = 0; 36442caa339Snicm char *cp, *value, *s; 3655a160f88Snicm const char *errstr, *name = term->name; 3665e07382cSnicm u_int i; 3675c9b8f32Snicm int n, remove; 3685e07382cSnicm 3695a160f88Snicm while ((s = tty_term_override_next(capabilities, &offset)) != NULL) { 3705c9b8f32Snicm if (*s == '\0') 3715c9b8f32Snicm continue; 3725c9b8f32Snicm value = NULL; 3735c9b8f32Snicm 3745c9b8f32Snicm remove = 0; 3755c9b8f32Snicm if ((cp = strchr(s, '=')) != NULL) { 3765c9b8f32Snicm *cp++ = '\0'; 3775c9b8f32Snicm value = xstrdup(cp); 3785c9b8f32Snicm if (strunvis(value, cp) == -1) { 3795c9b8f32Snicm free(value); 3805c9b8f32Snicm value = xstrdup(cp); 3815c9b8f32Snicm } 3825c9b8f32Snicm } else if (s[strlen(s) - 1] == '@') { 3835c9b8f32Snicm s[strlen(s) - 1] = '\0'; 3845c9b8f32Snicm remove = 1; 3855c9b8f32Snicm } else 3865c9b8f32Snicm value = xstrdup(""); 3875c9b8f32Snicm 3885a160f88Snicm if (!quiet) { 3895c9b8f32Snicm if (remove) 3905a160f88Snicm log_debug("%s override: %s@", name, s); 39142caa339Snicm else if (*value == '\0') 3925a160f88Snicm log_debug("%s override: %s", name, s); 3935c9b8f32Snicm else 3945a160f88Snicm log_debug("%s override: %s=%s", name, s, value); 3955a160f88Snicm } 3965c9b8f32Snicm 397361fb91cSnicm for (i = 0; i < tty_term_ncodes(); i++) { 3985e07382cSnicm ent = &tty_term_codes[i]; 3995c9b8f32Snicm if (strcmp(s, ent->name) != 0) 4005e07382cSnicm continue; 401361fb91cSnicm code = &term->codes[i]; 4025e07382cSnicm 4035c9b8f32Snicm if (remove) { 4045e07382cSnicm code->type = TTYCODE_NONE; 4055e07382cSnicm continue; 4065e07382cSnicm } 4075e07382cSnicm switch (ent->type) { 4085e07382cSnicm case TTYCODE_NONE: 4095e07382cSnicm break; 4105e07382cSnicm case TTYCODE_STRING: 411c1594c0fSnicm if (code->type == TTYCODE_STRING) 4127d053cf9Snicm free(code->value.string); 4135c9b8f32Snicm code->value.string = xstrdup(value); 4145e07382cSnicm code->type = ent->type; 4155e07382cSnicm break; 4165e07382cSnicm case TTYCODE_NUMBER: 4175c9b8f32Snicm n = strtonum(value, 0, INT_MAX, &errstr); 4185e07382cSnicm if (errstr != NULL) 4195e07382cSnicm break; 4205e07382cSnicm code->value.number = n; 4215e07382cSnicm code->type = ent->type; 4225e07382cSnicm break; 4235e07382cSnicm case TTYCODE_FLAG: 4245e07382cSnicm code->value.flag = 1; 4255e07382cSnicm code->type = ent->type; 4265e07382cSnicm break; 427311827fbSnicm } 428311827fbSnicm } 429311827fbSnicm 4305c9b8f32Snicm free(value); 431311827fbSnicm } 432311827fbSnicm } 433311827fbSnicm 4349c34abedSnicm void 4359c34abedSnicm tty_term_apply_overrides(struct tty_term *term) 4369c34abedSnicm { 4379c34abedSnicm struct options_entry *o; 4389c34abedSnicm struct options_array_item *a; 4399c34abedSnicm union options_value *ov; 440dd3a9cf8Snicm const char *s, *acs; 4419c34abedSnicm size_t offset; 4429c34abedSnicm char *first; 4439c34abedSnicm 444dd3a9cf8Snicm /* Update capabilities from the option. */ 4459c34abedSnicm o = options_get_only(global_options, "terminal-overrides"); 4469c34abedSnicm a = options_array_first(o); 4479c34abedSnicm while (a != NULL) { 4489c34abedSnicm ov = options_array_item_value(a); 4499c34abedSnicm s = ov->string; 4509c34abedSnicm 4519c34abedSnicm offset = 0; 4529c34abedSnicm first = tty_term_override_next(s, &offset); 4539c34abedSnicm if (first != NULL && fnmatch(first, term->name, 0) == 0) 4549c34abedSnicm tty_term_apply(term, s + offset, 0); 4559c34abedSnicm a = options_array_next(a); 4569c34abedSnicm } 457dd3a9cf8Snicm 458f4ec6bcaSnicm /* Log the SIXEL flag. */ 459f4ec6bcaSnicm log_debug("SIXEL flag is %d", !!(term->flags & TERM_SIXEL)); 460f4ec6bcaSnicm 461dd3a9cf8Snicm /* Update the RGB flag if the terminal has RGB colours. */ 462dd3a9cf8Snicm if (tty_term_has(term, TTYC_SETRGBF) && 463dd3a9cf8Snicm tty_term_has(term, TTYC_SETRGBB)) 464dd3a9cf8Snicm term->flags |= TERM_RGBCOLOURS; 465dd3a9cf8Snicm else 466dd3a9cf8Snicm term->flags &= ~TERM_RGBCOLOURS; 467dd3a9cf8Snicm log_debug("RGBCOLOURS flag is %d", !!(term->flags & TERM_RGBCOLOURS)); 468dd3a9cf8Snicm 469dd3a9cf8Snicm /* 470dd3a9cf8Snicm * Set or clear the DECSLRM flag if the terminal has the margin 471dd3a9cf8Snicm * capabilities. 472dd3a9cf8Snicm */ 473dd3a9cf8Snicm if (tty_term_has(term, TTYC_CMG) && tty_term_has(term, TTYC_CLMG)) 474dd3a9cf8Snicm term->flags |= TERM_DECSLRM; 475dd3a9cf8Snicm else 476dd3a9cf8Snicm term->flags &= ~TERM_DECSLRM; 477dd3a9cf8Snicm log_debug("DECSLRM flag is %d", !!(term->flags & TERM_DECSLRM)); 478dd3a9cf8Snicm 479dd3a9cf8Snicm /* 480dd3a9cf8Snicm * Set or clear the DECFRA flag if the terminal has the rectangle 481dd3a9cf8Snicm * capability. 482dd3a9cf8Snicm */ 483dd3a9cf8Snicm if (tty_term_has(term, TTYC_RECT)) 484dd3a9cf8Snicm term->flags |= TERM_DECFRA; 485dd3a9cf8Snicm else 486dd3a9cf8Snicm term->flags &= ~TERM_DECFRA; 487dd3a9cf8Snicm log_debug("DECFRA flag is %d", !!(term->flags & TERM_DECFRA)); 488dd3a9cf8Snicm 489dd3a9cf8Snicm /* 490dd3a9cf8Snicm * Terminals without am (auto right margin) wrap at at $COLUMNS - 1 491dd3a9cf8Snicm * rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1). 492dd3a9cf8Snicm * 493dd3a9cf8Snicm * Terminals without xenl (eat newline glitch) ignore a newline beyond 494dd3a9cf8Snicm * the right edge of the terminal, but tmux doesn't care about this - 495dd3a9cf8Snicm * it always uses absolute only moves the cursor with a newline when 496dd3a9cf8Snicm * also sending a linefeed. 497dd3a9cf8Snicm * 498dd3a9cf8Snicm * This is irritating, most notably because it is painful to write to 499dd3a9cf8Snicm * the very bottom-right of the screen without scrolling. 500dd3a9cf8Snicm * 501dd3a9cf8Snicm * Flag the terminal here and apply some workarounds in other places to 502dd3a9cf8Snicm * do the best possible. 503dd3a9cf8Snicm */ 504dd3a9cf8Snicm if (!tty_term_flag(term, TTYC_AM)) 505dd3a9cf8Snicm term->flags |= TERM_NOAM; 506dd3a9cf8Snicm else 507dd3a9cf8Snicm term->flags &= ~TERM_NOAM; 508dd3a9cf8Snicm log_debug("NOAM flag is %d", !!(term->flags & TERM_NOAM)); 509dd3a9cf8Snicm 510dd3a9cf8Snicm /* Generate ACS table. If none is present, use nearest ASCII. */ 511dd3a9cf8Snicm memset(term->acs, 0, sizeof term->acs); 512dd3a9cf8Snicm if (tty_term_has(term, TTYC_ACSC)) 513dd3a9cf8Snicm acs = tty_term_string(term, TTYC_ACSC); 514dd3a9cf8Snicm else 515dd3a9cf8Snicm acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~."; 516dd3a9cf8Snicm for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2) 517dd3a9cf8Snicm term->acs[(u_char) acs[0]][0] = acs[1]; 5189c34abedSnicm } 5199c34abedSnicm 520311827fbSnicm struct tty_term * 521c05282f8Snicm tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps, 522c05282f8Snicm int *feat, char **cause) 523311827fbSnicm { 524311827fbSnicm struct tty_term *term; 5259aab4fe6Snicm const struct tty_term_code_entry *ent; 526311827fbSnicm struct tty_code *code; 5275c9b8f32Snicm struct options_entry *o; 52839052edfSnicm struct options_array_item *a; 52984306383Snicm union options_value *ov; 530c05282f8Snicm u_int i, j; 531*527d0d53Snicm const char *s, *value, *errstr; 532c05282f8Snicm size_t offset, namelen; 5335a160f88Snicm char *first; 534*527d0d53Snicm int n; 535311827fbSnicm 5365a160f88Snicm log_debug("adding term %s", name); 537354b9f89Snicm 5385a160f88Snicm term = xcalloc(1, sizeof *term); 5395a160f88Snicm term->tty = tty; 540311827fbSnicm term->name = xstrdup(name); 541361fb91cSnicm term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes); 5420a271d7eSnicm LIST_INSERT_HEAD(&tty_terms, term, entry); 543311827fbSnicm 544311827fbSnicm /* Fill in codes. */ 545c05282f8Snicm for (i = 0; i < ncaps; i++) { 546c05282f8Snicm namelen = strcspn(caps[i], "="); 547c05282f8Snicm if (namelen == 0) 548c05282f8Snicm continue; 549c05282f8Snicm value = caps[i] + namelen + 1; 550311827fbSnicm 551c05282f8Snicm for (j = 0; j < tty_term_ncodes(); j++) { 552c05282f8Snicm ent = &tty_term_codes[j]; 553c05282f8Snicm if (strncmp(ent->name, caps[i], namelen) != 0) 554c05282f8Snicm continue; 555c05282f8Snicm if (ent->name[namelen] != '\0') 556c05282f8Snicm continue; 557c05282f8Snicm 558c05282f8Snicm code = &term->codes[j]; 559311827fbSnicm code->type = TTYCODE_NONE; 560311827fbSnicm switch (ent->type) { 561311827fbSnicm case TTYCODE_NONE: 562311827fbSnicm break; 563311827fbSnicm case TTYCODE_STRING: 564311827fbSnicm code->type = TTYCODE_STRING; 565c05282f8Snicm code->value.string = tty_term_strip(value); 566311827fbSnicm break; 567311827fbSnicm case TTYCODE_NUMBER: 568*527d0d53Snicm n = strtonum(value, 0, INT_MAX, &errstr); 569*527d0d53Snicm if (errstr != NULL) 570*527d0d53Snicm log_debug("%s: %s", ent->name, errstr); 571*527d0d53Snicm else { 572311827fbSnicm code->type = TTYCODE_NUMBER; 573*527d0d53Snicm code->value.number = n; 574*527d0d53Snicm } 575311827fbSnicm break; 576311827fbSnicm case TTYCODE_FLAG: 577311827fbSnicm code->type = TTYCODE_FLAG; 578c05282f8Snicm code->value.flag = (*value == '1'); 579311827fbSnicm break; 580311827fbSnicm } 581311827fbSnicm } 582c05282f8Snicm } 583807352cfSnicm 5845a160f88Snicm /* Apply terminal features. */ 5855a160f88Snicm o = options_get_only(global_options, "terminal-features"); 5865a160f88Snicm a = options_array_first(o); 5875a160f88Snicm while (a != NULL) { 5885a160f88Snicm ov = options_array_item_value(a); 5895a160f88Snicm s = ov->string; 5905a160f88Snicm 5915a160f88Snicm offset = 0; 5925a160f88Snicm first = tty_term_override_next(s, &offset); 5935a160f88Snicm if (first != NULL && fnmatch(first, term->name, 0) == 0) 5945a160f88Snicm tty_add_features(feat, s + offset, ":"); 5955a160f88Snicm a = options_array_next(a); 5965a160f88Snicm } 5975a160f88Snicm 5989d01fefaSnicm /* Apply overrides so any capabilities used for features are changed. */ 5999d01fefaSnicm tty_term_apply_overrides(term); 6009d01fefaSnicm 601311827fbSnicm /* These are always required. */ 602311827fbSnicm if (!tty_term_has(term, TTYC_CLEAR)) { 603311827fbSnicm xasprintf(cause, "terminal does not support clear"); 604311827fbSnicm goto error; 605311827fbSnicm } 606311827fbSnicm if (!tty_term_has(term, TTYC_CUP)) { 607311827fbSnicm xasprintf(cause, "terminal does not support cup"); 608311827fbSnicm goto error; 609311827fbSnicm } 610311827fbSnicm 6119884925cSnicm /* 6129884925cSnicm * If TERM has XT or clear starts with CSI then it is safe to assume 6139884925cSnicm * the terminal is derived from the VT100. This controls whether device 6149884925cSnicm * attributes requests are sent to get more information. 6159884925cSnicm * 6169884925cSnicm * This is a bit of a hack but there aren't that many alternatives. 6179884925cSnicm * Worst case tmux will just fall back to using whatever terminfo(5) 6189884925cSnicm * says without trying to correct anything that is missing. 6199884925cSnicm * 6209884925cSnicm * Also add few features that VT100-like terminals should either 6219884925cSnicm * support or safely ignore. 6229884925cSnicm */ 6239884925cSnicm s = tty_term_string(term, TTYC_CLEAR); 6249884925cSnicm if (tty_term_flag(term, TTYC_XT) || strncmp(s, "\033[", 2) == 0) { 6259884925cSnicm term->flags |= TERM_VT100LIKE; 6269884925cSnicm tty_add_features(feat, "bpaste,focus,title", ","); 627311827fbSnicm } 628311827fbSnicm 6295a160f88Snicm /* Add RGB feature if terminal has RGB colours. */ 6305a160f88Snicm if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) && 6315a160f88Snicm (!tty_term_has(term, TTYC_SETRGBF) || 6325a160f88Snicm !tty_term_has(term, TTYC_SETRGBB))) 63380bd3d52Snicm tty_add_features(feat, "RGB", ","); 634311827fbSnicm 6359d01fefaSnicm /* Apply the features and overrides again. */ 636dd3a9cf8Snicm if (tty_apply_features(term, *feat)) 6379c34abedSnicm tty_term_apply_overrides(term); 63876b45294Snicm 6395b964ae2Snicm /* Log the capabilities. */ 640354b9f89Snicm for (i = 0; i < tty_term_ncodes(); i++) 641354b9f89Snicm log_debug("%s%s", name, tty_term_describe(term, i)); 642354b9f89Snicm 643311827fbSnicm return (term); 644311827fbSnicm 645311827fbSnicm error: 646311827fbSnicm tty_term_free(term); 647311827fbSnicm return (NULL); 648311827fbSnicm } 649311827fbSnicm 650311827fbSnicm void 651311827fbSnicm tty_term_free(struct tty_term *term) 652311827fbSnicm { 653311827fbSnicm u_int i; 654311827fbSnicm 6555a160f88Snicm log_debug("removing term %s", term->name); 656311827fbSnicm 657361fb91cSnicm for (i = 0; i < tty_term_ncodes(); i++) { 658311827fbSnicm if (term->codes[i].type == TTYCODE_STRING) 6597d053cf9Snicm free(term->codes[i].value.string); 660311827fbSnicm } 661361fb91cSnicm free(term->codes); 662361fb91cSnicm 6635a160f88Snicm LIST_REMOVE(term, entry); 6647d053cf9Snicm free(term->name); 6657d053cf9Snicm free(term); 666311827fbSnicm } 667311827fbSnicm 668311827fbSnicm int 669c05282f8Snicm tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps, 670c05282f8Snicm char **cause) 671c05282f8Snicm { 672c05282f8Snicm const struct tty_term_code_entry *ent; 673c05282f8Snicm int error, n; 674c05282f8Snicm u_int i; 675c05282f8Snicm const char *s; 676c05282f8Snicm char tmp[11]; 677c05282f8Snicm 67845a9d9dcSnicm if (setupterm((char *)name, fd, &error) != OK) { 679c05282f8Snicm switch (error) { 680c05282f8Snicm case 1: 681c05282f8Snicm xasprintf(cause, "can't use hardcopy terminal: %s", 682c05282f8Snicm name); 683c05282f8Snicm break; 684c05282f8Snicm case 0: 685c05282f8Snicm xasprintf(cause, "missing or unsuitable terminal: %s", 686c05282f8Snicm name); 687c05282f8Snicm break; 688c05282f8Snicm case -1: 689c05282f8Snicm xasprintf(cause, "can't find terminfo database"); 690c05282f8Snicm break; 691c05282f8Snicm default: 692c05282f8Snicm xasprintf(cause, "unknown error"); 693c05282f8Snicm break; 694c05282f8Snicm } 695c05282f8Snicm return (-1); 696c05282f8Snicm } 697c05282f8Snicm 698c05282f8Snicm *ncaps = 0; 699c05282f8Snicm *caps = NULL; 700c05282f8Snicm 701c05282f8Snicm for (i = 0; i < tty_term_ncodes(); i++) { 702c05282f8Snicm ent = &tty_term_codes[i]; 703c05282f8Snicm switch (ent->type) { 704c05282f8Snicm case TTYCODE_NONE: 7052bd728e0Snicm continue; 706c05282f8Snicm case TTYCODE_STRING: 707c05282f8Snicm s = tigetstr((char *)ent->name); 708c05282f8Snicm if (s == NULL || s == (char *)-1) 709c05282f8Snicm continue; 710c05282f8Snicm break; 711c05282f8Snicm case TTYCODE_NUMBER: 712c05282f8Snicm n = tigetnum((char *)ent->name); 713c05282f8Snicm if (n == -1 || n == -2) 714c05282f8Snicm continue; 715c05282f8Snicm xsnprintf(tmp, sizeof tmp, "%d", n); 716c05282f8Snicm s = tmp; 717c05282f8Snicm break; 718c05282f8Snicm case TTYCODE_FLAG: 719c05282f8Snicm n = tigetflag((char *)ent->name); 720c05282f8Snicm if (n == -1) 721c05282f8Snicm continue; 722c05282f8Snicm if (n) 723c05282f8Snicm s = "1"; 724c05282f8Snicm else 725c05282f8Snicm s = "0"; 726c05282f8Snicm break; 727e3eeb0f8Snicm default: 728e3eeb0f8Snicm fatalx("unknown capability type"); 729c05282f8Snicm } 730c05282f8Snicm *caps = xreallocarray(*caps, (*ncaps) + 1, sizeof **caps); 731c05282f8Snicm xasprintf(&(*caps)[*ncaps], "%s=%s", ent->name, s); 732c05282f8Snicm (*ncaps)++; 733c05282f8Snicm } 734c05282f8Snicm 735c05282f8Snicm del_curterm(cur_term); 736c05282f8Snicm return (0); 737c05282f8Snicm } 738c05282f8Snicm 739c05282f8Snicm void 740c05282f8Snicm tty_term_free_list(char **caps, u_int ncaps) 741c05282f8Snicm { 742c05282f8Snicm u_int i; 743c05282f8Snicm 744c05282f8Snicm for (i = 0; i < ncaps; i++) 745c05282f8Snicm free(caps[i]); 746c05282f8Snicm free(caps); 747c05282f8Snicm } 748c05282f8Snicm 749c05282f8Snicm int 750311827fbSnicm tty_term_has(struct tty_term *term, enum tty_code_code code) 751311827fbSnicm { 752311827fbSnicm return (term->codes[code].type != TTYCODE_NONE); 753311827fbSnicm } 754311827fbSnicm 755311827fbSnicm const char * 756311827fbSnicm tty_term_string(struct tty_term *term, enum tty_code_code code) 757311827fbSnicm { 758311827fbSnicm if (!tty_term_has(term, code)) 759311827fbSnicm return (""); 760311827fbSnicm if (term->codes[code].type != TTYCODE_STRING) 7613baad57eSnicm fatalx("not a string: %d", code); 762311827fbSnicm return (term->codes[code].value.string); 763311827fbSnicm } 764311827fbSnicm 765311827fbSnicm const char * 76666f967b2Snicm tty_term_string_i(struct tty_term *term, enum tty_code_code code, int a) 767311827fbSnicm { 76866f967b2Snicm const char *x = tty_term_string(term, code), *s; 76966f967b2Snicm 77013bce48bSnicm s = tiparm_s(1, 0, x, a); 771528ed858Snicm if (s == NULL) { 772528ed858Snicm log_debug("could not expand %s", tty_term_codes[code].name); 773528ed858Snicm return (""); 774528ed858Snicm } 77566f967b2Snicm return (s); 776311827fbSnicm } 777311827fbSnicm 778311827fbSnicm const char * 77966f967b2Snicm tty_term_string_ii(struct tty_term *term, enum tty_code_code code, int a, int b) 780311827fbSnicm { 78166f967b2Snicm const char *x = tty_term_string(term, code), *s; 78266f967b2Snicm 78313bce48bSnicm s = tiparm_s(2, 0, x, a, b); 784528ed858Snicm if (s == NULL) { 785528ed858Snicm log_debug("could not expand %s", tty_term_codes[code].name); 786528ed858Snicm return (""); 787528ed858Snicm } 78866f967b2Snicm return (s); 789311827fbSnicm } 790311827fbSnicm 791f9bce6b9Snicm const char * 792528ed858Snicm tty_term_string_iii(struct tty_term *term, enum tty_code_code code, int a, 793528ed858Snicm int b, int c) 794a680c33fSnicm { 79566f967b2Snicm const char *x = tty_term_string(term, code), *s; 79666f967b2Snicm 79713bce48bSnicm s = tiparm_s(3, 0, x, a, b, c); 798528ed858Snicm if (s == NULL) { 799528ed858Snicm log_debug("could not expand %s", tty_term_codes[code].name); 800528ed858Snicm return (""); 801528ed858Snicm } 80266f967b2Snicm return (s); 803a680c33fSnicm } 804a680c33fSnicm 805a680c33fSnicm const char * 80666f967b2Snicm tty_term_string_s(struct tty_term *term, enum tty_code_code code, const char *a) 807e417d1c0Snicm { 80866f967b2Snicm const char *x = tty_term_string(term, code), *s; 80966f967b2Snicm 81013bce48bSnicm s = tiparm_s(1, 1, x, a); 811528ed858Snicm if (s == NULL) { 812528ed858Snicm log_debug("could not expand %s", tty_term_codes[code].name); 813528ed858Snicm return (""); 814528ed858Snicm } 81566f967b2Snicm return (s); 816e417d1c0Snicm } 817e417d1c0Snicm 818e417d1c0Snicm const char * 819528ed858Snicm tty_term_string_ss(struct tty_term *term, enum tty_code_code code, 820528ed858Snicm const char *a, const char *b) 821f9bce6b9Snicm { 82266f967b2Snicm const char *x = tty_term_string(term, code), *s; 82366f967b2Snicm 82413bce48bSnicm s = tiparm_s(2, 3, x, a, b); 825528ed858Snicm if (s == NULL) { 826528ed858Snicm log_debug("could not expand %s", tty_term_codes[code].name); 827528ed858Snicm return (""); 828528ed858Snicm } 82966f967b2Snicm return (s); 830f9bce6b9Snicm } 831f9bce6b9Snicm 832311827fbSnicm int 833311827fbSnicm tty_term_number(struct tty_term *term, enum tty_code_code code) 834311827fbSnicm { 835311827fbSnicm if (!tty_term_has(term, code)) 836311827fbSnicm return (0); 837311827fbSnicm if (term->codes[code].type != TTYCODE_NUMBER) 8383baad57eSnicm fatalx("not a number: %d", code); 839311827fbSnicm return (term->codes[code].value.number); 840311827fbSnicm } 841311827fbSnicm 842311827fbSnicm int 843311827fbSnicm tty_term_flag(struct tty_term *term, enum tty_code_code code) 844311827fbSnicm { 845311827fbSnicm if (!tty_term_has(term, code)) 846311827fbSnicm return (0); 847311827fbSnicm if (term->codes[code].type != TTYCODE_FLAG) 8483baad57eSnicm fatalx("not a flag: %d", code); 849311827fbSnicm return (term->codes[code].value.flag); 850311827fbSnicm } 851361fb91cSnicm 852361fb91cSnicm const char * 853361fb91cSnicm tty_term_describe(struct tty_term *term, enum tty_code_code code) 854361fb91cSnicm { 855361fb91cSnicm static char s[256]; 856361fb91cSnicm char out[128]; 857361fb91cSnicm 858361fb91cSnicm switch (term->codes[code].type) { 859361fb91cSnicm case TTYCODE_NONE: 860361fb91cSnicm xsnprintf(s, sizeof s, "%4u: %s: [missing]", 861361fb91cSnicm code, tty_term_codes[code].name); 862361fb91cSnicm break; 863361fb91cSnicm case TTYCODE_STRING: 864361fb91cSnicm strnvis(out, term->codes[code].value.string, sizeof out, 86506feda64Snicm VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL); 866361fb91cSnicm xsnprintf(s, sizeof s, "%4u: %s: (string) %s", 867361fb91cSnicm code, tty_term_codes[code].name, 868361fb91cSnicm out); 869361fb91cSnicm break; 870361fb91cSnicm case TTYCODE_NUMBER: 871361fb91cSnicm xsnprintf(s, sizeof s, "%4u: %s: (number) %d", 872361fb91cSnicm code, tty_term_codes[code].name, 873361fb91cSnicm term->codes[code].value.number); 874361fb91cSnicm break; 875361fb91cSnicm case TTYCODE_FLAG: 876361fb91cSnicm xsnprintf(s, sizeof s, "%4u: %s: (flag) %s", 877361fb91cSnicm code, tty_term_codes[code].name, 878361fb91cSnicm term->codes[code].value.flag ? "true" : "false"); 879361fb91cSnicm break; 880361fb91cSnicm } 881361fb91cSnicm return (s); 882361fb91cSnicm } 883