1 ;;; gnus-picons.el: Icon hacks for displaying pretty icons in Gnus.
2 ;; Copyright (C) 1996 Wes Hardaker
4 ;; Author: Wes Hardaker <hardaker@ece.ucdavis.edu>
5 ;; Keywords: gnus xpm annotation glyph faces
10 ;; - You must have XEmacs (19.12 or above I think) to use this.
11 ;; - Read the variable descriptions below.
15 ;; 1) display the icons in its own buffer:
17 ;; (add-hook 'gnus-article-display-hook 'gnus-article-display-picons t)
18 ;; (add-hook 'gnus-summary-display-hook 'gnus-group-display-picons t)
19 ;; (setq gnus-picons-display-where 'picons)
21 ;; Then add the picons buffer to your display configuration:
22 ;; The picons buffer needs to be at least 48 pixels high,
23 ;; which for me is 5 lines:
25 ;; (gnus-add-configuration
26 ;; '(article (vertical 1.0
29 ;; (summary .25 point)
32 ;; (gnus-add-configuration
33 ;; '(summary (vertical 1.0 (group 6)
35 ;; (summary 1.0 point))))
37 ;; 2) display the icons in the summary buffer
39 ;; (add-hook 'gnus-article-display-hook 'gnus-article-display-picons t)
40 ;; (add-hook 'gnus-summary-display-hook 'gnus-group-display-picons t)
41 ;; (setq gnus-picons-display-where 'summary)
43 ;; 3) display the icons in the article buffer
45 ;; (add-hook 'gnus-article-display-hook 'gnus-article-display-picons t)
46 ;; (add-hook 'gnus-article-display-hook 'gnus-group-display-picons t)
47 ;; (setq gnus-picons-display-where 'article)
51 ;; - I'm not even close to being a lisp expert.
52 ;; - The 't' (append) flag MUST be in the add-hook line
55 ;; - Remove the TODO section in the headers.
61 (require 'annotations)
62 (eval-when-compile (require 'cl))
64 (defvar gnus-picons-buffer "*Icon Buffer*"
65 "Buffer name to display the icons in if gnus-picons-display-where is 'picons.")
67 (defvar gnus-picons-display-where 'picons
68 "Where to display the group and article icons.")
70 (defvar gnus-picons-database "/usr/local/faces"
71 "Defines the location of the faces database.
72 For information on obtaining this database of pretty pictures, please
73 see http://www.cs.indiana.edu/picons/ftp/index.html" )
75 (defvar gnus-picons-news-directory "news"
76 "Sub-directory of the faces database containing the icons for newsgroups."
79 (defvar gnus-picons-user-directories '("local" "users" "usenix" "misc/MISC")
80 "List of directories to search for user faces."
83 (defvar gnus-picons-domain-directories '("domains")
84 "List of directories to search for domain faces.
85 Some people may want to add \"unknown\" to this list."
88 (defvar gnus-group-annotations nil)
89 (defvar gnus-article-annotations nil)
90 (defvar gnus-x-face-annotations nil)
92 (defun gnus-picons-remove (plist)
93 (let ((listitem (car plist)))
94 (while (setq listitem (car plist))
95 (if (annotationp listitem)
96 (delete-annotation listitem))
97 (setq plist (cdr plist))))
100 (defun gnus-picons-remove-all ()
101 "Removes all picons from the Gnus display(s)."
103 (gnus-picons-remove gnus-article-annotations)
104 (gnus-picons-remove gnus-group-annotations)
105 (gnus-picons-remove gnus-x-face-annotations)
106 (setq gnus-article-annotations nil
107 gnus-group-annotations nil
108 gnus-x-face-annotations nil)
109 (if (bufferp gnus-picons-buffer)
110 (kill-buffer gnus-picons-buffer))
113 (defun gnus-get-buffer-name (variable)
114 "Returns the buffer name associated with the contents of a variable."
115 (cond ((symbolp variable)
116 (let ((newvar (cdr (assq variable gnus-window-to-buffer))))
117 (cond ((symbolp newvar)
118 (symbol-value newvar))
119 ((stringp newvar) newvar))))
123 (defvar gnus-picons-x-face-file-name
124 (format "/tmp/picon-xface.%s.xbm" (user-login-name))
125 "The name of the file in which to store the converted X-face header.")
127 (defvar gnus-picons-convert-x-face (format "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | pbmtoxbm > %s" gnus-picons-x-face-file-name)
128 "Command to convert the x-face header into a xbm file."
131 (defun gnus-picons-article-display-x-face ()
132 "Display the x-face header bitmap in the 'gnus-picons-display-where buffer."
133 ;; delete any old ones.
134 (gnus-picons-remove gnus-x-face-annotations)
135 (setq gnus-x-face-annotations nil)
136 ;; display the new one.
137 (let ((gnus-article-x-face-command 'gnus-picons-display-x-face))
138 (gnus-article-display-x-face)))
140 (defun gnus-picons-display-x-face (beg end)
141 "Function to display the x-face header in the picons window.
142 To use: (setq gnus-article-x-face-command 'gnus-picons-display-x-face)"
144 ;; convert the x-face header to a .xbm file
145 (let ((process-connection-type nil)
147 (process-kill-without-query
148 (setq process (start-process
149 "gnus-x-face" nil "sh" "-c" gnus-picons-convert-x-face)))
150 (process-send-region "gnus-x-face" beg end)
151 (process-send-eof "gnus-x-face")
153 (while (not (equal (process-status process) 'exit))
157 (set-buffer (get-buffer-create (gnus-get-buffer-name
158 gnus-picons-display-where)))
159 (gnus-add-current-to-buffer-list)
160 (beginning-of-buffer)
161 (let ((iconpoint (point)))
162 (if (not (looking-at "^$"))
171 ;; append the annotation to gnus-article-annotations for deletion.
172 (setq gnus-x-face-annotations
174 (gnus-picons-try-to-find-face
175 gnus-picons-x-face-file-name iconpoint)
176 gnus-x-face-annotations)))
177 ;; delete the tmp file
178 (delete-file gnus-picons-x-face-file-name)))
180 (defun gnus-article-display-picons ()
181 "Display faces for an author and his/her domain in gnus-picons-display-where."
183 (if (and (featurep 'xpm)
184 (or (not (fboundp 'device-type)) (equal (device-type) 'x)))
186 (let* ((iconpoint (point)) (from (mail-fetch-field "from"))
189 (string-match "\\([-_a-zA-Z0-9]+\\)@" from)
190 (match-string 1 from)))
192 (concat (gnus-picons-reverse-domain-path
194 (replace-in-string from ".*@\\([_a-zA-Z0-9-.]+\\).*"
197 (switch-to-buffer (gnus-get-buffer-name gnus-picons-display-where))
198 (gnus-add-current-to-buffer-list)
199 (beginning-of-buffer)
200 (setq iconpoint (point))
201 (if (not (looking-at "^$"))
211 (gnus-picons-remove gnus-article-annotations)
212 (setq gnus-article-annotations 'nil)
213 (if (equal username from)
214 (setq username (progn
215 (string-match "<\\([_a-zA-Z0-9-.]+\\)>" from)
216 (match-string 1 from))))
217 (mapcar '(lambda (pathpart)
218 (setq gnus-article-annotations
220 (gnus-picons-insert-face-if-exists
222 (file-name-as-directory
223 gnus-picons-database) pathpart)
224 (concat hostpath username)
226 gnus-article-annotations)))
227 gnus-picons-user-directories)
228 (mapcar '(lambda (pathpart)
229 (setq gnus-article-annotations
231 (gnus-picons-insert-face-if-exists
232 (concat (file-name-as-directory
233 gnus-picons-database) pathpart)
234 (concat hostpath "unknown")
236 gnus-article-annotations)))
237 gnus-picons-domain-directories)
238 (add-hook 'gnus-summary-exit-hook 'gnus-picons-remove-all)
241 (defun gnus-group-display-picons ()
242 "Display icons for the group in the gnus-picons-display-where buffer."
244 (if (and (featurep 'xpm)
245 (or (not (fboundp 'device-type)) (equal (device-type) 'x)))
248 ((iconpoint (point)))
249 (switch-to-buffer (gnus-get-buffer-name gnus-picons-display-where))
250 (gnus-add-current-to-buffer-list)
251 (beginning-of-buffer)
253 ((listp gnus-group-annotations)
254 (mapcar 'delete-annotation gnus-group-annotations)
255 (setq gnus-group-annotations nil))
256 ((annotationp gnus-group-annotations)
257 (delete-annotation gnus-group-annotations)
258 (setq gnus-group-annotations nil))
260 (setq iconpoint (point))
261 (if (not (looking-at "^$"))
263 (gnus-picons-remove gnus-group-annotations)
264 (setq gnus-group-annotations nil)
265 (setq gnus-group-annotations
266 (gnus-picons-insert-face-if-exists
267 (concat (file-name-as-directory gnus-picons-database)
268 gnus-picons-news-directory)
269 (concat (replace-in-string gnus-newsgroup-name "\\." "/")
272 (add-hook 'gnus-summary-exit-hook 'gnus-picons-remove-all)))))
275 (defun gnus-picons-insert-face-if-exists (path filename ipoint &optional rev)
276 "Inserts a face at point if I can find one"
277 (let ((pathfile (concat path "/" filename "/face"))
279 (replace-in-string filename
280 "[_a-zA-Z0-9-]+/\\([_A-Za-z0-9-]+\\)$" "\\1"))
283 (not (equal filename newfilename)))
284 (setq annotations (append
285 (gnus-picons-insert-face-if-exists path newfilename ipoint rev)
287 (if (eq (length annotations) (length (setq annotations (append
288 (gnus-picons-try-to-find-face (concat pathfile ".xpm") ipoint)
290 (setq annotations (append
291 (gnus-picons-try-to-find-face
292 (concat pathfile ".xbm") ipoint)
295 (not (equal filename newfilename)))
296 (setq annotations (append
297 (gnus-picons-insert-face-if-exists path newfilename ipoint rev)
303 (defun gnus-picons-try-to-find-face (path ipoint)
304 "If PATH exists, display it as a bitmap. Returns t if succedded."
305 (when (file-exists-p path)
306 (let ((gl (make-glyph path)))
307 (set-glyph-face gl 'default)
308 (list (make-annotation gl ipoint 'text)))))
310 (defun gnus-picons-reverse-domain-path (str)
312 (if (equal (replace-in-string str "^[^/]*$" "") "")
314 (concat (replace-in-string str "^.*/\\([_a-zA-Z0-9-]+\\)$" "\\1") "/"
315 (gnus-picons-reverse-domain-path
316 (replace-in-string str "^\\(.*\\)/[_a-zA-Z0-9-]+$" "\\1")))))
318 (provide 'gnus-picon)
320 ;;; gnus-picon.el ends here