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