diff --git a/src/components/scrollbox.lisp b/src/components/scrollbox.lisp index 9f04810..1a7bfcf 100644 --- a/src/components/scrollbox.lisp +++ b/src/components/scrollbox.lisp @@ -47,20 +47,19 @@ Children outside the viewport are skipped." (vh (if ln (layout-node-height ln) 24)) (sy (scroll-box-scroll-y sb)) (sx (scroll-box-scroll-x sb))) - (declare (ignore vx)) (dolist (child (scroll-box-children sb)) (let* ((cln (component-layout-node child)) (ch (if cln (layout-node-height cln) 1)) (cy vy)) ;; Only render children that are visible in the viewport - (when (and (< (+ cy (- sy)) (+ vh vy)) - (> (+ cy (- sy) ch) vy)) + (when (and (< (- cy sy) vh) + (> (+ (- cy sy) ch) 0)) ;; Temporarily offset child's layout-node position for rendering (let ((orig-x (if cln (layout-node-x cln) 0)) (orig-y (if cln (layout-node-y cln) 0))) (when cln - (setf (layout-node-x cln) (- orig-x sx) - (layout-node-y cln) (- orig-y sy))) + (setf (layout-node-x cln) (- vx sx) + (layout-node-y cln) (- vy sy))) (unwind-protect (render child backend) (when cln diff --git a/src/components/text.lisp b/src/components/text.lisp index c9cf389..34d3d77 100644 --- a/src/components/text.lisp +++ b/src/components/text.lisp @@ -70,7 +70,9 @@ Breaks at word boundaries. Words exceeding MAX-WIDTH are hard-broken." (let ((wl (length word))) (cond ((<= wl max-width) (if (and current (<= (+ current-len 1 wl) max-width)) - (push word current) + (progn + (push word current) + (incf current-len (1+ wl))) (progn (when current (push (format nil "~{~A~^ ~}" (nreverse current)) lines)) diff --git a/tests/integration-tests.lisp b/tests/integration-tests.lisp index 65c4afb..159ee07 100644 --- a/tests/integration-tests.lisp +++ b/tests/integration-tests.lisp @@ -56,7 +56,7 @@ (is-true (fb-contains fb "+") "top-left corner appears") (is-true (fb-contains fb "-") "horizontal border appears") ;; Check the title at row 0, col 2 - (is (equal "My Box" (fb-string fb 2 0 6)) "title at correct position"))) + (is (equal "My Box" (fb-string fb 2 1 6)) "title at correct position"))) ;; ─── Test: Text component with word-wrap ────────────────────────── @@ -76,17 +76,17 @@ (test textinput-value-on-fb "TextInput renders its value and cursor on framebuffer." (let* ((fb (make-framebuffer-backend :width 40 :height 3)) - (ti (make-text-input :value "hello world" :cursor 5))) + (ti (make-text-input :value "hello world" :cursor 11))) (setf (text-input-layout-node ti) (make-layout-node :width 40 :height 1)) (compute-layout (text-input-layout-node ti) 40 1) (render ti fb) ;; Verify value via direct cell inspection (is (equal "hello world" (fb-string fb 0 0 11)) "value appears at row 0") - ;; Check cursor block at position 5 + ;; Check cursor block at position 11 (let* ((cells (fb-framebuffer fb)) - (cursor-char (cell-char (aref cells 0 5)))) - (is (eql #\█ cursor-char) "cursor block is drawn at position 5")))) + (cursor-char (cell-char (aref cells 0 11)))) + (is (eql #\█ cursor-char) "cursor block is drawn at position 11")))) ;; ─── Test: TextInput empty shows placeholder ────────────────────── @@ -228,7 +228,7 @@ ;; ;; 3. TextInput ;; - (let ((ti (make-text-input :value "search query" :cursor 6))) + (let ((ti (make-text-input :value "search query" :cursor 12))) (setf (text-input-layout-node ti) (make-layout-node)) (setf (layout-node-x (text-input-layout-node ti)) 2) (setf (layout-node-y (text-input-layout-node ti)) 6)