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