X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=glib%2Fgobject.type-designator.lisp;h=d31af2e57f42e32398c92067fa46cad1cbcce4dc;hb=db7c4d0c9eb2f2bead482bd0341a456a68a655a1;hp=546840301c582807e0c5662cbf630d4c9ba93a3e;hpb=fde1325ff108eeda03657ee20dda852d12712a00;p=cl-gtk2.git diff --git a/glib/gobject.type-designator.lisp b/glib/gobject.type-designator.lisp index 5468403..d31af2e 100644 --- a/glib/gobject.type-designator.lisp +++ b/glib/gobject.type-designator.lisp @@ -2,6 +2,86 @@ (defctype g-type gsize) +(defstruct gtype name %id) + +(defvar *name-to-gtype* (make-hash-table :test 'equal)) +(defvar *id-to-gtype* (make-hash-table)) +(defvar *gtype-lock* (bt:make-lock "gtype lock")) + +(defun invalidate-gtypes () + (bt:with-lock-held (*gtype-lock*) + (clrhash *id-to-gtype*) + (iter (for (name gtype) in-hashtable *name-to-gtype*) + (setf (gtype-%id gtype) nil)))) + +(at-finalize () (invalidate-gtypes)) + +(defcfun (%g-type-from-name "g_type_from_name") g-type + (name :string)) + +(defcfun (%g-type-name "g_type_name") (:string :free-from-foreign nil) + (type g-type)) + +(defun gtype-from-name (name) + (when (null name) (return-from gtype-from-name nil)) + (bt:with-lock-held (*gtype-lock*) + (let ((type (gethash name *name-to-gtype*))) + (when type + (when (null (gtype-%id type)) + (let ((n (%g-type-from-name name))) + (if (zerop n) + (warn "GType ~A is not known to GObject" name) + (progn + (setf (gtype-%id type) n + (gethash n *id-to-gtype*) type))))) + (return-from gtype-from-name type))) + (let ((n (%g-type-from-name name))) + (when (zerop n) + (warn "GType ~A is not known to GObject" name) + (setf n nil)) + (let ((type (make-gtype :name (copy-seq name) :%id n))) + (setf (gethash n *id-to-gtype*) type + (gethash name *name-to-gtype*) type) + (return-from gtype-from-name type))))) + +(defun gtype-from-id (id) + (when (zerop id) (return-from gtype-from-id nil)) + (bt:with-lock-held (*gtype-lock*) + (let ((type (gethash id *id-to-gtype*))) + (when type + (return-from gtype-from-id type))) + (let ((name (%g-type-name id))) + (unless name + (error "GType with ~A is not known to GObject" id)) + (let ((type (gethash name *name-to-gtype*))) + (when type + (setf (gtype-%id type) id + (gethash id *id-to-gtype*) type) + (return-from gtype-from-id type)) + (let ((type (make-gtype :name name :%id id))) + (setf (gethash id *id-to-gtype*) type + (gethash name *name-to-gtype*) type) + (return-from gtype-from-id type)))))) + +(defun gtype-id (gtype) + (when (null gtype) (return-from gtype-id 0)) + (when (gtype-%id gtype) (return-from gtype-id (gtype-%id gtype))) + (bt:with-lock-held (*gtype-lock*) + (let ((n (%g-type-from-name (gtype-name gtype)))) + (when (zerop n) + (warn "GType ~A is not known to GObject" (gtype-name gtype)) + (return-from gtype-id 0)) + (setf (gtype-%id gtype) n + (gethash n *id-to-gtype*) gtype) + n))) + +(defun gtype (thing) + (etypecase thing + (null nil) + (gtype thing) + (string (gtype-from-name thing)) + (integer (gtype-from-id thing)))) + (define-foreign-type g-type-designator () ((mangled-p :initarg :mangled-p :reader g-type-designator-mangled-p