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