*** empty log message ***
[gnus] / lisp / gnus-vis.el
1 ;;; gnus-vis.el --- display-oriented parts of Gnus
2 ;; Copyright (C) 1995 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;;      Per Abrahamsen <abraham@iesd.auc.dk>
6 ;; Keywords: news
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 ;;; Commentary:
25
26 ;;; Code:
27
28 (require 'gnus)
29 (require 'gnus-ems)
30 (require 'easymenu)
31 (require 'custom)
32
33 (defvar gnus-group-menu-hook nil
34   "*Hook run after the creation of the group mode menu.")
35
36 (defvar gnus-summary-menu-hook nil
37   "*Hook run after the creation of the summary mode menu.")
38
39 (defvar gnus-article-menu-hook nil
40   "*Hook run after the creation of the article mode menu.")
41
42 (defvar gnus-server-menu-hook nil
43   "*Hook run after the creation of the server mode menu.")
44
45 (defvar gnus-browse-menu-hook nil
46   "*Hook run after the creation of the browse mode menu.")
47   
48 ;;; Summary highlights.
49
50 ;(defvar gnus-summary-highlight-properties
51 ;  '((unread "ForestGreen" "green")
52 ;    (ticked "Firebrick" "pink")
53 ;    (read "black" "white")
54 ;    (low italic italic)
55 ;    (high bold bold)
56 ;    (canceled "yellow/black" "black/yellow")))
57
58 ;(defvar gnus-summary-highlight-translation
59 ;  '(((unread (= mark gnus-unread-mark))
60 ;     (ticked (or (= mark gnus-ticked-mark) (= mark gnus-dormant-mark)))
61 ;     (read (not (or (= mark gnus-unread-mark) (= mark gnus-dormant-mark)
62 ;                   (= mark gnus-ticked-mark) (= mark gnus-canceled-mark))))
63 ;     (canceled (= mark gnus-canceled-mark)))
64 ;    ((low (< score gnus-summary-default-score))
65 ;     (high (> score gnus-summary-default-score)))))
66
67 ;(defun gnus-visual-map-face-translation ()
68 ;  (let ((props gnus-summary-highlight-properties)
69 ;       (trans gnus-summary-highlight-translation)
70 ;       map)
71 ;    (while props)))
72       
73 ;see gnus-cus.el
74 ;(defvar gnus-summary-selected-face 'underline
75 ;  "*Face used for highlighting the current article in the summary buffer.")
76  
77 ;see gnus-cus.el
78 ;(defvar gnus-summary-highlight
79 ;  (cond ((not (eq gnus-display-type 'color))
80 ;        '(((> score default) . bold)
81 ;          ((< score default) . italic)))
82 ;       ((eq gnus-background-mode 'dark)
83 ;        (list (cons '(= mark gnus-canceled-mark)
84 ;                    (custom-face-lookup "yellow" "black" nil nil nil nil))
85 ;              (cons '(and (> score default) 
86 ;                          (or (= mark gnus-dormant-mark)
87 ;                              (= mark gnus-ticked-mark)))
88 ;                    (custom-face-lookup "pink" nil nil t nil nil))
89 ;              (cons '(and (< score default) 
90 ;                          (or (= mark gnus-dormant-mark)
91 ;                              (= mark gnus-ticked-mark)))
92 ;                    (custom-face-lookup "pink" nil nil nil t nil))
93 ;              (cons '(or (= mark gnus-dormant-mark)
94 ;                         (= mark gnus-ticked-mark))
95 ;                    (custom-face-lookup "pink" nil nil nil nil nil))
96
97 ;              (cons '(and (> score default) (= mark gnus-ancient-mark))
98 ;                    (custom-face-lookup "SkyBlue" nil nil t nil nil))
99 ;              (cons '(and (< score default) (= mark gnus-ancient-mark))
100 ;                    (custom-face-lookup "SkyBlue" nil nil nil t nil))
101 ;              (cons '(= mark gnus-ancient-mark)
102 ;                    (custom-face-lookup "SkyBlue" nil nil nil nil nil))
103
104 ;              (cons '(and (> score default) (= mark gnus-unread-mark))
105 ;                    (custom-face-lookup "white" nil nil t nil nil))
106 ;              (cons '(and (< score default) (= mark gnus-unread-mark))
107 ;                    (custom-face-lookup "white" nil nil nil t nil))
108 ;              (cons '(= mark gnus-unread-mark)
109 ;                    (custom-face-lookup "white" nil nil nil nil nil))
110
111 ;              (cons '(> score default) 'bold)
112 ;              (cons '(< score default) 'italic)))
113 ;       (t
114 ;        (list (cons '(= mark gnus-canceled-mark)
115 ;                    (custom-face-lookup "yellow" "black" nil nil nil nil))
116 ;              (cons '(and (> score default) 
117 ;                          (or (= mark gnus-dormant-mark)
118 ;                              (= mark gnus-ticked-mark)))
119 ;                    (custom-face-lookup "firebrick" nil nil t nil nil))
120 ;              (cons '(and (< score default) 
121 ;                          (or (= mark gnus-dormant-mark)
122 ;                              (= mark gnus-ticked-mark)))
123 ;                    (custom-face-lookup "firebrick" nil nil nil t nil))
124 ;              (cons '(or (= mark gnus-dormant-mark)
125 ;                         (= mark gnus-ticked-mark))
126 ;                    (custom-face-lookup "firebrick" nil nil nil nil nil))
127
128 ;              (cons '(and (> score default) (= mark gnus-ancient-mark))
129 ;                    (custom-face-lookup "RoyalBlue" nil nil t nil nil))
130 ;              (cons '(and (< score default) (= mark gnus-ancient-mark))
131 ;                    (custom-face-lookup "RoyalBlue" nil nil nil t nil))
132 ;              (cons '(= mark gnus-ancient-mark)
133 ;                    (custom-face-lookup "RoyalBlue" nil nil nil nil nil))
134
135 ;              (cons '(and (> score default) (/= mark gnus-unread-mark))
136 ;                    (custom-face-lookup "DarkGreen" nil nil t nil nil))
137 ;              (cons '(and (< score default) (/= mark gnus-unread-mark))
138 ;                    (custom-face-lookup "DarkGreen" nil nil nil t nil))
139 ;              (cons '(/= mark gnus-unread-mark)
140 ;                    (custom-face-lookup "DarkGreen" nil nil nil nil nil))
141
142 ;              (cons '(> score default) 'bold)
143 ;              (cons '(< score default) 'italic))))
144 ;  "*Alist of `(FORM . FACE)'.
145 ;Summary lines are highlighted with the FACE for the first FORM which
146 ;evaluate to a non-nil value.  
147
148 ;Point will be at the beginning of the line when FORM is evaluated.
149 ;The following can be used for convenience:
150
151 ;score:   (gnus-summary-article-score)
152 ;default: gnus-summary-default-score
153 ;below:   gnus-summary-mark-below
154 ;mark:    (gnus-summary-article-mark)
155
156 ;The latter can be used like this:
157 ;   ((= mark gnus-replied-mark) . underline)")
158
159 ;;; article highlights
160
161 ;see gnus-cus.el
162 ;(defvar gnus-header-face-alist 
163 ;  (cond ((not (eq gnus-display-type 'color))
164 ;        '(("" bold italic)))
165 ;       ((eq gnus-background-mode 'dark)
166 ;        (list (list "From" nil 
167 ;                    (custom-face-lookup "SkyBlue" nil nil t t nil))
168 ;              (list "Subject" nil 
169 ;                    (custom-face-lookup "pink" nil nil t t nil))
170 ;              (list "Newsgroups:.*," nil
171 ;                    (custom-face-lookup "yellow" nil nil t t nil))
172 ;              (list "" 
173 ;                    (custom-face-lookup "cyan" nil nil t nil nil)
174 ;                    (custom-face-lookup "green" nil nil nil t nil))))
175 ;       (t
176 ;        (list (list "From" nil 
177 ;                    (custom-face-lookup "RoyalBlue" nil nil t t nil))
178 ;              (list "Subject" nil 
179 ;                    (custom-face-lookup "firebrick" nil nil t t nil))
180 ;              (list "Newsgroups:.*," nil
181 ;                    (custom-face-lookup "red" nil nil t t nil))
182 ;              (list ""
183 ;                    (custom-face-lookup "DarkGreen" nil nil t nil nil)
184 ;                    (custom-face-lookup "DarkGreen" nil nil nil t nil)))))
185 ;  "Alist of headers and faces used for highlighting them.
186 ;The entries in the list has the form `(REGEXP NAME CONTENT)', where
187 ;REGEXP is a regular expression matching the beginning of the header,
188 ;NAME is the face used for highlighting the header name and CONTENT is
189 ;the face used for highlighting the header content. 
190
191 ;The first non-nil NAME or CONTENT with a matching REGEXP in the list
192 ;will be used.")
193
194
195 ;see gnus-cus.el
196 ;(defvar gnus-make-foreground t
197 ;  "Non nil means foreground color to highlight citations.")
198
199 ;see gnus-cus.el
200 ;(defvar gnus-article-button-face 'bold
201 ;  "Face used for text buttons.")
202
203 ;see gnus-cus.el
204 ;(defvar gnus-article-mouse-face (if (boundp 'gnus-mouse-face)
205 ;                                   gnus-mouse-face
206 ;                                 'highlight)
207 ;  "Face used when the mouse is over the button.")
208
209 ;see gnus-cus.el
210 ;(defvar gnus-signature-face 'italic
211 ;  "Face used for signature.")
212
213 (defvar gnus-button-alist 
214   '(("in\\( +article\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2 
215      (assq (count-lines (point-min) (match-end 0)) 
216            gnus-cite-attribution-alist)
217      gnus-button-message-id 3)
218     ;; This is how URLs _should_ be embedded in text...
219     ("<URL:\\([^\n\r>]*\\)>" 0 t gnus-button-url 1)
220     ;; Next regexp stolen from highlight-headers.el.
221     ;; Modified by Vladimir Alexiev.
222     ("\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?[-a-zA-Z0-9_=?#$@~`%&*+|\\/.,]*[-a-zA-Z0-9_=#$@~`%&*+|\\/]" 0 t gnus-button-url 0))
223   "Alist of regexps matching buttons in article bodies.
224
225 Each entry has the form (REGEXP BUTTON FORM CALLBACK PAR...), where
226 REGEXP: is the string matching text around the button,
227 BUTTON: is the number of the regexp grouping actually matching the button,
228 FORM: is a lisp expression which must eval to true for the button to
229 be added, 
230 CALLBACK: is the function to call when the user push this button, and each
231 PAR: is a number of a regexp grouping whose text will be passed to CALLBACK.
232
233 CALLBACK can also be a variable, in that case the value of that
234 variable it the real callback function.")
235
236 (defvar gnus-header-button-alist 
237   '(("^\\(References\\|Message-ID\\):" "<[^>]+>" 0 t gnus-button-message-id 0)
238     ("^\\(From\\|Reply-To\\): " ": *\\(.+\\)$" 1 t gnus-button-reply 0)
239     ("^\\(Cc\\|To\\):" "[^ \t\n<>,()\"]+@[^ \t\n<>,()\"]+" 
240      0 t gnus-button-mailto 0))
241   "Alist of headers and regexps to match buttons in article heads.
242
243 This alist is very similar to `gnus-button-alist', except that each
244 alist has an additional HEADER element first in each entry:
245
246 \(HEADER REGEXP BUTTON FORM CALLBACK PAR)
247
248 HEADER is a regexp to match a header.  For a fuller explanation, see
249 `gnus-button-alist'.")
250
251 ;see gnus-cus.el
252 ;(eval-when-compile
253 ;  (defvar browse-url-browser-function))
254
255 ;see gnus-cus.el
256 ;(defvar gnus-button-url
257 ;  (cond ((boundp 'browse-url-browser-function) browse-url-browser-function)
258 ;       ((fboundp 'w3-fetch) 'w3-fetch)
259 ;       ((eq window-system 'x) 'gnus-netscape-open-url))
260 ;  "*Function to fetch URL.
261 ;The function will be called with one argument, the URL to fetch.
262 ;Useful values of this function are:
263
264 ;w3-fetch: 
265 ;   defined in the w3 emacs package by William M. Perry.
266 ;gnus-netscape-open-url:
267 ;   open url in existing netscape, start netscape if none found.
268 ;gnus-netscape-start-url:
269 ;   start new netscape with url.")
270
271 \f
272
273 (eval-and-compile
274   (autoload 'nnkiboze-generate-groups "nnkiboze")
275   (autoload 'gnus-cite-parse-maybe "gnus-cite" nil t))
276
277 ;;;
278 ;;; gnus-menu
279 ;;;
280
281 (defun gnus-visual-turn-off-edit-menu (type)
282   (define-key (symbol-value (intern (format "gnus-%s-mode-map" type)))
283     [menu-bar edit] 'undefined))
284
285 ;; Newsgroup buffer
286
287 (defun gnus-group-make-menu-bar ()
288   (gnus-visual-turn-off-edit-menu 'group)
289   (or 
290    (boundp 'gnus-group-reading-menu)
291    (progn
292      (easy-menu-define
293       gnus-group-reading-menu
294       gnus-group-mode-map
295       ""
296       '("Group"
297         ["Read" gnus-group-read-group t]
298         ["Select" gnus-group-select-group t]
299         ["See old articles" gnus-group-select-group-all t]
300         ["Catch up" gnus-group-catchup-current t]
301         ["Catch up all articles" gnus-group-catchup-current-all t]
302         ["Check for new articles" gnus-group-get-new-news-this-group t]
303         ["Toggle subscription" gnus-group-unsubscribe-current-group t]
304         ["Kill" gnus-group-kill-group t]
305         ["Yank" gnus-group-yank-group t]
306         ["Describe" gnus-group-describe-group t]
307         ["Fetch FAQ" gnus-group-fetch-faq t]
308         ["Edit kill file" gnus-group-edit-local-kill t]
309         ["Expire articles" gnus-group-expire-articles t]
310         ["Set group level" gnus-group-set-current-level t]
311         ["Select quick" gnus-group-quick-select-group t]
312         ))
313   
314      (easy-menu-define
315       gnus-group-group-menu
316       gnus-group-mode-map
317       ""
318       '("Groups"
319         ("Listing"
320          ["List subscribed groups" gnus-group-list-groups t]
321          ["List all groups" gnus-group-list-all-groups t]
322          ["List groups matching..." gnus-group-list-matching t]
323          ["List killed groups" gnus-group-list-killed t]
324          ["List zombie groups" gnus-group-list-zombies t]
325          ["Describe all groups" gnus-group-describe-all-groups t]
326          ["Group apropos" gnus-group-apropos t]
327          ["Group and description apropos" gnus-group-description-apropos t]
328          ["List groups matching..." gnus-group-list-matching t]
329          ["List active file" gnus-group-list-active t])
330         ("Mark"
331          ["Mark group" gnus-group-mark-group t]
332          ["Unmark group" gnus-group-unmark-group t]
333          ["Mark region" gnus-group-mark-region t])
334         ("Subscribe"
335          ["Subscribe to random group" gnus-group-unsubscribe-group t]
336          ["Kill all newsgroups in region" gnus-group-kill-region t]
337          ["Kill all zombie groups" gnus-group-kill-all-zombies t])
338         ("Foreign groups"
339          ["Make a foreign group" gnus-group-make-group t]
340          ["Add a directory group" gnus-group-make-directory-group t]
341          ["Add the help group" gnus-group-make-help-group t]
342          ["Add the archive group" gnus-group-make-archive-group t]
343          ["Make a doc group" gnus-group-make-doc-group t]
344          ["Make a kiboze group" gnus-group-make-kiboze-group t]
345          ["Make a virtual group" gnus-group-make-empty-virtual t]
346          ["Add a group to a virtual" gnus-group-add-to-virtual t]
347          ["Rename group" gnus-group-rename-group t]
348          ["Delete group" gnus-group-delete-group t])
349         ("Editing groups"
350          ["Parameters" gnus-group-edit-group-parameters t]
351          ["Select method" gnus-group-edit-group-method t]
352          ["Info" gnus-group-edit-group t])
353         ("Score file"
354          ["Flush cache" gnus-score-flush-cache t])
355         ["Read a directory as a group" gnus-group-enter-directory t]
356         ["Jump to group" gnus-group-jump-to-group t]
357         ["Best unread group" gnus-group-best-unread-group t]
358         ))
359
360      (easy-menu-define
361       gnus-group-misc-menu
362       gnus-group-mode-map
363       ""
364       '("Misc"
365         ["Send a bug report" gnus-bug t]
366         ["Send a mail" gnus-group-mail t]
367         ["Post an article" gnus-group-post-news t]
368         ["Customize score file" gnus-score-customize 
369          (not (string-match "XEmacs" emacs-version)) ]
370         ["Check for new news" gnus-group-get-new-news t]     
371         ["Delete bogus groups" gnus-group-check-bogus-groups t]
372         ["Find new newsgroups" gnus-find-new-newsgroups t]
373         ["Restart Gnus" gnus-group-restart t]
374         ["Read init file" gnus-group-read-init-file t]
375         ["Browse foreign server" gnus-group-browse-foreign-server t]
376         ["Enter server buffer" gnus-group-enter-server-mode t]
377         ["Expire expirable articles" gnus-group-expire-all-groups t]
378         ["Generate any kiboze groups" nnkiboze-generate-groups t]
379         ["Gnus version" gnus-version t]
380         ["Save .newsrc files" gnus-group-save-newsrc t]
381         ["Suspend Gnus" gnus-group-suspend t]
382         ["Clear dribble buffer" gnus-group-clear-dribble t]
383         ["Exit from Gnus" gnus-group-exit t]
384         ["Exit without saving" gnus-group-quit t]
385         ["Edit global kill file" gnus-group-edit-global-kill t]
386         ["Sort group buffer" gnus-group-sort-groups t]
387         ))
388      (run-hooks 'gnus-group-menu-hook)
389      )))
390
391 ;; Server mode
392 (defun gnus-server-make-menu-bar ()
393   (gnus-visual-turn-off-edit-menu 'server)
394   (or
395    (boundp 'gnus-server-menu)
396    (progn
397      (easy-menu-define
398       gnus-server-menu
399       gnus-server-mode-map
400       ""
401       '("Server"
402         ["Add" gnus-server-add-server t]
403         ["Browse" gnus-server-read-server t]
404         ["List" gnus-server-list-servers t]
405         ["Kill" gnus-server-kill-server t]
406         ["Yank" gnus-server-yank-server t]
407         ["Copy" gnus-server-copy-server t]
408         ["Edit" gnus-server-edit-server t]
409         ["Exit" gnus-server-exit t]
410         ))
411      (run-hooks 'gnus-server-menu-hook)
412      )))
413
414 ;; Browse mode
415 (defun gnus-browse-make-menu-bar ()
416   (gnus-visual-turn-off-edit-menu 'browse)
417   (or
418    (boundp 'gnus-browse-menu)
419    (progn
420      (easy-menu-define
421       gnus-browse-menu
422       gnus-browse-mode-map
423       ""
424       '("Browse"
425         ["Subscribe" gnus-browse-unsubscribe-current-group t]
426         ["Read" gnus-group-read-group t]
427         ["Exit" gnus-browse-exit t]
428         ))
429       (run-hooks 'gnus-browse-menu-hook)
430       )))
431
432
433 ;; Summary buffer
434 (defun gnus-summary-make-menu-bar ()
435   (gnus-visual-turn-off-edit-menu 'summary)
436
437   (or
438    (boundp 'gnus-summary-misc-menu)
439    (progn
440
441      (easy-menu-define
442       gnus-summary-misc-menu
443       gnus-summary-mode-map
444       ""
445       '("Misc"
446         ("Mark"
447          ("Read"
448           ["Mark as read" gnus-summary-mark-as-read-forward t]
449           ["Mark same subject and select" gnus-summary-kill-same-subject-and-select t]
450           ["Mark same subject" gnus-summary-kill-same-subject t]
451           ["Catchup" gnus-summary-catchup t]
452           ["Catchup all" gnus-summary-catchup-all t]
453           ["Catchup to here" gnus-summary-catchup-to-here t]
454           ["Catchup region" gnus-summary-mark-region-as-read t])
455          ("Various"
456           ["Tick" gnus-summary-tick-article-forward t]
457           ["Mark as dormant" gnus-summary-mark-as-dormant t]
458           ["Remove marks" gnus-summary-clear-mark-forward t]
459           ["Set expirable mark" gnus-summary-mark-as-expirable t]
460           ["Set bookmark" gnus-summary-set-bookmark t]
461           ["Remove bookmark" gnus-summary-remove-bookmark t])
462          ("Limit"
463           ["Unread" gnus-summary-limit-to-unread t]
464           ["Marks" gnus-summary-limit-to-marks t]
465           ["Score" gnus-summary-limit-to-score t]
466           ["Subject" gnus-summary-limit-to-subject t]
467           ["Non-dormant" gnus-summary-limit-exclude-dormant t]
468           ["Articles" gnus-summary-limit-to-articles t]
469           ["Pop limit" gnus-summary-pop-limit t]
470           ["Show dormant" gnus-summary-limit-include-dormant t]
471           ["Show expunged" gnus-summary-show-all-expunged t])
472          ("Process mark"
473           ["Set mark" gnus-summary-mark-as-processable t]
474           ["Remove mark" gnus-summary-unmark-as-processable t]
475           ["Remove all marks" gnus-summary-unmark-all-processable t]
476           ["Mark series" gnus-uu-mark-series t]
477           ["Mark region" gnus-uu-mark-region t]
478           ["Mark by regexp" gnus-uu-mark-by-regexp t]
479           ["Mark all" gnus-uu-mark-all t]
480           ["Mark buffer" gnus-uu-mark-buffer t]
481           ["Mark sparse" gnus-uu-mark-sparse t]
482           ["Mark thread" gnus-uu-mark-thread t]
483           ["Unmark thread" gnus-uu-unmark-thread t]))
484         ("Move"
485          ["Scroll article forwards" gnus-summary-next-page t]
486          ["Next unread article" gnus-summary-next-unread-article t]
487          ["Previous unread article" gnus-summary-prev-unread-article t]
488          ["Next article" gnus-summary-next-article t]
489          ["Previous article" gnus-summary-prev-article t]
490          ["Next article same subject" gnus-summary-next-same-subject t]
491          ["Previous article same subject" gnus-summary-prev-same-subject t]
492          ["First unread article" gnus-summary-first-unread-article t]
493          ["Go to subject number..." gnus-summary-goto-subject t]
494          ["Go to the last article" gnus-summary-goto-last-article t]
495          ["Pop article off history" gnus-summary-pop-article t])        
496         ("Sort"
497          ["Sort by number" gnus-summary-sort-by-number t]
498          ["Sort by author" gnus-summary-sort-by-author t]
499          ["Sort by subject" gnus-summary-sort-by-subject t]
500          ["Sort by date" gnus-summary-sort-by-date t]
501          ["Sort by score" gnus-summary-sort-by-score t])
502         ("Exit"
503          ["Catchup and exit" gnus-summary-catchup-and-exit t]
504          ["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
505          ["Exit group" gnus-summary-exit t]
506          ["Exit group without updating" gnus-summary-exit-no-update t]
507          ["Reselect group" gnus-summary-reselect-current-group t]
508          ["Rescan group" gnus-summary-rescan-group t])
509         ["Fetch group FAQ" gnus-summary-fetch-faq t]
510         ["Filter articles" gnus-summary-execute-command t]
511         ["Toggle line truncation" gnus-summary-toggle-truncation t]
512         ["Expire expirable articles" gnus-summary-expire-articles t]
513         ["Describe group" gnus-summary-describe-group t]
514         ["Edit local kill file" gnus-summary-edit-local-kill t]
515         ))
516
517      (easy-menu-define
518       gnus-summary-kill-menu
519       gnus-summary-mode-map
520       ""
521       (cons
522        "Score"
523        (nconc
524         (list
525          ["Enter score" gnus-summary-score-entry t])
526         (gnus-visual-score-map 'increase)
527         (gnus-visual-score-map 'lower)
528         '(["Current score" gnus-summary-current-score t]
529           ["Set score" gnus-summary-set-score t]
530           ["Customize score file" gnus-score-customize t]
531           ["Switch current score file" gnus-score-change-score-file t]
532           ["Set mark below" gnus-score-set-mark-below t]
533           ["Set expunge below" gnus-score-set-expunge-below t]
534           ["Edit current score file" gnus-score-edit-alist t]
535           ["Edit score file" gnus-score-edit-file t]
536           ["Trace score" gnus-score-find-trace t]
537           ["Increase score" gnus-summary-increase-score t]
538           ["Lower score" gnus-summary-lower-score t]))))
539
540      (and nil
541           '(("Default header"
542              ["Ask" (gnus-score-set-default 'gnus-score-default-header nil)
543               :style radio 
544               :selected (null gnus-score-default-header)]
545              ["From" (gnus-score-set-default 'gnus-score-default-header 'a)
546               :style radio 
547               :selected (eq gnus-score-default-header 'a )]
548              ["Subject" (gnus-score-set-default 'gnus-score-default-header 's)
549               :style radio 
550               :selected (eq gnus-score-default-header 's )]
551              ["Article body"
552               (gnus-score-set-default 'gnus-score-default-header 'b)
553               :style radio 
554               :selected (eq gnus-score-default-header 'b )]
555              ["All headers"
556               (gnus-score-set-default 'gnus-score-default-header 'h)
557               :style radio 
558               :selected (eq gnus-score-default-header 'h )]
559              ["Message-Id" (gnus-score-set-default 'gnus-score-default-header 'i)
560               :style radio 
561               :selected (eq gnus-score-default-header 'i )]
562              ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
563               :style radio 
564               :selected (eq gnus-score-default-header 't )]
565              ["Crossposting"
566               (gnus-score-set-default 'gnus-score-default-header 'x)
567               :style radio 
568               :selected (eq gnus-score-default-header 'x )]
569              ["Lines" (gnus-score-set-default 'gnus-score-default-header 'l)
570               :style radio 
571               :selected (eq gnus-score-default-header 'l )]
572              ["Date" (gnus-score-set-default 'gnus-score-default-header 'd)
573               :style radio 
574               :selected (eq gnus-score-default-header 'd )]
575              ["Followups to author"
576               (gnus-score-set-default 'gnus-score-default-header 'f)
577               :style radio 
578               :selected (eq gnus-score-default-header 'f )])
579             ("Default type"
580              ["Ask" (gnus-score-set-default 'gnus-score-default-type nil)
581               :style radio 
582               :selected (null gnus-score-default-type)]
583              ;; The `:active' key is commented out in the following,
584              ;; because the GNU Emacs hack to support radio buttons use
585              ;; active to indicate which button is selected.  
586              ["Substring" (gnus-score-set-default 'gnus-score-default-type 's)
587               :style radio 
588               ;; :active (not (memq gnus-score-default-header '(l d)))
589               :selected (eq gnus-score-default-type 's)]
590              ["Regexp" (gnus-score-set-default 'gnus-score-default-type 'r)
591               :style radio
592               ;; :active (not (memq gnus-score-default-header '(l d)))
593               :selected (eq gnus-score-default-type 'r)]
594              ["Exact" (gnus-score-set-default 'gnus-score-default-type 'e)
595               :style radio
596               ;; :active (not (memq gnus-score-default-header '(l d)))
597               :selected (eq gnus-score-default-type 'e)]
598              ["Fuzzy" (gnus-score-set-default 'gnus-score-default-type 'f)
599               :style radio 
600               ;; :active (not (memq gnus-score-default-header '(l d)))
601               :selected (eq gnus-score-default-type 'f)]
602              ["Before date" (gnus-score-set-default 'gnus-score-default-type 'b)
603               :style radio 
604               ;; :active (eq (gnus-score-default-header 'd))
605               :selected (eq gnus-score-default-type 'b)]
606              ["At date" (gnus-score-set-default 'gnus-score-default-type 'n)
607               :style radio 
608               ;; :active (eq (gnus-score-default-header 'd))
609               :selected (eq gnus-score-default-type 'n)]
610              ["After date" (gnus-score-set-default 'gnus-score-default-type 'a)
611               :style radio 
612               ;; :active (eq (gnus-score-default-header 'd))
613               :selected (eq gnus-score-default-type 'a)]
614              ["Less than number"
615               (gnus-score-set-default 'gnus-score-default-type '<)
616               :style radio 
617               ;; :active (eq (gnus-score-default-header 'l))
618               :selected (eq gnus-score-default-type '<)]
619              ["Equal to number"
620               (gnus-score-set-default 'gnus-score-default-type '=)
621               :style radio 
622               ;; :active (eq (gnus-score-default-header 'l))
623               :selected (eq gnus-score-default-type '=)]
624              ["Greater than number" 
625               (gnus-score-set-default 'gnus-score-default-type '>)
626               :style radio 
627               ;; :active (eq (gnus-score-default-header 'l))
628               :selected (eq gnus-score-default-type '>)])
629             ["Default fold" gnus-score-default-fold-toggle
630              :style toggle
631              :selected gnus-score-default-fold]
632             ("Default duration"
633              ["Ask" (gnus-score-set-default 'gnus-score-default-duration nil)
634               :style radio
635               :selected (null gnus-score-default-duration)]
636              ["Permanent"
637               (gnus-score-set-default 'gnus-score-default-duration 'p)
638               :style radio
639               :selected (eq gnus-score-default-duration 'p)]
640              ["Temporary"
641               (gnus-score-set-default 'gnus-score-default-duration 't)
642               :style radio
643               :selected (eq gnus-score-default-duration 't)]
644              ["Immediate" 
645               (gnus-score-set-default 'gnus-score-default-duration 'i)
646               :style radio
647               :selected (eq gnus-score-default-duration 'i)])
648             ))
649
650      (easy-menu-define
651       gnus-summary-article-menu
652       gnus-summary-mode-map
653       ""
654       '("Article"
655         ("Hide"
656          ["All" gnus-article-hide t]
657          ["Headers" gnus-article-hide-headers t]
658          ["Signature" gnus-article-hide-signature t]
659          ["Citation" gnus-article-hide-citation t]
660          ["PGP" gnus-article-hide-pgp t])
661         ("Highlight"
662          ["All" gnus-article-highlight t]
663          ["Headers" gnus-article-highlight-headers t]
664          ["Signature" gnus-article-highlight-signature t]
665          ["Citation" gnus-article-highlight-citation t])
666         ("Date"
667          ["Local" gnus-article-date-local t]
668          ["UT" gnus-article-date-ut t]
669          ["Original" gnus-article-date-original t]
670          ["Lapsed" gnus-article-date-lapsed t])
671         ("Filter"
672          ["Overstrike" gnus-article-treat-overstrike t]
673          ["Word wrap" gnus-article-word-wrap t]
674          ["CR" gnus-article-remove-cr t]
675          ["Show X-Face" gnus-article-display-x-face t]
676          ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
677          ["Rot 13" gnus-summary-caesar-message t]
678          ["Add buttons" gnus-article-add-buttons t]
679          ["Add buttons to head" gnus-article-add-buttons-to-head t]
680          ["Stop page breaking" gnus-summary-stop-page-breaking t]
681          ["Toggle MIME" gnus-summary-toggle-mime t]
682          ["Toggle header" gnus-summary-toggle-header t])
683         ("Output"
684          ["Save in default format" gnus-summary-save-article t]
685          ["Save in file" gnus-summary-save-article-file t]
686          ["Save in Unix mail format" gnus-summary-save-article-mail t]
687          ["Save in MH folder" gnus-summary-save-article-folder t]
688          ["Save in VM folder" gnus-summary-save-article-vm t]
689          ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
690          ["Save body in file" gnus-summary-save-article-body-file t]
691          ["Pipe through a filter" gnus-summary-pipe-output t])
692         ("Backend"
693          ["Respool article" gnus-summary-respool-article t]
694          ["Move article" gnus-summary-move-article t]
695          ["Copy article" gnus-summary-copy-article t]
696          ["Import file" gnus-summary-import-article t]
697          ["Edit article" gnus-summary-edit-article t]
698          ["Delete article" gnus-summary-delete-article t])
699         ("Extract"
700          ["Uudecode" gnus-uu-decode-uu t]
701          ["Uudecode and save" gnus-uu-decode-uu-and-save t]
702          ["Unshar" gnus-uu-decode-unshar t]
703          ["Unshar and save" gnus-uu-decode-unshar-and-save t]
704          ["Save" gnus-uu-decode-save t]
705          ["Binhex" gnus-uu-decode-binhex t])
706         ["Enter digest buffer" gnus-summary-enter-digest-group t]
707         ["Isearch article" gnus-summary-isearch-article t]
708         ["Search all articles" gnus-summary-search-article-forward t]
709         ["Beginning of the article" gnus-summary-beginning-of-article t]
710         ["End of the article" gnus-summary-end-of-article t]
711         ["Fetch parent of article" gnus-summary-refer-parent-article t]
712         ["Fetch referenced articles" gnus-summary-refer-references t]
713         ["Fetch article with id..." gnus-summary-refer-article t]
714         ["Redisplay" gnus-summary-show-article t]))
715
716
717          
718      (easy-menu-define
719       gnus-summary-thread-menu
720       gnus-summary-mode-map
721       ""
722       '("Threads"
723         ["Toggle threading" gnus-summary-toggle-threads t]
724         ["Display hidden thread" gnus-summary-show-thread t]
725         ["Hide thread" gnus-summary-hide-thread t]
726         ["Go to next thread" gnus-summary-next-thread t]
727         ["Go to previous thread" gnus-summary-prev-thread t]
728         ["Go down thread" gnus-summary-down-thread t]
729         ["Go up thread" gnus-summary-up-thread t]
730         ["Mark thread as read" gnus-summary-kill-thread t]
731         ["Lower thread score" gnus-summary-lower-thread t]
732         ["Raise thread score" gnus-summary-raise-thread t]
733         ))
734      (easy-menu-define
735       gnus-summary-post-menu
736       gnus-summary-mode-map
737       ""
738       '("Post"
739         ["Post an article" gnus-summary-post-news t]
740         ["Followup" gnus-summary-followup t]
741         ["Followup and yank" gnus-summary-followup-with-original t]
742         ["Supersede article" gnus-summary-supersede-article t]
743         ["Cancel article" gnus-summary-cancel-article t]
744         ["Reply" gnus-summary-reply t]
745         ["Reply and yank" gnus-summary-reply-with-original t]
746         ["Mail forward" gnus-summary-mail-forward t]
747         ["Post forward" gnus-summary-post-forward t]
748         ["Digest and mail" gnus-uu-digest-mail-forward t]
749         ["Digest and post" gnus-uu-digest-post-forward t]
750         ["Send a mail" gnus-summary-mail-other-window t]
751         ["Reply & followup" gnus-summary-followup-and-reply t]
752         ["Reply & followup and yank" gnus-summary-followup-and-reply-with-original t]
753         ["Uuencode and post" gnus-uu-post-news t]
754         ("Draft"
755          ["Send" gnus-summary-send-draft t]
756          ["Send bounced" gnus-resend-bounced-mail t])
757         ))
758      (run-hooks 'gnus-summary-menu-hook)
759      )))
760
761 (defun gnus-score-set-default (var value)
762   ;; A version of set that updates the GNU Emacs menu-bar.
763   (set var value)
764   ;; It is the message that forces the active status to be updated.
765   (message ""))
766
767 (defvar gnus-score-default-header nil
768   "Default header when entering new scores.
769
770 Should be one of the following symbols.
771
772  a: from
773  s: subject
774  b: body
775  h: head
776  i: message-id
777  t: references
778  x: xref
779  l: lines
780  d: date
781  f: followup
782
783 If nil, the user will be asked for a header.")
784
785 (defvar gnus-score-default-type nil
786   "Default match type when entering new scores.
787
788 Should be one of the following symbols.
789
790  s: substring
791  e: exact string
792  f: fuzzy string
793  r: regexp string
794  b: before date
795  a: at date
796  n: this date
797  <: less than number
798  >: greater than number
799  =: equal to number
800
801 If nil, the user will be asked for a match type.")
802
803 (defvar gnus-score-default-fold nil
804   "Use case folding for new score file entries iff not nil.")
805
806
807 (defun gnus-score-default-fold-toggle ()
808   "Toggle folding for new score file entries."
809   (interactive)
810   (setq gnus-score-default-fold (not gnus-score-default-fold))
811   (if gnus-score-default-fold
812       (message "New score file entries will be case insensitive.")
813     (message "New score file entries will be case sensitive.")))
814
815 (defvar gnus-score-default-duration nil
816   "Default duration of effect when entering new scores.
817
818 Should be one of the following symbols.
819
820  t: temporary
821  p: permanent
822  i: immediate
823
824 If nil, the user will be asked for a duration.")
825
826 (defun gnus-visual-score-map (type)
827   (if t
828       nil
829     (let ((headers '(("author" "from" string)
830                      ("subject" "subject" string)
831                      ("article body" "body" string)
832                      ("article head" "head" string)
833                      ("xref" "xref" string)
834                      ("lines" "lines" number)
835                      ("followups to author" "followup" string)))
836           (types '((number ("less than" <)
837                            ("greater than" >)
838                            ("equal" =))
839                    (string ("substring" s)
840                            ("exact string" e)
841                            ("fuzzy string" f)
842                            ("regexp" r))))
843           (perms '(("temporary" (current-time-string))
844                    ("permanent" nil)
845                    ("immediate" now)))
846           header)
847       (list 
848        (apply 
849         'nconc
850         (list
851          (if (eq type 'lower)
852              "Lower score"
853            "Increase score"))
854         (let (outh)
855           (while headers
856             (setq header (car headers))
857             (setq outh 
858                   (cons 
859                    (apply 
860                     'nconc
861                     (list (car header))
862                     (let ((ts (cdr (assoc (nth 2 header) types)))
863                           outt)
864                       (while ts
865                         (setq outt
866                               (cons 
867                                (apply 
868                                 'nconc
869                                 (list (car (car ts)))
870                                 (let ((ps perms)
871                                       outp)
872                                   (while ps
873                                     (setq outp
874                                           (cons
875                                            (vector
876                                             (car (car ps)) 
877                                             (list
878                                              'gnus-summary-score-entry
879                                              (nth 1 header)
880                                              (if (or (string= (nth 1 header) 
881                                                               "head")
882                                                      (string= (nth 1 header)
883                                                               "body"))
884                                                  ""
885                                                (list 'gnus-summary-header 
886                                                      (nth 1 header)))
887                                              (list 'quote (nth 1 (car ts)))
888                                              (list 'gnus-score-default nil)
889                                              (nth 1 (car ps))
890                                              t)
891                                             t)
892                                            outp))
893                                     (setq ps (cdr ps)))
894                                   (list (nreverse outp))))
895                                outt))
896                         (setq ts (cdr ts)))
897                       (list (nreverse outt))))
898                    outh))
899             (setq headers (cdr headers)))
900           (list (nreverse outh))))))))
901  
902 ;; Article buffer
903 (defun gnus-article-make-menu-bar ()
904   (gnus-visual-turn-off-edit-menu 'summary)
905   (or
906    (boundp 'gnus-article-article-menu)
907    (progn
908      (easy-menu-define
909       gnus-article-article-menu
910       gnus-article-mode-map
911       ""
912       '("Article"
913         ["Scroll forwards" gnus-article-next-page t]
914         ["Scroll backwards" gnus-article-prev-page t]
915         ["Show summary" gnus-article-show-summary t]
916         ["Fetch Message-ID at point" gnus-article-refer-article t]
917         ["Mail to address at point" gnus-article-mail t]
918         ))
919
920      (easy-menu-define
921       gnus-article-treatment-menu
922       gnus-article-mode-map
923       ""
924       '("Treatment"
925         ["Hide headers" gnus-article-hide-headers t]
926         ["Hide signature" gnus-article-hide-signature t]
927         ["Hide citation" gnus-article-hide-citation t]
928         ["Treat overstrike" gnus-article-treat-overstrike t]
929         ["Remove carriage return" gnus-article-remove-cr t]
930         ["Remove quoted-unreadable" gnus-article-de-quoted-unreadable t]
931         ))
932      (run-hooks 'gnus-article-menu-hook)
933      )))
934
935 ;;;
936 ;;; summary highlights
937 ;;;
938
939 (defun gnus-highlight-selected-summary ()
940   ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
941   ;; Highlight selected article in summary buffer
942   (if gnus-summary-selected-face
943       (save-excursion
944         (let* ((beg (progn (beginning-of-line) (point)))
945                (end (progn (end-of-line) (point)))
946                ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
947                (from (if (get-text-property beg 'mouse-face) 
948                          beg
949                        (1+ (or (next-single-property-change 
950                                 beg 'mouse-face nil end) 
951                                beg))))
952                (to (1- (or (next-single-property-change
953                             from 'mouse-face nil end)
954                            end))))
955           ;; If no mouse-face prop on line (e.g. xemacs) we 
956           ;; will have to = from = end, so we highlight the
957           ;; entire line instead.
958           (if (= (+ to 2) from)
959               (progn
960                 (setq from beg)
961                 (setq to end)))
962           (if gnus-newsgroup-selected-overlay
963               (gnus-move-overlay gnus-newsgroup-selected-overlay 
964                                  from to (current-buffer))
965             (setq gnus-newsgroup-selected-overlay (gnus-make-overlay from to))
966             (gnus-overlay-put gnus-newsgroup-selected-overlay 'face 
967                               gnus-summary-selected-face))))))
968
969 ;; New implementation by Christian Limpach <Christian.Limpach@nice.ch>.
970 (defun gnus-summary-highlight-line ()
971   "Highlight current line according to `gnus-summary-highlight'."
972   (let* ((list gnus-summary-highlight)
973          (p (point))
974          (end (progn (end-of-line) (point)))
975          ;; now find out where the line starts and leave point there.
976          (beg (progn (beginning-of-line) (point)))
977          (score (or (cdr (assq (or (gnus-summary-article-number)
978                                    gnus-current-article)
979                                gnus-newsgroup-scored))
980                     gnus-summary-default-score 0))
981          (default gnus-summary-default-score)
982          (mark (gnus-summary-article-mark))
983          (inhibit-read-only t))
984     (while (and list (not (eval (car (car list)))))
985       (setq list (cdr list)))
986     (let ((face (and list (cdr (car list)))))
987       (or (null mark)
988           (eq face (get-text-property beg 'face))
989           (put-text-property beg end 'face 
990                              (if (boundp face) (symbol-value face) face))))
991     (goto-char p)))
992
993 ;;;
994 ;;; gnus-carpal
995 ;;;
996
997 (defvar gnus-carpal-group-buffer-buttons
998   '(("next" . gnus-group-next-unread-group)
999     ("prev" . gnus-group-prev-unread-group)
1000     ("read" . gnus-group-read-group)
1001     ("select" . gnus-group-select-group)
1002     ("catch up" . gnus-group-catchup-current)
1003     ("new news" . gnus-group-get-new-news-this-group)
1004     ("toggle sub" . gnus-group-unsubscribe-current-group)
1005     ("subscribe" . gnus-group-unsubscribe-group)
1006     ("kill" . gnus-group-kill-group)
1007     ("yank" . gnus-group-yank-group)
1008     ("describe" . gnus-group-describe-group)
1009     "list"
1010     ("subscribed" . gnus-group-list-groups)
1011     ("all" . gnus-group-list-all-groups)
1012     ("killed" . gnus-group-list-killed)
1013     ("zombies" . gnus-group-list-zombies)
1014     ("matching" . gnus-group-list-matching)
1015     ("post" . gnus-group-post-news)
1016     ("mail" . gnus-group-mail)
1017     ("rescan" . gnus-group-get-new-news)
1018     ("browse foreign" . gnus-group-browse-foreign)
1019     ("exit" . gnus-group-exit)))
1020
1021 (defvar gnus-carpal-summary-buffer-buttons
1022   '("mark" 
1023     ("read" . gnus-summary-mark-as-read-forward)
1024     ("tick" . gnus-summary-tick-article-forward)
1025     ("clear" . gnus-summary-clear-mark-forward)
1026     ("expirable" . gnus-summary-mark-as-expirable)
1027     "move"
1028     ("scroll" . gnus-summary-next-page)
1029     ("next unread" . gnus-summary-next-unread-article)
1030     ("prev unread" . gnus-summary-prev-unread-article)
1031     ("first" . gnus-summary-first-unread-article)
1032     ("best" . gnus-summary-best-unread-article)
1033     "article"
1034     ("headers" . gnus-summary-toggle-header)
1035     ("uudecode" . gnus-uu-decode-uu)
1036     ("enter digest" . gnus-summary-enter-digest-group)
1037     ("fetch parent" . gnus-summary-refer-parent-article)
1038     "mail"
1039     ("move" . gnus-summary-move-article)
1040     ("copy" . gnus-summary-copy-article)
1041     ("respool" . gnus-summary-respool-article)
1042     "threads"
1043     ("lower" . gnus-summary-lower-thread)
1044     ("kill" . gnus-summary-kill-thread)
1045     "post"
1046     ("post" . gnus-summary-post-news)
1047     ("mail" . gnus-summary-mail)
1048     ("followup" . gnus-summary-followup-with-original)
1049     ("reply" . gnus-summary-reply-with-original)
1050     ("cancel" . gnus-summary-cancel-article)
1051     "misc"
1052     ("exit" . gnus-summary-exit)
1053     ("fed up" . gnus-summary-catchup-and-goto-next-group)))
1054
1055 (defvar gnus-carpal-server-buffer-buttons 
1056   '(("add" . gnus-server-add-server)
1057     ("browse" . gnus-server-browse-server)
1058     ("list" . gnus-server-list-servers)
1059     ("kill" . gnus-server-kill-server)
1060     ("yank" . gnus-server-yank-server)
1061     ("copy" . gnus-server-copy-server)
1062     ("exit" . gnus-server-exit)))
1063
1064 (defvar gnus-carpal-browse-buffer-buttons
1065   '(("subscribe" . gnus-browse-unsubscribe-current-group)
1066     ("exit" . gnus-browse-exit)))
1067
1068 (defvar gnus-carpal-group-buffer "*Carpal Group*")
1069 (defvar gnus-carpal-summary-buffer "*Carpal Summary*")
1070 (defvar gnus-carpal-server-buffer "*Carpal Server*")
1071 (defvar gnus-carpal-browse-buffer "*Carpal Browse*")
1072
1073 (defvar gnus-carpal-attached-buffer nil)
1074
1075 (defvar gnus-carpal-mode-hook nil
1076   "*Hook run in carpal mode buffers.")
1077
1078 (defvar gnus-carpal-button-face 'bold
1079   "*Face used on carpal buttons.")
1080
1081 (defvar gnus-carpal-header-face 'bold-italic
1082   "*Face used on carpal buffer headers.")
1083
1084 (defvar gnus-carpal-mode-map nil)
1085 (put 'gnus-carpal-mode 'mode-class 'special)
1086
1087 (if gnus-carpal-mode-map
1088     nil
1089   (setq gnus-carpal-mode-map (make-keymap))
1090   (suppress-keymap gnus-carpal-mode-map)
1091   (define-key gnus-carpal-mode-map " " 'gnus-carpal-select)
1092   (define-key gnus-carpal-mode-map "\r" 'gnus-carpal-select)
1093   (define-key gnus-carpal-mode-map gnus-mouse-2 'gnus-carpal-mouse-select))
1094
1095 (defun gnus-carpal-mode ()
1096   "Major mode for clicking buttons.
1097
1098 All normal editing commands are switched off.
1099 \\<gnus-carpal-mode-map>
1100 The following commands are available:
1101
1102 \\{gnus-carpal-mode-map}"
1103   (interactive)
1104   (kill-all-local-variables)
1105   (setq mode-line-modified "-- ")
1106   (setq major-mode 'gnus-carpal-mode)
1107   (setq mode-name "Gnus Carpal")
1108   (setq mode-line-process nil)
1109   (use-local-map gnus-carpal-mode-map)
1110   (buffer-disable-undo (current-buffer))
1111   (setq buffer-read-only t)
1112   (make-local-variable 'gnus-carpal-attached-buffer)
1113   (run-hooks 'gnus-carpal-mode-hook))
1114
1115 (defun gnus-carpal-setup-buffer (type)
1116   (let ((buffer (symbol-value (intern (format "gnus-carpal-%s-buffer" type)))))
1117     (if (get-buffer buffer)
1118         ()
1119       (save-excursion
1120         (set-buffer (get-buffer-create buffer))
1121         (gnus-carpal-mode)
1122         (setq gnus-carpal-attached-buffer 
1123               (intern (format "gnus-%s-buffer" type)))
1124         (gnus-add-current-to-buffer-list)
1125         (let ((buttons (symbol-value 
1126                         (intern (format "gnus-carpal-%s-buffer-buttons"
1127                                         type))))
1128               (buffer-read-only nil)
1129               button)
1130           (while buttons
1131             (setq button (car buttons)
1132                   buttons (cdr buttons))
1133             (if (stringp button)
1134                 (set-text-properties
1135                  (point)
1136                  (prog2 (insert button) (point) (insert " "))
1137                  (list 'face gnus-carpal-header-face))
1138               (set-text-properties
1139                (point)
1140                (prog2 (insert (car button)) (point) (insert " "))
1141                (list 'gnus-callback (cdr button)
1142                      'face gnus-carpal-button-face
1143                      'mouse-face 'highlight))))
1144           (let ((fill-column (- (window-width) 2)))
1145             (fill-region (point-min) (point-max)))
1146           (set-window-point (get-buffer-window (current-buffer)) 
1147                             (point-min)))))))
1148
1149 (defun gnus-carpal-select ()
1150   "Select the button under point."
1151   (interactive)
1152   (let ((func (get-text-property (point) 'gnus-callback)))
1153     (if (null func)
1154         ()
1155       (pop-to-buffer (symbol-value gnus-carpal-attached-buffer))
1156       (call-interactively func))))
1157
1158 (defun gnus-carpal-mouse-select (event)
1159   "Select the button under the mouse pointer."
1160   (interactive "e")
1161   (mouse-set-point event)
1162   (gnus-carpal-select))
1163
1164 ;;; 
1165 ;;; article highlights
1166 ;;;
1167
1168 ;; Written by Per Abrahamsen <abraham@iesd.auc.dk>.
1169
1170 ;;; Internal Variables:
1171
1172 (defvar gnus-button-regexp nil)
1173 ;; Regexp matching any of the regexps from `gnus-button-alist'.
1174
1175 (defvar gnus-button-last nil)
1176 ;; The value of `gnus-button-alist' when `gnus-button-regexp' was build.
1177
1178 ;;; Commands:
1179
1180 (defun gnus-article-push-button (event)
1181   "Check text under the mouse pointer for a callback function.
1182 If the text under the mouse pointer has a `gnus-callback' property,
1183 call it with the value of the `gnus-data' text property."
1184   (interactive "e")
1185   (set-buffer (window-buffer (posn-window (event-start event))))
1186   (let* ((pos (posn-point (event-start event)))
1187          (data (get-text-property pos 'gnus-data))
1188          (fun (get-text-property pos 'gnus-callback)))
1189     (if fun (funcall fun data))))
1190
1191 (defun gnus-article-press-button ()
1192   "Check text at point for a callback function.
1193 If the text at point has a `gnus-callback' property,
1194 call it with the value of the `gnus-data' text property."
1195   (interactive)
1196   (let* ((data (get-text-property (point) 'gnus-data))
1197          (fun (get-text-property (point) 'gnus-callback)))
1198     (if fun (funcall fun data))))
1199
1200 ;; Suggested by Arne Elofsson <arne@hodgkin.mbi.ucla.edu>
1201 (defun gnus-article-next-button ()
1202   "Move point to next button."
1203   (interactive)
1204   (if (get-text-property (point) 'gnus-callback)
1205       (goto-char (next-single-property-change (point) 'gnus-callback
1206                                               nil (point-max))))
1207   (let ((pos (next-single-property-change (point) 'gnus-callback)))
1208     (if pos
1209         (goto-char pos)
1210       (setq pos (next-single-property-change (point-min) 'gnus-callback))
1211       (if pos
1212           (goto-char pos)
1213         (error "No buttons found")))))
1214
1215 (defun gnus-article-highlight (&optional force)
1216   "Highlight current article.
1217 This function calls `gnus-article-highlight-headers',
1218 `gnus-article-highlight-citation', 
1219 `gnus-article-highlight-signature', and `gnus-article-add-buttons' to
1220 do the highlighting.  See the documentation for those functions."
1221   (interactive (list 'force))
1222   (gnus-article-highlight-headers)
1223   (gnus-article-highlight-citation force)
1224   (gnus-article-highlight-signature)
1225   (gnus-article-add-buttons force)
1226   (gnus-article-add-buttons-to-head))
1227
1228 (defun gnus-article-highlight-some (&optional force)
1229   "Highlight current article.
1230 This function calls `gnus-article-highlight-headers',
1231 `gnus-article-highlight-signature', and `gnus-article-add-buttons' to
1232 do the highlighting.  See the documentation for those functions."
1233   (interactive (list 'force))
1234   (gnus-article-highlight-headers)
1235   (gnus-article-highlight-signature)
1236   (gnus-article-add-buttons))
1237
1238 (defun gnus-article-hide (&optional force)
1239   "Hide current article.
1240 This function calls `gnus-article-hide-headers',
1241 `gnus-article-hide-citation-maybe', and `gnus-article-hide-signature'
1242 to do the hiding.  See the documentation for those functions." 
1243   (interactive (list 'force))
1244   (gnus-article-hide-headers)
1245   (gnus-article-hide-citation-maybe force)
1246   (gnus-article-hide-signature))
1247
1248 (defun gnus-article-highlight-headers ()
1249   "Highlight article headers as specified by `gnus-header-face-alist'."
1250   (interactive)
1251   (save-excursion
1252     (set-buffer gnus-article-buffer)
1253     (goto-char (point-min))
1254     (if (not (search-forward "\n\n" nil t))
1255         ()
1256       (beginning-of-line 0)
1257       (while (not (bobp))
1258         (let ((alist gnus-header-face-alist)
1259               (buffer-read-only nil)
1260               (case-fold-search t)
1261               (end (point))
1262               (inhibit-point-motion-hooks t)
1263               begin entry regexp header-face field-face 
1264               header-found field-found)
1265           (re-search-backward "^[^ \t]" nil t)
1266           (setq begin (point))
1267           (while alist
1268             (setq entry (car alist)
1269                   regexp (nth 0 entry)
1270                   header-face (nth 1 entry)
1271                   field-face (nth 2 entry)
1272                   alist (cdr alist))
1273             (if (looking-at regexp)
1274                 (let ((from (point)))
1275                   (skip-chars-forward "^:\n")
1276                   (and (not header-found)
1277                        header-face
1278                        (progn
1279                          (put-text-property  from (point) 'face header-face)
1280                          (setq header-found t)))
1281                   (and (not field-found)
1282                        field-face
1283                        (progn 
1284                          (skip-chars-forward ": \t")
1285                          (let ((from (point)))
1286                            (goto-char end)
1287                            (skip-chars-backward " \t")
1288                            (put-text-property from (point) 'face field-face)
1289                            (setq field-found t))))))
1290             (goto-char begin)))))))
1291
1292 (defun gnus-article-highlight-signature ()
1293   "Highlight the signature in an article.
1294 It does this by highlighting everything after
1295 `gnus-signature-separator' using `gnus-signature-face'." 
1296   (interactive)
1297   (save-excursion
1298     (set-buffer gnus-article-buffer)
1299     (let ((buffer-read-only nil)
1300           (inhibit-point-motion-hooks t))
1301       (goto-char (point-max))
1302       (and (re-search-backward gnus-signature-separator nil t)
1303            gnus-signature-face
1304            (let ((start (match-beginning 0))
1305                  (end (match-end 0)))
1306              (gnus-article-add-button start end 'gnus-signature-toggle end)
1307              (gnus-overlay-put (gnus-make-overlay end (point-max))
1308                                'face gnus-signature-face))))))
1309
1310 (defun gnus-article-hide-signature ()
1311   "Hide the signature in an article.
1312 It does this by making everything after `gnus-signature-separator' invisible."
1313   (interactive)
1314   (save-excursion
1315     (set-buffer gnus-article-buffer)
1316     (let ((buffer-read-only nil))
1317       (goto-char (point-max))
1318       (and (re-search-backward gnus-signature-separator nil t)
1319            gnus-signature-face
1320            (add-text-properties (match-end 0) (point-max)
1321                                 gnus-hidden-properties)))))
1322
1323 (defun gnus-article-add-buttons (&optional force)
1324   "Find external references in the article and make buttons of them.
1325 \"External references\" are things like Message-IDs and URLs, as
1326 specified by `gnus-button-alist'."
1327   (interactive (list 'force))
1328   (if (eq gnus-button-last gnus-button-alist)
1329       ()
1330     (setq gnus-button-regexp (mapconcat 'car gnus-button-alist  "\\|")
1331           gnus-button-last gnus-button-alist))
1332   (save-excursion
1333     (set-buffer gnus-article-buffer)
1334     (gnus-cite-parse-maybe force)
1335     (let ((buffer-read-only nil)
1336           (inhibit-point-motion-hooks t)
1337           (case-fold-search t))
1338       (goto-char (point-min))
1339       (or (search-forward "\n\n" nil t)
1340           (goto-char (point-max)))
1341       (while (re-search-forward gnus-button-regexp nil t)
1342         (goto-char (match-beginning 0))
1343         (let* ((from (point))
1344                (entry (gnus-button-entry))
1345                (start (and entry (match-beginning (nth 1 entry))))
1346                (end (and entry (match-end (nth 1 entry))))
1347                (form (nth 2 entry)))
1348           (if (not entry)
1349               ()
1350             (goto-char (match-end 0))
1351             (if (eval form)
1352                 (gnus-article-add-button 
1353                  start end 'gnus-button-push
1354                  (set-marker (make-marker) from)))))))))
1355
1356 ;; Add buttons to the head of an article.
1357 (defun gnus-article-add-buttons-to-head ()
1358   "Add buttons to the head of the article."
1359   (interactive)
1360   (save-excursion
1361     (set-buffer gnus-article-buffer)
1362     (let ((buffer-read-only nil)
1363           (inhibit-point-motion-hooks t)
1364           (case-fold-search t)
1365           (alist gnus-header-button-alist)
1366           entry beg end)
1367       (gnus-narrow-to-headers)
1368       (while alist
1369         ;; Each alist entry.
1370         (setq entry (car alist)
1371               alist (cdr alist))
1372         (goto-char (point-min))
1373         (while (re-search-forward (car entry) nil t)
1374           ;; Each header matching the entry.
1375           (setq beg (match-beginning 0))
1376           (setq end (or (and (re-search-forward "^[^ \t]" nil t)
1377                              (match-beginning 0))
1378                         (point-max)))
1379           (goto-char beg)
1380           (while (re-search-forward (nth 1 entry) end t)
1381             ;; Each match within a header.
1382             (let* ((from (match-beginning 0))
1383                    (entry (cdr entry))
1384                    (start (match-beginning (nth 1 entry)))
1385                    (end (match-end (nth 1 entry)))
1386                    (form (nth 2 entry)))
1387               (goto-char (match-end 0))
1388               (and (eval form)
1389                    (gnus-article-add-button 
1390                     start end (nth 3 entry)
1391                     (buffer-substring (match-beginning (nth 4 entry))
1392                                       (match-end (nth 4 entry)))))))
1393           (goto-char end))))
1394     (widen)))
1395
1396 (defun gnus-netscape-open-url (url)
1397   "Open URL in netscape, or start new scape with URL."
1398   (let ((process
1399          (start-process 
1400           (concat "netscape " url) nil
1401           "netscape" "-remote"  (concat "openUrl(" url ")'"))))
1402     (set-process-sentinel process 
1403                           (` (lambda (process change)
1404                                (or (eq (process-exit-status process) 0)
1405                                    (gnus-netscape-start-url (, url))))))))
1406
1407 (defun gnus-netscape-start-url (url)
1408   "Start netscape with URL."
1409   (start-process (concat "netscape" url) nil "netscape" url))
1410
1411 ;;; External functions:
1412
1413 (defun gnus-article-add-button (from to fun &optional data)
1414   "Create a button between FROM and TO with callback FUN and data DATA."
1415   (and gnus-article-button-face
1416        (gnus-overlay-put (gnus-make-overlay from to)
1417                          'face gnus-article-button-face))
1418   (add-text-properties 
1419    from to
1420    (nconc (and gnus-article-mouse-face
1421                (list 'mouse-face gnus-article-mouse-face))
1422           (list 'gnus-callback fun)
1423           (and data (list 'gnus-data data)))))
1424
1425 ;;; Internal functions:
1426
1427 (defun gnus-signature-toggle (end)
1428   (save-excursion
1429     (set-buffer gnus-article-buffer)
1430     (let ((buffer-read-only nil))
1431       (if (get-text-property end 'invisible)
1432           (remove-text-properties end (point-max) gnus-hidden-properties)
1433         (add-text-properties end (point-max) gnus-hidden-properties)))))
1434
1435 ;see gnus-cus.el
1436 ;(defun gnus-make-face (color)
1437 ;  ;; Create entry for face with COLOR.
1438 ;  (if gnus-make-foreground
1439 ;      (custom-face-lookup color nil nil nil nil nil)
1440 ;    (custom-face-lookup nil color nil nil nil nil)))
1441
1442 (defun gnus-button-entry ()
1443   ;; Return the first entry in `gnus-button-alist' matching this place.
1444   (let ((alist gnus-button-alist)
1445         (entry nil))
1446     (while alist
1447       (setq entry (car alist)
1448             alist (cdr alist))
1449       (if (looking-at (car entry))
1450           (setq alist nil)
1451         (setq entry nil)))
1452     entry))
1453
1454 (defun gnus-button-push (marker)
1455   ;; Push button starting at MARKER.
1456   (save-excursion
1457     (set-buffer gnus-article-buffer)
1458     (goto-char marker)
1459     (let* ((entry (gnus-button-entry))
1460            (inhibit-point-motion-hooks t)
1461            (fun (nth 3 entry))
1462            (args (mapcar (lambda (group) 
1463                            (let ((string (buffer-substring
1464                                           (match-beginning group)
1465                                           (match-end group))))
1466                              (set-text-properties 0 (length string) nil string)
1467                              string))
1468                          (nthcdr 4 entry))))
1469       (cond ((fboundp fun)
1470              (apply fun args))
1471             ((and (boundp fun)
1472                   (fboundp (symbol-value fun)))
1473              (apply (symbol-value fun) args))
1474             (t
1475              (message "You must define `%S' to use this button"
1476                       (cons fun args)))))))
1477
1478 (defun gnus-button-message-id (message-id)
1479   ;; Fetch MESSAGE-ID.
1480   (save-excursion
1481     (set-buffer gnus-summary-buffer)
1482     (gnus-summary-refer-article message-id)))
1483
1484 (defun gnus-button-mailto (address)
1485   ;; Mail to ADDRESS.
1486   (gnus-new-mail address))
1487
1488 (defun gnus-button-reply (address)
1489   ;; Reply to ADDRESS.
1490   (gnus-mail-reply t address))
1491
1492 ;;; Compatibility Functions:
1493
1494 (or (fboundp 'rassoc)
1495     ;; Introduced in Emacs 19.29.
1496     (defun rassoc (elt list)
1497       "Return non-nil if ELT is `equal' to the cdr of an element of LIST.
1498 The value is actually the element of LIST whose cdr is ELT."
1499       (let (result)
1500         (while list
1501           (setq result (car list))
1502           (if (equal (cdr result) elt)
1503               (setq list nil)
1504             (setq result nil
1505                   list (cdr list))))
1506         result)))
1507
1508 ; (require 'gnus-cus)
1509 (gnus-ems-redefine)
1510 (provide 'gnus-vis)
1511
1512 ;;; gnus-vis.el ends here