Index: main/form-test.lisp
===================================================================
--- main/form-test.lisp	(revision main,43)
+++ main/form-test.lisp	(revision main,44)
@@ -47,4 +47,5 @@
              (progn
                (setf (scroll form) 4)
-               (tui-input:read-key w))
+               (activate form (lambda (key)
+                                (member key '(#\Esc #\Tab #\Return :key-f12)))))
           (destroy-form form))))))
Index: main/form.lisp
===================================================================
--- main/form.lisp	(revision main,43)
+++ main/form.lisp	(revision main,44)
@@ -3,5 +3,6 @@
 (defpackage #:tui-form
   (:use #:cl #:dso-util #:tui-input #:tui-widget #:tui-window)
-  (:export #:form-value #:defform #:create-form #:destroy-form #:scroll))
+  (:export #:form-value #:defform #:create-form #:destroy-form #:scroll
+           #:activate))
 
 (in-package #:tui-form)
@@ -87,5 +88,5 @@
 (defmethod (setf text) (text (r reflector))
   (with-slots (data name) r
-    (setf (form-value data name) r)))
+    (setf (form-value data name) text)))
 
 
@@ -119,7 +120,5 @@
 
 (defun widget-visible-p (form widget)
-  (with-slots (widgets window scroll) form
-    (when (integerp widget)
-      (setf widget (aref widgets widget)))
+  (with-slots (window scroll) form
     (with-slots (row) widget
       (<= 0 (- row scroll) (1- (size window))))))
@@ -139,4 +138,12 @@
             (setf (aref peers i) (create-peer widget-def form)))))
       r)))
+
+(defun ensure-widget-visible (form i)
+  (with-slots (widget-defs window scroll) form
+    (let ((widget (aref widget-defs i)))
+      (with-slots (row) widget
+        (let* ((line (- row scroll))
+               (diff (- line (bound line 0 (1- (size window))))))
+          (incf (scroll form) diff))))))
 
 
@@ -169,2 +176,23 @@
         (destroy (aref peers i))
         (setf (aref peers i) nil)))))
+
+
+
+(defmethod activate ((form form) &optional (callback 'nothing))
+  (with-slots (peers) form
+    (flet ((callback (key)
+             (if (member key '(#\Return #\Newline #\Tab :key-btab))
+                 key
+                 (funcall callback key))))
+      (let ((focus 0)
+            (n (length peers)))
+        (loop
+           (ensure-widget-visible form focus)
+           (let ((key (activate (aref peers focus) #'callback)))
+             (case key
+               ((#\Return #\Newline #\Tab)
+                (setf focus (mod (1+ focus) n)))
+               (:key-btab
+                (setf focus (mod (1- focus) n)))
+               (t
+                (return-from activate key)))))))))
Index: main/tui.asd
===================================================================
--- main/tui.asd	(revision main,42)
+++ main/tui.asd	(revision main,44)
@@ -16,5 +16,5 @@
                (:file "display-string"
                       ;; "input" only for testing
-                      :depends-on ("cdk" "input"))
+                      :depends-on ("cdk" "cursor" "input" "output" "window"))
                (:module "widget"
                         :depends-on ("cursor"
Index: main/widget/textbox.lisp
===================================================================
--- main/widget/textbox.lisp	(revision main,40)
+++ main/widget/textbox.lisp	(revision main,44)
@@ -102,5 +102,6 @@
                 (setf (insertion-point textbox) (insertion-point textbox)))))
            (t
-            (if (or (keywordp key) (member key '(#\Return #\Tab #\Esc)))
+            (if (or (keywordp key)
+                    (member key '(#\Return #\Newline #\Tab #\Esc)))
                 (let ((r (funcall callback key)))
                   (when r
