*** 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-summary-set-display-table ()
185   ;; Setup the display table -- like gnus-summary-setup-display-table,
186   ;; Setup the display table -- like `gnus-summary-setup-display-table',
187   ;; but done in an XEmacsish way.
188   (let ((table (make-display-table))
189         ;; Nix out all the control chars...
190         (default-table (specifier-instance current-display-table))
191         (i 32))
192     ;; Nix out all the control chars...
193     (while (>= (setq i (1- i)) 0)
194       (aset table i [??]))
195     ;; ... but not newline and cr, of course.  (cr is necessary for the
196     ;; selective display).
197     (aset table ?\n nil)
198     (aset table ?\r nil)
199     ;; We nix out any glyphs over 126 that are not set already.
200     (let ((i 256))
201       (while (>= (setq i (1- i)) 127)
202         ;; Only modify if the entry is nil.
203         (or (aref table i)
204         ;; Only modify if the default entry is nil.
205         (or (aref default-table i)
206             (aset table i [??]))))
207     ;; Can't use `set-specifier' because of a bug in 19.14 and earlier
208     (add-spec-to-specifier current-display-table table (current-buffer) nil)))
209
210 (defun gnus-xmas-add-hook (hook function &optional append local)
211   (add-hook hook function))
212
213 (defun gnus-xmas-add-text-properties (start end props &optional object)
214   (add-text-properties start end props object)
215   (put-text-property start end 'start-closed nil object))
216
217 (defun gnus-xmas-put-text-property (start end prop value &optional object)
218   (put-text-property start end prop value object)
219   (put-text-property start end 'start-closed nil object))
220
221 (defun gnus-xmas-extent-start-open (point)
222   (map-extents (lambda (extent arg)
223                  (set-extent-property extent 'start-open t))
224                nil point (min (1+ (point)) (point-max))))
225
226 (defun gnus-xmas-article-push-button (event)
227   "Check text under the mouse pointer for a callback function.
228 If the text under the mouse pointer has a `gnus-callback' property,
229 call it with the value of the `gnus-data' text property."
230   (interactive "e")
231   (set-buffer (window-buffer (event-window event)))
232   (let* ((pos (event-closest-point event))
233          (data (get-text-property pos 'gnus-data))
234          (fun (get-text-property pos 'gnus-callback)))
235     (when fun
236       (funcall fun data))))
237
238 (defun gnus-xmas-move-overlay (extent start end &optional buffer)
239   (set-extent-endpoints extent start end))
240
241 ;; Fixed by Christopher Davis <ckd@loiosh.kei.com>.
242 (defun gnus-xmas-article-add-button (from to fun &optional data)
243   "Create a button between FROM and TO with callback FUN and data DATA."
244   (when gnus-article-button-face
245     (gnus-overlay-put (gnus-make-overlay from to)
246                       'face gnus-article-button-face))
247   (gnus-add-text-properties
248    from to
249    (nconc
250     (and gnus-article-mouse-face
251          (list 'mouse-face gnus-article-mouse-face))
252     (list 'gnus-callback fun)
253     (and data (list 'gnus-data data))
254     (list 'highlight t))))
255
256 (defun gnus-xmas-window-top-edge (&optional window)
257   (nth 1 (window-pixel-edges window)))
258
259 (defun gnus-xmas-tree-minimize ()
260   (when (and gnus-tree-minimize-window
261              (not (one-window-p)))
262     (let* ((window-min-height 2)
263            (height (1+ (count-lines (point-min) (point-max))))
264            (min (max (1- window-min-height) height))
265            (tot (if (numberp gnus-tree-minimize-window)
266                     (min gnus-tree-minimize-window min)
267                   min))
268            (win (get-buffer-window (current-buffer)))
269            (wh (and win (1- (window-height win)))))
270       (when (and win
271                  (not (eq tot wh)))
272         (let ((selected (selected-window)))
273           (select-window win)
274           (enlarge-window (- tot wh))
275           (select-window selected))))))
276
277 ;; Select the lowest window on the frame.
278 (defun gnus-xmas-appt-select-lowest-window ()
279   (let* ((lowest-window (selected-window))
280          (bottom-edge (car (cdr (cdr (cdr (window-pixel-edges))))))
281          (last-window (previous-window))
282          (window-search t))
283     (while window-search
284       (let* ((this-window (next-window))
285              (next-bottom-edge (car (cdr (cdr (cdr
286                                                (window-pixel-edges
287                                                 this-window)))))))
288         (when (< bottom-edge next-bottom-edge)
289           (setq bottom-edge next-bottom-edge)
290           (setq lowest-window this-window))
291
292         (select-window this-window)
293         (when (eq last-window this-window)
294           (select-window lowest-window)
295           (setq window-search nil))))))
296
297 (defmacro gnus-xmas-menu-add (type &rest menus)
298   `(gnus-xmas-menu-add-1 ',type ',menus))
299 (put 'gnus-xmas-menu-add 'lisp-indent-function 1)
300
301 (defun gnus-xmas-menu-add-1 (type menus)
302   (when (and menu-bar-mode
303              (gnus-visual-p (intern (format "%s-menu" type)) 'menu))
304     (while menus
305       (easy-menu-add (symbol-value (pop menus))))))
306
307 (defun gnus-xmas-group-menu-add ()
308   (gnus-xmas-menu-add group
309     gnus-group-reading-menu gnus-group-group-menu gnus-group-misc-menu))
310
311 (defun gnus-xmas-summary-menu-add ()
312   (gnus-xmas-menu-add summary
313     gnus-summary-misc-menu gnus-summary-kill-menu
314     gnus-summary-article-menu gnus-summary-thread-menu
315     gnus-summary-post-menu ))
316
317 (defun gnus-xmas-article-menu-add ()
318   (gnus-xmas-menu-add article
319     gnus-article-article-menu gnus-article-treatment-menu))
320
321 (defun gnus-xmas-score-menu-add ()
322   (gnus-xmas-menu-add score
323     gnus-score-menu))
324
325 (defun gnus-xmas-pick-menu-add ()
326   (gnus-xmas-menu-add pick
327     gnus-pick-menu))
328
329 (defun gnus-xmas-topic-menu-add ()
330   (gnus-xmas-menu-add topic
331     gnus-topic-menu))
332
333 (defun gnus-xmas-binary-menu-add ()
334   (gnus-xmas-menu-add binary
335     gnus-binary-menu))
336
337 (defun gnus-xmas-tree-menu-add ()
338   (gnus-xmas-menu-add tree
339     gnus-tree-menu))
340
341 (defun gnus-xmas-server-menu-add ()
342   (gnus-xmas-menu-add menu
343     gnus-server-server-menu gnus-server-connections-menu))
344
345 (defun gnus-xmas-browse-menu-add ()
346   (gnus-xmas-menu-add browse
347     gnus-browse-menu))
348
349 (defun gnus-xmas-grouplens-menu-add ()
350   (gnus-xmas-menu-add grouplens
351     gnus-grouplens-menu))
352
353 (defun gnus-xmas-read-event-char ()
354   "Get the next event."
355   (let ((event (next-command-event)))
356     (sit-for 0)
357     ;; We junk all non-key events.  Is this naughty?
358     (while (not (or (key-press-event-p event)
359                     (button-press-event-p event)))
360       (dispatch-event event)
361       (setq event (next-command-event)))
362     (cons (and (key-press-event-p event)
363                (event-to-character event))
364           event)))
365
366 (defun gnus-xmas-group-remove-excess-properties ()
367   (let ((end (point))
368         (beg (progn (forward-line -1) (point))))
369     (remove-text-properties (1+ beg) end '(gnus-group nil))
370     (remove-text-properties
371      beg end
372      '(gnus-topic nil gnus-topic-level nil gnus-topic-visible nil))
373     (goto-char end)
374     (map-extents
375      (lambda (e ma)
376        (set-extent-property e 'start-closed t))
377      (current-buffer) beg end)))
378
379 (defun gnus-xmas-topic-remove-excess-properties ()
380   (let ((end (point))
381         (beg (progn (forward-line -1) (point))))
382     (remove-text-properties beg end '(gnus-group nil gnus-unread nil))
383     (remove-text-properties (1+ beg) end '(gnus-topic nil))
384     (goto-char end)))
385
386 (defun gnus-xmas-seconds-since-epoch (date)
387   "Return a floating point number that says how many seconds have lapsed between Jan 1 12:00:00 1970 and DATE."
388   (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
389                         (timezone-parse-date date)))
390          (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
391                         (timezone-parse-time
392                          (aref (timezone-parse-date date) 3))))
393          (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
394                         (timezone-parse-date "Jan 1 12:00:00 1970")))
395          (tday (- (timezone-absolute-from-gregorian
396                    (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
397                   (timezone-absolute-from-gregorian
398                    (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
399     (+ (nth 2 ttime)
400        (* (nth 1 ttime) 60)
401        (* (float (nth 0 ttime)) 60 60)
402        (* (float tday) 60 60 24))))
403
404 (defun gnus-xmas-define ()
405   (setq gnus-mouse-2 [button2])
406
407   (unless (memq 'underline (face-list))
408     (and (fboundp 'make-face)
409          (funcall (intern "make-face") 'underline)))
410   ;; Must avoid calling set-face-underline-p directly, because it
411   ;; is a defsubst in emacs19, and will make the .elc files non
412   ;; portable!
413   (unless (face-differs-from-default-p 'underline)
414     (funcall (intern "set-face-underline-p") 'underline t))
415
416   (cond
417    ((fboundp 'char-or-char-int-p)
418     ;; Handle both types of marks for XEmacs-20.x.
419     (fset 'gnus-characterp 'char-or-char-int-p))
420    ;; V19 of XEmacs, probably.
421    (t
422     (fset 'gnus-characterp 'characterp)))
423
424   (fset 'gnus-make-overlay 'make-extent)
425   (fset 'gnus-overlay-put 'set-extent-property)
426   (fset 'gnus-move-overlay 'gnus-xmas-move-overlay)
427   (fset 'gnus-overlay-end 'extent-end-position)
428   (fset 'gnus-extent-detached-p 'extent-detached-p)
429   (fset 'gnus-add-text-properties 'gnus-xmas-add-text-properties)
430   (fset 'gnus-put-text-property 'gnus-xmas-put-text-property)
431
432   (require 'text-props)
433   (if (and (<= emacs-major-version 19)
434            (< emacs-minor-version 14))
435       (fset 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
436
437   (when (fboundp 'turn-off-scroll-in-place)
438     (add-hook 'gnus-article-mode-hook 'turn-off-scroll-in-place))
439
440   (unless (boundp 'standard-display-table)
441     (setq standard-display-table nil))
442
443   (defvar gnus-mouse-face-prop 'highlight)
444
445   (unless (fboundp 'encode-time)
446     (defun encode-time (sec minute hour day month year &optional zone)
447       (let ((seconds
448              (gnus-xmas-seconds-since-epoch
449               (timezone-make-arpa-date
450                year month day (timezone-make-time-string hour minute sec)
451                zone))))
452         (list (floor (/ seconds (expt 2 16)))
453               (round (mod seconds (expt 2 16)))))))
454
455   (defun gnus-byte-code (func)
456     "Return a form that can be `eval'ed based on FUNC."
457     (let ((fval (symbol-function func)))
458       (if (compiled-function-p fval)
459           (list 'funcall fval)
460         (cons 'progn (cdr (cdr fval))))))
461
462   (fset 'gnus-x-color-values
463         (if (fboundp 'x-color-values)
464             'x-color-values
465           (lambda (color)
466             (color-instance-rgb-components
467              (make-color-instance color))))))
468
469 (defun gnus-xmas-redefine ()
470   "Redefine lots of Gnus functions for XEmacs."
471   (fset 'gnus-summary-set-display-table 'gnus-xmas-summary-set-display-table)
472   (fset 'gnus-visual-turn-off-edit-menu 'identity)
473   (fset 'gnus-summary-recenter 'gnus-xmas-summary-recenter)
474   (fset 'gnus-extent-start-open 'gnus-xmas-extent-start-open)
475   (fset 'gnus-article-push-button 'gnus-xmas-article-push-button)
476   (fset 'gnus-article-add-button 'gnus-xmas-article-add-button)
477   (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
478   (fset 'gnus-read-event-char 'gnus-xmas-read-event-char)
479   (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
480   (fset 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
481   (fset 'gnus-appt-select-lowest-window
482         'gnus-xmas-appt-select-lowest-window)
483   (fset 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
484   (fset 'gnus-add-hook 'gnus-xmas-add-hook)
485   (fset 'gnus-character-to-event 'character-to-event)
486   (fset 'gnus-mode-line-buffer-identification
487         'gnus-xmas-mode-line-buffer-identification)
488   (fset 'gnus-key-press-event-p 'key-press-event-p)
489   (fset 'gnus-region-active-p 'region-active-p)
490
491   (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
492   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
493   (add-hook 'gnus-article-mode-hook 'gnus-xmas-article-menu-add)
494   (add-hook 'gnus-score-mode-hook 'gnus-xmas-score-menu-add)
495
496   (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add)
497   (add-hook 'gnus-topic-mode-hook 'gnus-xmas-topic-menu-add)
498   (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
499   (add-hook 'gnus-binary-mode-hook 'gnus-xmas-binary-menu-add)
500   (add-hook 'gnus-grouplens-mode-hook 'gnus-xmas-grouplens-menu-add)
501   (add-hook 'gnus-server-mode-hook 'gnus-xmas-server-menu-add)
502   (add-hook 'gnus-browse-mode-hook 'gnus-xmas-browse-menu-add)
503
504   (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar)
505   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
506
507   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-switch-horizontal-scrollbar-off)
508
509   (when (and (<= emacs-major-version 19)
510              (<= emacs-minor-version 13))
511     (setq gnus-article-x-face-too-ugly (when (eq (device-type) 'tty)
512                                          "."))
513     (fset 'gnus-highlight-selected-summary
514           'gnus-xmas-highlight-selected-summary)
515     (fset 'gnus-group-remove-excess-properties
516           'gnus-xmas-group-remove-excess-properties)
517     (fset 'gnus-topic-remove-excess-properties
518           'gnus-xmas-topic-remove-excess-properties)
519     (fset 'gnus-mode-line-buffer-identification 'identity)
520     (unless (boundp 'shell-command-switch)
521       (setq shell-command-switch "-c"))))
522
523
524 ;;; XEmacs logo and toolbar.
525
526 (defun gnus-xmas-group-startup-message (&optional x y)
527   "Insert startup message in current buffer."
528   ;; Insert the message.
529   (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
530   (erase-buffer)
531   (let ((logo (and gnus-xmas-glyph-directory
532                    (concat
533                     (file-name-as-directory gnus-xmas-glyph-directory)
534                     "gnus."
535                     (if (featurep 'xpm) "xpm" "xbm"))))
536         (xpm-color-symbols
537          (and (featurep 'xpm)
538               (append `(("thing" ,(car gnus-xmas-logo-colors))
539                         ("shadow" ,(cadr gnus-xmas-logo-colors)))
540                       xpm-color-symbols))))
541     (if (and (featurep 'xpm)
542              (not (equal (device-type) 'tty))
543              logo
544              (file-exists-p logo))
545         (progn
546           (setq logo (make-glyph logo))
547           (insert " ")
548           (set-extent-begin-glyph (make-extent (point) (point)) logo)
549           (goto-char (point-min))
550           (while (not (eobp))
551             (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
552                                  ? ))
553             (forward-line 1))
554           (goto-char (point-min))
555           (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
556                  (wheight (window-height))
557                  (rest (- wheight pheight)))
558             (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
559
560       (insert
561        (format "              %s
562           _    ___ _             _
563           _ ___ __ ___  __    _ ___
564           __   _     ___    __  ___
565               _           ___     _
566              _  _ __             _
567              ___   __            _
568                    __           _
569                     _      _   _
570                    _      _    _
571                       _  _    _
572                   __  ___
573                  _   _ _     _
574                 _   _
575               _    _
576              _    _
577             _
578           __
579
580 "
581                ""))
582       ;; And then hack it.
583       (gnus-indent-rigidly (point-min) (point-max)
584                            (/ (max (- (window-width) (or x 46)) 0) 2))
585       (goto-char (point-min))
586       (forward-line 1)
587       (let* ((pheight (count-lines (point-min) (point-max)))
588              (wheight (window-height))
589              (rest (- wheight pheight)))
590         (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
591     ;; Fontify some.
592     (goto-char (point-min))
593     (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)
594     (goto-char (point-min))
595     (setq modeline-buffer-identification
596           (list (concat gnus-version ": *Group*")))
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   '([gnus-group-get-new-news gnus-group-get-new-news t "Get new news"]
612     [gnus-group-get-new-news-this-group
613      gnus-group-get-new-news-this-group t "Get new news in this group"]
614     [gnus-group-catchup-current
615      gnus-group-catchup-current t "Catchup group"]
616     [gnus-group-describe-group
617      gnus-group-describe-group t "Describe group"]
618     [gnus-group-unsubscribe gnus-group-unsubscribe t "Unsubscribe group"]
619     [gnus-group-subscribe gnus-group-subscribe t "Subscribe group"]
620     [gnus-group-kill-group gnus-group-kill-group t "Kill group"]
621     [gnus-group-exit gnus-group-exit t "Exit Gnus"]
622     )
623   "The group buffer toolbar.")
624
625 (defvar gnus-summary-toolbar
626   '([gnus-summary-prev-unread
627      gnus-summary-prev-page-or-article t "Page up"]
628     [gnus-summary-next-unread
629      gnus-summary-next-page t "Page down"]
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
654      gnus-summary-catchup t "Catchup"]
655     [gnus-summary-catchup-and-exit
656      gnus-summary-catchup-and-exit t "Catchup and exit"]
657     [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
658     )
659   "The summary buffer toolbar.")
660
661 (defvar gnus-summary-mail-toolbar
662   '(
663     [gnus-summary-prev-unread
664      gnus-summary-prev-unread-article t "Prev unread article"]
665     [gnus-summary-next-unread
666      gnus-summary-next-unread-article t "Next unread article"]
667     [gnus-summary-mail-reply gnus-summary-reply t "Reply"]
668 ;    [gnus-summary-mail-get gnus-mail-get t "Message get"]
669     [gnus-summary-mail-originate gnus-summary-post-news t "Originate"]
670     [gnus-summary-mail-save gnus-summary-save-article t "Save"]
671     [gnus-summary-mail-copy gnus-summary-copy-article t "Copy message"]
672 ;    [gnus-summary-mail-delete gnus-summary-delete-article t "Delete message"]
673     [gnus-summary-mail-forward gnus-summary-mail-forward t "Forward message"]
674 ;    [gnus-summary-mail-spell gnus-mail-spell t "Spell"]
675 ;    [gnus-summary-mail-help gnus-mail-help  t "Message help"]
676     [gnus-summary-caesar-message
677      gnus-summary-caesar-message t "Rot 13"]
678     [gnus-uu-decode-uu
679      gnus-uu-decode-uu t "Decode uuencoded articles"]
680     [gnus-summary-save-article-file
681      gnus-summary-save-article-file t "Save article in file"]
682     [gnus-summary-save-article
683      gnus-summary-save-article t "Save article"]
684     [gnus-summary-catchup
685      gnus-summary-catchup t "Catchup"]
686     [gnus-summary-catchup-and-exit
687      gnus-summary-catchup-and-exit t "Catchup and exit"]
688     [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
689     )
690   "The summary buffer mail toolbar.")
691
692 (defun gnus-xmas-setup-group-toolbar ()
693   (and gnus-use-toolbar
694        (message-xmas-setup-toolbar gnus-group-toolbar nil "gnus")
695        (set-specifier (symbol-value gnus-use-toolbar)
696                       (cons (current-buffer) gnus-group-toolbar))))
697
698 (defun gnus-xmas-setup-summary-toolbar ()
699   (let ((bar (if (gnus-news-group-p gnus-newsgroup-name)
700                  gnus-summary-toolbar gnus-summary-mail-toolbar)))
701     (and gnus-use-toolbar
702          (message-xmas-setup-toolbar bar nil "gnus")
703          (set-specifier (symbol-value gnus-use-toolbar)
704                         (cons (current-buffer) bar)))))
705
706 (defun gnus-xmas-mail-strip-quoted-names (address)
707   "Protect mail-strip-quoted-names from NIL input.
708 XEmacs compatibility workaround."
709   (if (null address)
710       nil
711     (mail-strip-quoted-names address)))
712
713 (defun gnus-xmas-call-region (command &rest args)
714   (apply
715    'call-process-region (point-min) (point-max) command t '(t nil) nil
716    args))
717
718 (unless (find-face 'gnus-x-face)
719   (copy-face 'default 'gnus-x-face)
720   (set-face-foreground 'gnus-x-face "black")
721   (set-face-background 'gnus-x-face "white"))
722
723 (defun gnus-xmas-article-display-xface (beg end)
724   "Display any XFace headers in the current article."
725   (save-excursion
726     (let (xface-glyph)
727       (if (featurep 'xface)
728           (setq xface-glyph
729                 (make-glyph (vector 'xface :data
730                                     (concat "X-Face: "
731                                             (buffer-substring beg end)))))
732         (let ((cur (current-buffer)))
733           (save-excursion
734             (gnus-set-work-buffer)
735             (insert (format "%s" (buffer-substring beg end cur)))
736             (gnus-xmas-call-region "uncompface")
737             (goto-char (point-min))
738             (insert "/* Width=48, Height=48 */\n")
739             (gnus-xmas-call-region "icontopbm")
740             (gnus-xmas-call-region "ppmtoxpm")
741             (setq xface-glyph
742                   (make-glyph
743                    (vector 'xpm :data (buffer-string )))))))
744       (set-glyph-face xface-glyph 'gnus-x-face)
745       (goto-char (point-min))
746       (re-search-forward "^From:" nil t)
747       (set-extent-begin-glyph
748        (make-extent (point) (1+ (point))) xface-glyph))))
749
750 (defvar gnus-xmas-pointer-glyph
751   (progn
752     (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
753     (make-pointer-glyph (concat gnus-xmas-glyph-directory "gnus-pointer."
754                                 (if (featurep 'xpm) "xpm" "xbm")))))
755
756 (defvar gnus-xmas-modeline-left-extent
757   (let ((ext (copy-extent modeline-buffer-id-left-extent)))
758     ;(set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
759     ext))
760
761 (defvar gnus-xmas-modeline-right-extent
762   (let ((ext (copy-extent modeline-buffer-id-right-extent)))
763     ;(set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
764     ext))
765
766 (defvar gnus-xmas-modeline-glyph
767   (progn
768     (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
769     (let* ((file (concat gnus-xmas-glyph-directory "gnus-pointer."
770                          (if (featurep 'xpm) "xpm" "xbm")))
771            (glyph (make-glyph file)))
772       (when (and (featurep 'x)
773                  (file-exists-p file))
774         (set-glyph-face glyph 'modeline-buffer-id)
775         (set-glyph-property glyph 'image (cons 'tty "Gnus:"))
776         glyph))))
777
778 (defun gnus-xmas-mode-line-buffer-identification (line)
779   (let ((line (car line))
780         chop)
781     (cond
782      ;; This is some weird type of id.
783      ((not (stringp line))
784       (list line))
785      ;; This is non-standard, so we just pass it through.
786      ((not (string-match "^Gnus:" line))
787       (list line))
788      ;; We have a standard line, so we colorize and glyphize it a bit.
789      (t
790       (setq chop (match-end 0))
791       (list
792        (if gnus-xmas-modeline-glyph
793            (cons gnus-xmas-modeline-left-extent gnus-xmas-modeline-glyph)
794          (cons gnus-xmas-modeline-left-extent (substring line 0 chop)))
795        (cons gnus-xmas-modeline-right-extent (substring line chop)))))))
796
797 (defun gnus-xmas-splash ()
798   (when (eq (device-type) 'x)
799     (gnus-splash)))
800
801 (provide 'gnus-xmas)
802
803 ;;; gnus-xmas.el ends here