*** 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 (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-grouplens-menu-add ()
320   (gnus-xmas-menu-add grouplens
321     gnus-grouplens-menu))
322
323 (defun gnus-xmas-read-event-char ()
324   "Get the next event."
325   (let ((event (next-event)))
326     ;; We junk all non-key events.  Is this naughty?
327     (while (not (key-press-event-p event))
328       (setq event (next-event)))
329     (cons (and (key-press-event-p event) 
330               ; (numberp (event-key event))
331                (event-to-character event)) 
332           event)))
333
334 (defun gnus-xmas-group-remove-excess-properties ()
335   (let ((end (point))
336         (beg (progn (forward-line -1) (point))))
337     (remove-text-properties (1+ beg) end '(gnus-group nil))
338     (remove-text-properties 
339      beg end 
340      '(gnus-topic nil gnus-topic-level nil gnus-topic-visible nil))
341     (goto-char end)
342     (map-extents 
343      (lambda (e ma)
344        (set-extent-property e 'start-closed t))
345      (current-buffer) beg end)))
346                   
347 (defun gnus-xmas-topic-remove-excess-properties ()
348   (let ((end (point))
349         (beg (progn (forward-line -1) (point))))
350     (remove-text-properties beg end '(gnus-group nil gnus-unread nil))
351     (remove-text-properties (1+ beg) end '(gnus-topic nil))
352     (goto-char end)))
353
354 (defun gnus-xmas-seconds-since-epoch (date)
355   "Return a floating point number that says how many seconds have lapsed between Jan 1 12:00:00 1970 and DATE."
356   (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
357                         (timezone-parse-date date)))
358          (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
359                         (timezone-parse-time
360                          (aref (timezone-parse-date date) 3))))
361          (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
362                         (timezone-parse-date "Jan 1 12:00:00 1970")))
363          (tday (- (timezone-absolute-from-gregorian 
364                    (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
365                   (timezone-absolute-from-gregorian 
366                    (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
367     (+ (nth 2 ttime)
368        (* (nth 1 ttime) 60)
369        (* (float (nth 0 ttime)) 60 60)
370        (* (float tday) 60 60 24))))
371
372 (defun gnus-xmas-define ()
373   (setq gnus-mouse-2 [button2])
374
375   (or (memq 'underline (list-faces))
376       (and (fboundp 'make-face)
377            (funcall (intern "make-face") 'underline)))
378   ;; Must avoid calling set-face-underline-p directly, because it
379   ;; is a defsubst in emacs19, and will make the .elc files non
380   ;; portable!
381   (or (face-differs-from-default-p 'underline)
382       (funcall (intern "set-face-underline-p") 'underline t))
383
384   (fset 'gnus-make-overlay 'make-extent)
385   (fset 'gnus-overlay-put 'set-extent-property)
386   (fset 'gnus-move-overlay 'gnus-xmas-move-overlay)
387   (fset 'gnus-overlay-end 'extent-end-position)
388   (fset 'gnus-extent-detached-p 'extent-detached-p)
389   (fset 'gnus-add-text-properties 'gnus-xmas-add-text-properties)
390   (fset 'gnus-put-text-property 'gnus-xmas-put-text-property)
391       
392   (require 'text-props)
393   (if (< emacs-minor-version 14)
394       (fset 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
395
396   (or (boundp 'standard-display-table) (setq standard-display-table nil))
397
398   (defvar gnus-mouse-face-prop 'highlight)
399
400   (unless (fboundp 'encode-time)
401     (defun encode-time (sec minute hour day month year &optional zone)
402       (let ((seconds
403              (gnus-xmas-seconds-since-epoch
404               (timezone-make-arpa-date 
405                year month day (timezone-make-time-string hour minute sec)
406                zone))))
407         (list (floor (/ seconds (expt 2 16)))
408               (round (mod seconds (expt 2 16)))))))
409       
410   (defun gnus-byte-code (func)
411     "Return a form that can be `eval'ed based on FUNC."
412     (let ((fval (symbol-function func)))
413       (if (byte-code-function-p fval)
414           (list 'funcall fval)
415         (cons 'progn (cdr (cdr fval))))))
416       
417   ;; Fix by "jeff (j.d.) sparkes" <jsparkes@bnr.ca>.
418   (defvar gnus-display-type (device-class)
419     "A symbol indicating the display Emacs is running under.
420 The symbol should be one of `color', `grayscale' or `mono'. If Emacs
421 guesses this display attribute wrongly, either set this variable in
422 your `~/.emacs' or set the resource `Emacs.displayType' in your
423 `~/.Xdefaults'. See also `gnus-background-mode'.
424
425 This is a meta-variable that will affect what default values other
426 variables get.  You would normally not change this variable, but
427 pounce directly on the real variables themselves.")
428
429
430   (fset 'gnus-x-color-values 
431         (if (fboundp 'x-color-values)
432             'x-color-values
433           (lambda (color)
434             (color-instance-rgb-components
435              (make-color-instance color)))))
436     
437   (defvar gnus-background-mode 
438     (let* ((bg-resource 
439             (condition-case ()
440                 (x-get-resource ".backgroundMode" "BackgroundMode" 'string)
441               (error nil)))
442            (params (frame-parameters))
443            (color (condition-case ()
444                       (or (assq 'background-color params)
445                           (color-instance-name
446                            (specifier-instance
447                             (face-background 'default))))
448                     (error nil))))
449       (cond (bg-resource (intern (downcase bg-resource)))
450             ((and color
451                   (< (apply '+ (gnus-x-color-values color))
452                      (/ (apply '+ (gnus-x-color-values "white")) 3)))
453              'dark)
454             (t 'light)))
455     "A symbol indicating the Emacs background brightness.
456 The symbol should be one of `light' or `dark'.
457 If Emacs guesses this frame attribute wrongly, either set this variable in
458 your `~/.emacs' or set the resource `Emacs.backgroundMode' in your
459 `~/.Xdefaults'.
460 See also `gnus-display-type'.
461
462 This is a meta-variable that will affect what default values other
463 variables get.  You would normally not change this variable, but
464 pounce directly on the real variables themselves.")
465   )
466
467
468
469 (defun gnus-xmas-redefine ()
470   "Redefine lots of Gnus functions for XEmacs."
471   (fset 'gnus-summary-make-display-table 'ignore)
472   (fset 'gnus-visual-turn-off-edit-menu 'identity)
473   (fset 'gnus-highlight-selected-summary
474         'gnus-xmas-highlight-selected-summary)
475   (fset 'gnus-summary-recenter 'gnus-xmas-summary-recenter)
476   (fset 'gnus-extent-start-open 'gnus-xmas-extent-start-open)
477   (fset 'gnus-copy-article-buffer 'gnus-xmas-copy-article-buffer)
478   (fset 'gnus-article-push-button 'gnus-xmas-article-push-button)
479   (fset 'gnus-article-add-button 'gnus-xmas-article-add-button)
480   (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
481   (fset 'gnus-read-event-char 'gnus-xmas-read-event-char)
482   (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
483   (fset 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
484   (fset 'gnus-appt-select-lowest-window 
485         'gnus-xmas-appt-select-lowest-window)
486   (fset 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
487   (fset 'gnus-make-local-hook 'make-local-variable)
488   (fset 'gnus-add-hook 'gnus-xmas-add-hook)
489   (fset 'gnus-character-to-event 'character-to-event)
490
491   (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
492   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
493   (add-hook 'gnus-article-mode-hook 'gnus-xmas-article-menu-add)
494
495   (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add)
496   (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
497   (add-hook 'gnus-binary-mode-hook 'gnus-xmas-binary-menu-add)
498   (add-hook 'gnus-grouplens-mode-hook 'gnus-xmas-grouplens-menu-add)
499
500   (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar)
501   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
502
503   (when (and (<= emacs-major-version 19)
504              (<= emacs-minor-version 13))
505     (fset 'gnus-group-remove-excess-properties
506           'gnus-xmas-group-remove-excess-properties)
507     (fset 'gnus-topic-remove-excess-properties
508           'gnus-xmas-topic-remove-excess-properties)))
509
510
511 ;;; XEmacs logo and toolbar.
512
513 (defun gnus-xmas-group-startup-message (&optional x y)
514   "Insert startup message in current buffer."
515   ;; Insert the message.
516   (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
517   (erase-buffer)
518   (let ((logo (and gnus-xmas-glyph-directory
519                    (concat 
520                     (file-name-as-directory gnus-xmas-glyph-directory)
521                     "gnus.xpm")))
522         (xpm-color-symbols 
523          (and (featurep 'xpm)
524               (append `(("thing" ,(car gnus-xmas-logo-colors))
525                         ("shadow" ,(cadr gnus-xmas-logo-colors)))
526                       xpm-color-symbols))))
527     (if (and (featurep 'xpm)
528              (not (equal (device-type) 'tty))
529              logo
530              (file-exists-p logo))
531         (progn
532           (setq logo (make-glyph logo))
533           (insert " ")
534           (set-extent-begin-glyph (make-extent (point) (point)) logo)
535           (goto-char (point-min))
536           (while (not (eobp))
537             (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
538                                  ? ))
539             (forward-line 1))
540           (goto-char (point-min))
541           (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
542                  (wheight (window-height))
543                  (rest (- wheight pheight)))
544             (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
545
546       (insert
547        (format "              %s
548           _    ___ _             _      
549           _ ___ __ ___  __    _ ___     
550           __   _     ___    __  ___     
551               _           ___     _     
552              _  _ __             _      
553              ___   __            _      
554                    __           _       
555                     _      _   _        
556                    _      _    _        
557                       _  _    _         
558                   __  ___               
559                  _   _ _     _          
560                 _   _                   
561               _    _                    
562              _    _                     
563             _                         
564           __                             
565
566
567                ""))
568       ;; And then hack it.
569       (gnus-indent-rigidly (point-min) (point-max) 
570                            (/ (max (- (window-width) (or x 46)) 0) 2))
571       (goto-char (point-min))
572       (forward-line 1)
573       (let* ((pheight (count-lines (point-min) (point-max)))
574              (wheight (window-height))
575              (rest (- wheight pheight)))
576         (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
577     ;; Fontify some.
578     (goto-char (point-min))
579     (and (search-forward "Praxis" nil t)
580          (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
581     (goto-char (point-min))
582     (let* ((mode-string (gnus-group-set-mode-line)))
583       (setq mode-line-buffer-identification 
584             (list (concat gnus-version (substring (car mode-string) 4))))
585       (set-buffer-modified-p t))))
586
587
588 ;;; The toolbar.
589
590 (defvar gnus-use-toolbar 'default-toolbar
591   "*If nil, do not use a toolbar.
592 If it is non-nil, it must be a toolbar.  The five legal values are
593 `default-toolbar', `top-toolbar', `bottom-toolbar',
594 `right-toolbar', and `left-toolbar'.")
595
596 (defvar gnus-group-toolbar 
597   '(
598     [gnus-group-get-new-news gnus-group-get-new-news t "Get new news"]
599     [gnus-group-get-new-news-this-group 
600      gnus-group-get-new-news-this-group t "Get new news in this group"]
601     [gnus-group-catchup-current 
602      gnus-group-catchup-current t "Catchup group"]
603     [gnus-group-describe-group 
604      gnus-group-describe-group t "Describe group"]
605     [gnus-group-kill-group gnus-group-kill-group t "Kill group"]
606     [gnus-group-exit gnus-group-exit t "Exit Gnus"]
607     )
608   "The group buffer toolbar.")
609
610 (defvar gnus-summary-toolbar 
611   '(
612     [gnus-summary-post-news 
613      gnus-summary-post-news t "Post an article"]
614     [gnus-summary-followup-with-original
615      gnus-summary-followup-with-original t 
616      "Post a followup and yank the original"]
617     [gnus-summary-followup 
618      gnus-summary-followup t "Post a followup"]
619     [gnus-summary-reply-with-original
620      gnus-summary-reply-with-original t "Mail a reply and yank the original"]
621     [gnus-summary-reply 
622      gnus-summary-reply t "Mail a reply"]
623     [gnus-summary-caesar-message
624      gnus-summary-caesar-message t "Rot 13"]
625     [gnus-uu-decode-uu
626      gnus-uu-decode-uu t "Decode uuencoded articles"]
627     [gnus-summary-save-article-file
628      gnus-summary-save-article-file t "Save article in file"]
629     [gnus-summary-save-article
630      gnus-summary-save-article t "Save article"]
631     [gnus-uu-post-news 
632      gnus-uu-post-news t "Post an uuencoded article"]
633     [gnus-summary-cancel-article
634      gnus-summary-cancel-article t "Cancel article"]
635     )
636   "The summary buffer toolbar.")
637
638 (defvar gnus-summary-mail-toolbar
639   '([gnus-summary-mail-reply gnus-summary-reply t "Reply"]
640     [gnus-summary-mail-get gnus-mail-get t "Message get"]
641     [gnus-summary-mail-originate gnus-summary-post-news t "Originate"]
642     [gnus-summary-mail-save gnus-summary-save-article t "Save"]
643     [gnus-summary-mail-copy gnus-summary-copy-article t "Copy message"]
644     [gnus-summary-mail-delete gnus-summary-delete-article t "Delete message"]
645     [gnus-summary-mail-forward gnus-summary-mail-forward t "Forward message"]
646 ;    [gnus-summary-mail-spell gnus-mail-spell t "Spell"]
647 ;    [gnus-summary-mail-help gnus-mail-help  t "Message help"]
648     )
649   "The summary buffer mail toolbar.")
650
651 (defun gnus-xmas-setup-group-toolbar ()
652   (let (dir)
653     (and gnus-use-toolbar
654          (setq dir (message-xmas-setup-toolbar gnus-group-toolbar nil "gnus"))
655          (file-exists-p (concat dir "gnus-group-catchup-current-up.xpm"))
656          (set-specifier (symbol-value gnus-use-toolbar)
657                         (cons (current-buffer) gnus-group-toolbar)))))
658
659 (defun gnus-xmas-setup-summary-toolbar ()
660   (let ((bar (if (gnus-news-group-p gnus-newsgroup-name)
661                  gnus-summary-toolbar gnus-summary-mail-toolbar))
662         dir)
663     (and gnus-use-toolbar
664          (setq dir (message-xmas-setup-toolbar bar 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) bar)))))
668
669 (defun gnus-xmas-mail-strip-quoted-names (address)
670   "Protect mail-strip-quoted-names from NIL input.
671 XEmacs compatibility workaround."
672   (if (null address)
673       nil
674     (mail-strip-quoted-names address)))
675
676 (defun gnus-xmas-article-display-xface (beg end)
677   "Display any XFace headers in the current article."
678   (save-excursion
679     (let (xface-glyph)
680       (when (featurep 'xface)
681         (setq xface-glyph
682               (make-glyph (vector 'xface :data 
683                                   (concat "X-Face: "
684                                           (buffer-substring beg end)))))
685         (goto-char (point-min))
686         (re-search-forward "^From:" nil t)
687         (beginning-of-line)
688         (set-extent-begin-glyph 
689          (make-extent (point) (point)) xface-glyph)))))
690
691 ;;; gnus-xmas.el ends here