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