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