Move ';;; Code:' comment.
[elisp/wanderlust.git] / elmo / elmo-imap4.el
index 5f1d5e2..6bd10f5 100644 (file)
@@ -38,6 +38,7 @@
 ;;    Author: Simon Josefsson <jas@pdc.kth.se>
 ;;
 
+;;; Code:
 (require 'elmo-vars)
 (require 'elmo-util)
 (require 'elmo-date)
@@ -48,7 +49,6 @@
 (require 'utf7)
 (require 'elmo-mime)
 
-;;; Code:
 (eval-when-compile (require 'cl))
 
 (defvar elmo-imap4-disuse-server-flag-mailbox-regexp "^#mh" ; UW imapd
@@ -210,8 +210,8 @@ Debug information is inserted in the buffer \"*IMAP4 DEBUG*\"")
 
 ;;; Debug
 (defmacro elmo-imap4-debug (message &rest args)
-  (` (if elmo-imap4-debug
-        (elmo-imap4-debug-1 (, message) (,@ args)))))
+  `(if elmo-imap4-debug
+       (elmo-imap4-debug-1 ,message ,@args)))
 
 (defun elmo-imap4-debug-1 (message &rest args)
   (with-current-buffer (get-buffer-create "*IMAP4 DEBUG*")
@@ -234,23 +234,23 @@ Debug information is inserted in the buffer \"*IMAP4 DEBUG*\"")
 
 (defmacro elmo-imap4-response-continue-req-p (response)
   "Returns non-nil if RESPONSE is '+' response."
-  (` (assq 'continue-req (, response))))
+  `(assq 'continue-req ,response))
 
 (defmacro elmo-imap4-response-ok-p (response)
   "Returns non-nil if RESPONSE is an 'OK' response."
-  (` (assq 'ok (, response))))
+  `(assq 'ok ,response))
 
 (defmacro elmo-imap4-response-bye-p (response)
   "Returns non-nil if RESPONSE is an 'BYE' response."
-  (` (assq 'bye (, response))))
+  `(assq 'bye ,response))
 
 (defmacro elmo-imap4-response-garbage-p (response)
   "Returns non-nil if RESPONSE is an 'garbage' response."
-  (` (assq 'garbage (, response))))
+  `(assq 'garbage ,response))
 
 (defmacro elmo-imap4-response-value (response symbol)
   "Get value of the SYMBOL from RESPONSE."
-  (` (nth 1 (assq (, symbol) (, response)))))
+  `(nth 1 (assq ,symbol ,response)))
 
 (defsubst elmo-imap4-response-value-all (response symbol)
   "Get all value of the SYMBOL from RESPONSE."
@@ -263,13 +263,13 @@ Debug information is inserted in the buffer \"*IMAP4 DEBUG*\"")
 
 (defmacro elmo-imap4-response-error-text (response)
   "Returns text of NO, BAD, BYE response."
-  (` (nth 1 (or (elmo-imap4-response-value (, response) 'no)
-               (elmo-imap4-response-value (, response) 'bad)
-               (elmo-imap4-response-value (, response) 'bye)))))
+  `(nth 1 (or (elmo-imap4-response-value ,response 'no)
+             (elmo-imap4-response-value ,response 'bad)
+             (elmo-imap4-response-value ,response 'bye))))
 
 (defmacro elmo-imap4-response-bodydetail-text (response)
   "Returns text of BODY[section]<partial>."
-  (` (nth 3 (assq 'bodydetail (, response)))))
+  `(nth 3 (assq 'bodydetail ,response)))
 
 ;;; Session commands.
 
@@ -937,6 +937,8 @@ If CHOP-LENGTH is not specified, message set is not chopped."
        (concat "(" (downcase (elmo-match-string 1 string)) ")"))))
 
 (defun elmo-imap4-clear-login (session)
+  (when (elmo-imap4-session-capable-p session 'logindisabled)
+    (signal 'elmo-authenticate-error '(elmo-imap4-clear-login)))
   (let ((elmo-imap4-debug-inhibit-logging t))
     (or
      (elmo-imap4-read-ok
@@ -983,8 +985,8 @@ If CHOP-LENGTH is not specified, message set is not chopped."
       ;; Skip garbage output from process before greeting.
       (while (and (memq (process-status process) '(open run))
                  (goto-char (point-max))
-                 (forward-line -1)
-                 (not (elmo-imap4-parse-greeting)))
+                 (or (/= (forward-line -1) 0)
+                     (not (elmo-imap4-parse-greeting))))
        (accept-process-output process 1))
       (erase-buffer)
       (set-process-filter process 'elmo-imap4-arrival-filter)
@@ -1246,13 +1248,11 @@ Return nil if no complete line has arrived."
     (if (match-string 1)
        (if (< (point-max) (+ (point) (string-to-number (match-string 1))))
            (progn
-             (when (elmo-progress-counter-label
-                    elmo-imap4-literal-progress-reporter)
-               (elmo-progress-counter-set-total
-                elmo-imap4-literal-progress-reporter
-                (string-to-number (match-string 1)))
-               (elmo-progress-notify 'elmo-retrieve-message
-                                     :set (- (point-max) (point))))
+             (when elmo-imap4-literal-progress-reporter
+               (elmo-progress-notify
+                'elmo-retrieve-message
+                :set (- (point-max) (point))
+                :total (string-to-number (match-string 1))))
              nil)
          (goto-char (+ (point) (string-to-number (match-string 1))))
          (elmo-imap4-find-next-line))
@@ -1630,12 +1630,13 @@ Return nil if no complete line has arrived."
 
 
 (defmacro elmo-imap4-value (value)
-  (` (if (eq (, value) 'NIL) nil
-       (, value))))
+  `(if (eq ,value 'NIL)
+       nil
+     ,value))
 
 (defmacro elmo-imap4-nth (pos list)
-  (` (let ((value (nth (, pos) (, list))))
-       (elmo-imap4-value value))))
+  `(let ((value (nth ,pos ,list)))
+     (elmo-imap4-value value)))
 
 (defun elmo-imap4-parse-namespace ()
   (list 'namespace
@@ -1942,15 +1943,17 @@ Return nil if no complete line has arrived."
                                                       &optional
                                                       enable-killed)
   (elmo-imap4-list folder
-                  (let ((killed
-                         (elmo-folder-killed-list-internal
-                          folder)))
-                    (if (and killed
-                             (eq (length killed) 1)
-                             (consp (car killed))
-                             (eq (car (car killed)) 1))
-                        (format "uid %d:*" (cdr (car killed)))
-                      "all"))))
+                  (concat
+                   (let ((killed
+                          (elmo-folder-killed-list-internal
+                           folder)))
+                     (if (and killed
+                              (eq (length killed) 1)
+                              (consp (car killed))
+                              (eq (car (car killed)) 1))
+                         (format "uid %d:*" (cdr (car killed)))
+                       "all"))
+                   " undeleted")))
 
 (luna-define-method elmo-folder-list-flagged-plugged
   ((folder elmo-imap4-folder) flag)
@@ -2034,13 +2037,13 @@ Return nil if no complete line has arrived."
                           root)))
            (setq root (concat root delim)))
          (while (setq folder (car result))
-           (when (string-match
-                  (concat "^\\(" (regexp-quote root) "[^" re-delim "]" "+\\)"
-                          re-delim)
-                  folder)
-             (setq folder (match-string 1 folder)))
-           (setq has-child-p nil
-                 result (delq
+           (setq has-child-p
+                 (when (string-match
+                        (concat "^\\(" (regexp-quote root) "[^" re-delim "]" "+\\)"
+                                re-delim)
+                        folder)
+                   (setq folder (match-string 1 folder))))
+           (setq result (delq
                          nil
                          (mapcar (lambda (fld)
                                    (if (string-match
@@ -2087,8 +2090,9 @@ Return nil if no complete line has arrived."
   t)
 
 (luna-define-method elmo-folder-delete ((folder elmo-imap4-folder))
-  (let ((msgs (and (elmo-folder-exists-p folder)
-                  (elmo-folder-list-messages folder))))
+  (let* ((exists (elmo-folder-exists-p folder))
+        (msgs (and exists
+                   (elmo-folder-list-messages folder))))
     (when (yes-or-no-p (format "%sDelete msgdb and substance of \"%s\"? "
                               (if (> (length msgs) 0)
                                   (format "%d msg(s) exists. " (length msgs))
@@ -2097,7 +2101,9 @@ Return nil if no complete line has arrived."
       (let ((session (elmo-imap4-get-session folder)))
        (when (elmo-imap4-folder-mailbox-internal folder)
          (when msgs (elmo-folder-delete-messages-internal folder msgs))
-         (elmo-imap4-send-command-wait session "close")
+         ;; close selected mailbox except one with \Noselect attribute
+         (when exists
+           (elmo-imap4-send-command-wait session "close"))
          (elmo-imap4-send-command-wait
           session
           (list "delete "
@@ -2189,18 +2195,24 @@ If optional argument REMOVE is non-nil, remove FLAG."
 
 (luna-define-method elmo-folder-delete-messages-plugged
   ((folder elmo-imap4-folder) numbers)
-  (let ((session (elmo-imap4-get-session folder)))
+  (let ((session (elmo-imap4-get-session folder))
+       (expunge
+        (or (null (elmo-imap4-list folder "deleted"))
+            (y-or-n-p
+             "There's hidden deleted messages, expunge anyway?"))))
     (elmo-imap4-session-select-mailbox
      session
      (elmo-imap4-folder-mailbox-internal folder))
     (unless (elmo-imap4-set-flag folder numbers "\\Deleted")
       (error "Failed to set deleted flag"))
-    (elmo-imap4-send-command session "expunge")))
+    (when expunge
+      (elmo-imap4-send-command session "expunge"))
+    t))
 
 (defmacro elmo-imap4-detect-search-charset (string)
-  (` (with-temp-buffer
-       (insert (, string))
-       (detect-mime-charset-region (point-min) (point-max)))))
+  `(with-temp-buffer
+     (insert ,string)
+     (detect-mime-charset-region (point-min) (point-max))))
 
 (defun elmo-imap4-search-internal-primitive (folder session filter from-msgs)
   (let ((search-key (elmo-filter-key filter))
@@ -2213,12 +2225,12 @@ If optional argument REMOVE is non-nil, remove FLAG."
      ((string= "last" search-key)
       (let ((numbers (or from-msgs (elmo-folder-list-messages folder))))
        (nthcdr (max (- (length numbers)
-                       (string-to-int (elmo-filter-value filter)))
+                       (string-to-number (elmo-filter-value filter)))
                     0)
                numbers)))
      ((string= "first" search-key)
       (let* ((numbers (or from-msgs (elmo-folder-list-messages folder)))
-            (rest (nthcdr (string-to-int (elmo-filter-value filter) )
+            (rest (nthcdr (string-to-number (elmo-filter-value filter) )
                           numbers)))
        (mapcar '(lambda (x) (delete x numbers)) rest)
        numbers))
@@ -2627,12 +2639,12 @@ If optional argument REMOVE is non-nil, remove FLAG."
 (eval-when-compile
   (defmacro elmo-imap4-identical-system-p (folder1 folder2)
     "Return t if FOLDER1 and FOLDER2 are in the same IMAP4 system."
-    (` (and (string= (elmo-net-folder-server-internal (, folder1))
-                    (elmo-net-folder-server-internal (, folder2)))
-           (eq (elmo-net-folder-port-internal (, folder1))
-               (elmo-net-folder-port-internal (, folder2)))
-           (string= (elmo-net-folder-user-internal (, folder1))
-                    (elmo-net-folder-user-internal (, folder2)))))))
+    `(and (string= (elmo-net-folder-server-internal ,folder1)
+                  (elmo-net-folder-server-internal ,folder2))
+         (eq (elmo-net-folder-port-internal ,folder1)
+             (elmo-net-folder-port-internal ,folder2))
+         (string= (elmo-net-folder-user-internal ,folder1)
+                  (elmo-net-folder-user-internal ,folder2)))))
 
 (luna-define-method elmo-folder-next-message-number-plugged
   ((folder elmo-imap4-folder))
@@ -2694,8 +2706,7 @@ If optional argument REMOVE is non-nil, remove FLAG."
       (setq elmo-imap4-fetch-callback nil)
       (setq elmo-imap4-fetch-callback-data nil))
     (elmo-with-progress-display (elmo-retrieve-message
-                                (or (elmo-message-field folder number :size)
-                                    0)
+                                (elmo-message-field folder number :size)
                                 elmo-imap4-literal-progress-reporter)
        "Retrieving"
       (setq response