Changes required by SBCL
[clg] / glib / utils.lisp
CommitLineData
40acf00a 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
3d36c5d6 18;; $Id: utils.lisp,v 1.3 2005/02/03 23:09:05 espen Exp $
40acf00a 19
20
21(in-package "GLIB")
22
23(defun type-expand-1 (form)
24 (let ((def (cond ((symbolp form)
3d36c5d6 25 #+cmu(kernel::info type expander form)
26 #+sbcl(sb-impl::info :type :expander form))
40acf00a 27 ((and (consp form) (symbolp (car form)))
3d36c5d6 28 #+cmu(kernel::info type expander (car form))
29 #+sbcl(sb-impl::info :type :expander (car form)))
40acf00a 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)
48 (let ((gc-inhibit (make-symbol "GC-INHIBIT")))
49 `(progn
3d36c5d6 50 (let ((,gc-inhibit #+cmu lisp::*gc-inhibit*
51 #+sbcl sb-impl::*gc-inhibit*))
52 (gc-off)
40acf00a 53 (unwind-protect
54 ,@body
55 (unless ,gc-inhibit
3d36c5d6 56 (gc-on)))))))
40acf00a 57
58(defun mklist (obj)
0e4d64cd 59 (if (and obj (atom obj)) (list obj) obj))
40acf00a 60
61(defun namep (obj)
62 (and (symbolp obj) (not (member obj '(t nil)))))
63
64(defun all-equal (&rest objects)
65 (or
66 (null objects)
67 (null (rest objects))
68 (and
69 (equal (first objects) (second objects))
70 (apply #'all-equal (rest objects)))))
71
72(defun neq (obj1 obj2)
73 (not (eq obj1 obj2)))
74
75(defmacro return-if (form)
76 (let ((result (make-symbol "RESULT")))
77 `(let ((,result ,form))
78 (when ,result
79 (return ,result)))))
80
81(defun make-pointer (address)
82 (int-sap address))
83
84(defun null-pointer-p (pointer)
85 (zerop (sap-int pointer)))
86
87
88(defmacro when-bind ((var expr) &body body)
89 `(let ((,var ,expr))
90 (when ,var
91 ,@body)))
92
93
94(defmacro assoc-ref (key alist &key (test #'eq))
95 `(cdr (assoc ,key ,alist :test ,test)))
96
97
98(defmacro assoc-lref (key alist &key (test #'eq))
99 `(cadr (assoc ,key ,alist :test ,test)))
100
101
102(defun assoc-rem (key alist &key (test #'eq))
103 (remove-if #'(lambda (element) (funcall test key (car element))) alist))
104
105
106(defun assoc-delete (key alist &key (test #'eq))
107 (delete-if #'(lambda (element) (funcall test key (car element))) alist))
108
109
110(defun funcallable (object)
111 (if (consp object)
112 (fdefinition object)
113 object))
114
115(defun intersection-p (list1 list2 &key (test #'eq))
116 (dolist (obj list1 nil)
117 (when (member obj list2 :test test)
118 (return-from intersection-p t))))
119
120
121(defun split-string (string delimiter)
122 (declare (simple-string string) (character delimiter))
40acf00a 123 (let ((pos (position delimiter string)))
124 (if (not pos)
125 (list string)
126 (cons
127 (subseq string 0 pos)
128 (split-string (subseq string (1+ pos)) delimiter)))))
129
130(defun split-string-if (string predicate)
131 (declare (simple-string string))
40acf00a 132 (let ((pos (position-if predicate string :start 1)))
133 (if (not pos)
134 (list string)
135 (cons
136 (subseq string 0 pos)
137 (split-string-if (subseq string pos) predicate)))))
138
139(defun concatenate-strings (strings &optional delimiter)
140 (if (not (rest strings))
141 (first strings)
142 (concatenate
143 'string
144 (first strings)
145 (if delimiter (string delimiter) "")
146 (concatenate-strings (rest strings) delimiter))))
147
148(defun string-prefix-p (prefix string)
149 (and
150 (>= (length string) (length prefix))
151 (string= prefix string :end2 (length prefix))))
152
153(defun get-all (plist property)
154 (multiple-value-bind (property value tail)
155 (get-properties plist (list property))
156 (when tail
157 (cons value (get-all (cddr tail) property)))))
158
159(defun plist-remove (plist property)
160 (when plist
161 (if (eq (first plist) property)
162 (plist-remove (cddr plist) property)
163 (list*
164 (first plist) (second plist) (plist-remove (cddr plist) property)))))
165
166
167;;;
168
169(defun utf-8-encode (code)
170 (labels ((encode-bytes (bit)
171 (unless (zerop bit)
172 (cons
173 (deposit-field
174 #x80 (byte 7 6) (ldb (byte bit (- bit 6)) code))
175 (encode-bytes (- bit 6)))))
176 (encode-string (length)
177 (map 'string #'code-char
178 (cons
179 (deposit-field
180 (mask-field (byte 7 (- 7 length)) #xFF)
181 (byte 7 (- 6 length))
182 (ldb (byte (+ (* length 6) 6) (* length 6)) code))
183 (encode-bytes (* length 6))))))
184 (cond
185 ((< code #x80) (string (code-char code)))
186 ((< code #x800) (encode-string 1))
187 ((< code #x10000) (encode-string 2))
188 ((< code #x200000) (encode-string 3))
189 ((< code #x4000000) (encode-string 4))
190 ((< code #x80000000) (encode-string 5))
191 (t (error "Invalid char code ~A" code)))))
192
193
194(defun latin1-to-unicode (string)
195 (reduce
196 #'(lambda (str1 str2)
197 (concatenate 'string str1 str2))
198 (map 'list #'(lambda (char) (utf-8-encode (char-code char))) string)))