+static bool
+set_position(NCURSES_SP_DCLx TERMINAL *termp, int row, int col)
+{
+ bool result;
+ char *actual = TIPARM_2(cursor_address, 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(termp->Filedes, actual, want);
+ result = ((int) want == have);
+ }
+#endif
+ returnBool(result);
+}
+
+/*
+ * This is a little more complicated than one might expect, because we do this
+ * 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(SCREEN *sp, TERMINAL *termp, int *linep, int *colp)
+{
+ int fd = termp->Filedes;
+ TTY saved;
+ const char *name = NULL;
+
+ if (IsRealTty(fd, name)
+ && VALID_STRING(cursor_address)
+ && is_expected(user7, "6n")
+ && (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;
+
+#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;
+ alter.c_cc[VTIME] = 1;
+ SET_TTY(fd, &alter);
+
+ if (get_position(termp, fd, ¤t_y, ¤t_x)
+ && set_position(NCURSES_SP_ARGx termp, 9999, 9999)
+ && get_position(termp, fd, &updated_y, &updated_x)) {
+ *linep = updated_y;
+ *colp = updated_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(sp, termp, linep, colp) /* nothing */
+#endif
+#endif /* !(defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER)) */
+
+NCURSES_EXPORT(void)
+_nc_get_screensize(SCREEN *sp,
+#ifdef USE_TERM_DRIVER
+ TERMINAL *termp,
+#endif
+ int *linep, int *colp)
+/* Obtain lines/columns values from the environment and/or terminfo entry */
+{
+#ifdef USE_TERM_DRIVER
+ TERMINAL_CONTROL_BLOCK *TCB;
+ int my_tabsize;
+
+ assert(termp != 0 && linep != 0 && colp != 0);
+ TCB = (TERMINAL_CONTROL_BLOCK *) termp;
+
+ my_tabsize = TCB->info.tabsize;
+ TCB->drv->td_size(TCB, linep, colp);
+
+#if USE_REENTRANT
+ if (sp != 0) {
+ sp->_TABSIZE = my_tabsize;
+ }
+#else
+ (void) sp;
+ TABSIZE = my_tabsize;
+#endif
+ T(("TABSIZE = %d", my_tabsize));
+#else /* !USE_TERM_DRIVER */
+ TERMINAL *termp = cur_term;
+ int my_tabsize;
+ 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
+ */
+ _nc_console_size(linep, colp);
+ T(("screen size: winconsole lines = %d columns = %d", *linep, *colp));
+#else
+ /* figure out the size of the screen */
+ T(("screen size: terminfo lines = %d columns = %d", lines, columns));
+
+ *linep = (int) lines;
+ *colp = (int) columns;
+#endif
+
+#if NCURSES_SP_FUNCS
+ if (sp) {
+ useEnv = sp->_use_env;
+ useTioctl = sp->use_tioctl;
+ }
+#endif
+
+ T(("useEnv:%d useTioctl:%d", useEnv, useTioctl));
+ if (useEnv || useTioctl) {