##// END OF EJS Templates
Fix a bug in dynamic return
naryl -
r65:4e5eb097 default
parent child Browse files
Show More
@@ -1,46 +1,47 b''
1
1
2 (in-package txt2web.api)
2 (in-package txt2web.api)
3
3
4 (defpsmacro with-call-args (args &body body)
4 (defpsmacro with-call-args (args return &body body)
5 `(progn
5 `(progn
6 (init-args ,args)
6 (init-args ,args)
7 ,@body
7 ,@body
8 (get-result)))
8 ,@(when return
9 '((get-result)))))
9
10
10 (defpsmacro with-frame (&body body)
11 (defpsmacro with-frame (&body body)
11 `(progn
12 `(progn
12 (push-local-frame)
13 (push-local-frame)
13 (unwind-protect
14 (unwind-protect
14 ,@body
15 ,@body
15 (pop-local-frame))))
16 (pop-local-frame))))
16
17
17 (defpsmacro href-call (func &rest args)
18 (defpsmacro href-call (func &rest args)
18 `(+ "javascript:" (inline-call ,func ,@args)))
19 `(+ "javascript:" (inline-call ,func ,@args)))
19
20
20 (defpsmacro inline-call (func &rest args)
21 (defpsmacro inline-call (func &rest args)
21 `(+ ',func
22 `(+ ',func
22 "(\""
23 "(\""
23 ,(first args)
24 ,(first args)
24 ,@(loop :for arg :in (cdr args)
25 ,@(loop :for arg :in (cdr args)
25 :collect "\", \""
26 :collect "\", \""
26 :collect arg)
27 :collect arg)
27 "\");"))
28 "\");"))
28
29
29 (defpsmacro with-sleep ((resume-func) &body body)
30 (defpsmacro with-sleep ((resume-func) &body body)
30 `(new (*promise
31 `(new (*promise
31 (lambda (resolve)
32 (lambda (resolve)
32 (start-sleeping)
33 (start-sleeping)
33 (let ((,resume-func (lambda ()
34 (let ((,resume-func (lambda ()
34 (finish-sleeping)
35 (finish-sleeping)
35 (resolve)))))
36 (resolve)))))
36 ,@body))))
37 ,@body))))
37
38
38 (defvar *serv-vars* nil)
39 (defvar *serv-vars* nil)
39
40
40 (defpsmacro define-serv-var (name (value &optional index) &body body)
41 (defpsmacro define-serv-var (name (value &optional index) &body body)
41 (setf name (string-upcase (symbol-name name)))
42 (setf name (string-upcase (symbol-name name)))
42 (pushnew name *serv-vars* :test #'equal)
43 (pushnew name *serv-vars* :test #'equal)
43 `(setf (getprop serv-vars ,name)
44 `(setf (getprop serv-vars ,name)
44 (create :name ,name
45 (create :name ,name
45 :body (lambda (,value ,@(when index (list index)))
46 :body (lambda (,value ,@(when index (list index)))
46 ,@body))))
47 ,@body))))
@@ -1,523 +1,522 b''
1
1
2 (in-package txt2web.api)
2 (in-package txt2web.api)
3
3
4 ;;; API deals with DOM manipulation and some bookkeeping for the
4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 ;;; intrinsics, namely variables
5 ;;; intrinsics, namely variables
6 ;;; API is an implementation detail and has no QSP documentation. It
6 ;;; API is an implementation detail and has no QSP documentation. It
7 ;;; doesn't call intrinsics
7 ;;; doesn't call intrinsics
8
8
9 ;;; Utils
9 ;;; Utils
10
10
11 (defun make-act-html (title img)
11 (defun make-act-html (title img)
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
13 (if img (+ "<img src='" img "'>") "")
13 (if img (+ "<img src='" img "'>") "")
14 title
14 title
15 "</a>"))
15 "</a>"))
16
16
17 (defun make-menu-item-html (num title img loc)
17 (defun make-menu-item-html (num title img loc)
18 (+ "<a href='" (href-call finish-menu loc) "'>"
18 (+ "<a href='" (href-call finish-menu loc) "'>"
19 (if img (+ "<img src='" img "'>") "")
19 (if img (+ "<img src='" img "'>") "")
20 title
20 title
21 "</a>"))
21 "</a>"))
22
22
23 (defun make-obj (title img selected)
23 (defun make-obj (title img selected)
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
26 (if img (+ "<img src='" img "'>") "")
26 (if img (+ "<img src='" img "'>") "")
27 title
27 title
28 "</a>"))
28 "</a>"))
29
29
30 (defun make-menu-delimiter ()
30 (defun make-menu-delimiter ()
31 "<hr>")
31 "<hr>")
32
32
33 (defun copy-obj (obj)
33 (defun copy-obj (obj)
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
35
35
36 (defun report-error (text)
36 (defun report-error (text)
37 (alert text))
37 (alert text))
38
38
39 (defun start-sleeping ()
39 (defun start-sleeping ()
40 (chain (by-id "qsp") class-list (add "disable")))
40 (chain (by-id "qsp") class-list (add "disable")))
41
41
42 (defun finish-sleeping ()
42 (defun finish-sleeping ()
43 (chain (by-id "qsp") class-list (remove "disable")))
43 (chain (by-id "qsp") class-list (remove "disable")))
44
44
45 (defun sleep (msec)
45 (defun sleep (msec)
46 (with-sleep (resume)
46 (with-sleep (resume)
47 (set-timeout resume msec)))
47 (set-timeout resume msec)))
48
48
49 (defun init-dom ()
49 (defun init-dom ()
50 ;; Save/load buttons
50 ;; Save/load buttons
51 (let ((btn (by-id "qsp-btn-save")))
51 (let ((btn (by-id "qsp-btn-save")))
52 (setf (@ btn onclick) savegame)
52 (setf (@ btn onclick) savegame)
53 (setf (@ btn href) "#"))
53 (setf (@ btn href) "#"))
54 (let ((btn (by-id "qsp-btn-open")))
54 (let ((btn (by-id "qsp-btn-open")))
55 (setf (@ btn onclick) opengame)
55 (setf (@ btn onclick) opengame)
56 (setf (@ btn href) "#"))
56 (setf (@ btn href) "#"))
57 ;; Close image on click
57 ;; Close image on click
58 (setf (@ (by-id "qsp-image-container") onclick)
58 (setf (@ (by-id "qsp-image-container") onclick)
59 show-image)
59 show-image)
60 ;; Enter in input field
60 ;; Enter in input field
61 (setf (@ (get-frame :input) onkeyup)
61 (setf (@ (get-frame :input) onkeyup)
62 on-input-key)
62 on-input-key)
63 ;; Close the dropdown on any click
63 ;; Close the dropdown on any click
64 (setf (@ window onclick)
64 (setf (@ window onclick)
65 (lambda (event)
65 (lambda (event)
66 (setf (@ window mouse)
66 (setf (@ window mouse)
67 (list (@ event page-x)
67 (list (@ event page-x)
68 (@ event page-y)))
68 (@ event page-y)))
69 (finish-menu nil))))
69 (finish-menu nil))))
70
70
71 (defun init-globals (game-name)
71 (defun init-globals (game-name)
72 (chain *object (assign *globals (getprop *default-globals game-name))))
72 (chain *object (assign *globals (getprop *default-globals game-name))))
73
73
74 (defun call-serv-loc (var-name &rest args)
74 (defun call-serv-loc (var-name &rest args)
75 (let ((loc-name (get-global var-name 0)))
75 (let ((loc-name (get-global var-name 0)))
76 (when loc-name
76 (when loc-name
77 (let ((loc (getprop *locs loc-name)))
77 (let ((loc (getprop *locs loc-name)))
78 (when loc
78 (when loc
79 (call-loc loc-name args))))))
79 (call-loc loc-name args))))))
80
80
81 (defun filename-game (filename)
81 (defun filename-game (filename)
82 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
82 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
83 (getprop *games game-name))
83 (getprop *games game-name))
84
84
85 (defun run-game (name)
85 (defun run-game (name)
86 (let ((game (filename-game name)))
86 (let ((game (filename-game name)))
87 (setf *main-game name)
87 (setf *main-game name)
88 ;; Replace locations with the new game's
88 ;; Replace locations with the new game's
89 (setf *locs game)
89 (setf *locs game)
90 (funcall (getprop game
90 (funcall (getprop game
91 (chain *object (keys game) 0))
91 (chain *object (keys game) 0))
92 (list))))
92 (list))))
93
93
94 ;;; Misc
94 ;;; Misc
95
95
96 (defun newline (key)
96 (defun newline (key)
97 (append-id (key-to-id key) "<br>" t))
97 (append-id (key-to-id key) "<br>" t))
98
98
99 (defun clear-id (id)
99 (defun clear-id (id)
100 (setf (inner-html (by-id id)) ""))
100 (setf (inner-html (by-id id)) ""))
101
101
102 (defun escape-html (text)
102 (defun escape-html (text)
103 (chain text
103 (chain text
104 (replace (regex "/&/g") "&amp;")
104 (replace (regex "/&/g") "&amp;")
105 (replace (regex "/</g") "&lt;")
105 (replace (regex "/</g") "&lt;")
106 (replace (regex "/>/g") "&gt;")
106 (replace (regex "/>/g") "&gt;")
107 (replace (regex "/\"/g") "&quot;")
107 (replace (regex "/\"/g") "&quot;")
108 (replace (regex "/'/g") "&apos;")))
108 (replace (regex "/'/g") "&apos;")))
109
109
110 (defun prepare-contents (s &optional force-html)
110 (defun prepare-contents (s &optional force-html)
111 (setf s (chain s (to-string)))
111 (setf s (chain s (to-string)))
112 (if (or force-html (get-global "USEHTML" 0))
112 (if (or force-html (get-global "USEHTML" 0))
113 s
113 s
114 (escape-html s)))
114 (escape-html s)))
115
115
116 (defun get-id (id &optional force-html)
116 (defun get-id (id &optional force-html)
117 (inner-html (by-id id)))
117 (inner-html (by-id id)))
118
118
119 (defun set-id (id contents &optional force-html)
119 (defun set-id (id contents &optional force-html)
120 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
120 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
121
121
122 (defun append-id (id contents &optional force-html)
122 (defun append-id (id contents &optional force-html)
123 (when contents
123 (when contents
124 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
124 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
125
125
126 (defun on-input-key (ev)
126 (defun on-input-key (ev)
127 (when (= 13 (@ ev key-code))
127 (when (= 13 (@ ev key-code))
128 (chain ev (prevent-default))
128 (chain ev (prevent-default))
129 (call-serv-loc "$USERCOM")))
129 (call-serv-loc "$USERCOM")))
130
130
131 ;;; Function calls
131 ;;; Function calls
132
132
133 (defun init-args (args)
133 (defun init-args (args)
134 (dotimes (i 10)
134 (dotimes (i 10)
135 (set-global "ARGS" i 0)
135 (set-global "ARGS" i 0)
136 (set-global "$ARGS" i "")
136 (set-global "$ARGS" i "")
137 (when (< i (length args))
137 (when (and args (< i (length args)))
138 (let ((arg (elt args i)))
138 (let ((arg (elt args i)))
139 (if (numberp arg)
139 (if (numberp arg)
140 (set-global "ARGS" i arg)
140 (set-global "ARGS" i arg)
141 (set-global "$ARGS" i arg))))))
141 (set-global "$ARGS" i arg))))))
142
142
143 (defun get-result ()
143 (defun get-result ()
144 (or (get-global "$RESULT" 0)
144 (or (get-global "$RESULT" 0)
145 (get-global "RESULT" 0)))
145 (get-global "RESULT" 0)))
146
146
147 (defun call-loc (name args)
147 (defun call-loc (name args)
148 (setf name (chain name (to-upper-case)))
148 (setf name (chain name (to-upper-case)))
149 (with-frame
149 (with-frame
150 (with-call-args args
150 (with-call-args args t
151 (funcall (getprop *locs name))))
151 (funcall (getprop *locs name)))))
152 (void))
153
152
154 (defun call-act (title)
153 (defun call-act (title)
155 (with-frame
154 (with-frame
156 (funcall (getprop *acts title :act)))
155 (funcall (getprop *acts title :act)))
157 (void))
156 (void))
158
157
159 ;;; Text windows
158 ;;; Text windows
160
159
161 (defun key-to-id (key)
160 (defun key-to-id (key)
162 (case key
161 (case key
163 (:all "qsp")
162 (:all "qsp")
164 (:main "qsp-main")
163 (:main "qsp-main")
165 (:stat "qsp-stat")
164 (:stat "qsp-stat")
166 (:objs "qsp-objs")
165 (:objs "qsp-objs")
167 (:acts "qsp-acts")
166 (:acts "qsp-acts")
168 (:input "qsp-input")
167 (:input "qsp-input")
169 (:image "qsp-image")
168 (:image "qsp-image")
170 (:dropdown "qsp-dropdown")
169 (:dropdown "qsp-dropdown")
171 (t (report-error "Internal error!"))))
170 (t (report-error "Internal error!"))))
172
171
173 (defun get-frame (key)
172 (defun get-frame (key)
174 (by-id (key-to-id key)))
173 (by-id (key-to-id key)))
175
174
176 (defun add-text (key text)
175 (defun add-text (key text)
177 (append-id (key-to-id key) text))
176 (append-id (key-to-id key) text))
178
177
179 (defun get-text (key)
178 (defun get-text (key)
180 (get-id (key-to-id key)))
179 (get-id (key-to-id key)))
181
180
182 (defun clear-text (key)
181 (defun clear-text (key)
183 (clear-id (key-to-id key)))
182 (clear-id (key-to-id key)))
184
183
185 (defun enable-frame (key enable)
184 (defun enable-frame (key enable)
186 (let ((obj (get-frame key)))
185 (let ((obj (get-frame key)))
187 (setf (@ obj style display) (if enable "block" "none"))
186 (setf (@ obj style display) (if enable "block" "none"))
188 (void)))
187 (void)))
189
188
190 ;;; Actions
189 ;;; Actions
191
190
192 (defun add-act (title img act)
191 (defun add-act (title img act)
193 (setf (getprop *acts title)
192 (setf (getprop *acts title)
194 (create :title title :img img :act act :selected nil))
193 (create :title title :img img :act act :selected nil))
195 (update-acts))
194 (update-acts))
196
195
197 (defun del-act (title)
196 (defun del-act (title)
198 (delete (getprop *acts title))
197 (delete (getprop *acts title))
199 (update-acts))
198 (update-acts))
200
199
201 (defun clear-act ()
200 (defun clear-act ()
202 (setf *acts (create))
201 (setf *acts (create))
203 (update-acts))
202 (update-acts))
204
203
205 (defun update-acts ()
204 (defun update-acts ()
206 (clear-id "qsp-acts")
205 (clear-id "qsp-acts")
207 (let ((elt (by-id "qsp-acts")))
206 (let ((elt (by-id "qsp-acts")))
208 (for-in (title *acts)
207 (for-in (title *acts)
209 (let ((obj (getprop *acts title)))
208 (let ((obj (getprop *acts title)))
210 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
209 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
211
210
212 (defun select-act (title)
211 (defun select-act (title)
213 (loop :for (k v) :of *acts
212 (loop :for (k v) :of *acts
214 :do (setf (getprop v :selected) nil))
213 :do (setf (getprop v :selected) nil))
215 (setf (getprop *acts title :selected) t)
214 (setf (getprop *acts title :selected) t)
216 (call-serv-loc "$ONACTSEL"))
215 (call-serv-loc "$ONACTSEL"))
217
216
218 ;;; Variables
217 ;;; Variables
219
218
220 (defun new-var (slot &rest indexes)
219 (defun new-var (slot &rest indexes)
221 (let ((v (list)))
220 (let ((v (list)))
222 (dolist (index indexes)
221 (dolist (index indexes)
223 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
222 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
224 (setf (@ v :indexes) (create))
223 (setf (@ v :indexes) (create))
225 v))
224 v))
226
225
227 (defun set-str-element (slot index value)
226 (defun set-str-element (slot index value)
228 (if (has index (getprop slot :indexes))
227 (if (has index (getprop slot :indexes))
229 (setf (elt (getprop slot)
228 (setf (elt (getprop slot)
230 (getprop slot :indexes index))
229 (getprop slot :indexes index))
231 value)
230 value)
232 (progn
231 (progn
233 (chain slot (push value))
232 (chain slot (push value))
234 (setf (elt slot index)
233 (setf (elt slot index)
235 (length slot))))
234 (length slot))))
236 (void))
235 (void))
237
236
238 (defun set-any-element (slot index value)
237 (defun set-any-element (slot index value)
239 (cond ((null index)
238 (cond ((null index)
240 (chain (elt slot) (push value)))
239 (chain (elt slot) (push value)))
241 ((numberp index)
240 ((numberp index)
242 (setf (elt slot index) value))
241 (setf (elt slot index) value))
243 ((stringp index)
242 ((stringp index)
244 (set-str-element slot index value))
243 (set-str-element slot index value))
245 (t (report-error "INTERNAL ERROR")))
244 (t (report-error "INTERNAL ERROR")))
246 (void))
245 (void))
247
246
248 (defun set-serv-var (name index value)
247 (defun set-serv-var (name index value)
249 (let ((slot (getprop *globals name)))
248 (let ((slot (getprop *globals name)))
250 (set-any-element slot index value))
249 (set-any-element slot index value))
251 (funcall (getprop serv-vars name :body) value index)
250 (funcall (getprop serv-vars name :body) value index)
252 (void))
251 (void))
253
252
254 (defun get-element (slot index)
253 (defun get-element (slot index)
255 (if (numberp index)
254 (if (numberp index)
256 (elt slot index)
255 (elt slot index)
257 (elt slot (getprop slot :indexes index))))
256 (elt slot (getprop slot :indexes index))))
258
257
259 (defun set-global (name index value)
258 (defun set-global (name index value)
260 (set-any-element (getprop *globals name) index value))
259 (set-any-element (getprop *globals name) index value))
261
260
262 (defun get-global (name index)
261 (defun get-global (name index)
263 (get-element (getprop *globals name) index))
262 (get-element (getprop *globals name) index))
264
263
265 (defun kill-var (&optional name index)
264 (defun kill-var (&optional name index)
266 (cond (name
265 (cond (name
267 (setf name (chain name (to-upper-case)))
266 (setf name (chain name (to-upper-case)))
268 (if (and index (not (= 0 index)))
267 (if (and index (not (= 0 index)))
269 (chain (getprop *globals name) (kill index))
268 (chain (getprop *globals name) (kill index))
270 (delete (getprop *globals name))))
269 (delete (getprop *globals name))))
271 (t
270 (t
272 (setf *globals (create))
271 (setf *globals (create))
273 (init-globals *main-game)))
272 (init-globals *main-game)))
274 (void))
273 (void))
275
274
276 (defun array-size (name)
275 (defun array-size (name)
277 (@ (var-ref name) :values length))
276 (@ (var-ref name) :values length))
278
277
279 ;;; Locals
278 ;;; Locals
280
279
281 (defun push-local-frame ()
280 (defun push-local-frame ()
282 (chain *locals (push (create)))
281 (chain *locals (push (create)))
283 (void))
282 (void))
284
283
285 (defun pop-local-frame ()
284 (defun pop-local-frame ()
286 (chain *locals (pop))
285 (chain *locals (pop))
287 (void))
286 (void))
288
287
289 (defun current-local-frame ()
288 (defun current-local-frame ()
290 (elt *locals (1- (length *locals))))
289 (elt *locals (1- (length *locals))))
291
290
292 ;;; Objects
291 ;;; Objects
293
292
294 (defun select-obj (title img)
293 (defun select-obj (title img)
295 (loop :for (k v) :of *objs
294 (loop :for (k v) :of *objs
296 :do (setf (getprop v :selected) nil))
295 :do (setf (getprop v :selected) nil))
297 (setf (getprop *objs title :selected) t)
296 (setf (getprop *objs title :selected) t)
298 (call-serv-loc "$ONOBJSEL" title img))
297 (call-serv-loc "$ONOBJSEL" title img))
299
298
300 (defun update-objs ()
299 (defun update-objs ()
301 (let ((elt (by-id "qsp-objs")))
300 (let ((elt (by-id "qsp-objs")))
302 (setf (inner-html elt) "<ul>")
301 (setf (inner-html elt) "<ul>")
303 (loop :for (name obj) :of *objs
302 (loop :for (name obj) :of *objs
304 :do (incf (inner-html elt)
303 :do (incf (inner-html elt)
305 (make-obj name (@ obj :img) (@ obj :selected))))
304 (make-obj name (@ obj :img) (@ obj :selected))))
306 (incf (inner-html elt) "</ul>")))
305 (incf (inner-html elt) "</ul>")))
307
306
308 ;;; Menu
307 ;;; Menu
309
308
310 (defun open-menu (menu-data)
309 (defun open-menu (menu-data)
311 (let ((elt (get-frame :dropdown))
310 (let ((elt (get-frame :dropdown))
312 (i 0))
311 (i 0))
313 (loop :for item :in menu-data
312 (loop :for item :in menu-data
314 :do (incf i)
313 :do (incf i)
315 :do (incf (inner-html elt)
314 :do (incf (inner-html elt)
316 (if (eq item :delimiter)
315 (if (eq item :delimiter)
317 (make-menu-delimiter i)
316 (make-menu-delimiter i)
318 (make-menu-item-html i
317 (make-menu-item-html i
319 (@ item :text)
318 (@ item :text)
320 (@ item :icon)
319 (@ item :icon)
321 (@ item :loc)))))
320 (@ item :loc)))))
322 (let ((mouse (@ window mouse)))
321 (let ((mouse (@ window mouse)))
323 (setf (@ elt style left) (+ (elt mouse 0) "px"))
322 (setf (@ elt style left) (+ (elt mouse 0) "px"))
324 (setf (@ elt style top) (+ (elt mouse 1) "px"))
323 (setf (@ elt style top) (+ (elt mouse 1) "px"))
325 ;; Make sure it's inside the viewport
324 ;; Make sure it's inside the viewport
326 (when (> (@ document body inner-width)
325 (when (> (@ document body inner-width)
327 (+ (elt mouse 0) (@ elt inner-width)))
326 (+ (elt mouse 0) (@ elt inner-width)))
328 (incf (@ elt style left) (@ elt inner-width)))
327 (incf (@ elt style left) (@ elt inner-width)))
329 (when (> (@ document body inner-height)
328 (when (> (@ document body inner-height)
330 (+ (elt mouse 0) (@ elt inner-height)))
329 (+ (elt mouse 0) (@ elt inner-height)))
331 (incf (@ elt style top) (@ elt inner-height))))
330 (incf (@ elt style top) (@ elt inner-height))))
332 (setf (@ elt style display) "block")))
331 (setf (@ elt style display) "block")))
333
332
334 (defun finish-menu (loc)
333 (defun finish-menu (loc)
335 (when *menu-resume
334 (when *menu-resume
336 (let ((elt (get-frame :dropdown)))
335 (let ((elt (get-frame :dropdown)))
337 (setf (inner-html elt) "")
336 (setf (inner-html elt) "")
338 (setf (@ elt style display) "none")
337 (setf (@ elt style display) "none")
339 (funcall *menu-resume)
338 (funcall *menu-resume)
340 (setf *menu-resume nil))
339 (setf *menu-resume nil))
341 (when loc
340 (when loc
342 (call-loc loc)))
341 (call-loc loc)))
343 (void))
342 (void))
344
343
345 (defun menu (menu-data)
344 (defun menu (menu-data)
346 (with-sleep (resume)
345 (with-sleep (resume)
347 (open-menu menu-data)
346 (open-menu menu-data)
348 (setf *menu-resume resume))
347 (setf *menu-resume resume))
349 (void))
348 (void))
350
349
351 ;;; Content
350 ;;; Content
352
351
353 (defun clean-audio ()
352 (defun clean-audio ()
354 (loop :for k :in (chain *object (keys *playing))
353 (loop :for k :in (chain *object (keys *playing))
355 :for v := (getprop *playing k)
354 :for v := (getprop *playing k)
356 :do (when (@ v ended)
355 :do (when (@ v ended)
357 (delete (@ *playing k)))))
356 (delete (@ *playing k)))))
358
357
359 (defun show-image (path)
358 (defun show-image (path)
360 (let ((img (get-frame :image)))
359 (let ((img (get-frame :image)))
361 (cond (path
360 (cond (path
362 (setf (@ img src) path)
361 (setf (@ img src) path)
363 (setf (@ img style display) "flex"))
362 (setf (@ img style display) "flex"))
364 (t
363 (t
365 (setf (@ img src) "")
364 (setf (@ img src) "")
366 (setf (@ img style display) "hidden")))))
365 (setf (@ img style display) "hidden")))))
367
366
368 (defun rgb-string (rgb)
367 (defun rgb-string (rgb)
369 (let ((red (ps::>> rgb 16))
368 (let ((red (ps::>> rgb 16))
370 (green (logand (ps::>> rgb 8) 255))
369 (green (logand (ps::>> rgb 8) 255))
371 (blue (logand rgb 255)))
370 (blue (logand rgb 255)))
372 (flet ((rgb-to-hex (comp)
371 (flet ((rgb-to-hex (comp)
373 (let ((hex (chain (*number comp) (to-string 16))))
372 (let ((hex (chain (*number comp) (to-string 16))))
374 (if (< (length hex) 2)
373 (if (< (length hex) 2)
375 (+ "0" hex)
374 (+ "0" hex)
376 hex))))
375 hex))))
377 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
376 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
378
377
379 (defun store-obj (key obj)
378 (defun store-obj (key obj)
380 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
379 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
381 (void))
380 (void))
382 (defun store-str (key str)
381 (defun store-str (key str)
383 (chain local-storage (set-item (+ "qsp_" key) str))
382 (chain local-storage (set-item (+ "qsp_" key) str))
384 (void))
383 (void))
385
384
386 (defun load-obj (key)
385 (defun load-obj (key)
387 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
386 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
388 (defun load-str (key)
387 (defun load-str (key)
389 (chain local-storage (get-item (+ "qsp_" key))))
388 (chain local-storage (get-item (+ "qsp_" key))))
390
389
391 ;;; Saves
390 ;;; Saves
392
391
393 (defun slot-savegame (slot comment)
392 (defun slot-savegame (slot comment)
394 (let ((saves (load-obj "saves")))
393 (let ((saves (load-obj "saves")))
395 (setf (@ saves slot) comment)
394 (setf (@ saves slot) comment)
396 (store-obj saves))
395 (store-obj saves))
397 (store-str slot (state-to-base64))
396 (store-str slot (state-to-base64))
398 (void))
397 (void))
399
398
400 (defun slot-loadgame (slot)
399 (defun slot-loadgame (slot)
401 (base64-to-state (load-str slot))
400 (base64-to-state (load-str slot))
402 (void))
401 (void))
403
402
404 (defun slot-deletegame (slot)
403 (defun slot-deletegame (slot)
405 (let ((saves (load-obj "saves")))
404 (let ((saves (load-obj "saves")))
406 (setf (@ saves slot) undefined)
405 (setf (@ saves slot) undefined)
407 (store-obj saves))
406 (store-obj saves))
408 (store-str slot undefined)
407 (store-str slot undefined)
409 (void))
408 (void))
410
409
411 (defun slot-listgames ()
410 (defun slot-listgames ()
412 (load-obj "saves"))
411 (load-obj "saves"))
413
412
414 (defun opengame ()
413 (defun opengame ()
415 (let ((element (chain document (create-element :input))))
414 (let ((element (chain document (create-element :input))))
416 (chain element (set-attribute :type :file))
415 (chain element (set-attribute :type :file))
417 (chain element (set-attribute :id :qsp-opengame))
416 (chain element (set-attribute :id :qsp-opengame))
418 (chain element (set-attribute :tabindex -1))
417 (chain element (set-attribute :tabindex -1))
419 (chain element (set-attribute "aria-hidden" t))
418 (chain element (set-attribute "aria-hidden" t))
420 (setf (@ element style display) :block)
419 (setf (@ element style display) :block)
421 (setf (@ element style visibility) :hidden)
420 (setf (@ element style visibility) :hidden)
422 (setf (@ element style position) :fixed)
421 (setf (@ element style position) :fixed)
423 (setf (@ element onchange)
422 (setf (@ element onchange)
424 (lambda (event)
423 (lambda (event)
425 (let* ((file (@ event target files 0))
424 (let* ((file (@ event target files 0))
426 (reader (new (*file-reader))))
425 (reader (new (*file-reader))))
427 (setf (@ reader onload)
426 (setf (@ reader onload)
428 (lambda (ev)
427 (lambda (ev)
429 (block nil
428 (block nil
430 (let ((target (@ ev current-target)))
429 (let ((target (@ ev current-target)))
431 (unless (@ target result)
430 (unless (@ target result)
432 (return))
431 (return))
433 (base64-to-state (@ target result))
432 (base64-to-state (@ target result))
434 (unstash-state)))))
433 (unstash-state)))))
435 (chain reader (read-as-text file)))))
434 (chain reader (read-as-text file)))))
436 (chain document body (append-child element))
435 (chain document body (append-child element))
437 (chain element (click))
436 (chain element (click))
438 (chain document body (remove-child element))))
437 (chain document body (remove-child element))))
439
438
440 (defun savegame ()
439 (defun savegame ()
441 (let ((element (chain document (create-element :a))))
440 (let ((element (chain document (create-element :a))))
442 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
441 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
443 (chain element (set-attribute :download "savegame.sav"))
442 (chain element (set-attribute :download "savegame.sav"))
444 (setf (@ element style display) :none)
443 (setf (@ element style display) :none)
445 (chain document body (append-child element))
444 (chain document body (append-child element))
446 (chain element (click))
445 (chain element (click))
447 (chain document body (remove-child element))))
446 (chain document body (remove-child element))))
448
447
449 (defun stash-state (args)
448 (defun stash-state (args)
450 (call-serv-loc "$ONGSAVE")
449 (call-serv-loc "$ONGSAVE")
451 (setf *state-stash
450 (setf *state-stash
452 (chain *j-s-o-n (stringify
451 (chain *j-s-o-n (stringify
453 (create :vars *globals
452 (create :vars *globals
454 :objs *objs
453 :objs *objs
455 :loc-args args
454 :loc-args args
456 :msecs (- (chain *date (now)) *started-at)
455 :msecs (- (chain *date (now)) *started-at)
457 :timer-interval *timer-interval
456 :timer-interval *timer-interval
458 :main-html (inner-html
457 :main-html (inner-html
459 (get-frame :main))
458 (get-frame :main))
460 :stat-html (inner-html
459 :stat-html (inner-html
461 (get-frame :stat))
460 (get-frame :stat))
462 :next-location *current-location))))
461 :next-location *current-location))))
463 (void))
462 (void))
464
463
465 (defun unstash-state ()
464 (defun unstash-state ()
466 (let ((data (chain *j-s-o-n (parse *state-stash))))
465 (let ((data (chain *j-s-o-n (parse *state-stash))))
467 (clear-act)
466 (clear-act)
468 (setf *globals (@ data :vars))
467 (setf *globals (@ data :vars))
469 (loop :for k :in (chain *object (keys *globals))
468 (loop :for k :in (chain *object (keys *globals))
470 :do (chain *object (set-prototype-of (getprop *globals k)
469 :do (chain *object (set-prototype-of (getprop *globals k)
471 (@ *var prototype))))
470 (@ *var prototype))))
472 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
471 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
473 (setf *objs (@ data :objs))
472 (setf *objs (@ data :objs))
474 (setf *current-location (@ data :next-location))
473 (setf *current-location (@ data :next-location))
475 (setf (inner-html (get-frame :main))
474 (setf (inner-html (get-frame :main))
476 (@ data :main-html))
475 (@ data :main-html))
477 (setf (inner-html (get-frame :stat))
476 (setf (inner-html (get-frame :stat))
478 (@ data :stat-html))
477 (@ data :stat-html))
479 (update-objs)
478 (update-objs)
480 (set-timer (@ data :timer-interval))
479 (set-timer (@ data :timer-interval))
481 (call-serv-loc "$ONGLOAD")
480 (call-serv-loc "$ONGLOAD")
482 (call-loc *current-location (@ data :loc-args))
481 (call-loc *current-location (@ data :loc-args))
483 (void)))
482 (void)))
484
483
485 (defun state-to-base64 ()
484 (defun state-to-base64 ()
486 (btoa (encode-u-r-i-component *state-stash)))
485 (btoa (encode-u-r-i-component *state-stash)))
487
486
488 (defun base64-to-state (data)
487 (defun base64-to-state (data)
489 (setf *state-stash (decode-u-r-i-component (atob data))))
488 (setf *state-stash (decode-u-r-i-component (atob data))))
490
489
491 ;;; Timers
490 ;;; Timers
492
491
493 (defun set-timer (interval)
492 (defun set-timer (interval)
494 (setf *timer-interval interval)
493 (setf *timer-interval interval)
495 (clear-interval *timer-obj)
494 (clear-interval *timer-obj)
496 (setf *timer-obj
495 (setf *timer-obj
497 (set-interval
496 (set-interval
498 (lambda ()
497 (lambda ()
499 (call-serv-loc "$COUNTER"))
498 (call-serv-loc "$COUNTER"))
500 interval)))
499 interval)))
501
500
502 ;;; Special variables
501 ;;; Special variables
503
502
504 (defvar serv-vars (create))
503 (defvar serv-vars (create))
505
504
506 (define-serv-var $backimage (path)
505 (define-serv-var $backimage (path)
507 (setf (@ (get-frame :main) style background-image) path))
506 (setf (@ (get-frame :main) style background-image) path))
508
507
509 (define-serv-var bcolor (color)
508 (define-serv-var bcolor (color)
510 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
509 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
511
510
512 (define-serv-var fcolor (color)
511 (define-serv-var fcolor (color)
513 (setf (@ (get-frame :all) style color) (rgb-string color)))
512 (setf (@ (get-frame :all) style color) (rgb-string color)))
514
513
515 (define-serv-var lcolor (color)
514 (define-serv-var lcolor (color)
516 (setf (@ (get-frame :style) inner-text)
515 (setf (@ (get-frame :style) inner-text)
517 (+ "a { color: " (rgb-string color) ";}")))
516 (+ "a { color: " (rgb-string color) ";}")))
518
517
519 (define-serv-var fsize (size)
518 (define-serv-var fsize (size)
520 (setf (@ (get-frame :all) style font-size) size))
519 (setf (@ (get-frame :all) style font-size) size))
521
520
522 (define-serv-var $fname (font-name)
521 (define-serv-var $fname (font-name)
523 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
522 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
@@ -1,181 +1,180 b''
1
1
2 (in-package txt2web.lib)
2 (in-package txt2web.lib)
3
3
4 ;;;; Macros implementing some intrinsics where it makes sense
4 ;;;; Macros implementing some intrinsics where it makes sense
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6
6
7 ;;; 1loc
7 ;;; 1loc
8
8
9 ;;; 2var
9 ;;; 2var
10
10
11 (defpsmacro killvar (&optional varname index)
11 (defpsmacro killvar (&optional varname index)
12 `(api-call kill-var ,varname ,index))
12 `(api-call kill-var ,varname ,index))
13
13
14 (defpsmacro killall ()
14 (defpsmacro killall ()
15 `(progn
15 `(progn
16 (killvar)
16 (killvar)
17 (killobj)))
17 (killobj)))
18
18
19 ;;; 3expr
19 ;;; 3expr
20
20
21 (defpsmacro no (arg)
21 (defpsmacro no (arg)
22 `(- -1 ,arg))
22 `(- -1 ,arg))
23
23
24 ;;; 4code
24 ;;; 4code
25
25
26 (defpsmacro qspver ()
26 (defpsmacro qspver ()
27 "0.0.1")
27 "0.0.1")
28
28
29 (defpsmacro curloc ()
29 (defpsmacro curloc ()
30 `*current-location)
30 `*current-location)
31
31
32 (defpsmacro rnd ()
32 (defpsmacro rnd ()
33 `(funcall rand 1 1000))
33 `(funcall rand 1 1000))
34
34
35 (defpsmacro qspmax (&rest args)
35 (defpsmacro qspmax (&rest args)
36 (if (= 1 (length args))
36 (if (= 1 (length args))
37 `(*math.max.apply nil ,@args)
37 `(*math.max.apply nil ,@args)
38 `(*math.max ,@args)))
38 `(*math.max ,@args)))
39
39
40 (defpsmacro qspmin (&rest args)
40 (defpsmacro qspmin (&rest args)
41 (if (= 1 (length args))
41 (if (= 1 (length args))
42 `(*math.min.apply nil ,@args)
42 `(*math.min.apply nil ,@args)
43 `(*math.min ,@args)))
43 `(*math.min ,@args)))
44
44
45 ;;; 5arrays
45 ;;; 5arrays
46
46
47 (defpsmacro arrsize (name)
47 (defpsmacro arrsize (name)
48 `(api-call array-size ,name))
48 `(api-call array-size ,name))
49
49
50 ;;; 6str
50 ;;; 6str
51
51
52 (defpsmacro len (s)
52 (defpsmacro len (s)
53 `(length ,s))
53 `(length ,s))
54
54
55 (defpsmacro mid (s from &optional count)
55 (defpsmacro mid (s from &optional count)
56 `(chain ,s (substring ,from ,count)))
56 `(chain ,s (substring ,from ,count)))
57
57
58 (defpsmacro ucase (s)
58 (defpsmacro ucase (s)
59 `(chain ,s (to-upper-case)))
59 `(chain ,s (to-upper-case)))
60
60
61 (defpsmacro lcase (s)
61 (defpsmacro lcase (s)
62 `(chain ,s (to-lower-case)))
62 `(chain ,s (to-lower-case)))
63
63
64 (defpsmacro trim (s)
64 (defpsmacro trim (s)
65 `(chain ,s (trim)))
65 `(chain ,s (trim)))
66
66
67 (defpsmacro qspreplace (s from to)
67 (defpsmacro qspreplace (s from to)
68 `(chain ,s (replace ,from ,to)))
68 `(chain ,s (replace ,from ,to)))
69
69
70 (defpsmacro val (s)
70 (defpsmacro val (s)
71 `(parse-int ,s 10))
71 `(parse-int ,s 10))
72
72
73 (defpsmacro qspstr (n)
73 (defpsmacro qspstr (n)
74 `(chain ,n (to-string)))
74 `(chain ,n (to-string)))
75
75
76 ;;; 7if
76 ;;; 7if
77
77
78 ;;; 8sub
78 ;;; 8sub
79
79
80 ;;; 9loops
80 ;;; 9loops
81
81
82 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
82 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
83
83
84 (defpsmacro exit ()
84 (defpsmacro exit ()
85 `(return-from nil (values)))
85 `(return-from nil (values)))
86
86
87 ;;; 10dynamic
87 ;;; 10dynamic
88
88
89 (defpsmacro dynamic (block &rest args)
89 (defpsmacro dynamic (block &rest args)
90 `(progn
90 `(progn
91 (when (stringp ,block)
91 (when (stringp ,block)
92 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
92 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
93 (api:with-call-args ,args
93 (api:with-call-args ,args nil
94 (funcall ,block))
94 (funcall ,block))))
95 (void)))
96
95
97 (defpsmacro dyneval (block &rest args)
96 (defpsmacro dyneval (block &rest args)
98 `(progn
97 `(progn
99 (when (stringp block)
98 (when (stringp ,block)
100 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
99 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
101 (api:with-call-args args
100 (api:with-call-args ,args t
102 (funcall block))))
101 (funcall ,block))))
103
102
104 ;;; 11main
103 ;;; 11main
105
104
106 (defpsmacro desc (s)
105 (defpsmacro desc (s)
107 (declare (ignore s))
106 (declare (ignore s))
108 "")
107 "")
109
108
110 ;;; 12stat
109 ;;; 12stat
111
110
112 (defpsmacro showstat (enable)
111 (defpsmacro showstat (enable)
113 `(api-call enable-frame :stat ,enable))
112 `(api-call enable-frame :stat ,enable))
114
113
115 ;;; 13diag
114 ;;; 13diag
116
115
117 (defpsmacro msg (text)
116 (defpsmacro msg (text)
118 `(alert ,text))
117 `(alert ,text))
119
118
120 ;;; 14act
119 ;;; 14act
121
120
122 (defpsmacro showacts (enable)
121 (defpsmacro showacts (enable)
123 `(api-call enable-frame :acts ,enable))
122 `(api-call enable-frame :acts ,enable))
124
123
125 (defpsmacro delact (&optional name)
124 (defpsmacro delact (&optional name)
126 (if name
125 (if name
127 `(api-call del-act ,name)
126 `(api-call del-act ,name)
128 `(api-call del-act)))
127 `(api-call del-act)))
129
128
130 (defpsmacro cla ()
129 (defpsmacro cla ()
131 `(api-call clear-act))
130 `(api-call clear-act))
132
131
133 ;;; 15objs
132 ;;; 15objs
134
133
135 (defpsmacro showobjs (enable)
134 (defpsmacro showobjs (enable)
136 `(api-call enable-frame :objs ,enable))
135 `(api-call enable-frame :objs ,enable))
137
136
138 (defpsmacro countobj ()
137 (defpsmacro countobj ()
139 `(length *objs))
138 `(length *objs))
140
139
141 (defpsmacro getobj (index)
140 (defpsmacro getobj (index)
142 `(or (elt *objs ,index) ""))
141 `(or (elt *objs ,index) ""))
143
142
144 ;;; 16menu
143 ;;; 16menu
145
144
146 ;;; 17sound
145 ;;; 17sound
147
146
148 (defpsmacro isplay (filename)
147 (defpsmacro isplay (filename)
149 `(funcall (@ playing includes) ,filename))
148 `(funcall (@ playing includes) ,filename))
150
149
151 ;;; 18img
150 ;;; 18img
152
151
153 (defpsmacro view (&optional path)
152 (defpsmacro view (&optional path)
154 `(api-call show-image ,path))
153 `(api-call show-image ,path))
155
154
156 ;;; 19input
155 ;;; 19input
157
156
158 (defpsmacro showinput (enable)
157 (defpsmacro showinput (enable)
159 `(api-call enable-frame :input ,enable))
158 `(api-call enable-frame :input ,enable))
160
159
161 ;;; 20time
160 ;;; 20time
162
161
163 (defpsmacro wait (msec)
162 (defpsmacro wait (msec)
164 `(await (api-call sleep ,msec)))
163 `(await (api-call sleep ,msec)))
165
164
166 (defpsmacro settimer (interval)
165 (defpsmacro settimer (interval)
167 `(api-call set-timer ,interval))
166 `(api-call set-timer ,interval))
168
167
169 ;;; 21local
168 ;;; 21local
170
169
171 ;;; 22for
170 ;;; 22for
172
171
173 ;;; misc
172 ;;; misc
174
173
175 (defpsmacro opengame (&optional filename)
174 (defpsmacro opengame (&optional filename)
176 (declare (ignore filename))
175 (declare (ignore filename))
177 `(api-call opengame))
176 `(api-call opengame))
178
177
179 (defpsmacro savegame (&optional filename)
178 (defpsmacro savegame (&optional filename)
180 (declare (ignore filename))
179 (declare (ignore filename))
181 `(api-call savegame))
180 `(api-call savegame))
General Comments 0
You need to be logged in to leave comments. Login now