1 ;; Common Lisp bindings for GTK+ v2.0
2 ;; Copyright (C) 2000 Espen S. Johnsen <esj@stud.cs.uit.no>
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.
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.
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
18 ;; $Id: gtype.lisp,v 1.9 2001-04-30 11:25:25 espen Exp $
27 (deftype type-number () '(unsigned 32))
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)))
38 (defbinding ("g_type_name" alien-type-name) (type) (static string)
39 ((find-type-number type) type-number))
41 (defbinding %type-from-name () type-number
44 (defbinding type-parent () type-number
47 (defbinding %type-query () nil
51 (defun type-query (type)
52 (let ((query (make-instance 'type-query)))
53 (%type-query (find-type-number type) query)
56 (defun type-instance-size (type)
57 (slot-value (type-query type) 'instance-size))
59 (defun type-class-size (type)
60 (slot-value (type-query type) 'class-size))
62 (defbinding type-class-ref () pointer
65 (defbinding type-class-unref () nil
68 (defbinding type-class-peek () pointer
71 (defbinding type-create-instance (type) pointer
72 ((find-type-number type) type-number))
74 (defbinding type-free-instance () nil
78 (defvar *type-to-number-hash* (make-hash-table))
79 (defvar *number-to-type-hash* (make-hash-table))
81 (defun type-number-from-alien-name (name &optional (error t))
82 (if (string= name "invalid")
84 (let ((type-number (%type-from-name name)))
86 ((and (zerop type-number) error)
87 (error "Invalid alien type name: ~A" name))
88 ((zerop type-number) nil)
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)))
97 (defun (setf find-type-number) (type-number type)
98 (setf (gethash (ensure-type-name type) *type-to-number-hash*) type-number))
100 (defun find-type-number (type)
103 (symbol (gethash type *type-to-number-hash*))
104 (pcl::class (gethash (class-name type) *type-to-number-hash*))))
106 (defun type-from-number (type-number)
107 (gethash type-number *number-to-type-hash*))
109 (defun type-number-of (object)
110 (find-type-number (type-of object)))
112 (defun type-init (name &optional init-fname)
115 (or init-fname (default-alien-fname (format nil "~A_get_type" name)))
119 ;;;; Superclass for wrapping types in the glib type system
121 (eval-when (:compile-toplevel :load-toplevel :execute)
122 (defclass ginstance (proxy)
124 (:metaclass proxy-class)
125 (:size 4 #|(size-of 'pointer|#)))
127 (defmethod initialize-proxy ((instance ginstance) &rest initargs &key location)
128 (declare (ignore initargs))
130 (slot-value instance 'location)
131 (funcall (ginstance-class-ref (class-of instance)) location))
134 (defmethod instance-finalizer ((instance ginstance))
135 (let ((location (proxy-location instance))
136 (unref (ginstance-class-unref (class-of instance))))
137 (declare (type system-area-pointer location))
139 (funcall unref location)
140 (remove-cached-instance location))))
142 (defun %type-of-ginstance (location)
143 (let ((class (sap-ref-sap location 0)))
144 (type-from-number (sap-ref-unsigned class 0))))
146 (deftype-method translate-from-alien
147 ginstance (type-spec location &optional weak-ref)
148 (declare (ignore type-spec))
149 `(let ((location ,location))
150 (unless (null-pointer-p location)
151 (ensure-proxy-instance
152 (%type-of-ginstance location) location ,weak-ref))))
154 (deftype-method translate-to-alien
155 ginstance (type-spec object &optional weak-ref)
156 (declare (ignore type-spec))
158 `(proxy-location ,object)
159 `(let ((object ,object))
161 (ginstance-class-ref (class-of object)) (proxy-location object)))))
163 (deftype-method unreference-alien ginstance (type-spec location)
164 (declare (ignore type-spec))
165 `(let* ((location ,location)
166 (class (find-class (%type-of-ginstance location))))
167 (funcall (ginstance-class-unref class) location)))
171 ;;;; Metaclass for subclasses of ginstance
173 (eval-when (:compile-toplevel :load-toplevel :execute)
174 (defclass ginstance-class (proxy-class)
175 ((ref :reader ginstance-class-ref)
176 (unref :reader ginstance-class-unref))))
179 (defmethod shared-initialize ((class ginstance-class) names
181 &key name alien-name size
183 (declare (ignore initargs names))
186 (let* ((class-name (or name (class-name class)))
189 ((and alien-name type-init)
191 "Specify either :type-init or :alien-name for class ~A"
193 (alien-name (type-number-from-alien-name (first alien-name)))
194 (type-init (type-init class-name (first type-init)))
197 (type-number-from-alien-name
198 (default-alien-type-name class-name) nil)
199 (type-init class-name))))))
200 (setf (find-type-number class) type-number)
203 (slot-value class 'size)
204 (type-instance-size (find-type-number class-name))))
207 (slot-value class 'ref)
208 (mkbinding (first ref) 'pointer 'pointer)))
211 (slot-value class 'unref)
212 (mkbinding (first unref) 'nil 'pointer)))))
214 (defmethod shared-initialize :after ((class ginstance-class) names
216 (declare (ignore names initargs))
217 (unless (slot-boundp class 'ref)
219 (slot-value class 'ref)
220 (ginstance-class-ref (most-specific-proxy-superclass class))))
221 (unless (slot-boundp class 'unref)
223 (slot-value class 'unref)
224 (ginstance-class-unref (most-specific-proxy-superclass class)))))
227 (defmethod validate-superclass
228 ((class ginstance-class) (super pcl::standard-class))
229 (subtypep (class-name super) 'ginstance))
232 ;;;; Initializing type numbers
234 (setf (alien-type-name 'invalid) "invalid")
235 (setf (alien-type-name 'char) "gchar")
236 (setf (alien-type-name 'unsigned-char) "guchar")
237 (setf (alien-type-name 'boolean) "gboolean")
238 (setf (alien-type-name 'int) "gint")
239 (setf (alien-type-name 'unsigned-int) "guint")
240 (setf (alien-type-name 'long) "glong")
241 (setf (alien-type-name 'unsigned-long) "gulong")
242 (setf (alien-type-name 'single-float) "gfloat")
243 (setf (alien-type-name 'double-float) "gdouble")
244 (setf (alien-type-name 'string) "GString")
245 (setf (find-type-number 'fixnum) (find-type-number 'int))