+(if (fboundp 'delete-dups)
+ (defalias 'mm-delete-duplicates 'delete-dups)
+ (defun mm-delete-duplicates (list)
+ "Destructively remove `equal' duplicates from LIST.
+Store the result in LIST and return it. LIST must be a proper list.
+Of several `equal' occurrences of an element in LIST, the first
+one is kept.
+
+This is a compatibility function for Emacsen without `delete-dups'."
+ ;; Code from `subr.el' in Emacs 22:
+ (let ((tail list))
+ (while tail
+ (setcdr tail (delete (car tail) (cdr tail)))
+ (setq tail (cdr tail))))
+ list))
+
+;; Fixme: This is used in places when it should be testing the
+;; default multibyteness. See mm-default-multibyte-p.
+(eval-and-compile
+ (if (and (not (featurep 'xemacs))
+ (boundp 'enable-multibyte-characters))
+ (defun mm-multibyte-p ()
+ "Non-nil if multibyte is enabled in the current buffer."
+ enable-multibyte-characters)
+ (defun mm-multibyte-p () (featurep 'mule))))
+
+(defun mm-default-multibyte-p ()
+ "Return non-nil if the session is multibyte.
+This affects whether coding conversion should be attempted generally."
+ (if (featurep 'mule)
+ (if (boundp 'default-enable-multibyte-characters)
+ default-enable-multibyte-characters
+ t)))
+
+(defun mm-iso-8859-x-to-15-region (&optional b e)
+ (if (fboundp 'char-charset)
+ (let (charset item c inconvertible)
+ (save-restriction
+ (if e (narrow-to-region b e))
+ (goto-char (point-min))
+ (skip-chars-forward "\0-\177")
+ (while (not (eobp))
+ (cond
+ ((not (setq item (assq (char-charset (setq c (char-after)))
+ mm-iso-8859-x-to-15-table)))
+ (forward-char))
+ ((memq c (cdr (cdr item)))
+ (setq inconvertible t)
+ (forward-char))
+ (t
+ (insert-before-markers (prog1 (+ c (car (cdr item)))
+ (delete-char 1)))))
+ (skip-chars-forward "\0-\177")))
+ (not inconvertible))))
+
+(defun mm-sort-coding-systems-predicate (a b)
+ (let ((priorities
+ (mapcar (lambda (cs)
+ ;; Note: invalid entries are dropped silently
+ (and (setq cs (mm-coding-system-p cs))
+ (coding-system-base cs)))
+ mm-coding-system-priorities)))
+ (and (setq a (mm-coding-system-p a))
+ (if (setq b (mm-coding-system-p b))
+ (> (length (memq (coding-system-base a) priorities))
+ (length (memq (coding-system-base b) priorities)))
+ t))))
+
+(eval-when-compile
+ (autoload 'latin-unity-massage-name "latin-unity")
+ (autoload 'latin-unity-maybe-remap "latin-unity")
+ (autoload 'latin-unity-representations-feasible-region "latin-unity")
+ (autoload 'latin-unity-representations-present-region "latin-unity")
+ (defvar latin-unity-coding-systems)
+ (defvar latin-unity-ucs-list))
+
+(defun mm-xemacs-find-mime-charset-1 (begin end)
+ "Determine which MIME charset to use to send region as message.
+This uses the XEmacs-specific latin-unity package to better handle the
+case where identical characters from diverse ISO-8859-? character sets
+can be encoded using a single one of the corresponding coding systems.
+
+It treats `mm-coding-system-priorities' as the list of preferred
+coding systems; a useful example setting for this list in Western
+Europe would be '(iso-8859-1 iso-8859-15 utf-8), which would default
+to the very standard Latin 1 coding system, and only move to coding
+systems that are less supported as is necessary to encode the
+characters that exist in the buffer.
+
+Latin Unity doesn't know about those non-ASCII Roman characters that
+are available in various East Asian character sets. As such, its
+behavior if you have a JIS 0212 LATIN SMALL LETTER A WITH ACUTE in a
+buffer and it can otherwise be encoded as Latin 1, won't be ideal.
+But this is very much a corner case, so don't worry about it."
+ (let ((systems mm-coding-system-priorities) csets psets curset)
+
+ ;; Load the Latin Unity library, if available.
+ (when (and (not (featurep 'latin-unity)) (locate-library "latin-unity"))
+ (require 'latin-unity))
+
+ ;; Now, can we use it?
+ (if (featurep 'latin-unity)
+ (progn
+ (setq csets (latin-unity-representations-feasible-region begin end)
+ psets (latin-unity-representations-present-region begin end))
+
+ (catch 'done
+
+ ;; Pass back the first coding system in the preferred list
+ ;; that can encode the whole region.
+ (dolist (curset systems)
+ (setq curset (latin-unity-massage-name 'buffer-default curset))
+
+ ;; If the coding system is a universal coding system, then
+ ;; it can certainly encode all the characters in the region.
+ (if (memq curset latin-unity-ucs-list)
+ (throw 'done (list curset)))
+
+ ;; If a coding system isn't universal, and isn't in
+ ;; the list that latin unity knows about, we can't
+ ;; decide whether to use it here. Leave that until later
+ ;; in `mm-find-mime-charset-region' function, whence we
+ ;; have been called.
+ (unless (memq curset latin-unity-coding-systems)
+ (throw 'done nil))
+
+ ;; Right, we know about this coding system, and it may
+ ;; conceivably be able to encode all the characters in
+ ;; the region.
+ (if (latin-unity-maybe-remap begin end curset csets psets t)
+ (throw 'done (list curset))))
+
+ ;; Can't encode using anything from the
+ ;; `mm-coding-system-priorities' list.
+ ;; Leave `mm-find-mime-charset' to do most of the work.
+ nil))
+
+ ;; Right, latin unity isn't available; let `mm-find-charset-region'
+ ;; take its default action, which equally applies to GNU Emacs.
+ nil)))
+
+(defmacro mm-xemacs-find-mime-charset (begin end)
+ (when (featurep 'xemacs)
+ `(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.
+nil means ASCII, a single-element list represents an appropriate MIME
+charset, and a longer list means no appropriate charset."
+ (let (charsets)
+ ;; The return possibilities of this function are a mess...
+ (or (and (mm-multibyte-p)
+ mm-use-find-coding-systems-region
+ ;; Find the mime-charset of the most preferred coding
+ ;; system that has one.
+ (let ((systems (find-coding-systems-region b e)))
+ (when mm-coding-system-priorities
+ (setq systems
+ (sort systems 'mm-sort-coding-systems-predicate)))
+ (setq systems (delq 'compound-text systems))
+ (unless (equal systems '(undecided))
+ (while systems
+ (let* ((head (pop systems))
+ (cs (or (coding-system-get head :mime-charset)
+ (coding-system-get head 'mime-charset))))
+ ;; The mime-charset (`x-ctext') of
+ ;; `compound-text' is not in the IANA list. We
+ ;; shouldn't normally use anything here with a
+ ;; mime-charset having an `x-' prefix.
+ ;; Fixme: Allow this to be overridden, since
+ ;; there is existing use of x-ctext.
+ ;; Also people apparently need the coding system
+ ;; `iso-2022-jp-3' (which Mule-UCS defines with
+ ;; mime-charset, though it's not valid).
+ (if (and cs
+ (not (string-match "^[Xx]-" (symbol-name cs)))
+ ;; UTF-16 of any variety is invalid for
+ ;; text parts and, unfortunately, has
+ ;; mime-charset defined both in Mule-UCS
+ ;; and versions of Emacs. (The name
+ ;; might be `mule-utf-16...' or
+ ;; `utf-16...'.)
+ (not (string-match "utf-16" (symbol-name cs))))
+ (setq systems nil
+ charsets (list cs))))))
+ charsets))
+ ;; If we're XEmacs, and some coding system is appropriate,
+ ;; mm-xemacs-find-mime-charset will return an appropriate list.
+ ;; Otherwise, we'll get nil, and the next setq will get invoked.
+ (setq charsets (mm-xemacs-find-mime-charset b e))
+
+ ;; We're not multibyte, or a single coding system won't cover it.
+ (setq charsets
+ (mm-delete-duplicates
+ (mapcar 'mm-mime-charset
+ (delq 'ascii
+ (mm-find-charset-region b e))))))
+ (if (and (> (length charsets) 1)
+ (memq 'iso-8859-15 charsets)
+ (memq 'iso-8859-15 hack-charsets)
+ (save-excursion (mm-iso-8859-x-to-15-region b e)))
+ (mapcar (lambda (x) (setq charsets (delq (car x) charsets)))
+ mm-iso-8859-15-compatible))
+ (if (and (memq 'iso-2022-jp-2 charsets)
+ (memq 'iso-2022-jp-2 hack-charsets))
+ (setq charsets (delq 'iso-2022-jp charsets)))
+ ;; Attempt to reduce the number of charsets if utf-8 is available.
+ (if (and (featurep 'xemacs)
+ (> (length charsets) 1)
+ (mm-coding-system-p 'utf-8))
+ (let ((mm-coding-system-priorities
+ (cons 'utf-8 mm-coding-system-priorities)))
+ (setq charsets
+ (mm-delete-duplicates
+ (mapcar 'mm-mime-charset
+ (delq 'ascii
+ (mm-find-charset-region b e)))))))
+ charsets))