Fix vterm: alt-screen gaps, line wrap, and column width calculation
ober
46bddacdd98e519ef5b00323947b27e3d84b9b13
--- a/lib/jerboa-emacs/qt/app.sls +++ b/lib/jerboa-emacs/qt/app.sls @@ -173,10 +173,12 @@ (vtscreen-clear-damage! vt) (hash-put! *vterm-dirty-rows* ts (make-hash-table)) #f] - [(and (> n 4) (not (vtscreen-alt-screen? vt))) + [(or (vtscreen-alt-screen? vt) (> n 4)) (let* ([rendered (vtscreen-render vt)] - [pre-text (or (terminal-state-pre-pty-text ts) - "")]) + [pre-text (if (vtscreen-alt-screen? vt) + "" + (or (terminal-state-pre-pty-text ts) + ""))]) (let update ([r2 0]) (when (< r2 rows) (vector-set! cache r2 (vtscreen-get-row-text vt r2)) @@ -1788,10 +1790,16 @@ 2370 0))] [widget-w (qt-widget-width ed)] + [char-w (max 1 + (sci-send/string + ed + 2275 + "0" + 0))] [new-cols (max 20 (quotient widget-w - 8))] + char-w))] [old-rows (vtscreen-rows vt)] [old-cols (vtscreen-cols vt)]) (when (or (not (= new-rows old-rows)) --- a/lib/jerboa-emacs/qt/buffer.sls +++ b/lib/jerboa-emacs/qt/buffer.sls @@ -49,6 +49,10 @@ (doc-editor-register! doc editor) (let ([ro (sci-send editor SCI_GETREADONLY)]) (sci-send editor SCI_SETREADONLY ro)) + (let ([lang (buffer-lexer-lang buf)]) + (qt-plain-text-edit-set-line-wrap! + editor + (not (or (eq? lang 'terminal) (eq? lang 'shell))))) (verbose-log! "qt-buffer-attach! post-buffer-attach-hook begin") (run-hooks! 'post-buffer-attach-hook editor buf) --- a/lib/jerboa-emacs/qt/commands-config.sls +++ b/lib/jerboa-emacs/qt/commands-config.sls @@ -871,6 +871,7 @@ "*")))] [buf (qt-buffer-create! name ed #f)]) (buffer-lexer-lang-set! buf 'terminal) + (qt-plain-text-edit-set-line-wrap! ed #f) (verbose-log! "cmd-term: qt-buffer-attach! begin") (qt-buffer-attach! ed buf) (verbose-log! "cmd-term: qt-buffer-attach! done") --- a/src/jerboa-emacs/qt/app.ss +++ b/src/jerboa-emacs/qt/app.ss @@ -201,12 +201,14 @@ (vtscreen-clear-damage! vt) (hash-put! *vterm-dirty-rows* ts (make-hash-table)) #f) - ((and (> n 4) (not (vtscreen-alt-screen? vt))) - ;; Many dirty rows in normal mode — full set-text! is faster than N line replacements. - ;; Never do this on alt screen (top, htop, etc.) — set-text! replaces the entire - ;; document, causing QScintilla to reset scroll/layout and visibly bounce. + ;; Alt-screen (top, htop, vim) OR many dirty rows: + ;; Full set-text! is more reliable than per-line replacement. + ;; setUpdatesEnabled batching (in the caller) prevents bounce. + ((or (vtscreen-alt-screen? vt) (> n 4)) (let* ((rendered (vtscreen-render vt)) - (pre-text (or (terminal-state-pre-pty-text ts) ""))) + (pre-text (if (vtscreen-alt-screen? vt) + "" ;; alt-screen: no pre-PTY prefix + (or (terminal-state-pre-pty-text ts) "")))) ;; Update cache for all rows (let update ((r2 0)) (when (< r2 rows) @@ -218,7 +220,7 @@ (qt-plain-text-edit-set-text! ed (string-append pre-text rendered)) #t)) (else - ;; Per-line replacement — only update rows whose text actually changed + ;; Few dirty rows in normal mode — per-line replacement (vterm-ensure-lines! ed (+ line-offset rows)) (let ((dirty-set (make-hash-table))) (let loop ((r2 0) (any-changed? #f)) @@ -1385,7 +1387,10 @@ (let* ((ed (qt-edit-window-editor (car wins))) (new-rows (max 2 (sci-send ed 2370 0))) (widget-w (qt-widget-width ed)) - (new-cols (max 20 (quotient widget-w 8))) + ;; Measure actual character width using Scintilla + ;; SCI_TEXTWIDTH(style, text) = 2275 + (char-w (max 1 (sci-send/string ed 2275 "0" 0))) + (new-cols (max 20 (quotient widget-w char-w))) (old-rows (vtscreen-rows vt)) (old-cols (vtscreen-cols vt))) (when (or (not (= new-rows old-rows)) --- a/src/jerboa-emacs/qt/buffer.ss +++ b/src/jerboa-emacs/qt/buffer.ss @@ -68,6 +68,12 @@ ;; subsequent buffers uneditable. (let ((ro (sci-send editor SCI_GETREADONLY))) (sci-send editor SCI_SETREADONLY ro)) + ;; Terminal buffers: disable line wrap (each vtscreen row = one visual line). + ;; Non-terminal buffers: enable word wrap for readability. + ;; Must be set per buffer-switch since wrap is a widget property, not per-document. + (let ((lang (buffer-lexer-lang buf))) + (qt-plain-text-edit-set-line-wrap! editor + (not (or (eq? lang 'terminal) (eq? lang 'shell))))) (verbose-log! "qt-buffer-attach! post-buffer-attach-hook begin") ;; Toggle image/editor display via hook (set up in qt/app.ss) (run-hooks! 'post-buffer-attach-hook editor buf) --- a/src/jerboa-emacs/qt/commands-config.ss +++ b/src/jerboa-emacs/qt/commands-config.ss @@ -715,6 +715,8 @@ modified so the next save uses the new encoding." (buf (qt-buffer-create! name ed #f))) ;; Mark as terminal buffer (set! (buffer-lexer-lang buf) 'terminal) + ;; Terminal: disable line wrap — each vtscreen row must be one visual line + (qt-plain-text-edit-set-line-wrap! ed #f) ;; Attach buffer to editor (verbose-log! "cmd-term: qt-buffer-attach! begin") (qt-buffer-attach! ed buf)