X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-picon.el;h=3cc7c3701c59615a1eb3e4a97c70a28620d04788;hb=8339220cc25db3fbdab4367d6252e596bddd9cb1;hp=ec529eadcd3814a859675b864d011ca9b061cfb5;hpb=17b7a13f8745857496a1fbe961154aa541024c7a;p=gnus diff --git a/lisp/gnus-picon.el b/lisp/gnus-picon.el index ec529eadc..3cc7c3701 100644 --- a/lisp/gnus-picon.el +++ b/lisp/gnus-picon.el @@ -1,436 +1,316 @@ ;;; gnus-picon.el --- displaying pretty icons in Gnus -;; Copyright (C) 1996,97 Free Software Foundation, Inc. -;; Author: Wes Hardaker +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + +;; Author: Lars Magne Ingebrigtsen ;; Keywords: news xpm annotation glyph faces ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GNU Emacs. If not, see . ;;; Commentary: +;; There are three picon types relevant to Gnus: +;; +;; Persons: person@subdomain.dom +;; users/dom/subdomain/person/face.gif +;; usenix/dom/subdomain/person/face.gif +;; misc/MISC/person/face.gif +;; Domains: subdomain.dom +;; domain/dom/subdomain/unknown/face.gif +;; Groups: comp.lang.lisp +;; news/comp/lang/lisp/unknown/face.gif +;; +;; Original implementation by Wes Hardaker . +;; ;;; Code: -(require 'gnus) -(require 'xpm) -(require 'annotations) -(require 'custom) -(require 'gnus-art) -(require 'gnus-win) - -(defgroup picons nil - "Show pictures of people, domains, and newsgroups (XEmacs). -For this to work, you must add gnus-group-display-picons to the -gnus-summary-display-hook or to the gnus-article-display-hook -depending on what gnus-picons-display-where is set to. You must -also add gnus-article-display-picons to gnus-article-display-hook." - :group 'gnus-visual) - -(defcustom gnus-picons-buffer "*Icon Buffer*" - "Buffer name to display the icons in if gnus-picons-display-where is 'picons." - :type 'string - :group 'picons) - -(defcustom gnus-picons-display-where 'picons - "Where to display the group and article icons. -Legal values are `article' and `picons'." - :type '(choice symbol string) - :group 'picons) - -(defcustom gnus-picons-database "/usr/local/faces" - "Defines the location of the faces database. -For information on obtaining this database of pretty pictures, please -see http://www.cs.indiana.edu/picons/ftp/index.html" - :type 'directory - :group 'picons) - -(defcustom gnus-picons-news-directory "news" - "Sub-directory of the faces database containing the icons for newsgroups." - :type 'string - :group 'picons) - -(defcustom gnus-picons-user-directories '("local" "users" "usenix" "misc") - "List of directories to search for user faces." - :type '(repeat string) - :group 'picons) +;; For Emacs < 22.2. +(eval-and-compile + (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))) -(defcustom gnus-picons-domain-directories '("domains") - "List of directories to search for domain faces. -Some people may want to add \"unknown\" to this list." - :type '(repeat string) - :group 'picons) +(eval-when-compile (require 'cl)) -(defcustom gnus-picons-refresh-before-display nil - "If non-nil, display the article buffer before computing the picons." - :type 'boolean - :group 'picons) +(require 'gnus) +(require 'gnus-art) -(defcustom gnus-picons-x-face-file-name - (format "/tmp/picon-xface.%s.xbm" (user-login-name)) - "The name of the file in which to store the converted X-face header." - :type 'string - :group 'picons) +;;; User variables: -(defcustom gnus-picons-convert-x-face (format "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | pbmtoxbm > %s" gnus-picons-x-face-file-name) - "Command to convert the x-face header into a xbm file." - :type 'string - :group 'picons) +(defcustom gnus-picon-news-directories '("news") + "*List of directories to search for newsgroups faces." + :type '(repeat string) + :group 'gnus-picon) -(defcustom gnus-picons-display-as-address t - "*If t display textual email addresses along with pictures." - :type 'boolean - :group 'picons) - -(defcustom gnus-picons-file-suffixes - (when (featurep 'x) - (let ((types (list "xbm"))) - (when (featurep 'gif) - (push "gif" types)) - (when (featurep 'xpm) - (push "xpm" types)) - types)) - "List of suffixes on picon file names to try." +(defcustom gnus-picon-user-directories '("users" "usenix" "local" "misc") + "*List of directories to search for user faces." :type '(repeat string) - :group 'picons) + :group 'gnus-picon) -(defcustom gnus-picons-display-article-move-p t - "*Whether to move point to first empty line when displaying picons. -This has only an effect if `gnus-picons-display-where' has value `article'." +(defcustom gnus-picon-domain-directories '("domains") + "*List of directories to search for domain faces. +Some people may want to add \"unknown\" to this list." + :type '(repeat string) + :group 'gnus-picon) + +(defcustom gnus-picon-file-types + (let ((types (list "xbm"))) + (when (gnus-image-type-available-p 'gif) + (push "gif" types)) + (when (gnus-image-type-available-p 'xpm) + (push "xpm" types)) + types) + "*List of suffixes on picon file names to try." + :type '(repeat string) + :group 'gnus-picon) + +(defcustom gnus-picon-style 'inline + "How should picons be displayed. +If `inline', the textual representation is replaced. If `right', picons are +added right to the textual representation." + ;; FIXME: `right' needs improvement for XEmacs. + :type '(choice (const inline) + (const right)) + :group 'gnus-picon) + +(defcustom gnus-picon-inhibit-top-level-domains t + "If non-nil, don't piconify top-level domains. +These are often not very interesting." :type 'boolean - :group 'picons) - -(defvar gnus-picons-map (make-sparse-keymap "gnus-picons-keys") - "keymap to hide/show picon glyphs") - -(define-key gnus-picons-map [(button2)] 'gnus-picons-toggle-extent) - -;;; Internal variables. - -(defvar gnus-group-annotations nil - "List of annotations added/removed when selecting/exiting a group") -(defvar gnus-article-annotations nil - "List of annotations added/removed when selecting an article") -(defvar gnus-x-face-annotations nil - "List of annotations added/removed when selecting an article with an X-Face.") - -(defun gnus-picons-remove (symbol) - "Remove all annotations/processes in variable named SYMBOL. -This function is careful to set it to nil before removing anything so that -asynchronous process don't get crazy." - (let ((listitems (symbol-value symbol))) - (set symbol nil) - (while listitems - (let ((item (pop listitems))) - (cond ((annotationp item) - (delete-annotation item)) - ((processp item) - ;; kill the process, ignore any output. - (set-process-sentinel item (function (lambda (p e)))) - (delete-process item))))))) - -(defun gnus-picons-remove-all () - "Removes all picons from the Gnus display(s)." + :group 'gnus-picon) + +;;; Internal variables: + +(defvar gnus-picon-glyph-alist nil + "Picon glyphs cache. +List of pairs (KEY . GLYPH) where KEY is either a filename or an URL.") +(defvar gnus-picon-cache nil) + +;;; Functions: + +(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)) + (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 'downcase + (reverse address) + "/") + "/" (downcase user) "/"))) + (throw 'found result)) + (if exact + (setq address nil) + (pop address))) + ;; Kludge to search MISC as well. But not in "news". + (unless (string= directory "news") + (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) + found type file) + (while (and (not found) + (setq type (pop types))) + (setq found (file-exists-p (setq file (concat directory "face." type))))) + (if found + file + nil))) + +(defun gnus-picon-insert-glyph (glyph category &optional nostring) + "Insert GLYPH into the buffer. +GLYPH can be either a glyph or a string. When NOSTRING, no textual +replacement is added." + ;; Using NOSTRING prevents wrong BBDB entries with `gnus-picon-style' set to + ;; 'right. + (if (stringp glyph) + (insert glyph) + (gnus-add-wash-type category) + (gnus-add-image category (car glyph)) + (gnus-put-image (car glyph) (unless nostring (cdr glyph)) category))) + +(defun gnus-picon-create-glyph (file) + (or (cdr (assoc file gnus-picon-glyph-alist)) + (cdar (push (cons file (gnus-create-image + file nil nil + :color-symbols '(("None" . "white")))) + gnus-picon-glyph-alist)))) + +;;; Functions that does picon transformations: + +(declare-function image-size "image.c" (spec &optional pixels frame)) + +(defun gnus-picon-transform-address (header category) + (gnus-with-article-headers + (let ((addresses + (mail-header-parse-addresses + ;; mail-header-parse-addresses does not work (reliably) on + ;; decoded headers. + (or + (ignore-errors + (mail-encode-encoded-word-string + (or (mail-fetch-field header) ""))) + (mail-fetch-field header)))) + spec file point cache len) + (dolist (address addresses) + (setq address (car address)) + (when (and (stringp address) + (setq spec (gnus-picon-split-address address))) + (if (setq cache (cdr (assoc address gnus-picon-cache))) + (setq spec cache) + (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 (- (length spec) + (if gnus-picon-inhibit-top-level-domains + 2 1))) + (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))))) + (setq spec (nreverse spec)) + (push (cons address spec) gnus-picon-cache)) + + (gnus-article-goto-header header) + (mail-header-narrow-to-field) + (case gnus-picon-style + (right + (when (= (length addresses) 1) + (setq len (apply '+ (mapcar (lambda (x) + (condition-case nil + (car (image-size (car x))) + (error 0))) spec))) + (when (> len 0) + (goto-char (point-at-eol)) + (insert (propertize + " " 'display + (cons 'space + (list :align-to (- (window-width) 1 len)))))) + (goto-char (point-at-eol)) + (setq point (point-at-eol)) + (dolist (image spec) + (unless (stringp image) + (goto-char point) + (gnus-picon-insert-glyph image category 'nostring))))) + (inline + (when (search-forward address nil t) + (delete-region (match-beginning 0) (match-end 0)) + (setq point (point)) + (while spec + (goto-char point) + (if (> (length spec) 2) + (insert ".") + (if (= (length spec) 2) + (insert "@"))) + (gnus-picon-insert-glyph (pop spec) category)))))))))) + +(defun gnus-picon-transform-newsgroups (header) (interactive) - (gnus-picons-remove 'gnus-article-annotations) - (gnus-picons-remove 'gnus-group-annotations) - (gnus-picons-remove 'gnus-x-face-annotations) - (when (bufferp gnus-picons-buffer) - (kill-buffer gnus-picons-buffer))) - -(defun gnus-get-buffer-name (variable) - "Returns the buffer name associated with the contents of a variable." - (cond ((symbolp variable) - (let ((newvar (cdr (assq variable gnus-window-to-buffer)))) - (cond ((symbolp newvar) - (symbol-value newvar)) - ((stringp newvar) newvar)))) - ((stringp variable) - variable))) - -(defun gnus-picons-prepare-for-annotations (annotations) - "Prepare picons buffer for puting annotations memorized in ANNOTATIONS. -ANNOTATIONS should be a symbol naming a variable wich contains a list of -annotations. Sets buffer to `gnus-picons-display-where'." - ;; let drawing catch up - (when gnus-picons-refresh-before-display - (sit-for 0)) - (set-buffer (get-buffer-create - (gnus-get-buffer-name gnus-picons-display-where))) - (gnus-add-current-to-buffer-list) - (goto-char (point-min)) - (if (and (eq gnus-picons-display-where 'article) - gnus-picons-display-article-move-p) - (when (search-forward "\n\n" nil t) - (forward-line -1))) - (gnus-picons-remove annotations)) - -(defun gnus-picons-article-display-x-face () - "Display the x-face header bitmap in the 'gnus-picons-display-where buffer." - ;; delete any old ones. - ;; This is needed here because gnus-picons-display-x-face will not - ;; be called if there is no X-Face header - (gnus-picons-remove 'gnus-x-face-annotations) - ;; display the new one. - (let ((gnus-article-x-face-command 'gnus-picons-display-x-face)) - (gnus-article-display-x-face))) - -(defun gnus-picons-x-face-sentinel (process event) - ;; don't call gnus-picons-prepare-for-annotations, it would reset - ;; gnus-x-face-annotations. - (set-buffer (get-buffer-create - (gnus-get-buffer-name gnus-picons-display-where))) - (gnus-add-current-to-buffer-list) - (goto-char (point-min)) - (if (and (eq gnus-picons-display-where 'article) - gnus-picons-display-article-move-p) - (when (search-forward "\n\n" nil t) - (forward-line -1))) - ;; If the process is still in the list, insert this icon - (let ((myself (member process gnus-x-face-annotations))) - (when myself - (setcar myself - (make-annotation gnus-picons-x-face-file-name nil 'text)) - (delete-file gnus-picons-x-face-file-name)))) - -(defun gnus-picons-display-x-face (beg end) - "Function to display the x-face header in the picons window. -To use: (setq gnus-article-x-face-command 'gnus-picons-display-x-face)" + (gnus-with-article-headers + (gnus-article-goto-header header) + (mail-header-narrow-to-field) + (let ((groups (message-tokenize-header (mail-fetch-field header))) + spec file point) + (dolist (group groups) + (unless (setq spec (cdr (assoc group gnus-picon-cache))) + (setq spec (nreverse (split-string group "[.]"))) + (dotimes (i (length spec)) + (when (setq file (gnus-picon-find-face + (concat "unknown@" + (mapconcat + 'identity (nthcdr i spec) ".")) + gnus-picon-news-directories t)) + (setcar (nthcdr i spec) + (cons (gnus-picon-create-glyph file) + (nth i spec))))) + (push (cons group spec) gnus-picon-cache)) + (when (search-forward group nil t) + (delete-region (match-beginning 0) (match-end 0)) + (save-restriction + (narrow-to-region (point) (point)) + (while spec + (goto-char (point-min)) + (if (> (length spec) 1) + (insert ".")) + (gnus-picon-insert-glyph (pop spec) 'newsgroups-picon)) + (goto-char (point-max)))))))) + +;;; Commands: + +;; #### NOTE: the test for buffer-read-only is the same as in +;; article-display-[x-]face. See the comment up there. + +;;;###autoload +(defun gnus-treat-from-picon () + "Display picons in the From header. +If picons are already displayed, remove them." (interactive) - (if (featurep 'xface) - ;; Use builtin support - (let ((buf (current-buffer))) - (save-excursion - (gnus-picons-prepare-for-annotations 'gnus-x-face-annotations) - (setq gnus-x-face-annotations - (cons (make-annotation (concat "X-Face: " - (buffer-substring beg end buf)) - nil 'text) - gnus-x-face-annotations)))) - ;; convert the x-face header to a .xbm file - (let* ((process-connection-type nil) - (process (start-process "gnus-x-face" nil - shell-file-name shell-command-switch - gnus-picons-convert-x-face))) - (process-kill-without-query process) - (setq gnus-x-face-annotations (list process)) - (set-process-sentinel process 'gnus-picons-x-face-sentinel) - (process-send-region process beg end) - (process-send-eof process)))) - -(defun gnus-article-display-picons () - "Display faces for an author and his/her domain in gnus-picons-display-where." + (let ((wash-picon-p buffer-read-only)) + (gnus-with-article-buffer + (if (and wash-picon-p (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) - (let (from at-idx) - (when (and (featurep 'xpm) - (or (not (fboundp 'device-type)) (equal (device-type) 'x)) - (setq from (mail-fetch-field "from")) - (setq from (downcase - (or (cadr (mail-extract-address-components from)) - ""))) - (or (setq at-idx (string-match "@" from)) - (setq at-idx (length from)))) - (save-excursion - (let ((username (substring from 0 at-idx)) - (addrs (if (eq at-idx (length from)) - (if gnus-local-domain - (message-tokenize-header gnus-local-domain ".") - nil) - (message-tokenize-header (substring from (1+ at-idx)) - ".")))) - (gnus-picons-prepare-for-annotations 'gnus-article-annotations) - (setq gnus-article-annotations - (nconc gnus-article-annotations - ;; look for domain paths. - (gnus-picons-display-pairs - (gnus-picons-lookup-pairs addrs - gnus-picons-domain-directories) - (not (or gnus-picons-display-as-address - gnus-article-annotations)) - nil "." t) - ;; add an '@' if displaying as address - (if (and gnus-picons-display-as-address addrs) - (list (make-annotation "@" nil 'text nil nil nil t))) - ;; then do user directories, - (gnus-picons-display-picon-or-name - (gnus-picons-lookup-user (downcase username) addrs) - username nil t))) - - (add-hook 'gnus-summary-exit-hook 'gnus-picons-remove-all)))))) - -(defun gnus-group-display-picons () - "Display icons for the group in the gnus-picons-display-where buffer." + (let ((wash-picon-p buffer-read-only)) + (gnus-with-article-buffer + (if (and wash-picon-p (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) - (when (and (featurep 'xpm) - (or (not (fboundp 'device-type)) (equal (device-type) 'x))) - (save-excursion - (gnus-picons-prepare-for-annotations 'gnus-group-annotations) - (setq gnus-group-annotations - (gnus-picons-display-pairs - (gnus-picons-lookup-pairs (reverse (message-tokenize-header - gnus-newsgroup-name ".")) - gnus-picons-news-directory) - t nil ".")) - (add-hook 'gnus-summary-exit-hook 'gnus-picons-remove-all)))) - -(defun gnus-picons-make-path (dir subdirs) - "Make a directory name from a base DIR and a list of SUBDIRS. -Returns a directory name build by concatenating DIR and all elements of -SUBDIRS with \"/\" between elements." - (while subdirs - (setq dir (file-name-as-directory (concat dir (pop subdirs))))) - dir) - -(defsubst gnus-picons-try-suffixes (file) - (let ((suffixes gnus-picons-file-suffixes) - f) - (while (and suffixes - (not (file-exists-p (setq f (concat file (pop suffixes)))))) - (setq f nil)) - f)) - -(defun gnus-picons-lookup (addrs dirs) - "Lookup the picon for ADDRS in databases DIRS. -Returns the picon filename or NIL if none found." - (let (result) - (while (and dirs (null result)) - (setq result - (gnus-picons-try-suffixes - (expand-file-name "face." - (gnus-picons-make-path - (file-name-as-directory - (concat - (file-name-as-directory gnus-picons-database) - (pop dirs))) - (reverse addrs)))))) - result)) - -(defun gnus-picons-lookup-user-internal (user domains) - (let ((dirs gnus-picons-user-directories) - picon) - (while (and dirs (null picon)) - (let ((dir (list (pop dirs))) - (domains domains)) - (while (and domains (null picon)) - (setq picon (gnus-picons-lookup (cons user domains) dir)) - (pop domains)) - ;; Also make a try MISC subdir - (unless picon - (setq picon (gnus-picons-lookup (list user "MISC") dir))))) - - picon)) - -(defun gnus-picons-lookup-user (user domains) - "Lookup the picon for USER at DOMAINS. -USER is a string containing a name. -DOMAINS is a list of strings from the fully qualified domain name." - (or (gnus-picons-lookup-user-internal user domains) - (gnus-picons-lookup-user-internal "unknown" domains))) - -(defun gnus-picons-lookup-pairs (domains directories) - "Lookup picons for DOMAINS and all its parents in DIRECTORIES. -Returns a list of PAIRS whose CAR is the picon filename or NIL if -none, and whose CDR is the corresponding element of DOMAINS." - (let (picons) - (while domains - (push (list (gnus-picons-lookup (cons "unknown" domains) - (if (listp directories) - directories - (list directories))) - (pop domains)) - picons)) - picons)) - -(defun gnus-picons-display-picon-or-name (picon name &optional xface-p right-p) - (if picon - (gnus-picons-try-to-find-face picon xface-p name right-p) - (list (make-annotation name nil 'text nil nil nil right-p)))) - -(defun gnus-picons-display-pairs (pairs &optional bar-p xface-p dot-p right-p) - "Display picons in list PAIRS." - (let ((bar (and bar-p (or gnus-picons-display-as-address - (annotations-in-region (point) - (min (point-max) (1+ (point))) - (current-buffer))))) - (domain-p (and gnus-picons-display-as-address dot-p)) - picons) - (while pairs - (let ((pair (pop pairs))) - (setq picons (nconc (if (and domain-p picons (not right-p)) - (list (make-annotation - dot-p nil 'text nil nil nil right-p))) - (gnus-picons-display-picon-or-name (car pair) - (cadr pair) - xface-p - right-p) - (if (and domain-p pairs right-p) - (list (make-annotation - dot-p nil 'text nil nil nil right-p))) - (when (and bar domain-p) - (setq bar nil) - (gnus-picons-try-to-find-face - (expand-file-name "bar.xbm" - gnus-xmas-glyph-directory) - nil nil t)) - picons)))) - picons)) - -(defvar gnus-picons-glyph-alist nil) - -(defun gnus-picons-try-to-find-face (path &optional xface-p part rightp) - "If PATH exists, display it as a bitmap. Returns t if succeeded." - (let ((glyph (and (not xface-p) - (cdr (assoc path gnus-picons-glyph-alist))))) - (when (or glyph (file-exists-p path)) - (unless glyph - (setq glyph (make-glyph path)) - (unless xface-p - (push (cons path glyph) gnus-picons-glyph-alist)) - (set-glyph-face glyph 'default)) - (let ((new (make-annotation glyph (point) 'text nil nil nil rightp))) - (nconc - (list new) - (when (and (eq major-mode 'gnus-article-mode) - (not gnus-picons-display-as-address) - (not part)) - (list (make-annotation " " (point) 'text nil nil nil rightp))) - (when (and part gnus-picons-display-as-address) - (let ((txt (make-annotation part (point) 'text nil nil nil rightp))) - (hide-annotation txt) - (set-extent-property txt 'its-partner new) - (set-extent-property txt 'keymap gnus-picons-map) - (set-extent-property txt 'mouse-face gnus-article-mouse-face) - (set-extent-property new 'its-partner txt) - (set-extent-property new 'keymap gnus-picons-map) - (list txt)))))))) - -(defun gnus-picons-toggle-extent (event) - "Toggle picon glyph at given point" - (interactive "e") - (let* ((ant1 (event-glyph-extent event)) - (ant2 (extent-property ant1 'its-partner))) - (when (and (annotationp ant1) (annotationp ant2)) - (reveal-annotation ant2) - (hide-annotation ant1)))) - -(gnus-add-shutdown 'gnus-picons-close 'gnus) - -(defun gnus-picons-close () - "Shut down the picons." - (setq gnus-picons-glyph-alist nil)) + (let ((wash-picon-p buffer-read-only)) + (gnus-with-article-buffer + (if (and wash-picon-p (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)