Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-40
authorMiles Bader <miles@gnu.org>
Wed, 15 Sep 2004 09:00:10 +0000 (09:00 +0000)
committerMiles Bader <miles@gnu.org>
Wed, 15 Sep 2004 09:00:10 +0000 (09:00 +0000)
Merge from emacs--cvs-trunk--0

Patches applied:

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-535
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-536
   sync-tree with gnus--rel--5.10

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-537
 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-538
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-539
   Merge from gnus--rel--5.10

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-540
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-541
   Merge from gnus--rel--5.10

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-542
 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-545
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-546
   Merge from gnus--rel--5.10

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-547
 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-548
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-549
   Use symbol-matching for generic-mode keywords

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-550
   Update from CVS

 * miles@gnu.org--gnu-2004/gnus--devo--0--patch-2
   Add {arch}/=cvs-sync-make-log

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--base-0
   Import from Gnus CVS branch V5-8

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-1
   {arch}/=tagging-method: Add CVS and autoconf grot to junk regexp

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-2
   Use explicit tags for autoconf input files

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-3
   Remove RCS keywords

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-4
   Fix copied explicit id-tags

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-5
   Add {arch}/=cvs-sync-make-log

 * miles@gnu.org--gnu-2004/gnus--rel--5.8--patch-6
   configure.in: Use ifelse instead of m4_if for arch-tag: comment

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--base-0
   tag of miles@gnu.org--gnu-2004/gnus--rel--5.8--base-0

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-1
   Gnus 5.10, from CVS branch v5-10

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-2
   Merge from gnus--rel--5.8

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-3
   Use explicit tags for autoconf input files

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-4
   sync-tree with gnus--rel--5.8

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-5
   Update from CVS

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-6
   Merge from gnus--rel--5.8

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-7
   Remove RCS keywords

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-8
   Merge from gnus--rel--5.8

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-9
   Update from CVS

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-10
   Add {arch}/=cvs-sync-make-log

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-11
   Merge from gnus--rel--5.8

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-12
   Update from CVS: make.bat: Fix line endings around arch-tag.

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-13
 - miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-17
   Update from CVS

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-21
   Merge from emacs--cvs-trunk--0

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-22
   Update from CVS: lisp/nndb.el (require): Remove tcp and duplicate cl.

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-23
   Update from CVS

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-24
   lisp/nnimap.el (nnimap-open-connection): Remove extraneous end-paren

 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-25
 - miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-26
   Update from CVS

17 files changed:
1  2 
etc/MORE.STUFF
etc/NEWS
lisp/desktop.el
lisp/faces.el
lisp/files.el
lisp/generic.el
lisp/gnus/gnus-sum.el
lisp/isearch.el
lisp/simple.el
src/Makefile.in
src/alloc.c
src/bytecode.c
src/editfns.c
src/fileio.c
src/msdos.c
src/xdisp.c
src/xfaces.c

diff --combined etc/MORE.STUFF
@@@ -140,9 -140,7 +140,7 @@@ Several are for Debian GNU/Linux in par
   * Dismal: spreadsheet:
     <URL:http://acs.ist.psu.edu/dismal/dismal.html>
  
-  * EDB: database:
-    <URL:http://sdg.lcs.mit.edu/%7Emernst/software/edb-mrp.tar.gz>
-    Not maintained?
+  * EDB: database: <URL:http://www.glug.org/people/ttn/software/edb/>
  
   * Ee: categorizing information manager:
     <URL:http://www.jurta.org/emacs/ee/>
   * JDE: <URL:http://jdee.sunsite.dk/>
     Provides a Java development environment for Emacs.
  
 - * Mule-UCS: Universal enCoding System:
 -   <URL:ftp://ftp.m17n.org/pub/mule/Mule-UCS/>
 -   Extended coding systems for Mule, specifically for reading and
 -   writing UTF-8 encoded Unicode.  This probably doesn't have much
 -   advantage over the built-in `mule-utf-8' coding system with
 -   `utf-translate-cjk' turned on.
 -
   * Mailcrypt:
     <URL:http://www.pobox.com/%7Elbudney/linux/software/mailcrypt.html>
     PGP and GPG support.  PGP isn't free software, but GPG, the GNU
diff --combined etc/NEWS
+++ b/etc/NEWS
@@@ -13,81 -13,6 +13,81 @@@ Temporary note
  When you add a new item, please add it without either +++ or ---
  so we will look at it and add it to the manual.
  
 +Fixme: The notes about Emacs 22 are quite incomplete.
 +
 +\f
 +* Changes in Emacs 22.1
 +
 +** The Emacs character set is now a superset of Unicode.  
 +(It has about four times the code space, which should be plenty).
 +
 +The internal encoding used for buffers and strings is now
 +Unicode-based and called `utf-8-emacs'.  utf-8-emacs is backwards
 +compatible with the UTF-8 encoding of Unicode.  The `emacs-mule'
 +coding system can still read and write data in the old internal
 +encoding.
 +
 +There are still charsets which contain disjoint sets of characters
 +where this is necessary or useful, especially for various Far Eastern
 +sets which are problematic with Unicode.
 +
 +Since the internal encoding is also used by default for byte-compiled
 +files -- i.e. the normal coding system for byte-compiled Lisp files is
 +now utf-8-Emacs -- Lisp containing non-ASCII characters which is
 +compiled by Emacs 22 can't be read by earlier versions of Emacs.
 +Files compiled by Emacs 20 or 21 are loaded correctly as emacs-mule
 +(whether or not they contain multibyte characters), which makes
 +loading them somewhat slower than Emacs 22-compiled files.  Thus it
 +may be worth recompiling existing .elc files which don't need to be
 +shared with older Emacsen.
 +
 +** There are assorted new coding systems/aliases -- see
 +M-x list-coding-systems.
 +
 +** New charset implementation with many new charsets.
 +See M-x list-character-sets.  New charsets can be defined conveniently
 +as tables of unicodes.
 +
 +The dimension of a charset is now 0, 1, 2, or 3, and the size of each
 +dimension is no longer limited to 94 or 96.
 +
 +Generic characters no longer exist.  
 +
 +A dynamic charset priority list is used to infer the charset of
 +unicodes for display &c.
 +
 +** The following facilities are obsolete:
 +
 +Minor modes: unify-8859-on-encoding-mode, unify-8859-on-decoding-mode
 +
 +\f
 +* Lisp changes in Emacs 22.1
 +
 +map-char-table's behaviour has changed.
 +
 +New functions: characterp, max-char, map-charset-chars,
 +define-charset-alias, primary-charset, set-primary-charset,
 +unify-charset, clear-charset-maps, charset-priority-list,
 +set-charset-priority, define-coding-system,
 +define-coding-system-alias, coding-system-aliases, langinfo,
 +string-to-multibyte.
 +
 +Changed functions: copy-sequence, decode-char, encode-char,
 +set-fontset-font, new-fontset, modify-syntax-entry, define-charset,
 +modify-category-entry
 +
 +Obsoleted: char-bytes, chars-in-region, set-coding-priority,
 +char-valid-p
 +
 +\f
 +* Incompatible Lisp changes
 +
 +Deleted functions: make-coding-system, register-char-codings,
 +coding-system-spec
 +
 +** The character codes for characters from the
 +eight-bit-control/eight-bit-graphic charsets aren't now in the range
 +128-255.
  \f
  * Installation Changes in Emacs 21.4
  
@@@ -692,6 -617,8 +692,8 @@@ version 4.7 or newer, compiles to Info 
  'sql-sqlite'.
  
  ** BibTeX mode:
+ *** The new command bibtex-url browses a URL for the BibTeX entry at
+ point (bound to C-c C-l and mouse-2 on clickable fields).
  *** The new command bibtex-entry-update (bound to C-c C-u) updates
  an existing BibTeX entry.
  *** New `bibtex-entry-format' option `required-fields', enabled by default.
@@@ -1247,9 -1174,9 +1249,9 @@@ and to type `C-f' at the end of the sea
  search string used as the string to replace.
  
  +++
- ** New user option `isearch-resume-enabled'.
- This option can be disabled, to avoid the normal behavior of isearch
which puts calls to `isearch-resume' in the command history.
+ ** Isearch no longer adds `isearch-resume' commands to the command
+ history by default.  To enable this feature, customize the new
user option `isearch-resume-in-command-history'.
  
  +++
  ** New user option `history-delete-duplicates'.
@@@ -1569,29 -1496,31 +1571,31 @@@ per line.  Lines beginning with space o
  **** The `::' qualifier triggers C++ parsing in C file.
  Previously, only the `template' and `class' keywords had this effect.
  
+ **** New language HTML.
+ Title and h1, h2, h3 are tagged.  Also, tags are generated when name= is
+ used inside an anchor and whenever id= is used.
+ **** In Makefiles, constants are tagged.
+ If you want the old behavior instead, thus avoiding to increase the
+ size of the tags file, use the --no-globals option.
+ **** In Lua, all functions are tagged.
  **** In Perl, packages are tags.
  Subroutine tags are named from their package.  You can jump to sub tags
  as you did before, by the sub name, or additionally by looking for
  package::sub.
  
+ **** In Prolog, etags creates tags for rules in addition to predicates.
  **** New language PHP.
  Tags are functions, classes and defines.
  If the --members option is specified to etags, tags are vars also.
  
- **** New language HTML.
- Title and h1, h2, h3 are tagged.  Also, tags are generated when name= is
- used inside an anchor and whenever id= is used.
  **** New default keywords for TeX.
  The new keywords are def, newcommand, renewcommand, newenvironment and
  renewenvironment.
  
- **** In Makefiles, constants are tagged.
- If you want the old behavior instead, thus avoiding to increase the
- size of the tags file, use the --no-globals option.
- **** In Prolog, etags creates tags for rules in addition to predicates.
  *** Honour #line directives.
  When Etags parses an input file that contains C preprocessor's #line
  directives, it creates tags using the file name and line number
@@@ -1602,7 -1531,7 +1606,7 @@@ writes tags pointing to the source file
  *** New option --parse-stdin=FILE.
  This option is mostly useful when calling etags from programs.  It can
  be used (only once) in place of a file name on the command line.  Etags
- reads from standard input and mark the produced tags as belonging to
+ reads from standard input and marks the produced tags as belonging to
  the file FILE.
  
  +++
@@@ -2075,6 -2004,10 +2079,10 @@@ anyone has committed to the repository 
  \f
  * New modes and packages in Emacs 21.4
  
+ ** The new package dns-mode.el add syntax highlight of DNS master files.
+ The key binding C-c C-s (`dns-mode-soa-increment-serial') can be used
+ to increment the SOA serial.
  ** The new package flymake.el does on-the-fly syntax checking of program
  source files.  See the Flymake's Info manual for more details.
  
diff --combined lisp/desktop.el
@@@ -171,13 -171,13 +171,13 @@@ This is useful for truncating history l
    :type 'hook
    :group 'desktop)
  
- (defcustom desktop-globals-to-save '(
-   desktop-missing-file-warning
-   tags-file-name
-   tags-table-list
-   search-ring
-   regexp-search-ring
-   register-alist)
+ (defcustom desktop-globals-to-save
+   '(desktop-missing-file-warning
+     tags-file-name
+     tags-table-list
+     search-ring
+     regexp-search-ring
+     register-alist)
    "List of global variables saved by `desktop-save'.
  An element may be variable name (a symbol) or a cons cell of the form
  \(VAR . MAX-SIZE), which means to truncate VAR's value to at most
@@@ -186,13 -186,13 +186,13 @@@ Feature: Saving `kill-ring' implies sav
    :type '(repeat (restricted-sexp :match-alternatives (symbolp consp)))
    :group 'desktop)
  
- (defcustom desktop-globals-to-clear '(
-   kill-ring
-   kill-ring-yank-pointer
-   search-ring
-   search-ring-yank-pointer
-   regexp-search-ring
-   regexp-search-ring-yank-pointer)
+ (defcustom desktop-globals-to-clear
+   '(kill-ring
+     kill-ring-yank-pointer
+     search-ring
+     search-ring-yank-pointer
+     regexp-search-ring
+     regexp-search-ring-yank-pointer)
    "List of global variables to clear by `desktop-clear'.
  An element may be variable name (a symbol) or a cons cell of the form
  \(VAR . FORM). Symbols are set to nil and for cons cells VAR is set
@@@ -202,29 -202,27 +202,27 @@@ to the value obtained by evaluateing FO
  
  (defcustom desktop-clear-preserve-buffers-regexp
    "^\\(\\*scratch\\*\\|\\*Messages\\*\\|\\*tramp/.+\\*\\)$"
-   "Regexp identifying buffers that `desktop-clear' should not delete."
+   "Regexp identifying buffers that `desktop-clear' should not delete.
+ See also `desktop-clear-preserve-buffers'."
    :type 'regexp
    :group 'desktop)
  
- ;; Maintained for backward compatibility
  (defcustom desktop-clear-preserve-buffers nil
    "*List of buffer names that `desktop-clear' should not delete.
This variable is maintained for backward compatibility only."
See also `desktop-clear-preserve-buffers-regexp'."
    :type '(repeat string)
    :group 'desktop)
- (make-obsolete-variable 'desktop-clear-preserve-buffers
-                         'desktop-clear-preserve-buffers-regexp)
- (defcustom desktop-locals-to-save '(
-   desktop-locals-to-save  ; Itself!  Think it over.
-   truncate-lines
-   case-fold-search
-   case-replace
-   fill-column
-   overwrite-mode
-   change-log-default-name
-   line-number-mode
-   buffer-file-coding-system)
+ (defcustom desktop-locals-to-save
+   '(desktop-locals-to-save  ; Itself!  Think it over.
+     truncate-lines
+     case-fold-search
+     case-replace
+     fill-column
+     overwrite-mode
+     change-log-default-name
+     line-number-mode
+     buffer-file-coding-system)
    "List of local variables to save for each buffer.
  The variables are saved only when they really are local."
    :type '(repeat symbol)
@@@ -282,11 -280,11 +280,11 @@@ DESKTOP-BUFFER-MISC."
  (make-obsolete-variable 'desktop-buffer-misc-functions
                          'desktop-save-buffer)
  
- (defcustom desktop-buffer-mode-handlers '(
-   (dired-mode . dired-restore-desktop-buffer)
-   (rmail-mode . rmail-restore-desktop-buffer)
-   (mh-folder-mode . mh-restore-desktop-buffer)
-   (Info-mode . Info-restore-desktop-buffer))
+ (defcustom desktop-buffer-mode-handlers
+   '((dired-mode . dired-restore-desktop-buffer)
+     (rmail-mode . rmail-restore-desktop-buffer)
+     (mh-folder-mode . mh-restore-desktop-buffer)
+     (Info-mode . Info-restore-desktop-buffer))
    "Alist of major mode specific functions to restore a desktop buffer.
  Functions are called by `desktop-read'. List elements must have the form
  \(MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
@@@ -580,8 -578,7 +578,7 @@@ See also `desktop-base-file-name'.
      (let ((filename (expand-file-name desktop-base-file-name dirname))
            (info
              (mapcar
-               (function
-                 (lambda (b)
+               #'(lambda (b)
                    (set-buffer b)
                    (list
                      (desktop-file-name (buffer-file-name) dirname)
                              (when (member (car locals) loclist)
                                (setq ll (cons (car locals) ll)))))
                          (setq locals (cdr locals)))
-                       ll))))
+                       ll)))
                (buffer-list)))
            (buf (get-buffer-create "*desktop*")))
        (set-buffer buf)
        (erase-buffer)
  
        (insert
 -        ";; -*- coding: emacs-mule; -*-\n"
 +        ";; -*- coding: utf-8-emacs; -*-\n"
          desktop-header
          ";; Created " (current-time-string) "\n"
          ";; Desktop file format version " desktop-file-version "\n"
            " kill-ring))\n"))
  
        (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
-       (mapcar
-         (function
-           (lambda (l)
-             (if (apply 'desktop-save-buffer-p l)
-               (progn
-                 (insert "(desktop-create-buffer " desktop-file-version)
-                 (mapcar
-                   (function
-                     (lambda (e)
-                       (insert "\n  " (desktop-value-to-string e))))
-                   l)
-                 (insert ")\n\n")))))
-         info)
+       (mapcar #'(lambda (l)
+                   (if (apply 'desktop-save-buffer-p l)
+                       (progn
+                         (insert "(desktop-create-buffer " desktop-file-version)
+                         (mapcar #'(lambda (e)
+                                     (insert "\n  " (desktop-value-to-string e)))
+                                 l)
+                         (insert ")\n\n"))))
+               info)
        (setq default-directory dirname)
        (when (file-exists-p filename) (delete-file filename))
 -      (let ((coding-system-for-write 'emacs-mule))
 +      (let ((coding-system-for-write 'utf-8-emacs))
          (write-region (point-min) (point-max) filename nil 'nomessage))))
    (setq desktop-dirname dirname))
  
@@@ -816,18 -809,18 +809,18 @@@ directory DIRNAME.
     (defvar desktop-first-buffer) ;; Dynamically bound in `desktop-read'
  )
  
- (defun desktop-create-buffer (
-   desktop-file-version
-   desktop-buffer-file-name
-   desktop-buffer-name
-   desktop-buffer-major-mode
-   desktop-buffer-minor-modes
-   desktop-buffer-point
-   desktop-buffer-mark
-   desktop-buffer-read-only
-   desktop-buffer-misc
-   &optional
-   desktop-buffer-locals)
+ (defun desktop-create-buffer
+   (desktop-file-version
+    desktop-buffer-file-name
+    desktop-buffer-name
+    desktop-buffer-major-mode
+    desktop-buffer-minor-modes
+    desktop-buffer-point
+    desktop-buffer-mark
+    desktop-buffer-read-only
+    desktop-buffer-misc
+    &optional
+    desktop-buffer-locals)
    ;; Just to silence the byte compiler. Bound locally in `desktop-read'.
    (eval-when-compile
      (defvar desktop-buffer-ok-count)
    ;; To make desktop files with relative file names possible, we cannot
    ;; allow `default-directory' to change. Therefore we save current buffer.
    (save-current-buffer
-     (let (
-       (buffer-list (buffer-list))
-       (result
-          (condition-case err
-              (funcall (or (cdr (assq desktop-buffer-major-mode desktop-buffer-mode-handlers))
-                           'desktop-restore-file-buffer)
-                       desktop-buffer-file-name
-                       desktop-buffer-name
-                       desktop-buffer-misc)
-            (error
-              (message "Desktop: Can't load buffer %s: %s"
-                       desktop-buffer-name (error-message-string err))
-              (when desktop-missing-file-warning (sit-for 1))
-              nil)))
-     )
+     (let ((buffer-list (buffer-list))
+           (result
+            (condition-case err
+                (funcall (or (cdr (assq desktop-buffer-major-mode
+                                        desktop-buffer-mode-handlers))
+                             'desktop-restore-file-buffer)
+                         desktop-buffer-file-name
+                         desktop-buffer-name
+                         desktop-buffer-misc)
+              (error
+               (message "Desktop: Can't load buffer %s: %s"
+                        desktop-buffer-name
+                        (error-message-string err))
+               (when desktop-missing-file-warning (sit-for 1))
+               nil))))
        (if (bufferp result)
            (setq desktop-buffer-ok-count (1+ desktop-buffer-ok-count))
          (setq desktop-buffer-fail-count (1+ desktop-buffer-fail-count))
          (unless (equal (buffer-name) desktop-buffer-name)
            (rename-buffer desktop-buffer-name))
          ;; minor modes
-         (cond (
-           ;; backwards compatible
-           (equal '(t) desktop-buffer-minor-modes)
-           (auto-fill-mode 1))(
-           (equal '(nil) desktop-buffer-minor-modes)
-           (auto-fill-mode 0))(
-           t
-           (mapcar
-             #'(lambda (minor-mode)
-               (when (functionp minor-mode) (funcall minor-mode 1)))
-             desktop-buffer-minor-modes)))
+         (cond ((equal '(t) desktop-buffer-minor-modes) ; backwards compatible
+                (auto-fill-mode 1))
+               ((equal '(nil) desktop-buffer-minor-modes) ; backwards compatible
+                (auto-fill-mode 0))
+               (t
+                (mapcar #'(lambda (minor-mode)
+                            (when (functionp minor-mode) (funcall minor-mode 1)))
+                        desktop-buffer-minor-modes)))
          ;; Even though point and mark are non-nil when written by `desktop-save'
          ;; they may be modified by handlers wanting to set point or mark themselves.
          (when desktop-buffer-point
diff --combined lisp/faces.el
@@@ -1068,7 -1068,7 +1068,7 @@@ of a global face.  Value is the new att
  If optional argument FRAME Is nil or omitted, use the selected frame."
    (let ((completion-ignore-case t))
      (completing-read (format "Set font attributes of face `%s' from font: " face)
 -                   (x-list-fonts "*" nil frame))))
 +                   (append (fontset-list) (x-list-fonts "*" nil frame)))))
  
  
  (defun read-all-face-attributes (face &optional frame)
@@@ -1223,8 -1223,7 +1223,8 @@@ If FRAME is omitted or nil, use the sel
                  (:box . "Box")
                  (:inverse-video . "Inverse")
                  (:stipple . "Stipple")
 -                (:font . "Font or fontset")
 +                (:font . "Font")
 +                (:fontset . "Fontset")
                  (:inherit . "Inherit")))
        (max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x)))
                                        attrs))))
@@@ -1925,11 -1924,13 +1925,13 @@@ created.
  
  
  (defface cursor '()
-   "Basic face for the cursor color under X."
+   "Basic face for the cursor color under X.
+ Note: Other faces cannot inherit from the cursor face."
    :version "21.1"
    :group 'cursor
    :group 'basic-faces)
  
+ (put 'cursor 'face-no-inherit t)
  
  (defface mouse '()
    "Basic face for the mouse color under X."
diff --combined lisp/files.el
@@@ -1771,6 -1771,7 +1771,7 @@@ in that case, this function acts as if 
       ("\\.g\\'" . antlr-mode)
       ("\\.ses\\'" . ses-mode)
       ("\\.orig\\'" nil t)             ; from patch
+      ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
       ("\\.in\\'" nil t)))
    "Alist of filename patterns vs corresponding major mode functions.
  Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
@@@ -3601,7 -3602,7 +3602,7 @@@ non-nil, it is called instead of reread
                   (let ((coding-system-for-read
                          ;; Auto-saved file shoule be read without
                          ;; any code conversion.
 -                        (if auto-save-p 'emacs-mule-unix
 +                        (if auto-save-p 'utf-8-emacs
                            (or coding-system-for-read
                                buffer-file-coding-system))))
                     ;; This force after-insert-file-set-coding
diff --combined lisp/generic.el
@@@ -294,8 -294,8 +294,8 @@@ Some generic modes are defined in `gene
        (when (consp start)
          (setq end (or (cdr start) end))
          (setq start (car start)))
 -      (when (char-valid-p start) (setq start (char-to-string start)))
 -      (when (char-valid-p end)   (setq end (char-to-string end)))
 +      (when (characterp start) (setq start (char-to-string start)))
 +      (when (characterp end)   (setq end (char-to-string end)))
  
        ;; Setup the vars for `comment-region'
        (if comment-start
@@@ -405,10 -405,10 +405,10 @@@ INI file.  This hook is NOT installed b
  The regexp is highlighted with FACE."
    (unless (listp keywords-list)
      (error "Keywords argument must be a list of strings"))
-   (list (concat prefix "\\<"
+   (list (concat prefix "\\_<"
                ;; Use an optimized regexp.
                (regexp-opt keywords-list t)
-               "\\>" suffix)
+               "\\_>" suffix)
        1
        face))
  
diff --combined lisp/gnus/gnus-sum.el
@@@ -1,5 -1,5 +1,5 @@@
  ;;; gnus-sum.el --- summary mode commands for Gnus
 -;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
  ;;        Free Software Foundation, Inc.
  
  ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@@ -9056,8 -9056,8 +9056,8 @@@ ACTION can be either `move' (the defaul
      (gnus-set-mode-line 'summary)))
  
  (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
-   "Move the current article to a different newsgroup.
- If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
+   "Copy the current article to some other group.
+ If TO-NEWSGROUP is string, do not prompt for a newsgroup to copy to.
  When called interactively, if TO-NEWSGROUP is nil, use the value of
  the variable `gnus-move-split-methods' for finding a default target
  newsgroup.
diff --combined lisp/isearch.el
@@@ -146,8 -146,10 +146,10 @@@ Ordinarily the text becomes invisible a
    :type 'boolean
    :group 'isearch)
  
- (defcustom isearch-resume-enabled t
-   "*If non-nil, `isearch-resume' commands are added to the command history."
+ (defcustom isearch-resume-in-command-history nil
+   "*If non-nil, `isearch-resume' commands are added to the command history.
+ This allows you to resume earlier isearch sessions through the
+ command history."
    :type 'boolean
    :group 'isearch)
  
@@@ -200,11 -202,15 +202,11 @@@ Default value, nil, means edit the stri
  (defvar isearch-mode-map
    (let* ((i 0)
         (map (make-keymap)))
 -    (or (vectorp (nth 1 map))
 -      (char-table-p (nth 1 map))
 +    (or (char-table-p (nth 1 map))
        (error "The initialization of isearch-mode-map must be updated"))
      ;; Make all multibyte characters search for themselves.
 -    (let ((l (generic-character-list))
 -        (table (nth 1 map)))
 -      (while l
 -      (set-char-table-default table (car l) 'isearch-printing-char)
 -      (setq l (cdr l))))
 +    (set-char-table-range (nth 1 map) (cons #x100 (max-char))
 +                        'isearch-printing-char)
      ;; Make function keys, etc, which aren't bound to a scrolling-function
      ;; exit the search.
      (define-key map [t] 'isearch-other-control-char)
@@@ -647,7 -653,7 +649,7 @@@ is treated as a regexp.  See \\[isearch
    (setq disable-point-adjustment t))
  
  (defun isearch-done (&optional nopush edit)
-   (if isearch-resume-enabled
+   (if isearch-resume-in-command-history
        (let ((command `(isearch-resume ,isearch-string ,isearch-regexp
                                      ,isearch-word ,isearch-forward
                                      ,isearch-message
diff --combined lisp/simple.el
@@@ -799,9 -799,9 +799,9 @@@ in *Help* buffer.  See also the comman
        (if (or (not coding)
                (eq (coding-system-type coding) t))
            (setq coding default-buffer-file-coding-system))
 -      (if (not (char-valid-p char))
 +      (if (eq (char-charset char) 'eight-bit)
            (setq encoding-msg
 -                (format "(0%o, %d, 0x%x, invalid)" char char char))
 +                (format "(0%o, %d, 0x%x, raw-byte)" char char char))
          (setq encoded (and (>= char 128) (encode-coding-char char coding)))
          (setq encoding-msg
                (if encoded
@@@ -4297,11 -4297,12 +4297,12 @@@ to decide what to delete.
                 (not (equal buffer
                             (window-buffer (active-minibuffer-window))))))
        (error "Minibuffer is not active for completion")
+       ;; Set buffer so buffer-local choose-completion-string-functions works.
+       (set-buffer buffer)
        (unless (run-hook-with-args-until-success
               'choose-completion-string-functions
               choice buffer mini-p base-size)
        ;; Insert the completion into the buffer where it was requested.
-       (set-buffer buffer)
        (if base-size
            (delete-region (+ base-size (if mini-p
                                            (minibuffer-prompt-end)
diff --combined src/Makefile.in
@@@ -578,7 -578,7 +578,7 @@@ emacsappsrc = ${srcdir}/../mac/Emacs.ap
  /* lastfile must follow all files
     whose initialized data areas should be dumped as pure by dump-emacs.  */
  obj=    dispnew.o frame.o scroll.o xdisp.o $(XMENU_OBJ) window.o \
 -      charset.o coding.o category.o ccl.o \
 +      charset.o coding.o category.o ccl.o character.o chartab.o \
        cm.o term.o xfaces.o $(XOBJ) $(GTK_OBJ)\
        emacs.o keyboard.o macros.o keymap.o sysdep.o \
        buffer.o filelock.o insdel.o marker.o \
@@@ -701,7 -701,6 +701,7 @@@ lisp= 
        ${lispsource}buff-menu.elc \
        ${lispsource}button.elc \
        ${lispsource}emacs-lisp/byte-run.elc \
 +      ${lispsource}composite.elc \
        ${lispsource}cus-face.elc \
        ${lispsource}cus-start.elc \
        ${lispsource}custom.elc \
        ${lispsource}international/mule-conf.el \
        ${lispsource}international/mule-cmds.elc \
        ${lispsource}international/characters.elc \
 -      ${lispsource}international/ucs-tables.elc \
 -      ${lispsource}international/utf-8.elc \
 -      ${lispsource}international/utf-16.elc \
 -      ${lispsource}international/latin-1.el \
 -      ${lispsource}international/latin-2.el \
 -      ${lispsource}international/latin-3.el \
 -      ${lispsource}international/latin-4.el \
 -      ${lispsource}international/latin-5.el \
 -      ${lispsource}international/latin-8.el \
 -      ${lispsource}international/latin-9.el \
        ${lispsource}case-table.elc \
 -      ${lispsource}language/chinese.elc \
 -      ${lispsource}language/cyrillic.elc \
 -      ${lispsource}language/indian.elc \
 +      ${lispsource}language/chinese.el \
 +      ${lispsource}language/cyrillic.el \
 +      ${lispsource}language/indian.el \
        ${lispsource}language/devanagari.el \
        ${lispsource}language/kannada.el \
        ${lispsource}language/malayalam.el \
        ${lispsource}language/lao.el \
        ${lispsource}language/thai.el \
        ${lispsource}language/tibetan.elc \
 -      ${lispsource}language/vietnamese.elc \
 +      ${lispsource}language/vietnamese.el \
        ${lispsource}language/misc-lang.el \
        ${lispsource}language/utf-8-lang.el \
        ${lispsource}language/georgian.el \
@@@ -784,7 -793,6 +784,7 @@@ shortlisp= 
        ../lisp/buff-menu.elc \
        ../lisp/button.elc \
        ../lisp/emacs-lisp/byte-run.elc \
 +      ../lisp/composite.elc \
        ../lisp/cus-face.elc \
        ../lisp/cus-start.elc \
        ../lisp/custom.elc \
        ../lisp/international/mule-conf.el \
        ../lisp/international/mule-cmds.elc \
        ../lisp/international/characters.elc \
 -      ../lisp/international/ucs-tables.elc \
 -      ../lisp/international/utf-8.elc \
 -      ../lisp/international/utf-16.elc \
 -      ../lisp/international/latin-1.el \
 -      ../lisp/international/latin-2.el \
 -      ../lisp/international/latin-3.el \
 -      ../lisp/international/latin-4.el \
 -      ../lisp/international/latin-5.el \
 -      ../lisp/international/latin-8.el \
 -      ../lisp/international/latin-9.el \
        ../lisp/case-table.elc \
 -      ../lisp/language/chinese.elc \
 -      ../lisp/language/cyrillic.elc \
 -      ../lisp/language/indian.elc \
 +      ../lisp/language/chinese.el \
 +      ../lisp/language/cyrillic.el \
 +      ../lisp/language/indian.el \
        ../lisp/language/devanagari.el \
        ../lisp/language/kannada.el \
        ../lisp/language/malayalam.el \
        ../lisp/language/lao.el \
        ../lisp/language/thai.el \
        ../lisp/language/tibetan.elc \
 -      ../lisp/language/vietnamese.elc \
 +      ../lisp/language/vietnamese.el \
        ../lisp/language/misc-lang.el \
        ../lisp/language/utf-8-lang.el \
        ../lisp/language/georgian.el \
@@@ -1023,73 -1041,71 +1023,77 @@@ alloca.o: alloca.c blockinput.h atimer.
     it is so often changed in ways that do not require any recompilation
     and so rarely changed in ways that do require any.  */
  
 -abbrev.o: abbrev.c buffer.h window.h dispextern.h commands.h charset.h \
 +abbrev.o: abbrev.c buffer.h window.h dispextern.h commands.h character.h \
-       $(config_h)
+       syntax.h $(config_h)
  buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \
 -   dispextern.h $(INTERVAL_SRC) blockinput.h atimer.h systime.h charset.h \
 +   dispextern.h $(INTERVAL_SRC) blockinput.h atimer.h systime.h character.h \
     $(config_h)
- callint.o: callint.c window.h commands.h buffer.h \
+ callint.o: callint.c window.h commands.h buffer.h keymap.h \
     keyboard.h dispextern.h $(config_h)
  callproc.o: callproc.c epaths.h buffer.h commands.h $(config_h) \
 -      process.h systty.h syssignal.h charset.h coding.h ccl.h msdos.h \
 +      process.h systty.h syssignal.h character.h coding.h ccl.h msdos.h \
-         composite.h
+         composite.h w32.h
 -casefiddle.o: casefiddle.c syntax.h commands.h buffer.h composite.h \
 +casefiddle.o: casefiddle.c syntax.h commands.h buffer.h character.h \
-    composite.h $(config_h)
++   composite.h \
+       charset.h keymap.h $(config_h)
  casetab.o: casetab.c buffer.h $(config_h)
- category.o: category.c category.h buffer.h charset.h character.h $(config_h)
 -category.o: category.c category.h buffer.h charset.h keymap.h $(config_h)
 -ccl.o: ccl.c ccl.h charset.h coding.h $(config_h)
 -charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \
 -      $(config_h)
 -coding.o: coding.c coding.h ccl.h buffer.h charset.h intervals.h composite.h \
++category.o: category.c category.h buffer.h charset.h keymap.h \
++      character.h $(config_h)
 +ccl.o: ccl.c ccl.h charset.h character.h coding.h $(config_h)
 +character.o: character.c character.h buffer.h charset.h composite.h disptab.h \
 +   $(config.h)
 +charset.o: charset.c charset.h character.h buffer.h coding.h composite.h \
 +   disptab.h $(config_h)
 +chartab.o: charset.h character.h $(config.h)
- coding.o: coding.c coding.h ccl.h buffer.h character.h charset.h intervals.h composite.h window.h $(config_h)
++coding.o: coding.c coding.h ccl.h buffer.h character.h charset.h intervals.h composite.h \
+       window.h dispextern.h $(config_h)
  cm.o: cm.c cm.h termhooks.h $(config_h)
 -cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \
 +cmds.o: cmds.c syntax.h buffer.h character.h commands.h window.h $(config_h) \
-       msdos.h dispextern.h
+       msdos.h dispextern.h keyboard.h keymap.h
  pre-crt0.o: pre-crt0.c
  ecrt0.o: ecrt0.c $(config_h)
        CRT0_COMPILE ${srcdir}/ecrt0.c
 -dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \
 -   systime.h
 +dired.o: dired.c commands.h buffer.h $(config_h) character.h charset.h \
 +   coding.h regex.h systime.h
  dispnew.o: dispnew.c  systty.h systime.h commands.h process.h frame.h \
     window.h buffer.h dispextern.h termchar.h termopts.h termhooks.h cm.h \
-    disptab.h \
+    disptab.h indent.h intervals.h \
 -   xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \
 +   xterm.h blockinput.h atimer.h character.h msdos.h composite.h keyboard.h \
     $(config_h)
- doc.o: doc.c $(config_h) epaths.h buffer.h keyboard.h character.h
 -doc.o: doc.c $(config_h) epaths.h buffer.h keyboard.h keymap.h charset.h
 -doprnt.o: doprnt.c charset.h $(config_h)
++doc.o: doc.c $(config_h) epaths.h buffer.h keyboard.h keymap.h character.h
 +doprnt.o: doprnt.c character.h $(config_h)
- dosfns.o: buffer.h termchar.h termhooks.h frame.h msdos.h dosfns.h $(config_h)
+ dosfns.o: buffer.h termchar.h termhooks.h frame.h blockinput.h window.h \
+    msdos.h dosfns.h dispextern.h charset.h coding.h $(config_h)
 -editfns.o: editfns.c window.h buffer.h systime.h $(INTERVAL_SRC) charset.h \
 +editfns.o: editfns.c window.h buffer.h systime.h $(INTERVAL_SRC) character.h \
-    coding.h dispextern.h $(config_h)
+    coding.h dispextern.h frame.h $(config_h)
  emacs.o: emacs.c commands.h systty.h syssignal.h blockinput.h process.h \
     termhooks.h buffer.h atimer.h systime.h $(INTERVAL_SRC) $(config_h) \
-    window.h keyboard.h keymap.h
+    window.h dispextern.h keyboard.h keymap.h
 -fileio.o: fileio.c window.h buffer.h systime.h $(INTERVAL_SRC) charset.h \
 +fileio.o: fileio.c window.h buffer.h systime.h $(INTERVAL_SRC) character.h \
-    coding.h ccl.h msdos.h dispextern.h $(config_h)
+    coding.h msdos.h dispextern.h $(config_h)
 -filelock.o: filelock.c buffer.h charset.h coding.h systime.h epaths.h $(config_h)
 +filelock.o: filelock.c buffer.h character.h charset.h coding.h systime.h \
 +   epaths.h $(config_h)
  filemode.o: filemode.c  $(config_h)
  frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \
 -   blockinput.h atimer.h systime.h buffer.h charset.h fontset.h \
 +   blockinput.h atimer.h systime.h buffer.h character.h fontset.h \
-    msdos.h dosfns.h dispextern.h $(config_h)
+    msdos.h dosfns.h dispextern.h w32term.h macterm.h $(config_h)
  fringe.o: fringe.c dispextern.h frame.h window.h buffer.h $(config_h)
 -fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \
 -   keyboard.h $(config_h)
 +fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h character.h \
 +   charset.h frame.h keyboard.h $(config_h)
  getloadavg.o: getloadavg.c $(config_h)
  image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \
     systime.h xterm.h w32term.h w32gui.h macterm.h macgui.h $(config_h)
  indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \
 -   termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \
 -   keyboard.h
 -insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h \
 +   termopts.h disptab.h region-cache.h character.h category.h composite.h \
 +   dispextern.h keyboard.h
 +insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h character.h \
-    dispextern.h atimer.h systime.h $(config_h)
+    dispextern.h atimer.h systime.h region-cache.h $(config_h)
 -keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h charset.h \
 +keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \
     commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \
     systty.h systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \
-    atimer.h xterm.h puresize.h msdos.h $(config_h)
+    atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h $(config_h)
  keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \
 -   atimer.h systime.h puresize.h charset.h intervals.h $(config_h)
 +   atimer.h systime.h puresize.h character.h intervals.h $(config_h)
  lastfile.o: lastfile.c  $(config_h)
  macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h \
        dispextern.h $(config_h)
@@@ -1097,35 -1113,34 +1101,36 @@@ malloc.o: malloc.c $(config_h
  gmalloc.o: gmalloc.c $(config_h)
  ralloc.o: ralloc.c $(config_h)
  vm-limit.o: vm-limit.c mem-limits.h $(config_h)
 -marker.o: marker.c buffer.h charset.h $(config_h)
 +marker.o: marker.c buffer.h character.h $(config_h)
  md5.o: md5.c md5.h $(config_h)
  minibuf.o: minibuf.c syntax.h dispextern.h frame.h window.h keyboard.h \
-    buffer.h commands.h character.h msdos.h $(config_h)
 -   buffer.h commands.h charset.h msdos.h $(INTERVAL_SRC) keymap.h $(config_h)
++   buffer.h commands.h character.h msdos.h $(INTERVAL_SRC) keymap.h $(config_h)
  mktime.o: mktime.c $(config_h)
  msdos.o: msdos.c msdos.h dosfns.h systime.h termhooks.h dispextern.h frame.h \
 -   termopts.h termchar.h charset.h coding.h ccl.h disptab.h window.h \
 +   termopts.h termchar.h character.h coding.h ccl.h disptab.h window.h \
-    keyboard.h intervals.h $(config_h)
+    keyboard.h intervals.h buffer.h commands.h blockinput.h $(config_h)
  process.o: process.c process.h buffer.h window.h termhooks.h termopts.h \
     commands.h syssignal.h systime.h systty.h syswait.h frame.h dispextern.h \
     blockinput.h atimer.h charset.h coding.h ccl.h msdos.h composite.h \
     keyboard.h $(config_h)
 -regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h
 +regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h character.h \
 +   charset.h
  region-cache.o: region-cache.c buffer.h region-cache.h $(config_h)
  scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.h \
     $(config_h)
  search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
 -   blockinput.h atimer.h systime.h category.h charset.h composite.h \
 -   $(INTERVAL_SRC) $(config_h)
 +   blockinput.h atimer.h systime.h category.h character.h composite.h \
++   $(INTERVAL_SRC) \
 +   $(config_h)
  strftime.o: strftime.c $(config_h)
 -syntax.o: syntax.c syntax.h buffer.h commands.h category.h charset.h \
 +syntax.o: syntax.c syntax.h buffer.h commands.h category.h character.h \
-    composite.h $(config_h)
+    composite.h keymap.h regex.h $(INTERVAL_SRC) $(config_h)
  sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
     process.h dispextern.h termhooks.h termchar.h termopts.h \
     frame.h atimer.h window.h msdos.h dosfns.h keyboard.h  $(config_h)
  term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
 -   disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h \
 -   window.h keymap.h
 +   disptab.h dispextern.h keyboard.h character.h charset.h coding.h ccl.h \
-    msdos.h keymap.h
++   msdos.h window.h keymap.h
  termcap.o: termcap.c $(config_h)
  terminfo.o: terminfo.c $(config_h)
  tparam.o: tparam.c $(config_h)
@@@ -1135,29 -1150,29 +1140,31 @@@ undo.o: undo.c buffer.h commands.h $(co
  UNEXEC_ALIAS=UNEXEC
  $(UNEXEC_ALIAS): UNEXEC_SRC $(config_h)
  w16select.o: w16select.c dispextern.h frame.h blockinput.h atimer.h systime.h \
-    msdos.h $(config_h)
+    msdos.h buffer.h charset.h coding.h composite.h $(config_h)
  widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
     $(srcdir)/../lwlib/lwlib.h $(config_h)
  window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \
     termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \
 -xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \
 -   termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \
 -   keyboard.h $(INTERVAL_SRC) region-cache.h xterm.h w32term.h macterm.h \
 -   msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h
 -xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
 -   window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \
 -   keyboard.h fontset.h w32term.h macterm.h $(INTERVAL_SRC) $(config_h)
+    keymap.h blockinput.h $(INTERVAL_SRC) xterm.h w32term.h macterm.h $(config_h)
- xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \
-    termchar.h frame.h window.h disptab.h termhooks.h character.h charset.h \
-    $(config_h) msdos.h composite.h fontset.h blockinput.h atimer.h systime.h \
-    keymap.h region-cache.h
- xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
-    window.h character.h charset.h msdos.h dosfns.h composite.h atimer.h \
-    systime.h fontset.h $(config_h) $(INTERVAL_SRC)
++xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h \
++   coding.h termchar.h frame.h window.h disptab.h termhooks.h character.h     \
++   charset.h keyboard.h $(INTERVAL_SRC) region-cache.h xterm.h w32term.h      \
++   macterm.h $(config_h) msdos.h composite.h fontset.h blockinput.h atimer.h  \
++   systime.h keymap.h
++xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
++   window.h character.h charset.h msdos.h dosfns.h composite.h atimer.h       \
++   systime.h keyboard.h fontset.h w32term.h macterm.h $(INTERVAL_SRC) \
 +   $(config_h)
  xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
     $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
 -   charset.h gtkutil.h $(config_h)
 +   character.h charset.h coding.h gtkutil.h $(config_h) termhooks.h
  xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \
 -   keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \
 -   gtkutil.h msdos.h coding.h $(config_h)
 +   charset.h keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h \
 +   systime.h gtkutil.h msdos.h coding.h $(config_h)
  xterm.o: xterm.c xterm.h termhooks.h termopts.h termchar.h window.h buffer.h \
 -  dispextern.h frame.h disptab.h blockinput.h atimer.h systime.h syssignal.h \
 -  keyboard.h gnu.h charset.h ccl.h fontset.h composite.h \
 -  coding.h process.h gtkutil.h $(config_h)
 +   dispextern.h frame.h disptab.h blockinput.h atimer.h systime.h syssignal.h \
 +   keyboard.h gnu.h character.h charset.h ccl.h fontset.h composite.h \
 +   coding.h process.h gtkutil.h $(config_h)
  xselect.o: xselect.c process.h dispextern.h frame.h xterm.h blockinput.h \
    buffer.h atimer.h systime.h $(config_h)
  xrdb.o: xrdb.c $(config_h) epaths.h
@@@ -1173,26 -1188,27 +1180,29 @@@ atimer.o: atimer.c atimer.h systime.h $
  /* The files of Lisp proper */
  
  alloc.o: alloc.c process.h frame.h window.h buffer.h  puresize.h syssignal.h keyboard.h \
 - blockinput.h atimer.h systime.h charset.h dispextern.h $(config_h) $(INTERVAL_SRC)
 -bytecode.o: bytecode.c buffer.h syntax.h charset.h window.h dispextern.h \
 + blockinput.h atimer.h systime.h character.h dispextern.h $(config_h) \
 + $(INTERVAL_SRC)
- bytecode.o: bytecode.c buffer.h syntax.h character.h window.h $(config_h)
- data.o: data.c buffer.h puresize.h character.h syssignal.h keyboard.h \
++bytecode.o: bytecode.c buffer.h syntax.h character.h window.h dispextern.h \
+   frame.h xterm.h $(config_h)
 -data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h frame.h $(config_h)
++data.o: data.c buffer.h puresize.h character.h syssignal.h keyboard.h frame.h \
 + $(config_h)
  eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h \
    dispextern.h $(config_h)
  floatfns.o: floatfns.c $(config_h)
 -fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \
 +fns.o: fns.c commands.h $(config_h) frame.h buffer.h character.h keyboard.h \
-  frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h
+  keymap.h frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h \
+  blockinput.h xterm.h
 -print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \
 +print.o: print.c process.h frame.h window.h buffer.h keyboard.h character.h \
-    $(config_h) dispextern.h msdos.h composite.h
+    $(config_h) dispextern.h termchar.h $(INTERVAL_SRC) msdos.h composite.h
 -lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h \
 - $(config_h) $(INTERVAL_SRC) termhooks.h coding.h msdos.h
 +lread.o: lread.c commands.h keyboard.h buffer.h epaths.h character.h \
-  charset.h $(config_h) termhooks.h coding.h msdos.h
++ charset.h $(config_h) $(INTERVAL_SRC) termhooks.h coding.h msdos.h
  
  /* Text properties support */
  textprop.o: textprop.c buffer.h window.h dispextern.h $(INTERVAL_SRC) \
        $(config_h)
- intervals.o: intervals.c buffer.h $(INTERVAL_SRC) keyboard.h puresize.h $(config_h)
+ intervals.o: intervals.c buffer.h $(INTERVAL_SRC) keyboard.h puresize.h \
+       keymap.h $(config_h)
 -composite.o: composite.c buffer.h  charset.h $(INTERVAL_SRC) $(config_h)
 +composite.o: composite.c buffer.h  character.h $(INTERVAL_SRC) $(config_h)
  
  /* System-specific programs to be made.
     OTHER_FILES and OBJECTS_MACHINE
diff --combined src/alloc.c
@@@ -1,6 -1,6 +1,6 @@@
  /* Storage allocation and gc for GNU Emacs Lisp interpreter.
-    Copyright (C) 1985,86,88,93,94,95,97,98,1999,2000,01,02,03,2004
-       Free Software Foundation, Inc.
+    Copyright (C) 1985, 1986, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
+       2000, 2001, 2002, 2003, 2004  Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
  
@@@ -45,7 -45,7 +45,7 @@@ Boston, MA 02111-1307, USA.  *
  #include "keyboard.h"
  #include "frame.h"
  #include "blockinput.h"
 -#include "charset.h"
 +#include "character.h"
  #include "syssignal.h"
  #include <setjmp.h>
  
@@@ -1928,7 -1928,7 +1928,7 @@@ INIT must be an integer that represent
    CHECK_NUMBER (init);
  
    c = XINT (init);
 -  if (SINGLE_BYTE_CHAR_P (c))
 +  if (ASCII_CHAR_P (c))
      {
        nbytes = XINT (length);
        val = make_uninit_string (nbytes);
@@@ -2675,6 -2675,49 +2675,6 @@@ See also the function `vector'.  */
  }
  
  
 -DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
 -       doc: /* Return a newly created char-table, with purpose PURPOSE.
 -Each element is initialized to INIT, which defaults to nil.
 -PURPOSE should be a symbol which has a `char-table-extra-slots' property.
 -The property's value should be an integer between 0 and 10.  */)
 -     (purpose, init)
 -     register Lisp_Object purpose, init;
 -{
 -  Lisp_Object vector;
 -  Lisp_Object n;
 -  CHECK_SYMBOL (purpose);
 -  n = Fget (purpose, Qchar_table_extra_slots);
 -  CHECK_NUMBER (n);
 -  if (XINT (n) < 0 || XINT (n) > 10)
 -    args_out_of_range (n, Qnil);
 -  /* Add 2 to the size for the defalt and parent slots.  */
 -  vector = Fmake_vector (make_number (CHAR_TABLE_STANDARD_SLOTS + XINT (n)),
 -                       init);
 -  XCHAR_TABLE (vector)->top = Qt;
 -  XCHAR_TABLE (vector)->parent = Qnil;
 -  XCHAR_TABLE (vector)->purpose = purpose;
 -  XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
 -  return vector;
 -}
 -
 -
 -/* Return a newly created sub char table with default value DEFALT.
 -   Since a sub char table does not appear as a top level Emacs Lisp
 -   object, we don't need a Lisp interface to make it.  */
 -
 -Lisp_Object
 -make_sub_char_table (defalt)
 -     Lisp_Object defalt;
 -{
 -  Lisp_Object vector
 -    = Fmake_vector (make_number (SUB_CHAR_TABLE_STANDARD_SLOTS), Qnil);
 -  XCHAR_TABLE (vector)->top = Qnil;
 -  XCHAR_TABLE (vector)->defalt = defalt;
 -  XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
 -  return vector;
 -}
 -
 -
  DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
         doc: /* Return a newly created vector with specified arguments as elements.
  Any number of arguments, even zero arguments, are allowed.
@@@ -4411,6 -4454,20 +4411,20 @@@ returns nil, because real GC can't be d
    for (i = 0; i < staticidx; i++)
      mark_object (*staticvec[i]);
  
+   for (bind = specpdl; bind != specpdl_ptr; bind++)
+     {
+       mark_object (bind->symbol);
+       mark_object (bind->old_value);
+     }
+   mark_kboards ();
+ #ifdef USE_GTK
+   {
+     extern void xg_mark_data ();
+     xg_mark_data ();
+   }
+ #endif
  #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
       || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
    mark_stack ();
  #endif
  
    mark_byte_stack ();
-   for (bind = specpdl; bind != specpdl_ptr; bind++)
-     {
-       mark_object (bind->symbol);
-       mark_object (bind->old_value);
-     }
    for (catch = catchlist; catch; catch = catch->next)
      {
        mark_object (catch->tag);
        mark_object (handler->var);
      }
    mark_backtrace ();
-   mark_kboards ();
  
  #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
    mark_stack ();
  #endif
  
- #ifdef USE_GTK
-   {
-     extern void xg_mark_data ();
-     xg_mark_data ();
-   }
- #endif
    /* Everything is now marked, except for the things that require special
       finalization, i.e. the undo_list.
       Look thru every buffer's undo list
@@@ -5738,6 -5782,7 +5739,6 @@@ The time is in seconds as a floating po
    defsubr (&Smake_byte_code);
    defsubr (&Smake_list);
    defsubr (&Smake_vector);
 -  defsubr (&Smake_char_table);
    defsubr (&Smake_string);
    defsubr (&Smake_bool_vector);
    defsubr (&Smake_symbol);
diff --combined src/bytecode.c
@@@ -1,5 -1,5 +1,5 @@@
  /* Execution of byte code produced by bytecomp.el.
-    Copyright (C) 1985, 1986, 1987, 1988, 1993, 2000, 2001, 2002, 2003
+    Copyright (C) 1985, 1986, 1987, 1988, 1993, 2000, 2001, 2002, 2003, 2004
     Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
@@@ -37,7 -37,7 +37,7 @@@ by Hallvard
  #include <config.h>
  #include "lisp.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "syntax.h"
  #include "window.h"
  
@@@ -387,6 -387,7 +387,7 @@@ unmark_byte_stack (
        Vquit_flag = Qnil;                              \
          BEFORE_POTENTIAL_GC ();                               \
        Fsignal (Qquit, Qnil);                          \
+       AFTER_POTENTIAL_GC ();                          \
        }                                                       \
    } while (0)
  
@@@ -539,9 -540,7 +540,7 @@@ If the third argument is incorrect, Ema
              TOP = Qnil;
            else
              {
-               BEFORE_POTENTIAL_GC ();
-               Fcar (wrong_type_argument (Qlistp, v1));
-               AFTER_POTENTIAL_GC ();
+               wrong_type_argument (Qlistp, v1);
              }
            break;
          }
              TOP = Qnil;
            else
              {
-               BEFORE_POTENTIAL_GC ();
-               Fcdr (wrong_type_argument (Qlistp, v1));
-               AFTER_POTENTIAL_GC ();
+               wrong_type_argument (Qlistp, v1);
              }
            break;
          }
                else if (!NILP (v1))
                  {
                    immediate_quit = 0;
-                   BEFORE_POTENTIAL_GC ();
-                   v1 = wrong_type_argument (Qlistp, v1);
-                   AFTER_POTENTIAL_GC ();
-                   immediate_quit = 1;
-                   op++;
+                   wrong_type_argument (Qlistp, v1);
                  }
              }
            immediate_quit = 0;
            else if (NILP (v1))
              TOP = Qnil;
            else
-             {
-               BEFORE_POTENTIAL_GC ();
-               Fcar (wrong_type_argument (Qlistp, v1));
-               AFTER_POTENTIAL_GC ();
-             }
+             wrong_type_argument (Qlistp, v1);
            break;
          }
  
          break;
  
        case Bchar_syntax:
 -        BEFORE_POTENTIAL_GC ();
 -        CHECK_NUMBER (TOP);
 -        AFTER_POTENTIAL_GC ();
 -        XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (XINT (TOP))]);
 +        {
 +          int c;
 +
 +          BEFORE_POTENTIAL_GC ();
 +          CHECK_CHARACTER (TOP);
 +          AFTER_POTENTIAL_GC ();
 +          c = XFASTINT (TOP);
 +          if (NILP (current_buffer->enable_multibyte_characters))
 +            MAKE_CHAR_MULTIBYTE (c);
 +          XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (c)]);
 +        }
          break;
  
        case Bbuffer_substring:
                    else if (!NILP (v1))
                      {
                        immediate_quit = 0;
-                       BEFORE_POTENTIAL_GC ();
-                       v1 = wrong_type_argument (Qlistp, v1);
-                       AFTER_POTENTIAL_GC ();
-                       immediate_quit = 1;
-                       op++;
+                       wrong_type_argument (Qlistp, v1);
                      }
                  }
                immediate_quit = 0;
                else if (NILP (v1))
                  TOP = Qnil;
                else
-                 {
-                   BEFORE_POTENTIAL_GC ();
-                   Fcar (wrong_type_argument (Qlistp, v1));
-                   AFTER_POTENTIAL_GC ();
-                 }
+                 wrong_type_argument (Qlistp, v1);
              }
            else
              {
diff --combined src/editfns.c
@@@ -44,7 -44,7 +44,7 @@@ Boston, MA 02111-1307, USA.  *
  #include "lisp.h"
  #include "intervals.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "coding.h"
  #include "frame.h"
  #include "window.h"
@@@ -181,7 -181,9 +181,7 @@@ usage: (char-to-string CHAR)  */
  
    CHECK_NUMBER (character);
  
 -  len = (SINGLE_BYTE_CHAR_P (XFASTINT (character))
 -       ? (*str = (unsigned char)(XFASTINT (character)), 1)
 -       : char_to_string (XFASTINT (character), str));
 +  len = CHAR_STRING (XFASTINT (character), str);
    return make_string_from_bytes (str, 1, len);
  }
  
@@@ -246,7 -248,10 +246,7 @@@ clip_to_bounds (lower, num, upper
  
  DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
         doc: /* Set point to POSITION, a number or marker.
 -Beginning of buffer is position (point-min), end is (point-max).
 -If the position is in the middle of a multibyte form,
 -the actual point is set at the head of the multibyte form
 -except in the case that `enable-multibyte-characters' is nil.  */)
 +Beginning of buffer is position (point-min), end is (point-max).  */)
       (position)
       register Lisp_Object position;
  {
@@@ -2013,7 -2018,7 +2013,7 @@@ general_insert_function (insert_func, i
            len = CHAR_STRING (XFASTINT (val), str);
          else
            {
 -            str[0] = (SINGLE_BYTE_CHAR_P (XINT (val))
 +            str[0] = (ASCII_CHAR_P (XINT (val))
                        ? XINT (val)
                        : multibyte_char_to_unibyte (XINT (val), Qnil));
              len = 1;
@@@ -2184,29 -2189,6 +2184,29 @@@ from adjoining text, if those propertie
    return Qnil;
  }
  
 +DEFUN ("insert-byte", Finsert_byte, Sinsert_byte, 2, 3, 0,
 +       doc: /* Insert COUNT (second arg) copies of BYTE (first arg).
 +Both arguments are required.
 +BYTE is a number of the range 0..255.
 +
 +If BYTE is 128..255 and the current buffer is multibyte, the
 +corresponding eight-bit character is inserted.
 +
 +Point, and before-insertion markers, are relocated as in the function `insert'.
 +The optional third arg INHERIT, if non-nil, says to inherit text properties
 +from adjoining text, if those properties are sticky.  */)
 +     (byte, count, inherit)
 +       Lisp_Object byte, count, inherit;
 +{
 +  CHECK_NUMBER (byte);
 +  if (XINT (byte) < 0 || XINT (byte) > 255)
 +    args_out_of_range_3 (byte, make_number (0), make_number (255));
 +  if (XINT (byte) >= 128
 +      && ! NILP (current_buffer->enable_multibyte_characters))
 +    XSETFASTINT (byte, BYTE8_TO_CHAR (XINT (byte)));
 +  return Finsert_char (byte, count, inherit);
 +}
 +
  \f
  /* Making strings from buffer contents.  */
  
@@@ -2754,73 -2736,10 +2754,73 @@@ Both characters must have the same leng
    return Qnil;
  }
  
 -DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
 -       doc: /* From START to END, translate characters according to TABLE.
 -TABLE is a string; the Nth character in it is the mapping
 -for the character with code N.
 +
 +static Lisp_Object check_translation P_ ((int, int, int, Lisp_Object));
 +
 +/* Helper function for Ftranslate_region_internal.
 +
 +   Check if a character sequence at POS (POS_BYTE) matches an element
 +   of VAL.  VAL is a list (([FROM-CHAR ...] . TO) ...).  If a matching
 +   element is found, return it.  Otherwise return Qnil.  */
 +
 +static Lisp_Object
 +check_translation (pos, pos_byte, end, val)
 +     int pos, pos_byte, end;
 +     Lisp_Object val;
 +{
 +  int buf_size = 16, buf_used = 0;
 +  int *buf = alloca (sizeof (int) * buf_size);
 +
 +  for (; CONSP (val); val = XCDR (val))
 +    {
 +      Lisp_Object elt;
 +      int len, i;
 +
 +      elt = XCAR (val);
 +      if (! CONSP (elt))
 +      continue;
 +      elt = XCAR (elt);
 +      if (! VECTORP (elt))
 +      continue;
 +      len = ASIZE (elt);
 +      if (len <= end - pos)
 +      {
 +        for (i = 0; i < len; i++)
 +          {
 +            if (buf_used <= i)
 +              {
 +                unsigned char *p = BYTE_POS_ADDR (pos_byte);
 +                int len;
 +
 +                if (buf_used == buf_size)
 +                  {
 +                    int *newbuf;
 +
 +                    buf_size += 16;
 +                    newbuf = alloca (sizeof (int) * buf_size);
 +                    memcpy (newbuf, buf, sizeof (int) * buf_used);
 +                    buf = newbuf;
 +                  }
 +                buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, 0, len);
 +                pos_byte += len;
 +              }
 +            if (XINT (AREF (elt, i)) != buf[i])
 +              break;
 +          }
 +        if (i == len)
 +          return XCAR (val);
 +      }
 +    }
 +  return Qnil;
 +}
 +
 +
 +DEFUN ("translate-region-internal", Ftranslate_region_internal,
 +       Stranslate_region_internal, 3, 3, 0,
 +       doc: /* Internal use only.
 +From START to END, translate characters according to TABLE.
 +TABLE is a string or a char-table; the Nth character in it is the
 +mapping for the character with code N.
  It returns the number of characters changed.  */)
       (start, end, table)
       Lisp_Object start;
    register int nc;            /* New character. */
    int cnt;                    /* Number of changes made. */
    int size;                   /* Size of translate table. */
 -  int pos, pos_byte;
 +  int pos, pos_byte, end_pos;
    int multibyte = !NILP (current_buffer->enable_multibyte_characters);
    int string_multibyte;
 +  Lisp_Object val;
  
    validate_region (&start, &end);
 -  CHECK_STRING (table);
 -
 -  if (multibyte != (SCHARS (table) < SBYTES (table)))
 -    table = (multibyte
 -           ? string_make_multibyte (table)
 -           : string_make_unibyte (table));
 -  string_multibyte = SCHARS (table) < SBYTES (table);
 -
 -  size = SCHARS (table);
 -  tt = SDATA (table);
 +  if (CHAR_TABLE_P (table))
 +    {
 +      if (! EQ (XCHAR_TABLE (table)->purpose, Qtranslation_table))
 +      error ("Not a translation table");
 +      tt = NULL;
 +    }
 +  else
 +    {
 +      CHECK_STRING (table);
 +
 +      if (multibyte != (SCHARS (table) < SBYTES (table)))
 +      table = (multibyte
 +               ? string_make_multibyte (table)
 +               : string_make_unibyte (table));
 +      string_multibyte = SCHARS (table) < SBYTES (table);
 +      size = SBYTES (table);
 +      tt = SDATA (table);
 +    }
  
    pos = XINT (start);
    pos_byte = CHAR_TO_BYTE (pos);
 -  modify_region (current_buffer, pos, XINT (end));
 +  end_pos = XINT (end); 
 +  modify_region (current_buffer, pos, end_pos);
  
    cnt = 0;
 -  for (; pos < XINT (end); )
 +  for (; pos < end_pos; )
      {
        register unsigned char *p = BYTE_POS_ADDR (pos_byte);
 -      unsigned char *str;
 +      unsigned char *str, buf[MAX_MULTIBYTE_LENGTH];
        int len, str_len;
        int oc;
 +      Lisp_Object val;
  
        if (multibyte)
 -      oc = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, len);
 +      nc = oc = STRING_CHAR_AND_LENGTH (p, 0, len);
        else
 -      oc = *p, len = 1;
 -      if (oc < size)
 +      nc = oc = *p, len = 1;
 +      if (tt)
        {
 -        if (string_multibyte)
 +        if (oc < size)
            {
 -            str = tt + string_char_to_byte (table, oc);
 -            nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, str_len);
 +            if (string_multibyte)
 +              {
 +                str = tt + string_char_to_byte (table, oc);
 +                nc = STRING_CHAR_AND_LENGTH (str, 0, str_len);
 +              }
 +            else
 +              {
 +                str = tt + oc;
 +                nc = tt[oc], str_len = 1;
 +              }
            }
 -        else
 +      }
 +      else
 +      {
 +        val = CHAR_TABLE_REF (table, oc);
 +        if (CHARACTERP (val))
            {
 -            str = tt + oc;
 -            nc = tt[oc], str_len = 1;
 +            nc = XFASTINT (val);
 +            str_len = CHAR_STRING (nc, buf);
 +            str = buf;
            }
 -        if (nc != oc)
 +        else if (VECTORP (val) || (CONSP (val)))
            {
 +            /* VAL is [TO_CHAR ...] or (([FROM-CHAR ...] .  TO) ...)
 +               where TO is TO-CHAR or [TO-CHAR ...].  */
 +            nc = -1;
 +          }
 +      }
 +
 +      if (nc != oc)
 +      {
 +        if (nc >= 0)
 +          {
 +            /* Simple one char to one char translation.  */
              if (len != str_len)
                {
                  Lisp_Object string;
  
                  /* This is less efficient, because it moves the gap,
 -                   but it should multibyte characters correctly.  */
 +                   but it should handle multibyte characters correctly.  */
                  string = make_multibyte_string (str, 1, str_len);
                  replace_range (pos, pos + 1, string, 1, 0, 1);
                  len = str_len;
                }
              ++cnt;
            }
 +        else
 +          {
 +            Lisp_Object string;
 +
 +            if (CONSP (val))
 +              {
 +                val = check_translation (pos, pos_byte, end_pos, val);
 +                if (NILP (val))
 +                  {
 +                    pos_byte += len;
 +                    pos++;
 +                    continue;
 +                  }
 +                /* VAL is ([FROM-CHAR ...] . TO).  */
 +                len = ASIZE (XCAR (val));
 +                val = XCDR (val);
 +              }
 +            else
 +              len = 1;
 +
 +            if (VECTORP (val))
 +              {
 +                int i;
 +
 +                string = Fmake_string (make_number (ASIZE (val)),
 +                                       AREF (val, 0));
 +                for (i = 1; i < ASIZE (val); i++)
 +                  Faset (string, make_number (i), AREF (val, i));
 +              }
 +            else
 +              {
 +                string = Fmake_string (make_number (1), val);
 +              }
 +            replace_range (pos, pos + len, string, 1, 0, 1);
 +            pos_byte += SBYTES (string);
 +            pos += SCHARS (string);
 +            cnt += SCHARS (string);
 +            end_pos += SCHARS (string) - len;
 +            continue;
 +          }
        }
        pos_byte += len;
        pos++;
@@@ -3556,8 -3400,8 +3556,8 @@@ usage: (format STRING &rest OBJECTS)  *
            thissize = 30;
            if (*format == 'c')
              {
 -              if (! SINGLE_BYTE_CHAR_P (XINT (args[n]))
 -                  /* Note: No one can remember why we have to treat
 +              if (! ASCII_CHAR_P (XINT (args[n]))
 +                  /* Note: No one can remeber why we have to treat
                       the character 0 as a multibyte character here.
                       But, until it causes a real problem, let's
                       don't change it.  */
  
          /* Adjust the bounds of each text property
             to the proper start and end in the output string.  */
-         /* We take advantage of the fact that the positions in PROPS
-            are in increasing order, so that we can do (effectively)
-            one scan through the position space of the format string.
  
-            BYTEPOS is the byte position in the format string,
+         /* Put the positions in PROPS in increasing order, so that
+            we can do (effectively) one scan through the position
+            space of the format string.  */
+         props = Fnreverse (props);
+         /* BYTEPOS is the byte position in the format string,
             POSITION is the untranslated char position in it,
             TRANSLATED is the translated char position in BUF,
             and ARGN is the number of the next arg we will come to.  */
@@@ -3939,20 -3785,8 +3941,20 @@@ Case is ignored if `case-fold-search' i
    /* Do these in separate statements,
       then compare the variables.
       because of the way DOWNCASE uses temp variables.  */
 -  i1 = DOWNCASE (XFASTINT (c1));
 -  i2 = DOWNCASE (XFASTINT (c2));
 +  i1 = XFASTINT (c1);
 +  if (NILP (current_buffer->enable_multibyte_characters)
 +      && ! ASCII_CHAR_P (i1))
 +    {
 +      MAKE_CHAR_MULTIBYTE (i1);
 +    }
 +  i2 = XFASTINT (c2);
 +  if (NILP (current_buffer->enable_multibyte_characters)
 +      && ! ASCII_CHAR_P (i2))
 +    {
 +      MAKE_CHAR_MULTIBYTE (i2);
 +    }
 +  i1 = DOWNCASE (i1);
 +  i2 = DOWNCASE (i2);
    return (i1 == i2 ? Qt :  Qnil);
  }
  \f
@@@ -4429,7 -4263,6 +4431,7 @@@ functions if all the text being accesse
    defsubr (&Sinsert_and_inherit);
    defsubr (&Sinsert_and_inherit_before_markers);
    defsubr (&Sinsert_char);
 +  defsubr (&Sinsert_byte);
  
    defsubr (&Suser_login_name);
    defsubr (&Suser_real_login_name);
    defsubr (&Sinsert_buffer_substring);
    defsubr (&Scompare_buffer_substrings);
    defsubr (&Ssubst_char_in_region);
 -  defsubr (&Stranslate_region);
 +  defsubr (&Stranslate_region_internal);
    defsubr (&Sdelete_region);
    defsubr (&Sdelete_and_extract_region);
    defsubr (&Swiden);
diff --combined src/fileio.c
@@@ -1,6 -1,6 +1,6 @@@
  /* File IO for GNU Emacs.
-    Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000,01,03,2004
-      Free Software Foundation, Inc.
+    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998,
+      1999, 2000, 2001, 2003, 2004  Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
  
@@@ -75,7 -75,7 +75,7 @@@ extern int errno
  #include "lisp.h"
  #include "intervals.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "coding.h"
  #include "window.h"
  
@@@ -296,7 -296,6 +296,7 @@@ restore_point_unwind (location
    Fset_marker (location, Qnil, Qnil);
    return Qnil;
  }
 +
  \f
  Lisp_Object Qexpand_file_name;
  Lisp_Object Qsubstitute_in_file_name;
@@@ -3696,7 -3695,7 +3696,7 @@@ actually used.  */
    unsigned char buffer[1 << 14];
    int replace_handled = 0;
    int set_coding_system = 0;
 -  int coding_system_decided = 0;
 +  Lisp_Object coding_system;
    int read_quit = 0;
  
    if (current_buffer->base_buffer && ! NILP (visit))
    CHECK_STRING (filename);
    filename = Fexpand_file_name (filename, Qnil);
  
 +  /* The value Qnil means that the coding system is not yet
 +     decided.  */
 +  coding_system = Qnil;
 +
    /* If the file name has special constructs in it,
       call the corresponding file handler.  */
    handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
  
    if (EQ (Vcoding_system_for_read, Qauto_save_coding))
      {
 -      /* We use emacs-mule for auto saving... */
 -      setup_coding_system (Qemacs_mule, &coding);
 -      /* ... but with the special flag to indicate to read in a
 -       multibyte sequence for eight-bit-control char as is.  */
 -      coding.flags = 1;
 -      coding.src_multibyte = 0;
 -      coding.dst_multibyte
 -      = !NILP (current_buffer->enable_multibyte_characters);
 -      coding.eol_type = CODING_EOL_LF;
 -      coding_system_decided = 1;
 +      coding_system = Qutf_8_emacs;
 +      setup_coding_system (coding_system, &coding);
 +      /* Ensure we set Vlast_coding_system_used.  */
 +      set_coding_system = 1;
      }
    else if (BEG < Z)
      {
        /* Decide the coding system to use for reading the file now
           because we can't use an optimized method for handling
           `coding:' tag if the current buffer is not empty.  */
 -      Lisp_Object val;
 -      val = Qnil;
 -
        if (!NILP (Vcoding_system_for_read))
 -      val = Vcoding_system_for_read;
 +      coding_system = Vcoding_system_for_read;
        else if (! NILP (replace))
        /* In REPLACE mode, we can use the same coding system
           that was used to visit the file.  */
 -      val = current_buffer->buffer_file_coding_system;
 +      coding_system = current_buffer->buffer_file_coding_system;
        else
        {
          /* Don't try looking inside a file for a coding system
  
                  insert_1_both (read_buf, nread, nread, 0, 0, 0);
                  TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
 -                val = call2 (Vset_auto_coding_function,
 -                             filename, make_number (nread));
 +                coding_system = call2 (Vset_auto_coding_function,
 +                                       filename, make_number (nread));
                  set_buffer_internal (prev);
  
                  /* Discard the unwind protect for recovering the
                }
            }
  
 -        if (NILP (val))
 +        if (NILP (coding_system))
            {
              /* If we have not yet decided a coding system, check
                   file-coding-system-alist.  */
 -            Lisp_Object args[6], coding_systems;
 +            Lisp_Object args[6];
  
              args[0] = Qinsert_file_contents, args[1] = orig_filename;
              args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
 -            coding_systems = Ffind_operation_coding_system (6, args);
 -            if (CONSP (coding_systems))
 -              val = XCAR (coding_systems);
 +            coding_system = Ffind_operation_coding_system (6, args);
 +            if (CONSP (coding_system))
 +              coding_system = XCAR (coding_system);
            }
        }
  
 -      setup_coding_system (Fcheck_coding_system (val), &coding);
 -      /* Ensure we set Vlast_coding_system_used.  */
 -      set_coding_system = 1;
 +      if (NILP (coding_system))
 +      coding_system = Qundecided;
 +      else
 +      CHECK_CODING_SYSTEM (coding_system);
  
 -      if (NILP (current_buffer->enable_multibyte_characters)
 -        && ! NILP (val))
 +      if (NILP (current_buffer->enable_multibyte_characters))
        /* We must suppress all character code conversion except for
           end-of-line conversion.  */
 -      setup_raw_text_coding_system (&coding);
 +      coding_system = raw_text_coding_system (coding_system);
  
 -      coding.src_multibyte = 0;
 -      coding.dst_multibyte
 -      = !NILP (current_buffer->enable_multibyte_characters);
 -      coding_system_decided = 1;
 +      setup_coding_system (coding_system, &coding);
 +      /* Ensure we set Vlast_coding_system_used.  */
 +      set_coding_system = 1;
      }
  
    /* If requested, replace the accessible part of the buffer
       and let the following if-statement handle the replace job.  */
    if (!NILP (replace)
        && BEGV < ZV
 -      && !(coding.common_flags & CODING_REQUIRE_DECODING_MASK))
 +      && (NILP (coding_system)
 +        || ! CODING_REQUIRE_DECODING (&coding)))
      {
        /* same_at_start and same_at_end count bytes,
         because file access counts bytes
          else if (nread == 0)
            break;
  
 -        if (coding.type == coding_type_undecided)
 -          detect_coding (&coding, buffer, nread);
 -        if (coding.common_flags & CODING_REQUIRE_DECODING_MASK)
 -          /* We found that the file should be decoded somehow.
 -               Let's give up here.  */
 +        if (CODING_REQUIRE_DETECTION (&coding))
            {
 -            giveup_match_end = 1;
 -            break;
 +            coding_system = detect_coding_system (buffer, nread, nread, 1, 0,
 +                                                  coding_system);
 +            setup_coding_system (coding_system, &coding);
            }
  
 -        if (coding.eol_type == CODING_EOL_UNDECIDED)
 -          detect_eol (&coding, buffer, nread);
 -        if (coding.eol_type != CODING_EOL_UNDECIDED
 -            && coding.eol_type != CODING_EOL_LF)
 -          /* We found that the format of eol should be decoded.
 +        if (CODING_REQUIRE_DECODING (&coding))
 +          /* We found that the file should be decoded somehow.
                 Let's give up here.  */
            {
              giveup_match_end = 1;
      {
        int same_at_start = BEGV_BYTE;
        int same_at_end = ZV_BYTE;
 +      int same_at_start_charpos;
 +      int inserted_chars;
        int overlap;
        int bufpos;
 -      /* Make sure that the gap is large enough.  */
 -      int bufsize = 2 * st.st_size;
 -      unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
 +      unsigned char *decoded;
        int temp;
 +      int this_count = SPECPDL_INDEX ();
 +      int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 +      Lisp_Object conversion_buffer;
 +
 +      conversion_buffer = code_conversion_save (1, multibyte);
  
        /* First read the whole file, performing code conversion into
         CONVERSION_BUFFER.  */
  
        if (lseek (fd, XINT (beg), 0) < 0)
 -      {
 -        xfree (conversion_buffer);
 -        report_file_error ("Setting file position",
 -                           Fcons (orig_filename, Qnil));
 -      }
 +      report_file_error ("Setting file position",
 +                         Fcons (orig_filename, Qnil));
  
        total = st.st_size;     /* Total bytes in the file.  */
        how_much = 0;           /* Bytes read from file so far.  */
        inserted = 0;           /* Bytes put into CONVERSION_BUFFER so far.  */
        unprocessed = 0;                /* Bytes not processed in previous loop.  */
  
 +      GCPRO1 (conversion_buffer);
        while (how_much < total)
        {
 +        /* We read one bunch by one (READ_BUF_SIZE bytes) to allow
 +           quitting while reading a huge while.  */
          /* try is reserved in some compilers (Microsoft C) */
          int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
 -        unsigned char *destination = read_buf + unprocessed;
          int this;
  
          /* Allow quitting out of the actual I/O.  */
          immediate_quit = 1;
          QUIT;
 -        this = emacs_read (fd, destination, trytry);
 +        this = emacs_read (fd, read_buf + unprocessed, trytry);
          immediate_quit = 0;
  
 -        if (this < 0 || this + unprocessed == 0)
 +        if (this <= 0)
            {
 -            how_much = this;
 +            if (this < 0)
 +              how_much = this;
              break;
            }
  
          how_much += this;
  
 -        if (CODING_MAY_REQUIRE_DECODING (&coding))
 -          {
 -            int require, result;
 -
 -            this += unprocessed;
 -
 -            /* If we are using more space than estimated,
 -               make CONVERSION_BUFFER bigger.  */
 -            require = decoding_buffer_size (&coding, this);
 -            if (inserted + require + 2 * (total - how_much) > bufsize)
 -              {
 -                bufsize = inserted + require + 2 * (total - how_much);
 -                conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
 -              }
 -
 -            /* Convert this batch with results in CONVERSION_BUFFER.  */
 -            if (how_much >= total)  /* This is the last block.  */
 -              coding.mode |= CODING_MODE_LAST_BLOCK;
 -            if (coding.composing != COMPOSITION_DISABLED)
 -              coding_allocate_composition_data (&coding, BEGV);
 -            result = decode_coding (&coding, read_buf,
 -                                    conversion_buffer + inserted,
 -                                    this, bufsize - inserted);
 -
 -            /* Save for next iteration whatever we didn't convert.  */
 -            unprocessed = this - coding.consumed;
 -            bcopy (read_buf + coding.consumed, read_buf, unprocessed);
 -            if (!NILP (current_buffer->enable_multibyte_characters))
 -              this = coding.produced;
 -            else
 -              this = str_as_unibyte (conversion_buffer + inserted,
 -                                     coding.produced);
 -          }
 -
 -        inserted += this;
 +        BUF_SET_PT (XBUFFER (conversion_buffer),
 +                    BUF_Z (XBUFFER (conversion_buffer)));
 +        decode_coding_c_string (&coding, read_buf, unprocessed + this,
 +                                conversion_buffer);
 +        unprocessed = coding.carryover_bytes;
 +        if (coding.carryover_bytes > 0)
 +          bcopy (coding.carryover, read_buf, unprocessed);
        }
 +      UNGCPRO;
 +      emacs_close (fd);
  
 -      /* At this point, INSERTED is how many characters (i.e. bytes)
 -       are present in CONVERSION_BUFFER.
 -       HOW_MUCH should equal TOTAL,
 -       or should be <= 0 if we couldn't read the file.  */
 +      /* At this point, HOW_MUCH should equal TOTAL, or should be <= 0
 +       if we couldn't read the file.  */
  
        if (how_much < 0)
        {
 -        xfree (conversion_buffer);
 -
          if (how_much == -1)
            error ("IO error reading %s: %s",
                   SDATA (orig_filename), emacs_strerror (errno));
            error ("maximum buffer size exceeded");
        }
  
 -      /* Compare the beginning of the converted file
 -       with the buffer text.  */
 +      if (unprocessed > 0)
 +      {
 +        coding.mode |= CODING_MODE_LAST_BLOCK;
 +        decode_coding_c_string (&coding, read_buf, unprocessed,
 +                                conversion_buffer);
 +        coding.mode &= ~CODING_MODE_LAST_BLOCK;
 +      }
 +
 +      decoded = BUF_BEG_ADDR (XBUFFER (conversion_buffer));
 +      inserted = (BUF_Z_BYTE (XBUFFER (conversion_buffer))
 +                - BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
 +
 +      /* Compare the beginning of the converted string with the buffer
 +       text.  */
  
        bufpos = 0;
        while (bufpos < inserted && same_at_start < same_at_end
 -           && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
 +           && FETCH_BYTE (same_at_start) == decoded[bufpos])
        same_at_start++, bufpos++;
  
 -      /* If the file matches the buffer completely,
 +      /* If the file matches the head of buffer completely,
         there's no need to replace anything.  */
  
        if (bufpos == inserted)
        {
 -        xfree (conversion_buffer);
 -        emacs_close (fd);
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
          del_range_byte (same_at_start, same_at_end, 0);
          inserted = 0;
 +
 +        unbind_to (this_count, Qnil);
          goto handled;
        }
  
 -      /* Extend the start of non-matching text area to multibyte
 -       character boundary.  */
 +      /* Extend the start of non-matching text area to the previous
 +       multibyte character boundary.  */
        if (! NILP (current_buffer->enable_multibyte_characters))
        while (same_at_start > BEGV_BYTE
               && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
        /* Compare with same_at_start to avoid counting some buffer text
         as matching both at the file's beginning and at the end.  */
        while (bufpos > 0 && same_at_end > same_at_start
 -           && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
 +           && FETCH_BYTE (same_at_end - 1) == decoded[bufpos - 1])
        same_at_end--, bufpos--;
  
 -      /* Extend the end of non-matching text area to multibyte
 -       character boundary.  */
 +      /* Extend the end of non-matching text area to the next
 +       multibyte character boundary.  */
        if (! NILP (current_buffer->enable_multibyte_characters))
        while (same_at_end < ZV_BYTE
               && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
  
        /* Replace the chars that we need to replace,
         and update INSERTED to equal the number of bytes
 -       we are taking from the file.  */
 +       we are taking from the decoded string.  */
-       inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
+       inserted -= (ZV_BYTE - same_at_end) + (same_at_start - BEGV_BYTE);
  
        if (same_at_end != same_at_start)
        {
        }
        /* Insert from the file at the proper position.  */
        SET_PT_BOTH (temp, same_at_start);
 -      insert_1 (conversion_buffer + same_at_start - BEGV_BYTE, inserted,
 -              0, 0, 0);
 -      if (coding.cmp_data && coding.cmp_data->used)
 -      coding_restore_composition (&coding, Fcurrent_buffer ());
 -      coding_free_composition_data (&coding);
 -
 +      same_at_start_charpos
 +      = buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
 +                                same_at_start);
 +      inserted_chars
 +      = (buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
 +                                 same_at_start + inserted)
 +         - same_at_start_charpos);
 +      insert_from_buffer (XBUFFER (conversion_buffer),
 +                        same_at_start_charpos, inserted_chars, 0);
        /* Set `inserted' to the number of inserted characters.  */
        inserted = PT - temp;
  
 -      xfree (conversion_buffer);
 -      emacs_close (fd);
 -      specpdl_ptr--;
 +      unbind_to (this_count, Qnil);
  
        goto handled;
      }
    inserted = 0;
  
    /* Here, we don't do code conversion in the loop.  It is done by
 -     code_convert_region after all data are read into the buffer.  */
 +     decode_coding_gap after all data are read into the buffer.  */
    {
      int gap_size = GAP_SIZE;
  
  
   notfound:
  
 -  if (! coding_system_decided)
 +  if (NILP (coding_system))
      {
        /* The coding system is not yet decided.  Decide it by an
         optimized method for handling `coding:' tag.
  
         Note that we can get here only if the buffer was empty
         before the insertion.  */
 -      Lisp_Object val;
 -      val = Qnil;
  
        if (!NILP (Vcoding_system_for_read))
 -      val = Vcoding_system_for_read;
 +      coding_system = Vcoding_system_for_read;
        else
        {
          /* Since we are sure that the current buffer was empty
             before the insertion, we can toggle
             enable-multibyte-characters directly here without taking
 -           care of marker adjustment and byte combining problem.  By
 -           this way, we can run Lisp program safely before decoding
 -           the inserted text.  */
 +           care of marker adjustment.  By this way, we can run Lisp
 +           program safely before decoding the inserted text.  */
          Lisp_Object unwind_data;
 -            int count = SPECPDL_INDEX ();
 +        int count = SPECPDL_INDEX ();
  
          unwind_data = Fcons (current_buffer->enable_multibyte_characters,
                               Fcons (current_buffer->undo_list,
  
          if (inserted > 0 && ! NILP (Vset_auto_coding_function))
            {
 -            val = call2 (Vset_auto_coding_function,
 -                         filename, make_number (inserted));
 +            coding_system = call2 (Vset_auto_coding_function,
 +                                   filename, make_number (inserted));
            }
  
 -        if (NILP (val))
 +        if (NILP (coding_system))
            {
              /* If the coding system is not yet decided, check
                 file-coding-system-alist.  */
 -            Lisp_Object args[6], coding_systems;
 +            Lisp_Object args[6];
  
              args[0] = Qinsert_file_contents, args[1] = orig_filename;
              args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
 -            coding_systems = Ffind_operation_coding_system (6, args);
 -            if (CONSP (coding_systems))
 -              val = XCAR (coding_systems);
 +            coding_system = Ffind_operation_coding_system (6, args);
 +            if (CONSP (coding_system))
 +              coding_system = XCAR (coding_system);
            }
  
          unbind_to (count, Qnil);
          inserted = Z_BYTE - BEG_BYTE;
        }
  
 -      /* The following kludgy code is to avoid some compiler bug.
 -       We can't simply do
 -       setup_coding_system (val, &coding);
 -       on some system.  */
 -      {
 -      struct coding_system temp_coding;
 -      setup_coding_system (val, &temp_coding);
 -      bcopy (&temp_coding, &coding, sizeof coding);
 -      }
 -      /* Ensure we set Vlast_coding_system_used.  */
 -      set_coding_system = 1;
 +      if (NILP (coding_system))
 +      coding_system = Qundecided;
 +      else
 +      CHECK_CODING_SYSTEM (coding_system);
  
 -      if (NILP (current_buffer->enable_multibyte_characters)
 -        && ! NILP (val))
 +      if (NILP (current_buffer->enable_multibyte_characters))
        /* We must suppress all character code conversion except for
           end-of-line conversion.  */
 -      setup_raw_text_coding_system (&coding);
 -      coding.src_multibyte = 0;
 -      coding.dst_multibyte
 -      = !NILP (current_buffer->enable_multibyte_characters);
 +      coding_system = raw_text_coding_system (coding_system);
 +      setup_coding_system (coding_system, &coding);
 +      /* Ensure we set Vlast_coding_system_used.  */
 +      set_coding_system = 1;
      }
  
 -  if (!NILP (visit)
 -      /* Can't do this if part of the buffer might be preserved.  */
 -      && NILP (replace)
 -      && (coding.type == coding_type_no_conversion
 -        || coding.type == coding_type_raw_text))
 +  if (!NILP (visit))
      {
 -      /* Visiting a file with these coding system makes the buffer
 -         unibyte. */
 -      current_buffer->enable_multibyte_characters = Qnil;
 -      coding.dst_multibyte = 0;
 +      /* When we visit a file by raw-text, we change the buffer to
 +       unibyte.  */
 +      if (CODING_FOR_UNIBYTE (&coding)
 +        /* Can't do this if part of the buffer might be preserved.  */
 +        && NILP (replace))
 +      /* Visiting a file with these coding system makes the buffer
 +         unibyte. */
 +      current_buffer->enable_multibyte_characters = Qnil;
      }
  
 -  if (inserted > 0 || coding.type == coding_type_ccl)
 +  coding.dst_multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 +  if (CODING_MAY_REQUIRE_DECODING (&coding)
 +      && (inserted > 0 || CODING_REQUIRE_FLUSHING (&coding)))
      {
 -      if (CODING_MAY_REQUIRE_DECODING (&coding))
 -      {
 -        code_convert_region (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
 -                             &coding, 0, 0);
 -        inserted = coding.produced_char;
 -      }
 -      else
 -      adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
 -                           inserted);
 +      move_gap_both (PT, PT_BYTE);
 +      GAP_SIZE += inserted;
 +      ZV_BYTE -= inserted;
 +      Z_BYTE -= inserted;
 +      ZV -= inserted;
 +      Z -= inserted;
 +      decode_coding_gap (&coding, inserted, inserted);
 +      inserted = coding.produced_char;
 +      coding_system = CODING_ID_NAME (coding.id);
      }
 +  else if (inserted > 0)
 +    adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
 +                       inserted);
  
    /* Now INSERTED is measured in characters.  */
  
    /* Use the conversion type to determine buffer-file-type
       (find-buffer-file-type is now used to help determine the
       conversion).  */
 -  if ((coding.eol_type == CODING_EOL_UNDECIDED
 -       || coding.eol_type == CODING_EOL_LF)
 +  if ((VECTORP (CODING_ID_EOL_TYPE (coding.id))
 +       || EQ (CODING_ID_EOL_TYPE (coding.id), Qunix))
        && ! CODING_REQUIRE_DECODING (&coding))
      current_buffer->buffer_file_type = Qt;
    else
      }
  
    if (set_coding_system)
 -    Vlast_coding_system_used = coding.symbol;
 +    Vlast_coding_system_used = coding_system;
  
    if (! NILP (Ffboundp (Qafter_insert_file_set_coding)))
      {
  }
  \f
  static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object));
 -static Lisp_Object build_annotations_2 P_ ((Lisp_Object, Lisp_Object,
 -                                          Lisp_Object, Lisp_Object));
  
  /* If build_annotations switched buffers, switch back to BUF.
     Kill the temporary buffer that was selected in the meantime.
@@@ -4709,7 -4739,7 +4709,7 @@@ build_annotations_unwind (buf
  
  /* Decide the coding-system to encode the data with.  */
  
 -void
 +static Lisp_Object
  choose_write_coding_system (start, end, filename,
                            append, visit, lockname, coding)
       Lisp_Object start, end, filename, append, visit, lockname;
    if (auto_saving
        && NILP (Fstring_equal (current_buffer->filename,
                              current_buffer->auto_save_file_name)))
 -    {
 -      /* We use emacs-mule for auto saving... */
 -      setup_coding_system (Qemacs_mule, coding);
 -      /* ... but with the special flag to indicate not to strip off
 -       leading code of eight-bit-control chars.  */
 -      coding->flags = 1;
 -      goto done_setup_coding;
 -    }
 +    val = Qutf_8_emacs;
    else if (!NILP (Vcoding_system_for_write))
      {
        val = Vcoding_system_for_write;
            val = XCDR (coding_systems);
        }
  
 -      if (NILP (val)
 -        && !NILP (current_buffer->buffer_file_coding_system))
 +      if (NILP (val))
        {
          /* If we still have not decided a coding system, use the
             default value of buffer-file-coding-system.  */
          using_default_coding = 1;
        }
  
 +      if (! NILP (val) && ! force_raw_text)
 +      {
 +        Lisp_Object spec, attrs;
 +
 +        CHECK_CODING_SYSTEM_GET_SPEC (val, spec);
 +        attrs = AREF (spec, 0);
 +        if (EQ (CODING_ATTR_TYPE (attrs), Qraw_text))
 +          force_raw_text = 1;
 +      }
 +
        if (!force_raw_text
          && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
        /* Confirm that VAL can surely encode the current region.  */
        val = call5 (Vselect_safe_coding_system_function,
                     start, end, val, Qnil, filename);
  
 -      setup_coding_system (Fcheck_coding_system (val), coding);
 -      if (coding->eol_type == CODING_EOL_UNDECIDED
 -        && !using_default_coding)
 -      {
 -        if (! EQ (default_buffer_file_coding.symbol,
 -                  buffer_defaults.buffer_file_coding_system))
 -          setup_coding_system (buffer_defaults.buffer_file_coding_system,
 -                               &default_buffer_file_coding);
 -        if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
 -          {
 -            Lisp_Object subsidiaries;
 -
 -            coding->eol_type = default_buffer_file_coding.eol_type;
 -            subsidiaries = Fget (coding->symbol, Qeol_type);
 -            if (VECTORP (subsidiaries)
 -                && XVECTOR (subsidiaries)->size == 3)
 -              coding->symbol
 -                = XVECTOR (subsidiaries)->contents[coding->eol_type];
 -          }
 -      }
 +      /* If the decided coding-system doesn't specify end-of-line
 +       format, we use that of
 +       `default-buffer-file-coding-system'.  */
 +      if (! using_default_coding
 +        && ! NILP (buffer_defaults.buffer_file_coding_system))
 +      val = (coding_inherit_eol_type
 +             (val, buffer_defaults.buffer_file_coding_system));
  
 +      /* If we decide not to encode text, use `raw-text' or one of its
 +       subsidiaries.  */
        if (force_raw_text)
 -      setup_raw_text_coding_system (coding);
 -      goto done_setup_coding;
 +      val = raw_text_coding_system (val);
      }
  
 -  setup_coding_system (Fcheck_coding_system (val), coding);
 +  setup_coding_system (val, coding);
 +  if (! NILP (val)
 +      && VECTORP (CODING_ID_EOL_TYPE (coding->id)))
 +    val = AREF (CODING_ID_EOL_TYPE (coding->id), 0);
  
 - done_setup_coding:
    if (!STRINGP (start) && !NILP (current_buffer->selective_display))
      coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
 +  return val;
  }
  
  DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 7,
@@@ -4857,6 -4894,7 +4857,6 @@@ This does code conversion according to 
    int save_errno = 0;
    const unsigned char *fn;
    struct stat st;
 -  int tem;
    int count = SPECPDL_INDEX ();
    int count1;
  #ifdef VMS
       We used to make this choice before calling build_annotations, but that
       leads to problems when a write-annotate-function takes care of
       unsavable chars (as was the case with X-Symbol).  */
 -  choose_write_coding_system (start, end, filename,
 -                            append, visit, lockname, &coding);
 -  Vlast_coding_system_used = coding.symbol;
 -
 -  given_buffer = current_buffer;
 -  if (! STRINGP (start))
 -    {
 -      annotations = build_annotations_2 (start, end,
 -                                       coding.pre_write_conversion, annotations);
 -      if (current_buffer != given_buffer)
 -      {
 -        XSETFASTINT (start, BEGV);
 -        XSETFASTINT (end, ZV);
 -      }
 -    }
 +  Vlast_coding_system_used
 +    = choose_write_coding_system (start, end, filename,
 +                                append, visit, lockname, &coding);
  
  #ifdef CLASH_DETECTION
    if (!auto_saving)
    if (GPT > BEG && GPT_ADDR[-1] != '\n')
      move_gap (find_next_newline (GPT, 1));
  #else
 +#if 0
 +  /* The new encoding routine doesn't require the following.  */
 +
    /* Whether VMS or not, we must move the gap to the next of newline
       when we must put designation sequences at beginning of line.  */
    if (INTEGERP (start)
        move_gap_both (PT, PT_BYTE);
        SET_PT_BOTH (opoint, opoint_byte);
      }
 +#endif
  #endif
  
    failure = 0;
      }
    else if (XINT (start) != XINT (end))
      {
 -      tem = CHAR_TO_BYTE (XINT (start));
 -
 -      if (XINT (start) < GPT)
 -      {
 -        failure = 0 > a_write (desc, Qnil, XINT (start),
 -                               min (GPT, XINT (end)) - XINT (start),
 -                               &annotations, &coding);
 -        save_errno = errno;
 -      }
 -
 -      if (XINT (end) > GPT && !failure)
 -      {
 -        tem = max (XINT (start), GPT);
 -        failure = 0 > a_write (desc, Qnil, tem , XINT (end) - tem,
 -                               &annotations, &coding);
 -        save_errno = errno;
 -      }
 +      failure = 0 > a_write (desc, Qnil,
 +                           XINT (start), XINT (end) - XINT (start),
 +                           &annotations, &coding);
 +      save_errno = errno;
      }
    else
      {
      {
        /* We have to flush out a data. */
        coding.mode |= CODING_MODE_LAST_BLOCK;
 -      failure = 0 > e_write (desc, Qnil, 0, 0, &coding);
 +      failure = 0 > e_write (desc, Qnil, 1, 1, &coding);
        save_errno = errno;
      }
  
@@@ -5340,6 -5399,30 +5340,6 @@@ build_annotations (start, end
    return annotations;
  }
  
 -static Lisp_Object
 -build_annotations_2 (start, end, pre_write_conversion, annotations)
 -     Lisp_Object start, end, pre_write_conversion, annotations;
 -{
 -  struct gcpro gcpro1;
 -  Lisp_Object res;
 -
 -  GCPRO1 (annotations);
 -  /* At last, do the same for the function PRE_WRITE_CONVERSION
 -     implied by the current coding-system.  */
 -  if (!NILP (pre_write_conversion))
 -    {
 -      struct buffer *given_buffer = current_buffer;
 -      Vwrite_region_annotations_so_far = annotations;
 -      res = call2 (pre_write_conversion, start, end);
 -      Flength (res);
 -      annotations = (current_buffer != given_buffer
 -                   ? res
 -                   : merge (annotations, res, Qcar_less_than_car));
 -    }
 -
 -  UNGCPRO;
 -  return annotations;
 -}
  \f
  /* Write to descriptor DESC the NCHARS chars starting at POS of STRING.
     If STRING is nil, POS is the character position in the current buffer.
@@@ -5395,6 -5478,9 +5395,6 @@@ a_write (desc, string, pos, nchars, ann
    return 0;
  }
  
 -#ifndef WRITE_BUF_SIZE
 -#define WRITE_BUF_SIZE (16 * 1024)
 -#endif
  
  /* Write text in the range START and END into descriptor DESC,
     encoding them with coding system CODING.  If STRING is nil, START
@@@ -5408,77 -5494,78 +5408,77 @@@ e_write (desc, string, start, end, codi
       int start, end;
       struct coding_system *coding;
  {
 -  register char *addr;
 -  register int nbytes;
 -  char buf[WRITE_BUF_SIZE];
 -  int return_val = 0;
 -
 -  if (start >= end)
 -    coding->composing = COMPOSITION_DISABLED;
 -  if (coding->composing != COMPOSITION_DISABLED)
 -    coding_save_composition (coding, start, end, string);
 -
    if (STRINGP (string))
      {
 -      addr = SDATA (string);
 -      nbytes = SBYTES (string);
 -      coding->src_multibyte = STRING_MULTIBYTE (string);
 -    }
 -  else if (start < end)
 -    {
 -      /* It is assured that the gap is not in the range START and END-1.  */
 -      addr = CHAR_POS_ADDR (start);
 -      nbytes = CHAR_TO_BYTE (end) - CHAR_TO_BYTE (start);
 -      coding->src_multibyte
 -      = !NILP (current_buffer->enable_multibyte_characters);
 -    }
 -  else
 -    {
 -      addr = "";
 -      nbytes = 0;
 -      coding->src_multibyte = 1;
 +      start = 0;
 +      end = SCHARS (string);
      }
  
    /* We used to have a code for handling selective display here.  But,
       now it is handled within encode_coding.  */
 -  while (1)
 -    {
 -      int result;
  
 -      result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
 -      if (coding->produced > 0)
 +  while (start < end)
 +    {
 +      if (STRINGP (string))
        {
 -        coding->produced -= emacs_write (desc, buf, coding->produced);
 -        if (coding->produced)
 +        coding->src_multibyte = SCHARS (string) < SBYTES (string);
 +        if (CODING_REQUIRE_ENCODING (coding))
            {
 -            return_val = -1;
 -            break;
 +            encode_coding_object (coding, string,
 +                                  start, string_char_to_byte (string, start),
 +                                  end, string_char_to_byte (string, end), Qt);
 +          }
 +        else
 +          {
 +            coding->dst_object = string;
 +            coding->consumed_char = SCHARS (string);
 +            coding->produced = SBYTES (string);
            }
        }
 -      nbytes -= coding->consumed;
 -      addr += coding->consumed;
 -      if (result == CODING_FINISH_INSUFFICIENT_SRC
 -        && nbytes > 0)
 +      else
        {
 -        /* The source text ends by an incomplete multibyte form.
 -             There's no way other than write it out as is.  */
 -        nbytes -= emacs_write (desc, addr, nbytes);
 -        if (nbytes)
 +        int start_byte = CHAR_TO_BYTE (start);
 +        int end_byte = CHAR_TO_BYTE (end);
 +
 +        coding->src_multibyte = (end - start) < (end_byte - start_byte);
 +        if (CODING_REQUIRE_ENCODING (coding))
            {
 -            return_val = -1;
 -            break;
 +            encode_coding_object (coding, Fcurrent_buffer (),
 +                                  start, start_byte, end, end_byte, Qt);
 +          }
 +        else
 +          {
 +            coding->dst_object = Qnil;
 +            coding->dst_pos_byte = start_byte;
 +            if (start >= GPT || end <= GPT)
 +              {
 +                coding->consumed_char = end - start;
 +                coding->produced = end_byte - start_byte;
 +              }
 +            else
 +              {
 +                coding->consumed_char = GPT - start;
 +                coding->produced = GPT_BYTE - start_byte;
 +              }
            }
        }
 -      if (nbytes <= 0)
 -      break;
 +
 +      if (coding->produced > 0)
 +      {
 +        coding->produced -=
 +          emacs_write (desc,
 +                       STRINGP (coding->dst_object)
 +                       ? SDATA (coding->dst_object)
 +                       : BYTE_POS_ADDR (coding->dst_pos_byte),
 +                       coding->produced);
 +
 +        if (coding->produced)
 +          return -1;
 +      }
        start += coding->consumed_char;
 -      if (coding->cmp_data)
 -      coding_adjust_composition_offset (coding, start);
      }
  
 -  if (coding->cmp_data)
 -    coding_free_composition_data (coding);
 -
 -  return return_val;
 +  return 0;
  }
  \f
  DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
diff --combined src/msdos.c
@@@ -56,7 -56,7 +56,7 @@@ Boston, MA 02111-1307, USA.  *
  #include "dispextern.h"
  #include "dosfns.h"
  #include "termopts.h"
 -#include "charset.h"
 +#include "character.h"
  #include "coding.h"
  #include "disptab.h"
  #include "frame.h"
@@@ -752,6 -752,9 +752,9 @@@ msdos_set_cursor_shape (struct frame *f
    if (f && f != SELECTED_FRAME())
      return;
  
+   if (termscript)
+     fprintf (termscript, "\nCURSOR SHAPE=(%d,%d)", start_line, width);
    /* The character cell size in scan lines is stored at 40:85 in the
       BIOS data area.  */
    max_line = _farpeekw (_dos_ds, 0x485) - 1;
@@@ -851,10 -854,12 +854,12 @@@ IT_set_cursor_type (struct frame *f, Li
        }
      }
    else
-     /* Treat anything unknown as "box cursor".  This includes nil, so
-        that a frame which doesn't specify a cursor type gets a box,
-        which is the default in Emacs.  */
-     msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
+     {
+       /* Treat anything unknown as "box cursor".  This includes nil, so
+        that a frame which doesn't specify a cursor type gets a box,
+        which is the default in Emacs.  */
+       msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
+     }
  }
  
  static void
@@@ -1826,6 -1831,8 +1831,8 @@@ static int cursor_cleared
  static void
  IT_display_cursor (int on)
  {
+   if (termscript)
+     fprintf (termscript, "\nCURSOR %s", on ? "ON" : "OFF");
    if (on && cursor_cleared)
      {
        ScreenSetCursor (current_pos_Y, current_pos_X);
@@@ -3792,15 -3799,15 +3799,15 @@@ XMenuActivate (Display *foo, XMenu *men
    screensize = screen_size * 2;
    faces[0]
      = lookup_derived_face (sf, intern ("msdos-menu-passive-face"),
 -                         0, DEFAULT_FACE_ID);
 +                         DEFAULT_FACE_ID);
    faces[1]
      = lookup_derived_face (sf, intern ("msdos-menu-active-face"),
 -                         0, DEFAULT_FACE_ID);
 +                         DEFAULT_FACE_ID);
    selectface = intern ("msdos-menu-select-face");
    faces[2] = lookup_derived_face (sf, selectface,
 -                                0, faces[0]);
 +                                faces[0]);
    faces[3] = lookup_derived_face (sf, selectface,
 -                                0, faces[1]);
 +                                faces[1]);
  
    /* Make sure the menu title is always displayed with
       `msdos-menu-active-face', no matter where the mouse pointer is.  */
diff --combined src/xdisp.c
@@@ -176,7 -176,6 +176,7 @@@ Boston, MA 02111-1307, USA.  *
  #include "termchar.h"
  #include "dispextern.h"
  #include "buffer.h"
 +#include "character.h"
  #include "charset.h"
  #include "indent.h"
  #include "commands.h"
@@@ -715,13 -714,11 +715,13 @@@ static enum prop_handled handle_display
  static enum prop_handled handle_composition_prop P_ ((struct it *));
  static enum prop_handled handle_overlay_change P_ ((struct it *));
  static enum prop_handled handle_fontified_prop P_ ((struct it *));
 +static enum prop_handled handle_auto_composed_prop P_ ((struct it *));
  
  /* Properties handled by iterators.  */
  
  static struct props it_props[] =
  {
 +  {&Qauto_composed,   AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop},
    {&Qfontified,               FONTIFIED_PROP_IDX,     handle_fontified_prop},
    /* Handle `face' before `display' because some sub-properties of
       `display' need to know the face.  */
@@@ -3031,7 -3028,7 +3031,7 @@@ face_before_or_after_it_pos (it, before
          struct face *face = FACE_FROM_ID (it->f, face_id);
  
          c = string_char_and_length (p, rest, &len);
 -        face_id = FACE_FOR_CHAR (it->f, face, c);
 +        face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
        }
      }
    else
        {
          int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
          struct face *face = FACE_FROM_ID (it->f, face_id);
 -        face_id = FACE_FOR_CHAR (it->f, face, c);
 +        face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
        }
      }
  
@@@ -3589,7 -3586,7 +3589,7 @@@ handle_single_display_prop (it, prop, o
            {
              Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
  
 -            face_id = lookup_named_face (it->f, face_name, 'A');
 +            face_id = lookup_named_face (it->f, face_name);
              if (face_id < 0)
                return 0;
            }
@@@ -3922,90 -3919,6 +3922,90 @@@ string_buffer_position (w, string, arou
                        `composition' property
   ***********************************************************************/
  
 +static enum prop_handled
 +handle_auto_composed_prop (it)
 +     struct it *it;
 +{
 +  enum prop_handled handled = HANDLED_NORMALLY;
 +
 +  if (FUNCTIONP (Vauto_composition_function))
 +    {
 +      Lisp_Object val;
 +      EMACS_INT pos, this_pos;
 +
 +      if (STRINGP (it->string))
 +      pos = IT_STRING_CHARPOS (*it);
 +      else
 +      pos = IT_CHARPOS (*it);
 +      this_pos = pos;
 +
 +      val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
 +      if (! NILP (val))
 +      {
 +        Lisp_Object limit = Qnil, next;
 +        
 +        /* As Fnext_single_char_property_change is very slow, we
 +           limit the search to the current line.  */
 +        if (STRINGP (it->string))
 +          limit = make_number (SCHARS (it->string));
 +        else
 +          limit = make_number (find_next_newline_no_quit (pos, 1));
 +
 +        next = (Fnext_single_property_change
 +                   (make_number (pos), Qauto_composed, it->string, limit));
 +        if (XINT (next) < XINT (limit))
 +          {
 +            /* The current point is auto-composed, but there exist
 +               characters not yet composed beyond the auto-composed
 +               region.  There's a possiblity that the last
 +               characters in the region may be newly composed.  */
 +            int charpos = XINT (next) - 1, bytepos, c;
 +
 +            if (STRINGP (it->string))
 +              {
 +                bytepos = string_char_to_byte (it->string, charpos);
 +                c = SDATA (it->string)[bytepos];
 +              }
 +            else
 +              {
 +                bytepos = CHAR_TO_BYTE (charpos);
 +                c = FETCH_BYTE (bytepos);
 +              }
 +            if (c != '\n')
 +              /* If the last character is not newline, it may be
 +                 composed with the following characters.  */
 +              val = Qnil, pos = charpos + 1;
 +          }
 +      }
 +      if (NILP (val))
 +      {
 +        int count = SPECPDL_INDEX ();
 +        Lisp_Object args[3];
 +
 +        args[0] = Vauto_composition_function;
 +        specbind (Qauto_composition_function, Qnil);
 +        args[1] = make_number (pos);
 +        args[2] = it->string;
 +        safe_call (3, args);
 +        unbind_to (count, Qnil);
 +
 +        if (this_pos == pos)
 +          {
 +            val = Fget_char_property (args[1], Qauto_composed, it->string);
 +            /* Return HANDLED_RECOMPUTE_PROPS only if function composed
 +               something.  This avoids an endless loop if they failed to
 +               fontify the text for which reason ever.  */
 +            if (! NILP (val))
 +              handled = HANDLED_RECOMPUTE_PROPS;
 +          }
 +        else
 +          handled = HANDLED_RECOMPUTE_PROPS;
 +      }
 +    }
 +
 +  return handled;
 +}
 +
  /* Set up iterator IT from `composition' property at its current
     position.  Called from handle_stop.  */
  
@@@ -4014,7 -3927,7 +4014,7 @@@ handle_composition_prop (it
       struct it *it;
  {
    Lisp_Object prop, string;
 -  int pos, pos_byte, end;
 +  EMACS_INT pos, pos_byte, start, end;
    enum prop_handled handled = HANDLED_NORMALLY;
  
    if (STRINGP (it->string))
    /* If there's a valid composition and point is not inside of the
       composition (in the case that the composition is from the current
       buffer), draw a glyph composed from the composition components.  */
 -  if (find_composition (pos, -1, &pos, &end, &prop, string)
 -      && COMPOSITION_VALID_P (pos, end, prop)
 -      && (STRINGP (it->string) || (PT <= pos || PT >= end)))
 +  if (find_composition (pos, -1, &start, &end, &prop, string)
 +      && COMPOSITION_VALID_P (start, end, prop)
 +      && (STRINGP (it->string) || (PT <= start || PT >= end)))
      {
 -      int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
 +      int id;
 +
 +      if (start != pos)
 +      {
 +        if (STRINGP (it->string))
 +          pos_byte = string_char_to_byte (it->string, start);
 +        else
 +          pos_byte = CHAR_TO_BYTE (start);
 +      }
 +      id = get_composition_id (start, pos_byte, end - start, prop, string);
  
        if (id >= 0)
        {
@@@ -4985,9 -4889,12 +4985,9 @@@ get_next_display_element (it
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
                        || (it->c != '\n' && it->c != '\t')))
 -                 || (it->multibyte_p
 -                     ? ((it->c >= 127
 -                         && it->len == 1)
 -                        || !CHAR_PRINTABLE_P (it->c))
 -                     : (it->c >= 127
 -                        && it->c == unibyte_char_to_multibyte (it->c))))
 +                 || (it->c != '\n' && it->c != '\t'
 +                     && (it->multibyte_p ? !CHAR_PRINTABLE_P (it->c)
 +                         : it->c == 127)))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
                  else
                    escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
  
 -                if (SINGLE_BYTE_CHAR_P (it->c))
 -                  str[0] = it->c, len = 1;
 +                if (CHAR_BYTE8_P (it->c))
 +                  {
 +                    str[0] = CHAR_TO_BYTE8 (it->c);
 +                    len = 1;
 +                  }
 +                else if (it->c < 256)
 +                  {
 +                    str[0] = it->c;
 +                    len = 1;
 +                  }
                  else
                    {
 -                    len = CHAR_STRING_NO_SIGNAL (it->c, str);
 -                    if (len < 0)
 -                      {
 -                        /* It's an invalid character, which
 -                           shouldn't happen actually, but due to
 -                           bugs it may happen.  Let's print the char
 -                           as is, there's not much meaningful we can
 -                           do with it.  */
 -                        str[0] = it->c;
 -                        str[1] = it->c >> 8;
 -                        str[2] = it->c >> 16;
 -                        str[3] = it->c >> 24;
 -                        len = 4;
 -                      }
 +                    /* It's an invalid character, which
 +                       shouldn't happen actually, but due to
 +                       bugs it may happen.  Let's print the char
 +                       as is, there's not much meaningful we can
 +                       do with it.  */
 +                    str[0] = it->c;
 +                    str[1] = it->c >> 8;
 +                    str[2] = it->c >> 16;
 +                    str[3] = it->c >> 24;
 +                    len = 4;
                    }
  
                  for (i = 0; i < len; i++)
          && FRAME_WINDOW_P (it->f))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
 -        it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
 +        int pos = (it->s ? -1
 +                   : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
 +                   : IT_CHARPOS (*it));
 +        
 +        it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
        }
      }
  
@@@ -6066,16 -5965,6 +6066,16 @@@ move_it_to (it, to_charpos, to_x, to_y
             the line.  */
          if (skip == MOVE_X_REACHED)
            {
 +            /* Wait!  We can conclude that TO_Y is in the line if
 +               the already scanned glyphs make the line tall enough
 +               because further scanning doesn't make it shorter.  */
 +            line_height = it->max_ascent + it->max_descent;
 +            if (to_y >= it->current_y
 +                && to_y < it->current_y + line_height)
 +              {
 +                reached = 6;
 +                break;
 +              }
              it_backup = *it;
              TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
              skip2 = move_it_in_display_line_to (it, to_charpos, -1,
@@@ -6549,7 -6438,7 +6549,7 @@@ message_dolog (m, nbytes, nlflag, multi
          for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (m + i, nbytes - i, &char_bytes);
 -            work[0] = (SINGLE_BYTE_CHAR_P (c)
 +            work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@@ -7819,7 -7708,7 +7819,7 @@@ set_message_1 (a1, a2, nbytes, multibyt
          for (i = 0; i < nbytes; i += n)
            {
              c = string_char_and_length (s + i, nbytes - i, &n);
 -            work[0] = (SINGLE_BYTE_CHAR_P (c)
 +            work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@@ -9678,7 -9567,7 +9678,7 @@@ check_point_in_composition (prev_buf, p
       struct buffer *prev_buf, *buf;
       int prev_pt, pt;
  {
 -  int start, end;
 +  EMACS_INT start, end;
    Lisp_Object prop;
    Lisp_Object buffer;
  
@@@ -10643,24 -10532,35 +10643,24 @@@ disp_char_vector (dp, c
       struct Lisp_Char_Table *dp;
       int c;
  {
 -  int code[4], i;
    Lisp_Object val;
  
 -  if (SINGLE_BYTE_CHAR_P (c))
 -    return (dp->contents[c]);
 -
 -  SPLIT_CHAR (c, code[0], code[1], code[2]);
 -  if (code[1] < 32)
 -    code[1] = -1;
 -  else if (code[2] < 32)
 -    code[2] = -1;
 -
 -  /* Here, the possible range of code[0] (== charset ID) is
 -     128..max_charset.  Since the top level char table contains data
 -     for multibyte characters after 256th element, we must increment
 -     code[0] by 128 to get a correct index.  */
 -  code[0] += 128;
 -  code[3] = -1;               /* anchor */
 -
 -  for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
 +  if (ASCII_CHAR_P (c))
      {
 -      val = dp->contents[code[i]];
 -      if (!SUB_CHAR_TABLE_P (val))
 -      return (NILP (val) ? dp->defalt : val);
 +      val = dp->ascii;
 +      if (SUB_CHAR_TABLE_P (val))
 +      val = XSUB_CHAR_TABLE (val)->contents[c];
      }
 +  else
 +    {
 +      Lisp_Object table;
  
 -  /* Here, val is a sub char table.  We return the default value of
 -     it.  */
 -  return (dp->defalt);
 +      XSETCHAR_TABLE (table, dp);
 +      val = char_table_ref (table, c);
 +    }
 +  if (NILP (val))
 +    val = dp->defalt;
 +  return val;
  }
  
  
@@@ -14395,7 -14295,7 +14395,7 @@@ append_space_for_newline (it, default_f
          else if (it->face_before_selective_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
 -        it->face_id = FACE_FOR_CHAR (it->f, face, 0);
 +        it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
  
          PRODUCE_GLYPHS (it);
  
@@@ -14454,9 -14354,9 +14454,9 @@@ extend_face_to_end_of_line (it
           ASCII face.  This will be automatically undone the next time
           get_next_display_element returns a multibyte character.  Note
           that the character will always be single byte in unibyte text.  */
 -  if (!SINGLE_BYTE_CHAR_P (it->c))
 +  if (!ASCII_CHAR_P (it->c))
      {
 -      it->face_id = FACE_FOR_CHAR (f, face, 0);
 +      it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
      }
  
    if (FRAME_WINDOW_P (f))
@@@ -14562,7 -14462,7 +14562,7 @@@ highlight_trailing_whitespace (f, row
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
 -        int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
 +        int face_id = lookup_named_face (f, Qtrailing_whitespace);
  
          while (glyph >= start
                 && BUFFERP (glyph->object)
@@@ -16160,7 -16060,7 +16160,7 @@@ decode_mode_spec_coding (coding_system
    /* The EOL conversion we are using.  */
    Lisp_Object eoltype;
  
 -  val = Fget (coding_system, Qcoding_system);
 +  val = CODING_SYSTEM_SPEC (coding_system);
    eoltype = Qnil;
  
    if (!VECTORP (val))         /* Not yet decided.  */
      }
    else
      {
 +      Lisp_Object attrs;
        Lisp_Object eolvalue;
  
 -      eolvalue = Fget (coding_system, Qeol_type);
 +      attrs = AREF (val, 0);
 +      eolvalue = AREF (val, 2);
  
        if (multibyte)
 -      *buf++ = XFASTINT (AREF (val, 1));
 +      *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
  
        if (eol_flag)
        {
            eoltype = eol_mnemonic_undecided;
          else if (VECTORP (eolvalue)) /* Not yet decided.  */
            eoltype = eol_mnemonic_undecided;
 -        else                  /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
 -          eoltype = (XFASTINT (eolvalue) == 0
 +        else                  /* eolvalue is Qunix, Qdos, or Qmac.  */
 +          eoltype = (EQ (eolvalue, Qunix)
                       ? eol_mnemonic_unix
 -                     : (XFASTINT (eolvalue) == 1
 +                     : (EQ (eolvalue, Qdos) == 1
                          ? eol_mnemonic_dos : eol_mnemonic_mac));
        }
      }
          eol_str = SDATA (eoltype);
          eol_str_len = SBYTES (eoltype);
        }
 -      else if (INTEGERP (eoltype)
 -             && CHAR_VALID_P (XINT (eoltype), 0))
 +      else if (CHARACTERP (eoltype))
        {
          unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
          eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
     generated by character C.  PRECISION >= 0 means don't return a
     string longer than that value.  FIELD_WIDTH > 0 means pad the
     string returned with spaces to that value.  Return 1 in *MULTIBYTE
-    if the result is multibyte text.  */
+    if the result is multibyte text.
+    Note we operate on the current buffer for most purposes,
+    the exception being w->base_line_pos.  */
  
  static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
  
@@@ -16242,7 -16144,7 +16245,7 @@@ decode_mode_spec (w, c, field_width, pr
    Lisp_Object obj;
    struct frame *f = XFRAME (WINDOW_FRAME (w));
    char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
-   struct buffer *b = XBUFFER (w->buffer);
+   struct buffer *b = current_buffer;
  
    obj = Qnil;
    *multibyte = 0;
  
      case 's':
        /* status of process */
-       obj = Fget_buffer_process (w->buffer);
+       obj = Fget_buffer_process (Fcurrent_buffer ());
        if (NILP (obj))
        return "no process";
  #ifdef subprocesses
          {
            /* No need to mention EOL here--the terminal never needs
               to do EOL conversion.  */
 -          p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
 -          p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
 +          p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
 +                                       p, 0);
 +          p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
 +                                       p, 0);
          }
        p = decode_mode_spec_coding (b->buffer_file_coding_system,
                                     p, eol_flag);
@@@ -16845,7 -16745,7 +16848,7 @@@ display_string (string, lisp_string, fa
                }
              break;
            }
 -        else if (x + glyph->pixel_width > it->first_visible_x)
 +        else if (x + glyph->pixel_width >= it->first_visible_x)
            {
              /* Glyph is at least partially visible.  */
              ++it->hpos;
@@@ -17394,25 -17294,24 +17397,25 @@@ get_glyph_face_and_encoding (f, glyph, 
      }
    else
      {
 -      int c1, c2, charset;
 +      struct font_info *font_info
 +      = FONT_INFO_FROM_ID (f, face->font_info_id);
 +      if (font_info)
 +      {
 +        struct charset *charset = CHARSET_FROM_ID (font_info->charset);
 +        unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
  
 -      /* Split characters into bytes.  If c2 is -1 afterwards, C is
 -       really a one-byte character so that byte1 is zero.  */
 -      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
 -      if (c2 > 0)
 -      STORE_XCHAR2B (char2b, c1, c2);
 -      else
 -      STORE_XCHAR2B (char2b, 0, c1);
 +        if (CHARSET_DIMENSION (charset) == 1)
 +          STORE_XCHAR2B (char2b, 0, code);
 +        else
 +          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
  
 -      /* Maybe encode the character in *CHAR2B.  */
 -      if (charset != CHARSET_ASCII)
 -      {
 -        struct font_info *font_info
 -          = FONT_INFO_FROM_ID (f, face->font_info_id);
 -        if (font_info)
 -          glyph->font_type
 -            = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
 +        /* Maybe encode the character in *CHAR2B.  */
 +        if (CHARSET_ID (charset) != charset_ascii)
 +          {
 +            glyph->font_type
 +              = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
 +                                  two_byte_p);
 +          }
        }
      }
  
@@@ -17651,13 -17550,6 +17654,13 @@@ x_get_glyph_overhangs (glyph, f, left, 
            *left = -pcm->lbearing;
        }
      }
 +  else if (glyph->type == COMPOSITE_GLYPH)
 +    {
 +      struct composition *cmp = composition_table[glyph->u.cmp_id];
 +
 +      *right = cmp->rbearing - cmp->pixel_width;
 +      *left = - cmp->lbearing;
 +    }
  }
  
  
@@@ -17792,7 -17684,7 +17795,7 @@@ get_char_face_and_encoding (f, c, face_
        /* Unibyte case.  We don't have to encode, but we have to make
         sure to use a face suitable for unibyte.  */
        STORE_XCHAR2B (char2b, 0, c);
 -      face_id = FACE_FOR_CHAR (f, face, c);
 +      face_id = FACE_FOR_CHAR (f, face, c, -1, Qnil);
        face = FACE_FROM_ID (f, face_id);
      }
    else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
        /* Case of ASCII in a face known to fit ASCII.  */
        STORE_XCHAR2B (char2b, 0, c);
      }
 -  else
 +  else if (face->font != NULL)
      {
 -      int c1, c2, charset;
 +      struct font_info *font_info
 +      = FONT_INFO_FROM_ID (f, face->font_info_id);
 +      struct charset *charset = CHARSET_FROM_ID (font_info->charset);
 +      unsigned code = ENCODE_CHAR (charset, c);
  
 -      /* Split characters into bytes.  If c2 is -1 afterwards, C is
 -       really a one-byte character so that byte1 is zero.  */
 -      SPLIT_CHAR (c, charset, c1, c2);
 -      if (c2 > 0)
 -      STORE_XCHAR2B (char2b, c1, c2);
 +      if (CHARSET_DIMENSION (charset) == 1)
 +      STORE_XCHAR2B (char2b, 0, code);
        else
 -      STORE_XCHAR2B (char2b, 0, c1);
 -
 -      /* Maybe encode the character in *CHAR2B.  */
 -      if (face->font != NULL)
 -      {
 -        struct font_info *font_info
 -          = FONT_INFO_FROM_ID (f, face->font_info_id);
 -        if (font_info)
 -          rif->encode_char (c, char2b, font_info, 0);
 -      }
 +      STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 +       /* Maybe encode the character in *CHAR2B.  */
 +      rif->encode_char (c, char2b, font_info, charset, NULL);
      }
  
    /* Make sure X resources of the face are allocated.  */
@@@ -17971,9 -17870,10 +17974,9 @@@ compute_overhangs_and_x (s, x, backward
  #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)          \
       do                                                                          \
         {                                                                 \
 -       int c, face_id;                                                   \
 +       int face_id;                                                      \
         XChar2b *char2b;                                                  \
                                                                           \
 -       c = (row)->glyphs[area][START].u.ch;                              \
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
         s = (struct glyph_string *) alloca (sizeof *s);                   \
      for (n = 0; n < glyph_len; n++)                                     \
        {                                                                         \
        int c = COMPOSITION_GLYPH (cmp, n);                               \
 -      int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
 +      int this_face_id = FACE_FOR_CHAR (f, base_face, c, -1, Qnil);     \
        faces[n] = FACE_FROM_ID (f, this_face_id);                        \
        get_char_face_and_encoding (f, c, this_face_id,                   \
                                    char2b + n, 1, 1);                    \
                 abort ();                                                 \
               }                                                           \
                                                                           \
 -             set_glyph_string_background_width (s, START, LAST_X);       \
 -           (X) += s->width;                                              \
 +           if (s)                                                        \
 +             {                                                           \
 +               set_glyph_string_background_width (s, START, LAST_X);     \
 +               (X) += s->width;                                          \
 +             }                                                           \
              }                                                            \
         }                                                                 \
       while (0)
@@@ -18117,7 -18014,7 +18120,7 @@@ draw_glyphs (w, x, row, area, start, en
       int x;
       struct glyph_row *row;
       enum glyph_row_area area;
 -     int start, end;
 +     EMACS_INT start, end;
       enum draw_glyphs_face hl;
       int overlaps_p;
  {
@@@ -18809,7 -18706,7 +18812,7 @@@ calc_line_height_property (it, prop, fo
        struct face *face;
        struct font_info *font_info;
  
 -      face_id = lookup_named_face (it->f, face_name, ' ');
 +      face_id = lookup_named_face (it->f, face_name);
        if (face_id < 0)
        return make_number (-1);
  
@@@ -18880,17 -18777,23 +18883,17 @@@ x_produce_glyphs (it
        /* Maybe translate single-byte characters to multibyte, or the
         other way.  */
        it->char_to_display = it->c;
 -      if (!ASCII_BYTE_P (it->c))
 +      if (!ASCII_BYTE_P (it->c)
 +        && ! it->multibyte_p)
        {
 -        if (unibyte_display_via_language_environment
 -            && SINGLE_BYTE_CHAR_P (it->c)
 -            && (it->c >= 0240
 -                || !NILP (Vnonascii_translation_table)))
 -          {
 -            it->char_to_display = unibyte_char_to_multibyte (it->c);
 -            it->multibyte_p = 1;
 -            it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
 -            face = FACE_FROM_ID (it->f, it->face_id);
 -          }
 -        else if (!SINGLE_BYTE_CHAR_P (it->c)
 -                 && !it->multibyte_p)
 +        if (SINGLE_BYTE_CHAR_P (it->c)
 +            && unibyte_display_via_language_environment)
 +          it->char_to_display = unibyte_char_to_multibyte (it->c);
 +        if (! SINGLE_BYTE_CHAR_P (it->c))
            {
              it->multibyte_p = 1;
 -            it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
 +            it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
 +                                         -1, Qnil);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
        }
  
          /* If we found a font, this font should give us the right
             metrics.  If we didn't find a font, use the frame's
 -           default font and calculate the width of the character
 -           from the charset width; this is what old redisplay code
 -           did.  */
 +           default font and calculate the width of the character by
 +           multiplying the width of font by the width of the
 +           character.  */
  
          pcm = rif->per_char_metric (font, &char2b,
                                      FONT_TYPE_FOR_MULTIBYTE (font, it->c));
  
          if (font_not_found_p || !pcm)
            {
 -            int charset = CHAR_CHARSET (it->char_to_display);
 -
              it->glyph_not_available_p = 1;
              it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
 -                               * CHARSET_WIDTH (charset));
 +                               * CHAR_WIDTH (it->char_to_display));
              it->phys_ascent = FONT_BASE (font) + boff;
              it->phys_descent = FONT_DESCENT (font) - boff;
            }
        struct font_info *font_info;
        int boff;                       /* baseline offset */
        struct composition *cmp = composition_table[it->cmp_id];
 +      int pos;
  
        /* Maybe translate single-byte characters to multibyte.  */
        it->char_to_display = it->c;
        if (unibyte_display_via_language_environment
 -        && SINGLE_BYTE_CHAR_P (it->c)
 -        && (it->c >= 0240
 -            || (it->c >= 0200
 -                && !NILP (Vnonascii_translation_table))))
 +        && it->c >= 0200)
        {
          it->char_to_display = unibyte_char_to_multibyte (it->c);
        }
  
        /* Get face and font to use.  Encode IT->char_to_display.  */
 -      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
 +      pos = STRINGP (it->string) ? IT_STRING_CHARPOS (*it) : IT_CHARPOS (*it);
 +      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
 +                                 pos, it->string);
        face = FACE_FROM_ID (it->f, it->face_id);
        get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
                                  &char2b, it->multibyte_p, 0);
         now.  Theoretically, we have to check all fonts for the
         glyphs, but that requires much time and memory space.  So,
         here we check only the font of the first glyph.  This leads
 -       to incorrect display very rarely, and C-l (recenter) can
 -       correct the display anyway.  */
 -      if (cmp->font != (void *) font)
 +       to incorrect display, but it's very rare, and C-l (recenter)
 +       can correct the display anyway.  */
 +      if (cmp->glyph_len == 0)
 +      {
 +        cmp->lbearing = cmp->rbearing = 0;
 +        cmp->pixel_width = cmp->ascent = cmp->descent = 0;
 +      }
 +      else if (cmp->font != (void *) font)
        {
          /* Ascent and descent of the font of the first character of
             this composition (adjusted by baseline offset).  Ascent
             them respectively.  */
          int font_ascent = FONT_BASE (font) + boff;
          int font_descent = FONT_DESCENT (font) - boff;
 +        int font_height = FONT_HEIGHT (font);
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
 +        int lbearing, rbearing;
          int i, width, ascent, descent;
  
          cmp->font = (void *) font;
              width = pcm->width;
              ascent = pcm->ascent;
              descent = pcm->descent;
 +            lbearing = pcm->lbearing;
 +            if (lbearing > 0)
 +              lbearing = 0;
 +            rbearing = pcm->rbearing;
 +            if (rbearing < width)
 +              rbearing = width;
            }
          else
            {
              width = FONT_WIDTH (font);
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
 +            lbearing = 0;
 +            rbearing = width;
            }
  
          rightmost = width;
             the left.  */
          cmp->offsets[0] = 0;
          cmp->offsets[1] = boff;
 +        cmp->lbearing = lbearing;
 +        cmp->rbearing = rbearing;
  
          /* Set cmp->offsets for the remaining glyphs.  */
          for (i = 1; i < cmp->glyph_len; i++)
            {
              int left, right, btm, top;
              int ch = COMPOSITION_GLYPH (cmp, i);
 -            int face_id = FACE_FOR_CHAR (it->f, face, ch);
 +            int face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
  
              face = FACE_FROM_ID (it->f, face_id);
              get_char_face_and_encoding (it->f, ch, face->id,
                  width = pcm->width;
                  ascent = pcm->ascent;
                  descent = pcm->descent;
 +                lbearing = pcm->lbearing;
 +                if (lbearing > 0)
 +                  lbearing = 0;
 +                rbearing = pcm->rbearing;
 +                if (rbearing < width)
 +                  rbearing = width;
                }
              else
                {
                  width = FONT_WIDTH (font);
                  ascent = 1;
                  descent = 0;
 +                lbearing = 0;
 +                rbearing = width;
                }
  
              if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
                        6---7---8 -- descent
                  */
                  int rule = COMPOSITION_RULE (cmp, i);
 -                int gref, nref, grefx, grefy, nrefx, nrefy;
 +                int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
  
 -                COMPOSITION_DECODE_RULE (rule, gref, nref);
 +                COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
                  grefx = gref % 3, nrefx = nref % 3;
                  grefy = gref / 3, nrefy = nref / 3;
 +                if (xoff)
 +                  xoff = font_height * (xoff - 128) / 256;
 +                if (yoff)
 +                  yoff = font_height * (yoff - 128) / 256;
  
                  left = (leftmost
                          + grefx * (rightmost - leftmost) / 2
 -                        - nrefx * width / 2);
 +                        - nrefx * width / 2
 +                        + xoff);
 +                
                  btm = ((grefy == 0 ? highest
                          : grefy == 1 ? 0
                          : grefy == 2 ? lowest
                         - (nrefy == 0 ? ascent + descent
                            : nrefy == 1 ? descent - boff
                            : nrefy == 2 ? 0
 -                          : (ascent + descent) / 2));
 +                          : (ascent + descent) / 2)
 +                       + yoff);
                }
  
              cmp->offsets[i * 2] = left;
              cmp->offsets[i * 2 + 1] = btm + descent;
  
              /* Update the bounding box of the overall glyphs. */
 -            right = left + width;
 +            if (width > 0)
 +              {
 +                right = left + width;
 +                if (left < leftmost)
 +                  leftmost = left;
 +                if (right > rightmost)
 +                  rightmost = right;
 +              }
              top = btm + descent + ascent;
 -            if (left < leftmost)
 -              leftmost = left;
 -            if (right > rightmost)
 -              rightmost = right;
              if (top > highest)
                highest = top;
              if (btm < lowest)
                lowest = btm;
 +
 +            if (cmp->lbearing > left + lbearing)
 +              cmp->lbearing = left + lbearing;
 +            if (cmp->rbearing < left + rbearing)
 +              cmp->rbearing = left + rbearing;
            }
  
          /* If there are glyphs whose x-offsets are negative,
              for (i = 0; i < cmp->glyph_len; i++)
                cmp->offsets[i * 2] -= leftmost;
              rightmost -= leftmost;
 +            cmp->lbearing -= leftmost;
 +            cmp->rbearing -= leftmost;
            }
  
          cmp->pixel_width = rightmost;
            cmp->descent = font_descent;
        }
  
 +      if (it->glyph_row
 +        && (cmp->lbearing < 0
 +            || cmp->rbearing > cmp->pixel_width))
 +      it->glyph_row->contains_overlapping_glyphs_p = 1;
 +
        it->pixel_width = cmp->pixel_width;
        it->ascent = it->phys_ascent = cmp->ascent;
        it->descent = it->phys_descent = cmp->descent;
@@@ -19588,8 -19446,7 +19591,8 @@@ x_insert_glyphs (start, len
    int line_height, shift_by_width, shifted_region_width;
    struct glyph_row *row;
    struct glyph *glyph;
 -  int frame_x, frame_y, hpos;
 +  int frame_x, frame_y;
 +  EMACS_INT hpos;
  
    xassert (updated_window && updated_row);
    BLOCK_INPUT;
@@@ -20485,7 -20342,7 +20488,7 @@@ cursor_in_mouse_face_p (w
  static int
  fast_find_position (w, charpos, hpos, vpos, x, y, stop)
       struct window *w;
 -     int charpos;
 +     EMACS_INT charpos;
       int *hpos, *vpos, *x, *y;
       Lisp_Object stop;
  {
  static int
  fast_find_position (w, pos, hpos, vpos, x, y, stop)
       struct window *w;
 -     int pos;
 +     EMACS_INT pos;
       int *hpos, *vpos, *x, *y;
       Lisp_Object stop;
  {
  static int
  fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
       struct window *w;
 -     int pos;
 +     EMACS_INT pos;
       Lisp_Object object;
       int *hpos, *vpos, *x, *y;
       int right_p;
diff --combined src/xfaces.c
@@@ -56,7 -56,7 +56,7 @@@ Boston, MA 02111-1307, USA.  *
     13. Whether or not a box should be drawn around characters, the box
     type, and, for simple boxes, in what color.
  
 -   14. Font or fontset pattern, or nil.  This is a special attribute.
 +   14. Font pattern, or nil.  This is a special attribute.
     When this attribute is specified, the face uses a font opened by
     that pattern as is.  In addition, all the other font-related
     attributes (1st thru 5th) are generated from the opened font name.
@@@ -72,8 -72,6 +72,8 @@@
     and is used to ensure that a font specified on the command line,
     for example, can be matched exactly.
  
 +   17. A fontset name.
 +
     Faces are frame-local by nature because Emacs allows to define the
     same named face (face names are symbols) differently for different
     frames.  Each frame has an alist of face definitions for all named
     is realized, it inherits (thus shares) a fontset of an ASCII face
     that has the same attributes other than font-related ones.
  
 -   Thus, all realized face have a realized fontset.
 +   Thus, all realized faces have a realized fontset.
  
  
     Unibyte text.
  #include <sys/stat.h>
  
  #include "lisp.h"
 +#include "character.h"
  #include "charset.h"
  #include "keyboard.h"
  #include "frame.h"
@@@ -303,7 -300,6 +303,7 @@@ Lisp_Object QCinverse_video, QCforegrou
  Lisp_Object QCwidth, QCfont, QCbold, QCitalic;
  Lisp_Object QCreverse_video;
  Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
 +Lisp_Object QCfontset;
  
  /* Symbols used for attribute values.  */
  
@@@ -389,6 -385,10 +389,10 @@@ Lisp_Object Qforeground_color, Qbackgro
  Lisp_Object Qface;
  extern Lisp_Object Qmouse_face;
  
+ /* Property for basic faces which other faces cannot inherit.  */
+ Lisp_Object Qface_no_inherit;
  /* Error symbol for wrong_type_argument in load_pixmap.  */
  
  Lisp_Object Qbitmap_spec_p;
@@@ -481,7 -481,7 +485,7 @@@ static int load_pixmap P_ ((struct fram
  static unsigned char *xstrlwr P_ ((unsigned char *));
  static void signal_error P_ ((char *, Lisp_Object));
  static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
 -static void load_face_font P_ ((struct frame *, struct face *, int));
 +static void load_face_font P_ ((struct frame *, struct face *));
  static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
  static void free_face_colors P_ ((struct frame *, struct face *));
  static int face_color_gray_p P_ ((struct frame *, char *));
@@@ -494,17 -494,18 +498,17 @@@ static int font_list_1 P_ ((struct fram
                            Lisp_Object, struct font_name **));
  static int font_list P_ ((struct frame *, Lisp_Object, Lisp_Object,
                          Lisp_Object, struct font_name **));
 -static int try_font_list P_ ((struct frame *, Lisp_Object *,
 -                            Lisp_Object, Lisp_Object, struct font_name **,
 -                            int));
 +static int try_font_list P_ ((struct frame *, Lisp_Object,
 +                            Lisp_Object, Lisp_Object, struct font_name **));
  static int try_alternative_families P_ ((struct frame *f, Lisp_Object,
                                         Lisp_Object, struct font_name **));
  static int cmp_font_names P_ ((const void *, const void *));
 -static struct face *realize_face P_ ((struct face_cache *, Lisp_Object *, int,
 -                                    struct face *, int));
 -static struct face *realize_x_face P_ ((struct face_cache *,
 -                                      Lisp_Object *, int, struct face *));
 -static struct face *realize_tty_face P_ ((struct face_cache *,
 -                                        Lisp_Object *, int));
 +static struct face *realize_face P_ ((struct face_cache *, Lisp_Object *,
 +                                    int));
 +static struct face *realize_non_ascii_face P_ ((struct frame *, int,
 +                                              struct face *));
 +static struct face *realize_x_face P_ ((struct face_cache *, Lisp_Object *));
 +static struct face *realize_tty_face P_ ((struct face_cache *, Lisp_Object *));
  static int realize_basic_faces P_ ((struct frame *));
  static int realize_default_face P_ ((struct frame *));
  static void realize_named_face P_ ((struct frame *, Lisp_Object, int));
@@@ -514,12 -515,14 +518,12 @@@ static unsigned hash_string_case_insens
  static unsigned lface_hash P_ ((Lisp_Object *));
  static int lface_same_font_attributes_p P_ ((Lisp_Object *, Lisp_Object *));
  static struct face_cache *make_face_cache P_ ((struct frame *));
 -static void free_realized_face P_ ((struct frame *, struct face *));
  static void clear_face_gcs P_ ((struct face_cache *));
  static void free_face_cache P_ ((struct face_cache *));
  static int face_numeric_weight P_ ((Lisp_Object));
  static int face_numeric_slant P_ ((Lisp_Object));
  static int face_numeric_swidth P_ ((Lisp_Object));
  static int face_fontset P_ ((Lisp_Object *));
 -static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int, int*));
  static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*,
                                    struct named_merge_point *));
  static int merge_face_ref P_ ((struct frame *, Lisp_Object, Lisp_Object *,
@@@ -528,6 -531,7 +532,6 @@@ static int set_lface_from_font_name P_ 
                                         Lisp_Object, int, int));
  static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
  static struct face *make_realized_face P_ ((Lisp_Object *));
 -static void free_realized_faces P_ ((struct face_cache *));
  static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
                                     struct font_name *, int, int, int *));
  static void cache_face P_ ((struct face_cache *, struct face *, unsigned));
@@@ -1216,13 -1220,15 +1220,13 @@@ load_pixmap (f, name, w_ptr, h_ptr
  
  #ifdef HAVE_WINDOW_SYSTEM
  
 -/* Load font of face FACE which is used on frame F to display
 -   character C.  The name of the font to load is determined by lface
 -   and fontset of FACE.  */
 +/* Load font of face FACE which is used on frame F to display ASCII
 +   characters.  The name of the font to load is determined by lface.  */
  
  static void
 -load_face_font (f, face, c)
 +load_face_font (f, face)
       struct frame *f;
       struct face *face;
 -     int c;
  {
    struct font_info *font_info = NULL;
    char *font_name;
  
    face->font_info_id = -1;
    face->font = NULL;
 +  face->font_name = NULL;
  
 -  font_name = choose_face_font (f, face->lface, face->fontset, c,
 -                              &needs_overstrike);
 +  font_name = choose_face_font (f, face->lface, Qnil, &needs_overstrike);
    if (!font_name)
      return;
  
    BLOCK_INPUT;
 -  font_info = FS_LOAD_FACE_FONT (f, c, font_name, face);
 +  font_info = FS_LOAD_FONT (f, font_name);
    UNBLOCK_INPUT;
  
    if (font_info)
@@@ -1376,7 -1382,7 +1380,7 @@@ tty_defined_color (f, color_name, color
    color_def->green = 0;
  
    if (*color_name)
 -    status = tty_lookup_color (f, build_string (color_name), color_def, 0);
 +    status = tty_lookup_color (f, build_string (color_name), color_def, NULL);
  
    if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
      {
@@@ -2119,7 -2125,7 +2123,7 @@@ face_value (table, dim, symbol
  static INLINE int
  face_numeric_value (table, dim, symbol)
       struct table_entry *table;
 -     int dim;
 +     size_t dim;
       Lisp_Object symbol;
  {
    struct table_entry *p = face_value (table, dim, symbol);
@@@ -2160,65 -2166,9 +2164,65 @@@ face_numeric_swidth (width
    return face_numeric_value (swidth_table, DIM (swidth_table), width);
  }
  
 -
  #ifdef HAVE_WINDOW_SYSTEM
  
 +Lisp_Object
 +split_font_name_into_vector (fontname)
 +     Lisp_Object fontname;
 +{
 +  struct font_name font;
 +  Lisp_Object vec;
 +  int i;
 +
 +  font.name = LSTRDUPA (fontname);
 +  if (! split_font_name (NULL, &font, 0))
 +    return Qnil;
 +  vec = Fmake_vector (make_number (XLFD_LAST), Qnil);
 +  for (i = 0; i < XLFD_LAST; i++)
 +    if (font.fields[i][0] != '*')
 +      ASET (vec, i, build_string (font.fields[i]));
 +  return vec;
 +}
 +
 +Lisp_Object
 +build_font_name_from_vector (vec)
 +     Lisp_Object vec;
 +{
 +  struct font_name font;
 +  Lisp_Object fontname;
 +  char *p;
 +  int i;
 +
 +  for (i = 0; i < XLFD_LAST; i++)
 +    {
 +      font.fields[i] = (NILP (AREF (vec, i))
 +                      ? "*" : (char *) SDATA (AREF (vec, i)));
 +      if ((i == XLFD_FAMILY || i == XLFD_REGISTRY)
 +        && (p = strchr (font.fields[i], '-')))
 +      {
 +        char *p1 = STRDUPA (font.fields[i]);
 +
 +        p1[p - font.fields[i]] = '\0';
 +        if (i == XLFD_FAMILY)
 +          {
 +            font.fields[XLFD_FOUNDRY] = p1;
 +            font.fields[XLFD_FAMILY] = p + 1;
 +          }
 +        else
 +          {
 +            font.fields[XLFD_REGISTRY] = p1;
 +            font.fields[XLFD_ENCODING] = p + 1;
 +            break;
 +          }
 +      }
 +    }
 +
 +  p = build_font_name (&font);
 +  fontname = build_string (p);
 +  xfree (p);
 +  return fontname;
 +}
 +
  /* Return non-zero if FONT is the name of a fixed-pitch font.  */
  
  static INLINE int
@@@ -2241,9 -2191,7 +2245,9 @@@ xlfd_fixed_p (font
     72dpi versions, only.)
  
     Value is the real point size of FONT on frame F, or 0 if it cannot
 -   be determined.  */
 +   be determined.
 +
 +   By side effect, set FONT->numeric[XLFD_PIXEL_SIZE].  */
  
  static INLINE int
  xlfd_point_size (f, font)
    else
      pixel = atoi (pixel_field);
  
 +  font->numeric[XLFD_PIXEL_SIZE] = pixel;
    if (pixel == 0)
      real_pt = 0;
    else
@@@ -2769,12 -2716,12 +2773,12 @@@ cmp_font_names (a, b
  }
  
  
 -/* Get a sorted list of fonts of family FAMILY on frame F.  If PATTERN
 -   is non-nil list fonts matching that pattern.  Otherwise, if
 -   REGISTRY is non-nil return only fonts with that registry, otherwise
 -   return fonts of any registry.  Set *FONTS to a vector of font_name
 -   structures allocated from the heap containing the fonts found.
 -   Value is the number of fonts found.  */
 +/* Get a sorted list of fonts matching PATTERN on frame F.  If PATTERN
 +   is nil, list fonts matching FAMILY and REGISTRY.  FAMILY is a
 +   family name string or nil.  REGISTRY is a registry name string.
 +   Set *FONTS to a vector of font_name structures allocated from the
 +   heap containing the fonts found.  Value is the number of fonts
 +   found.  */
  
  static int
  font_list_1 (f, pattern, family, registry, fonts)
@@@ -2835,11 -2782,10 +2839,11 @@@ concat_font_list (fonts1, nfonts1, font
  
  /* Get a sorted list of fonts of family FAMILY on frame F.
  
 -   If PATTERN is non-nil list fonts matching that pattern.
 +   If PATTERN is non-nil, list fonts matching that pattern.
  
 -   If REGISTRY is non-nil, return fonts with that registry and the
 -   alternative registries from Vface_alternative_font_registry_alist.
 +   If REGISTRY is non-nil, it is a list of registry (and encoding)
 +   names.  Return fonts with those registries and the alternative
 +   registries from Vface_alternative_font_registry_alist.
  
     If REGISTRY is nil return fonts of any registry.
  
@@@ -2853,37 -2799,35 +2857,37 @@@ font_list (f, pattern, family, registry
       Lisp_Object pattern, family, registry;
       struct font_name **fonts;
  {
 -  int nfonts = font_list_1 (f, pattern, family, registry, fonts);
 +  int nfonts;
 +  int reg_prio;
 +  int i;
 +
 +  if (NILP (registry))
 +    return font_list_1 (f, pattern, family, registry, fonts);
  
 -  if (!NILP (registry)
 -      && CONSP (Vface_alternative_font_registry_alist))
 +  for (reg_prio = 0, nfonts = 0; CONSP (registry); registry = XCDR (registry))
      {
 -      Lisp_Object alter;
 +      Lisp_Object elt, alter;
 +      int nfonts2;
 +      struct font_name *fonts2;
  
 -      alter = Fassoc (registry, Vface_alternative_font_registry_alist);
 -      if (CONSP (alter))
 +      elt = XCAR (registry);
 +      alter = Fassoc (elt, Vface_alternative_font_registry_alist);
 +      if (NILP (alter))
 +      alter = Fcons (elt, Qnil);
 +      for (; CONSP (alter); alter = XCDR (alter), reg_prio++)
        {
 -        int reg_prio, i;
 -
 -        for (alter = XCDR (alter), reg_prio = 1;
 -             CONSP (alter);
 -             alter = XCDR (alter), reg_prio++)
 -          if (STRINGP (XCAR (alter)))
 -            {
 -              int nfonts2;
 -              struct font_name *fonts2;
 -
 -              nfonts2 = font_list_1 (f, pattern, family, XCAR (alter),
 -                                     &fonts2);
 +        nfonts2 = font_list_1 (f, pattern, family, XCAR (alter), &fonts2);
 +        if (nfonts2 > 0)
 +          {
 +            if (reg_prio > 0)
                for (i = 0; i < nfonts2; i++)
                  fonts2[i].registry_priority = reg_prio;
 -              *fonts = (nfonts > 0
 -                        ? concat_font_list (*fonts, nfonts, fonts2, nfonts2)
 -                        : fonts2);
 -              nfonts += nfonts2;
 -            }
 +            if (nfonts > 0)
 +              *fonts = concat_font_list (*fonts, nfonts, fonts2, nfonts2);
 +            else
 +              *fonts = fonts2;
 +            nfonts += nfonts2;
 +          }
        }
      }
  
@@@ -3065,7 -3009,7 +3069,7 @@@ the WIDTH times as wide as FACE on FRAM
      {
        /* This is of limited utility since it works with character
         widths.  Keep it for compatibility.  --gerd.  */
 -      int face_id = lookup_named_face (f, face, 0);
 +      int face_id = lookup_named_face (f, face);
        struct face *face = (face_id < 0
                           ? NULL
                           : FACE_FROM_ID (f, face_id));
  #define LFACE_FONT(LFACE)         AREF ((LFACE), LFACE_FONT_INDEX)
  #define LFACE_INHERIT(LFACE)      AREF ((LFACE), LFACE_INHERIT_INDEX)
  #define LFACE_AVGWIDTH(LFACE)     AREF ((LFACE), LFACE_AVGWIDTH_INDEX)
 +#define LFACE_FONTSET(LFACE)      AREF ((LFACE), LFACE_FONTSET_INDEX)
  
  /* Non-zero if LFACE is a Lisp face.  A Lisp face is a vector of size
     LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@@ -3188,8 -3131,6 +3192,8 @@@ check_lface_attrs (attrs
    xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
           || NILP (attrs[LFACE_FONT_INDEX])
           || STRINGP (attrs[LFACE_FONT_INDEX]));
 +  xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
 +         || STRINGP (attrs[LFACE_FONTSET_INDEX]));
  #endif
  }
  
@@@ -3359,7 -3300,7 +3363,7 @@@ lface_fully_specified_p (attrs
  
    for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
      if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
 -      && i != LFACE_AVGWIDTH_INDEX)
 +      && i != LFACE_AVGWIDTH_INDEX && i != LFACE_FONTSET_INDEX)
        if (UNSPECIFIEDP (attrs[i])
  #ifdef MAC_OS
          /* MAC_TODO: No stipple support on Mac OS yet, this index is
@@@ -3403,14 -3344,8 +3407,14 @@@ set_lface_from_font_name (f, lface, fon
  
    /* If FONTNAME is actually a fontset name, get ASCII font name of it.  */
    fontset = fs_query_fontset (fontname, 0);
 -  if (fontset >= 0)
 +  if (fontset > 0)
      font_name = SDATA (fontset_ascii (fontset));
 +  else if (fontset == 0)
 +    {
 +      if (may_fail_p)
 +      return 0;
 +      abort ();
 +    }
  
    /* Check if FONT_NAME is surely available on the system.  Usually
       FONT_NAME is already cached for the frame F and FS_LOAD_FONT
       caching it now is not futail because we anyway load the font
       later.  */
    BLOCK_INPUT;
 -  font_info = FS_LOAD_FONT (f, 0, font_name, -1);
 +  font_info = FS_LOAD_FONT (f, font_name);
    UNBLOCK_INPUT;
  
    if (!font_info)
      LFACE_SLANT (lface)
        = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
  
 -  LFACE_FONT (lface) = fontname;
 -
 +  if (fontset > 0)
 +    {
 +      LFACE_FONT (lface) = build_string (font_info->full_name);
 +      LFACE_FONTSET (lface) = fontset_name (fontset);
 +    }
 +  else
 +    {
 +      LFACE_FONT (lface) = fontname;
 +      fontset
 +      = new_fontset_from_font_name (build_string (font_info->full_name));
 +      LFACE_FONTSET (lface) = fontset_name (fontset);
 +    }
    return 1;
  }
  
@@@ -3944,8 -3869,11 +3948,11 @@@ Value is a vector of face attributes.  
       depend on the face, make sure they are all removed.  This is done
       by incrementing face_change_count.  The next call to
       init_iterator will then free realized faces.  */
-   ++face_change_count;
-   ++windows_or_buffers_changed;
+   if (NILP (Fget (face, Qface_no_inherit)))
+     {
+       ++face_change_count;
+       ++windows_or_buffers_changed;
+     }
  
    xassert (LFACEP (lface));
    check_lface (lface);
@@@ -4020,8 -3948,11 +4027,11 @@@ The value is TO.  */
       depend on the face, make sure they are all removed.  This is done
       by incrementing face_change_count.  The next call to
       init_iterator will then free realized faces.  */
-   ++face_change_count;
-   ++windows_or_buffers_changed;
+   if (NILP (Fget (to, Qface_no_inherit)))
+     {
+       ++face_change_count;
+       ++windows_or_buffers_changed;
+     }
  
    return to;
  }
@@@ -4302,7 -4233,7 +4312,7 @@@ FRAME 0 means change the face on all fr
        LFACE_SWIDTH (lface) = value;
        font_related_attr_p = 1;
      }
 -  else if (EQ (attr, QCfont))
 +  else if (EQ (attr, QCfont) || EQ (attr, QCfontset))
      {
  #ifdef HAVE_WINDOW_SYSTEM
        if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
              tmp = Fquery_fontset (value, Qnil);
              if (!NILP (tmp))
                value = tmp;
 +            else if (EQ (attr, QCfontset))
 +              signal_error ("Invalid fontset name", value);
  
 -            if (!set_lface_from_font_name (f, lface, value, 1, 1))
 -              signal_error ("Invalid font or fontset name", value);
 +            if (EQ (attr, QCfont))
 +              {
 +                if (!set_lface_from_font_name (f, lface, value, 1, 1))
 +                  signal_error ("Invalid font or fontset name", value);
 +              }
 +            else
 +              LFACE_FONTSET (lface) = value;
            }
  
          font_attr_p = 1;
       by incrementing face_change_count.  The next call to
       init_iterator will then free realized faces.  */
    if (!EQ (frame, Qt)
+       && NILP (Fget (face, Qface_no_inherit))
        && (EQ (attr, QCfont)
 +        || EQ (attr, QCfontset)
          || NILP (Fequal (old_value, value))))
      {
        ++face_change_count;
  #ifdef HAVE_WINDOW_SYSTEM
  
  /* Set the `font' frame parameter of FRAME determined from `default'
 -   face attributes LFACE.  If a face or fontset name is explicitely
 +   face attributes LFACE.  If a font name is explicitely
     specfied in LFACE, use it as is.  Otherwise, determine a font name
     from the other font-related atrributes of LFACE.  In that case, if
     there's no matching font, signals an error.  */
@@@ -4517,7 -4441,7 +4528,7 @@@ set_font_frame_param (frame, lface
          /* Choose a font name that reflects LFACE's attributes and has
             the registry and encoding pattern specified in the default
             fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
 -        font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0, 0);
 +        font = choose_face_font (f, XVECTOR (lface)->contents, Qnil, NULL);
          if (!font)
            error ("No font matches the specified attribute");
          font_name = build_string (font);
@@@ -4538,6 -4462,7 +4549,7 @@@ update_face_from_frame_parameter (f, pa
       struct frame *f;
       Lisp_Object param, new_value;
  {
+   Lisp_Object face = Qnil;
    Lisp_Object lface;
  
    /* If there are no faces yet, give up.  This is the case when called
    if (NILP (f->face_alist))
      return;
  
-   /* Changing a named face means that all realized faces depending on
-      that face are invalid.  Since we cannot tell which realized faces
-      depend on the face, make sure they are all removed.  This is done
-      by incrementing face_change_count.  The next call to
-      init_iterator will then free realized faces.  */
-   ++face_change_count;
-   ++windows_or_buffers_changed;
    if (EQ (param, Qforeground_color))
      {
-       lface = lface_from_face_name (f, Qdefault, 1);
+       face = Qdefault;
+       lface = lface_from_face_name (f, face, 1);
        LFACE_FOREGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
        realize_basic_faces (f);
        XSETFRAME (frame, f);
        call1 (Qframe_update_face_colors, frame);
  
-       lface = lface_from_face_name (f, Qdefault, 1);
+       face = Qdefault;
+       lface = lface_from_face_name (f, face, 1);
        LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
        realize_basic_faces (f);
      }
-   if (EQ (param, Qborder_color))
+   else if (EQ (param, Qborder_color))
      {
-       lface = lface_from_face_name (f, Qborder, 1);
+       face = Qborder;
+       lface = lface_from_face_name (f, face, 1);
        LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
      }
    else if (EQ (param, Qcursor_color))
      {
-       lface = lface_from_face_name (f, Qcursor, 1);
+       face = Qcursor;
+       lface = lface_from_face_name (f, face, 1);
        LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
      }
    else if (EQ (param, Qmouse_color))
      {
-       lface = lface_from_face_name (f, Qmouse, 1);
+       face = Qmouse;
+       lface = lface_from_face_name (f, face, 1);
        LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
      }
+   /* Changing a named face means that all realized faces depending on
+      that face are invalid.  Since we cannot tell which realized faces
+      depend on the face, make sure they are all removed.  This is done
+      by incrementing face_change_count.  The next call to
+      init_iterator will then free realized faces.  */
+   if (!NILP (face)
+       && NILP (Fget (face, Qface_no_inherit)))
+     {
+       ++face_change_count;
+       ++windows_or_buffers_changed;
+     }
  }
  
  
@@@ -4867,8 -4801,6 +4888,8 @@@ frames).  If FRAME is omitted or nil, u
      value = LFACE_INHERIT (lface);
    else if (EQ (keyword, QCfont))
      value = LFACE_FONT (lface);
 +  else if (EQ (keyword, QCfontset))
 +    value = LFACE_FONTSET (lface);
    else
      signal_error ("Invalid face attribute name", keyword);
  
@@@ -4965,18 -4897,15 +4986,18 @@@ Default face attributes override any lo
     return fonts with the same size as the font of a face.  This is
     done in fontset.el.  */
  
 -DEFUN ("face-font", Fface_font, Sface_font, 1, 2, 0,
 +DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
         doc: /* Return the font name of face FACE, or nil if it is unspecified.
 +The font name is, by default, for ASCII characters.
  If the optional argument FRAME is given, report on face FACE in that frame.
  If FRAME is t, report on the defaults for face FACE (for new frames).
    The font default for a face is either nil, or a list
    of the form (bold), (italic) or (bold italic).
 -If FRAME is omitted or nil, use the selected frame.  */)
 -     (face, frame)
 -     Lisp_Object face, frame;
 +If FRAME is omitted or nil, use the selected frame.  And, in this case,
 +if the optional third argument CHARACTER is given,
 +return the font name used for CHARACTER.  */)
 +     (face, frame, character)
 +     Lisp_Object face, frame, character;
  {
    if (EQ (frame, Qt))
      {
    else
      {
        struct frame *f = frame_or_selected_frame (frame, 1);
 -      int face_id = lookup_named_face (f, face, 0);
 +      int face_id = lookup_named_face (f, face);
        struct face *face = FACE_FROM_ID (f, face_id);
 -      return face ? build_string (face->font_name) : Qnil;
 +
 +      if (! face)
 +      return Qnil;
 +#ifdef HAVE_WINDOW_SYSTEM
 +      if (FRAME_WINDOW_P (f) && !NILP (character))
 +      {
 +        CHECK_CHARACTER (character);
 +        face_id = FACE_FOR_CHAR (f, face, XINT (character), -1, Qnil);
 +        face = FACE_FROM_ID (f, face_id);
 +        return (face->font && face->font_name
 +                ? build_string (face->font_name)
 +                : Qnil);
 +      }
 +#endif
 +      return build_string (face->font_name);
      }
  }
  
@@@ -5078,8 -4993,18 +5099,8 @@@ If FRAME is omitted or nil, use the sel
       Lisp_Object face1, face2, frame;
  {
    int equal_p;
 -  struct frame *f;
    Lisp_Object lface1, lface2;
  
 -  if (EQ (frame, Qt))
 -    f = NULL;
 -  else
 -    /* Don't use check_x_frame here because this function is called
 -       before X frames exist.  At that time, if FRAME is nil,
 -       selected_frame will be used which is the frame dumped with
 -       Emacs.  That frame is not an X frame.  */
 -    f = frame_or_selected_frame (frame, 2);
 -
    lface1 = lface_from_face_name (NULL, face1, 1);
    lface2 = lface_from_face_name (NULL, face2, 1);
    equal_p = lface_equal_p (XVECTOR (lface1)->contents,
@@@ -5165,8 -5090,8 +5186,8 @@@ lface_hash (v
  
  /* Return non-zero if LFACE1 and LFACE2 specify the same font (without
     considering charsets/registries).  They do if they specify the same
 -   family, point size, weight, width, slant, and fontset.  Both LFACE1
 -   and LFACE2 must be fully-specified.  */
 +   family, point size, weight, width, slant, font, and fontset.  Both
 +   LFACE1 and LFACE2 must be fully-specified.  */
  
  static INLINE int
  lface_same_font_attributes_p (lface1, lface2)
          && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
              || (STRINGP (lface1[LFACE_FONT_INDEX])
                  && STRINGP (lface2[LFACE_FONT_INDEX])
 -                && xstricmp (SDATA (lface1[LFACE_FONT_INDEX]),
 -                             SDATA (lface2[LFACE_FONT_INDEX])))));
 +                && ! xstricmp (SDATA (lface1[LFACE_FONT_INDEX]),
 +                               SDATA (lface2[LFACE_FONT_INDEX]))))
 +        && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
 +            || (STRINGP (lface1[LFACE_FONTSET_INDEX])
 +                && STRINGP (lface2[LFACE_FONTSET_INDEX])
 +                && ! xstricmp (SDATA (lface1[LFACE_FONTSET_INDEX]),
 +                               SDATA (lface2[LFACE_FONTSET_INDEX]))))
 +        );
  }
  
  
@@@ -5218,7 -5137,7 +5239,7 @@@ make_realized_face (attr
  /* Free realized face FACE, including its X resources.  FACE may
     be null.  */
  
 -static void
 +void
  free_realized_face (f, face)
       struct frame *f;
       struct face *face;
@@@ -5453,10 -5372,11 +5474,10 @@@ free_realized_faces (c
  }
  
  
 -/* Free all faces realized for multibyte characters on frame F that
 -   has FONTSET.  */
 +/* Free all realized faces that are using FONTSET on frame F.  */
  
  void
 -free_realized_multibyte_face (f, fontset)
 +free_realized_faces_for_fontset (f, fontset)
       struct frame *f;
       int fontset;
  {
      {
        face = cache->faces_by_id[i];
        if (face
 -        && face != face->ascii_face
          && face->fontset == fontset)
        {
          uncache_face (cache, face);
@@@ -5530,11 -5451,10 +5551,11 @@@ free_face_cache (c
  
  
  /* Cache realized face FACE in face cache C.  HASH is the hash value
 -   of FACE.  If FACE->fontset >= 0, add the new face to the end of the
 -   collision list of the face hash table of C.  This is done because
 -   otherwise lookup_face would find FACE for every character, even if
 -   faces with the same attributes but for specific characters exist.  */
 +   of FACE.  If FACE is for ASCII characters (i.e. FACE->ascii_face ==
 +   FACE), insert the new face to the beginning of the collision list
 +   of the face hash table of C.  Otherwise, add the new face to the
 +   end of the collision list.  This way, lookup_face can quickly find
 +   that a requested face is not cached.  */
  
  static void
  cache_face (c, face, hash)
  
    face->hash = hash;
  
 -  if (face->fontset >= 0)
 +  if (face->ascii_face != face)
      {
        struct face *last = c->buckets[i];
        if (last)
@@@ -5638,14 -5558,17 +5659,14 @@@ uncache_face (c, face
  
  
  /* Look up a realized face with face attributes ATTR in the face cache
 -   of frame F.  The face will be used to display character C.  Value
 -   is the ID of the face found.  If no suitable face is found, realize
 -   a new one.  In that case, if C is a multibyte character, BASE_FACE
 -   is a face that has the same attributes.  */
 +   of frame F.  The face will be used to display ASCII characters.
 +   Value is the ID of the face found.  If no suitable face is found,
 +   realize a new one.  */
  
  INLINE int
 -lookup_face (f, attr, c, base_face)
 +lookup_face (f, attr)
       struct frame *f;
       Lisp_Object *attr;
 -     int c;
 -     struct face *base_face;
  {
    struct face_cache *cache = FRAME_FACE_CACHE (f);
    unsigned hash;
    i = hash % FACE_CACHE_BUCKETS_SIZE;
  
    for (face = cache->buckets[i]; face; face = face->next)
 -    if (face->hash == hash
 -      && (!FRAME_WINDOW_P (f)
 -          || FACE_SUITABLE_FOR_CHAR_P (face, c))
 -      && lface_equal_p (face->lface, attr))
 -      break;
 +    {
 +      if (face->ascii_face != face)
 +      {
 +        /* There's no more ASCII face.  */
 +        face = NULL;
 +        break;
 +      }
 +      if (face->hash == hash
 +        && lface_equal_p (face->lface, attr))
 +      break;
 +    }
  
    /* If not found, realize a new face.  */
    if (face == NULL)
 -    face = realize_face (cache, attr, c, base_face, -1);
 +    face = realize_face (cache, attr, -1);
  
  #if GLYPH_DEBUG
    xassert (face == FACE_FROM_ID (f, face->id));
 -
 -/* When this function is called from face_for_char (in this case, C is
 -   a multibyte character), a fontset of a face returned by
 -   realize_face is not yet set, i.e. FACE_SUITABLE_FOR_CHAR_P (FACE,
 -   C) is not sutisfied.  The fontset is set for this face by
 -   face_for_char later.  */
 -#if 0
 -  if (FRAME_WINDOW_P (f))
 -    xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
 -#endif
  #endif /* GLYPH_DEBUG */
  
    return face->id;
  }
  
 +#ifdef HAVE_WINDOW_SYSTEM
 +/* Look up a realized face that has the same attributes as BASE_FACE
 +   except for the font in the face cache of frame F.  If FONT_ID is
 +   not negative, it is an ID number of an already opened font that is
 +   used by the face.  If FONT_ID is negative, the face has no font.
 +   Value is the ID of the face found.  If no suitable face is found,
 +   realize a new one.  */
 +
 +int
 +lookup_non_ascii_face (f, font_id, base_face)
 +     struct frame *f;
 +     int font_id;
 +     struct face *base_face;
 +{
 +  struct face_cache *cache = FRAME_FACE_CACHE (f);
 +  unsigned hash;
 +  int i;
 +  struct face *face;
 +
 +  xassert (cache != NULL);
 +  base_face = base_face->ascii_face;
 +  hash = lface_hash (base_face->lface);
 +  i = hash % FACE_CACHE_BUCKETS_SIZE;
 +
 +  for (face = cache->buckets[i]; face; face = face->next)
 +    {
 +      if (face->ascii_face == face)
 +      continue;
 +      if (face->ascii_face == base_face
 +        && face->font_info_id == font_id)
 +      break;
 +    }
 +
 +  /* If not found, realize a new face.  */
 +  if (face == NULL)
 +    face = realize_non_ascii_face (f, font_id, base_face);
 +
 +#if GLYPH_DEBUG
 +  xassert (face == FACE_FROM_ID (f, face->id));
 +#endif /* GLYPH_DEBUG */
 +
 +  return face->id;
 +}
 +#endif        /* HAVE_WINDOW_SYSTEM */
  
  /* Return the face id of the realized face for named face SYMBOL on
 -   frame F suitable for displaying character C.  Value is -1 if the
 -   face couldn't be determined, which might happen if the default face
 -   isn't realized and cannot be realized.  */
 +   frame F suitable for displaying ASCII characters.  Value is -1 if
 +   the face couldn't be determined, which might happen if the default
 +   face isn't realized and cannot be realized.  */
  
  int
 -lookup_named_face (f, symbol, c)
 +lookup_named_face (f, symbol)
       struct frame *f;
       Lisp_Object symbol;
 -     int c;
  {
    Lisp_Object attrs[LFACE_VECTOR_SIZE];
    Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, 0);
  
 -  return lookup_face (f, attrs, c, NULL);
 +  return lookup_face (f, attrs);
  }
  
  
@@@ -5770,7 -5654,7 +5791,7 @@@ ascii_face_of_lisp_face (f, lface_id
    if (lface_id >= 0 && lface_id < lface_id_to_name_size)
      {
        Lisp_Object face_name = lface_id_to_name[lface_id];
 -      face_id = lookup_named_face (f, face_name, 0);
 +      face_id = lookup_named_face (f, face_name);
      }
    else
      face_id = -1;
@@@ -5818,7 -5702,7 +5839,7 @@@ smaller_face (f, face_id, steps
        /* Look up a face for a slightly smaller/larger font.  */
        pt += delta;
        attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
 -      new_face_id = lookup_face (f, attrs, 0, NULL);
 +      new_face_id = lookup_face (f, attrs);
        new_face = FACE_FROM_ID (f, new_face_id);
  
        /* If height changes, count that as one step.  */
@@@ -5861,7 -5745,7 +5882,7 @@@ face_with_height (f, face_id, height
    face = FACE_FROM_ID (f, face_id);
    bcopy (face->lface, attrs, sizeof attrs);
    attrs[LFACE_HEIGHT_INDEX] = make_number (height);
 -  face_id = lookup_face (f, attrs, 0, NULL);
 +  face_id = lookup_face (f, attrs);
  #endif /* HAVE_WINDOW_SYSTEM */
  
    return face_id;
  
  
  /* Return the face id of the realized face for named face SYMBOL on
 -   frame F suitable for displaying character C, and use attributes of
 -   the face FACE_ID for attributes that aren't completely specified by
 -   SYMBOL.  This is like lookup_named_face, except that the default
 -   attributes come from FACE_ID, not from the default face.  FACE_ID
 -   is assumed to be already realized.  */
 +   frame F suitable for displaying ASCII characters, and use
 +   attributes of the face FACE_ID for attributes that aren't
 +   completely specified by SYMBOL.  This is like lookup_named_face,
 +   except that the default attributes come from FACE_ID, not from the
 +   default face.  FACE_ID is assumed to be already realized.  */
  
  int
 -lookup_derived_face (f, symbol, c, face_id)
 +lookup_derived_face (f, symbol, face_id)
       struct frame *f;
       Lisp_Object symbol;
 -     int c;
       int face_id;
  {
    Lisp_Object attrs[LFACE_VECTOR_SIZE];
    get_lface_attributes (f, symbol, symbol_attrs, 1);
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, 0);
 -  return lookup_face (f, attrs, c, default_face);
 +  return lookup_face (f, attrs);
  }
  
  DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
@@@ -5978,7 -5863,6 +5999,7 @@@ x_supports_face_attributes_p (f, attrs
        || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
        || !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]))
      {
 +      int face_id;
        struct face *face;
        Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
  
  
        merge_face_vectors (f, attrs, merged_attrs, 0);
  
 -      face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0));
 +      face_id = lookup_face (f, merged_attrs);
 +      face = FACE_FROM_ID (f, face_id);
  
        if (! face)
        error ("cannot make face");
@@@ -6267,7 -6150,7 +6288,7 @@@ face for italic. */
                            Font selection
   ***********************************************************************/
  
 -DEFUN ("internal-set-font-selection-order",
 + DEFUN ("internal-set-font-selection-order",
         Finternal_set_font_selection_order,
         Sinternal_set_font_selection_order, 1, 1, 0,
         doc: /* Set font selection order for face font selection to ORDER.
@@@ -6507,12 -6390,6 +6528,12 @@@ build_scalable_font_name (f, font, spec
    double resy = FRAME_X_DISPLAY_INFO (f)->resy;
    double pt;
  
 +  if (font->numeric[XLFD_PIXEL_SIZE] != 0
 +      || font->numeric[XLFD_POINT_SIZE] != 0)
 +    /* This is a scalable font but is requested for a specific size.
 +       We should not change that size.  */
 +    return build_font_name (font);
 +
    /* If scalable font is for a specific resolution, compute
       the point size we must specify from the resolution of
       the display and the specified resolution of the font.  */
@@@ -6792,62 -6669,69 +6813,62 @@@ try_alternative_families (f, family, re
  
  /* Get a list of matching fonts on frame F.
  
 -   FAMILY, if a string, specifies a font family derived from the fontset.
 -   It is only used if the face does not specify any family in ATTRS or
 -   if we cannot find any font of the face's family.
 +   PATTERN, if a string, specifies a font name pattern to match while
 +   ignoring FAMILY and REGISTRY.
  
 -   REGISTRY, if a string, specifies a font registry and encoding to
 -   match.  A value of nil means include fonts of any registry and
 -   encoding.
 +   FAMILY, if a list, specifies a list of font families to try.
  
 -   If PREFER_FACE_FAMILY is nonzero, perfer face's family to FAMILY.
 -   Otherwise, prefer FAMILY.
 +   REGISTRY, if a list, specifies a list of font registries and
 +   encodinging to try.
  
     Return in *FONTS a pointer to a vector of font_name structures for
     the fonts matched.  Value is the number of fonts found.  */
  
  static int
 -try_font_list (f, attrs, family, registry, fonts, prefer_face_family)
 +try_font_list (f, pattern, family, registry, fonts)
       struct frame *f;
 -     Lisp_Object *attrs;
 -     Lisp_Object family, registry;
 +     Lisp_Object pattern, family, registry;
       struct font_name **fonts;
 -     int prefer_face_family;
  {
    int nfonts = 0;
 -  Lisp_Object face_family = attrs[LFACE_FAMILY_INDEX];
 -  Lisp_Object try_family;
 -
 -  try_family = (prefer_face_family || NILP (family)) ? face_family : family;
 -
 -  if (STRINGP (try_family))
 -    nfonts = try_alternative_families (f, try_family, registry, fonts);
  
 -#ifdef MAC_OS
 -  /* When realizing the default face and a font spec does not matched
 -     exactly, Emacs looks for ones with the same registry as the
 -     default font.  On the Mac, this is mac-roman, which does not work
 -     if the family is -etl-fixed, e.g.  The following widens the
 -     choices and fixes that problem.  */
 -  if (nfonts == 0 && STRINGP (try_family) && STRINGP (registry)
 -      && xstricmp (SDATA (registry), "mac-roman") == 0)
 -    nfonts = try_alternative_families (f, try_family, Qnil, fonts);
 -#endif
 +  if (STRINGP (pattern))
 +    {
 +      nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
 +      if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
 +      {
 +        int count = SPECPDL_INDEX ();
 +        specbind (Qscalable_fonts_allowed, Qt);
 +        nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
 +        unbind_to (count, Qnil);
 +      }
 +    }
 +  else
 +    {
 +      Lisp_Object tail;
  
 -  if (EQ (try_family, family))
 -    family = face_family;
 +      if (NILP (family))
 +      nfonts = font_list (f, Qnil, Qnil, registry, fonts);
 +      else
 +      for (tail = family; ! nfonts && CONSP (tail); tail = XCDR (tail))
 +        nfonts = try_alternative_families (f, XCAR (tail), registry, fonts);
  
 -  if (nfonts == 0 && STRINGP (family))
 -    nfonts = try_alternative_families (f, family, registry, fonts);
 +      /* Try font family of the default face or "fixed".  */
 +      if (nfonts == 0 && !NILP (family))
 +      {
 +        struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
 +        if (default_face)
 +          family = default_face->lface[LFACE_FAMILY_INDEX];
 +        else
 +          family = build_string ("fixed");
 +        nfonts = try_alternative_families (f, family, registry, fonts);
 +      }
  
 -  /* Try font family of the default face or "fixed".  */
 -  if (nfonts == 0)
 -    {
 -      struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
 -      if (default_face)
 -      family = default_face->lface[LFACE_FAMILY_INDEX];
 -      else
 -      family = build_string ("fixed");
 -      nfonts = font_list (f, Qnil, family, registry, fonts);
 +      /* Try any family with the given registry.  */
 +      if (nfonts == 0 && !NILP (family))
 +      nfonts = try_alternative_families (f, Qnil, registry, fonts);
      }
  
 -  /* Try any family with the given registry.  */
 -  if (nfonts == 0)
 -    nfonts = try_alternative_families (f, Qnil, registry, fonts);
 -
    return nfonts;
  }
  
@@@ -6862,108 -6746,63 +6883,108 @@@ face_fontset (attrs
  {
    Lisp_Object name;
  
 -  name = attrs[LFACE_FONT_INDEX];
 +  name = attrs[LFACE_FONTSET_INDEX];
    if (!STRINGP (name))
      return -1;
    return fs_query_fontset (name, 0);
  }
  
  
 -/* Choose a name of font to use on frame F to display character C with
 +/* Choose a name of font to use on frame F to display characters with
     Lisp face attributes specified by ATTRS.  The font name is
 -   determined by the font-related attributes in ATTRS and the name
 -   pattern for C in FONTSET.  Value is the font name which is
 -   allocated from the heap and must be freed by the caller, or NULL if
 -   we can get no information about the font name of C.  It is assured
 -   that we always get some information for a single byte
 -   character.
 +   determined by the font-related attributes in ATTRS and FONT-SPEC
 +   (if specified).
  
 -   If NEEDS_OVERSTRIKE is non-zero, a boolean is returned in it to
 -   indicate whether the resulting font should be drawn using overstrike
 -   to simulate bold-face.  */
 +   When we are choosing a font for ASCII characters, FONT-SPEC is
 +   always nil.  Otherwise FONT-SPEC is a list
 +      [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
 +   or a string specifying a font name pattern.
  
 -static char *
 -choose_face_font (f, attrs, fontset, c, needs_overstrike)
 +   If NEEDS_OVERSTRIKE is not NULL, a boolean is returned in it to
 +   indicate whether the resulting font should be drawn using
 +   overstrike to simulate bold-face.
 +
 +   Value is the font name which is allocated from the heap and must be
 +   freed by the caller.  */
 +
 +char *
 +choose_face_font (f, attrs, font_spec, needs_overstrike)
       struct frame *f;
       Lisp_Object *attrs;
 -     int fontset, c;
 +     Lisp_Object font_spec;
       int *needs_overstrike;
  {
 -  Lisp_Object pattern;
 +  Lisp_Object pattern, family, adstyle, registry;
    char *font_name = NULL;
    struct font_name *fonts;
 -  int nfonts, width_ratio;
 +  int nfonts;
  
    if (needs_overstrike)
      *needs_overstrike = 0;
  
 -  /* Get (foundry and) family name and registry (and encoding) name of
 -     a font for C.  */
 -  pattern = fontset_font_pattern (f, fontset, c);
 -  if (NILP (pattern))
 +  /* If we are choosing an ASCII font and a font name is explicitly
 +     specified in ATTRS, return it.  */
 +  if (NILP (font_spec) && STRINGP (attrs[LFACE_FONT_INDEX]))
 +    return xstrdup (SDATA (attrs[LFACE_FONT_INDEX]));
 +
 +  if (NILP (attrs[LFACE_FAMILY_INDEX]))
 +    family = Qnil;
 +  else
 +    family = Fcons (attrs[LFACE_FAMILY_INDEX], Qnil);
 +
 +  /* Decide FAMILY, ADSTYLE, and REGISTRY from FONT_SPEC.  But,
 +     ADSTYLE is not used in the font selector for the moment.  */
 +  if (VECTORP (font_spec))
      {
 -      xassert (!SINGLE_BYTE_CHAR_P (c));
 -      return NULL;
 +      pattern = Qnil;
 +      if (STRINGP (AREF (font_spec, FONT_SPEC_FAMILY_INDEX)))
 +      family = Fcons (AREF (font_spec, FONT_SPEC_FAMILY_INDEX), family);
 +      adstyle = AREF (font_spec, FONT_SPEC_ADSTYLE_INDEX);
 +      registry = Fcons (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX), Qnil);
 +    }
 +  else if (STRINGP (font_spec))
 +    {
 +      pattern = font_spec;
 +      family = Qnil;
 +      adstyle = Qnil;
 +      registry = Qnil;
 +    }
 +  else
 +    {
 +      /* We are choosing an ASCII font.  By default, use the registry
 +       name "iso8859-1".  But, if the registry name of the ASCII
 +       font specified in the fontset of ATTRS is not "iso8859-1"
 +       (e.g "iso10646-1"), use also that name with higher
 +       priority.  */
 +      int fontset = face_fontset (attrs);
 +      Lisp_Object ascii;
 +      int len;
 +      struct font_name font;
 +
 +      pattern = Qnil;
 +      adstyle = Qnil;
 +      registry = Fcons (build_string ("iso8859-1"), Qnil);
 +
 +      ascii = fontset_ascii (fontset);
 +      len = SBYTES (ascii);
 +      if (len < 9
 +        || strcmp (SDATA (ascii) + len - 9, "iso8859-1"))
 +      {
 +        font.name = LSTRDUPA (ascii);
 +        /* Check if the name is in XLFD.  */
 +        if (split_font_name (f, &font, 0))
 +          {
 +            font.fields[XLFD_ENCODING][-1] = '-';
 +            registry = Fcons (build_string (font.fields[XLFD_REGISTRY]),
 +                              registry);
 +          }
 +      }
      }
 -
 -  /* If what we got is a name pattern, return it.  */
 -  if (STRINGP (pattern))
 -    return xstrdup (SDATA (pattern));
  
    /* Get a list of fonts matching that pattern and choose the
       best match for the specified face attributes from it.  */
 -  nfonts = try_font_list (f, attrs, XCAR (pattern), XCDR (pattern), &fonts,
 -                        (SINGLE_BYTE_CHAR_P (c)
 -                         || CHAR_CHARSET (c) == charset_latin_iso8859_1));
 -  width_ratio = (SINGLE_BYTE_CHAR_P (c)
 -               ? 1
 -               : CHARSET_WIDTH (CHAR_CHARSET (c)));
 -  font_name = best_matching_font (f, attrs, fonts, nfonts, width_ratio,
 +  nfonts = try_font_list (f, pattern, family, registry, &fonts);
 +  font_name = best_matching_font (f, attrs, fonts, nfonts, NILP (font_spec),
                                  needs_overstrike);
    return font_name;
  }
@@@ -7125,7 -6964,7 +7146,7 @@@ realize_default_face (f
    xassert (lface_fully_specified_p (XVECTOR (lface)->contents));
    check_lface (lface);
    bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
 -  face = realize_face (c, attrs, 0, NULL, DEFAULT_FACE_ID);
 +  face = realize_face (c, attrs, DEFAULT_FACE_ID);
    return 1;
  }
  
@@@ -7164,19 -7003,23 +7185,19 @@@ realize_named_face (f, symbol, id
    merge_face_vectors (f, symbol_attrs, attrs, 0);
  
    /* Realize the face.  */
 -  new_face = realize_face (c, attrs, 0, NULL, id);
 +  new_face = realize_face (c, attrs, id);
  }
  
  
  /* Realize the fully-specified face with attributes ATTRS in face
 -   cache CACHE for character C.  If C is a multibyte character,
 -   BASE_FACE is a face that has the same attributes.  Otherwise,
 -   BASE_FACE is ignored.  If FORMER_FACE_ID is non-negative, it is an
 -   ID of face to remove before caching the new face.  Value is a
 -   pointer to the newly created realized face.  */
 +   cache CACHE for ASCII characters.  If FORMER_FACE_ID is
 +   non-negative, it is an ID of face to remove before caching the new
 +   face.  Value is a pointer to the newly created realized face.  */
  
  static struct face *
 -realize_face (cache, attrs, c, base_face, former_face_id)
 +realize_face (cache, attrs, former_face_id)
       struct face_cache *cache;
       Lisp_Object *attrs;
 -     int c;
 -     struct face *base_face;
       int former_face_id;
  {
    struct face *face;
      }
  
    if (FRAME_WINDOW_P (cache->f))
 -    face = realize_x_face (cache, attrs, c, base_face);
 +    face = realize_x_face (cache, attrs);
    else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
 -    face = realize_tty_face (cache, attrs, c);
 +    face = realize_tty_face (cache, attrs);
    else
      abort ();
  
    /* Insert the new face.  */
    cache_face (cache, face, lface_hash (attrs));
 +  return face;
 +}
 +
 +
  #ifdef HAVE_WINDOW_SYSTEM
 -  if (FRAME_WINDOW_P (cache->f) && face->font == NULL)
 -    load_face_font (cache->f, face, c);
 -#endif  /* HAVE_WINDOW_SYSTEM */
 +/* Realize the fully-specified face that has the same attributes as
 +   BASE_FACE except for the font on frame F.  If FONT_ID is not
 +   negative, it is an ID number of an already opened font that should
 +   be used by the face.  If FONT_ID is negative, the face has no font,
 +   i.e., characters are displayed by empty boxes.  */
 +
 +static struct face *
 +realize_non_ascii_face (f, font_id, base_face)
 +     struct frame *f;
 +     int font_id;
 +     struct face *base_face;
 +{
 +  struct face_cache *cache = FRAME_FACE_CACHE (f);
 +  struct face *face;
 +  struct font_info *font_info;
 +
 +  face = (struct face *) xmalloc (sizeof *face);
 +  *face = *base_face;
 +  face->gc = 0;
 +
 +  /* Don't try to free the colors copied bitwise from BASE_FACE.  */
 +  face->colors_copied_bitwise_p = 1;
 +
 +  face->font_info_id = font_id;
 +  if (font_id >= 0)
 +    {
 +      font_info = FONT_INFO_FROM_ID (f, font_id);
 +      face->font = font_info->font;
 +      face->font_name = font_info->full_name;
 +    }
 +  else
 +    {
 +      face->font = NULL;
 +      face->font_name = NULL;
 +    }
 +
 +  face->gc = 0;
 +
 +  cache_face (cache, face, face->hash);
 +
    return face;
  }
 +#endif        /* HAVE_WINDOW_SYSTEM */
  
  
  /* Realize the fully-specified face with attributes ATTRS in face
 -   cache CACHE for character C.  Do it for X frame CACHE->f.  If C is
 -   a multibyte character, BASE_FACE is a face that has the same
 -   attributes.  Otherwise, BASE_FACE is ignored.  If the new face
 -   doesn't share font with the default face, a fontname is allocated
 -   from the heap and set in `font_name' of the new face, but it is not
 -   yet loaded here.  Value is a pointer to the newly created realized
 -   face.  */
 +   cache CACHE for ASCII characters.  Do it for X frame CACHE->f.  If
 +   the new face doesn't share font with the default face, a fontname
 +   is allocated from the heap and set in `font_name' of the new face,
 +   but it is not yet loaded here.  Value is a pointer to the newly
 +   created realized face.  */
  
  static struct face *
 -realize_x_face (cache, attrs, c, base_face)
 +realize_x_face (cache, attrs)
       struct face_cache *cache;
       Lisp_Object *attrs;
 -     int c;
 -     struct face *base_face;
  {
  #ifdef HAVE_WINDOW_SYSTEM
    struct face *face, *default_face;
    Lisp_Object stipple, overline, strike_through, box;
  
    xassert (FRAME_WINDOW_P (cache->f));
 -  xassert (SINGLE_BYTE_CHAR_P (c)
 -         || base_face);
  
    /* Allocate a new realized face.  */
    face = make_realized_face (attrs);
 +  face->ascii_face = face;
  
    f = cache->f;
  
 -  /* If C is a multibyte character, we share all face attirbutes with
 -     BASE_FACE including the realized fontset.  But, we must load a
 -     different font.  */
 -  if (!SINGLE_BYTE_CHAR_P (c))
 -    {
 -      bcopy (base_face, face, sizeof *face);
 -      face->gc = 0;
 -
 -      /* Don't try to free the colors copied bitwise from BASE_FACE.  */
 -      face->colors_copied_bitwise_p = 1;
 -
 -      /* to force realize_face to load font */
 -      face->font = NULL;
 -      return face;
 -    }
 -
 -  /* Now we are realizing a face for ASCII (and unibyte) characters.  */
 -
    /* Determine the font to use.  Most of the time, the font will be
       the same as the font of the default face, so try that first.  */
    default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
    if (default_face
 -      && FACE_SUITABLE_FOR_CHAR_P (default_face, c)
        && lface_same_font_attributes_p (default_face->lface, attrs))
      {
        face->font = default_face->font;
 -      face->fontset = default_face->fontset;
        face->font_info_id = default_face->font_info_id;
        face->font_name = default_face->font_name;
 -      face->ascii_face = face;
 -
 -      /* But, as we can't share the fontset, make a new realized
 -       fontset that has the same base fontset as of the default
 -       face.  */
        face->fontset
 -      = make_fontset_for_ascii_face (f, default_face->fontset);
 +      = make_fontset_for_ascii_face (f, default_face->fontset, face);
      }
    else
      {
         are constructed from ATTRS.  */
        int fontset = face_fontset (attrs);
  
 -      if ((fontset == -1) && default_face)
 +      /* If we are realizing the default face, ATTRS should specify a
 +       fontset.  In other words, if FONTSET is -1, we are not
 +       realizing the default face, thus the default face should have
 +       already been realized.  */
 +      if (fontset == -1)
        fontset = default_face->fontset;
 -      face->fontset = make_fontset_for_ascii_face (f, fontset);
 -      face->font = NULL;      /* to force realize_face to load font */
 +      if (fontset == -1)
 +      abort ();
 +      load_face_font (f, face);
 +      face->fontset = make_fontset_for_ascii_face (f, fontset, face);
      }
  
    /* Load colors, and set remaining attributes.  */
    if (!NILP (stipple))
      face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
  
 -  xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
    return face;
  #endif /* HAVE_WINDOW_SYSTEM */
  }
@@@ -7532,13 -7358,14 +7553,13 @@@ map_tty_color (f, face, idx, defaulted
  
  
  /* Realize the fully-specified face with attributes ATTRS in face
 -   cache CACHE for character C.  Do it for TTY frame CACHE->f.  Value is a
 -   pointer to the newly created realized face.  */
 +   cache CACHE for ASCII characters.  Do it for TTY frame CACHE->f.
 +   Value is a pointer to the newly created realized face.  */
  
  static struct face *
 -realize_tty_face (cache, attrs, c)
 +realize_tty_face (cache, attrs)
       struct face_cache *cache;
       Lisp_Object *attrs;
 -     int c;
  {
    struct face *face;
    int weight, slant;
@@@ -7631,7 -7458,7 +7652,7 @@@ compute_char_face (f, ch, prop
    if (NILP (prop))
      {
        struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
 -      face_id = FACE_FOR_CHAR (f, face, ch);
 +      face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
      }
    else
      {
        struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
        bcopy (default_face->lface, attrs, sizeof attrs);
        merge_face_ref (f, prop, attrs, 1, 0);
 -      face_id = lookup_face (f, attrs, ch, NULL);
 +      face_id = lookup_face (f, attrs);
      }
  
    return face_id;
@@@ -7756,7 -7583,7 +7777,7 @@@ face_at_buffer_position (w, pos, region
  
    /* Look up a realized face with the given face attributes,
       or realize a new one for ASCII characters.  */
 -  return lookup_face (f, attrs, 0, NULL);
 +  return lookup_face (f, attrs);
  }
  
  
@@@ -7852,7 -7679,7 +7873,7 @@@ face_at_string_position (w, string, pos
  
    /* Look up a realized face with the given face attributes,
       or realize a new one for ASCII characters.  */
 -  return lookup_face (f, attrs, 0, NULL);
 +  return lookup_face (f, attrs);
  }
  
  
@@@ -7891,6 -7718,7 +7912,6 @@@ dump_realized_face (face
           face->underline_p,
           SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
    fprintf (stderr, "hash: %d\n", face->hash);
 -  fprintf (stderr, "charset: %d\n", face->charset);
  }
  
  
@@@ -7951,6 -7779,8 +7972,8 @@@ syms_of_xfaces (
  {
    Qface = intern ("face");
    staticpro (&Qface);
+   Qface_no_inherit = intern ("face-no-inherit");
+   staticpro (&Qface_no_inherit);
    Qbitmap_spec_p = intern ("bitmap-spec-p");
    staticpro (&Qbitmap_spec_p);
    Qframe_update_face_colors = intern ("frame-update-face-colors");
    staticpro (&QCwidth);
    QCfont = intern (":font");
    staticpro (&QCfont);
 +  QCfontset = intern (":fontset");
 +  staticpro (&QCfontset);
    QCbold = intern (":bold");
    staticpro (&QCbold);
    QCitalic = intern (":italic");