Add the following comment to add-on modules.
[riece] / lisp / riece-icon.el
1 ;;; riece-icon.el --- display icons in IRC buffers
2 ;; Copyright (C) 1998-2003 Daiki Ueno
3
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Created: 1998-09-28
6 ;; Keywords: IRC, riece
7
8 ;; This file is part of Riece.
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Commentary:
26
27 ;; NOTE: This is an add-on module for Riece.
28
29 ;;; Code:
30
31 (require 'riece-globals)
32 (require 'riece-signal)
33
34 (defvar riece-channel-list-icons
35   '((" " . "/* XPM */
36 static char * blank_xpm[] = {
37 \"12 12 1 1\",
38 \"      c None\",
39 \"            \",
40 \"            \",
41 \"            \",
42 \"            \",
43 \"            \",
44 \"            \",
45 \"            \",
46 \"            \",
47 \"            \",
48 \"            \",
49 \"            \",
50 \"            \"};")
51     ("!" . "/* XPM */
52 static char * balloon_xpm[] = {
53 \"12 12 3 1\",
54 \"       c None\",
55 \"+      c #FFDD99\",
56 \"@      c #000000\",
57 \"            \",
58 \"    ++++    \",
59 \"  ++++++++  \",
60 \" ++@@@@@@++ \",
61 \" ++++++++++ \",
62 \" ++@@@@@@++ \",
63 \" ++++++++++ \",
64 \" ++@@@@@@++ \",
65 \"  ++++++++  \",
66 \"   ++++++   \",
67 \"   +++      \",
68 \"   +        \"};")
69     ("+" . "/* XPM */
70 static char * check_xpm[] = {
71 \"12 12 3 1\",
72 \"      c None\",
73 \".     c #9696FF\",
74 \"+     c #5959FF\",
75 \"            \",
76 \"            \",
77 \" ..      .. \",
78 \".++.    .++.\",
79 \" .++.  .++. \",
80 \"  .++..++.  \",
81 \"   .++++.   \",
82 \"    .++.    \",
83 \"     ..     \",
84 \"            \",
85 \"            \",
86 \"            \"};")
87     ("*" . "/* XPM */
88 static char * active_xpm[] = {
89 \"12 12 3 1\",
90 \"      c None\",
91 \".     c #96FF96\",
92 \"+     c #59FF59\",
93 \"            \",
94 \"     ..     \",
95 \"     .+.    \",
96 \" .....++.   \",
97 \" .+++++++.  \",
98 \" .++++++++. \",
99 \" .+++++++.  \",
100 \" .....++.   \",
101 \"     .+.    \",
102 \"     ..     \",
103 \"            \",
104 \"            \"};")))
105
106 (defvar riece-user-list-icons
107   '((" " . "/* XPM */
108 static char * blank_xpm[] = {
109 \"12 12 1 1\",
110 \"      c None\",
111 \"            \",
112 \"            \",
113 \"            \",
114 \"            \",
115 \"            \",
116 \"            \",
117 \"            \",
118 \"            \",
119 \"            \",
120 \"            \",
121 \"            \",
122 \"            \"};")
123     ("@" . "/* XPM */
124 static char * spiral_xpm[] = {
125 \"12 12 3 1\",
126 \"      c None\",
127 \".     c #FF5959\",
128 \"+     c #FF9696\",
129 \"            \",
130 \"            \",
131 \"    +++++   \",
132 \"   ++...++  \",
133 \"  ++.+++.++ \",
134 \"  +.++.++.+ \",
135 \"  +.+.+.+.+ \",
136 \"  +.+.+++.+ \",
137 \"  +.++...++ \",
138 \"  ++.+++++.+\",
139 \"   ++.....+ \",
140 \"    ++++++  \"};")
141     ("+" . "/* XPM */
142 static char * cross_xpm[] = {
143 \"12 12 3 1\",
144 \"      c None\",
145 \".     c #7F7F7F\",
146 \"+     c #B2B2B2\",
147 \"     ++     \",
148 \"    +..+    \",
149 \"    +..+    \",
150 \"  +++..+++  \",
151 \" +........+ \",
152 \" +........+ \",
153 \"  +++..+++  \",
154 \"    +..+    \",
155 \"    +..+    \",
156 \"    +..+    \",
157 \"    +..+    \",
158 \"     ++     \"};")))
159
160 (defvar riece-pointer-icon
161   "/* XPM */
162 static char * a_xpm[] = {
163 \"14 14 5 1\",
164 \"      c None\",
165 \".     c #FF9646\",
166 \"+     c #FF5909\",
167 \"@     c #FF7020\",
168 \"*     c #FFA500\",
169 \"              \",
170 \"  @@@@@@@@@@@ \",
171 \" @*.++++++.**@\",
172 \" @*.++...++.*@\",
173 \" @*.++.*.++.*@\",
174 \" @*.++...+.**@\",
175 \" @*.+++.+.***@\",
176 \" @*.++.*.+.**@\",
177 \" @*.++.*.++.*@\",
178 \" @*.++.*.++.*@\",
179 \" @*.++.*.++.*@\",
180 \" @**..***..**@\",
181 \"  @@@@@@@@@@@ \",
182 \"              \"};")
183
184 (defvar riece-icon-enabled nil)
185
186 (defconst riece-icon-description
187   "Display icons in IRC buffers.")
188
189 (defun riece-icon-available-p ()
190   (if (featurep 'xemacs)
191       (featurep 'xpm)
192     (if (fboundp 'image-type-available-p)
193         (image-type-available-p 'xpm))))
194
195 (eval-and-compile
196   (if (featurep 'xemacs)
197       (defun riece-icon-make-image (data string)
198         (make-glyph (list (vector 'xpm :data data)
199                           (vector 'string :data string))))
200     (defun riece-icon-make-image (data string)
201       (create-image data 'xpm t :ascent 'center))))
202
203 (defun riece-icon-make-images (alist)
204   (let ((pointer (setq alist (copy-alist alist))))
205     (while pointer
206       (setcdr (car pointer)
207               (riece-icon-make-image (cdr (car pointer)) (car (car pointer))))
208       (setq pointer (cdr pointer)))
209     alist))
210
211 (eval-and-compile
212   (if (featurep 'xemacs)
213       (defun riece-icon-add-image-region (image start end)
214         (map-extents
215          (lambda (extent ignore)
216            (if (or (extent-property extent 'riece-icon-user-list-extent)
217                    (extent-property extent 'riece-icon-user-list-annotation))
218                (delete-extent extent)))
219          (current-buffer) start end)
220         (let ((extent (make-extent start end))
221               (annotation (make-annotation image end 'text)))
222           (set-extent-property extent 'end-open t)
223           (set-extent-property extent 'start-open t)
224           (set-extent-property extent 'invisible t)
225           (set-extent-property extent 'intangible t)
226           (set-extent-property annotation
227                                'riece-icon-user-list-extent extent)
228           (set-extent-property extent
229                                'riece-icon-user-list-annotation annotation)))
230     (defun riece-icon-add-image-region (image start end)
231       (let ((inhibit-read-only t)
232             buffer-read-only)
233         (add-text-properties start end
234                              (list 'display
235                                    image
236                                    'rear-nonsticky (list 'display)))))))
237
238 (defun riece-icon-update-user-list-buffer ()
239   (if riece-icon-enabled
240       (let ((images (riece-icon-make-images riece-user-list-icons)))
241         (save-excursion
242           (goto-char (point-min))
243           (while (re-search-forward "^[ @+]" nil t)
244             (riece-icon-add-image-region
245              (cdr (assoc (match-string 0) images))
246              (1- (point)) (point)))))))
247
248 (defun riece-icon-update-channel-list-buffer ()
249   (if riece-icon-enabled
250       (let ((images (riece-icon-make-images riece-channel-list-icons)))
251         (save-excursion
252           (goto-char (point-min))
253           (while (re-search-forward "^ ?[0-9]+:\\([ !+*]\\)" nil t)
254             (riece-icon-add-image-region
255              (cdr (assoc (match-string 1) images))
256              (match-beginning 1) (match-end 1)))))))
257
258 (eval-and-compile
259   (if (featurep 'xemacs)
260       (progn
261         (defvar riece-icon-xemacs-modeline-left-extent
262           (copy-extent modeline-buffer-id-left-extent))
263
264         (defvar riece-icon-xemacs-modeline-right-extent
265           (copy-extent modeline-buffer-id-right-extent))
266
267         (defun riece-icon-modeline-buffer-identification (line)
268           "Decorate 1st element of `mode-line-buffer-identification' LINE.
269 Modify whole identification by side effect."
270           (let ((id (car line)) chopped)
271             (if (and (stringp id) (string-match "^Riece:" id))
272                 (progn
273                   (setq chopped (substring id 0 (match-end 0))
274                         id (substring id (match-end 0)))
275                   (nconc
276                    (list
277                     (let ((glyph
278                            (make-glyph
279                             (nconc
280                              (if (featurep 'xpm)
281                                  (list (vector 'xpm :data
282                                                riece-pointer-icon)))
283                              (list (vector 'string :data chopped))))))
284                       (set-glyph-face glyph 'modeline-buffer-id)
285                       (cons riece-icon-xemacs-modeline-left-extent glyph))
286                     (cons riece-icon-xemacs-modeline-right-extent id))
287                    (cdr line)))
288               line))))
289     (condition-case nil
290         (progn
291           (require 'image)
292           (defun riece-icon-modeline-buffer-identification (line)
293             "Decorate 1st element of `mode-line-buffer-identification' LINE.
294 Modify whole identification by side effect."
295             (let ((id (copy-sequence (car line)))
296                   (image
297                    (if (image-type-available-p 'xpm)
298                        (create-image riece-pointer-icon 'xpm t
299                                      :ascent 'center))))
300               (when (and image
301                          (stringp id) (string-match "^Riece:" id))
302                 (add-text-properties 0 (length id)
303                                      (list 'display image
304                                            'rear-nonsticky (list 'display))
305                                      id)
306                 (setcar line id))
307               line)))
308       (error
309        (defalias 'riece-icon-modeline-buffer-identification 'identity)))))
310
311 (defun riece-icon-insinuate ()
312   (defalias 'riece-mode-line-buffer-identification
313     #'riece-icon-modeline-buffer-identification)
314   (add-hook 'riece-user-list-mode-hook
315             (lambda ()
316               (if (riece-icon-available-p)
317                   (add-hook 'riece-update-buffer-functions
318                             'riece-icon-update-user-list-buffer t t))))
319   (add-hook 'riece-channel-list-mode-hook
320             (lambda ()
321               (if (riece-icon-available-p)
322                   (add-hook 'riece-update-buffer-functions
323                             'riece-icon-update-channel-list-buffer t t)))))
324
325 (defun riece-icon-enable ()
326   (setq riece-icon-enabled t)
327   (if riece-current-channel
328       (riece-emit-signal 'user-list-changed riece-current-channel))
329   (riece-emit-signal 'channel-list-changed))
330
331 (defun riece-icon-disable ()
332   (setq riece-icon-enabled nil)
333   (if riece-current-channel
334       (riece-emit-signal 'user-list-changed riece-current-channel))
335   (riece-emit-signal 'channel-list-changed))
336
337 (provide 'riece-icon)
338
339 ;;; riece-icon.el ends here