chiark / gitweb /
gtk/gtk.lisp: Apparently when you ask for a stock Button, you get a Bin.
[clg] / glib / gcallback.lisp
CommitLineData
112ac1d3 1;; Common Lisp bindings for GTK+ v2.x
2;; Copyright 2000 Espen S. Johnsen <espen@users.sf.net>
c8c48a4c 3;;
112ac1d3 4;; Permission is hereby granted, free of charge, to any person obtaining
5;; a copy of this software and associated documentation files (the
6;; "Software"), to deal in the Software without restriction, including
7;; without limitation the rights to use, copy, modify, merge, publish,
8;; distribute, sublicense, and/or sell copies of the Software, and to
9;; permit persons to whom the Software is furnished to do so, subject to
10;; the following conditions:
c8c48a4c 11;;
112ac1d3 12;; The above copyright notice and this permission notice shall be
13;; included in all copies or substantial portions of the Software.
c8c48a4c 14;;
112ac1d3 15;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
ce9d2008 23;; $Id: gcallback.lisp,v 1.51 2009-02-10 15:18:15 espen Exp $
c8c48a4c 24
25(in-package "GLIB")
26
27(use-prefix "g")
28
29
457f874e 30;;;; Callback invocation
c8c48a4c 31
6851535e 32(deftype gclosure () 'pointer)
33(register-type 'gclosure '|g_closure_get_type|)
34
e378b861 35(defun register-callback-function (function)
36 (check-type function (or null symbol function))
37 (register-user-data function))
c8c48a4c 38
e69e2618 39(deftype user-callback () '(or function symbol))
40
41(define-type-method alien-type ((type user-callback))
42 (declare (ignore type))
43 (alien-type 'pointer-data))
44
45(define-type-method to-alien-form ((type user-callback) func &optional copy-p)
46 (declare (ignore type copy-p))
47 `(register-callback-function ,func))
48
49
e7225d0f 50;; Callback marshaller for regular signal handlers
51(define-callback signal-handler-marshal nil
56ccd5b7 52 ((gclosure gclosure) (return-value gvalue) (n-params unsigned-int)
53 (param-values pointer) (invocation-hint pointer)
41932b02 54 (callback-id pointer-data))
266ca870 55 (declare (ignore gclosure invocation-hint))
e7225d0f 56 (callback-trampoline #'invoke-signal-handler callback-id n-params param-values return-value))
c8c48a4c 57
41932b02 58;; Callback marshaller for class handlers
e7225d0f 59(define-callback class-handler-marshal nil
60 ((gclosure gclosure) (return-value gvalue) (n-params unsigned-int)
61 (param-values pointer) (invocation-hint pointer)
41932b02 62 (callback-id pointer-data))
e7225d0f 63 (declare (ignore gclosure invocation-hint))
64 (callback-trampoline #'invoke-callback callback-id n-params param-values return-value))
65
66;; Callback marshaller for emission hooks
67(define-callback emission-hook-marshal nil
56ccd5b7 68 ((invocation-hint pointer) (n-params unsigned-int) (param-values pointer)
41932b02 69 (callback-id pointer-data))
5de2b5f6 70 (declare (ignore invocation-hint))
e7225d0f 71 (callback-trampoline #'invoke-callback callback-id n-params param-values))
e0d2987b 72
e7225d0f 73(defun callback-trampoline (restart-wrapper callback-id n-params param-values
74 &optional (return-value (make-pointer 0)))
c8c48a4c 75 (let* ((return-type (unless (null-pointer-p return-value)
e378b861 76 (gvalue-type return-value)))
34f9e1d4 77 (args (loop
78 for n from 0 below n-params
832df308 79 for offset from 0 by +gvalue-size+
77a843ca 80 collect (gvalue-peek (pointer+ param-values offset)))))
832df308 81 (unwind-protect
e7225d0f 82 (multiple-value-bind (result aborted-p)
83 (apply restart-wrapper callback-id nil args)
84 (when (and return-type (not aborted-p))
832df308 85 (gvalue-set return-value result)))
77a843ca 86 ;; TODO: this should be made more general, by adding a type
e7225d0f 87 ;; method to return invalidating functions.
832df308 88 (loop
89 for arg in args
77a843ca 90 when (typep arg 'struct)
832df308 91 do (invalidate-instance arg)))))
92
e7225d0f 93(defun invoke-signal-handler (callback-id return-type &rest args)
94 (declare (ignore return-type))
95 (let* ((instance (first args))
96 (handler-id (signal-handler-find instance '(:data)
97 0 0 nil nil callback-id)))
98 (signal-handler-block instance handler-id)
99 (unwind-protect
100 (restart-case (apply #'invoke-callback callback-id nil args)
bbb73c8a 101 (disconnect () :report "Disconnect and exit signal handler"
e7225d0f 102 (when (signal-handler-is-connected-p instance handler-id)
103 (signal-handler-disconnect instance handler-id))
e69e2618 104 (values nil t)))
e7225d0f 105 (when (signal-handler-is-connected-p instance handler-id)
e69e2618 106 (signal-handler-unblock instance handler-id)))))
34f9e1d4 107
8755b1a5 108(defun invoke-callback (callback-id return-type &rest args)
e7225d0f 109 (restart-case (apply (find-user-data callback-id) args)
34f9e1d4 110 (continue nil :report "Return from callback function"
e7225d0f 111 (cond
112 (return-type
113 (format *query-io* "Enter return value of type ~S: " return-type)
114 (force-output *query-io*)
115 (eval (read *query-io*)))
116 (t (values nil t))))
34f9e1d4 117 (re-invoke nil :report "Re-invoke callback function"
e7225d0f 118 (apply #'invoke-callback callback-id return-type args))))
c8c48a4c 119
c8c48a4c 120
e378b861 121;;;; Timeouts and idle functions
122
acd28982 123(defconstant +priority-high+ -100)
124(defconstant +priority-default+ 0)
125(defconstant +priority-high-idle+ 100)
126(defconstant +priority-default-idle+ 200)
127(defconstant +priority-low+ 300)
128
129(defbinding source-remove () boolean
130 (tag unsigned-int))
131
bbb73c8a 132(define-callback source-callback-marshal boolean ((callback-id unsigned-int))
133 (invoke-source-callback callback-id))
134
34c336c4 135(defun invoke-source-callback (callback-id &rest args)
136 (restart-case (apply (find-user-data callback-id) args)
bbb73c8a 137 (remove () :report "Exit and remove source callback"
138 nil)
139 (continue () :report "Return from source callback"
140 t)
141 (re-invoke nil :report "Re-invoke source callback"
34c336c4 142 (apply #'invoke-source-callback callback-id args))))
bbb73c8a 143
e378b861 144
145(defbinding (timeout-add "g_timeout_add_full")
acd28982 146 (interval function &optional (priority +priority-default+)) unsigned-int
e378b861 147 (priority int)
148 (interval unsigned-int)
56ccd5b7 149 (source-callback-marshal callback)
e378b861 150 ((register-callback-function function) unsigned-long)
56ccd5b7 151 (user-data-destroy-callback callback))
e378b861 152
acd28982 153(defun timeout-remove (timeout)
154 (source-remove timeout))
155
e378b861 156(defbinding (idle-add "g_idle_add_full")
acd28982 157 (function &optional (priority +priority-default-idle+)) unsigned-int
e378b861 158 (priority int)
56ccd5b7 159 (source-callback-marshal callback)
e378b861 160 ((register-callback-function function) unsigned-long)
56ccd5b7 161 (user-data-destroy-callback callback))
e378b861 162
acd28982 163(defun idle-remove (idle)
164 (source-remove idle))
e378b861 165
c8c48a4c 166
e0d2987b 167;;;; Signal information querying
c8c48a4c 168
e0d2987b 169(defbinding signal-lookup (name type) unsigned-int
c8c48a4c 170 ((signal-name-to-string name) string)
e0d2987b 171 ((find-type-number type t) type-number))
c8c48a4c 172
c345a646 173(defbinding signal-name () (or null (copy-of string))
c8c48a4c 174 (signal-id unsigned-int))
175
e0d2987b 176(defbinding signal-list-ids (type) (vector unsigned-int n-ids)
177 ((find-type-number type t) type-number)
178 (n-ids unsigned-int :out))
179
180(defun signal-list-names (type)
181 (map 'list #'signal-name (signal-list-ids type)))
182
183(defun ensure-signal-id-from-type (signal-id type)
c8c48a4c 184 (etypecase signal-id
e0d2987b 185 (integer (if (signal-name signal-id)
186 signal-id
187 (error "Invalid signal id: ~D" signal-id)))
188 ((or symbol string)
189 (let ((numeric-id (signal-lookup signal-id type)))
190 (if (zerop numeric-id)
191 (error "Invalid signal name for ~S: ~D" type signal-id)
192 numeric-id)))))
193
194(defun ensure-signal-id (signal-id instance)
195 (ensure-signal-id-from-type signal-id (type-of instance)))
c8c48a4c 196
e0d2987b 197(eval-when (:compile-toplevel :load-toplevel :execute)
198 (deftype signal-flags ()
199 '(flags :run-first :run-last :run-cleanup :no-recurse
200 :detailed :action :no-hooks))
201
e7225d0f 202 (define-flags-type signal-match-type
203 :id :detail :closure :func :data :unblocked)
204
e0d2987b 205 (defclass signal-query (struct)
206 ((id :allocation :alien :type unsigned-int)
207 (name :allocation :alien :type (copy-of string))
208 (type :allocation :alien :type type-number)
209 (flags :allocation :alien :type signal-flags)
210 (return-type :allocation :alien :type type-number)
211 (n-params :allocation :alien :type unsigned-int)
212 (param-types :allocation :alien :type pointer))
213 (:metaclass struct-class)))
214
215(defbinding signal-query
216 (signal-id &optional (signal-query (make-instance 'signal-query))) nil
217 (signal-id unsigned-int)
77a843ca 218 (signal-query signal-query :in/return))
e0d2987b 219
220(defun signal-param-types (info)
221 (with-slots (n-params param-types) info
222 (map-c-vector 'list
223 #'(lambda (type-number)
224 (type-from-number type-number))
225 param-types 'type-number n-params)))
226
227
228(defun describe-signal (signal-id &optional type)
229 (let ((info (signal-query (ensure-signal-id-from-type signal-id type))))
230 (with-slots (id name type flags return-type n-params) info
457f874e 231 (format t "The signal with id ~D is named '~A' and may be emitted on instances of type ~S." id name (type-from-number type t))
232 (when flags
233 (format t " It has the followin invocation flags: ~{~S ~}" flags))
234 (format t "~%~%Signal handlers should take ~A and return ~A~%"
e0d2987b 235 (if (zerop n-params)
236 "no arguments"
237 (format nil "arguments with the following types: ~A"
457f874e 238 (signal-param-types info)))
239 (cond
240 ((= return-type (find-type-number "void")) "no values")
241 ((not (type-from-number return-type)) "values of unknown type")
242 ((format nil "values of type ~S" (type-from-number return-type))))))))
e0d2987b 243
244
245;;;; Signal connecting and controlling
246
8d5ac0cb 247(define-flags-type connect-flags :after :swapped)
248
ce9d2008 249(defvar *signal-override-closures* (make-hash-table :test 'equalp))
9944c385 250
ce9d2008 251(defbinding %%signal-override-class-closure () nil
9944c385 252 (signal-id unsigned-int)
253 (type-number type-number)
254 (callback-closure pointer))
255
256
ce9d2008 257(defun %signal-override-class-closure (type name function)
258 (multiple-value-bind (callback-closure callback-id)
259 (make-callback-closure function class-handler-marshal)
260 (let ((signal-id (ensure-signal-id-from-type name type)))
261 (%%signal-override-class-closure signal-id (find-type-number type t) callback-closure))
262 (setf
263 (gethash (list type name) *signal-override-closures*)
264 (list callback-id function))))
265
9944c385 266(defun signal-override-class-closure (name type function)
ce9d2008 267 (let ((callback-id
268 (first (gethash (list type name) *signal-override-closures*))))
9944c385 269 (if callback-id
270 (update-user-data callback-id function)
ce9d2008 271 (%signal-override-class-closure type name function))))
9944c385 272
ce9d2008 273(defun reinitialize-signal-override-class-closures ()
274 (maphash
275 #'(lambda (key value)
276 (destructuring-bind (type name) key
277 (destructuring-bind (callback-id function) value
278 (declare (ignore callback-id))
279 (%signal-override-class-closure type name function))))
280 *signal-override-closures*))
9944c385 281
282(defbinding %signal-chain-from-overridden () nil
283 (args pointer)
284 (return-value (or null gvalue)))
285
38049b1a 286
287(defun %call-next-handler (n-params types args return-type)
9944c385 288 (let ((params (allocate-memory (* n-params +gvalue-size+))))
289 (loop
38049b1a 290 for arg in args
9944c385 291 for type in types
292 for offset from 0 by +gvalue-size+
77a843ca 293 do (gvalue-init (pointer+ params offset) type arg))
9944c385 294
295 (unwind-protect
296 (if return-type
297 (with-gvalue (return-value return-type)
298 (%signal-chain-from-overridden params return-value))
299 (%signal-chain-from-overridden params nil))
300 (progn
301 (loop
302 repeat n-params
303 for offset from 0 by +gvalue-size+
77a843ca 304 do (gvalue-unset (pointer+ params offset)))
9944c385 305 (deallocate-memory params)))))
306
9944c385 307(defmacro define-signal-handler (name ((object class) &rest args) &body body)
308 (let* ((info (signal-query (ensure-signal-id-from-type name class)))
309 (types (cons class (signal-param-types info)))
310 (n-params (1+ (slot-value info 'n-params)))
311 (return-type (type-from-number (slot-value info 'return-type)))
312 (vars (loop
313 for arg in args
314 until (eq arg '&rest)
315 collect arg))
316 (rest (cadr (member '&rest args)))
38049b1a 317 (next (make-symbol "ARGS"))
318 (default (make-symbol "DEFAULT")))
9944c385 319
320 `(progn
321 (signal-override-class-closure ',name ',class
322 #'(lambda (,object ,@args)
38049b1a 323 (let ((,default (list* ,object ,@vars ,rest)))
324 (flet ((call-next-handler (&rest ,next)
9944c385 325 (%call-next-handler
e1fcda22 326 ,n-params ',types (or ,next ,default) ',return-type)))
327 ,@body))))
9944c385 328 ',name)))
329
330
e0d2987b 331(defbinding %signal-stop-emission () nil
c8c48a4c 332 (instance ginstance)
e0d2987b 333 (signal-id unsigned-int)
334 (detail quark))
335
336(defvar *signal-stop-emission* nil)
337(declaim (special *signal-stop-emission*))
c8c48a4c 338
e0d2987b 339(defun signal-stop-emission ()
340 (if *signal-stop-emission*
341 (funcall *signal-stop-emission*)
342 (error "Not inside a signal handler")))
343
344
345(defbinding signal-add-emission-hook (type signal function &key (detail 0))
e7225d0f 346 unsigned-long
e0d2987b 347 ((ensure-signal-id-from-type signal type) unsigned-int)
348 (detail quark)
e7225d0f 349 (emission-hook-marshal callback)
e0d2987b 350 ((register-callback-function function) unsigned-int)
56ccd5b7 351 (user-data-destroy-callback callback))
e0d2987b 352
353(defbinding signal-remove-emission-hook (type signal hook-id) nil
354 ((ensure-signal-id-from-type signal type) unsigned-int)
e7225d0f 355 (hook-id unsigned-long))
c8c48a4c 356
c8c48a4c 357
0383dd48 358(defbinding (signal-has-handler-pending-p "g_signal_has_handler_pending")
c8c48a4c 359 (instance signal-id &key detail blocked) boolean
360 (instance ginstance)
e49e135a 361 ((ensure-signal-id signal-id instance) unsigned-int)
c8c48a4c 362 ((or detail 0) quark)
73572c12 363 (blocked boolean))
c8c48a4c 364
e7225d0f 365(defbinding %signal-connect-closure-by-id () unsigned-long
c8c48a4c 366 (instance ginstance)
e0d2987b 367 (signal-id unsigned-int)
368 (detail quark)
369 (closure pointer)
c8c48a4c 370 (after boolean))
371
0383dd48 372(defbinding signal-handler-block () nil
c8c48a4c 373 (instance ginstance)
e7225d0f 374 (handler-id unsigned-long))
c8c48a4c 375
0383dd48 376(defbinding signal-handler-unblock () nil
c8c48a4c 377 (instance ginstance)
e7225d0f 378 (handler-id unsigned-long))
379
380;; Internal
381(defbinding signal-handler-find () unsigned-long
382 (instance gobject)
383 (mask signal-match-type)
384 (signal-id unsigned-int)
385 (detail quark)
386 (closure (or null pointer))
387 (func (or null pointer))
b7c49e0c 388 (data pointer-data))
c8c48a4c 389
0383dd48 390(defbinding signal-handler-disconnect () nil
c8c48a4c 391 (instance ginstance)
e7225d0f 392 (handler-id unsigned-long))
e0d2987b 393
394(defbinding signal-handler-is-connected-p () boolean
395 (instance ginstance)
e7225d0f 396 (handler-id unsigned-long))
c8c48a4c 397
d4f4418a 398(defbinding (closure-new "g_cclosure_new") () gclosure
399 ((make-pointer #xFFFFFFFF) pointer)
e0d2987b 400 (callback-id unsigned-int)
56ccd5b7 401 (destroy-notify callback))
c8c48a4c 402
d4f4418a 403(defbinding closure-set-meta-marshal () nil
404 (gclosure gclosure)
405 (callback-id unsigned-int)
406 (callback callback))
407
408(defun callback-closure-new (callback-id callback destroy-notify)
409 (let ((gclosure (closure-new callback-id destroy-notify)))
410 (closure-set-meta-marshal gclosure callback-id callback)
411 gclosure))
412
b7c49e0c 413(defun make-callback-closure (function &optional (marshaller signal-handler-marshal))
e0d2987b 414 (let ((callback-id (register-callback-function function)))
415 (values
e7225d0f 416 (callback-closure-new callback-id marshaller user-data-destroy-callback)
e0d2987b 417 callback-id)))
418
457f874e 419(defgeneric compute-signal-function (gobject signal function object args))
65670fe5 420
457f874e 421(defmethod compute-signal-function ((gobject gobject) signal function object args)
cd9b9e8b 422 (declare (ignore signal))
e0d2987b 423 (cond
457f874e 424 ((or (eq object t) (eq object gobject))
425 (if args
426 #'(lambda (&rest emission-args)
427 (apply function (nconc emission-args args)))
428 function))
429 (object
430 (if args
431 #'(lambda (&rest emission-args)
432 (apply function object (nconc (rest emission-args) args)))
433 #'(lambda (&rest emission-args)
434 (apply function object (rest emission-args)))))
435 (args
436 #'(lambda (&rest emission-args)
437 (apply function (nconc (rest emission-args) args))))
e0d2987b 438 (t
457f874e 439 #'(lambda (&rest emission-args)
440 (apply function (rest emission-args))))))
cd9b9e8b 441
442(defgeneric compute-signal-id (gobject signal))
443
444(defmethod compute-signal-id ((gobject gobject) signal)
445 (ensure-signal-id signal gobject))
446
447
457f874e 448(defgeneric signal-connect (gobject signal function &key detail after object remove args))
cd9b9e8b 449
450(defmethod signal-connect :around ((gobject gobject) signal function &rest args)
451 (declare (ignore gobject signal args))
452 (when function
453 (call-next-method)))
e0d2987b 454
65670fe5 455
e0d2987b 456(defmethod signal-connect ((gobject gobject) signal function
457f874e 457 &key detail after object remove args)
e0d2987b 458"Connects a callback function to a signal for a particular object. If
459:OBJECT is T, the object connected to is passed as the first argument
460to the callback function, or if :OBJECT is any other non NIL value, it
461is passed as the first argument instead. If :AFTER is non NIL, the
462handler will be called after the default handler for the signal. If
463:REMOVE is non NIL, the handler will be removed after beeing invoked
457f874e 464once. ARGS is a list of additional arguments passed to the callback
465function."
d1b6a54e 466 (let* ((signal-id (compute-signal-id gobject signal))
467 (detail-quark (if detail (quark-intern detail) 0))
468 (callback
469 (compute-signal-function gobject signal function object args))
470 (wrapper
471 #'(lambda (&rest args)
472 (let ((*signal-stop-emission*
473 #'(lambda ()
474 (%signal-stop-emission (first args)
475 signal-id detail-quark))))
476 (apply callback args)))))
477 (multiple-value-bind (closure-id callback-id)
478 (make-callback-closure wrapper signal-handler-marshal)
479 (let ((handler-id (%signal-connect-closure-by-id
480 gobject signal-id detail-quark closure-id after)))
481 (when remove
482 (update-user-data callback-id
483 #'(lambda (&rest args)
484 (let ((gobject (first args)))
e0d2987b 485 (unwind-protect
d1b6a54e 486 (let ((*signal-stop-emission*
487 #'(lambda ()
488 (%signal-stop-emission gobject
489 signal-id detail-quark))))
490 (apply callback args))
e7225d0f 491 (when (signal-handler-is-connected-p gobject handler-id)
d1b6a54e 492 (signal-handler-disconnect gobject handler-id)))))))
493 handler-id))))
e0d2987b 494
495
496;;;; Signal emission
497
498(defbinding %signal-emitv () nil
499 (gvalues pointer)
500 (signal-id unsigned-int)
501 (detail quark)
502 (return-value gvalue))
503
504(defvar *signal-emit-functions* (make-hash-table))
505
506(defun create-signal-emit-function (signal-id)
507 (let ((info (signal-query signal-id)))
508 (let* ((type (type-from-number (slot-value info 'type)))
509 (param-types (cons type (signal-param-types info)))
510 (return-type (type-from-number (slot-value info 'return-type)))
511 (n-params (1+ (slot-value info 'n-params)))
512 (params (allocate-memory (* n-params +gvalue-size+))))
513 #'(lambda (detail object &rest args)
514 (unless (= (length args) (1- n-params))
b4375317 515 (error "Invalid number of arguments in emmision of signal ~A: ~A" signal-id (length args)))
e0d2987b 516 (unwind-protect
517 (loop
518 for arg in (cons object args)
519 for type in param-types
77a843ca 520 as tmp = params then (pointer+ tmp +gvalue-size+)
e0d2987b 521 do (gvalue-init tmp type arg)
522 finally
523 (if return-type
524 (return
ca5f64e9 525 (with-gvalue (return-value return-type)
e0d2987b 526 (%signal-emitv params signal-id detail return-value)))
527 (%signal-emitv params signal-id detail (make-pointer 0))))
528 (loop
529 repeat n-params
77a843ca 530 as tmp = params then (pointer+ tmp +gvalue-size+)
e0d2987b 531 while (gvalue-p tmp)
532 do (gvalue-unset tmp)))))))
533
534(defun signal-emit-with-detail (object signal detail &rest args)
535 (let* ((signal-id (ensure-signal-id signal object))
536 (function (or
537 (gethash signal-id *signal-emit-functions*)
538 (setf
539 (gethash signal-id *signal-emit-functions*)
540 (create-signal-emit-function signal-id)))))
541 (apply function detail object args)))
542
543(defun signal-emit (object signal &rest args)
544 (apply #'signal-emit-with-detail object signal 0 args))
545
c0f178d0 546
457f874e 547;;;; Signal registration
548
ce9d2008 549(defvar *registered-signals* ())
550
457f874e 551(defbinding %signal-newv (name itype flags return-type param-types)
552 unsigned-int
553 ((signal-name-to-string name) string)
554 (itype gtype)
555 (flags signal-flags)
556 (nil null) ; class closure
557 (nil null) ; accumulator
558 (nil null) ; accumulator data
559 (nil null) ; c marshaller
560 (return-type gtype)
561 ((length param-types) unsigned-int)
562 (param-types (vector gtype)))
563
564(defun signal-new (name itype flags return-type param-types)
565 (when (zerop (signal-lookup name itype))
ce9d2008 566 (push (list name itype flags return-type param-types) *registered-signals*)
457f874e 567 (%signal-newv name itype flags return-type param-types)))
568
ce9d2008 569(defun reinitialize-signals ()
570 (mapc #'(lambda (args) (apply #'%signal-newv args)) *registered-signals*))
571
572(asdf:install-init-hook 'reinitialize-signals)
573(asdf:install-init-hook 'reinitialize-signal-override-class-closures)
574
fd1e4a39 575;;;; Convenient macros
576
56ccd5b7 577(defmacro define-callback-marshal (name return-type args &key (callback-id :last))
578 (let* ((ignore ())
579 (params ())
580 (names (loop
581 for arg in args
582 collect (if (or
583 (eq arg :ignore)
584 (and (consp arg) (eq (first arg) :ignore)))
585 (let ((name (gensym "IGNORE")))
586 (push name ignore)
587 name)
588 (let ((name (if (atom arg)
589 (gensym (string arg))
590 (first arg))))
591 (push name params)
592 name))))
593 (types (loop
594 for arg in args
595 collect (cond
596 ((eq arg :ignore) 'pointer)
597 ((atom arg) arg)
598 (t (second arg))))))
599 `(define-callback ,name ,return-type
600 ,(ecase callback-id
0146aef0 601 (:first `((callback-id pointer-data) ,@(mapcar #'list names types)))
602 (:last `(,@(mapcar #'list names types) (callback-id pointer-data))))
56ccd5b7 603 (declare (ignore ,@ignore))
248f4dd7 604 (invoke-callback callback-id ',return-type ,@(nreverse params)))))
fd1e4a39 605
606(defmacro with-callback-function ((id function) &body body)
607 `(let ((,id (register-callback-function ,function)))
608 (unwind-protect
609 (progn ,@body)
610 (destroy-user-data ,id))))