X-Git-Url: http://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_setup.c;h=976227effade9116f1253868123a52390a2911b7;hb=HEAD;hp=4752ba899d4d884414a4cb17dcaedc46512cf93a;hpb=19c0d4acfed45a13096019aa305a63b657fdb24c;p=ncurses.git diff --git a/ncurses/tinfo/lib_setup.c b/ncurses/tinfo/lib_setup.c index 4752ba89..66226b11 100644 --- a/ncurses/tinfo/lib_setup.c +++ b/ncurses/tinfo/lib_setup.c @@ -49,7 +49,7 @@ #include #endif -MODULE_ID("$Id: lib_setup.c,v 1.231 2024/02/04 00:09:34 tom Exp $") +MODULE_ID("$Id: lib_setup.c,v 1.241 2024/05/11 19:07:34 tom Exp $") /**************************************************************************** * @@ -332,7 +332,9 @@ get_position(TERMINAL *termp, int fd, int *row, int *col) int y, x; char buf[20]; char *s; - char ignore; + char cc; + const char *skipped; + int scanned; s = memset(buf, '\0', sizeof(buf)); do { @@ -343,51 +345,91 @@ get_position(TERMINAL *termp, int fd, int *row, int *col) s += got; *s = '\0'; } while (strchr(buf, 'R') == NULL && (size_t) (s + 1 - buf) < sizeof(buf)); - T(("response %s", _nc_visbuf(buf))); - if (sscanf(skip_csi(buf), "%d;%d%c", &y, &x, &ignore) != 2 - || (ignore != 'R' && ignore != ';')) { + T(("CPR response %s", _nc_visbuf(buf))); + skipped = skip_csi(buf); + cc = '\0'; + if (skipped != buf + && *skipped != '\0' + && (scanned = sscanf(skip_csi(buf), "%d;%d%c", &y, &x, &cc)) == 3 + && (cc == 'R')) { *row = y; *col = x; result = TRUE; } } - T(("get_position %d,%d", *row, *col)); + T(("get_position %s %d,%d", result ? "OK" : "ERR", *row, *col)); return result; } static bool -set_position(TERMINAL *termp, int fd, int row, int col) +set_position(NCURSES_SP_DCLx TERMINAL *termp, int row, int col) { - bool result = FALSE; + bool result; char *actual = TIPARM_2(cursor_address, row, col); - T(("set_position %d,%d", row, col)); + T((T_CALLED("set_position %d,%d)"), row, col)); +#if NCURSES_SP_FUNCS + result = (NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "set_position", + actual) == OK); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); +#else + /* This does not support padding because without sp-funcs, we have only + * the interface using stdio, but we are not guaranteed that Filedes + * is the same as fileno(stdout). + */ + result = FALSE; if (actual != NULL) { size_t want = strlen(actual); - int have = (int) write(fd, actual, want); /* FIXME - padding */ + int have = (int) write(termp->Filedes, actual, want); result = ((int) want == have); } - return result; +#endif + returnBool(result); } /* * This is a little more complicated than one might expect, because we do this - * before setting up the terminal modes, etc. + * before setting up the terminal modes, etc., and cannot use the timeout or + * buffering functions. + * + * We check if the terminal description has the ECMA-48 CPR (cursor position + * report) in u7 and the response in u6. The two variations of is_expected() + * cover the termcap style and terminfo style, and are equivalent as far as we + * are concerned. For analyzing the response, we wait (a short time) for 'R' + * to be echoed, and then check if we received two integers in the response. + * + * In principle, this could run on "any" ECMA-48 terminal, but in practice, + * there is a scenario using GNU screen where it uses ncurses with a partially + * configured pseudo-terminal, and the CPR response goes to the wrong place. + * So we do a simple check to exclude pseudo-terminals. */ static void -_nc_check_screensize(TERMINAL *termp, int *linep, int *colp) +_nc_check_screensize(SCREEN *sp, TERMINAL *termp, int *linep, int *colp) { - int fd = fileno(stderr); + int fd = termp->Filedes; TTY saved; + const char *name = NULL; - if (NC_ISATTY(fd) + if (IsRealTty(fd, name) && VALID_STRING(cursor_address) && is_expected(user7, "6n") - && is_expected(user6, "%i%d;%dR") + && (is_expected(user6, "%i%d;%dR") || + is_expected(user6, "%i%p1%d;%p2%dR")) && GET_TTY(fd, &saved) == OK) { - int current_y, current_x; - int updated_y, updated_x; + int current_y = -1, current_x = -1; + int updated_y = -1, updated_x = -1; TTY alter = saved; +#if NCURSES_SP_FUNCS + if (sp == NULL) { + sp = new_prescr(); + sp->_term = termp; + NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); + } +#else + (void) sp; +#endif + + T(("trying CPR (u7/u6) with %s", name)); alter.c_lflag &= (unsigned) ~(ECHO | ICANON | ISIG | IEXTEN); alter.c_iflag &= (unsigned) ~(IXON | BRKINT | PARMRK); alter.c_cc[VMIN] = 0; @@ -395,20 +437,23 @@ _nc_check_screensize(TERMINAL *termp, int *linep, int *colp) SET_TTY(fd, &alter); if (get_position(termp, fd, ¤t_y, ¤t_x) - && set_position(termp, fd, 9999, 9999) + && set_position(NCURSES_SP_ARGx termp, 9999, 9999) && get_position(termp, fd, &updated_y, &updated_x)) { *linep = updated_y; *colp = updated_x; - set_position(termp, fd, current_y, current_x); + set_position(NCURSES_SP_ARGx termp, current_y, current_x); } /* restore tty modes */ SET_TTY(fd, &saved); + } else { + T(("NOT trying CPR with fd %d (%s): %s", + fd, NonNull(name), NC_ISATTY(fd) ? "tty" : "not a tty")); } _nc_default_screensize(termp, linep, colp); } #else /* !USE_CHECK_SIZE */ -#define _nc_check_screensize(termp, linep, colp) /* nothing */ +#define _nc_check_screensize(sp, termp, linep, colp) /* nothing */ #endif #endif /* !(defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER)) */ @@ -445,6 +490,7 @@ _nc_get_screensize(SCREEN *sp, bool useEnv = _nc_prescreen.use_env; bool useTioctl = _nc_prescreen.use_tioctl; + T((T_CALLED("_nc_get_screensize (%p)"), (void *) sp)); #ifdef EXP_WIN32_DRIVER /* If we are here, then Windows console is used in terminfo mode. We need to figure out the size using the console API @@ -466,6 +512,7 @@ _nc_get_screensize(SCREEN *sp, } #endif + T(("useEnv:%d useTioctl:%d", useEnv, useTioctl)); if (useEnv || useTioctl) { #ifdef __EMX__ { @@ -522,17 +569,17 @@ _nc_get_screensize(SCREEN *sp, * variable. */ if ((value = _nc_getenv_num("LINES")) > 0) { - *linep = value; + *linep = Min(value, MAX_ENV_LINES); T(("screen size: environment LINES = %d", *linep)); } if ((value = _nc_getenv_num("COLUMNS")) > 0) { - *colp = value; + *colp = Min(value, MAX_ENV_COLUMNS); T(("screen size: environment COLUMNS = %d", *colp)); } _nc_default_screensize(termp, linep, colp); } else { - _nc_check_screensize(termp, linep, colp); + _nc_check_screensize(sp, termp, linep, colp); } /* @@ -548,7 +595,7 @@ _nc_get_screensize(SCREEN *sp, OldNumber(termp, columns) = (short) (*colp); #endif } else { - _nc_check_screensize(termp, linep, colp); + _nc_check_screensize(sp, termp, linep, colp); } T(("screen size is %dx%d", *linep, *colp)); @@ -565,6 +612,7 @@ _nc_get_screensize(SCREEN *sp, TABSIZE = my_tabsize; #endif T(("TABSIZE = %d", TABSIZE)); + returnVoid; #endif /* USE_TERM_DRIVER */ }