Since Gtk+-2.18 "helpfully" ignores SIGPIPE in gtk_init, reinstall handler
[cl-gtk2.git] / glib / gobject.type-designator.lisp
blob98a48082b1b5cdaed272572ab2c1d5195646958f
1 (in-package :gobject.ffi)
3 (defctype g-type gsize)
5 (defstruct gtype name %id)
7 (defvar *name-to-gtype* (make-hash-table :test 'equal))
8 (defvar *id-to-gtype* (make-hash-table))
9 (defvar *gtype-lock* (bt:make-lock "gtype lock"))
11 (defun invalidate-gtypes ()
12 (bt:with-lock-held (*gtype-lock*)
13 (clrhash *id-to-gtype*)
14 (iter (for (name gtype) in-hashtable *name-to-gtype*)
15 (setf (gtype-%id gtype) nil))))
17 (at-finalize () (invalidate-gtypes))
19 (defcfun (%g-type-from-name "g_type_from_name") g-type
20 (name :string))
22 (defcfun (%g-type-name "g_type_name") (:string :free-from-foreign nil)
23 (type g-type))
25 (defun warn-unknown-gtype (name)
26 (warn "GType ~A is not known to GObject" name))
28 (defun gtype-from-name (name)
29 (declare (optimize (safety 0) (speed 3)))
30 (when (null name) (return-from gtype-from-name nil))
31 (bt:with-lock-held (*gtype-lock*)
32 (let ((type (gethash name *name-to-gtype*)))
33 (when type
34 (when (null (gtype-%id type))
35 (let ((n (%g-type-from-name name)))
36 (if (zerop n)
37 (warn-unknown-gtype name)
38 (progn
39 (setf (gtype-%id type) n
40 (gethash n *id-to-gtype*) type)))))
41 (return-from gtype-from-name type)))
42 (let ((n (%g-type-from-name name)))
43 (when (zerop n)
44 (warn-unknown-gtype name)
45 (setf n nil))
46 (let ((type (make-gtype :name (copy-seq name) :%id n)))
47 (setf (gethash n *id-to-gtype*) type
48 (gethash name *name-to-gtype*) type)
49 (return-from gtype-from-name type)))))
51 (defun gtype-from-id (id)
52 (declare (optimize (safety 0) (speed 3)))
53 (when (zerop id) (return-from gtype-from-id nil))
54 (bt:with-lock-held (*gtype-lock*)
55 (let ((type (gethash id *id-to-gtype*)))
56 (when type
57 (return-from gtype-from-id type)))
58 (let ((name (%g-type-name id)))
59 (unless name
60 (warn-unknown-gtype id))
61 (let ((type (gethash name *name-to-gtype*)))
62 (when type
63 (setf (gtype-%id type) id
64 (gethash id *id-to-gtype*) type)
65 (return-from gtype-from-id type))
66 (let ((type (make-gtype :name name :%id id)))
67 (setf (gethash id *id-to-gtype*) type
68 (gethash name *name-to-gtype*) type)
69 (return-from gtype-from-id type))))))
71 (defun gtype-id (gtype)
72 (when (null gtype) (return-from gtype-id 0))
73 (when (gtype-%id gtype) (return-from gtype-id (gtype-%id gtype)))
74 (bt:with-lock-held (*gtype-lock*)
75 (let ((n (%g-type-from-name (gtype-name gtype))))
76 (when (zerop n)
77 (warn-unknown-gtype (gtype-name gtype))
78 (return-from gtype-id 0))
79 (setf (gtype-%id gtype) n
80 (gethash n *id-to-gtype*) gtype)
81 n)))
83 (defun %gtype (thing)
84 (etypecase thing
85 (null nil)
86 (gtype thing)
87 (string (gtype-from-name thing))
88 (integer (gtype-from-id thing))))
90 (defun gtype (thing)
91 (%gtype thing))
93 (define-compiler-macro gtype (&whole whole thing)
94 (if (constantp thing)
95 `(load-time-value (%gtype ,thing))
96 whole))
98 (define-foreign-type g-type-designator ()
99 ((mangled-p :initarg :mangled-p
100 :reader g-type-designator-mangled-p
101 :initform nil
102 :documentation "Whether the type designator is mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag"))
103 (:documentation "Values of this CFFI foreign type identify the GType. GType is designated by a its name (a string) or a numeric identifier. Functions accept GType designators as a string or integer and return them as a string. Functions @fun{g-type-name} and @fun{g-type-from-name} are used to convert between name and numeric identifier.
105 Numeric identifier of GType may be different between different program runs. But string identifier of GType does not change.")
106 (:actual-type g-type)
107 (:simple-parser g-type-designator))
109 (defun unmangle-g-type (g-type)
110 (logxor g-type (ldb (byte 1 0) g-type)));;subtract the G_SIGNAL_TYPE_STATIC_SCOPE
112 (defmethod translate-from-foreign (value (type g-type-designator))
113 (gtype (if (g-type-designator-mangled-p type)
114 (unmangle-g-type value)
115 value)))
117 (defmethod translate-to-foreign (value (type g-type-designator))
118 (gtype-id (gtype value)))
120 (defun g-type= (type-1 type-2)
121 (eq (gtype type-1) (gtype type-2)))
123 (defun g-type/= (type-1 type-2)
124 (not (eq (gtype type-1) (gtype type-2))))