+#if !(defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER))
+static void
+_nc_default_screensize(TERMINAL *termp, int *linep, int *colp)
+{
+ /* if we can't get dynamic info about the size, use static */
+ if (*linep <= 0) {
+ *linep = (int) lines;
+ }
+ if (*colp <= 0) {
+ *colp = (int) columns;
+ }
+
+ /* the ultimate fallback, assume fixed 24x80 size */
+ if (*linep <= 0) {
+ *linep = 24;
+ }
+ if (*colp <= 0) {
+ *colp = 80;
+ }
+}
+
+#if defined(USE_CHECK_SIZE) && defined(user6) && defined(user7)
+static const char *
+skip_csi(const char *value)
+{
+ if (UChar(*value) == CSI_CHR) {
+ ++value;
+ } else if (*value == ESC_CHR && value[1] == L_BLOCK) {
+ value += 2;
+ }
+ return value;
+}
+
+static bool
+is_expected(const char *value, const char *expected)
+{
+ bool result = FALSE;
+ if (VALID_STRING(value)) {
+ const char *skipped = skip_csi(value);
+ if (skipped != value) {
+ if (!strcmp(skipped, expected))
+ result = TRUE;
+ }
+ }
+ return result;
+}
+
+static bool
+get_position(TERMINAL *termp, int fd, int *row, int *col)
+{
+ bool result = FALSE;
+ size_t need = strlen(user7);
+ int have;
+
+ have = (int) write(fd, user7, need);
+
+ if (have == (int) need) {
+ int y, x;
+ char buf[20];
+ char *s;
+ char cc;
+ const char *skipped;
+ int scanned;
+
+ s = memset(buf, '\0', sizeof(buf));
+ do {
+ size_t ask = (sizeof(buf) - 1 - (size_t) (s - buf));
+ int got = (int) read(fd, s, ask);
+ if (got == 0)
+ break;
+ s += got;
+ *s = '\0';
+ } while (strchr(buf, 'R') == NULL && (size_t) (s + 1 - buf) < sizeof(buf));
+ 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 %s %d,%d", result ? "OK" : "ERR", *row, *col));
+ return result;
+}
+
+static bool
+set_position(TERMINAL *termp, int fd, int row, int col)
+{
+ bool result = FALSE;
+ char *actual = TIPARM_2(cursor_address, row, col);
+ T(("set_position %d,%d", row, col));
+ if (actual != NULL) {
+ size_t want = strlen(actual);
+ int have = (int) write(fd, actual, want); /* FIXME - padding */
+ result = ((int) want == have);
+ }
+ return 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(TERMINAL *termp, int *linep, int *colp)
+{
+ 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%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;
+ alter.c_cc[VTIME] = 1;
+ SET_TTY(fd, &alter);
+
+ if (get_position(termp, fd, ¤t_y, ¤t_x)
+ && set_position(termp, fd, 9999, 9999)
+ && get_position(termp, fd, &updated_y, &updated_x)) {
+ *linep = updated_y;
+ *colp = updated_x;
+ set_position(termp, fd, current_y, current_x);
+ }
+ /* restore tty modes */
+ SET_TTY(fd, &saved);
+ }
+
+ _nc_default_screensize(termp, linep, colp);
+}
+#else /* !USE_CHECK_SIZE */
+#define _nc_check_screensize(termp, linep, colp) /* nothing */
+#endif
+#endif /* !(defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER)) */
+