X-Git-Url: https://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=progs%2Ftic.c;h=6f562126ce2be2bb9f6881f637ffe9d842a6c16d;hb=6cd4a712ad4ac58bf801e5dc66648338d2aa294e;hp=152010d260c416872a158f50ef2b7fb16f8d6215;hpb=80803f3a4a1fbdebb4de105cef9a10af36230f3c;p=ncurses.git diff --git a/progs/tic.c b/progs/tic.c index 152010d2..6f562126 100644 --- a/progs/tic.c +++ b/progs/tic.c @@ -49,7 +49,7 @@ #include #include -MODULE_ID("$Id: tic.c,v 1.311 2022/04/23 19:47:57 tom Exp $") +MODULE_ID("$Id: tic.c,v 1.315 2022/07/02 20:40:22 tom Exp $") #define STDIN_NAME "" @@ -2977,6 +2977,186 @@ check_user_capability_type(const char *name, int actual) } #endif +#define IN_DELAY "0123456789*/." + +static bool +check_ANSI_cap(const char *value, int nparams, char final) +{ + bool result = FALSE; + if (VALID_STRING(value) && csi_length(value) > 0) { + char *p_is_s[NUM_PARM]; + int popcount; + int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount); + if (analyzed < popcount) { + analyzed = popcount; + } + if (analyzed == nparams) { + bool numbers = TRUE; + int p; + for (p = 0; p < nparams; ++p) { + if (p_is_s[p]) { + numbers = FALSE; + break; + } + } + if (numbers) { + int in_delay = 0; + p = (int) strlen(value); + while (p-- > 0) { + char ch = value[p]; + if (ch == final) { + result = TRUE; + break; + } + switch (in_delay) { + case 0: + if (ch == '>') + in_delay = 1; + break; + case 1: + if (strchr(IN_DELAY, value[p]) != NULL) + break; + if (ch != '<') + p = 0; + in_delay = 2; + break; + case 2: + if (ch != '$') + p = 0; + in_delay = 0; + break; + } + } + } + } + } + return result; +} + +static const char * +skip_Delay(const char *value) +{ + const char *result = value; + + if (*value == '$') { + ++result; + if (*result++ == '<') { + while (strchr(IN_DELAY, *result) != NULL) + ++result; + if (*result++ != '>') { + result = value; + } + } else { + result = value; + } + } + return result; +} + +static bool +isValidString(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (!strcmp(value, expect)) + result = TRUE; + } + return result; +} + +static bool +isValidEscape(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (*value == '\033') { + size_t need = strlen(expect); + size_t have = strlen(value) - 1; + if (have >= need && !strncmp(value + 1, expect, need)) { + if (*skip_Delay(value + need + 1) == '\0') { + result = TRUE; + } + } + } + } + return result; +} + +static int +guess_ANSI_VTxx(TERMTYPE2 *tp) +{ + int result = -1; + int checks = 0; + + /* VT100s have scrolling region, but ANSI (ECMA-48) does not specify */ + if (check_ANSI_cap(change_scroll_region, 2, 'r') && + (isValidEscape(scroll_forward, "D") || + isValidString(scroll_forward, "\n") || + isValidEscape(scroll_forward, "6")) && + (isValidEscape(scroll_reverse, "M") || + isValidEscape(scroll_reverse, "9"))) { + checks |= 2; + } + if (check_ANSI_cap(cursor_address, 2, 'H') && + check_ANSI_cap(cursor_up, 0, 'A') && + (check_ANSI_cap(cursor_down, 0, 'B') || + isValidString(cursor_down, "\n")) && + check_ANSI_cap(cursor_right, 0, 'C') && + (check_ANSI_cap(cursor_left, 0, 'D') || + isValidString(cursor_left, "\b")) && + check_ANSI_cap(clr_eos, 0, 'J') && + check_ANSI_cap(clr_bol, 0, 'K') && + check_ANSI_cap(clr_eol, 0, 'K')) { + checks |= 1; + } + if (checks == 3) + result = 1; + if (checks == 1) + result = 0; + return result; +} + +/* + * u6/u7 and u8/u9 are query/response extensions which most terminals support. + * In particular, any ECMA-48 terminal should support these, though the details + * for u9 are implementation dependent. + */ +static void +check_user_6789(TERMTYPE2 *tp) +{ + /* + * Check if the terminal is known to not + */ +#define NO_QUERY(longname,shortname) \ + if (PRESENT(longname)) _nc_warning(#shortname " is not supported") + if (tigetflag("NQ") > 0) { + NO_QUERY(user6, u6); + NO_QUERY(user7, u7); + NO_QUERY(user8, u8); + NO_QUERY(user9, u9); + return; + } + + PAIRED(user6, user7); + PAIRED(user8, user9); + + if (strchr(tp->term_names, '+') != NULL) + return; + + switch (guess_ANSI_VTxx(tp)) { + case 1: + if (!PRESENT(user8)) { + _nc_warning("expected u8/u9 for device-attributes"); + } + /* FALLTHRU */ + case 0: + if (!PRESENT(user6)) { + _nc_warning("expected u6/u7 for cursor-position"); + } + break; + } +} + /* other sanity-checks (things that we don't want in the normal * logic that reads a terminfo entry) */ @@ -3025,6 +3205,7 @@ check_termtype(TERMTYPE2 *tp, bool literal) check_keypad(tp); check_printer(tp); check_screen(tp); + check_user_6789(tp); /* * These are probably both or none.