X-Git-Url: http://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-util.el;h=62977576a005669cde3788413b8fe5d4c0ed85a2;hb=1c2ed0ce5abe2181e51f777171f8cd40a547e5a9;hp=1a09e04193b15c42f9bdd4f0b859efc5ba332433;hpb=18836c407ba5a49028cc957fa511195199dbbd77;p=gnus diff --git a/lisp/gnus-util.el b/lisp/gnus-util.el index 1a09e0419..62977576a 100644 --- a/lisp/gnus-util.el +++ b/lisp/gnus-util.el @@ -1,7 +1,6 @@ ;;; gnus-util.el --- utility functions for Gnus -;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 1996-2014 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: news @@ -33,16 +32,10 @@ ;;; Code: -;; For Emacs <22.2 and XEmacs. -(eval-and-compile - (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))) (eval-when-compile (require 'cl)) -(eval-when-compile - (unless (fboundp 'with-no-warnings) - (defmacro with-no-warnings (&rest body) - `(progn ,@body)))) +(require 'time-date) (defcustom gnus-completing-read-function 'gnus-emacs-completing-read "Function use to do completing read." @@ -72,7 +65,7 @@ "Value of `completion-styles' to use when completing." :version "24.1" :group 'gnus-meta - :type 'list) + :type '(repeat symbol)) ;; Fixme: this should be a gnus variable, not nnmail-. (defvar nnmail-pathname-coding-system) @@ -173,15 +166,6 @@ This is a compatibility function for different Emacsen." `(delete-region (point-at-bol) (progn (forward-line ,(or n 1)) (point)))) -(defun gnus-byte-code (func) - "Return a form that can be `eval'ed based on FUNC." - (let ((fval (indirect-function func))) - (if (byte-code-function-p fval) - (let ((flist (append fval nil))) - (setcar flist 'byte-code) - flist) - (cons 'progn (cddr fval))))) - (defun gnus-extract-address-components (from) "Extract address components from a From header. Given an RFC-822 address FROM, extract full name and canonical address. @@ -220,16 +204,6 @@ is slower." (match-end 0))))) (list (if (string= name "") nil name) (or address from)))) -(defun gnus-extract-address-component-name (from) - "Extract name from a From header. -Uses `gnus-extract-address-components'." - (nth 0 (gnus-extract-address-components from))) - -(defun gnus-extract-address-component-email (from) - "Extract e-mail address from a From header. -Uses `gnus-extract-address-components'." - (nth 1 (gnus-extract-address-components from))) - (declare-function message-fetch-field "message" (header &optional not-all)) (defun gnus-fetch-field (field) @@ -248,7 +222,7 @@ Uses `gnus-extract-address-components'." (defun gnus-goto-colon () - (beginning-of-line) + (move-beginning-of-line 1) (let ((eol (point-at-eol))) (goto-char (or (text-property-any (point) eol 'gnus-position t) (search-forward ":" eol t) @@ -282,6 +256,24 @@ Uses `gnus-extract-address-components'." (setq start (when end (next-single-property-change start prop)))))) +(defun gnus-find-text-property-region (start end prop) + "Return a list of text property regions that has property PROP." + (let (regions value) + (unless (get-text-property start prop) + (setq start (next-single-property-change start prop))) + (while start + (setq value (get-text-property start prop) + end (text-property-not-all start (point-max) prop value)) + (if (not end) + (setq start nil) + (when value + (push (list (set-marker (make-marker) start) + (set-marker (make-marker) end) + value) + regions)) + (setq start (next-single-property-change start prop)))) + (nreverse regions))) + (defun gnus-newsgroup-directory-form (newsgroup) "Make hierarchical directory name from NEWSGROUP name." (let* ((newsgroup (gnus-newsgroup-savable-name newsgroup)) @@ -319,14 +311,16 @@ Symbols are also allowed; their print names are used instead." (and (= (car fdate) (car date)) (> (nth 1 fdate) (nth 1 date)))))) +;; Every version of Emacs Gnus supports has built-in float-time. +;; The featurep test silences an irritating compiler warning. (eval-and-compile - (if (and (fboundp 'float-time) - (subrp (symbol-function 'float-time))) + (if (or (featurep 'emacs) + (fboundp 'float-time)) (defalias 'gnus-float-time 'float-time) (defun gnus-float-time (&optional time) "Convert time value TIME to a floating point number. TIME defaults to the current time." - (with-no-warnings (time-to-seconds (or time (current-time))))))) + (time-to-seconds (or time (current-time)))))) ;;; Keymap macros. @@ -336,6 +330,13 @@ TIME defaults to the current time." (defmacro gnus-define-keys (keymap &rest plist) "Define all keys in PLIST in KEYMAP." + ;; Convert the key [?\S-\ ] to [(shift space)] for XEmacs. + (when (featurep 'xemacs) + (let ((bindings plist)) + (while bindings + (when (equal (car bindings) [?\S-\ ]) + (setcar bindings [(shift space)])) + (setq bindings (cddr bindings))))) `(gnus-define-keys-1 (quote ,keymap) (quote ,plist))) (defmacro gnus-define-keys-safe (keymap &rest plist) @@ -372,57 +373,14 @@ TIME defaults to the current time." (define-key keymap key (pop plist)) (pop plist))))) -;; Two silly functions to ensure that all `y-or-n-p' questions clear -;; the echo area. -;; -;; Do we really need these functions? Workarounds for bugs in the corresponding -;; Emacs functions? Maybe these bugs are no longer present in any supported -;; (X)Emacs version? Alias them to the original functions and see if anyone -;; reports a problem. If not, replace with original functions. --rsteib, -;; 2007-12-14 -;; -;; All supported Emacsen clear the echo area after `yes-or-no-p', so we can -;; remove `yes-or-no-p'. RMS says that not clearing after `y-or-n-p' is -;; intentional (see below), so we could remove `gnus-y-or-n-p' too. -;; Objections? --rsteib, 2008-02-16 -;; -;; ,----[ http://thread.gmane.org/gmane.emacs.gnus.general/65099/focus=66070 ] -;; | From: Richard Stallman -;; | Subject: Re: Do we need gnus-yes-or-no-p and gnus-y-or-n-p? -;; | To: Katsumi Yamaoka [...] -;; | Cc: emacs-devel@[...], xemacs-beta@[...], ding@[...] -;; | Date: Mon, 07 Jan 2008 12:16:05 -0500 -;; | Message-ID: -;; | -;; | The behavior of `y-or-n-p' that it doesn't clear the question -;; | and the answer is not serious of course, but I feel it is not -;; | cool. -;; | -;; | It is intentional. -;; | -;; | Currently, it is commented out in the trunk by Reiner Steib. He -;; | also wrote the benefit of leaving the question and the answer in -;; | the echo area as follows: -;; | -;; | (http://article.gmane.org/gmane.emacs.gnus.general/66061) -;; | > In contrast to yes-or-no-p it is much easier to type y, n, -;; | > SPC, DEL, etc accidentally, so it might be useful for the user -;; | > to see what he has typed. -;; | -;; | Yes, that is the reason. -;; `---- - -;; (defun gnus-y-or-n-p (prompt) -;; (prog1 -;; (y-or-n-p prompt) -;; (message ""))) -;; (defun gnus-yes-or-no-p (prompt) -;; (prog1 -;; (yes-or-no-p prompt) -;; (message ""))) - -(defalias 'gnus-y-or-n-p 'y-or-n-p) -(defalias 'gnus-yes-or-no-p 'yes-or-no-p) +(defun gnus-y-or-n-p (prompt) + (prog1 + (y-or-n-p prompt) + (message ""))) +(defun gnus-yes-or-no-p (prompt) + (prog1 + (yes-or-no-p prompt) + (message ""))) ;; By Frank Schmitt . Allows to have ;; age-depending date representations. (e.g. just the time if it's @@ -461,51 +419,6 @@ Cache the result as a text property stored in DATE." (put-text-property 0 1 'gnus-time time d) time))))) -(defvar gnus-user-date-format-alist - '(((gnus-seconds-today) . "%k:%M") - (604800 . "%a %k:%M") ;;that's one week - ((gnus-seconds-month) . "%a %d") - ((gnus-seconds-year) . "%b %d") - (t . "%b %d '%y")) ;;this one is used when no - ;;other does match - "Specifies date format depending on age of article. -This is an alist of items (AGE . FORMAT). AGE can be a number (of -seconds) or a Lisp expression evaluating to a number. When the age of -the article is less than this number, then use `format-time-string' -with the corresponding FORMAT for displaying the date of the article. -If AGE is not a number or a Lisp expression evaluating to a -non-number, then the corresponding FORMAT is used as a default value. - -Note that the list is processed from the beginning, so it should be -sorted by ascending AGE. Also note that items following the first -non-number AGE will be ignored. - -You can use the functions `gnus-seconds-today', `gnus-seconds-month' -and `gnus-seconds-year' in the AGE spec. They return the number of -seconds passed since the start of today, of this month, of this year, -respectively.") - -(defun gnus-user-date (messy-date) - "Format the messy-date according to gnus-user-date-format-alist. -Returns \" ? \" if there's bad input or if another error occurs. -Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"." - (condition-case () - (let* ((messy-date (gnus-float-time (gnus-date-get-time messy-date))) - (now (gnus-float-time)) - ;;If we don't find something suitable we'll use this one - (my-format "%b %d '%y")) - (let* ((difference (- now messy-date)) - (templist gnus-user-date-format-alist) - (top (eval (caar templist)))) - (while (if (numberp top) (< top difference) (not top)) - (progn - (setq templist (cdr templist)) - (setq top (eval (caar templist))))) - (if (stringp (cdr (car templist))) - (setq my-format (cdr (car templist))))) - (format-time-string (eval my-format) (seconds-to-time messy-date))) - (error " ? "))) - (defun gnus-dd-mmm (messy-date) "Return a string like DD-MMM from a big messy string." (condition-case () @@ -543,12 +456,13 @@ Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"." (setq i (* 2 i))) i)) -(defcustom gnus-verbose 7 +(defcustom gnus-verbose 6 "*Integer that says how verbose Gnus should be. The higher the number, the more messages Gnus will flash to say what it's doing. At zero, Gnus will be totally mute; at five, Gnus will display most important messages; and at ten, Gnus will keep on jabbering all the time." + :version "24.1" :group 'gnus-start :type 'integer) @@ -569,8 +483,7 @@ but also to the ones displayed in the echo area." (eval-when-compile (defmacro gnus-message-with-timestamp-1 (format-string args) - (let ((timestamp '((format-time-string "%Y%m%dT%H%M%S" time) - "." (format "%03d" (/ (nth 2 time) 1000)) "> "))) + (let ((timestamp '(format-time-string "%Y%m%dT%H%M%S.%3N> " time))) (if (featurep 'xemacs) `(let (str time) (if (or (and (null ,format-string) (null ,args)) @@ -583,10 +496,10 @@ but also to the ones displayed in the echo area." (cond ((eq gnus-add-timestamp-to-message 'log) (setq time (current-time)) (display-message 'no-log str) - (log-message 'message (concat ,@timestamp str))) + (log-message 'message (concat ,timestamp str))) (gnus-add-timestamp-to-message (setq time (current-time)) - (display-message 'message (concat ,@timestamp str))) + (display-message 'message (concat ,timestamp str))) (t (display-message 'message str)))) str) @@ -598,11 +511,14 @@ but also to the ones displayed in the echo area." (> message-log-max 0) (/= (length str) 0)) (setq time (current-time)) - (with-current-buffer (get-buffer-create "*Messages*") + (with-current-buffer (if (fboundp 'messages-buffer) + (messages-buffer) + (get-buffer-create "*Messages*")) (goto-char (point-max)) - (insert ,@timestamp str "\n") - (forward-line (- message-log-max)) - (delete-region (point-min) (point)) + (let ((inhibit-read-only t)) + (insert ,timestamp str "\n") + (forward-line (- message-log-max)) + (delete-region (point-min) (point))) (goto-char (point-max)))) str) (gnus-add-timestamp-to-message @@ -614,7 +530,7 @@ but also to the ones displayed in the echo area." (and ,format-string str) (message nil)) (setq time (current-time)) - (message "%s" (concat ,@timestamp str)) + (message "%s" (concat ,timestamp str)) str)) (t (apply 'message ,format-string ,args)))))))) @@ -701,11 +617,9 @@ If N, return the Nth ancestor instead." (when (string-match "\\(<[^<]+>\\)[ \t]*\\'" references) (match-string 1 references)))))) -(defun gnus-buffer-live-p (buffer) +(defsubst gnus-buffer-live-p (buffer) "Say whether BUFFER is alive or not." - (and buffer - (get-buffer buffer) - (buffer-name (get-buffer buffer)))) + (and buffer (buffer-live-p (get-buffer buffer)))) (defun gnus-horizontal-recenter () "Recenter the current buffer horizontally." @@ -738,10 +652,6 @@ If N, return the Nth ancestor instead." ;; should be gnus-characterp, but this can't be called in XEmacs anyway (cons (and (numberp event) event) event))) -(defun gnus-sortable-date (date) - "Make string suitable for sorting from DATE." - (gnus-time-iso8601 (date-to-time date))) - (defun gnus-copy-file (file &optional to) "Copy FILE to TO." (interactive @@ -888,6 +798,7 @@ Bind `print-quoted' and `print-readably' to t, and `print-length' and (defun gnus-write-buffer (file) "Write the current buffer's contents to FILE." + (require 'nnmail) (let ((file-name-coding-system nnmail-pathname-coding-system)) ;; Make sure the directory exists. (gnus-make-directory (file-name-directory file)) @@ -899,6 +810,15 @@ Bind `print-quoted' and `print-readably' to t, and `print-length' and (when (file-exists-p file) (delete-file file))) +(defun gnus-delete-duplicates (list) + "Remove duplicate entries from LIST." + (let ((result nil)) + (while list + (unless (member (car list) result) + (push (car list) result)) + (pop list)) + (nreverse result))) + (defun gnus-delete-directory (directory) "Delete files in DIRECTORY. Subdirectories remain. If there's no subdirectory, delete DIRECTORY as well." @@ -916,28 +836,6 @@ If there's no subdirectory, delete DIRECTORY as well." (unless dir (delete-directory directory))))) -;; The following two functions are used in gnus-registry. -;; They were contributed by Andreas Fuchs . -(defun gnus-alist-to-hashtable (alist) - "Build a hashtable from the values in ALIST." - (let ((ht (make-hash-table - :size 4096 - :test 'equal))) - (mapc - (lambda (kv-pair) - (puthash (car kv-pair) (cdr kv-pair) ht)) - alist) - ht)) - -(defun gnus-hashtable-to-alist (hash) - "Build an alist from the values in HASH." - (let ((list nil)) - (maphash - (lambda (key value) - (setq list (cons (cons key value) list))) - hash) - list)) - (defun gnus-strip-whitespace (string) "Return STRING stripped of all whitespace." (while (string-match "[\r\n\t ]+" string) @@ -975,18 +873,29 @@ If there's no subdirectory, delete DIRECTORY as well." (setq beg (point))) (gnus-overlay-put (gnus-make-overlay beg (point)) prop val))))) -(defun gnus-put-text-property-excluding-characters-with-faces (beg end - prop val) - "The same as `put-text-property', but don't put props on characters with the `gnus-face' property." - (let ((b beg)) - (while (/= b end) - (when (get-text-property b 'gnus-face) - (setq b (next-single-property-change b 'gnus-face nil end))) - (when (/= b end) +(defun gnus-put-text-property-excluding-characters-with-faces (beg end prop val) + "The same as `put-text-property', except where `gnus-face' is set. +If so, and PROP is `face', set the second element of its value to VAL. +Otherwise, do nothing." + (while (< beg end) + ;; Property values are compared with `eq'. + (let ((stop (next-single-property-change beg 'face nil end))) + (if (get-text-property beg 'gnus-face) + (when (eq prop 'face) + (setcar (cdr (get-text-property beg 'face)) (or val 'default))) (inline - (gnus-put-text-property - b (setq b (next-single-property-change b 'gnus-face nil end)) - prop val)))))) + (gnus-put-text-property beg stop prop val))) + (setq beg stop)))) + +(defun gnus-get-text-property-excluding-characters-with-faces (pos prop) + "The same as `get-text-property', except where `gnus-face' is set. +If so, and PROP is `face', return the second element of its value. +Otherwise, return the value." + (let ((val (get-text-property pos prop))) + (if (and (get-text-property pos 'gnus-face) + (eq prop 'face)) + (cadr val) + (get-text-property pos prop)))) (defmacro gnus-faces-at (position) "Return a list of faces at POSITION." @@ -1025,7 +934,7 @@ If there's no subdirectory, delete DIRECTORY as well." 'previous-extent-change 'previous-char-property-change)) ;;; Protected and atomic operations. dmoore@ucsd.edu 21.11.1996 -;; The primary idea here is to try to protect internal datastructures +;; The primary idea here is to try to protect internal data structures ;; from becoming corrupted when the user hits C-g, or if a hook or ;; similar blows up. Often in Gnus multiple tables/lists need to be ;; updated at the same time, or information can be lost. @@ -1116,6 +1025,15 @@ with potentially long computations." (declare-function mm-append-to-file "mm-util" (start end filename &optional codesys inhibit)) +(declare-function rmail-swap-buffers-maybe "rmail" ()) +(declare-function rmail-maybe-set-message-counters "rmail" ()) +(declare-function rmail-count-new-messages "rmail" (&optional nomsg)) +(declare-function rmail-summary-exists "rmail" ()) +(declare-function rmail-show-message "rmail" (&optional n no-summary)) +;; Macroexpansion of rmail-select-summary: +(declare-function rmail-summary-displayed "rmail" ()) +(declare-function rmail-pop-to-buffer "rmail" (&rest args)) +(declare-function rmail-maybe-display-summary "rmail" ()) (defun gnus-output-to-rmail (filename &optional ask) "Append the current article to an Rmail file named FILENAME. @@ -1123,6 +1041,7 @@ In Emacs 22 this writes Babyl format; in Emacs 23 it writes mbox unless FILENAME exists and is Babyl format." (require 'rmail) (require 'mm-util) + (require 'nnmail) ;; Some of this codes is borrowed from rmailout.el. (setq filename (expand-file-name filename)) ;; FIXME should we really be messing with this defcustom? @@ -1214,6 +1133,7 @@ FILENAME exists and is Babyl format." (defun gnus-output-to-mail (filename &optional ask) "Append the current article to a mail file named FILENAME." + (require 'nnmail) (setq filename (expand-file-name filename)) (let ((artbuf (current-buffer)) (tmpbuf (get-buffer-create " *Gnus-output*"))) @@ -1638,9 +1558,15 @@ SPEC is a predicate specifier that contains stuff like `or', `and', "Call standard `completing-read-function'." (let ((completion-styles gnus-completion-styles)) (completing-read prompt - ;; Old XEmacs (at least 21.4) expect an alist for - ;; collection. - (mapcar 'list collection) + (if (featurep 'xemacs) + ;; Old XEmacs (at least 21.4) expect an alist, + ;; in which the car of each element is a string, + ;; for collection. + (mapcar + (lambda (elem) + (list (format "%s" (or (car-safe elem) elem)))) + collection) + collection) nil require-match initial-input history def))) (autoload 'ido-completing-read "ido") @@ -1651,10 +1577,16 @@ SPEC is a predicate specifier that contains stuff like `or', `and', initial-input history def)) -(autoload 'iswitchb-read-buffer "iswitchb") +(declare-function iswitchb-read-buffer "iswitchb" + (prompt &optional default require-match start matches-set)) +(defvar iswitchb-temp-buflist) + (defun gnus-iswitchb-completing-read (prompt collection &optional require-match initial-input history def) "`iswitchb' based completing-read function." + ;; Make sure iswitchb is loaded before we let-bind its variables. + ;; If it is loaded inside the let, variables can become unbound afterwards. + (require 'iswitchb) (let ((iswitchb-make-buflist-hook (lambda () (setq iswitchb-temp-buflist @@ -1667,11 +1599,11 @@ SPEC is a predicate specifier that contains stuff like `or', `and', (nreverse filtered-choices)))))) (unwind-protect (progn - (when (not iswitchb-mode) - (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)) + (or iswitchb-mode + (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)) (iswitchb-read-buffer prompt def require-match)) - (when (not iswitchb-mode) - (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup))))) + (or iswitchb-mode + (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup))))) (defun gnus-graphic-display-p () (if (featurep 'xemacs) @@ -1758,14 +1690,16 @@ CHOICE is a list of the choice char and help message at IDX." (kill-buffer buf)) tchar)) -(if (fboundp 'select-frame-set-input-focus) +(if (featurep 'emacs) (defalias 'gnus-select-frame-set-input-focus 'select-frame-set-input-focus) - ;; XEmacs 21.4, SXEmacs - (defun gnus-select-frame-set-input-focus (frame) - "Select FRAME, raise it, and set input focus, if possible." - (raise-frame frame) - (select-frame frame) - (focus-frame frame))) + (if (fboundp 'select-frame-set-input-focus) + (defalias 'gnus-select-frame-set-input-focus 'select-frame-set-input-focus) + ;; XEmacs 21.4, SXEmacs + (defun gnus-select-frame-set-input-focus (frame) + "Select FRAME, raise it, and set input focus, if possible." + (raise-frame frame) + (select-frame frame) + (focus-frame frame)))) (defun gnus-frame-or-window-display-name (object) "Given a frame or window, return the associated display name. @@ -1954,6 +1888,8 @@ empty directories from OLD-PATH." (get-char-table ,character ,display-table))) `(aref ,display-table ,character))) +(declare-function image-size "image.c" (spec &optional pixels frame)) + (defun gnus-rescale-image (image size) "Rescale IMAGE to SIZE if possible. SIZE is in format (WIDTH . HEIGHT). Return a new image. @@ -1974,6 +1910,79 @@ Sizes are in pixels." image))) image))) +(defun gnus-recursive-directory-files (dir) + "Return all regular files below DIR." + (let (files) + (dolist (file (directory-files dir t)) + (when (and (not (member (file-name-nondirectory file) '("." ".."))) + (file-readable-p file)) + (cond + ((file-regular-p file) + (push file files)) + ((file-directory-p file) + (setq files (append (gnus-recursive-directory-files file) files)))))) + files)) + +(defun gnus-list-memq-of-list (elements list) + "Return non-nil if any of the members of ELEMENTS are in LIST." + (let ((found nil)) + (dolist (elem elements) + (setq found (or found + (memq elem list)))) + found)) + +(eval-and-compile + (cond + ((fboundp 'match-substitute-replacement) + (defalias 'gnus-match-substitute-replacement 'match-substitute-replacement)) + (t + (defun gnus-match-substitute-replacement (replacement &optional fixedcase literal string subexp) + "Return REPLACEMENT as it will be inserted by `replace-match'. +In other words, all back-references in the form `\\&' and `\\N' +are substituted with actual strings matched by the last search. +Optional FIXEDCASE, LITERAL, STRING and SUBEXP have the same +meaning as for `replace-match'. + +This is the definition of match-substitute-replacement in subr.el from GNU Emacs." + (let ((match (match-string 0 string))) + (save-match-data + (set-match-data (mapcar (lambda (x) + (if (numberp x) + (- x (match-beginning 0)) + x)) + (match-data t))) + (replace-match replacement fixedcase literal match subexp))))))) + +(if (fboundp 'string-match-p) + (defalias 'gnus-string-match-p 'string-match-p) + (defsubst gnus-string-match-p (regexp string &optional start) + "\ +Same as `string-match' except this function does not change the match data." + (save-match-data + (string-match regexp string start)))) + +(if (fboundp 'string-prefix-p) + (defalias 'gnus-string-prefix-p 'string-prefix-p) + (defun gnus-string-prefix-p (str1 str2 &optional ignore-case) + "Return non-nil if STR1 is a prefix of STR2. +If IGNORE-CASE is non-nil, the comparison is done without paying attention +to case differences." + (and (<= (length str1) (length str2)) + (let ((prefix (substring str2 0 (length str1)))) + (if ignore-case + (string-equal (downcase str1) (downcase prefix)) + (string-equal str1 prefix)))))) + +;; Simple check: can be a macro but this way, although slow, it's really clear. +;; We don't use `bound-and-true-p' because it's not in XEmacs. +(defun gnus-bound-and-true-p (sym) + (and (boundp sym) (symbol-value sym))) + +(if (fboundp 'timer--function) + (defalias 'gnus-timer--function 'timer--function) + (defun gnus-timer--function (timer) + (elt timer 5))) + (provide 'gnus-util) ;;; gnus-util.el ends here