Synch to Gnus 200312030159.
[elisp/gnus.git-] / lisp / gnus-xmas.el
index 36b2b20..6fff59e 100644 (file)
@@ -1,9 +1,10 @@
 ;;; gnus-xmas.el --- Gnus functions for XEmacs
 
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile
+  (autoload 'gnus-active "gnus" nil nil 'macro)
+  (autoload 'gnus-group-entry "gnus" nil nil 'macro)
+  (autoload 'gnus-info-level "gnus" nil nil 'macro)
+  (autoload 'gnus-info-marks "gnus" nil nil 'macro)
+  (autoload 'gnus-info-method "gnus" nil nil 'macro)
+  (autoload 'gnus-info-score "gnus" nil nil 'macro))
+
 (require 'text-props)
 (defvar menu-bar-mode (featurep 'menubar))
 (require 'messagexmas)
@@ -340,8 +349,10 @@ call it with the value of the `gnus-data' text property."
   (gnus-xmas-menu-add grouplens
     gnus-grouplens-menu))
 
-(defun gnus-xmas-read-event-char ()
+(defun gnus-xmas-read-event-char (&optional prompt)
   "Get the next event."
+  (when prompt
+    (message "%s" prompt))
   (let ((event (next-command-event)))
     (sit-for 0)
     ;; We junk all non-key events.  Is this naughty?
@@ -388,9 +399,10 @@ call it with the value of the `gnus-data' text property."
   (defalias 'gnus-put-text-property 'gnus-xmas-put-text-property)
   (defalias 'gnus-deactivate-mark 'ignore)
   (defalias 'gnus-window-edges 'window-pixel-edges)
-  
+  (defalias 'gnus-assq-delete-all 'gnus-xmas-assq-delete-all)
+
   (if (and (<= emacs-major-version 19)
-          (< emacs-minor-version 14))
+          (< emacs-minor-version 14))
       (defalias 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
 
   (unless (boundp 'standard-display-table)
@@ -405,15 +417,12 @@ call it with the value of the `gnus-data' text property."
          (list 'funcall fval)
        (cons 'progn (cdr (cdr fval))))))
 
-  (unless (fboundp 'match-string-no-properties)
-    (defalias 'match-string-no-properties 'match-string))
-
   (defalias 'gnus-x-color-values
-       (if (fboundp 'x-color-values)
-           'x-color-values
-         (lambda (color)
-           (color-instance-rgb-components
-            (make-color-instance color))))))
+    (if (fboundp 'x-color-values)
+       'x-color-values
+      (lambda (color)
+       (color-instance-rgb-components
+        (make-color-instance color))))))
 
 (defun gnus-xmas-redefine ()
   "Redefine lots of Gnus functions for XEmacs."
@@ -427,13 +436,14 @@ call it with the value of the `gnus-data' text property."
   (defalias 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
   (defalias 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
   (defalias 'gnus-appt-select-lowest-window
-       'gnus-xmas-appt-select-lowest-window)
+    'gnus-xmas-appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'character-to-event)
   (defalias 'gnus-mode-line-buffer-identification
-       'gnus-xmas-mode-line-buffer-identification)
+    'gnus-xmas-mode-line-buffer-identification)
   (defalias 'gnus-key-press-event-p 'key-press-event-p)
   (defalias 'gnus-region-active-p 'region-active-p)
+  (defalias 'gnus-mark-active-p 'region-exists-p)
   (defalias 'gnus-annotation-in-region-p 'gnus-xmas-annotation-in-region-p)
   (defalias 'gnus-mime-button-menu 'gnus-xmas-mime-button-menu)
   (defalias 'gnus-image-type-available-p 'gnus-xmas-image-type-available-p)
@@ -441,6 +451,11 @@ call it with the value of the `gnus-data' text property."
   (defalias 'gnus-create-image 'gnus-xmas-create-image)
   (defalias 'gnus-remove-image 'gnus-xmas-remove-image)
 
+  (when (or (< emacs-major-version 21)
+           (and (= emacs-major-version 21)
+                (< emacs-minor-version 3)))
+    (defalias 'gnus-completing-read 'gnus-xmas-completing-read))
+
   ;; These ones are not defcutom'ed, sometimes not even defvar'ed. They
   ;; probably should. If that is done, the code below should then be moved
   ;; where each variable is defined, in order not to mess with user settings.
@@ -451,8 +466,62 @@ call it with the value of the `gnus-data' text property."
   (add-hook 'gnus-server-mode-hook 'gnus-xmas-server-menu-add)
   (add-hook 'gnus-browse-mode-hook 'gnus-xmas-browse-menu-add)
   (add-hook 'gnus-draft-mode-hook 'gnus-xmas-draft-menu-add)
-  (add-hook 'gnus-mailing-list-mode-hook 'gnus-xmas-mailing-list-menu-add))
-
+  (add-hook 'gnus-mailing-list-mode-hook 'gnus-xmas-mailing-list-menu-add)
+
+  (when (featurep 'mule)
+    (defun gnus-truncate-string (str end-column &optional start-column padding)
+      "Truncate string STR to end at column END-COLUMN.
+The optional 2nd arg START-COLUMN, if non-nil, specifies
+the starting column; that means to return the characters occupying
+columns START-COLUMN ... END-COLUMN of STR.
+
+The optional 3rd arg PADDING, if non-nil, specifies a padding character
+to add at the end of the result if STR doesn't reach column END-COLUMN,
+or if END-COLUMN comes in the middle of a character in STR.
+PADDING is also added at the beginning of the result
+if column START-COLUMN appears in the middle of a character in STR.
+
+If PADDING is nil, no padding is added in these cases, so
+the resulting string may be narrower than END-COLUMN.
+\[Emacs 20.3 emulating function]"
+      (or start-column
+         (setq start-column 0))
+      (let ((len (length str))
+           (idx 0)
+           (column 0)
+           (head-padding "") (tail-padding "")
+           ch last-column last-idx from-idx)
+       (condition-case nil
+           (while (< column start-column)
+             (setq ch (aref str idx)
+                   column (+ column (char-width ch))
+                   idx (1+ idx)))
+         (args-out-of-range (setq idx len)))
+       (if (< column start-column)
+           (if padding (make-string end-column padding) "")
+         (if (and padding (> column start-column))
+             (setq head-padding
+                   (make-string (- column start-column) padding)))
+         (setq from-idx idx)
+         (if (< end-column column)
+             (setq idx from-idx)
+           (condition-case nil
+               (while (< column end-column)
+                 (setq last-column column
+                       last-idx idx
+                       ch (aref str idx)
+                       column (+ column (char-width ch))
+                       idx (1+ idx)))
+             (args-out-of-range (setq idx len)))
+           (if (> column end-column)
+               (setq column last-column idx last-idx))
+           (if (and padding (< column end-column))
+               (setq tail-padding
+                     (make-string (- end-column column) padding))))
+         (setq str (substring str from-idx idx))
+         (if padding
+             (concat head-padding str tail-padding)
+           str))))))
 
 ;;; XEmacs logo and toolbar.
 
@@ -473,10 +542,15 @@ call it with the value of the `gnus-data' text property."
                            :color-symbols
                            (("thing" . ,(car gnus-logo-colors))
                             ("shadow" . ,(cadr gnus-logo-colors))
+                            ("oort" . "#eeeeee")
                             ("background" . ,(face-background 'default)))])
                         ((featurep 'xbm)
                          `[xbm :file ,logo-xbm])
-                        (t [nothing])))))
+                        (t [nothing]))))
+          (wpheight (window-pixel-height))
+          (rest (max 0 (1- (/ (* (- wpheight (glyph-height glyph))
+                                 (window-height))
+                              wpheight 2)))))
       (insert " ")
       (set-extent-begin-glyph (make-extent (point) (point)) glyph)
       (goto-char (point-min))
@@ -484,37 +558,57 @@ call it with the value of the `gnus-data' text property."
        (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
                             ?\ ))
        (forward-line 1))
-      (setq gnus-simple-splash nil))
-    (goto-char (point-min))
-    (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
-          (wheight (window-height))
-          (rest (- wheight pheight)))
-      (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
+      (setq gnus-simple-splash nil)
+      (goto-char (point-min))
+      (insert gnus-product-name " " gnus-version-number
+             (if (zerop (string-to-number gnus-revision-number))
+                 ""
+               (concat " (r" gnus-revision-number ")"))
+             " based on " gnus-original-product-name " v"
+             gnus-original-version-number "\n")
+      (end-of-line 0)
+      (put-text-property (point-min) (point) 'face 'gnus-splash-face)
+      (insert-char ?\  (prog1
+                          (max 0 (/ (- (window-width) (point)) 2))
+                        (goto-char (point-min))))
+      (forward-line 1)
+      (insert-char ?\n rest)
+      (set-window-start (selected-window) (point-min))))
    (t
-    (insert
-     (format "              %s
-          _    ___ _             _
-          _ ___ __ ___  __    _ ___
-          __   _     ___    __  ___
-              _           ___     _
-             _  _ __             _
-             ___   __            _
-                   __           _
-                    _      _   _
-                   _      _    _
-                      _  _    _
-                  __  ___
-                 _   _ _     _
-                _   _
-              _    _
-             _    _
-            _
-          __
+    (insert "
+         _    ___ _             _
+         _ ___ __ ___  __    _ ___
+         __   _     ___    __  ___
+             _           ___     _
+            _  _ __             _
+            ___   __            _
+                  __           _
+                   _      _   _
+                  _      _    _
+                     _  _    _
+                 __  ___
+                _   _ _     _
+               _   _
+             _    _
+            _    _
+           _
+         __
 
 "
-            ""))
+           )
+    (goto-char (point-min))
+    (insert gnus-product-name " " gnus-version-number
+           (if (zerop (string-to-number gnus-revision-number))
+               ""
+             (concat " (r" gnus-revision-number ")"))
+           " based on " gnus-original-product-name " v"
+           gnus-original-version-number)
+    (insert-char ?\  (prog1
+                        (max 0 (/ (- (window-width) (point)) 2))
+                      (goto-char (point-min))))
+    (forward-line 1)
     ;; And then hack it.
-    (gnus-indent-rigidly (point-min) (point-max)
+    (gnus-indent-rigidly (point) (point-max)
                         (/ (max (- (window-width) (or x 46)) 0) 2))
     (goto-char (point-min))
     (forward-line 1)
@@ -524,6 +618,7 @@ call it with the value of the `gnus-data' text property."
       (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))
     ;; Paint it.
     (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)))
+  (goto-char (point-min))
   (setq modeline-buffer-identification
        (list (concat gnus-version ": *Group*")))
   (set-buffer-modified-p t))
@@ -555,6 +650,8 @@ If it is non-nil, it must be a toolbar.  The five valid values are
     [gnus-group-unsubscribe gnus-group-unsubscribe t "Unsubscribe group"]
     [gnus-group-subscribe gnus-group-subscribe t "Subscribe group"]
     [gnus-group-kill-group gnus-group-kill-group t "Kill group"]
+    [gnus-summary-mail-save
+     gnus-group-save-newsrc t "Save .newsrc files"] ; borrowed icon.
     [gnus-group-exit gnus-group-exit t "Exit Gnus"])
   "The group buffer toolbar.")
 
@@ -612,6 +709,8 @@ If it is non-nil, it must be a toolbar.  The five valid values are
      gnus-summary-save-article-file t "Save article in file"]
     [gnus-summary-save-article
      gnus-summary-save-article t "Save article"]
+    [gnus-summary-cancel-article ; usenet : cancellation :: mail : deletion.
+     gnus-summary-delete-article t "Delete message"]
     [gnus-summary-catchup
      gnus-summary-catchup t "Catchup"]
     [gnus-summary-catchup-and-exit
@@ -645,41 +744,6 @@ XEmacs compatibility workaround."
    'call-process-region (point-min) (point-max) command t '(t nil) nil
    args))
 
-(defface gnus-x-face '((t (:foreground "black" :background "white")))
-  "Face to show X face"
-  :group 'gnus-xmas)
-
-(defun gnus-xmas-article-display-xface (data)
-  "Display the XFace in DATA."
-  (save-excursion
-    (let ((xface-glyph
-          (cond
-           ((featurep 'xface)
-            (make-glyph (vector 'xface :data
-                                (concat "X-Face: " data))))
-           ((featurep 'xpm)
-            (let ((cur (current-buffer)))
-              (save-excursion
-                (gnus-set-work-buffer)
-                (insert data)
-                (let ((coding-system-for-read 'binary)
-                      (coding-system-for-write 'binary))
-                  (gnus-xmas-call-region "uncompface")
-                  (goto-char (point-min))
-                  (insert "/* Width=48, Height=48 */\n")
-                  (gnus-xmas-call-region "icontopbm")
-                  (gnus-xmas-call-region "ppmtoxpm")
-                  (make-glyph
-                   (vector 'xpm :data (buffer-string)))))))
-           (t
-            (make-glyph [nothing])))))
-      ;;(set-glyph-face xface-glyph 'gnus-x-face)
-
-      (gnus-article-goto-header "from")
-      (gnus-put-image xface-glyph " ")
-      (gnus-add-wash-type 'xface)
-      (gnus-add-image 'xface xface-glyph))))
-
 (defvar gnus-xmas-modeline-left-extent
   (let ((ext (copy-extent modeline-buffer-id-left-extent)))
     ext))
@@ -736,9 +800,9 @@ XEmacs compatibility workaround."
          (eq (cadr (memq 'gnus-undeletable (text-properties-at b))) t)
        (text-property-any b e 'gnus-undeletable t))))
 
-(defun gnus-xmas-mime-button-menu (event)
+(defun gnus-xmas-mime-button-menu (event prefix)
   "Construct a context-sensitive menu of MIME commands."
-  (interactive "e")
+  (interactive "e\nP")
   (let ((response (get-popup-menu-response
                   `("MIME Part"
                     ,@(mapcar (lambda (c) `[,(caddr c) ,(car c) t])
@@ -750,7 +814,7 @@ XEmacs compatibility workaround."
 (defun gnus-group-add-icon ()
   "Add an icon to the current line according to `gnus-group-icon-list'."
   (let* ((p (point))
-        (end (progn (end-of-line) (point)))
+        (end (gnus-point-at-eol))
         ;; now find out where the line starts and leave point there.
         (beg (progn (beginning-of-line) (point))))
     (save-restriction
@@ -817,32 +881,101 @@ XEmacs compatibility workaround."
 
 (defun gnus-xmas-mailing-list-menu-add ()
   (gnus-xmas-menu-add mailing-list
-                     gnus-mailing-list-menu))
+    gnus-mailing-list-menu))
 
 (defun gnus-xmas-image-type-available-p (type)
-  (featurep type))
-
-(defun gnus-xmas-create-image (file)
-  (with-temp-buffer
-    (insert-file-contents file)
-    (mm-create-image-xemacs (car (last (split-string file "[.]"))))))
-
-(defun gnus-xmas-put-image (glyph &optional string)
+  (and window-system
+       (featurep (if (eq type 'pbm) 'xbm type))))
+
+(defun gnus-xmas-create-image (file &optional type data-p &rest props)
+  (let ((type (if type
+                 (symbol-name type)
+               (car (last (split-string file "[.]")))))
+       (face (plist-get props :face))
+       glyph)
+    (when (equal type "pbm")
+      (with-temp-buffer
+       (if data-p
+           (insert file)
+         (insert-file-contents-literally file))
+       (shell-command-on-region (point-min) (point-max)
+                                "ppmtoxpm 2>/dev/null" t)
+       (setq file (buffer-string)
+             type "xpm"
+             data-p t)))
+    (setq glyph
+         (if (equal type "xbm")
+             (make-glyph (list (cons 'x file)))
+           (with-temp-buffer
+             (if data-p
+                 (insert file)
+               (insert-file-contents-literally file))
+             (make-glyph
+              (vector
+               (or (intern type)
+                   (mm-image-type-from-buffer))
+               :data (buffer-string))))))
+    (when face
+      (set-glyph-face glyph face))
+    glyph))
+
+(defun gnus-xmas-put-image (glyph &optional string category)
+  "Insert STRING, but display GLYPH.
+Warning: Don't insert text immediately after the image."
   (let ((begin (point))
        extent)
-    (insert string)
+    (if (and (bobp) (not string))
+       (setq string " "))
+    (if string
+       (insert string)
+      (setq begin (1- begin)))
     (setq extent (make-extent begin (point)))
-    (set-extent-property extent 'gnus-image t)
+    (set-extent-property extent 'gnus-image category)
     (set-extent-property extent 'duplicable t)
-    (set-extent-property extent 'begin-glyph glyph)))
+    (if string
+       (set-extent-property extent 'invisible t))
+    (set-extent-property extent 'end-glyph glyph))
+  glyph)
 
-(defun gnus-xmas-remove-image (image)
+(defun gnus-xmas-remove-image (image &optional category)
   (map-extents
    (lambda (ext unused)
-     (when (equal (extent-begin-glyph ext) image)
-       (set-extent-property ext 'begin-glyph nil))
+     (when (equal (extent-end-glyph ext) image)
+       (set-extent-property ext 'invisible nil)
+       (set-extent-property ext 'end-glyph nil))
      nil)
-   nil nil nil nil nil 'gnus-image))
+   nil nil nil nil nil 'gnus-image category))
+
+(defun gnus-xmas-completing-read (prompt table &optional
+                                        predicate require-match history)
+  (when (and history
+            (not (boundp history)))
+    (set history nil))
+  (completing-read
+   (if (symbol-value history)
+       (concat prompt " (" (car (symbol-value history)) "): ")
+     (concat prompt ": "))
+   table
+   predicate
+   require-match
+   nil
+   history))
+
+;; This macro is because XEmacs versions prior to 21.2 do not have the
+;; PROTOCOL argument to `open-network-stream'.
+(defmacro gnus-xmas-open-network-stream (name buffer host service &optional protocol)
+  "Like `open-network-stream' but take into account older XEmacs versions."
+  (if (and (featurep 'xemacs)
+          (fboundp 'open-network-stream)
+          (emacs-version>= 21 2))
+      `(open-network-stream ,name ,buffer ,host ,service ,protocol)
+    `(open-network-stream ,name ,buffer ,host ,service)))
+
+(defun gnus-xmas-assq-delete-all (key alist)
+  (let ((elem nil))
+    (while (setq elem (assq key alist))
+      (setq alist (delq elem alist)))
+    alist))
 
 (provide 'gnus-xmas)