*** empty log message ***
[gnus] / lisp / gnus-xmas.el
1 ;;; gnus-xmas.el --- Gnus functions for XEmacs
2 ;; Copyright (C) 1995,96 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Keywords: news
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;;; Code:
27
28 (require 'text-props)
29 (defvar menu-bar-mode (featurep 'menubar))
30 (require 'messagexmas)
31
32 (defvar gnus-xmas-glyph-directory nil
33   "*Directory where Gnus logos and icons are located.
34 If this variable is nil, Gnus will try to locate the directory
35 automatically.")
36
37 (defvar gnus-xmas-logo-color-alist
38   '((flame "#cc3300" "#ff2200")
39     (pine "#c0cc93" "#f8ffb8")
40     (moss "#a1cc93" "#d2ffb8")
41     (irish "#04cc90" "#05ff97")
42     (sky "#049acc" "#05deff")
43     (tin "#6886cc" "#82b6ff")
44     (velvet "#7c68cc" "#8c82ff")
45     (grape "#b264cc" "#cf7df")
46     (labia "#cc64c2" "#fd7dff")
47     (berry "#cc6485" "#ff7db5")
48     (neutral "#b4b4b4" "#878787")
49     (september "#bf9900" "#ffcc00"))
50   "Color alist used for the Gnus logo.")
51
52 (defvar gnus-xmas-logo-color-style 'flame
53   "Color styles used for the Gnus logo.")
54
55 (defvar gnus-xmas-logo-colors
56   (cdr (assq gnus-xmas-logo-color-style gnus-xmas-logo-color-alist))
57   "Colors used for the Gnus logo.")
58
59 (defvar gnus-article-x-face-command
60   (if (featurep 'xface)
61       'gnus-xmas-article-display-xface
62     "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -")
63   "String or function to be executed to display an X-Face header.
64 If it is a string, the command will be executed in a sub-shell
65 asynchronously.  The compressed face will be piped to this command.")
66
67 ;;; Internal variables.
68
69 ;; Don't warn about these undefined variables.
70
71 (defvar gnus-group-mode-hook)
72 (defvar gnus-summary-mode-hook)
73 (defvar gnus-article-mode-hook)
74
75 ;;defined in gnus.el
76 (defvar gnus-active-hashtb)
77 (defvar gnus-article-buffer)
78 (defvar gnus-auto-center-summary)
79 (defvar gnus-buffer-list)
80 (defvar gnus-current-headers)
81 (defvar gnus-level-killed)
82 (defvar gnus-level-zombie)
83 (defvar gnus-newsgroup-bookmarks)
84 (defvar gnus-newsgroup-dependencies)
85 (defvar gnus-newsgroup-selected-overlay)
86 (defvar gnus-newsrc-hashtb)
87 (defvar gnus-read-mark)
88 (defvar gnus-refer-article-method)
89 (defvar gnus-reffed-article-number)
90 (defvar gnus-unread-mark)
91 (defvar gnus-version)
92 (defvar gnus-view-pseudos)
93 (defvar gnus-view-pseudos-separately)
94 (defvar gnus-visual)
95 (defvar gnus-zombie-list)
96 ;;defined in gnus-msg.el
97 (defvar gnus-article-copy)
98 (defvar gnus-check-before-posting)
99 ;;defined in gnus-vis.el
100 (defvar gnus-article-button-face)
101 (defvar gnus-article-mouse-face)
102 (defvar gnus-summary-selected-face)
103 (defvar gnus-group-reading-menu)
104 (defvar gnus-group-group-menu)
105 (defvar gnus-group-misc-menu)
106 (defvar gnus-summary-article-menu)
107 (defvar gnus-summary-thread-menu)
108 (defvar gnus-summary-misc-menu)
109 (defvar gnus-summary-post-menu)
110 (defvar gnus-summary-kill-menu)
111 (defvar gnus-article-article-menu)
112 (defvar gnus-article-treatment-menu)
113 (defvar gnus-mouse-2)
114 (defvar standard-display-table)
115 (defvar gnus-tree-minimize-window)
116
117 (defun gnus-xmas-set-text-properties (start end props &optional buffer)
118   "You should NEVER use this function.  It is ideologically blasphemous.
119 It is provided only to ease porting of broken FSF Emacs programs."
120   (if (stringp buffer)
121       nil
122     (map-extents (lambda (extent ignored)
123                    (remove-text-properties 
124                     start end
125                     (list (extent-property extent 'text-prop) nil)
126                     buffer))
127                  buffer start end nil nil 'text-prop)
128     (gnus-add-text-properties start end props buffer)))
129
130 (defun gnus-xmas-highlight-selected-summary ()
131   ;; Highlight selected article in summary buffer
132   (when gnus-summary-selected-face
133     (when gnus-newsgroup-selected-overlay
134       (delete-extent gnus-newsgroup-selected-overlay))
135     (setq gnus-newsgroup-selected-overlay 
136           (make-extent (gnus-point-at-bol) (gnus-point-at-eol)))
137     (set-extent-face gnus-newsgroup-selected-overlay
138                      gnus-summary-selected-face)))
139
140 (defun gnus-xmas-summary-recenter ()
141   "\"Center\" point in the summary window.
142 If `gnus-auto-center-summary' is nil, or the article buffer isn't
143 displayed, no centering will be performed."
144   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
145   ;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
146   (when gnus-auto-center-summary
147     (let* ((height (if (fboundp 'window-displayed-height)
148                        (window-displayed-height)
149                      (- (window-height) 2)))
150            (top (cond ((< height 4) 0)
151                       ((< height 7) 1)
152                       (t 2)))
153            (bottom (save-excursion (goto-char (point-max))
154                                    (forward-line (- height))
155                                    (point)))
156            (window (get-buffer-window (current-buffer))))
157       (when (get-buffer-window gnus-article-buffer)
158         ;; Only do recentering when the article buffer is displayed,
159         ;; Set the window start to either `bottom', which is the biggest
160         ;; possible valid number, or the second line from the top,
161         ;; whichever is the least.
162         (set-window-start
163          window (min bottom (save-excursion (forward-line (- top)) (point)))))
164       ;; Do horizontal recentering while we're at it.
165       (when (and (get-buffer-window (current-buffer) t)
166                  (not (eq gnus-auto-center-summary 'vertical)))
167         (let ((selected (selected-window)))
168           (select-window (get-buffer-window (current-buffer) t))
169           (gnus-summary-position-point)
170           (gnus-horizontal-recenter)
171           (select-window selected))))))
172
173 (defun gnus-xmas-add-hook (hook function &optional append local)
174   (add-hook hook function))
175
176 (defun gnus-xmas-add-text-properties (start end props &optional object)
177   (add-text-properties start end props object)
178   (put-text-property start end 'start-closed nil object))
179
180 (defun gnus-xmas-put-text-property (start end prop value &optional object)
181   (put-text-property start end prop value object)
182   (put-text-property start end 'start-closed nil object))
183
184 (defun gnus-xmas-extent-start-open (point)
185   (map-extents (lambda (extent arg)
186                  (set-extent-property extent 'start-open t))
187                nil point (min (1+ (point)) (point-max))))
188                   
189 (defun gnus-xmas-article-push-button (event)
190   "Check text under the mouse pointer for a callback function.
191 If the text under the mouse pointer has a `gnus-callback' property,
192 call it with the value of the `gnus-data' text property."
193   (interactive "e")
194   (set-buffer (window-buffer (event-window event)))
195   (let* ((pos (event-closest-point event))
196          (data (get-text-property pos 'gnus-data))
197          (fun (get-text-property pos 'gnus-callback)))
198     (when fun
199       (funcall fun data))))
200
201 (defun gnus-xmas-move-overlay (extent start end &optional buffer)
202   (set-extent-endpoints extent start end))
203
204 ;; Fixed by Christopher Davis <ckd@loiosh.kei.com>.
205 (defun gnus-xmas-article-add-button (from to fun &optional data)
206   "Create a button between FROM and TO with callback FUN and data DATA."
207   (when gnus-article-button-face
208     (gnus-overlay-put (gnus-make-overlay from to)
209                       'face gnus-article-button-face))
210   (gnus-add-text-properties 
211    from to
212    (nconc
213     (and gnus-article-mouse-face
214          (list 'mouse-face gnus-article-mouse-face))
215     (list 'gnus-callback fun)
216     (and data (list 'gnus-data data))
217     (list 'highlight t))))
218
219 (defun gnus-xmas-window-top-edge (&optional window)
220   (nth 1 (window-pixel-edges window)))
221
222 (defun gnus-xmas-tree-minimize ()
223   (when (and gnus-tree-minimize-window
224              (not (one-window-p)))
225     (let* ((window-min-height 2)
226            (height (1+ (count-lines (point-min) (point-max))))
227            (min (max (1- window-min-height) height))
228            (tot (if (numberp gnus-tree-minimize-window)
229                     (min gnus-tree-minimize-window min)
230                   min))
231            (win (get-buffer-window (current-buffer)))
232            (wh (and win (1- (window-height win)))))
233       (when (and win
234                  (not (eq tot wh)))
235         (let ((selected (selected-window)))
236           (select-window win)
237           (enlarge-window (- tot wh))
238           (select-window selected))))))
239
240 ;; Select the lowest window on the frame.
241 (defun gnus-xmas-appt-select-lowest-window ()
242   (let* ((lowest-window (selected-window))
243          (bottom-edge (car (cdr (cdr (cdr (window-pixel-edges))))))
244          (last-window (previous-window))
245          (window-search t))
246     (while window-search
247       (let* ((this-window (next-window))
248              (next-bottom-edge (car (cdr (cdr (cdr 
249                                                (window-pixel-edges 
250                                                 this-window)))))))
251         (when (< bottom-edge next-bottom-edge)
252           (setq bottom-edge next-bottom-edge)
253           (setq lowest-window this-window))
254
255         (select-window this-window)
256         (when (eq last-window this-window)
257           (select-window lowest-window)
258           (setq window-search nil))))))
259
260 (defmacro gnus-xmas-menu-add (type &rest menus)
261   `(gnus-xmas-menu-add-1 ',type ',menus))
262 (put 'gnus-xmas-menu-add 'lisp-indent-function 1)
263 (put 'gnus-xmas-menu-add 'lisp-indent-hook 1)
264
265 (defun gnus-xmas-menu-add-1 (type menus)
266   (when (and menu-bar-mode
267              (gnus-visual-p (intern (format "%s-menu" type)) 'menu))
268     (while menus
269       (easy-menu-add (symbol-value (pop menus))))))
270
271 (defun gnus-xmas-group-menu-add ()
272   (gnus-xmas-menu-add group
273                       gnus-group-reading-menu gnus-group-group-menu gnus-group-misc-menu))
274
275 (defun gnus-xmas-summary-menu-add ()
276   (gnus-xmas-menu-add summary
277                       gnus-summary-misc-menu gnus-summary-kill-menu
278                       gnus-summary-article-menu gnus-summary-thread-menu
279                       gnus-summary-post-menu ))
280
281 (defun gnus-xmas-article-menu-add ()
282   (gnus-xmas-menu-add article
283                       gnus-article-article-menu gnus-article-treatment-menu))
284
285 (defun gnus-xmas-score-menu-add ()
286   (gnus-xmas-menu-add score
287                       gnus-score-menu))
288
289 (defun gnus-xmas-pick-menu-add ()
290   (gnus-xmas-menu-add pick
291                       gnus-pick-menu))
292
293 (defun gnus-xmas-binary-menu-add ()
294   (gnus-xmas-menu-add binary
295                       gnus-binary-menu))
296
297 (defun gnus-xmas-tree-menu-add ()
298   (gnus-xmas-menu-add tree
299                       gnus-tree-menu))
300
301 (defun gnus-xmas-server-menu-add ()
302   (gnus-xmas-menu-add menu
303                       gnus-server-server-menu gnus-server-connections-menu))
304
305 (defun gnus-xmas-browse-menu-add ()
306   (gnus-xmas-menu-add browse
307                       gnus-browse-menu))
308
309 (defun gnus-xmas-grouplens-menu-add ()
310   (gnus-xmas-menu-add grouplens
311                       gnus-grouplens-menu))
312
313 (defun gnus-xmas-read-event-char ()
314   "Get the next event."
315   (let ((event (next-command-event)))
316     ;; We junk all non-key events.  Is this naughty?
317     (while (not (key-press-event-p event))
318       (setq event (next-command-event)))
319     (cons (and (key-press-event-p event) 
320                (event-to-character event)) 
321           event)))
322
323 (defun gnus-xmas-group-remove-excess-properties ()
324   (let ((end (point))
325         (beg (progn (forward-line -1) (point))))
326     (remove-text-properties (1+ beg) end '(gnus-group nil))
327     (remove-text-properties 
328      beg end 
329      '(gnus-topic nil gnus-topic-level nil gnus-topic-visible nil))
330     (goto-char end)
331     (map-extents 
332      (lambda (e ma)
333        (set-extent-property e 'start-closed t))
334      (current-buffer) beg end)))
335                   
336 (defun gnus-xmas-topic-remove-excess-properties ()
337   (let ((end (point))
338         (beg (progn (forward-line -1) (point))))
339     (remove-text-properties beg end '(gnus-group nil gnus-unread nil))
340     (remove-text-properties (1+ beg) end '(gnus-topic nil))
341     (goto-char end)))
342
343 (defun gnus-xmas-seconds-since-epoch (date)
344   "Return a floating point number that says how many seconds have lapsed between Jan 1 12:00:00 1970 and DATE."
345   (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
346                         (timezone-parse-date date)))
347          (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
348                         (timezone-parse-time
349                          (aref (timezone-parse-date date) 3))))
350          (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
351                         (timezone-parse-date "Jan 1 12:00:00 1970")))
352          (tday (- (timezone-absolute-from-gregorian 
353                    (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
354                   (timezone-absolute-from-gregorian 
355                    (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
356     (+ (nth 2 ttime)
357        (* (nth 1 ttime) 60)
358        (* (float (nth 0 ttime)) 60 60)
359        (* (float tday) 60 60 24))))
360
361 (defun gnus-xmas-define ()
362   (setq gnus-mouse-2 [button2])
363
364   (unless (memq 'underline (face-list))
365     (and (fboundp 'make-face)
366          (funcall (intern "make-face") 'underline)))
367   ;; Must avoid calling set-face-underline-p directly, because it
368   ;; is a defsubst in emacs19, and will make the .elc files non
369   ;; portable!
370   (unless (face-differs-from-default-p 'underline)
371     (funcall (intern "set-face-underline-p") 'underline t))
372
373   (fset 'gnus-make-overlay 'make-extent)
374   (fset 'gnus-overlay-put 'set-extent-property)
375   (fset 'gnus-move-overlay 'gnus-xmas-move-overlay)
376   (fset 'gnus-overlay-end 'extent-end-position)
377   (fset 'gnus-extent-detached-p 'extent-detached-p)
378   (fset 'gnus-add-text-properties 'gnus-xmas-add-text-properties)
379   (fset 'gnus-put-text-property 'gnus-xmas-put-text-property)
380       
381   (require 'text-props)
382   (when (< emacs-minor-version 14)
383     (fset 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
384
385   (unless (boundp 'standard-display-table)
386     (setq standard-display-table nil))
387
388   (defvar gnus-mouse-face-prop 'highlight)
389
390   (unless (fboundp 'encode-time)
391     (defun encode-time (sec minute hour day month year &optional zone)
392       (let ((seconds
393              (gnus-xmas-seconds-since-epoch
394               (timezone-make-arpa-date 
395                year month day (timezone-make-time-string hour minute sec)
396                zone))))
397         (list (floor (/ seconds (expt 2 16)))
398               (round (mod seconds (expt 2 16)))))))
399       
400   (defun gnus-byte-code (func)
401     "Return a form that can be `eval'ed based on FUNC."
402     (let ((fval (symbol-function func)))
403       (if (compiled-function-p fval)
404           (list 'funcall fval)
405         (cons 'progn (cdr (cdr fval))))))
406
407   (fset 'gnus-x-color-values 
408         (if (fboundp 'x-color-values)
409             'x-color-values
410           (lambda (color)
411             (color-instance-rgb-components
412              (make-color-instance color))))))
413
414
415 (defun gnus-xmas-redefine ()
416   "Redefine lots of Gnus functions for XEmacs."
417   (fset 'gnus-summary-make-display-table 'ignore)
418   (fset 'gnus-visual-turn-off-edit-menu 'identity)
419   (fset 'gnus-summary-recenter 'gnus-xmas-summary-recenter)
420   (fset 'gnus-extent-start-open 'gnus-xmas-extent-start-open)
421   (fset 'gnus-article-push-button 'gnus-xmas-article-push-button)
422   (fset 'gnus-article-add-button 'gnus-xmas-article-add-button)
423   (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
424   (fset 'gnus-read-event-char 'gnus-xmas-read-event-char)
425   (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
426   (fset 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
427   (fset 'gnus-appt-select-lowest-window 
428         'gnus-xmas-appt-select-lowest-window)
429   (fset 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
430   (fset 'gnus-make-local-hook 'make-local-variable)
431   (fset 'gnus-add-hook 'gnus-xmas-add-hook)
432   (fset 'gnus-character-to-event 'character-to-event)
433   (fset 'gnus-article-show-hidden-text 'gnus-xmas-article-show-hidden-text)
434   (fset 'gnus-mode-line-buffer-identification
435         'gnus-xmas-mode-line-buffer-identification)
436
437   (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
438   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
439   (add-hook 'gnus-article-mode-hook 'gnus-xmas-article-menu-add)
440   (add-hook 'gnus-score-mode-hook 'gnus-xmas-score-menu-add)
441
442   (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add)
443   (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
444   (add-hook 'gnus-binary-mode-hook 'gnus-xmas-binary-menu-add)
445   (add-hook 'gnus-grouplens-mode-hook 'gnus-xmas-grouplens-menu-add)
446   (add-hook 'gnus-server-mode-hook 'gnus-xmas-server-menu-add)
447   (add-hook 'gnus-browse-mode-hook 'gnus-xmas-browse-menu-add)
448
449   (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar)
450   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
451
452   (when (and (<= emacs-major-version 19)
453              (<= emacs-minor-version 13))
454     (setq gnus-article-x-face-too-ugly (when (eq (device-type) 'tty)
455                                          "."))
456     (fset 'gnus-highlight-selected-summary
457           'gnus-xmas-highlight-selected-summary)
458     (fset 'gnus-group-remove-excess-properties
459           'gnus-xmas-group-remove-excess-properties)
460     (fset 'gnus-topic-remove-excess-properties
461           'gnus-xmas-topic-remove-excess-properties)
462     (fset 'gnus-mode-line-buffer-identification 'identity)
463     (unless (boundp 'shell-command-switch)
464       (setq shell-command-switch "-c"))
465     ))
466
467
468 ;;; XEmacs logo and toolbar.
469
470 (defun gnus-xmas-group-startup-message (&optional x y)
471   "Insert startup message in current buffer."
472   ;; Insert the message.
473   (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
474   (erase-buffer)
475   (let ((logo (and gnus-xmas-glyph-directory
476                    (concat 
477                     (file-name-as-directory gnus-xmas-glyph-directory)
478                     "gnus."
479                     (if (featurep 'xpm) "xpm" "xbm"))))
480         (xpm-color-symbols 
481          (and (featurep 'xpm)
482               (append `(("thing" ,(car gnus-xmas-logo-colors))
483                         ("shadow" ,(cadr gnus-xmas-logo-colors)))
484                       xpm-color-symbols))))
485     (if (and (featurep 'xpm)
486              (not (equal (device-type) 'tty))
487              logo
488              (file-exists-p logo))
489         (progn
490           (setq logo (make-glyph logo))
491           (insert " ")
492           (set-extent-begin-glyph (make-extent (point) (point)) logo)
493           (goto-char (point-min))
494           (while (not (eobp))
495             (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
496                                  ? ))
497             (forward-line 1))
498           (goto-char (point-min))
499           (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
500                  (wheight (window-height))
501                  (rest (- wheight pheight)))
502             (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
503
504       (insert
505        (format "              %s
506           _    ___ _             _      
507           _ ___ __ ___  __    _ ___     
508           __   _     ___    __  ___     
509               _           ___     _     
510              _  _ __             _      
511              ___   __            _      
512                    __           _       
513                     _      _   _        
514                    _      _    _        
515                       _  _    _         
516                   __  ___               
517                  _   _ _     _          
518                 _   _                   
519               _    _                    
520              _    _                     
521             _                         
522           __                             
523
524
525                ""))
526       ;; And then hack it.
527       (gnus-indent-rigidly (point-min) (point-max)
528                            (/ (max (- (window-width) (or x 46)) 0) 2))
529       (goto-char (point-min))
530       (forward-line 1)
531       (let* ((pheight (count-lines (point-min) (point-max)))
532              (wheight (window-height))
533              (rest (- wheight pheight)))
534         (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
535     ;; Fontify some.
536     (goto-char (point-min))
537     (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)
538     (goto-char (point-min))
539     (setq modeline-buffer-identification 
540           (list (concat gnus-version ": *Group*")))
541     (set-buffer-modified-p t)))
542
543
544 ;;; The toolbar.
545
546 (defvar gnus-use-toolbar (if (featurep 'toolbar)
547                              'default-toolbar
548                            nil)
549   "*If nil, do not use a toolbar.
550 If it is non-nil, it must be a toolbar.  The five legal values are
551 `default-toolbar', `top-toolbar', `bottom-toolbar',
552 `right-toolbar', and `left-toolbar'.")
553
554 (defvar gnus-group-toolbar 
555   '([gnus-group-get-new-news gnus-group-get-new-news t "Get new news"]
556     [gnus-group-get-new-news-this-group 
557      gnus-group-get-new-news-this-group t "Get new news in this group"]
558     [gnus-group-catchup-current 
559      gnus-group-catchup-current t "Catchup group"]
560     [gnus-group-describe-group 
561      gnus-group-describe-group t "Describe group"]
562     [gnus-group-unsubscribe gnus-group-unsubscribe t "Unsubscribe group"]
563     [gnus-group-subscribe gnus-group-subscribe t "Subscribe group"]
564     [gnus-group-kill-group gnus-group-kill-group t "Kill group"]
565     [gnus-group-exit gnus-group-exit t "Exit Gnus"]
566     )
567   "The group buffer toolbar.")
568
569 (defvar gnus-summary-toolbar 
570   '([gnus-summary-prev-unread 
571      gnus-summary-prev-unread-article t "Prev unread article"]
572     [gnus-summary-next-unread 
573      gnus-summary-next-unread-article t "Next unread article"]
574     [gnus-summary-post-news 
575      gnus-summary-post-news t "Post an article"]
576     [gnus-summary-followup-with-original
577      gnus-summary-followup-with-original t 
578      "Post a followup and yank the original"]
579     [gnus-summary-followup 
580      gnus-summary-followup t "Post a followup"]
581     [gnus-summary-reply-with-original
582      gnus-summary-reply-with-original t "Mail a reply and yank the original"]
583     [gnus-summary-reply 
584      gnus-summary-reply t "Mail a reply"]
585     [gnus-summary-caesar-message
586      gnus-summary-caesar-message t "Rot 13"]
587     [gnus-uu-decode-uu
588      gnus-uu-decode-uu t "Decode uuencoded articles"]
589     [gnus-summary-save-article-file
590      gnus-summary-save-article-file t "Save article in file"]
591     [gnus-summary-save-article
592      gnus-summary-save-article t "Save article"]
593     [gnus-uu-post-news 
594      gnus-uu-post-news t "Post an uuencoded article"]
595     [gnus-summary-cancel-article
596      gnus-summary-cancel-article t "Cancel article"]
597     [gnus-summary-catchup
598      gnus-summary-catchup t "Catchup"]
599     [gnus-summary-catchup-and-exit
600      gnus-summary-catchup-and-exit t "Catchup and exit"]
601     [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
602     )
603   "The summary buffer toolbar.")
604
605 (defvar gnus-summary-mail-toolbar
606   '(
607     [gnus-summary-prev-unread 
608      gnus-summary-prev-unread-article t "Prev unread article"]
609     [gnus-summary-next-unread 
610      gnus-summary-next-unread-article t "Next unread article"]
611     [gnus-summary-mail-reply gnus-summary-reply t "Reply"]
612 ;    [gnus-summary-mail-get gnus-mail-get t "Message get"]
613     [gnus-summary-mail-originate gnus-summary-post-news t "Originate"]
614     [gnus-summary-mail-save gnus-summary-save-article t "Save"]
615     [gnus-summary-mail-copy gnus-summary-copy-article t "Copy message"]
616 ;    [gnus-summary-mail-delete gnus-summary-delete-article t "Delete message"]
617     [gnus-summary-mail-forward gnus-summary-mail-forward t "Forward message"]
618 ;    [gnus-summary-mail-spell gnus-mail-spell t "Spell"]
619 ;    [gnus-summary-mail-help gnus-mail-help  t "Message help"]
620     [gnus-summary-caesar-message
621      gnus-summary-caesar-message t "Rot 13"]
622     [gnus-uu-decode-uu
623      gnus-uu-decode-uu t "Decode uuencoded articles"]
624     [gnus-summary-save-article-file
625      gnus-summary-save-article-file t "Save article in file"]
626     [gnus-summary-save-article
627      gnus-summary-save-article t "Save article"]
628     [gnus-summary-catchup-and-exit
629      gnus-summary-catchup-and-exit t "Catchup and exit"]
630     [gnus-summary-catchup
631      gnus-summary-catchup t "Catchup"]
632     [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
633     )
634   "The summary buffer mail toolbar.")
635
636 (defun gnus-xmas-setup-group-toolbar ()
637   (and gnus-use-toolbar
638        (message-xmas-setup-toolbar gnus-group-toolbar nil "gnus")
639        (set-specifier (symbol-value gnus-use-toolbar)
640                       (cons (current-buffer) gnus-group-toolbar))))
641
642 (defun gnus-xmas-setup-summary-toolbar ()
643   (let ((bar (if (gnus-news-group-p gnus-newsgroup-name)
644                  gnus-summary-toolbar gnus-summary-mail-toolbar)))
645     (and gnus-use-toolbar
646          (message-xmas-setup-toolbar bar nil "gnus")
647          (set-specifier (symbol-value gnus-use-toolbar)
648                         (cons (current-buffer) bar)))))
649
650 (defun gnus-xmas-mail-strip-quoted-names (address)
651   "Protect mail-strip-quoted-names from NIL input.
652 XEmacs compatibility workaround."
653   (if (null address)
654       nil
655     (mail-strip-quoted-names address)))
656
657 (defun gnus-xmas-call-region (command &rest args)
658   (apply
659    'call-process-region (point-min) (point-max) command t '(t nil) nil
660    args))
661
662 (unless (find-face 'gnus-x-face)
663   (copy-face 'default 'gnus-x-face)
664   (set-face-foreground 'gnus-x-face "black")
665   (set-face-background 'gnus-x-face "white"))
666
667 (defun gnus-xmas-article-display-xface (beg end)
668   "Display any XFace headers in the current article."
669   (save-excursion
670     (let (xface-glyph)
671       (if (featurep 'xface)
672           (setq xface-glyph
673                 (make-glyph (vector 'xface :data 
674                                     (concat "X-Face: "
675                                             (buffer-substring beg end)))))
676         (let ((cur (current-buffer)))
677           (save-excursion
678             (gnus-set-work-buffer)
679             (insert (format "%s" (buffer-substring beg end cur)))
680             (gnus-xmas-call-region "uncompface")
681             (goto-char (point-min))
682             (insert "/* Width=48, Height=48 */\n")
683             (gnus-xmas-call-region "icontopbm")
684             (gnus-xmas-call-region "ppmtoxpm")
685             (setq xface-glyph
686                   (make-glyph
687                    (vector 'xpm :data (buffer-string )))))))
688       (set-glyph-face xface-glyph 'gnus-x-face)
689       (goto-char (point-min))
690       (re-search-forward "^From:" nil t)
691       (set-extent-begin-glyph 
692        (make-extent (point) (1+ (point))) xface-glyph))))
693
694 (defun gnus-xmas-article-show-hidden-text (type &optional hide)
695   "Show all hidden text of type TYPE.
696 If HIDE, hide the text instead."
697   (save-excursion
698     (set-buffer gnus-article-buffer)
699     (let ((buffer-read-only nil)
700           (inhibit-point-motion-hooks t)
701           (beg (point-min)))
702       (while (gnus-goto-char (text-property-any
703                               beg (point-max) 'gnus-type type))
704         (setq beg (point))
705         (forward-char)
706         (if hide
707             (article-hide-text beg (point) gnus-hidden-properties)
708           (article-unhide-text beg (point)))
709         (setq beg (point)))
710       (save-window-excursion
711         (select-window (get-buffer-window (current-buffer)))
712         (recenter))
713       t)))
714
715 (defvar gnus-xmas-pointer-glyph 
716   (progn
717     (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
718     (make-pointer-glyph (concat gnus-xmas-glyph-directory "gnus-pointer."
719                                 (if (featurep 'xpm) "xpm" "xbm")))))
720
721 (defvar gnus-xmas-modeline-left-extent 
722   (let ((ext (copy-extent modeline-buffer-id-left-extent)))
723     ;(set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
724     ext))
725       
726 (defvar gnus-xmas-modeline-right-extent 
727   (let ((ext (copy-extent modeline-buffer-id-right-extent)))
728     ;(set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
729     ext))
730
731 (defvar gnus-xmas-modeline-glyph
732   (progn
733     (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
734     (let* ((file (concat gnus-xmas-glyph-directory "gnus-pointer."
735                          (if (featurep 'xpm) "xpm" "xbm")))
736            (glyph (make-glyph file)))
737       (when (and (featurep 'x)
738                  (file-exists-p file))
739         (set-glyph-face glyph 'modeline-buffer-id))
740       (set-glyph-property glyph 'image (cons 'tty "Gnus:"))
741       glyph)))
742
743 (defun gnus-xmas-mode-line-buffer-identification (line)
744   (let ((line (car line))
745         chop)
746     (if (not (stringp line))
747         (list line)
748       (when (string-match "^Gnus:" line)
749         (setq chop (match-end 0))
750         (list 
751          (if gnus-xmas-modeline-glyph
752              (cons gnus-xmas-modeline-left-extent gnus-xmas-modeline-glyph)
753            (cons gnus-xmas-modeline-left-extent (substring line 0 chop)))
754          (cons gnus-xmas-modeline-right-extent (substring line chop)))))))
755
756 (defun gnus-xmas-splash ()
757   (when (eq (device-type) 'x)
758     (gnus-splash)))
759
760 (provide 'gnus-xmas)
761
762 ;;; gnus-xmas.el ends here