1 ;; Common Lisp bindings for GTK+ v2.0
2 ;; Copyright (C) 2000-2001 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: genums.lisp,v 1.6 2005/02/01 15:24:52 espen Exp $
23 (defun %map-enum (args op)
24 (let ((current-value 0))
27 (destructuring-bind (symbol &optional (value current-value))
29 (setf current-value (1+ value))
31 (:enum-int (list symbol value))
32 (:flags-int (list symbol value))
33 (:int-enum (list value symbol))
34 (:int-flags (list value symbol))
38 (defun %query-enum-or-flags-values (query-function class type)
39 (multiple-value-bind (sap length)
40 (funcall query-function (type-class-ref type))
42 (size (proxy-instance-size (find-class class)))
43 (proxy (make-instance class :location sap)))
45 (with-slots (location nickname value) proxy
47 (setq sap (sap+ sap size))
50 (intern (substitute #\- #\_ (string-upcase nickname)) "KEYWORD")
56 ;;;; Generic enum type
58 (deftype enum (&rest args)
59 `(member ,@(%map-enum args :symbols)))
61 (defmethod alien-type ((type (eql 'enum)) &rest args)
62 (declare (ignore type args))
65 (defmethod size-of ((type (eql 'enum)) &rest args)
66 (declare (ignore type args))
69 (defmethod to-alien-form (form (type (eql 'enum)) &rest args)
70 (declare (ignore type))
72 ,@(%map-enum args :enum-int)))
74 (defmethod from-alien-form (form (type (eql 'enum)) &rest args)
75 (declare (ignore type))
77 ,@(%map-enum args :int-enum)))
79 (defmethod to-alien-function ((type (eql 'enum)) &rest args)
80 (let ((mappings (%map-enum args :enum-int)))
83 (second (assoc enum mappings))
84 (error "~S is not of type ~S" enum (cons type args))))))
86 (defmethod from-alien-function ((type (eql 'enum)) &rest args)
87 (declare (ignore type))
88 (let ((mappings (%map-enum args :int-enum)))
90 (second (assoc int mappings)))))
92 (defmethod writer-function ((type (eql 'enum)) &rest args)
93 (declare (ignore type))
94 (let ((writer (writer-function 'signed))
95 (function (apply #'to-alien-function 'enum args)))
96 #'(lambda (enum location &optional (offset 0))
97 (funcall writer (funcall function enum) location offset))))
99 (defmethod reader-function ((type (eql 'enum)) &rest args)
100 (declare (ignore type))
101 (let ((reader (reader-function 'signed))
102 (function (apply #'from-alien-function 'enum args)))
103 #'(lambda (location &optional (offset 0))
104 (funcall function (funcall reader location offset)))))
108 (defclass %enum-value (struct)
109 ((value :allocation :alien :type int)
110 (name :allocation :alien :type string)
111 (nickname :allocation :alien :type string))
112 (:metaclass static-struct-class))
114 (defbinding %enum-class-values () pointer
116 (n-values unsigned-int :out))
118 (defun query-enum-values (type)
119 (%query-enum-or-flags-values #'%enum-class-values '%enum-value type))
121 (defun enum-int (enum type)
122 (funcall (to-alien-function type) enum))
124 (defun int-enum (int type)
125 (funcall (from-alien-function type) int))
127 (defun enum-mapping (type)
128 (rest (type-expand-to 'enum type)))
130 ;;;; Generic flags type
132 (deftype flags (&rest args)
133 `(or null (cons (member ,@(%map-enum args :symbols)) list)))
135 (defmethod alien-type ((type (eql 'flags)) &rest args)
136 (declare (ignore type args))
137 (alien-type 'unsigned))
139 (defmethod size-of ((type (eql 'flags)) &rest args)
140 (declare (ignore type args))
143 (defmethod to-alien-form (flags (type (eql 'flags)) &rest args)
147 for flag in (mklist flags)
150 (second (assoc flag ',(%map-enum args :flags-int)))
151 (error "~S is not of type ~S" flags '(,type ,@args)))))
152 (setq value (logior value flagval)))
153 finally (return value)))
155 (defmethod from-alien-form (int (type (eql 'flags)) &rest args)
156 (declare (ignore type))
158 for mapping in ',(%map-enum args :int-flags)
159 unless (zerop (logand int (first mapping)))
160 collect (second mapping)))
162 (defmethod to-alien-function ((type (eql 'flags)) &rest args)
163 (let ((mappings (%map-enum args :flags-int)))
167 for flag in (mklist flags)
168 do (let ((flagval (or
169 (second (assoc flag mappings))
170 (error "~S is not of type ~S" flags (cons type args)))))
171 (setq value (logior value flagval)))
172 finally (return value)))))
174 (defmethod from-alien-function ((type (eql 'flags)) &rest args)
175 (declare (ignore type))
176 (let ((mappings (%map-enum args :int-flags)))
179 for mapping in mappings
180 unless (zerop (logand int (first mapping)))
181 collect (second mapping)))))
183 (defmethod writer-function ((type (eql 'flags)) &rest args)
184 (declare (ignore type))
185 (let ((writer (writer-function 'unsigned))
186 (function (apply #'to-alien-function 'flags args)))
187 #'(lambda (flags location &optional (offset 0))
188 (funcall writer (funcall function flags) location offset))))
190 (defmethod reader-function ((type (eql 'flags)) &rest args)
191 (declare (ignore type))
192 (let ((reader (reader-function 'unsigned))
193 (function (apply #'from-alien-function 'flags args)))
194 #'(lambda (location &optional (offset 0))
195 (funcall function (funcall reader location offset)))))
199 (defclass %flags-value (struct)
200 ((value :allocation :alien :type unsigned-int)
201 (name :allocation :alien :type string)
202 (nickname :allocation :alien :type string))
203 (:metaclass static-struct-class))
205 (defbinding %flags-class-values () pointer
207 (n-values unsigned-int :out))
209 (defun query-flags-values (type)
210 (%query-enum-or-flags-values #'%flags-class-values '%flags-value type))
216 (defun expand-enum-type (type-number forward-p options)
217 (declare (ignore forward))
218 (let* ((super (supertype type-number))
219 (type (type-from-number type-number))
220 (mappings (getf options :mappings))
226 (assoc (first mapping) mappings)
227 (rassoc (cdr mapping) mappings :test #'equal)))
229 (query-enum-values type-number)
230 (query-flags-values type-number)))
232 #'(lambda (mapping) (eq (second mapping) nil)) mappings))))
234 (register-type ',type ,(find-type-name type-number))
235 (deftype ,type () '(,super ,@expanded-mappings)))))
238 (register-derivable-type 'enum "GEnum" 'expand-enum-type)
239 (register-derivable-type 'flags "GFlags" 'expand-enum-type)