Moved GValue parsing code to gobject.gvalue.lisp
[cl-gtk2.git] / glib / gobject.gvalue.lisp
1 (in-package :gobject)
2
3 (defun g-value-zero (g-value)
4   "Initializes the GValue in \"unset\" state.
5
6 @arg[g-value]{a C pointer to the GValue structure}"
7   (loop
8      for i from 0 below (foreign-type-size 'g-value)
9      do (setf (mem-ref g-value :uchar i) 0)))
10
11 (defun gvalue-type (gvalue)
12   (foreign-slot-value gvalue 'g-value :type))
13
14 (defmacro ev-case (keyform &body clauses)
15   "Macro that is an analogue of CASE except that it evaluates keyforms"
16   (let ((value (gensym)))
17     `(let ((,value ,keyform))
18        (cond
19          ,@(loop
20               for (key . forms) in clauses
21               collect
22                 (if (eq key t)
23                     `(t ,@forms)
24                     `((equalp ,key ,value) ,@forms)))))))
25
26 (defun parse-gvalue (gvalue)
27   "Parses the GValue structure and returns the corresponding Lisp object.
28
29 @arg[value]{a C pointer to the GValue structure}
30 @return{value contained in the GValue structure. Type of value depends on GValue type}"
31   (let* ((type (ensure-g-type (gvalue-type gvalue)))
32          (fundamental-type (ensure-g-type (g-type-fundamental type))))
33     (cond
34       ((= type (ensure-g-type (g-strv-get-type))) (convert-from-foreign (g-value-get-boxed gvalue) '(glib:gstrv :free-from-foreign nil)))
35       (t (ev-case fundamental-type
36            (+g-type-invalid+ (error "GValue is of invalid type (~A)" (g-type-name type)))
37            (+g-type-void+ nil)
38            (+g-type-char+ (g-value-get-char gvalue))
39            (+g-type-uchar+ (g-value-get-uchar gvalue))
40            (+g-type-boolean+ (g-value-get-boolean gvalue))
41            (+g-type-int+ (g-value-get-int gvalue))
42            (+g-type-uint+ (g-value-get-uint gvalue))
43            (+g-type-long+ (g-value-get-long gvalue))
44            (+g-type-ulong+ (g-value-get-ulong gvalue))
45            (+g-type-int64+ (g-value-get-int64 gvalue))
46            (+g-type-uint64+ (g-value-get-uint64 gvalue))
47            (+g-type-enum+ (parse-gvalue-enum gvalue))
48            (+g-type-flags+ (parse-gvalue-flags gvalue))
49            (+g-type-float+ (g-value-get-float gvalue))
50            (+g-type-double+ (g-value-get-double gvalue))
51            (+g-type-string+ (g-value-get-string gvalue))
52            (+g-type-pointer+ (g-value-get-pointer gvalue))
53            (+g-type-boxed+ (parse-gvalue-boxed gvalue))
54            (+g-type-param+ (parse-g-param-spec (g-value-get-param gvalue)))
55            (+g-type-object+ (parse-gvalue-object gvalue))
56            (+g-type-interface+ (parse-gvalue-object gvalue))
57            (t (error "Unknown type: ~A (~A)" type (g-type-name type))))))))
58
59 (defun set-g-value (gvalue value type &key zero-g-value unset-g-value (g-value-init t))
60   "Assigns the GValue structure @code{gvalue} the value @code{value} of GType @code{type}.
61
62 @arg[gvalue]{a C pointer to the GValue structure}
63 @arg[value]{a Lisp object that is to be assigned}
64 @arg[type]{a GType that is to be assigned}
65 @arg[zero-g-value]{a boolean specifying whether GValue should be zero-initialized before assigning. See @fun{g-value-zero}}
66 @arg[unset-g-value]{a boolean specifying whether GValue should be \"unset\" before assigning. See @fun{g-value-unset}. The \"true\" value should not be passed to both @code{zero-g-value} and @code{unset-g-value} arguments}
67 @arg[g-value-init]{a boolean specifying where GValue should be initialized}"
68   (setf type (ensure-g-type type))
69   (cond
70     (zero-g-value (g-value-zero gvalue))
71     (unset-g-value (g-value-unset gvalue)))
72   (when g-value-init (g-value-init gvalue type))
73   (let ((fundamental-type (ensure-g-type (g-type-fundamental type))))
74     (cond
75       ((= type (ensure-g-type (g-strv-get-type))) (g-value-set-boxed gvalue (convert-to-foreign value 'glib:gstrv)))
76       (t (ev-case fundamental-type
77            (+g-type-invalid+ (error "Invalid type (~A)" type))
78            (+g-type-void+ nil)
79            (+g-type-char+ (g-value-set-char gvalue value))
80            (+g-type-uchar+ (g-value-set-uchar gvalue value))
81            (+g-type-boolean+ (g-value-set-boolean gvalue value))
82            (+g-type-int+ (g-value-set-int gvalue value))
83            (+g-type-uint+ (g-value-set-uint gvalue value))
84            (+g-type-long+ (g-value-set-long gvalue value))
85            (+g-type-ulong+ (g-value-set-ulong gvalue value))
86            (+g-type-int64+ (g-value-set-int64 gvalue value))
87            (+g-type-uint64+ (g-value-set-uint64 gvalue value))
88            (+g-type-enum+ (set-gvalue-enum gvalue value))
89            (+g-type-flags+ (set-gvalue-flags gvalue value))
90            (+g-type-float+ (unless (realp value) (error "~A is not a real number" value)) (g-value-set-float gvalue (coerce value 'single-float)))
91            (+g-type-double+ (unless (realp value) (error "~A is not a real number" value)) (g-value-set-double gvalue (coerce value 'double-float)))
92            (+g-type-string+ (g-value-set-string gvalue value))
93            (+g-type-pointer+ (g-value-set-pointer gvalue value))
94            (+g-type-boxed+ (set-gvalue-boxed gvalue value))
95                                         ;(+g-type-param+ (set-gvalue-param gvalue value))
96            (+g-type-object+ (set-gvalue-object gvalue value))
97            (+g-type-interface+ (set-gvalue-object gvalue value))
98            (t (error "Unknown type: ~A (~A)" type (g-type-name type))))))))
99
100 ;;Enums
101
102 (defvar *registered-enum-types* (make-hash-table :test 'equal))
103 (defun register-enum-type (name type)
104   (setf (gethash name *registered-enum-types*) type))
105 (defun registered-enum-type (name)
106   (gethash name *registered-enum-types*))
107
108 (defun parse-gvalue-enum (gvalue)
109   (let* ((g-type (gvalue-type gvalue))
110          (type-name (g-type-name g-type))
111          (enum-type (registered-enum-type type-name)))
112     (unless enum-type
113       (error "Enum ~A is not registered" type-name))
114     (convert-from-foreign (g-value-get-enum gvalue) enum-type)))
115
116 (defun set-gvalue-enum (gvalue value)
117   (let* ((g-type (gvalue-type gvalue))
118          (type-name (g-type-name g-type))
119          (enum-type (registered-enum-type type-name)))
120     (unless enum-type
121       (error "Enum ~A is not registered" type-name))
122     (g-value-set-enum gvalue (convert-to-foreign value enum-type))))
123
124
125 ;;Flags
126
127 (defvar *registered-flags-types* (make-hash-table :test 'equal))
128 (defun register-flags-type (name type)
129   (setf (gethash name *registered-flags-types*) type))
130 (defun registered-flags-type (name)
131   (gethash name *registered-flags-types*))
132
133 (defun parse-gvalue-flags (gvalue)
134   (let* ((g-type (gvalue-type gvalue))
135          (type-name (g-type-name g-type))
136          (flags-type (registered-flags-type type-name)))
137     (unless flags-type
138       (error "Flags ~A is not registered" type-name))
139     (convert-from-foreign (g-value-get-flags gvalue) flags-type)))
140
141 (defun set-gvalue-flags (gvalue value)
142   (let* ((g-type (gvalue-type gvalue))
143          (type-name (g-type-name g-type))
144          (flags-type (registered-flags-type type-name)))
145     (unless flags-type
146       (error "Flags ~A is not registered" type-name))
147     (g-value-set-flags gvalue (convert-to-foreign value flags-type))))
148
149 ;;Objects
150
151 (defun parse-gvalue-object (gvalue)
152   (get-g-object-for-pointer (g-value-get-object gvalue)))
153
154 (defun set-gvalue-object (gvalue value)
155   (g-value-set-object gvalue (if value (pointer value) (null-pointer))))