3 (defclass mcl-window
(ccl:window
)
6 (defclass mcl-frame
(frame)
7 ((mcl-window :type window
:initarg
:mcl-window
:accessor mcl-frame-window
)
8 (double-buffer :type
(array ccl
:static-text-dialog-item
1) :initarg
:double-buffer
:accessor frame-double-buffer
:documentation
9 "The display double buffer. This structure is compared to
10 the characters we want to blit. Only differences are sent to the video
12 (2d-double-buffer :type
(array ccl
:static-text-dialog-item
2) :initarg
:2d-double-buffer
:accessor frame-2d-double-buffer
:documentation
13 "Displaced from DISPLAY. This array is divided into rows and columns.")
16 (defmethod frame-start-render ((frame mcl-frame
))
19 (defmethod frame-end-render ((frame mcl-frame
))
23 (defun window-move-cursor (window x y
)
26 (defmethod frame-move-cursor ((frame mcl-frame
) win x y
)
27 (window-move-cursor win x y
))
29 (defun putch (ch x y window frame
)
30 (ccl:set-dialog-item-text
(aref (frame-2d-double-buffer frame
) (+ y
(window-y window
)) (+ x
(window-x window
)))
33 (defun putstr (s x y w frame
)
34 (loop for i from
0 below
(length s
)
36 ;;if (char/= (aref (window-2d-display w) y j) (aref s i))
37 do
(putch (char s i
) j y w frame
)))
39 (defun clear-line-between (w y start end frame
)
40 "insert LEN spaces from START on line Y."
41 (window-move-cursor w start y
)
42 ;; FIXME: this could be done faster
43 (loop for i from start to end
44 do
(putch #\Space i y w frame
)))
46 (defun clear-to-eol (y start window frame
)
47 (declare (type window window
)
48 (type fixnum y start
))
49 (let ((display (frame-2d-double-buffer frame
))
50 (linear (frame-double-buffer frame
)))
51 (clear-line-between window y start
(1- (window-width window
)) frame
)
53 (when (window-seperator window
)
54 (putch #\|
(+ (window-x window
) (1- (window-width window t
))) y window frame
))))
56 (defun turn-on-attributes (buffer point
)
59 (defmethod window-render (w (frame mcl-frame
))
61 (let ((p (buffer-char-to-aref (window-buffer w
) (marker-position (window-top w
))))
62 ;; current point in buffer buffer
63 (bp (marker-position (window-top w
)))
64 (buf (window-buffer w
))
65 ;; The cursor point in the buffer. When the buffer isn't
66 ;; current, then use the window's backup of the point.
67 (point (window-point w
))
70 (cache-size (length (lc-cache (window-cache w
))))
71 (linear (frame-double-buffer frame
))
72 (display (frame-2d-double-buffer frame
)))
73 ;; Special case: when the buffer is empty
74 (if (= (buffer-size (window-buffer w
)) 0)
76 (dotimes (y (window-height w
))
77 (clear-to-eol y
0 w frame
))
80 (let ((end (loop named row
81 for y below
(window-height w
)
82 for line from
(window-top-line w
) below cache-size
83 ;; return the last line, so we can erase the rest
84 finally
(return-from row y
)
85 ;; go to the next line
86 do
(let* ((line-end (cache-item-end (item-in-cache w line
)))
87 (line-start (cache-item-start (item-in-cache w line
)))
88 (next-prop (next-single-property-change line-start
:face
(window-buffer w
) line-end
)))
89 (setf bp
(cache-item-start (item-in-cache w line
))
90 p
(buffer-char-to-aref (window-buffer w
) bp
))
91 ;; setup the display properties.
92 (turn-on-attributes (window-buffer w
) bp
)
94 for x below
(window-width w
) do
97 (when (= p
(buffer-gap-start buf
))
98 (incf p
(buffer-gap-size buf
)))
99 ;; Record point position on screen
103 (when (or (> bp line-end
)
104 (>= p
(length (buffer-data buf
))))
105 ;; Check if the rest of the line is blank
106 (clear-to-eol y x w frame
)
109 (when (>= bp next-prop
)
110 (turn-on-attributes (window-buffer w
) bp
))
111 (let ((ch (elt (buffer-data buf
) p
)))
113 (cond ((char= ch
#\Newline
)
114 (putch #\Space x y w frame
))
116 (putch ch x y w frame
)))
117 ;; go to the next character in the buffer
120 ;; Check if the bottom of the window needs to be erased.
121 (when (< end
(1- (window-height w
)))
122 (loop for i from end below
(window-height w
) do
123 (clear-to-eol i
0 w frame
)))))
124 ;; Update the mode-line if it exists. FIXME: Not the right place
125 ;; to update the mode-line.
126 (when (buffer-mode-line (window-buffer w
))
127 (update-mode-line (window-buffer w
))
128 (putstr (truncate-mode-line (window-buffer w
) (window-width w
))
129 0 (window-height w nil
) w frame
)
130 ;; don't forget the seperator on the modeline line
131 (when (window-seperator w
)
132 (putch #\|
(+ (window-x w
) (window-width w
)) (window-height w
) w frame
)))
134 ;; Set the cursor at the right spot
135 (values cursor-x cursor-y
)))
137 (defmethod frame-read-event ((frame mcl-frame
))
142 (defvar *mcl-key-list
* nil
143 "List of keys pressed.")
145 (defmethod view-key-event-handler :after
((w mcl-window
) ch
)
146 (format t
"LICE keypress: ~a~%" ch
)
147 (push ch
*mcl-key-list
*))
149 (defun make-default-mcl-frame (buffer)
153 (l (make-array (* lines cols
)
154 :element-type
'ccl
:static-text-dialog-item
))
155 (d (make-array (list lines cols
)
156 :element-type
'ccl
:static-text-dialog-item
157 :displaced-to l
:displaced-index-offset
0))
158 (w (make-window :x
0 :y
0 :cols cols
:rows height
:buffer buffer
))
159 (mb (make-minibuffer-window lines cols
))
160 (frame (make-instance 'mcl-frame
163 :window-tree
(list w mb
)
165 :minibuffer-window mb
168 :mcl-window
(make-instance 'mcl-window
169 :view-size
(ccl:make-point
(* cols
11) (* lines
16))))))
170 (dotimes (i (* cols lines
))
171 (setf (aref (frame-double-buffer frame
) i
) (make-instance 'ccl
:static-text-dialog-item
172 :view-font
'("Monaco" 12)
173 :view-container
(mcl-frame-window frame
)
174 :view-position
(ccl:make-point
(* (multiple-value-bind (q r
) (truncate i cols
) r
) 11) (* (truncate i cols
) 16))
175 :dialog-item-text
(make-string 1 :initial-element
#\-
))))
176 (setf (window-frame w
) frame
177 (window-frame mb
) frame
)