#include <locale.h>
#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 $")
/****************************************************************************
*
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;
}
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;
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)) */
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
}
#endif
+ T(("useEnv:%d useTioctl:%d", useEnv, useTioctl));
if (useEnv || useTioctl) {
#ifdef __EMX__
{
* 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);
}
/*
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));
TABSIZE = my_tabsize;
#endif
T(("TABSIZE = %d", TABSIZE));
+ returnVoid;
#endif /* USE_TERM_DRIVER */
}