#include <locale.h>
#endif
-MODULE_ID("$Id: lib_setup.c,v 1.232 2024/03/02 19:42:13 tom Exp $")
+MODULE_ID("$Id: lib_setup.c,v 1.233 2024/03/16 23:39:28 tom Exp $")
/****************************************************************************
*
int y, x;
char buf[20];
char *s;
- char ignore;
+ char cc;
+ const char *skipped;
+ int scanned;
s = memset(buf, '\0', sizeof(buf));
do {
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;
}
/*
* 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)
{
- int fd = fileno(stderr);
+ int fd = termp->Filedes;
TTY saved;
+ const char *name;
if (NC_ISATTY(fd)
+ && (name = ttyname(fd)) != NULL
+ && strncmp(name, "/dev/pts/", 9)
&& 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 = -1, current_x = -1;
int updated_y = -1, updated_x = -1;
TTY alter = saved;
+ T(("checking screensize of %s", name));
alter.c_lflag &= (unsigned) ~(ECHO | ICANON | ISIG | IEXTEN);
alter.c_iflag &= (unsigned) ~(IXON | BRKINT | PARMRK);
alter.c_cc[VMIN] = 0;
bool useEnv = _nc_prescreen.use_env;
bool useTioctl = _nc_prescreen.use_tioctl;
+ T((T_CALLED("_nc_get_screensize (%p)"), 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
}
#endif
+ T(("useEnv:%d useTioctl:%d", useEnv, useTioctl));
if (useEnv || useTioctl) {
#ifdef __EMX__
{
TABSIZE = my_tabsize;
#endif
T(("TABSIZE = %d", TABSIZE));
+ returnVoid;
#endif /* USE_TERM_DRIVER */
}