;;; header-narrowing.el -- Narrowing mail headers ;; Copyright (C) 2003 Hideyuki Shirai ;; Author: Hideyuki Shirai ;; Yuuichi Teranishi ;; Keywords: Mail ;; This program 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. ;; This program 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 this program; if not, you can either send email to this ;; program's maintainer or write to: The Free Software Foundation, ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. ;;; Commentary: ;; ;;; Code: (defvar header-narrowing-lines 4) (defvar header-narrowing-header-end "^\\(----\\|--text follows this line--\\|\\)$") (defvar header-narrowing-fields '("to" "cc")) (defvar header-narrowing-string " ...") (defface header-narrowing-face '((((class color) (background light)) (:foreground "black" :background "dark khaki")) (((class color) (background dark)) (:foreground "white" :background "dark goldenrod")) (t (:bold t))) "*header narrowing face." :group 'mail) (defun header-narrowing () "Narrowing headers." (save-excursion (save-restriction (goto-char (point-min)) (if (re-search-forward header-narrowing-header-end nil t) (beginning-of-line) (goto-char (point-max))) (narrow-to-region (point-min) (point)) (let ((fields header-narrowing-fields)) (while fields (header-narrowing-1 (concat "^" (car fields) ":")) (setq fields (cdr fields))))))) (defvar header-narrowing-map (make-sparse-keymap)) (define-key header-narrowing-map [mouse-2] 'header-narrowing-again-at-mouse) (defvar header-narrowing-widen-map (make-sparse-keymap)) (define-key header-narrowing-widen-map [mouse-2] 'header-narrowing-widen-at-mouse) (defun header-narrowing-again-at-mouse (event) (interactive "e") (save-window-excursion (save-excursion (mouse-set-point event) (header-narrowing)))) (defun header-narrowing-1 (hregexp) (let ((case-fold-search t) ov start end) (goto-char (point-min)) (while (re-search-forward hregexp nil t) (setq start (match-beginning 0)) (forward-line 1) (setq end (progn (while (looking-at "^[ \t]") (forward-line)) (forward-line -1) (line-end-position))) (if (<= (count-lines start end) header-narrowing-lines) (forward-line 1) (goto-char start) (forward-line (1- header-narrowing-lines)) (end-of-line) (setq start (point)) (unless (eq (get-char-property start 'invisible) 'header-narrowing) (setq ov (or (let ((ovs (overlays-at start)) ov) (while (and ovs (not (overlayp ov))) (if (overlay-get (car ovs) 'header-narrowing) (setq ov (car ovs))) (setq ovs (cdr ovs))) ov) (make-overlay start end))) (overlay-put ov 'header-narrowing t) (overlay-put ov 'evaporate t) (overlay-put ov 'invisible 'header-narrowing) (overlay-put ov 'after-string header-narrowing-string)))))) (defun header-narrowing-widen-at-mouse (event) (interactive "e") (save-selected-window (select-window (posn-window (event-start event))) (let* ((win (selected-window)) (wpos (window-start win)) (pos (posn-point (event-start event))) (ovs (overlays-in (1- pos) (1+ pos))) ;; Uum... ov) (while (and ovs (not (overlayp ov))) (when (overlay-get (car ovs) 'header-narrowing) (setq ov (car ovs))) (setq ovs (cdr ovs))) (when (overlayp ov) (overlay-put ov 'face 'header-narrowing-face) (overlay-put ov 'local-map header-narrowing-map) (overlay-put ov 'invisible nil) (overlay-put ov 'after-string nil)) (set-window-start win wpos)))) (defun header-narrowing-setup () (when (boundp 'line-move-ignore-invisible) (set (make-local-variable 'line-move-ignore-invisible) t)) (set-text-properties 0 (length header-narrowing-string) `(face header-narrowing-face keymap ,header-narrowing-widen-map) header-narrowing-string)) (defun header-narrowing-toggle () (interactive) (save-excursion (goto-char (point-min)) (if (re-search-forward header-narrowing-header-end nil t) (beginning-of-line) (goto-char (point-max))) (let ((ovs (overlays-in (point-min) (point))) ov hn-ovs) (while (setq ov (car ovs)) (when (overlay-get ov 'header-narrowing) (setq hn-ovs (cons ov hn-ovs))) (setq ovs (cdr ovs))) (if hn-ovs (while hn-ovs (delete-overlay (car hn-ovs)) (setq hn-ovs (cdr hn-ovs))) (header-narrowing))))) ;; MUA specific (defun wl-message-header-narrowing () (unless (eq this-command 'wl-summary-redisplay-all-header) (header-narrowing))) (defun wl-summary-header-narrowing-toggle () (interactive) (save-selected-window (let* ((mbuf wl-message-buffer) (mwin (when mbuf (get-buffer-window mbuf))) (wpos (when mwin (window-start mwin)))) (when mbuf (set-buffer mbuf) (header-narrowing-toggle) (and wpos (set-window-start mwin wpos)))))) (add-hook 'wl-message-buffer-created-hook 'header-narrowing-setup) (add-hook 'wl-message-redisplay-hook 'wl-message-header-narrowing) (add-hook 'wl-summary-mode-hook (lambda () (define-key wl-summary-mode-map "\C-c\C-f" 'wl-summary-header-narrowing-toggle))) (defun mew-message-header-narrowing () (unless (and (eq this-command 'mew-summary-display) current-prefix-arg) (header-narrowing))) (defun mew-summary-header-narrowing-toggle () (interactive) (save-selected-window (let* ((mbuf (mew-buffer-message)) (mwin (when mbuf (get-buffer-window mbuf))) (wpos (when mwin (window-start mwin)))) (when mbuf (set-buffer mbuf) (header-narrowing-toggle) (and wpos (set-window-start mwin wpos)))))) (add-hook 'mew-message-mode-hook 'header-narrowing-setup) (add-hook 'mew-message-hook 'mew-message-header-narrowing) (add-hook 'mew-summary-mode-hook (lambda () (define-key mew-summary-mode-map "zh" 'mew-summary-header-narrowing-toggle))) (provide 'header-narrowing) ;;; header-narrowing.el ends here