chiark / gitweb /
fa11693a7b22fb0235970e066914d1de7b1e5f7c
[clg] / glib / utils.lisp
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)))