* gnus-picon.el (gnus-picon-find-face): Search MISC for all types.
[gnus] / lisp / gnus-picon.el
index 9e27f01..d29d2e5 100644 (file)
 (require 'gnus)
 (require 'custom)
 (require 'gnus-art)
-(require 'gnus-win)
 
 ;;; User variables:
 
 (defgroup picon nil
-  "Show pictures of people, domains, and newsgroups.
-For this to work, you must switch on the `gnus-treat-display-picon'
-variable."
+  "Show pictures of people, domains, and newsgroups."
   :group 'gnus-visual)
 
 (defcustom gnus-picon-databases '("/usr/lib/picon" "/usr/local/faces")
@@ -63,7 +60,8 @@ see http://www.cs.indiana.edu/picons/ftp/index.html"
   :type '(repeat string)
   :group 'picon)
 
-(defcustom gnus-picon-user-directories '("users" "usenix" "local" "misc")
+(defcustom gnus-picon-user-directories '("users" "usenix" "local"
+                                        "misc" "unknown")
   "*List of directories to search for user faces."
   :type '(repeat string)
   :group 'picon)
@@ -102,27 +100,37 @@ List of pairs (KEY . GLYPH) where KEY is either a filename or an URL.")
 
 ;;; Functions:
 
-(defun gnus-picon-find-user (address directories &optional exact)
-  (let* ((databases gnus-picon-databases)
-        (address (split-string address "[.@]"))
+(defsubst gnus-picon-split-address (address)
+  (setq address (split-string address "@"))
+  (if (stringp (cadr address))
+      (cons (car address) (split-string (cadr address) "\\."))
+    (if (stringp (car address))
+       (split-string (car address) "\\."))))
+
+(defun gnus-picon-find-face (address directories &optional exact)
+  (let* ((address (gnus-picon-split-address address))
         (user (pop address))
-        database directory found instance base)
-    (while (and (not found)
-               (setq database (pop databases)))
-      (while (and (not found)
-                 (setq directory (pop directories)))
-       (setq base (expand-file-name directory database))
-       (while (and (not found)
-                   address)
-         (setq found (gnus-picon-find-image
-                      (concat base "/" (mapconcat 'identity
-                                                  (reverse address)
-                                                  "/")
-                              "/" user "/")))
-         (if exact
-             (setq address nil)
-           (pop address)))))
-    found))
+        (faddress address)
+        database directory result instance base)
+    (catch 'found
+      (dolist (database gnus-picon-databases)
+       (dolist (directory directories)
+         (setq address faddress
+               base (expand-file-name directory database))
+         (while address
+           (when (setq result (gnus-picon-find-image
+                               (concat base "/" (mapconcat 'identity
+                                                           (reverse address)
+                                                           "/")
+                                       "/" user "/")))
+             (throw 'found result))
+           (if exact
+               (setq address nil)
+             (pop address)))
+         ;; Kludge to search MISC as well.
+         (when (setq result (gnus-picon-find-image
+                             (concat base "/MISC/" user "/")))
+           (throw 'found result)))))))
 
 (defun gnus-picon-find-image (directory)
   (let ((types gnus-picon-file-types)
@@ -134,47 +142,127 @@ List of pairs (KEY . GLYPH) where KEY is either a filename or an URL.")
        file
       nil)))
 
-(defun gnus-treat-from-picon ()
+(defun gnus-picon-insert-glyph (glyph category)
+  "Insert GLYPH into the buffer.
+GLYPH can be either a glyph or a string."
+  (if (stringp glyph)
+      (insert glyph)
+    (gnus-add-wash-type category)
+    (gnus-add-image category (car glyph))
+    (gnus-put-image (car glyph) (cdr glyph))))
+
+(defun gnus-picon-create-glyph (file)
+  (or (cdr (assoc file gnus-picon-glyph-alist))
+      (cdar (push (cons file (gnus-create-image file))
+                 gnus-picon-glyph-alist))))
+
+;;; Functions that does picon transformations:
+
+(defun gnus-picon-transform-address (header category)
+  (gnus-with-article-headers
+    (let ((addresses
+          (mail-header-parse-addresses (mail-fetch-field header)))
+         first spec file)
+      (dolist (address addresses)
+       (setq address (car address)
+             first t)
+       (when (and (stringp address)
+                  (setq spec (gnus-picon-split-address address)))
+         (when (setq file (or (gnus-picon-find-face
+                               address gnus-picon-user-directories)
+                              (gnus-picon-find-face
+                               (concat "unknown@"
+                                       (mapconcat
+                                        'identity (cdr spec) "."))
+                               gnus-picon-user-directories)))
+           (setcar spec (cons (gnus-picon-create-glyph file)
+                              (car spec))))
+             
+         (dotimes (i (1- (length spec)))
+           (when (setq file (gnus-picon-find-face
+                             (concat "unknown@"
+                                     (mapconcat
+                                      'identity (nthcdr (1+ i) spec) "."))
+                             gnus-picon-domain-directories t))
+             (setcar (nthcdr (1+ i) spec)
+                     (cons (gnus-picon-create-glyph file)
+                           (nth (1+ i) spec)))))
+         
+         (gnus-article-goto-header header)
+         (mail-header-narrow-to-field)
+         (when (search-forward address nil t)
+           (delete-region (match-beginning 0) (match-end 0))
+           (while spec
+             (gnus-picon-insert-glyph (pop spec) category)
+             (when spec
+               (if (not first)
+                   (insert ".")
+                 (insert "@")
+                 (setq first nil))))))))))
+
+(defun gnus-picon-transform-newsgroups (header)
   (interactive)
   (gnus-with-article-headers
-    (let ((address
-          (car (mail-header-parse-address (mail-fetch-field "from"))))
-         (first t)
+    (let ((groups
+          (sort
+           (message-tokenize-header (mail-fetch-field header))
+           (lambda (g1 g2) (> (length g1) (length g2)))))
          spec file)
-      (when address
-       (setq spec (split-string address "[.@]"))
-       (when (setq file (gnus-picon-find-user
-                         address gnus-picon-user-directories))
-         (setcar spec (gnus-picon-find-glyph file)))
-       (dotimes (i (1- (length spec)))
-         (when (setq file (gnus-picon-find-user
+      (dolist (group groups)
+       (setq spec (nreverse (split-string group "[.]")))
+       (dotimes (i (length spec))
+         (when (setq file (gnus-picon-find-face
                            (concat "unknown@"
                                    (mapconcat
-                                    'identity (nthcdr (1+ i) spec) "."))
-                           gnus-picon-domain-directories t))
-           (setcar (nthcdr (1+ i) spec) (gnus-picon-find-glyph file))))
+                                    'identity (nthcdr i spec) "."))
+                           gnus-picon-news-directories t))
+           (setcar (nthcdr i spec)
+                   (cons (gnus-picon-create-glyph file)
+                         (nth i spec)))))
        
-       (gnus-article-goto-header "from")
+       (gnus-article-goto-header header)
        (mail-header-narrow-to-field)
-       (when (search-forward address nil t)
+       (when (search-forward group nil t)
          (delete-region (match-beginning 0) (match-end 0))
+         (setq spec (nreverse spec))
          (while spec
-           (gnus-picon-insert-glyph (pop spec))
+           (gnus-picon-insert-glyph (pop spec) 'newsgroups-picon)
            (when spec
-             (if (not first)
-                 (insert ".")
-               (insert "@")
-               (setq first nil)))))))))
+             (insert "."))))))))
 
-(defun gnus-picon-insert-glyph (glyph)
-  "Insert GLYPH into the buffer.
-GLYPH can be either a glyph or a string."
-  (if (stringp glyph)
-      (insert glyph)
-    (gnus-put-image glyph)))
+;;; Commands:
 
-(defun gnus-picon-find-glyph (file)
-  (gnus-create-image file))
+;;;###autoload
+(defun gnus-treat-from-picon ()
+  "Display picons in the From header.
+If picons are already displayed, remove them."
+  (interactive)
+  (gnus-with-article-buffer
+    (if (memq 'from-picon gnus-article-wash-types)
+       (gnus-delete-images 'from-picon)
+      (gnus-picon-transform-address "from" 'from-picon))))
+
+;;;###autoload
+(defun gnus-treat-mail-picon ()
+  "Display picons in the Cc and To headers.
+If picons are already displayed, remove them."
+  (interactive)
+  (gnus-with-article-buffer
+    (if (memq 'mail-picon gnus-article-wash-types)
+       (gnus-delete-images 'mail-picon)
+      (gnus-picon-transform-address "cc" 'mail-picon)
+      (gnus-picon-transform-address "to" 'mail-picon))))
+
+;;;###autoload
+(defun gnus-treat-newsgroups-picon ()
+  "Display picons in the Newsgroups and Followup-To headers.
+If picons are already displayed, remove them."
+  (interactive)
+  (gnus-with-article-buffer
+    (if (memq 'newsgroups-picon gnus-article-wash-types)
+       (gnus-delete-images 'newsgroups-picon)
+      (gnus-picon-transform-newsgroups "newsgroups")
+      (gnus-picon-transform-newsgroups "followup-to"))))
 
 (provide 'gnus-picon)