git.fiddlerwoaroof.com
Browse code

Used cells to handle character display

Ed L authored on 30/10/2015 16:12:12
Showing 1 changed files
... ...
@@ -10,7 +10,6 @@
10 10
   (:use :cl :cl-charms :cells :alexandria :anaphora))
11 11
 (in-package :lisp-edit)
12 12
 
13
-
14 13
 (defun apply-cursor-action (action)
15 14
   (case action
16 15
     ((:up)    (cons  0 -1))
... ...
@@ -18,7 +17,6 @@
18 17
     ((:left)  (cons -1  0))
19 18
     ((:right) (cons  1  0))))
20 19
 
21
-
22 20
 (defun dispatch-char (c)
23 21
   (case c
24 22
     ((nil) nil)
... ...
@@ -35,11 +33,25 @@
35 33
 
36 34
 (defmodel cursor ()
37 35
           ((action :cell :ephemeral :initarg :action :accessor action :initform (c-in nil))
36
+           (current-char :initarg :current-char :accessor current-char :initform (c-in nil))
38 37
            (delta :accessor cursor-delta :initform
39 38
                   (c? (apply-cursor-action (^action))))
40 39
            (x :accessor cursor-x :initarg :x :initform (c... (0) (car (^cursor-delta))))
41 40
            (y :accessor cursor-y :initarg :y :initform (c... (0) (cdr (^cursor-delta))))))
42 41
 
42
+(defun map-actions (current-char action)
43
+  (case action
44
+    ((:paint) (case current-char
45
+                ((#\#) #\Space)
46
+                ((#\Space) #\*)
47
+                ((#\*) #\#)))))
48
+
49
+(defmodel painter ()
50
+          ((action :cell :ephemeral :initarg :action :accessor action :initform (c-in nil))
51
+           (current-char :initarg :current-char :accessor current-char :initform (c-in nil))
52
+           (output :cell :ephemeral :accessor output :initform (c? (map-actions (^current-char)
53
+                                                                                (^action))))))
54
+
43 55
 (defvar *input-handler*)
44 56
 (defvar *painter*)
45 57
 (defvar *cursor*)
... ...
@@ -72,38 +84,54 @@
72 84
       (enable-raw-input :interpret-control-characters t)
73 85
       (enable-non-blocking-mode *standard-window*)
74 86
 
75
-      (let* ((*input-handler* (make-instance 'input-handler))
76
-             (*cursor* (make-instance 'cursor :action (c? (action *input-handler*))))
77
-             (screen-dimensions (multiple-value-list (window-dimensions *standard-window*))))
78
-
79
-        (defobserver action ((self input-handler))
80
-                    (case new-value
81
-                      ((:paint) (paint))))
82
-
83
-
84
-        (defobserver y ((self cursor))
85
-                     (with-integrity (:change)
86
-                                     (let ((adjusted-n-v (mod new-value
87
-                                                              (cadr screen-dimensions))))
88
-                                       (if (/= new-value adjusted-n-v)
89
-                                         (setf (^cursor-y) (- adjusted-n-v new-value))
90
-                                         (move-cursor *standard-window*
91
-                                                      (^cursor-x) adjusted-n-v)))))
92
-
93
-        (defobserver x ((self cursor))
94
-                     (with-integrity (:change)
95
-                                     (let ((adjusted-n-v (mod new-value
96
-                                                              (car screen-dimensions))))
97
-                                       (if (/= new-value adjusted-n-v)
98
-                                         (setf (^cursor-x) (- adjusted-n-v new-value))
99
-                                         (move-cursor *standard-window*
100
-                                                      adjusted-n-v (^cursor-y))))))
101
-
102
-        (loop :named driver-loop
103
-              :for c := (get-char *standard-window* :ignore-error t)
104
-              :do (progn
105
-                    (refresh-window *standard-window*)
106
-
107
-                    (setf (input-key *input-handler*) c)))))
87
+      (setf *input-handler* (make-instance 'input-handler) 
88
+            *cursor* (make-instance 'cursor :action (c? (action *input-handler*)))
89
+            *painter* (make-instance 'painter
90
+                                     :action (c? (action *input-handler*))
91
+                                     :current-char (c? (current-char *cursor*))))
92
+
93
+      (let* ((screen-dimensions (multiple-value-bind (x y) (window-dimensions *standard-window*)
94
+                                  (cons x y))))
95
+        (labels
96
+          ((set-current-char (cursor)
97
+             (with-restored-cursor *standard-window*
98
+               (setf (current-char cursor) (char-at-cursor *standard-window*))))
99
+           (mvc (x y)
100
+             (move-cursor *standard-window* x y)
101
+             (set-current-char *cursor*))
102
+           (constrain-coordinate (side coord)
103
+             (mod coord (funcall
104
+                          (ecase side
105
+                            ((:x) #'car)
106
+                            ((:y) #'cdr))
107
+                          screen-dimensions))))
108
+
109
+          (defobserver output ((self painter))
110
+                       (with-restored-cursor *standard-window*
111
+                         (write-char-at-cursor *standard-window* new-value))
112
+                       (with-integrity (:change)
113
+                         (set-current-char *cursor*)))
114
+
115
+          (defobserver y ((self cursor))
116
+                       (with-integrity (:change)
117
+                         (let ((adjusted-n-v (constrain-coordinate :y new-value)))
118
+                           (if (/= new-value adjusted-n-v)
119
+                             (setf (^cursor-y) (- adjusted-n-v new-value))
120
+                             (mvc (^cursor-x) adjusted-n-v)))))
121
+
122
+          (defobserver x ((self cursor))
123
+                       (with-integrity (:change)
124
+                         (let ((adjusted-n-v (constrain-coordinate :x new-value)))
125
+                           (if (/= new-value adjusted-n-v)
126
+                             (setf (^cursor-x) (- adjusted-n-v new-value))
127
+                             (mvc adjusted-n-v (^cursor-y))))))
128
+
129
+          (mvc 0 0)
130
+          (loop :named driver-loop
131
+                :for c := (get-char *standard-window* :ignore-error t)
132
+                :do (progn
133
+                      (refresh-window *standard-window*)
134
+                      (setf (input-key *input-handler*) c))))))
135
+
108 136
     (sb-sys:interactive-interrupt (c) (declare (ignore c)))))
109 137