chiark / gitweb /
Added dependency to the gtk system and a couple of bug fixes
[clg] / glib / utils.lisp
CommitLineData
ee4d9781 1;; Common Lisp bindings for GTK+ v2.0
2;; Copyright (C) 1999-2000 Espen S. Johnsen <espejohn@online.no>
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
6887e01d 18;; $Id: utils.lisp,v 1.4 2005-04-17 21:38:15 espen Exp $
ee4d9781 19
20
21(in-package "GLIB")
22
23(defun type-expand-1 (form)
24 (let ((def (cond ((symbolp form)
73572c12 25 #+cmu(kernel::info type expander form)
26 #+sbcl(sb-impl::info :type :expander form))
ee4d9781 27 ((and (consp form) (symbolp (car form)))
73572c12 28 #+cmu(kernel::info type expander (car form))
29 #+sbcl(sb-impl::info :type :expander (car form)))
ee4d9781 30 (t nil))))
31 (if def
32 (values (funcall def (if (consp form) form (list form))) t)
33 (values form nil))))
34
35
36(defun type-expand-to (type form)
37 (labels ((expand (form0)
38 (if (eq (first (mklist form0)) type)
39 form0
40 (multiple-value-bind (expanded-form expanded-p)
41 (type-expand-1 form0)
42 (if expanded-p
43 (expand expanded-form)
44 (error "~A can not be expanded to ~A" form type))))))
45 (expand form)))
46
47(defmacro with-gc-disabled (&body body)
6887e01d 48 #+cmu`(system:without-gcing ,@body)
49 #+sbcl`(sb-impl::without-gcing ,@body))
ee4d9781 50
51(defun mklist (obj)
a375e049 52 (if (and obj (atom obj)) (list obj) obj))
ee4d9781 53
54(defun namep (obj)
55 (and (symbolp obj) (not (member obj '(t nil)))))
56
57(defun all-equal (&rest objects)
58 (or
59 (null objects)
60 (null (rest objects))
61 (and
62 (equal (first objects) (second objects))
63 (apply #'all-equal (rest objects)))))
64
65(defun neq (obj1 obj2)
66 (not (eq obj1 obj2)))
67
68(defmacro return-if (form)
69 (let ((result (make-symbol "RESULT")))
70 `(let ((,result ,form))
71 (when ,result
72 (return ,result)))))
73
74(defun make-pointer (address)
75 (int-sap address))
76
77(defun null-pointer-p (pointer)
78 (zerop (sap-int pointer)))
79
80
81(defmacro when-bind ((var expr) &body body)
82 `(let ((,var ,expr))
83 (when ,var
84 ,@body)))
85
86
87(defmacro assoc-ref (key alist &key (test #'eq))
88 `(cdr (assoc ,key ,alist :test ,test)))
89
90
91(defmacro assoc-lref (key alist &key (test #'eq))
92 `(cadr (assoc ,key ,alist :test ,test)))
93
94
95(defun assoc-rem (key alist &key (test #'eq))
96 (remove-if #'(lambda (element) (funcall test key (car element))) alist))
97
98
99(defun assoc-delete (key alist &key (test #'eq))
100 (delete-if #'(lambda (element) (funcall test key (car element))) alist))
101
102
103(defun funcallable (object)
104 (if (consp object)
105 (fdefinition object)
106 object))
107
108(defun intersection-p (list1 list2 &key (test #'eq))
109 (dolist (obj list1 nil)
110 (when (member obj list2 :test test)
111 (return-from intersection-p t))))
112
113
114(defun split-string (string delimiter)
115 (declare (simple-string string) (character delimiter))
ee4d9781 116 (let ((pos (position delimiter string)))
117 (if (not pos)
118 (list string)
119 (cons
120 (subseq string 0 pos)
121 (split-string (subseq string (1+ pos)) delimiter)))))
122
123(defun split-string-if (string predicate)
124 (declare (simple-string string))
ee4d9781 125 (let ((pos (position-if predicate string :start 1)))
126 (if (not pos)
127 (list string)
128 (cons
129 (subseq string 0 pos)
130 (split-string-if (subseq string pos) predicate)))))
131
132(defun concatenate-strings (strings &optional delimiter)
133 (if (not (rest strings))
134 (first strings)
135 (concatenate
136 'string
137 (first strings)
138 (if delimiter (string delimiter) "")
139 (concatenate-strings (rest strings) delimiter))))
140
141(defun string-prefix-p (prefix string)
142 (and
143 (>= (length string) (length prefix))
144 (string= prefix string :end2 (length prefix))))
145
146(defun get-all (plist property)
147 (multiple-value-bind (property value tail)
148 (get-properties plist (list property))
149 (when tail
150 (cons value (get-all (cddr tail) property)))))
151
152(defun plist-remove (plist property)
153 (when plist
154 (if (eq (first plist) property)
155 (plist-remove (cddr plist) property)
156 (list*
157 (first plist) (second plist) (plist-remove (cddr plist) property)))))
158
159
160;;;
161
162(defun utf-8-encode (code)
163 (labels ((encode-bytes (bit)
164 (unless (zerop bit)
165 (cons
166 (deposit-field
167 #x80 (byte 7 6) (ldb (byte bit (- bit 6)) code))
168 (encode-bytes (- bit 6)))))
169 (encode-string (length)
170 (map 'string #'code-char
171 (cons
172 (deposit-field
173 (mask-field (byte 7 (- 7 length)) #xFF)
174 (byte 7 (- 6 length))
175 (ldb (byte (+ (* length 6) 6) (* length 6)) code))
176 (encode-bytes (* length 6))))))
177 (cond
178 ((< code #x80) (string (code-char code)))
179 ((< code #x800) (encode-string 1))
180 ((< code #x10000) (encode-string 2))
181 ((< code #x200000) (encode-string 3))
182 ((< code #x4000000) (encode-string 4))
183 ((< code #x80000000) (encode-string 5))
184 (t (error "Invalid char code ~A" code)))))
185
186
187(defun latin1-to-unicode (string)
188 (reduce
189 #'(lambda (str1 str2)
190 (concatenate 'string str1 str2))
191 (map 'list #'(lambda (char) (utf-8-encode (char-code char))) string)))