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