+ (if (and (elmo-folder-plugged-p folder)
+ (wl-folder-entity-exists-p (elmo-folder-name-internal folder)))
+ (progn
+ (elmo-folder-set-biff-internal folder t)
+ (if (and (eq (elmo-folder-type-internal folder) 'imap4)
+ (elmo-folder-use-flag-p folder))
+ ;; Check asynchronously only when IMAP4 and use server diff.
+ (progn
+ (setq elmo-folder-diff-async-callback
+ 'wl-biff-check-folder-async-callback)
+ (setq elmo-folder-diff-async-callback-data
+ (list (elmo-folder-name-internal folder)
+ (get-buffer wl-folder-buffer-name)
+ notify-minibuf))
+ (elmo-folder-diff-async folder))
+ (unwind-protect
+ (wl-biff-notify (car (wl-biff-check-folder folder))
+ notify-minibuf)
+ (setq wl-biff-check-folders-running nil))))
+ (setq wl-biff-check-folders-running nil)))
+
+(if (and (fboundp 'regexp-opt)
+ (not (featurep 'xemacs)))
+ (defalias 'wl-regexp-opt 'regexp-opt)
+ (defun wl-regexp-opt (strings &optional paren)
+ "Return a regexp to match a string in STRINGS.
+Each string should be unique in STRINGS and should not contain any regexps,
+quoted or not. If optional PAREN is non-nil, ensure that the returned regexp
+is enclosed by at least one regexp grouping construct."
+ (let ((open-paren (if paren "\\(" "")) (close-paren (if paren "\\)" "")))
+ (concat open-paren (mapconcat 'regexp-quote strings "\\|")
+ close-paren))))
+
+(defalias 'wl-expand-newtext 'elmo-expand-newtext)
+(defalias 'wl-regexp-opt 'elmo-regexp-opt)
+
+(defun wl-region-exists-p ()
+ "Return non-nil if a region exists on current buffer."
+ (static-if (featurep 'xemacs)
+ (region-active-p)
+ (and transient-mark-mode mark-active)))
+
+(defun wl-deactivate-region ()
+ "Deactivate region on current buffer"
+ (static-if (not (featurep 'xemacs))
+ (setq mark-active nil)))
+
+(defvar wl-line-string)
+(defun wl-line-parse-format (format spec-alist)
+ "Make a formatter from FORMAT and SPEC-ALIST."
+ (let (f spec specs stack)
+ (setq f
+ (with-temp-buffer
+ (insert format)
+ (goto-char (point-min))
+ (while (search-forward "%" nil t)
+ (cond
+ ((looking-at "%")
+ (goto-char (match-end 0)))
+ ((looking-at "\\(-?\\(0?\\)[0-9]*\\)\\([^0-9]\\)")
+ (cond
+ ((string= (match-string 3) "(")
+ (if (zerop (length (match-string 1)))
+ (error "No number specification for %%( line format"))
+ (push (list
+ (match-beginning 0) ; start
+ (match-end 0) ; start-content
+ (string-to-number
+ (match-string 1)) ; width
+ specs) ; specs
+ stack)
+ (setq specs nil))
+ ((string= (match-string 3) ")")
+ (let ((entry (pop stack))
+ form)
+ (unless entry
+ (error
+ "No matching %%( parenthesis in summary line format"))
+ (goto-char (car entry)) ; start
+ (setq form (buffer-substring (nth 1 entry) ; start-content
+ (- (match-beginning 0) 1)))
+ (delete-region (car entry) (match-end 0))
+ (insert "s")
+ (setq specs
+ (append
+ (nth 3 entry)
+ (list (list 'wl-set-string-width (nth 2 entry)
+ (append
+ (list 'format form)
+ specs)))))))
+ (t
+ (setq spec
+ (if (setq spec (assq (string-to-char (match-string 3))
+ spec-alist))
+ (nth 1 spec)
+ (match-string 3)))
+ (unless (string= "" (match-string 1))
+ (setq spec (list 'wl-set-string-width
+ (string-to-number (match-string 1))
+ spec
+ (unless (string= "" (match-string 2))
+ (string-to-char (match-string 2))))))
+ (replace-match "s" 'fixed)
+ (setq specs (append specs
+ (list
+ (list
+ 'setq 'wl-line-string
+ spec)))))))))
+ (buffer-string)))
+ (append (list 'format f) specs)))
+
+(defmacro wl-line-formatter-setup (formatter format alist)
+ `(let (byte-compile-warnings)
+ (setq ,formatter
+ (byte-compile
+ (list 'lambda ()
+ (wl-line-parse-format ,format ,alist))))
+ (when (get-buffer "*Compile-Log*")
+ (bury-buffer "*Compile-Log*"))
+ (when (get-buffer "*Compile-Log-Show*")
+ (bury-buffer "*Compile-Log-Show*"))))
+
+(defsubst wl-copy-local-variables (src dst local-variables)
+ "Copy value of LOCAL-VARIABLES from SRC buffer to DST buffer."
+ (with-current-buffer dst
+ (dolist (variable local-variables)
+ (set (make-local-variable variable)
+ (with-current-buffer src
+ (symbol-value variable))))))
+
+;;; Search Condition
+(defun wl-search-condition-fields ()
+ (let ((denial-fields
+ (nconc (mapcar 'capitalize elmo-msgdb-extra-fields)
+ (mapcar 'capitalize wl-additional-search-condition-fields)
+ '("Flag" "Since" "Before"
+ "From" "Subject" "To" "Cc" "Body" "ToCc"
+ "Larger" "Smaller"))))
+ (append '("Last" "First")
+ denial-fields
+ (mapcar (lambda (f) (concat "!" f))
+ denial-fields))))
+
+(defun wl-read-search-condition (default)
+ "Read search condition string interactively."
+ (wl-read-search-condition-internal "Search by" default))
+
+(defun wl-read-search-condition-internal (prompt default &optional paren)
+ (let* ((completion-ignore-case t)
+ (field (completing-read
+ (format "%s (%s): " prompt default)
+ (mapcar #'list
+ (append '("AND" "OR") (wl-search-condition-fields)))))
+ value)
+ (setq field (if (string= field "")
+ (setq field default)
+ field))
+ (cond
+ ((or (string= field "AND") (string= field "OR"))
+ (concat (if paren "(" "")
+ (wl-read-search-condition-internal
+ (concat field "(1) Search by") default 'paren)
+ (if (string= field "AND") "&" "|")
+ (wl-read-search-condition-internal
+ (concat field "(2) Search by") default 'paren)
+ (if paren ")" "")))
+ ((string-match "Since\\|Before" field)
+ (let ((default (format-time-string "%Y-%m-%d")))
+ (setq value (completing-read
+ (format "Value for '%s' [%s]: " field default)
+ (mapcar
+ (lambda (x)
+ (list (format "%s" (car x))))
+ elmo-date-descriptions)))
+ (concat (downcase field) ":"
+ (if (equal value "") default value))))
+ ((string-match "!?Flag" field)
+ (while (null value)
+ (setq value (downcase
+ (completing-read
+ (format "Value for '%s': " field)
+ (mapcar (lambda (f) (list (capitalize (symbol-name f))))
+ (elmo-uniq-list
+ (append
+ '(unread answered forwarded digest any)
+ (copy-sequence elmo-global-flags))
+ #'delq)))))
+ (unless (elmo-flag-valid-p value)
+ (message "Invalid char in `%s'" value)
+ (setq value nil)
+ (sit-for 1)))
+ (unless (string-match (concat "^" elmo-condition-atom-regexp "$")
+ value)
+ (setq value (prin1-to-string value)))
+ (concat (downcase field) ":" value))
+ (t
+ (setq value (read-from-minibuffer (format "Value for '%s': " field)))
+ (unless (string-match (concat "^" elmo-condition-atom-regexp "$")
+ value)
+ (setq value (prin1-to-string value)))
+ (concat (downcase field) ":" value)))))
+
+(defun wl-y-or-n-p-with-scroll (prompt &optional scroll-by-SPC)
+ (let ((prompt (concat prompt (if scroll-by-SPC
+ "<y/n/SPC(down)/BS(up)> "
+ "<y/n/j(down)/k(up)> "))))
+ (catch 'done
+ (while t
+ (discard-input)
+ (case (let ((cursor-in-echo-area t))
+ (cdr (wl-read-event-char prompt)))
+ ((?y ?Y)
+ (throw 'done t))
+ ((string-to-char " ")
+ (if scroll-by-SPC
+ (ignore-errors (scroll-up))
+ (throw 'done t)))
+ ((?v ?j ?J next)
+ (ignore-errors (scroll-up)))
+ ((?^ ?k ?K prior backspace)
+ (ignore-errors (scroll-down)))
+ (t
+ (throw 'done nil)))))))
+
+(defun wl-find-region (beg-regexp end-regexp)
+ (if (or (re-search-forward end-regexp nil t)
+ (re-search-backward end-regexp nil t))
+ (let ((end (match-end 0))
+ (beg (re-search-backward beg-regexp nil t)))
+ (if beg
+ (cons beg end)))))
+
+(defun wl-simple-display-progress (label action current total)
+ (message "%s... %d%%"
+ action
+ (if (> total 0) (floor (* (/ current (float total)) 100)) 0)))
+
+(when (fboundp 'progress-feedback-with-label)
+ (defun wl-display-progress-with-gauge (label action current total)
+ (progress-feedback-with-label
+ label
+ "%s..."
+ (if (> total 0) (floor (* (/ current (float total)) 100)) 0)
+ action)))
+
+(defun wl-progress-callback-function (label action current total)
+ (case current
+ (query
+ (let ((threshold (if (consp wl-display-progress-threshold)
+ (cdr (or (assq label wl-display-progress-threshold)
+ (assq t wl-display-progress-threshold)))
+ wl-display-progress-threshold)))
+ (and threshold
+ (>= total threshold))))
+ (start
+ (message "%s..." action))
+ (done
+ (message "%s...done" action))
+ (t
+ (when wl-display-progress-function
+ (funcall wl-display-progress-function label action current total)))))
+
+;; read multiple strings with completion
+(defun wl-completing-read-multiple-1 (prompt
+ table
+ &optional predicate
+ require-match initial-input
+ hist def inherit-input-method)
+ "Read multiple strings in the minibuffer"
+ (split-string
+ (completing-read prompt table predicate nil
+ initial-input hist def inherit-input-method)
+ ","))
+
+(static-when (fboundp 'completing-read-multiple)
+ (eval-when-compile
+ (require 'crm))
+ (defun wl-completing-read-multiple-2 (prompt
+ table
+ &optional predicate
+ require-match initial-input
+ hist def inherit-input-method)
+ "Read multiple strings in the minibuffer"
+ (let ((ret (completing-read-multiple prompt table predicate
+ require-match initial-input
+ hist def inherit-input-method)))
+ (if (and def (equal ret '("")))
+ (split-string def crm-separator)
+ ret))))
+
+(static-cond
+ ((not (fboundp 'completing-read-multiple))
+ (defalias 'wl-completing-read-multiple 'wl-completing-read-multiple-1))
+ ((< emacs-major-version 22)
+ (defun wl-completing-read-multiple (prompt
+ table
+ &optional predicate
+ require-match initial-input
+ hist def inherit-input-method)
+ "Read multiple strings in the minibuffer"
+ (if require-match
+ (wl-completing-read-multiple-1 prompt table predicate
+ nil initial-input
+ hist def inherit-input-method)
+ (wl-completing-read-multiple-2 prompt table predicate
+ nil initial-input
+ hist def inherit-input-method))))
+ (t
+ (defalias 'wl-completing-read-multiple 'completing-read-multiple)))
+
+
+(cond
+ ((fboundp 'shell-command-read-minibuffer)
+ (defun wl-read-shell-command (prompt &optional
+ initial-contents keymap read hist)
+ (shell-command-read-minibuffer prompt default-directory
+ initial-contents keymap read hist)))
+ (t
+ (defalias 'wl-read-shell-command 'read-from-minibuffer)))
+
+(require 'product)
+(product-provide (provide 'wl-util) (require 'wl-version))