X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-picon.el;h=188f07168fee71d70b5cd2b6919df703688bc3b3;hb=a8ee92ba66284aa600ccd866e9a85fcbe35ea116;hp=36437edb1692a9dc08d87cb4b0dff3ff232b3714;hpb=c66544cbcf56f439e6fc8c07079c829e7e16d1e0;p=gnus diff --git a/lisp/gnus-picon.el b/lisp/gnus-picon.el index 36437edb1..188f07168 100644 --- a/lisp/gnus-picon.el +++ b/lisp/gnus-picon.el @@ -1,121 +1,264 @@ -;; gnus-picon.el: Copyright (C) 1995 Wes Hardaker -;; Icon hacks for displaying pretty icons in Gnus. -;; -;; Author: Wes hardaker -;; hardaker@ece.ucdavis.edu -;; -;; Usage: -;; - You must have XEmacs to use this. -;; - (add-hook 'gnus-article-display-hook 'gnus-article-display-picons t) -;; This HAS to have the 't' flag above to make sure it appends the hook. -;; - Read the variable descriptions below. -;; -;; Warnings: -;; - I'm not even close to being a lisp expert. -;; -;; TODO: -;; - Following the Gnus motto: We've got to build him bigger, -;; better, stronger, faster than before... errr.... sorry. -;; - Create a seperate frame to store icons in so icons are -;; visibile immediately upon entering a group rather than just -;; at the top of the article buffer. +;;; gnus-picon.el --- displaying pretty icons in Gnus + +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Free Software Foundation, Inc. + +;; Author: Wes Hardaker +;; 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 +;; 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. + +;; 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 +;; 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. + +;;; 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 + +;;; Code: + +(require 'gnus) +(require 'custom) +(require 'gnus-art) + +;;; User variables: + +(defcustom gnus-picon-news-directories '("news") + "*List of directories to search for newsgroups faces." + :type '(repeat string) + :group 'gnus-picon) + +(defcustom gnus-picon-user-directories '("users" "usenix" "local" "misc") + "*List of directories to search for user faces." + :type '(repeat string) + :group 'gnus-picon) + +(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) -(require 'xpm) -(require 'annotations) +(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) -(defvar 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" -) +(defface gnus-picon-xbm-face '((t (:foreground "black" :background "white"))) + "Face to show xbm picon in." + :group 'gnus-picon) -(defvar gnus-picons-news-directory "news" - "Sub-directory of the faces database containing the icons for - newsgroups." -) +(defface gnus-picon-face '((t (:foreground "black" :background "white"))) + "Face to show picon in." + :group 'gnus-picon) -(defvar gnus-picons-user-directories '("local" "users" "usenix" "misc/MISC") - "List of directories to search for user faces." -) +;;; Internal variables: -(defvar gnus-picons-domain-directories '("domains") - "List of directories to search for domain faces. Some people may - want to add \"unknown\" to this list." -) +(defvar gnus-picon-setup-p nil) +(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) + "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))) + spec file point cache) + (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 (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))))) + (setq spec (nreverse spec)) + (push (cons address spec) gnus-picon-cache)) + + (gnus-article-goto-header header) + (mail-header-narrow-to-field) + (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-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: + +;;;###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)))) -(defun gnus-article-display-picons () - "prepare article buffer with pretty pictures" +;;;###autoload +(defun gnus-treat-newsgroups-picon () + "Display picons in the Newsgroups and Followup-To headers. +If picons are already displayed, remove them." (interactive) - (if (featurep 'xpm) - (save-excursion - (beginning-of-buffer) - (open-line 1) - (let* ((iconpoint (point)) (from (mail-fetch-field "from")) - (username - (progn - (string-match "\\([-_a-zA-Z0-9]+\\)@" from) - (match-string 1 from))) - (hostpath - (gnus-picons-reverse-domain-path - (replace-in-string - (replace-in-string from ".*@\\([_a-zA-Z0-9-.]+\\).*" "\\1") - "\\." "/")))) - (if (equal username from) - (setq username (replace-in-string from - ".*<\\([_a-zA-Z0-9-.]+\\)>.*" - "\\1"))) - (insert username) - (gnus-picons-insert-face-if-exists - (concat gnus-picons-database "/" gnus-picons-news-directory) - (concat (replace-in-string gnus-newsgroup-name "\\." "/") "/unknown") - iconpoint) - (mapcar '(lambda (pathpart) - (gnus-picons-insert-face-if-exists - (concat gnus-picons-database "/" pathpart) - (concat hostpath "/" username) - iconpoint)) - gnus-picons-user-directories) - (mapcar '(lambda (pathpart) - (gnus-picons-insert-face-if-exists - (concat gnus-picons-database "/" pathpart) - (concat hostpath "/" "unknown") - iconpoint)) - gnus-picons-domain-directories) - )))) - -(defun gnus-picons-insert-face-if-exists (path filename ipoint) - "inserts a face at point if I can find one" - (let ((pathfile (concat path "/" filename "/face"))) - (let ((newfilename - (replace-in-string filename - "[_a-zA-Z0-9-]+/\\([_A-Za-z0-9-]+\\)$" "\\1"))) - (if (not (equal filename newfilename)) - (gnus-picons-insert-face-if-exists path newfilename ipoint))) - (if (not (gnus-picons-try-to-find-face (concat pathfile ".xpm") ipoint)) - (gnus-picons-try-to-find-face (concat pathfile ".xbm") ipoint)) - ) - ) - - -(defun gnus-picons-try-to-find-face (path ipoint) - "if path exists, display it as a bitmap. Returns t if succedded." - (if (file-exists-p path) - (progn - (setq gl (make-glyph path)) - (set-glyph-face gl 'default) - (setq annot (make-annotation gl ipoint 'text)) - t) -; (insert (format "no: %s\n" path)) - nil)) - -(defun gnus-picons-reverse-domain-path (str) - "a/b/c/d -> d/c/b/a" - (if (equal (replace-in-string str "^[^/]*$" "") "") - str - (concat (replace-in-string str "^.*/\\([_a-zA-Z0-9-]+\\)$" "\\1") "/" - (gnus-picons-reverse-domain-path - (replace-in-string str "^\\(.*\\)/[_a-zA-Z0-9-]+$" "\\1"))))) + (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) +;;; gnus-picon.el ends here