diff --git a/src/backend/modern.lisp b/src/backend/modern.lisp index a0b8bd1..4c15fcf 100644 --- a/src/backend/modern.lisp +++ b/src/backend/modern.lisp @@ -164,29 +164,34 @@ as a fallback when a keyword is not in *named-colors*.") (values)) (defmethod backend-size ((b modern-backend)) - (or (ignore-errors - (let* ((+tiocgwinsz+ 21523) ; 0x5413 on Linux - (winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) - (unwind-protect - (progn - (sb-unix:unix-ioctl (sb-sys:fd-stream-fd (backend-output-stream b)) - +tiocgwinsz+ - (sb-alien:alien-sap winsize)) + (multiple-value-bind (w h) + (or (ignore-errors + (let* ((+tiocgwinsz+ 21523) ; 0x5413 on Linux + (winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) + (unwind-protect + (progn + (sb-unix:unix-ioctl (sb-sys:fd-stream-fd (backend-output-stream b)) + +tiocgwinsz+ + (sb-alien:alien-sap winsize)) (values (sb-alien:deref winsize 1) ;; cols - (sb-alien:deref winsize 0))) ;; rows - (sb-alien:free-alien winsize)))) - ;; $COLUMNS / $LINES env vars — set by every POSIX shell. - ;; Catches cases where ioctl on stdout's fd disagrees with - ;; the real terminal size (e.g. stdout redirected or a - ;; file descriptor mismatch). - (ignore-errors - (let ((cols (parse-integer (sb-ext:posix-getenv "COLUMNS") - :junk-allowed t)) - (rows (parse-integer (sb-ext:posix-getenv "LINES") - :junk-allowed t))) - (when (and cols rows (> cols 0) (> rows 0)) - (values cols rows)))) - (values 80 24))) + (sb-alien:deref winsize 0))) ;; rows + (sb-alien:free-alien winsize)))) + (values 0 0)) + ;; If ioctl returned a plausible size (not the 80x24 default), + ;; trust it — it will be correct at runtime after SIGWINCH. + (if (and (> w 80) (> h 24)) + (values w h) + ;; ioctl returned 80x24 or less — suspicious. Try $COLUMNS/ + ;; $LINES from the shell, which reflect the true size at + ;; process start even when ioctl on stdout's fd disagrees. + (or (ignore-errors + (let ((cols (parse-integer (sb-ext:posix-getenv "COLUMNS") + :junk-allowed t)) + (rows (parse-integer (sb-ext:posix-getenv "LINES") + :junk-allowed t))) + (when (and cols rows (> cols 0) (> rows 0)) + (values cols rows)))) + (values w h))))) (defmethod backend-write ((b modern-backend) string) (let ((stream (backend-output-stream b))) diff --git a/src/backend/simple.lisp b/src/backend/simple.lisp index 4722ce4..570ab9b 100644 --- a/src/backend/simple.lisp +++ b/src/backend/simple.lisp @@ -27,26 +27,30 @@ (values)) (defmethod backend-size ((b simple-backend)) - (or (ignore-errors - (let* ((+tiocgwinsz+ 21523) - (winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) - (unwind-protect - (progn - (sb-unix:unix-ioctl (sb-sys:fd-stream-fd - (backend-output-stream b)) - +tiocgwinsz+ - (sb-alien:alien-sap winsize)) - (values (sb-alien:deref winsize 1) - (sb-alien:deref winsize 0))) - (sb-alien:free-alien winsize)))) - (ignore-errors - (let ((cols (parse-integer (sb-ext:posix-getenv "COLUMNS") - :junk-allowed t)) - (rows (parse-integer (sb-ext:posix-getenv "LINES") - :junk-allowed t))) - (when (and cols rows (> cols 0) (> rows 0)) - (values cols rows)))) - (values 80 24))) + (multiple-value-bind (w h) + (or (ignore-errors + (let* ((+tiocgwinsz+ 21523) + (winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) + (unwind-protect + (progn + (sb-unix:unix-ioctl (sb-sys:fd-stream-fd + (backend-output-stream b)) + +tiocgwinsz+ + (sb-alien:alien-sap winsize)) + (values (sb-alien:deref winsize 1) + (sb-alien:deref winsize 0))) + (sb-alien:free-alien winsize)))) + (values 0 0)) + (if (and (> w 80) (> h 24)) + (values w h) + (or (ignore-errors + (let ((cols (parse-integer (sb-ext:posix-getenv "COLUMNS") + :junk-allowed t)) + (rows (parse-integer (sb-ext:posix-getenv "LINES") + :junk-allowed t))) + (when (and cols rows (> cols 0) (> rows 0)) + (values cols rows)))) + (values w h))))) (defmethod backend-write ((b simple-backend) string) (let ((stream (backend-output-stream b)))