Index: main/cdk.lisp
===================================================================
--- main/cdk.lisp	(revision main,22.1.1)
+++ main/cdk.lisp	(revision main,24)
@@ -1,5 +1,6 @@
 (defpackage #:cdk
   (:use #:cl #:cffi)
-  (:export #:with-screen #:with-der-window #:add-ch #:add-string #:wmove))
+  (:export #:with-screen #:with-der-window #:add-string #:add-clipped-string
+           #:wmove))
 
 (in-package #:cdk)
@@ -17,4 +18,5 @@
 
 (defctype chtype :uint64)
+(defctype wchar :int32)                 ; On my 64-bit laptop.
 
 (defcvar ("cdk_exit_early" +cdk-exit-early+) :int :read-only t)
@@ -160,24 +162,31 @@
   (x :int))
 
-(defun add-char (window ch)
-  (with-foreign-object (s 'cchar_t)
-    (with-foreign-slots ((attr char) s cchar_t)
-      (setf attr 0)
-      (dotimes (i 5)
-        (setf (mem-aref char :uint32 i) 0))
-      (setf (mem-aref char :uint32) (char-code ch)))
-    (wadd-wch window s)))
+(defcfun "waddnwstr" :int
+  (window :pointer)
+  (wstr :pointer)
+  (n :int))
 
 (defun add-string (window s)
-  (dotimes (i (length s))
-    (add-char window (aref s i))))
-
-(defun move-and-add-char (window y x ch)
-  (wmove window y x)
-  (add-char window ch))
+  (let ((n (length s)))
+    (with-foreign-object (a 'wchar n)
+      (dotimes (i n)
+        (setf (mem-aref a 'wchar i) (char-code (aref s i))))
+      (waddnwstr window a n))))
 
 (defun move-and-add-string (window y x s)
   (wmove window y x)
   (add-string window s))
+
+(defun add-clipped-string (window y x s)
+  (let ((maxy (getmaxy window)))
+    (unless (<= 0 y maxy) (return-from add-clipped-string)))
+  (let ((maxx (getmaxx window)))
+    (when (< x 0)
+      (setf s (subseq s (- x))
+            x 0))
+    (let ((over (- (+ x (length s)) maxx)))
+      (when (> over 0)
+        (setf s (subseq s 0 (- (length s) over)))))
+    (move-and-add-string window y x s)))
 
 (defcfun ("wrefresh" c-refresh-window) :int
