+(defmacro mm-with-unibyte-current-buffer (&rest forms)
+ "Evaluate FORMS with current current buffer temporarily made unibyte.
+Also bind `default-enable-multibyte-characters' to nil.
+Equivalent to `progn' in XEmacs"
+ (let ((buffer (make-symbol "buffer")))
+ `(if (and (not (featurep 'xemacs))
+ (boundp 'enable-multibyte-characters)
+ enable-multibyte-characters
+ (fboundp 'set-buffer-multibyte))
+ (let ((,buffer (current-buffer)))
+ (unwind-protect
+ (let (default-enable-multibyte-characters)
+ (set-buffer-multibyte nil)
+ ,@forms)
+ (set-buffer ,buffer)
+ (set-buffer-multibyte t)))
+ (let (default-enable-multibyte-characters)
+ ,@forms))))
+(put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0)
+(put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body))
+
+(defmacro mm-with-unibyte-current-buffer-mule4 (&rest forms)
+ "Evaluate FORMS there like `progn' in current buffer.
+Mule4 only."
+ (let ((buffer (make-symbol "buffer")))
+ `(if (and (not (featurep 'xemacs))
+ (boundp 'enable-multibyte-characters)
+ enable-multibyte-characters
+ (fboundp 'set-buffer-multibyte)
+ (fboundp 'charsetp)
+ (not (charsetp 'eight-bit-control))) ;; For Emacs Mule 4 only.
+ (let ((,buffer (current-buffer)))
+ (unwind-protect
+ (let (default-enable-multibyte-characters)
+ (set-buffer-multibyte nil)
+ ,@forms)
+ (set-buffer ,buffer)
+ (set-buffer-multibyte t)))
+ (let (default-enable-multibyte-characters)
+ ,@forms))))
+(put 'mm-with-unibyte-current-buffer-mule4 'lisp-indent-function 0)
+(put 'mm-with-unibyte-current-buffer-mule4 'edebug-form-spec '(body))
+
+(defmacro mm-with-unibyte (&rest forms)
+ "Eval the FORMS with the default value of `enable-multibyte-characters' nil, ."
+ `(let (default-enable-multibyte-characters)
+ ,@forms))
+(put 'mm-with-unibyte 'lisp-indent-function 0)
+(put 'mm-with-unibyte 'edebug-form-spec '(body))
+
+(defun mm-find-charset-region (b e)
+ "Return a list of Emacs charsets in the region B to E."
+ (cond
+ ((and (mm-multibyte-p)
+ (fboundp 'find-charset-region))
+ ;; Remove composition since the base charsets have been included.
+ ;; Remove eight-bit-*, treat them as ascii.
+ (let ((css (find-charset-region b e)))
+ (mapcar (lambda (cs) (setq css (delq cs css)))
+ '(composition eight-bit-control eight-bit-graphic))
+ css))
+ (t
+ ;; We are in a unibyte buffer or XEmacs non-mule, so we futz around a bit.
+ (save-excursion
+ (save-restriction
+ (narrow-to-region b e)
+ (goto-char (point-min))
+ (skip-chars-forward "\0-\177")
+ (if (eobp)
+ '(ascii)
+ (let (charset)
+ (setq charset
+ (and (boundp 'current-language-environment)
+ (car (last (assq 'charset
+ (assoc current-language-environment
+ language-info-alist))))))
+ (if (eq charset 'ascii) (setq charset nil))
+ (or charset
+ (setq charset
+ (car (last (assq mail-parse-charset
+ mm-mime-mule-charset-alist)))))
+ (list 'ascii (or charset 'latin-iso8859-1)))))))))
+
+(static-if (fboundp 'shell-quote-argument)
+ (defalias 'mm-quote-arg 'shell-quote-argument)
+ (defun mm-quote-arg (arg)
+ "Return a version of ARG that is safe to evaluate in a shell."
+ (let ((pos 0) new-pos accum)
+ ;; *** bug: we don't handle newline characters properly
+ (while (setq new-pos (string-match "[]*[;!'`\"$\\& \t{} |()<>]" arg pos))
+ (push (substring arg pos new-pos) accum)
+ (push "\\" accum)
+ (push (list (aref arg new-pos)) accum)
+ (setq pos (1+ new-pos)))
+ (if (= pos 0)
+ arg
+ (apply 'concat (nconc (nreverse accum) (list (substring arg pos))))))))
+
+(defun mm-auto-mode-alist ()
+ "Return an `auto-mode-alist' with only the .gz (etc) thingies."
+ (let ((alist auto-mode-alist)
+ out)
+ (while alist
+ (when (listp (cdar alist))
+ (push (car alist) out))
+ (pop alist))
+ (nreverse out)))
+
+(defvar mm-inhibit-file-name-handlers
+ '(jka-compr-handler)
+ "A list of handlers doing (un)compression (etc) thingies.")
+
+(defun mm-insert-file-contents (filename &optional visit beg end replace
+ inhibit)
+ "Like `insert-file-contents', q.v., but only reads in the file.
+A buffer may be modified in several ways after reading into the buffer due
+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)))
+
+(defun mm-append-to-file (start end filename &optional codesys inhibit)
+ "Append the contents of the region to the end of file FILENAME.
+When called from a function, expects three arguments,
+START, END and FILENAME. START and END are buffer positions
+saying what text to write.
+Optional fourth argument specifies the coding system to use when
+encoding the file.
+If INHIBIT is non-nil, inhibit mm-inhibit-file-name-handlers."
+ (let ((coding-system-for-write
+ (or codesys mm-text-coding-system-for-write
+ mm-text-coding-system))
+ (inhibit-file-name-operation (if inhibit
+ 'append-to-file
+ inhibit-file-name-operation))
+ (inhibit-file-name-handlers
+ (if inhibit
+ (append mm-inhibit-file-name-handlers
+ inhibit-file-name-handlers)
+ inhibit-file-name-handlers)))
+ (append-to-file start end filename)))
+
+(defun mm-write-region (start end filename &optional append visit lockname
+ coding-system inhibit)
+
+ "Like `write-region'.
+If INHIBIT is non-nil, inhibit mm-inhibit-file-name-handlers."
+ (let ((coding-system-for-write
+ (or coding-system mm-text-coding-system-for-write
+ mm-text-coding-system))
+ (inhibit-file-name-operation (if inhibit
+ 'write-region
+ inhibit-file-name-operation))
+ (inhibit-file-name-handlers
+ (if inhibit
+ (append mm-inhibit-file-name-handlers
+ inhibit-file-name-handlers)
+ inhibit-file-name-handlers)))
+ (write-region start end filename append visit lockname)))
+
+(defun mm-image-load-path (&optional package)
+ (let (dir result)
+ (dolist (path load-path (nreverse result))
+ (if (file-directory-p
+ (setq dir (concat (file-name-directory
+ (directory-file-name path))
+ "etc/" (or package "gnus/"))))
+ (push dir result))
+ (push path result))))