Synch to No Gnus 200506160601, and
[elisp/gnus.git-] / lisp / mm-util.el
index f5d4be0..d365044 100644 (file)
@@ -57,7 +57,8 @@
                    mm-mime-mule-charset-alist)
            nil t))))
      (subst-char-in-string
-      . (lambda (from to string &optional inplace) ;; stolen (and renamed) from nnheader.el
+      . (lambda (from to string &optional inplace)
+         ;; stolen (and renamed) from nnheader.el
          "Replace characters in STRING from FROM to TO.
          Unless optional argument INPLACE is non-nil, return a new string."
          (let ((string (if inplace string (copy-sequence string)))
          (replace-regexp-in-string regexp rep string nil literal)))
      (string-as-unibyte . identity)
      (string-make-unibyte . identity)
+     ;; string-as-multibyte often doesn't really do what you think it does.
+     ;; Example:
+     ;;    (aref (string-as-multibyte "\201") 0) -> 129 (aka ?\201)
+     ;;    (aref (string-as-multibyte "\300") 0) -> 192 (aka ?\300)
+     ;;    (aref (string-as-multibyte "\300\201") 0) -> 192 (aka ?\300)
+     ;;    (aref (string-as-multibyte "\300\201") 1) -> 129 (aka ?\201)
+     ;; but
+     ;;    (aref (string-as-multibyte "\201\300") 0) -> 2240
+     ;;    (aref (string-as-multibyte "\201\300") 1) -> <error>
+     ;; Better use string-to-multibyte or encode-coding-string.
+     ;; If you really need string-as-multibyte somewhere it's usually
+     ;; because you're using the internal emacs-mule representation (maybe
+     ;; because you're using string-as-unibyte somewhere), which is
+     ;; generally a problem in itself.
+     ;; Here is an approximate equivalence table to help think about it:
+     ;; (string-as-multibyte s)   ~= (decode-coding-string s 'emacs-mule)
+     ;; (string-to-multibyte s)   ~= (decode-coding-string s 'binary)
+     ;; (string-make-multibyte s) ~= (decode-coding-string s locale-coding-system)
      (string-as-multibyte . identity)
      (string-to-multibyte
       . (lambda (string)
@@ -138,7 +157,7 @@ In XEmacs, also return non-nil if CS is a coding system object.
 If CS is available, return CS itself in Emacs, and return a coding
 system object in XEmacs."
   (if (fboundp 'find-coding-system)
-      (find-coding-system cs)
+      (and cs (find-coding-system cs))
     (if (fboundp 'coding-system-p)
        (when (coding-system-p cs)
          cs)
@@ -668,7 +687,7 @@ But this is very much a corner case, so don't worry about it."
 
 (defmacro mm-xemacs-find-mime-charset (begin end)
   (when (featurep 'xemacs)
-    `(mm-xemacs-find-mime-charset-1 ,begin ,end)))
+    `(and (featurep 'mule) (mm-xemacs-find-mime-charset-1 ,begin ,end))))
 
 (defun mm-find-mime-charset-region (b e &optional hack-charsets)
   "Return the MIME charsets needed to encode the region between B and E.
@@ -839,22 +858,28 @@ to advanced Emacs features, such as file-name-handlers, format decoding,
 `find-file-hooks', etc.
 If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'.
   This function ensures that none of these modifications will take place."
-  (let ((format-alist nil)
-       (auto-mode-alist (if inhibit nil (mm-auto-mode-alist)))
-       (default-major-mode 'fundamental-mode)
-       (enable-local-variables nil)
-       (after-insert-file-functions nil)
-       (enable-local-eval nil)
-       (find-file-hooks nil)
-       (inhibit-file-name-operation (if inhibit
-                                        'insert-file-contents
-                                      inhibit-file-name-operation))
-       (inhibit-file-name-handlers
-        (if inhibit
-            (append mm-inhibit-file-name-handlers
-                    inhibit-file-name-handlers)
-          inhibit-file-name-handlers)))
-    (insert-file-contents filename visit beg end replace)))
+  (let* ((format-alist nil)
+        (auto-mode-alist (if inhibit nil (mm-auto-mode-alist)))
+        (default-major-mode 'fundamental-mode)
+        (enable-local-variables nil)
+        (after-insert-file-functions nil)
+        (enable-local-eval nil)
+        (inhibit-file-name-operation (if inhibit
+                                         'insert-file-contents
+                                       inhibit-file-name-operation))
+        (inhibit-file-name-handlers
+         (if inhibit
+             (append mm-inhibit-file-name-handlers
+                     inhibit-file-name-handlers)
+           inhibit-file-name-handlers))
+        (ffh (if (boundp 'find-file-hook)
+                 'find-file-hook
+               'find-file-hooks))
+        (val (symbol-value ffh)))
+    (set ffh nil)
+    (unwind-protect
+       (insert-file-contents filename visit beg end replace)
+      (set ffh val))))
 
 (defun mm-append-to-file (start end filename &optional codesys inhibit)
   "Append the contents of the region to the end of file FILENAME.
@@ -903,7 +928,7 @@ If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'."
                 (file-directory-p
                  (setq dir (concat (file-name-directory
                                     (directory-file-name path))
-                                   "etc/" (or package "gnus/")))))
+                                   "etc/images/" (or package "gnus/")))))
        (push dir result))
       (push path result))))
 
@@ -912,7 +937,7 @@ If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'."
     (defun mm-detect-coding-region (start end)
       "Like `detect-coding-region' except returning the best one."
       (let ((coding-systems
-            (detect-coding-region (point) (point-max))))
+            (detect-coding-region start end)))
        (or (car-safe coding-systems)
            coding-systems)))
   (defun mm-detect-coding-region (start end)
@@ -942,8 +967,9 @@ If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'."
   "Return the MIME charset corresponding to CODING-SYSTEM.
 To make this function work with XEmacs, the APEL package is required."
   (when coding-system
-    (or (coding-system-get coding-system :mime-charset)
-       (coding-system-get coding-system 'mime-charset)
+    (or (and (fboundp 'coding-system-get)
+            (or (coding-system-get coding-system :mime-charset)
+                (coding-system-get coding-system 'mime-charset)))
        (and (featurep 'xemacs)
             (or (and (fboundp 'coding-system-to-mime-charset)
                      (not (eq (symbol-function 'coding-system-to-mime-charset)
@@ -959,11 +985,13 @@ To make this function work with XEmacs, the APEL package is required."
 
 (defun mm-decompress-buffer (filename &optional inplace force)
   "Decompress buffer's contents, depending on jka-compr.
-Only when FORCE is non-nil or `auto-compression-mode' is enabled and
-FILENAME agrees with `jka-compr-compression-info-list', decompression
-is done.  If INPLACE is nil, return decompressed data or nil without
-modifying the buffer.  Otherwise, replace the buffer's contents with
-the decompressed data.  The buffer's multibyteness must be turned off."
+Only when FORCE is t or `auto-compression-mode' is enabled and FILENAME
+agrees with `jka-compr-compression-info-list', decompression is done.
+Signal an error if FORCE is neither nil nor t and compressed data are
+not decompressed because `auto-compression-mode' is disabled.
+If INPLACE is nil, return decompressed data or nil without modifying
+the buffer.  Otherwise, replace the buffer's contents with the
+decompressed data.  The buffer's multibyteness must be turned off."
   (when (and filename
             (if force
                 (prog1 t (require 'jka-compr))
@@ -971,6 +999,9 @@ the decompressed data.  The buffer's multibyteness must be turned off."
                    (jka-compr-installed-p))))
     (let ((info (jka-compr-get-compression-info filename)))
       (when info
+       (unless (or (memq force (list nil t))
+                   (jka-compr-installed-p))
+         (error ""))
        (let ((prog (jka-compr-info-uncompress-program info))
              (args (jka-compr-info-uncompress-args info))
              (msg (format "%s %s..."
@@ -1034,7 +1065,12 @@ gzip, bzip2, etc. are allowed."
   (unless filename
     (setq filename buffer-file-name))
   (save-excursion
-    (let ((decomp (mm-decompress-buffer filename nil t)))
+    (let ((decomp (unless ;; No worth to examine charset of tar files.
+                     (and filename
+                          (string-match
+                           "\\.\\(?:tar\\.[^.]+\\|tbz\\|tgz\\)\\'"
+                           filename))
+                   (mm-decompress-buffer filename nil t))))
       (when decomp
        (set-buffer (let (default-enable-multibyte-characters)
                      (generate-new-buffer " *temp*")))