199e242abSchristos /* $OpenBSD$ */ 2698d5317Sjmmv 3698d5317Sjmmv /* 4f26e8bc9Schristos * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> 5698d5317Sjmmv * 6698d5317Sjmmv * Permission to use, copy, modify, and distribute this software for any 7698d5317Sjmmv * purpose with or without fee is hereby granted, provided that the above 8698d5317Sjmmv * copyright notice and this permission notice appear in all copies. 9698d5317Sjmmv * 10698d5317Sjmmv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11698d5317Sjmmv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12698d5317Sjmmv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13698d5317Sjmmv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14698d5317Sjmmv * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15698d5317Sjmmv * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16698d5317Sjmmv * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17698d5317Sjmmv */ 18698d5317Sjmmv 19698d5317Sjmmv #include <sys/types.h> 20698d5317Sjmmv 21f26e8bc9Schristos #if defined(HAVE_CURSES_H) 22698d5317Sjmmv #include <curses.h> 23f26e8bc9Schristos #elif defined(HAVE_NCURSES_H) 240f3d2746Sjmmv #include <ncurses.h> 25698d5317Sjmmv #endif 26698d5317Sjmmv #include <fnmatch.h> 27698d5317Sjmmv #include <stdlib.h> 28698d5317Sjmmv #include <string.h> 29698d5317Sjmmv #include <term.h> 30698d5317Sjmmv 31698d5317Sjmmv #include "tmux.h" 32698d5317Sjmmv 33e9a2d6faSchristos static char *tty_term_strip(const char *); 34698d5317Sjmmv 350f3d2746Sjmmv struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms); 36698d5317Sjmmv 3799e242abSchristos enum tty_code_type { 3899e242abSchristos TTYCODE_NONE = 0, 3999e242abSchristos TTYCODE_STRING, 4099e242abSchristos TTYCODE_NUMBER, 4199e242abSchristos TTYCODE_FLAG, 42698d5317Sjmmv }; 43698d5317Sjmmv 4499e242abSchristos struct tty_code { 4599e242abSchristos enum tty_code_type type; 4699e242abSchristos union { 4799e242abSchristos char *string; 4899e242abSchristos int number; 4999e242abSchristos int flag; 5099e242abSchristos } value; 5199e242abSchristos }; 5299e242abSchristos 5399e242abSchristos struct tty_term_code_entry { 5499e242abSchristos enum tty_code_type type; 5599e242abSchristos const char *name; 5699e242abSchristos }; 5799e242abSchristos 58e9a2d6faSchristos static const struct tty_term_code_entry tty_term_codes[] = { 5999e242abSchristos [TTYC_ACSC] = { TTYCODE_STRING, "acsc" }, 60e271dbb8Schristos [TTYC_AM] = { TTYCODE_FLAG, "am" }, 6199e242abSchristos [TTYC_AX] = { TTYCODE_FLAG, "AX" }, 6299e242abSchristos [TTYC_BCE] = { TTYCODE_FLAG, "bce" }, 6399e242abSchristos [TTYC_BEL] = { TTYCODE_STRING, "bel" }, 64e271dbb8Schristos [TTYC_BIDI] = { TTYCODE_STRING, "Bidi" }, 6599e242abSchristos [TTYC_BLINK] = { TTYCODE_STRING, "blink" }, 6699e242abSchristos [TTYC_BOLD] = { TTYCODE_STRING, "bold" }, 6799e242abSchristos [TTYC_CIVIS] = { TTYCODE_STRING, "civis" }, 6899e242abSchristos [TTYC_CLEAR] = { TTYCODE_STRING, "clear" }, 69e271dbb8Schristos [TTYC_CLMG] = { TTYCODE_STRING, "Clmg" }, 70e271dbb8Schristos [TTYC_CMG] = { TTYCODE_STRING, "Cmg" }, 7199e242abSchristos [TTYC_CNORM] = { TTYCODE_STRING, "cnorm" }, 7299e242abSchristos [TTYC_COLORS] = { TTYCODE_NUMBER, "colors" }, 7399e242abSchristos [TTYC_CR] = { TTYCODE_STRING, "Cr" }, 7499e242abSchristos [TTYC_CSR] = { TTYCODE_STRING, "csr" }, 75fe99a117Schristos [TTYC_CS] = { TTYCODE_STRING, "Cs" }, 7699e242abSchristos [TTYC_CUB1] = { TTYCODE_STRING, "cub1" }, 77fe99a117Schristos [TTYC_CUB] = { TTYCODE_STRING, "cub" }, 7899e242abSchristos [TTYC_CUD1] = { TTYCODE_STRING, "cud1" }, 79fe99a117Schristos [TTYC_CUD] = { TTYCODE_STRING, "cud" }, 8099e242abSchristos [TTYC_CUF1] = { TTYCODE_STRING, "cuf1" }, 81fe99a117Schristos [TTYC_CUF] = { TTYCODE_STRING, "cuf" }, 8299e242abSchristos [TTYC_CUP] = { TTYCODE_STRING, "cup" }, 8399e242abSchristos [TTYC_CUU1] = { TTYCODE_STRING, "cuu1" }, 84fe99a117Schristos [TTYC_CUU] = { TTYCODE_STRING, "cuu" }, 8599e242abSchristos [TTYC_CVVIS] = { TTYCODE_STRING, "cvvis" }, 8699e242abSchristos [TTYC_DCH1] = { TTYCODE_STRING, "dch1" }, 87fe99a117Schristos [TTYC_DCH] = { TTYCODE_STRING, "dch" }, 8899e242abSchristos [TTYC_DIM] = { TTYCODE_STRING, "dim" }, 8999e242abSchristos [TTYC_DL1] = { TTYCODE_STRING, "dl1" }, 90fe99a117Schristos [TTYC_DL] = { TTYCODE_STRING, "dl" }, 91e271dbb8Schristos [TTYC_DSEKS] = { TTYCODE_STRING, "Dseks" }, 92e271dbb8Schristos [TTYC_DSFCS] = { TTYCODE_STRING, "Dsfcs" }, 93e271dbb8Schristos [TTYC_DSBP] = { TTYCODE_STRING, "Dsbp" }, 94e271dbb8Schristos [TTYC_DSMG] = { TTYCODE_STRING, "Dsmg" }, 9599e242abSchristos [TTYC_E3] = { TTYCODE_STRING, "E3" }, 9699e242abSchristos [TTYC_ECH] = { TTYCODE_STRING, "ech" }, 97e9a2d6faSchristos [TTYC_ED] = { TTYCODE_STRING, "ed" }, 9899e242abSchristos [TTYC_EL1] = { TTYCODE_STRING, "el1" }, 99fe99a117Schristos [TTYC_EL] = { TTYCODE_STRING, "el" }, 10099e242abSchristos [TTYC_ENACS] = { TTYCODE_STRING, "enacs" }, 101e271dbb8Schristos [TTYC_ENBP] = { TTYCODE_STRING, "Enbp" }, 102e271dbb8Schristos [TTYC_ENEKS] = { TTYCODE_STRING, "Eneks" }, 103e271dbb8Schristos [TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" }, 104e271dbb8Schristos [TTYC_ENMG] = { TTYCODE_STRING, "Enmg" }, 10599e242abSchristos [TTYC_FSL] = { TTYCODE_STRING, "fsl" }, 106f844e94eSwiz [TTYC_HLS] = { TTYCODE_STRING, "Hls" }, 10799e242abSchristos [TTYC_HOME] = { TTYCODE_STRING, "home" }, 10899e242abSchristos [TTYC_HPA] = { TTYCODE_STRING, "hpa" }, 10999e242abSchristos [TTYC_ICH1] = { TTYCODE_STRING, "ich1" }, 110fe99a117Schristos [TTYC_ICH] = { TTYCODE_STRING, "ich" }, 11199e242abSchristos [TTYC_IL1] = { TTYCODE_STRING, "il1" }, 112fe99a117Schristos [TTYC_IL] = { TTYCODE_STRING, "il" }, 113e9a2d6faSchristos [TTYC_INDN] = { TTYCODE_STRING, "indn" }, 11499e242abSchristos [TTYC_INVIS] = { TTYCODE_STRING, "invis" }, 11599e242abSchristos [TTYC_KCBT] = { TTYCODE_STRING, "kcbt" }, 11699e242abSchristos [TTYC_KCUB1] = { TTYCODE_STRING, "kcub1" }, 11799e242abSchristos [TTYC_KCUD1] = { TTYCODE_STRING, "kcud1" }, 11899e242abSchristos [TTYC_KCUF1] = { TTYCODE_STRING, "kcuf1" }, 11999e242abSchristos [TTYC_KCUU1] = { TTYCODE_STRING, "kcuu1" }, 12099e242abSchristos [TTYC_KDC2] = { TTYCODE_STRING, "kDC" }, 12199e242abSchristos [TTYC_KDC3] = { TTYCODE_STRING, "kDC3" }, 12299e242abSchristos [TTYC_KDC4] = { TTYCODE_STRING, "kDC4" }, 12399e242abSchristos [TTYC_KDC5] = { TTYCODE_STRING, "kDC5" }, 12499e242abSchristos [TTYC_KDC6] = { TTYCODE_STRING, "kDC6" }, 12599e242abSchristos [TTYC_KDC7] = { TTYCODE_STRING, "kDC7" }, 12699e242abSchristos [TTYC_KDCH1] = { TTYCODE_STRING, "kdch1" }, 127fe99a117Schristos [TTYC_KDN2] = { TTYCODE_STRING, "kDN" }, /* not kDN2 */ 12899e242abSchristos [TTYC_KDN3] = { TTYCODE_STRING, "kDN3" }, 12999e242abSchristos [TTYC_KDN4] = { TTYCODE_STRING, "kDN4" }, 13099e242abSchristos [TTYC_KDN5] = { TTYCODE_STRING, "kDN5" }, 13199e242abSchristos [TTYC_KDN6] = { TTYCODE_STRING, "kDN6" }, 13299e242abSchristos [TTYC_KDN7] = { TTYCODE_STRING, "kDN7" }, 13399e242abSchristos [TTYC_KEND2] = { TTYCODE_STRING, "kEND" }, 13499e242abSchristos [TTYC_KEND3] = { TTYCODE_STRING, "kEND3" }, 13599e242abSchristos [TTYC_KEND4] = { TTYCODE_STRING, "kEND4" }, 13699e242abSchristos [TTYC_KEND5] = { TTYCODE_STRING, "kEND5" }, 13799e242abSchristos [TTYC_KEND6] = { TTYCODE_STRING, "kEND6" }, 13899e242abSchristos [TTYC_KEND7] = { TTYCODE_STRING, "kEND7" }, 139fe99a117Schristos [TTYC_KEND] = { TTYCODE_STRING, "kend" }, 14099e242abSchristos [TTYC_KF10] = { TTYCODE_STRING, "kf10" }, 14199e242abSchristos [TTYC_KF11] = { TTYCODE_STRING, "kf11" }, 14299e242abSchristos [TTYC_KF12] = { TTYCODE_STRING, "kf12" }, 14399e242abSchristos [TTYC_KF13] = { TTYCODE_STRING, "kf13" }, 14499e242abSchristos [TTYC_KF14] = { TTYCODE_STRING, "kf14" }, 14599e242abSchristos [TTYC_KF15] = { TTYCODE_STRING, "kf15" }, 14699e242abSchristos [TTYC_KF16] = { TTYCODE_STRING, "kf16" }, 14799e242abSchristos [TTYC_KF17] = { TTYCODE_STRING, "kf17" }, 14899e242abSchristos [TTYC_KF18] = { TTYCODE_STRING, "kf18" }, 14999e242abSchristos [TTYC_KF19] = { TTYCODE_STRING, "kf19" }, 150fe99a117Schristos [TTYC_KF1] = { TTYCODE_STRING, "kf1" }, 15199e242abSchristos [TTYC_KF20] = { TTYCODE_STRING, "kf20" }, 15299e242abSchristos [TTYC_KF21] = { TTYCODE_STRING, "kf21" }, 15399e242abSchristos [TTYC_KF22] = { TTYCODE_STRING, "kf22" }, 15499e242abSchristos [TTYC_KF23] = { TTYCODE_STRING, "kf23" }, 15599e242abSchristos [TTYC_KF24] = { TTYCODE_STRING, "kf24" }, 15699e242abSchristos [TTYC_KF25] = { TTYCODE_STRING, "kf25" }, 15799e242abSchristos [TTYC_KF26] = { TTYCODE_STRING, "kf26" }, 15899e242abSchristos [TTYC_KF27] = { TTYCODE_STRING, "kf27" }, 15999e242abSchristos [TTYC_KF28] = { TTYCODE_STRING, "kf28" }, 16099e242abSchristos [TTYC_KF29] = { TTYCODE_STRING, "kf29" }, 161fe99a117Schristos [TTYC_KF2] = { TTYCODE_STRING, "kf2" }, 16299e242abSchristos [TTYC_KF30] = { TTYCODE_STRING, "kf30" }, 16399e242abSchristos [TTYC_KF31] = { TTYCODE_STRING, "kf31" }, 16499e242abSchristos [TTYC_KF32] = { TTYCODE_STRING, "kf32" }, 16599e242abSchristos [TTYC_KF33] = { TTYCODE_STRING, "kf33" }, 16699e242abSchristos [TTYC_KF34] = { TTYCODE_STRING, "kf34" }, 16799e242abSchristos [TTYC_KF35] = { TTYCODE_STRING, "kf35" }, 16899e242abSchristos [TTYC_KF36] = { TTYCODE_STRING, "kf36" }, 16999e242abSchristos [TTYC_KF37] = { TTYCODE_STRING, "kf37" }, 17099e242abSchristos [TTYC_KF38] = { TTYCODE_STRING, "kf38" }, 17199e242abSchristos [TTYC_KF39] = { TTYCODE_STRING, "kf39" }, 172fe99a117Schristos [TTYC_KF3] = { TTYCODE_STRING, "kf3" }, 17399e242abSchristos [TTYC_KF40] = { TTYCODE_STRING, "kf40" }, 17499e242abSchristos [TTYC_KF41] = { TTYCODE_STRING, "kf41" }, 17599e242abSchristos [TTYC_KF42] = { TTYCODE_STRING, "kf42" }, 17699e242abSchristos [TTYC_KF43] = { TTYCODE_STRING, "kf43" }, 17799e242abSchristos [TTYC_KF44] = { TTYCODE_STRING, "kf44" }, 17899e242abSchristos [TTYC_KF45] = { TTYCODE_STRING, "kf45" }, 17999e242abSchristos [TTYC_KF46] = { TTYCODE_STRING, "kf46" }, 18099e242abSchristos [TTYC_KF47] = { TTYCODE_STRING, "kf47" }, 18199e242abSchristos [TTYC_KF48] = { TTYCODE_STRING, "kf48" }, 18299e242abSchristos [TTYC_KF49] = { TTYCODE_STRING, "kf49" }, 183fe99a117Schristos [TTYC_KF4] = { TTYCODE_STRING, "kf4" }, 18499e242abSchristos [TTYC_KF50] = { TTYCODE_STRING, "kf50" }, 18599e242abSchristos [TTYC_KF51] = { TTYCODE_STRING, "kf51" }, 18699e242abSchristos [TTYC_KF52] = { TTYCODE_STRING, "kf52" }, 18799e242abSchristos [TTYC_KF53] = { TTYCODE_STRING, "kf53" }, 18899e242abSchristos [TTYC_KF54] = { TTYCODE_STRING, "kf54" }, 18999e242abSchristos [TTYC_KF55] = { TTYCODE_STRING, "kf55" }, 19099e242abSchristos [TTYC_KF56] = { TTYCODE_STRING, "kf56" }, 19199e242abSchristos [TTYC_KF57] = { TTYCODE_STRING, "kf57" }, 19299e242abSchristos [TTYC_KF58] = { TTYCODE_STRING, "kf58" }, 19399e242abSchristos [TTYC_KF59] = { TTYCODE_STRING, "kf59" }, 194fe99a117Schristos [TTYC_KF5] = { TTYCODE_STRING, "kf5" }, 19599e242abSchristos [TTYC_KF60] = { TTYCODE_STRING, "kf60" }, 19699e242abSchristos [TTYC_KF61] = { TTYCODE_STRING, "kf61" }, 19799e242abSchristos [TTYC_KF62] = { TTYCODE_STRING, "kf62" }, 19899e242abSchristos [TTYC_KF63] = { TTYCODE_STRING, "kf63" }, 199fe99a117Schristos [TTYC_KF6] = { TTYCODE_STRING, "kf6" }, 20099e242abSchristos [TTYC_KF7] = { TTYCODE_STRING, "kf7" }, 20199e242abSchristos [TTYC_KF8] = { TTYCODE_STRING, "kf8" }, 20299e242abSchristos [TTYC_KF9] = { TTYCODE_STRING, "kf9" }, 20399e242abSchristos [TTYC_KHOM2] = { TTYCODE_STRING, "kHOM" }, 20499e242abSchristos [TTYC_KHOM3] = { TTYCODE_STRING, "kHOM3" }, 20599e242abSchristos [TTYC_KHOM4] = { TTYCODE_STRING, "kHOM4" }, 20699e242abSchristos [TTYC_KHOM5] = { TTYCODE_STRING, "kHOM5" }, 20799e242abSchristos [TTYC_KHOM6] = { TTYCODE_STRING, "kHOM6" }, 20899e242abSchristos [TTYC_KHOM7] = { TTYCODE_STRING, "kHOM7" }, 20999e242abSchristos [TTYC_KHOME] = { TTYCODE_STRING, "khome" }, 21099e242abSchristos [TTYC_KIC2] = { TTYCODE_STRING, "kIC" }, 21199e242abSchristos [TTYC_KIC3] = { TTYCODE_STRING, "kIC3" }, 21299e242abSchristos [TTYC_KIC4] = { TTYCODE_STRING, "kIC4" }, 21399e242abSchristos [TTYC_KIC5] = { TTYCODE_STRING, "kIC5" }, 21499e242abSchristos [TTYC_KIC6] = { TTYCODE_STRING, "kIC6" }, 21599e242abSchristos [TTYC_KIC7] = { TTYCODE_STRING, "kIC7" }, 21699e242abSchristos [TTYC_KICH1] = { TTYCODE_STRING, "kich1" }, 217fe99a117Schristos [TTYC_KIND] = { TTYCODE_STRING, "kind" }, 21899e242abSchristos [TTYC_KLFT2] = { TTYCODE_STRING, "kLFT" }, 21999e242abSchristos [TTYC_KLFT3] = { TTYCODE_STRING, "kLFT3" }, 22099e242abSchristos [TTYC_KLFT4] = { TTYCODE_STRING, "kLFT4" }, 22199e242abSchristos [TTYC_KLFT5] = { TTYCODE_STRING, "kLFT5" }, 22299e242abSchristos [TTYC_KLFT6] = { TTYCODE_STRING, "kLFT6" }, 22399e242abSchristos [TTYC_KLFT7] = { TTYCODE_STRING, "kLFT7" }, 22499e242abSchristos [TTYC_KMOUS] = { TTYCODE_STRING, "kmous" }, 22599e242abSchristos [TTYC_KNP] = { TTYCODE_STRING, "knp" }, 22699e242abSchristos [TTYC_KNXT2] = { TTYCODE_STRING, "kNXT" }, 22799e242abSchristos [TTYC_KNXT3] = { TTYCODE_STRING, "kNXT3" }, 22899e242abSchristos [TTYC_KNXT4] = { TTYCODE_STRING, "kNXT4" }, 22999e242abSchristos [TTYC_KNXT5] = { TTYCODE_STRING, "kNXT5" }, 23099e242abSchristos [TTYC_KNXT6] = { TTYCODE_STRING, "kNXT6" }, 23199e242abSchristos [TTYC_KNXT7] = { TTYCODE_STRING, "kNXT7" }, 23299e242abSchristos [TTYC_KPP] = { TTYCODE_STRING, "kpp" }, 23399e242abSchristos [TTYC_KPRV2] = { TTYCODE_STRING, "kPRV" }, 23499e242abSchristos [TTYC_KPRV3] = { TTYCODE_STRING, "kPRV3" }, 23599e242abSchristos [TTYC_KPRV4] = { TTYCODE_STRING, "kPRV4" }, 23699e242abSchristos [TTYC_KPRV5] = { TTYCODE_STRING, "kPRV5" }, 23799e242abSchristos [TTYC_KPRV6] = { TTYCODE_STRING, "kPRV6" }, 23899e242abSchristos [TTYC_KPRV7] = { TTYCODE_STRING, "kPRV7" }, 23999e242abSchristos [TTYC_KRIT2] = { TTYCODE_STRING, "kRIT" }, 24099e242abSchristos [TTYC_KRIT3] = { TTYCODE_STRING, "kRIT3" }, 24199e242abSchristos [TTYC_KRIT4] = { TTYCODE_STRING, "kRIT4" }, 24299e242abSchristos [TTYC_KRIT5] = { TTYCODE_STRING, "kRIT5" }, 24399e242abSchristos [TTYC_KRIT6] = { TTYCODE_STRING, "kRIT6" }, 24499e242abSchristos [TTYC_KRIT7] = { TTYCODE_STRING, "kRIT7" }, 245fe99a117Schristos [TTYC_KRI] = { TTYCODE_STRING, "kri" }, 246fe99a117Schristos [TTYC_KUP2] = { TTYCODE_STRING, "kUP" }, /* not kUP2 */ 24799e242abSchristos [TTYC_KUP3] = { TTYCODE_STRING, "kUP3" }, 24899e242abSchristos [TTYC_KUP4] = { TTYCODE_STRING, "kUP4" }, 24999e242abSchristos [TTYC_KUP5] = { TTYCODE_STRING, "kUP5" }, 25099e242abSchristos [TTYC_KUP6] = { TTYCODE_STRING, "kUP6" }, 25199e242abSchristos [TTYC_KUP7] = { TTYCODE_STRING, "kUP7" }, 25299e242abSchristos [TTYC_MS] = { TTYCODE_STRING, "Ms" }, 253f844e94eSwiz [TTYC_NOBR] = { TTYCODE_STRING, "Nobr" }, 254e271dbb8Schristos [TTYC_OL] = { TTYCODE_STRING, "ol" }, 25599e242abSchristos [TTYC_OP] = { TTYCODE_STRING, "op" }, 25659b94b2cSchristos [TTYC_RECT] = { TTYCODE_STRING, "Rect" }, 25799e242abSchristos [TTYC_REV] = { TTYCODE_STRING, "rev" }, 258c7e17de0Schristos [TTYC_RGB] = { TTYCODE_FLAG, "RGB" }, 25930744affSchristos [TTYC_RIN] = { TTYCODE_STRING, "rin" }, 260e271dbb8Schristos [TTYC_RI] = { TTYCODE_STRING, "ri" }, 26199e242abSchristos [TTYC_RMACS] = { TTYCODE_STRING, "rmacs" }, 26299e242abSchristos [TTYC_RMCUP] = { TTYCODE_STRING, "rmcup" }, 26399e242abSchristos [TTYC_RMKX] = { TTYCODE_STRING, "rmkx" }, 26499e242abSchristos [TTYC_SETAB] = { TTYCODE_STRING, "setab" }, 26599e242abSchristos [TTYC_SETAF] = { TTYCODE_STRING, "setaf" }, 266e271dbb8Schristos [TTYC_SETAL] = { TTYCODE_STRING, "setal" }, 267fe99a117Schristos [TTYC_SETRGBB] = { TTYCODE_STRING, "setrgbb" }, 268fe99a117Schristos [TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" }, 26930744affSchristos [TTYC_SETULC] = { TTYCODE_STRING, "Setulc" }, 270f844e94eSwiz [TTYC_SETULC1] = { TTYCODE_STRING, "Setulc1" }, 271fe99a117Schristos [TTYC_SE] = { TTYCODE_STRING, "Se" }, 272f844e94eSwiz [TTYC_SXL] = { TTYCODE_FLAG, "Sxl" }, 27399e242abSchristos [TTYC_SGR0] = { TTYCODE_STRING, "sgr0" }, 27499e242abSchristos [TTYC_SITM] = { TTYCODE_STRING, "sitm" }, 27599e242abSchristos [TTYC_SMACS] = { TTYCODE_STRING, "smacs" }, 27699e242abSchristos [TTYC_SMCUP] = { TTYCODE_STRING, "smcup" }, 27799e242abSchristos [TTYC_SMKX] = { TTYCODE_STRING, "smkx" }, 27830744affSchristos [TTYC_SMOL] = { TTYCODE_STRING, "Smol" }, 27999e242abSchristos [TTYC_SMSO] = { TTYCODE_STRING, "smso" }, 2800a274e86Schristos [TTYC_SMULX] = { TTYCODE_STRING, "Smulx" }, 28199e242abSchristos [TTYC_SMUL] = { TTYCODE_STRING, "smul" }, 282e9a2d6faSchristos [TTYC_SMXX] = { TTYCODE_STRING, "smxx" }, 28399e242abSchristos [TTYC_SS] = { TTYCODE_STRING, "Ss" }, 28446548964Swiz [TTYC_SWD] = { TTYCODE_STRING, "Swd" }, 285e271dbb8Schristos [TTYC_SYNC] = { TTYCODE_STRING, "Sync" }, 286f26e8bc9Schristos [TTYC_TC] = { TTYCODE_FLAG, "Tc" }, 28799e242abSchristos [TTYC_TSL] = { TTYCODE_STRING, "tsl" }, 288fe99a117Schristos [TTYC_U8] = { TTYCODE_NUMBER, "U8" }, 28999e242abSchristos [TTYC_VPA] = { TTYCODE_STRING, "vpa" }, 290e271dbb8Schristos [TTYC_XT] = { TTYCODE_FLAG, "XT" } 29199e242abSchristos }; 29299e242abSchristos 29399e242abSchristos u_int 29499e242abSchristos tty_term_ncodes(void) 29599e242abSchristos { 29699e242abSchristos return (nitems(tty_term_codes)); 29799e242abSchristos } 29899e242abSchristos 299e9a2d6faSchristos static char * 300698d5317Sjmmv tty_term_strip(const char *s) 301698d5317Sjmmv { 302698d5317Sjmmv const char *ptr; 30330744affSchristos static char buf[8192]; 304698d5317Sjmmv size_t len; 305698d5317Sjmmv 306698d5317Sjmmv /* Ignore strings with no padding. */ 307698d5317Sjmmv if (strchr(s, '$') == NULL) 308698d5317Sjmmv return (xstrdup(s)); 309698d5317Sjmmv 310698d5317Sjmmv len = 0; 311698d5317Sjmmv for (ptr = s; *ptr != '\0'; ptr++) { 312698d5317Sjmmv if (*ptr == '$' && *(ptr + 1) == '<') { 313698d5317Sjmmv while (*ptr != '\0' && *ptr != '>') 314698d5317Sjmmv ptr++; 315698d5317Sjmmv if (*ptr == '>') 316698d5317Sjmmv ptr++; 317e271dbb8Schristos if (*ptr == '\0') 318e271dbb8Schristos break; 319698d5317Sjmmv } 320698d5317Sjmmv 321698d5317Sjmmv buf[len++] = *ptr; 322698d5317Sjmmv if (len == (sizeof buf) - 1) 323698d5317Sjmmv break; 324698d5317Sjmmv } 325698d5317Sjmmv buf[len] = '\0'; 326698d5317Sjmmv 327698d5317Sjmmv return (xstrdup(buf)); 328698d5317Sjmmv } 329698d5317Sjmmv 3300a274e86Schristos static char * 3310a274e86Schristos tty_term_override_next(const char *s, size_t *offset) 3320a274e86Schristos { 33330744affSchristos static char value[8192]; 3340a274e86Schristos size_t n = 0, at = *offset; 3350a274e86Schristos 3360a274e86Schristos if (s[at] == '\0') 3370a274e86Schristos return (NULL); 3380a274e86Schristos 3390a274e86Schristos while (s[at] != '\0') { 3400a274e86Schristos if (s[at] == ':') { 3410a274e86Schristos if (s[at + 1] == ':') { 3420a274e86Schristos value[n++] = ':'; 3430a274e86Schristos at += 2; 3440a274e86Schristos } else 3450a274e86Schristos break; 3460a274e86Schristos } else { 3470a274e86Schristos value[n++] = s[at]; 3480a274e86Schristos at++; 3490a274e86Schristos } 3500a274e86Schristos if (n == (sizeof value) - 1) 3510a274e86Schristos return (NULL); 3520a274e86Schristos } 3530a274e86Schristos if (s[at] != '\0') 3540a274e86Schristos *offset = at + 1; 3550a274e86Schristos else 3560a274e86Schristos *offset = at; 3570a274e86Schristos value[n] = '\0'; 3580a274e86Schristos return (value); 3590a274e86Schristos } 3600a274e86Schristos 361e271dbb8Schristos void 362e271dbb8Schristos tty_term_apply(struct tty_term *term, const char *capabilities, int quiet) 363698d5317Sjmmv { 3640f3d2746Sjmmv const struct tty_term_code_entry *ent; 365698d5317Sjmmv struct tty_code *code; 3660a274e86Schristos size_t offset = 0; 3670a274e86Schristos char *cp, *value, *s; 368e271dbb8Schristos const char *errstr, *name = term->name; 369698d5317Sjmmv u_int i; 370e9a2d6faSchristos int n, remove; 371698d5317Sjmmv 372e271dbb8Schristos while ((s = tty_term_override_next(capabilities, &offset)) != NULL) { 373e9a2d6faSchristos if (*s == '\0') 374e9a2d6faSchristos continue; 375e9a2d6faSchristos value = NULL; 376e9a2d6faSchristos 377e9a2d6faSchristos remove = 0; 378e9a2d6faSchristos if ((cp = strchr(s, '=')) != NULL) { 379e9a2d6faSchristos *cp++ = '\0'; 380e9a2d6faSchristos value = xstrdup(cp); 381e9a2d6faSchristos if (strunvis(value, cp) == -1) { 382e9a2d6faSchristos free(value); 383e9a2d6faSchristos value = xstrdup(cp); 384e9a2d6faSchristos } 385e9a2d6faSchristos } else if (s[strlen(s) - 1] == '@') { 386e9a2d6faSchristos s[strlen(s) - 1] = '\0'; 387e9a2d6faSchristos remove = 1; 388e9a2d6faSchristos } else 389e9a2d6faSchristos value = xstrdup(""); 390e9a2d6faSchristos 391e271dbb8Schristos if (!quiet) { 392e9a2d6faSchristos if (remove) 393e271dbb8Schristos log_debug("%s override: %s@", name, s); 3940a274e86Schristos else if (*value == '\0') 395e271dbb8Schristos log_debug("%s override: %s", name, s); 396e9a2d6faSchristos else 397e271dbb8Schristos log_debug("%s override: %s=%s", name, s, value); 398e271dbb8Schristos } 399e9a2d6faSchristos 40099e242abSchristos for (i = 0; i < tty_term_ncodes(); i++) { 401698d5317Sjmmv ent = &tty_term_codes[i]; 402e9a2d6faSchristos if (strcmp(s, ent->name) != 0) 403698d5317Sjmmv continue; 40499e242abSchristos code = &term->codes[i]; 405698d5317Sjmmv 406e9a2d6faSchristos if (remove) { 407698d5317Sjmmv code->type = TTYCODE_NONE; 408698d5317Sjmmv continue; 409698d5317Sjmmv } 410698d5317Sjmmv switch (ent->type) { 411698d5317Sjmmv case TTYCODE_NONE: 412698d5317Sjmmv break; 413698d5317Sjmmv case TTYCODE_STRING: 414698d5317Sjmmv if (code->type == TTYCODE_STRING) 41561fba46bSchristos free(code->value.string); 416e9a2d6faSchristos code->value.string = xstrdup(value); 417698d5317Sjmmv code->type = ent->type; 418698d5317Sjmmv break; 419698d5317Sjmmv case TTYCODE_NUMBER: 420e9a2d6faSchristos n = strtonum(value, 0, INT_MAX, &errstr); 421698d5317Sjmmv if (errstr != NULL) 422698d5317Sjmmv break; 423698d5317Sjmmv code->value.number = n; 424698d5317Sjmmv code->type = ent->type; 425698d5317Sjmmv break; 426698d5317Sjmmv case TTYCODE_FLAG: 427698d5317Sjmmv code->value.flag = 1; 428698d5317Sjmmv code->type = ent->type; 429698d5317Sjmmv break; 430698d5317Sjmmv } 431698d5317Sjmmv } 432698d5317Sjmmv 433e9a2d6faSchristos free(value); 434698d5317Sjmmv } 435698d5317Sjmmv } 436698d5317Sjmmv 437e271dbb8Schristos void 438e271dbb8Schristos tty_term_apply_overrides(struct tty_term *term) 439e271dbb8Schristos { 440e271dbb8Schristos struct options_entry *o; 441e271dbb8Schristos struct options_array_item *a; 442e271dbb8Schristos union options_value *ov; 44359b94b2cSchristos const char *s, *acs; 444e271dbb8Schristos size_t offset; 445e271dbb8Schristos char *first; 446e271dbb8Schristos 44759b94b2cSchristos /* Update capabilities from the option. */ 448e271dbb8Schristos o = options_get_only(global_options, "terminal-overrides"); 449e271dbb8Schristos a = options_array_first(o); 450e271dbb8Schristos while (a != NULL) { 451e271dbb8Schristos ov = options_array_item_value(a); 452e271dbb8Schristos s = ov->string; 453e271dbb8Schristos 454e271dbb8Schristos offset = 0; 455e271dbb8Schristos first = tty_term_override_next(s, &offset); 456e271dbb8Schristos if (first != NULL && fnmatch(first, term->name, 0) == 0) 457e271dbb8Schristos tty_term_apply(term, s + offset, 0); 458e271dbb8Schristos a = options_array_next(a); 459e271dbb8Schristos } 46059b94b2cSchristos 461f844e94eSwiz /* Log the SIXEL flag. */ 462f844e94eSwiz log_debug("SIXEL flag is %d", !!(term->flags & TERM_SIXEL)); 463f844e94eSwiz 46459b94b2cSchristos /* Update the RGB flag if the terminal has RGB colours. */ 46559b94b2cSchristos if (tty_term_has(term, TTYC_SETRGBF) && 46659b94b2cSchristos tty_term_has(term, TTYC_SETRGBB)) 46759b94b2cSchristos term->flags |= TERM_RGBCOLOURS; 46859b94b2cSchristos else 46959b94b2cSchristos term->flags &= ~TERM_RGBCOLOURS; 47059b94b2cSchristos log_debug("RGBCOLOURS flag is %d", !!(term->flags & TERM_RGBCOLOURS)); 47159b94b2cSchristos 47259b94b2cSchristos /* 47359b94b2cSchristos * Set or clear the DECSLRM flag if the terminal has the margin 47459b94b2cSchristos * capabilities. 47559b94b2cSchristos */ 47659b94b2cSchristos if (tty_term_has(term, TTYC_CMG) && tty_term_has(term, TTYC_CLMG)) 47759b94b2cSchristos term->flags |= TERM_DECSLRM; 47859b94b2cSchristos else 47959b94b2cSchristos term->flags &= ~TERM_DECSLRM; 48059b94b2cSchristos log_debug("DECSLRM flag is %d", !!(term->flags & TERM_DECSLRM)); 48159b94b2cSchristos 48259b94b2cSchristos /* 48359b94b2cSchristos * Set or clear the DECFRA flag if the terminal has the rectangle 48459b94b2cSchristos * capability. 48559b94b2cSchristos */ 48659b94b2cSchristos if (tty_term_has(term, TTYC_RECT)) 48759b94b2cSchristos term->flags |= TERM_DECFRA; 48859b94b2cSchristos else 48959b94b2cSchristos term->flags &= ~TERM_DECFRA; 49059b94b2cSchristos log_debug("DECFRA flag is %d", !!(term->flags & TERM_DECFRA)); 49159b94b2cSchristos 49259b94b2cSchristos /* 49359b94b2cSchristos * Terminals without am (auto right margin) wrap at at $COLUMNS - 1 49459b94b2cSchristos * rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1). 49559b94b2cSchristos * 49659b94b2cSchristos * Terminals without xenl (eat newline glitch) ignore a newline beyond 49759b94b2cSchristos * the right edge of the terminal, but tmux doesn't care about this - 49859b94b2cSchristos * it always uses absolute only moves the cursor with a newline when 49959b94b2cSchristos * also sending a linefeed. 50059b94b2cSchristos * 50159b94b2cSchristos * This is irritating, most notably because it is painful to write to 50259b94b2cSchristos * the very bottom-right of the screen without scrolling. 50359b94b2cSchristos * 50459b94b2cSchristos * Flag the terminal here and apply some workarounds in other places to 50559b94b2cSchristos * do the best possible. 50659b94b2cSchristos */ 50759b94b2cSchristos if (!tty_term_flag(term, TTYC_AM)) 50859b94b2cSchristos term->flags |= TERM_NOAM; 50959b94b2cSchristos else 51059b94b2cSchristos term->flags &= ~TERM_NOAM; 51159b94b2cSchristos log_debug("NOAM flag is %d", !!(term->flags & TERM_NOAM)); 51259b94b2cSchristos 51359b94b2cSchristos /* Generate ACS table. If none is present, use nearest ASCII. */ 51459b94b2cSchristos memset(term->acs, 0, sizeof term->acs); 51559b94b2cSchristos if (tty_term_has(term, TTYC_ACSC)) 51659b94b2cSchristos acs = tty_term_string(term, TTYC_ACSC); 51759b94b2cSchristos else 51859b94b2cSchristos acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~."; 51959b94b2cSchristos for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2) 52059b94b2cSchristos term->acs[(u_char) acs[0]][0] = acs[1]; 521e271dbb8Schristos } 522e271dbb8Schristos 523698d5317Sjmmv struct tty_term * 524e271dbb8Schristos tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps, 525e271dbb8Schristos int *feat, char **cause) 526698d5317Sjmmv { 527698d5317Sjmmv struct tty_term *term; 5280f3d2746Sjmmv const struct tty_term_code_entry *ent; 529698d5317Sjmmv struct tty_code *code; 530e9a2d6faSchristos struct options_entry *o; 5310a274e86Schristos struct options_array_item *a; 53230744affSchristos union options_value *ov; 533e271dbb8Schristos u_int i, j; 534*890b6d91Swiz const char *s, *value, *errstr; 535e271dbb8Schristos size_t offset, namelen; 536e271dbb8Schristos char *first; 537*890b6d91Swiz int n; 538698d5317Sjmmv 539e271dbb8Schristos log_debug("adding term %s", name); 540fe99a117Schristos 541e271dbb8Schristos term = xcalloc(1, sizeof *term); 542e271dbb8Schristos term->tty = tty; 543698d5317Sjmmv term->name = xstrdup(name); 54499e242abSchristos term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes); 5450f3d2746Sjmmv LIST_INSERT_HEAD(&tty_terms, term, entry); 546698d5317Sjmmv 547698d5317Sjmmv /* Fill in codes. */ 548e271dbb8Schristos for (i = 0; i < ncaps; i++) { 549e271dbb8Schristos namelen = strcspn(caps[i], "="); 550e271dbb8Schristos if (namelen == 0) 551e271dbb8Schristos continue; 552e271dbb8Schristos value = caps[i] + namelen + 1; 553698d5317Sjmmv 554e271dbb8Schristos for (j = 0; j < tty_term_ncodes(); j++) { 555e271dbb8Schristos ent = &tty_term_codes[j]; 556e271dbb8Schristos if (strncmp(ent->name, caps[i], namelen) != 0) 557e271dbb8Schristos continue; 558e271dbb8Schristos if (ent->name[namelen] != '\0') 559e271dbb8Schristos continue; 560e271dbb8Schristos 561e271dbb8Schristos code = &term->codes[j]; 562698d5317Sjmmv code->type = TTYCODE_NONE; 563698d5317Sjmmv switch (ent->type) { 564698d5317Sjmmv case TTYCODE_NONE: 565698d5317Sjmmv break; 566698d5317Sjmmv case TTYCODE_STRING: 567698d5317Sjmmv code->type = TTYCODE_STRING; 568e271dbb8Schristos code->value.string = tty_term_strip(value); 569698d5317Sjmmv break; 570698d5317Sjmmv case TTYCODE_NUMBER: 571*890b6d91Swiz n = strtonum(value, 0, INT_MAX, &errstr); 572*890b6d91Swiz if (errstr != NULL) 573*890b6d91Swiz log_debug("%s: %s", ent->name, errstr); 574*890b6d91Swiz else { 575698d5317Sjmmv code->type = TTYCODE_NUMBER; 576*890b6d91Swiz code->value.number = n; 577*890b6d91Swiz } 578698d5317Sjmmv break; 579698d5317Sjmmv case TTYCODE_FLAG: 580698d5317Sjmmv code->type = TTYCODE_FLAG; 581e271dbb8Schristos code->value.flag = (*value == '1'); 582698d5317Sjmmv break; 583698d5317Sjmmv } 584698d5317Sjmmv } 585e271dbb8Schristos } 58699e242abSchristos 587e271dbb8Schristos /* Apply terminal features. */ 588e271dbb8Schristos o = options_get_only(global_options, "terminal-features"); 5890a274e86Schristos a = options_array_first(o); 5900a274e86Schristos while (a != NULL) { 59130744affSchristos ov = options_array_item_value(a); 592e271dbb8Schristos s = ov->string; 593e271dbb8Schristos 594e271dbb8Schristos offset = 0; 595e271dbb8Schristos first = tty_term_override_next(s, &offset); 596e271dbb8Schristos if (first != NULL && fnmatch(first, term->name, 0) == 0) 597e271dbb8Schristos tty_add_features(feat, s + offset, ":"); 5980a274e86Schristos a = options_array_next(a); 599e9a2d6faSchristos } 600698d5317Sjmmv 601698d5317Sjmmv /* Delete curses data. */ 60261fba46bSchristos #if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \ 60361fba46bSchristos (NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6) 604698d5317Sjmmv del_curterm(cur_term); 605698d5317Sjmmv #endif 606698d5317Sjmmv 607e271dbb8Schristos /* Apply overrides so any capabilities used for features are changed. */ 608e271dbb8Schristos tty_term_apply_overrides(term); 609e271dbb8Schristos 610698d5317Sjmmv /* These are always required. */ 611698d5317Sjmmv if (!tty_term_has(term, TTYC_CLEAR)) { 612698d5317Sjmmv xasprintf(cause, "terminal does not support clear"); 613698d5317Sjmmv goto error; 614698d5317Sjmmv } 615698d5317Sjmmv if (!tty_term_has(term, TTYC_CUP)) { 616698d5317Sjmmv xasprintf(cause, "terminal does not support cup"); 617698d5317Sjmmv goto error; 618698d5317Sjmmv } 619698d5317Sjmmv 620e271dbb8Schristos /* 621e271dbb8Schristos * If TERM has XT or clear starts with CSI then it is safe to assume 622e271dbb8Schristos * the terminal is derived from the VT100. This controls whether device 623e271dbb8Schristos * attributes requests are sent to get more information. 624e271dbb8Schristos * 625e271dbb8Schristos * This is a bit of a hack but there aren't that many alternatives. 626e271dbb8Schristos * Worst case tmux will just fall back to using whatever terminfo(5) 627e271dbb8Schristos * says without trying to correct anything that is missing. 628e271dbb8Schristos * 629e271dbb8Schristos * Also add few features that VT100-like terminals should either 630e271dbb8Schristos * support or safely ignore. 631e271dbb8Schristos */ 632e271dbb8Schristos s = tty_term_string(term, TTYC_CLEAR); 633e271dbb8Schristos if (tty_term_flag(term, TTYC_XT) || strncmp(s, "\033[", 2) == 0) { 634e271dbb8Schristos term->flags |= TERM_VT100LIKE; 635e271dbb8Schristos tty_add_features(feat, "bpaste,focus,title", ","); 636698d5317Sjmmv } 637698d5317Sjmmv 638e271dbb8Schristos /* Add RGB feature if terminal has RGB colours. */ 639e271dbb8Schristos if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) && 640e271dbb8Schristos (!tty_term_has(term, TTYC_SETRGBF) || 641e271dbb8Schristos !tty_term_has(term, TTYC_SETRGBB))) 642e271dbb8Schristos tty_add_features(feat, "RGB", ","); 64368e6ba84Schristos 644e271dbb8Schristos /* Apply the features and overrides again. */ 64559b94b2cSchristos if (tty_apply_features(term, *feat)) 646e271dbb8Schristos tty_term_apply_overrides(term); 647e271dbb8Schristos 64868e6ba84Schristos /* Log the capabilities. */ 649fe99a117Schristos for (i = 0; i < tty_term_ncodes(); i++) 650fe99a117Schristos log_debug("%s%s", name, tty_term_describe(term, i)); 651fe99a117Schristos 652698d5317Sjmmv return (term); 653698d5317Sjmmv 654698d5317Sjmmv error: 655698d5317Sjmmv tty_term_free(term); 656698d5317Sjmmv return (NULL); 657698d5317Sjmmv } 658698d5317Sjmmv 659698d5317Sjmmv void 660698d5317Sjmmv tty_term_free(struct tty_term *term) 661698d5317Sjmmv { 662698d5317Sjmmv u_int i; 663698d5317Sjmmv 664e271dbb8Schristos log_debug("removing term %s", term->name); 665698d5317Sjmmv 66699e242abSchristos for (i = 0; i < tty_term_ncodes(); i++) { 667698d5317Sjmmv if (term->codes[i].type == TTYCODE_STRING) 66861fba46bSchristos free(term->codes[i].value.string); 669698d5317Sjmmv } 67099e242abSchristos free(term->codes); 67199e242abSchristos 672e271dbb8Schristos LIST_REMOVE(term, entry); 67361fba46bSchristos free(term->name); 67461fba46bSchristos free(term); 675698d5317Sjmmv } 676698d5317Sjmmv 677698d5317Sjmmv int 678e271dbb8Schristos tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps, 679e271dbb8Schristos char **cause) 680e271dbb8Schristos { 681e271dbb8Schristos const struct tty_term_code_entry *ent; 682e271dbb8Schristos int error, n; 683e271dbb8Schristos u_int i; 684e271dbb8Schristos const char *s; 685e271dbb8Schristos char tmp[11]; 686e271dbb8Schristos 68746548964Swiz if (setupterm(__UNCONST(name), fd, &error) != OK) { 688e271dbb8Schristos switch (error) { 689e271dbb8Schristos case 1: 690e271dbb8Schristos xasprintf(cause, "can't use hardcopy terminal: %s", 691e271dbb8Schristos name); 692e271dbb8Schristos break; 693e271dbb8Schristos case 0: 694e271dbb8Schristos xasprintf(cause, "missing or unsuitable terminal: %s", 695e271dbb8Schristos name); 696e271dbb8Schristos break; 697e271dbb8Schristos case -1: 698e271dbb8Schristos xasprintf(cause, "can't find terminfo database"); 699e271dbb8Schristos break; 700e271dbb8Schristos default: 701e271dbb8Schristos xasprintf(cause, "unknown error"); 702e271dbb8Schristos break; 703e271dbb8Schristos } 704e271dbb8Schristos return (-1); 705e271dbb8Schristos } 706e271dbb8Schristos 707e271dbb8Schristos *ncaps = 0; 708e271dbb8Schristos *caps = NULL; 709e271dbb8Schristos 710e271dbb8Schristos for (i = 0; i < tty_term_ncodes(); i++) { 711e271dbb8Schristos ent = &tty_term_codes[i]; 712e271dbb8Schristos switch (ent->type) { 713e271dbb8Schristos case TTYCODE_NONE: 714e271dbb8Schristos continue; 715e271dbb8Schristos case TTYCODE_STRING: 716e271dbb8Schristos s = tigetstr((const char *)ent->name); 717e271dbb8Schristos if (s == NULL || s == (char *)-1) 718e271dbb8Schristos continue; 719e271dbb8Schristos break; 720e271dbb8Schristos case TTYCODE_NUMBER: 721e271dbb8Schristos n = tigetnum((const char *)ent->name); 722e271dbb8Schristos if (n == -1 || n == -2) 723e271dbb8Schristos continue; 724e271dbb8Schristos xsnprintf(tmp, sizeof tmp, "%d", n); 725e271dbb8Schristos s = tmp; 726e271dbb8Schristos break; 727e271dbb8Schristos case TTYCODE_FLAG: 728e271dbb8Schristos n = tigetflag((const char *)ent->name); 729e271dbb8Schristos if (n == -1) 730e271dbb8Schristos continue; 731e271dbb8Schristos if (n) 732e271dbb8Schristos s = "1"; 733e271dbb8Schristos else 734e271dbb8Schristos s = "0"; 735e271dbb8Schristos break; 736e271dbb8Schristos default: 737f844e94eSwiz fatalx("unknown capability type"); 738e271dbb8Schristos } 739e271dbb8Schristos *caps = xreallocarray(*caps, (*ncaps) + 1, sizeof **caps); 740e271dbb8Schristos xasprintf(&(*caps)[*ncaps], "%s=%s", ent->name, s); 741e271dbb8Schristos (*ncaps)++; 742e271dbb8Schristos } 743e271dbb8Schristos 744e271dbb8Schristos #if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \ 745e271dbb8Schristos (NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6) 746e271dbb8Schristos del_curterm(cur_term); 747e271dbb8Schristos #endif 748e271dbb8Schristos return (0); 749e271dbb8Schristos } 750e271dbb8Schristos 751e271dbb8Schristos void 752e271dbb8Schristos tty_term_free_list(char **caps, u_int ncaps) 753e271dbb8Schristos { 754e271dbb8Schristos u_int i; 755e271dbb8Schristos 756e271dbb8Schristos for (i = 0; i < ncaps; i++) 757e271dbb8Schristos free(caps[i]); 758e271dbb8Schristos free(caps); 759e271dbb8Schristos } 760e271dbb8Schristos 761e271dbb8Schristos int 762698d5317Sjmmv tty_term_has(struct tty_term *term, enum tty_code_code code) 763698d5317Sjmmv { 764698d5317Sjmmv return (term->codes[code].type != TTYCODE_NONE); 765698d5317Sjmmv } 766698d5317Sjmmv 767698d5317Sjmmv const char * 768698d5317Sjmmv tty_term_string(struct tty_term *term, enum tty_code_code code) 769698d5317Sjmmv { 770698d5317Sjmmv if (!tty_term_has(term, code)) 771698d5317Sjmmv return (""); 772698d5317Sjmmv if (term->codes[code].type != TTYCODE_STRING) 773f26e8bc9Schristos fatalx("not a string: %d", code); 774698d5317Sjmmv return (term->codes[code].value.string); 775698d5317Sjmmv } 776698d5317Sjmmv 777698d5317Sjmmv const char * 778f844e94eSwiz tty_term_string_i(struct tty_term *term, enum tty_code_code code, int a) 779698d5317Sjmmv { 780f844e94eSwiz const char *x = tty_term_string(term, code), *s; 781f844e94eSwiz 782f844e94eSwiz #if defined(HAVE_TIPARM_S) 783f844e94eSwiz s = tiparm_s(1, 0, x, a); 784f844e94eSwiz #elif defined(HAVE_TIPARM) 785f844e94eSwiz s = tiparm(x, a); 786f844e94eSwiz #else 7873f0a6bcaSwiz s = tparm((char *)x, a, 0, 0, 0, 0, 0, 0, 0, 0); 788f844e94eSwiz #endif 789f844e94eSwiz if (s == NULL) { 790f844e94eSwiz log_debug("could not expand %s", tty_term_codes[code].name); 791f844e94eSwiz return (""); 792f844e94eSwiz } 793f844e94eSwiz return (s); 794698d5317Sjmmv } 795698d5317Sjmmv 796698d5317Sjmmv const char * 797f844e94eSwiz tty_term_string_ii(struct tty_term *term, enum tty_code_code code, int a, int b) 798698d5317Sjmmv { 799f844e94eSwiz const char *x = tty_term_string(term, code), *s; 800f844e94eSwiz 801f844e94eSwiz #if defined(HAVE_TIPARM_S) 802f844e94eSwiz s = tiparm_s(2, 0, x, a, b); 803f844e94eSwiz #elif defined(HAVE_TIPARM) 804f844e94eSwiz s = tiparm(x, a, b); 805f844e94eSwiz #else 8063f0a6bcaSwiz s = tparm((char *)x, a, b, 0, 0, 0, 0, 0, 0, 0); 807f844e94eSwiz #endif 808f844e94eSwiz if (s == NULL) { 809f844e94eSwiz log_debug("could not expand %s", tty_term_codes[code].name); 810f844e94eSwiz return (""); 811f844e94eSwiz } 812f844e94eSwiz return (s); 813698d5317Sjmmv } 814698d5317Sjmmv 8150f3d2746Sjmmv const char * 816f844e94eSwiz tty_term_string_iii(struct tty_term *term, enum tty_code_code code, int a, 817f844e94eSwiz int b, int c) 818fe99a117Schristos { 819f844e94eSwiz const char *x = tty_term_string(term, code), *s; 820f844e94eSwiz 821f844e94eSwiz #if defined(HAVE_TIPARM_S) 822f844e94eSwiz s = tiparm_s(3, 0, x, a, b, c); 823f844e94eSwiz #elif defined(HAVE_TIPARM) 824f844e94eSwiz s = tiparm(x, a, b, c); 825f844e94eSwiz #else 8263f0a6bcaSwiz s = tparm((char *)x, a, b, c, 0, 0, 0, 0, 0, 0); 827f844e94eSwiz #endif 828f844e94eSwiz if (s == NULL) { 829f844e94eSwiz log_debug("could not expand %s", tty_term_codes[code].name); 830f844e94eSwiz return (""); 831f844e94eSwiz } 832f844e94eSwiz return (s); 833fe99a117Schristos } 834fe99a117Schristos 835fe99a117Schristos const char * 836f844e94eSwiz tty_term_string_s(struct tty_term *term, enum tty_code_code code, const char *a) 8370f3d2746Sjmmv { 838f844e94eSwiz const char *x = tty_term_string(term, code), *s; 839f844e94eSwiz 840f844e94eSwiz #if defined(HAVE_TIPARM_S) 841f844e94eSwiz s = tiparm_s(1, 1, x, a); 842f844e94eSwiz #elif defined(HAVE_TIPARM) 843f844e94eSwiz s = tiparm(x, a); 844f844e94eSwiz #else 8453f0a6bcaSwiz s = tparm((char *)x, (long)a, 0, 0, 0, 0, 0, 0, 0, 0); 846f844e94eSwiz #endif 847f844e94eSwiz if (s == NULL) { 848f844e94eSwiz log_debug("could not expand %s", tty_term_codes[code].name); 849f844e94eSwiz return (""); 850f844e94eSwiz } 851f844e94eSwiz return (s); 8520f3d2746Sjmmv } 8530f3d2746Sjmmv 8540f3d2746Sjmmv const char * 855f844e94eSwiz tty_term_string_ss(struct tty_term *term, enum tty_code_code code, 856f844e94eSwiz const char *a, const char *b) 8570f3d2746Sjmmv { 858f844e94eSwiz const char *x = tty_term_string(term, code), *s; 859f844e94eSwiz 860f844e94eSwiz #if defined(HAVE_TIPARM_S) 861f844e94eSwiz s = tiparm_s(2, 3, x, a, b); 862f844e94eSwiz #elif defined(HAVE_TIPARM) 863f844e94eSwiz s = tiparm(x, a, b); 864f844e94eSwiz #else 8653f0a6bcaSwiz s = tparm((char *)x, (long)a, (long)b, 0, 0, 0, 0, 0, 0, 0); 866f844e94eSwiz #endif 867f844e94eSwiz if (s == NULL) { 868f844e94eSwiz log_debug("could not expand %s", tty_term_codes[code].name); 869f844e94eSwiz return (""); 870f844e94eSwiz } 871f844e94eSwiz return (s); 8720f3d2746Sjmmv } 8730f3d2746Sjmmv 874698d5317Sjmmv int 875698d5317Sjmmv tty_term_number(struct tty_term *term, enum tty_code_code code) 876698d5317Sjmmv { 877698d5317Sjmmv if (!tty_term_has(term, code)) 878698d5317Sjmmv return (0); 879698d5317Sjmmv if (term->codes[code].type != TTYCODE_NUMBER) 880f26e8bc9Schristos fatalx("not a number: %d", code); 881698d5317Sjmmv return (term->codes[code].value.number); 882698d5317Sjmmv } 883698d5317Sjmmv 884698d5317Sjmmv int 885698d5317Sjmmv tty_term_flag(struct tty_term *term, enum tty_code_code code) 886698d5317Sjmmv { 887698d5317Sjmmv if (!tty_term_has(term, code)) 888698d5317Sjmmv return (0); 889698d5317Sjmmv if (term->codes[code].type != TTYCODE_FLAG) 890f26e8bc9Schristos fatalx("not a flag: %d", code); 891698d5317Sjmmv return (term->codes[code].value.flag); 892698d5317Sjmmv } 89399e242abSchristos 89499e242abSchristos const char * 89599e242abSchristos tty_term_describe(struct tty_term *term, enum tty_code_code code) 89699e242abSchristos { 89799e242abSchristos static char s[256]; 89899e242abSchristos char out[128]; 89999e242abSchristos 90099e242abSchristos switch (term->codes[code].type) { 90199e242abSchristos case TTYCODE_NONE: 90299e242abSchristos xsnprintf(s, sizeof s, "%4u: %s: [missing]", 90399e242abSchristos code, tty_term_codes[code].name); 90499e242abSchristos break; 90599e242abSchristos case TTYCODE_STRING: 90699e242abSchristos strnvis(out, sizeof out, term->codes[code].value.string, 90730744affSchristos VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL); 90899e242abSchristos xsnprintf(s, sizeof s, "%4u: %s: (string) %s", 90999e242abSchristos code, tty_term_codes[code].name, 91099e242abSchristos out); 91199e242abSchristos break; 91299e242abSchristos case TTYCODE_NUMBER: 91399e242abSchristos xsnprintf(s, sizeof s, "%4u: %s: (number) %d", 91499e242abSchristos code, tty_term_codes[code].name, 91599e242abSchristos term->codes[code].value.number); 91699e242abSchristos break; 91799e242abSchristos case TTYCODE_FLAG: 91899e242abSchristos xsnprintf(s, sizeof s, "%4u: %s: (flag) %s", 91999e242abSchristos code, tty_term_codes[code].name, 92099e242abSchristos term->codes[code].value.flag ? "true" : "false"); 92199e242abSchristos break; 92299e242abSchristos } 92399e242abSchristos return (s); 92499e242abSchristos } 925