chiark / gitweb /
Updated for glib-1.3.4
[clg] / glib / gtype.lisp
CommitLineData
560af5c5 1;; Common Lisp bindings for GTK+ v2.0
c8c48a4c 2;; Copyright (C) 2000 Espen S. Johnsen <esj@stud.cs.uit.no>
560af5c5 3;;
4;; This library is free software; you can redistribute it and/or
5;; modify it under the terms of the GNU Lesser General Public
6;; License as published by the Free Software Foundation; either
7;; version 2 of the License, or (at your option) any later version.
8;;
9;; This library is distributed in the hope that it will be useful,
10;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12;; Lesser General Public License for more details.
13;;
14;; You should have received a copy of the GNU Lesser General Public
15;; License along with this library; if not, write to the Free Software
16;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
93aa67db 18;; $Id: gtype.lisp,v 1.8 2001-04-29 20:17:07 espen Exp $
560af5c5 19
20(in-package "GLIB")
21
22(use-prefix "g")
23
24
25;;;;
26
27(deftype type-number () '(unsigned 32))
28
93aa67db 29(eval-when (:compile-toplevel :load-toplevel :execute)
30 (defclass type-query (alien-structure)
31 ((type-number :allocation :alien :type type-number)
32 (name :allocation :alien :type string)
33 (class-size :allocation :alien :type unsigned-int)
34 (instance-size :allocation :alien :type unsigned-int))
35 (:metaclass proxy-class)))
36
37
38(defbinding ("g_type_name" alien-type-name) (type) (static string)
560af5c5 39 ((find-type-number type) type-number))
40
93aa67db 41(defbinding %type-from-name () type-number
560af5c5 42 (name string))
43
93aa67db 44(defbinding type-parent () type-number
45 (type type-number))
560af5c5 46
93aa67db 47(defbinding %type-query () nil
48 (type type-number)
49 (query type-query))
50
51(defun type-query (type)
52 (let ((query (make-instance 'type-query)))
53 (%type-query (find-type-number type) query)
54 query))
55
56(defun type-instance-size (type)
57 (slot-value (type-query type) 'instance-size))
58
59(defun type-class-size (type)
60 (slot-value (type-query type) 'class-size))
560af5c5 61
93aa67db 62(defbinding type-class-ref () pointer
63 (type type-number))
560af5c5 64
93aa67db 65(defbinding type-class-unref () nil
66 (type type-number))
67
68(defbinding type-class-peek () pointer
69 (type type-number))
70
71(defbinding type-create-instance (type) pointer
72 ((find-type-number type) type-number))
73
74(defbinding type-free-instance () nil
560af5c5 75 (instance pointer))
76
77
78(defvar *type-to-number-hash* (make-hash-table))
79(defvar *number-to-type-hash* (make-hash-table))
80
81(defun type-number-from-alien-name (name &optional (error t))
82 (if (string= name "invalid")
83 0
84 (let ((type-number (%type-from-name name)))
85 (cond
86 ((and (zerop type-number) error)
87 (error "Invalid alien type name: ~A" name))
88 ((zerop type-number) nil)
89 (t type-number)))))
90
91(defun (setf alien-type-name) (alien-name type)
92 (let ((type-name (ensure-type-name type))
93 (type-number (type-number-from-alien-name alien-name)))
94 (setf (gethash type-number *number-to-type-hash*) type-name)
95 (setf (gethash type-name *type-to-number-hash*) type-number)))
96
97(defun (setf find-type-number) (type-number type)
98 (setf (gethash (ensure-type-name type) *type-to-number-hash*) type-number))
99
100(defun find-type-number (type)
101 (etypecase type
102 (integer type)
103 (symbol (gethash type *type-to-number-hash*))
104 (pcl::class (gethash (class-name type) *type-to-number-hash*))))
105
106(defun type-from-number (type-number)
107 (gethash type-number *number-to-type-hash*))
108
109(defun type-number-of (object)
110 (find-type-number (type-of object)))
111
93aa67db 112(defun alien-function (name return-type &rest arg-types)
113 (let ((alien
114 (alien::%heap-alien
115 (alien::make-heap-alien-info
116 :type (alien::parse-alien-type
117 `(function ,@(cons return-type arg-types)))
118 :sap-form (system:foreign-symbol-address name)))))
119 #'(lambda (&rest args)
120 (apply #'alien:alien-funcall alien args))))
560af5c5 121
122
93aa67db 123(defun type-init (name &optional init-fname)
124 (funcall
125 (alien-function
126 (or
127 init-fname
128 (default-alien-fname (format nil "~A_get_type" name)))
129 '(unsigned 32))))
560af5c5 130
131
93aa67db 132;;;; Superclass for wrapping types in the glib type system
560af5c5 133
134(eval-when (:compile-toplevel :load-toplevel :execute)
93aa67db 135 (defclass ginstance (proxy)
560af5c5 136 ()
93aa67db 137 (:metaclass proxy-class)
138 (:size 4 #|(size-of 'pointer|#)))
560af5c5 139
93aa67db 140(defmethod initialize-proxy ((instance ginstance) &rest initargs &key location)
560af5c5 141 (declare (ignore initargs))
93aa67db 142 (setf
143 (slot-value instance 'location)
144 (funcall (ginstance-class-ref (class-of instance)) location))
145 (call-next-method))
560af5c5 146
93aa67db 147(defmethod instance-finalizer ((instance ginstance))
148 (let ((location (proxy-location instance))
149 (unref (ginstance-class-unref (class-of instance))))
150 (declare (type system-area-pointer location))
560af5c5 151 #'(lambda ()
93aa67db 152 (funcall unref location)
153 (remove-cached-instance location))))
560af5c5 154
93aa67db 155(defun %type-of-ginstance (location)
156 (let ((class (sap-ref-sap location 0)))
157 (type-from-number (sap-ref-unsigned class 0))))
560af5c5 158
159(deftype-method translate-from-alien
93aa67db 160 ginstance (type-spec location &optional weak-ref)
161 (declare (ignore type-spec))
560af5c5 162 `(let ((location ,location))
163 (unless (null-pointer-p location)
93aa67db 164 (ensure-proxy-instance
165 (%type-of-ginstance location) location ,weak-ref))))
560af5c5 166
93aa67db 167(deftype-method translate-to-alien
168 ginstance (type-spec object &optional weak-ref)
560af5c5 169 (declare (ignore type-spec))
93aa67db 170 (if weak-ref
171 `(proxy-location ,object)
172 `(let ((object ,object))
173 (funcall
174 (ginstance-class-ref (class-of object)) (proxy-location object)))))
560af5c5 175
93aa67db 176(deftype-method unreference-alien ginstance (type-spec location)
560af5c5 177 (declare (ignore type-spec))
93aa67db 178 `(let* ((location ,location)
179 (class (find-class (%type-of-ginstance location))))
180 (funcall (ginstance-class-unref class) location)))
560af5c5 181
560af5c5 182
183
93aa67db 184;;;; Metaclass for subclasses of ginstance
560af5c5 185
186(eval-when (:compile-toplevel :load-toplevel :execute)
93aa67db 187 (defclass ginstance-class (proxy-class)
188 ((ref :reader ginstance-class-ref)
189 (unref :reader ginstance-class-unref))))
560af5c5 190
191
c8c48a4c 192(defmethod shared-initialize ((class ginstance-class) names
93aa67db 193 &rest initargs
194 &key name alien-name size
195 ref unref type-init)
560af5c5 196 (declare (ignore initargs names))
197 (call-next-method)
93aa67db 198
199 (let* ((class-name (or name (class-name class)))
200 (type-number
201 (cond
202 ((and alien-name type-init)
203 (error
204 "Specify either :type-init or :alien-name for class ~A"
205 class-name))
206 (alien-name (type-number-from-alien-name (first alien-name)))
207 (type-init (type-init class-name (first type-init)))
208 (t
209 (or
210 (type-number-from-alien-name
211 (default-alien-type-name class-name) nil)
212 (type-init class-name))))))
213 (setf (find-type-number class) type-number)
214 (unless size
215 (setf
216 (slot-value class 'size)
217 (type-instance-size (find-type-number class-name))))
218 (when ref
219 (setf
220 (slot-value class 'ref)
221 (alien-function (first ref) 'system-area-pointer 'system-area-pointer)))
222 (when unref
223 (setf
224 (slot-value class 'unref)
225 (alien-function (first unref) 'void 'system-area-pointer)))))
226
227(defmethod shared-initialize :after ((class ginstance-class) names
228 &rest initargs)
229 (declare (ignore names initargs))
230 (unless (slot-boundp class 'ref)
231 (setf
232 (slot-value class 'ref)
233 (ginstance-class-ref (most-specific-proxy-superclass class))))
234 (unless (slot-boundp class 'unref)
235 (setf
236 (slot-value class 'unref)
237 (ginstance-class-unref (most-specific-proxy-superclass class)))))
560af5c5 238
239
240(defmethod validate-superclass
c8c48a4c 241 ((class ginstance-class) (super pcl::standard-class))
242 (subtypep (class-name super) 'ginstance))
560af5c5 243
244
560af5c5 245;;;; Initializing type numbers
246
247(setf (alien-type-name 'invalid) "invalid")
248(setf (alien-type-name 'char) "gchar")
249(setf (alien-type-name 'unsigned-char) "guchar")
250(setf (alien-type-name 'boolean) "gboolean")
251(setf (alien-type-name 'int) "gint")
252(setf (alien-type-name 'unsigned-int) "guint")
253(setf (alien-type-name 'long) "glong")
254(setf (alien-type-name 'unsigned-long) "gulong")
560af5c5 255(setf (alien-type-name 'single-float) "gfloat")
256(setf (alien-type-name 'double-float) "gdouble")
93aa67db 257(setf (alien-type-name 'string) "GString")
560af5c5 258(setf (find-type-number 'fixnum) (find-type-number 'int))