]> code.delx.au - gnu-emacs/commitdiff
Merge from emacs--devo--0
authorMiles Bader <miles@gnu.org>
Mon, 15 Oct 2007 05:03:21 +0000 (05:03 +0000)
committerMiles Bader <miles@gnu.org>
Mon, 15 Oct 2007 05:03:21 +0000 (05:03 +0000)
Patches applied:

 * emacs--devo--0  (patch 887-889)

   - Update from CVS
   - Merge from emacs--rel--22

 * emacs--rel--22  (patch 116-121)

   - Update from CVS

Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-268

28 files changed:
1  2 
lisp/ChangeLog
lisp/cus-start.el
lisp/faces.el
lisp/startup.el
lisp/textmodes/ispell.el
src/buffer.c
src/ccl.c
src/data.c
src/dispextern.h
src/dispnew.c
src/editfns.c
src/fontset.c
src/frame.c
src/intervals.c
src/keyboard.c
src/lisp.h
src/macfns.c
src/macterm.c
src/msdos.c
src/w32fns.c
src/w32menu.c
src/w32term.c
src/window.c
src/xdisp.c
src/xfaces.c
src/xfns.c
src/xmenu.c
src/xterm.c

diff --combined lisp/ChangeLog
index 3fe5e2994cfc0a3ffdd9ae98628a45a31bed8794,3a68b694a34b644e363852e26826d42d095cc38d..d3fde16c4fa346a57b71adf876b829d2d33a01e4
+ 2007-10-14  Drew Adams  <drew.adams@oracle.com>
+       * emacs-lisp/ring.el (ring-convert-sequence-to-ring)
+       (ring-insert+extend, ring-remove+insert+extend, ring-member)
+       (ring-next, ring-previous): New functions.
+ 2007-10-14  Richard Stallman  <rms@gnu.org>
+       * emacs-lisp/advice.el (documentation): Advice deleted.
+       Doc for advised functions is now handled at C level.
+       This is now handled at C level.
+       (ad-stop-advice, ad-start-advice): Don't enable or disable
+       advice for `documentation'.
+       (ad-advised-definition-docstring-regexp): Var deleted.
+       (ad-make-advised-definition-docstring): Store orig name
+       as text property of string.
+       (ad-advised-definition-p): Check for text property of docstring.
+       * help-fns.el (describe-function-1): Find source of advised functions.
+ 2007-10-14  Juri Linkov  <juri@jurta.org>
+       * faces.el (describe-face): Allow handling a string as the face name.
+       * textmodes/ispell.el (ispell-word): Call `ispell-region' on the
+       active region in transient-mark-mode.
+       (ispell-region): Change messages displayed at the start and end of
+       the spell-checking to be the same.
+       * startup.el (fancy-startup-tail): Say exactly what does the button
+       dismiss ("Dismiss this startup screen").  Use text "Never show
+       it again" for the checkbox after this button.
+       (fancy-startup-screen, fancy-about-screen): Put point before the
+       first link, so the user can quickly select links with the keyboard.
+       (normal-mouse-startup-screen): Add more useful text describing how
+       to follow a link.
+ 2007-10-14  Glenn Morris  <rgm@gnu.org>
+       * progmodes/etags.el (select-tags-table): Disable undo in the
+       `*Tags Table List*' buffer.
+ 2007-10-13  Eli Zaretskii  <eliz@gnu.org>
+       * dired.el (dired-warn-writable): New face.
+       (dired-warn-writable-face): New variable.
+       (dired-font-lock-keywords): Use dired-warn-writable-face, instead
+       of dired-warning-face, for group- and world-writable files.
+ 2007-10-13  Richard Stallman  <rms@gnu.org>
+       * files.el (directory-abbrev-alist): Doc fix.
+ 2007-10-13  Jari Aalto  <jari.aalto@cante.net>
+       * comint.el (comint-password-prompt-regexp): Add 'LDAP'.
+ 2007-10-12  Martin Rudalics  <rudalics@gmx.at>
+       * frame.el (set-frame-configuration): Assign name parameter only
+       if it has been set explicitly before.
+ 2007-10-11  Tom Tromey  <tromey@redhat.com>
+       * progmodes/gdb-ui.el (gdb-info-stack-custom): Ensure current
+       frame is visible.
+ 2007-10-10  Richard Stallman  <rms@gnu.org>
+       * emacs-lisp/debug.el (debugger-setup-buffer): Disable undo
+       in *Backtrace*.
+       * faces.el (face-font-selection-order): Doc fix.
+       * loadhist.el (unload-feature): Doc fix.
+ 2007-10-13  Glenn Morris  <rgm@gnu.org>
+       * progmodes/octave-mod.el (octave-looking-at-kw): Add doc string.
+       (octave-re-search-forward-kw, octave-re-search-backward-kw):
+       Add doc string, and an explicit COUNT argument.
+       (octave-scan-blocks, octave-beginning-of-defun): Explicitly pass
+       `inc' to search functions.
+       * faces.el (face-spec-set): When FRAME is nil, set the default for
+       new frames (restores pre-2007-09-17 behavior).  Doc fix.
+ 2007-10-13  John W. Eaton  <jwe@octave.org>
+       * progmodes/octave-mod.el (octave-looking-at-kw)
+       (octave-re-search-forward-kw, octave-re-search-backward-kw):
+       New functions.
+       (octave-in-defun-p, calculate-octave-indent)
+       (octave-blink-matching-block-open, octave-beginning-of-defun)
+       (octave-auto-fill): Use octave-looking-at-kw instead of looking-at,
+       to search for regexps that contain case-sensitive keywords.
+       (octave-beginning-of-defun): Likewise, for octave-re-search-backward-kw.
+       (octave-scan-blocks): Likewise, for octave-re-search-forward-kw.
+ 2007-10-13  Dan Nicolaescu  <dann@ics.uci.edu>
+       * frame.el (select-frame-set-input-focus): Fix typo
+       "max" -> "mac". Do not use a single clause cond.
+       * cus-start.el (all): Use test that does not match the X11 version
+       for mac.
+ 2007-10-13  Markus Gritsch  <m.gritsch@gmail.com>  (tiny change)
+       * progmodes/ebrowse.el (ebrowse-tree-mode): Disable undo in the
+       BROWSE buffer.
+ 2007-10-13  Dan Nicolaescu  <dann@ics.uci.edu>
+       * cus-start.el (all): Undo previous change.
  2007-10-13  Glenn Morris  <rgm@gnu.org>
  
        * woman.el (woman0-rename): Fix paren typo.
        (idlwave-sintern-keyword-list, idlwave-scan-user-lib-files)
        (idlwave-write-paths, idlwave-all-method-classes)
        (idlwave-all-method-keyword-classes, idlwave-entry-keywords)
-       (idlwave-fix-keywords, idlwave-display-calling-sequence):
+       (idlwave-fix-keywords, idlwave-display-calling-sequence)
+       (idlwave-complete-in-buffer):
        * textmodes/org.el (org-export-as-html, org-export-as-ascii)
-       (org-fast-tag-selection): Use mapc rather than mapcar.
+       (org-fast-tag-selection):
+       * textmodes/reftex-sel.el (reftex-select-item):  Use mapc rather
+       than mapcar.
  
  2007-10-13  Dan Nicolaescu  <dann@ics.uci.edu>
  
  
  2007-10-11  Eric S. Raymond  <esr@snark.thyrsus.com>
  
-       * vc.el (vc-diff, vc-diff-internal): Bug fixes by Juanma Barranquero.
-       Temporarily disable the check for his edge case, it's calling some
-       brittle code.
-       (with-vc-properties): Fievaluation time of a macro argument.
+       * vc.el (vc-diff):
+       (vc-diff-internal): Merge a patch by Juanma Barranquero.  Also,
+       emporarily disable the check for his edge case of
+       vc-diff (stopping it from grinding when callerd from $HOME), as
+       it's calling some brittle code in vc-hooks.el.
+       (with-vc-properties): Fix evaluation time of a macro argument.
        * ediff-vers.el (ediff-vc-internal):
        * vc-hooks.el:
        * loaddefs.el: Follow up on VC terminology change.
  
        * net/trampver.el: Update release number.
  
+ 2007-10-09  Richard Stallman  <rms@gnu.org>
+       * play/gamegrid.el (gamegrid-setup-default-font): Use face-spec-set.
  2007-10-09  Juanma Barranquero  <lekktu@gmail.com>
  
        * follow.el: Require easymenu.
        (suspend-tty-functions, resume-tty-functions): Install extra hooks
        for multi-tty.
  
 +2007-10-10  Vinicius Jose Latorre  <viniciusjl@ig.com.br>
 +
 +      * ps-print.el: Fix the usage of :foreground and :background face
 +      attributes.  Reported by Nikolaj Schumacher <n_schumacher@web.de>.
 +      (ps-print-version): New version 7.2.5.
 +      (ps-face-attributes, ps-face-attribute-list, ps-face-background): Fix
 +      code.
 +      (ps-face-foreground-color-p, ps-face-background-color-p)
 +      (ps-face-color-p): New inline funs.
 +      (ps-background, ps-begin-file, ps-build-reference-face-lists): Use
 +      `mapc' rather than `mapcar'.
 +
 +
  2007-08-29  Stefan Monnier  <monnier@iro.umontreal.ca>
  
        * simple.el (invisible-p): Remove: implemented in C now.
diff --combined lisp/cus-start.el
index 53245d902ae11cab21516f5f5a657885b268eaf5,6a66d8caa75f0e23788ce97a93ab4d90b01d48f1..c6b0f269d1bb6ba526276c17c0a2099884c11f6e
@@@ -106,9 -106,6 +106,9 @@@ Leaving \"Default\" unchecked is equiva
             (exec-path execute
                        (repeat (choice (const :tag "default directory" nil)
                                        (directory :format "%v"))))
 +           ;; charset.c
 +           (charset-map-path installation
 +                             (repeat (directory :format "%v")))
             ;; coding.c
             (inhibit-eol-conversion mule boolean)
             (eol-mnemonic-undecided mule string)
@@@ -436,7 -433,7 +436,7 @@@ since it could result in memory overflo
                      ((string-match "\\`w32-" (symbol-name symbol))
                       (eq system-type 'windows-nt))
                      ((string-match "\\`mac-" (symbol-name symbol))
-                      (eq window-system 'mac))
+                      (featurep 'mac-carbon))
                      ((string-match "\\`x-.*gtk" (symbol-name symbol))
                       (featurep 'gtk))
                      ((string-match "\\`x-" (symbol-name symbol))
diff --combined lisp/faces.el
index 55be1fad20e3859fa476b449677ca6a2ab84d0fe,e31622d9ba0eeb634829f073f5f8a0cf7e7146bd..8a0ba7d221f28e71b8ae3a754918155f1dd062f1
@@@ -48,8 -48,8 +48,8 @@@
    "*A list specifying how face font selection chooses fonts.
  Each of the four symbols `:width', `:height', `:weight', and `:slant'
  must appear once in the list, and the list must not contain any other
- elements.  Font selection tries to find a best matching font for
those face attributes first that appear first in the list.  For
+ elements.  Font selection first tries to find a best matching font
for those face attributes that appear before in the list.  For
  example, if `:slant' appears before `:height', font selection first
  tries to find a font with a suitable slant, even if this results in
  a font height that isn't optimal."
@@@ -81,11 -81,11 +81,11 @@@ ALTERNATIVE2 etc.
  (defcustom face-font-registry-alternatives
    (if (eq system-type 'windows-nt)
        '(("iso8859-1" "ms-oemlatin")
 -      ("gb2312.1980" "gb2312")
 +      ("gb2312.1980" "gb2312" "gbk" "gb18030")
        ("jisx0208.1990" "jisx0208.1983" "jisx0208.1978")
        ("ksc5601.1989" "ksx1001.1992" "ksc5601.1987")
        ("muletibetan-2" "muletibetan-0"))
 -    '(("gb2312.1980" "gb2312.80&gb8565.88" "gbk*")
 +    '(("gb2312.1980" "gb2312.80&gb8565.88" "gbk" "gb18030")
        ("jisx0208.1990" "jisx0208.1983" "jisx0208.1978")
        ("ksc5601.1989" "ksx1001.1992" "ksc5601.1987")
        ("muletibetan-2" "muletibetan-0")))
@@@ -103,76 -103,6 +103,76 @@@ REGISTRY, ALTERNATIVE1, ALTERNATIVE2, a
           (internal-set-alternative-font-registry-alist value)))
  
  
 +(defcustom font-weight-table
 +  (if (eq system-type 'windows-nt)
 +      '((thin . 100)
 +        (ultralight . 200) (ultra-light . 200) (extra-light . 200)
 +        (light . 300)
 +        (semilight . 330) (semi-light . 330)
 +        (book . 350)
 +        (normal . 400) (regular . 400)
 +        (medium . 500) 
 +        (semibold . 600) (semi-bold . 600) (demibold . 600) (demi . 600)
 +        (bold . 700)
 +        (extrabold . 800) (extra-bold . 800)
 +        (ultrabold . 800) (ultra-bold . 800)
 +        (black . 900) (heavy . 900))
 +    '((thin . 0)
 +      (ultralight . 40) (ultra-light . 40) (extra-light . 40)
 +      (light . 50)
 +      (semilight . 65) (semi-light . 65)
 +      (book . 75)
 +      (medium . 100) (regular . 100) (normal . 100)
 +      (semibold . 180) (semi-bold . 180) (demibold . 180) (demi . 180)
 +      (bold . 200)
 +      (extrabold . 205) (extra-bold . 205)
 +      (ultrabold . 205) (ultra-bold . 205)
 +      (black . 210) (heavy . 210)))
 +  "*Alist of font weight symbols vs the corresponding numeric values."
 +  :tag "Font weight table"
 +  :version "23.1"
 +  :group 'font-selection
 +  :type '(repeat (cons symbol integer))
 +  :set #'(lambda (symbol value)
 +         (set-default symbol value)
 +         (if (fboundp 'internal-set-font-style-table)
 +             (internal-set-font-style-table :weight value))))
 +
 +(defcustom font-slant-table
 +  '((ro . 0)
 +    (ri . 10)
 +    (r . 100) (roman . 100) (normal . 100)
 +    (i . 200) (italic . 200) (ot . 200)
 +    (o . 210) (oblique . 210))
 +  "*Alist of font slant symbols vs the corresponding numeric values."
 +  :tag "Font slant table"
 +  :version "23.1"
 +  :group 'font-selection
 +  :type '(repeat (cons symbol integer))
 +  :set #'(lambda (symbol value)
 +         (set-default symbol value)
 +         (if (fboundp 'internal-set-font-style-table)
 +             (internal-set-font-style-table :slant value))))
 +
 +(defcustom font-swidth-table
 +  '((ultracondensed . 50) (ultra-condensed . 50)
 +    (extracondensed . 63) (extra-condensed . 63)
 +    (condensed . 75) (compressed . 75) (narrow . 75)
 +    (semicondensed . 87) (semi-condensed . 87)
 +    (normal . 100) (medium . 100) (regular . 100)
 +    (semiexpanded . 113) (semi-expanded . 113) (demiexpanded . 113)
 +    (expanded . 125)
 +    (extraexpanded . 150) (extra-expanded . 150)
 +    (ultraexpanded . 200) (ultra-expanded . 200) (wide . 200))
 +  "*Alist of font swidth symbols vs the corresponding numeric values."
 +  :tag "Font swidth table"
 +  :version "23.1"
 +  :group 'font-selection
 +  :type '(repeat (cons symbol integer))
 +  :set #'(lambda (symbol value)
 +         (set-default symbol value)
 +         (if (fboundp 'internal-set-font-style-table)
 +             (internal-set-font-style-table :width value))))
  \f
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Creation, copying.
@@@ -1168,7 -1098,7 +1168,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)
@@@ -1342,8 -1272,7 +1342,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))))
        (save-excursion
        (set-buffer standard-output)
        (dolist (f face)
+         (if (stringp f) (setq f (intern f)))
          (insert "Face: " (symbol-name f))
          (if (not (facep f))
              (insert "   undefined face.\n")
@@@ -1515,17 -1445,16 +1516,16 @@@ If SPEC is nil, return nil.
  (defun face-spec-set (face spec &optional frame)
    "Set FACE's attributes according to the first matching entry in SPEC.
  FRAME is the frame whose frame-local face is set.  FRAME nil means
- do it on all frames.  See `defface' for information about SPEC.
- If SPEC is nil, do nothing."
-   (if frame
-       (let ((attrs (face-spec-choose spec frame)))
-       (when spec
-         (face-spec-reset-face face frame))
-       (while attrs
-         (let ((attribute (car attrs))
-               (value (car (cdr attrs))))
-           ;; Support some old-style attribute names and values.
-           (case attribute
+ do it on all frames (and change the default for new frames).
+ See `defface' for information about SPEC.  If SPEC is nil, do nothing."
+   (let ((attrs (face-spec-choose spec frame)))
+     (when spec
+       (face-spec-reset-face face (or frame t)))
+     (while attrs
+       (let ((attribute (car attrs))
+           (value (car (cdr attrs))))
+       ;; Support some old-style attribute names and values.
+       (case attribute
              (:bold (setq attribute :weight value (if value 'bold 'normal)))
              (:italic (setq attribute :slant value (if value 'italic 'normal)))
              ((:foreground :background)
               (if (null value) (setq value 'unspecified)))
              (t (unless (assq attribute face-x-resources)
                   (setq attribute nil))))
-           (when attribute
-             (set-face-attribute face frame attribute value)))
-         (setq attrs (cdr (cdr attrs)))))
+       (when attribute
+         ;; If frame is nil, set the default for new frames.
+         ;; Existing frames are handled below.
+         (set-face-attribute face (or frame t) attribute value)))
+       (setq attrs (cdr (cdr attrs)))))
+   (unless frame
      ;; When we reset the face based on its spec, then it is unmodified
      ;; as far as Custom is concerned.
      (put (or (get face 'face-alias) face) 'face-modified nil)
diff --combined lisp/startup.el
index d1e44bdad6b98c0eb0802d6f47c3b1d172fafaa9,e0b4c794687ee6b6fd9df94e44d8ed1ba2a1a151..ff0caaf43b4f065b15cdcea52aef868add09be46
@@@ -844,7 -844,6 +844,7 @@@ opening the first frame (e.g. open a co
    (custom-reevaluate-setting 'file-name-shadow-mode)
    (custom-reevaluate-setting 'send-mail-function)
    (custom-reevaluate-setting 'focus-follows-mouse)
 +  (custom-reevaluate-setting 'global-auto-composition-mode)
  
    (normal-erase-is-backspace-setup-frame)
  
@@@ -1452,14 -1451,15 +1452,15 @@@ a face or button specification.
      (when concise
        (fancy-splash-insert
         :face 'variable-pitch "\n"
-        :link '("Dismiss" (lambda (button)
-                          (when startup-screen-inhibit-startup-screen
-                            (customize-set-variable 'inhibit-startup-screen t)
-                            (customize-mark-to-save 'inhibit-startup-screen)
-                            (custom-save-all))
-                          (let ((w (get-buffer-window "*GNU Emacs*")))
-                            (and w (not (one-window-p)) (delete-window w)))
-                          (kill-buffer "*GNU Emacs*")))
+        :link '("Dismiss this startup screen"
+              (lambda (button)
+                (when startup-screen-inhibit-startup-screen
+                  (customize-set-variable 'inhibit-startup-screen t)
+                  (customize-mark-to-save 'inhibit-startup-screen)
+                  (custom-save-all))
+                (let ((w (get-buffer-window "*GNU Emacs*")))
+                  (and w (not (one-window-p)) (delete-window w)))
+                (kill-buffer "*GNU Emacs*")))
         "  ")
        (when (or user-init-file custom-file)
        (let ((checked (create-image "\300\300\141\143\067\076\034\030"
                       (overlay-put button 'display (overlay-get button :on-glyph))
                       (setq startup-screen-inhibit-startup-screen t)))))
        (fancy-splash-insert :face '(variable-pitch :height 0.9)
-                            " Don't show this message again.")))))
+                            " Never show it again.")))))
  
  (defun exit-splash-screen ()
    "Stop displaying the splash screen buffer."
  If CONCISE is non-nil, display a concise version of the
  splash screen in another window."
    (let ((splash-buffer (get-buffer-create "*GNU Emacs*")))
-     (with-current-buffer splash-buffer 
+     (with-current-buffer splash-buffer
        (let ((inhibit-read-only t))
        (erase-buffer)
        (make-local-variable 'startup-screen-inhibit-startup-screen)
        (set-buffer-modified-p nil)
        (if (and view-read-only (not view-mode))
          (view-mode-enter nil 'kill-buffer))
-       (goto-char (point-max)))
+       (goto-char (point-min))
+       (forward-line (if concise 2 4)))
      (if concise
        (progn
          (display-buffer splash-buffer)
        (setq tab-width 22)
        (message "%s" (startup-echo-area-message))
        (setq buffer-read-only t)
-       (goto-char (point-min)))))
+       (goto-char (point-min))
+       (forward-line 3))))
  
  (defun fancy-splash-frame ()
    "Return the frame to use for the fancy splash screen.
@@@ -1658,7 -1660,7 +1661,7 @@@ after Emacs starts.  If STARTUP is nil
    ;; The user can use the mouse to activate menus
    ;; so give help in terms of menu items.
    (insert "\
You can do basic editing with the menu bar and scroll bar using the mouse.
To follow a link, click Mouse-1 on it, or move to it and type RET.
  To quit a partially entered command, type Control-g.\n")
  
    (insert "\nImportant Help menu items:\n")
diff --combined lisp/textmodes/ispell.el
index bf1487f02e2f81b856f871116339300e386cc100,0e6605dc131d270ca63fbfc9e3c46f7fda6a6f66..253c29f408e874fb5c87577d8a0e79a8722e294a
@@@ -1197,7 -1197,28 +1197,7 @@@ Protects against bogus binding of `enab
        (decode-coding-string str (ispell-get-coding-system))
      str))
  
 -(put 'ispell-unified-chars-table 'char-table-extra-slots 0)
 -
 -;; Char-table that maps an Unicode character (charset:
 -;; latin-iso8859-1, mule-unicode-0100-24ff, mule-unicode-2500-34ff) to
 -;; a string in which all equivalent characters are listed.
 -
 -(defconst ispell-unified-chars-table
 -  (let ((table (make-char-table 'ispell-unified-chars-table)))
 -    (map-char-table
 -     #'(lambda (c v)
 -       (if (and v (/= c v))
 -           (let ((unified (or (aref table v) (string v))))
 -             (aset table v (concat unified (string c))))))
 -     ucs-mule-8859-to-mule-unicode)
 -    table))
 -
 -;; Return a string decoded from Nth element of the current dictionary
 -;; while splicing equivalent characters into the string.  This splicing
 -;; is done only if the string is a regular expression of the form
 -;; "[...]" because, otherwise, splicing will result in incorrect
 -;; regular expression matching.
 -
 +;; Return a string decoded from Nth element of the current dictionary.
  (defun ispell-get-decoded-string (n)
    (let* ((slot (or
                (assoc ispell-current-dictionary ispell-local-dictionary-alist)
      (when (and (> (length str) 0)
               (not (multibyte-string-p str)))
        (setq str (ispell-decode-string str))
 -      (if (and (= (aref str 0) ?\[)
 -             (eq (string-match "\\]" str) (1- (length str))))
 -        (setq str
 -              (string-as-multibyte
 -               (mapconcat
 -                #'(lambda (c)
 -                    (let ((unichar (aref ucs-mule-8859-to-mule-unicode c)))
 -                      (if unichar
 -                          (aref ispell-unified-chars-table unichar)
 -                        (string c))))
 -                str ""))))
 +      (or (multibyte-string-p str)
 +        (setq str (string-to-multibyte str)))
        (setcar (nthcdr n slot) str))
      str))
  
@@@ -1564,8 -1594,12 +1564,12 @@@ nil           word is correct or spelli
  quit          spell session exited."
  
    (interactive (list ispell-following-word ispell-quietly current-prefix-arg))
-   (if continue
-       (ispell-continue)
+   (cond
+    ((and transient-mark-mode mark-active
+        (not (eq (region-beginning) (region-end))))
+     (ispell-region (region-beginning) (region-end)))
+    (continue (ispell-continue))
+    (t
      (ispell-maybe-find-aspell-dictionaries)
      (ispell-accept-buffer-local-defs) ; use the correct dictionary
      (let ((cursor-location (point))   ; retain cursor location
        ;; NB: Cancels ispell-quit incorrectly if called from ispell-region
        (if ispell-quit (setq ispell-quit nil replace 'quit))
        (goto-char cursor-location)     ; return to original location
-       replace)))
+       replace))))
  
  
  (defun ispell-get-word (following &optional extra-otherchars)
@@@ -2653,7 -2687,7 +2657,7 @@@ Return nil if spell session is quit
        (rstart (make-marker)))
    (unwind-protect
        (save-excursion
-       (message "Spell checking %s using %s with %s dictionary..."
+       (message "Spell-checking %s using %s with %s dictionary..."
                 (if (and (= reg-start (point-min)) (= reg-end (point-max)))
                     (buffer-name) "region")
                 (file-name-nondirectory ispell-program-name)
        (if (not recheckp) (set-marker ispell-region-end nil))
        ;; Only save if successful exit.
        (ispell-pdict-save ispell-silently-savep)
-       (message "Spell-checking using %s with %s dictionary done"
+       (message "Spell-checking %s using %s with %s dictionary done"
+              (if (and (= reg-start (point-min)) (= reg-end (point-max)))
+                  (buffer-name) "region")
               (file-name-nondirectory ispell-program-name)
               (or ispell-current-dictionary "default"))))))
  
diff --combined src/buffer.c
index 237c549df8b9f5c790203fee03d8855e814b6f1e,740f9fe53d64dcfda065fe2c4129bbd44482a99e..d5f9541301d2168590cbc2239df44ae40f8b6587
@@@ -42,7 -42,7 +42,7 @@@ extern int errno
  #include "window.h"
  #include "commands.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "region-cache.h"
  #include "indent.h"
  #include "blockinput.h"
@@@ -184,7 -184,6 +184,7 @@@ static struct Lisp_Overlay * copy_overl
  static void modify_overlay P_ ((struct buffer *, EMACS_INT, EMACS_INT));
  static Lisp_Object buffer_lisp_local_variables P_ ((struct buffer *));
  
 +extern char * emacs_strerror P_ ((int));
  
  /* For debugging; temporary.  See set_buffer_internal.  */
  /* Lisp_Object Qlisp_mode, Vcheck_symbol; */
@@@ -569,6 -568,7 +569,7 @@@ CLONE nil means the indirect buffer's s
  
    b = (struct buffer *) allocate_buffer ();
    b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
+   XSETPVECTYPE (b, PVEC_BUFFER);
  
    if (XBUFFER (base_buffer)->base_buffer)
      b->base_buffer = XBUFFER (base_buffer)->base_buffer;
@@@ -2184,10 -2184,8 +2185,10 @@@ DEFUN ("set-buffer-multibyte", Fset_buf
         doc: /* Set the multibyte flag of the current buffer to FLAG.
  If FLAG is t, this makes the buffer a multibyte buffer.
  If FLAG is nil, this makes the buffer a single-byte buffer.
 -The buffer contents remain unchanged as a sequence of bytes
 -but the contents viewed as characters do change.
 +In these cases, the buffer contents remain unchanged as a sequence of
 +bytes but the contents viewed as characters do change.
 +If FLAG is `to', this makes the buffer a multibyte buffer by changing
 +all eight-bit bytes to eight-bit characters.
  If the multibyte flag was really changed, undo information of the
  current buffer is cleared.  */)
       (flag)
              p = GAP_END_ADDR;
              stop = Z;
            }
 -        if (MULTIBYTE_STR_AS_UNIBYTE_P (p, bytes))
 -          p += bytes, pos += bytes;
 -        else
 +        if (ASCII_BYTE_P (*p))
 +          p++, pos++;
 +        else if (CHAR_BYTE8_HEAD_P (*p))
            {
 -            c = STRING_CHAR (p, stop - pos);
 +            c = STRING_CHAR_AND_LENGTH (p, stop - pos, bytes);
              /* Delete all bytes for this 8-bit character but the
                 last one, and change the last one to the charcter
                 code.  */
                zv -= bytes;
              stop = Z;
            }
 +        else
 +          {
 +            bytes = BYTES_BY_CHAR_HEAD (*p);
 +            p += bytes, pos += bytes;
 +          }
        }
        if (narrowed)
        Fnarrow_to_region (make_number (begv), make_number (zv));
      {
        int pt = PT;
        int pos, stop;
 -      unsigned char *p;
 +      unsigned char *p, *pend;
  
        /* Be sure not to have a multibyte sequence striding over the GAP.
 -       Ex: We change this: "...abc\201 _GAP_ \241def..."
 -           to: "...abc _GAP_ \201\241def..."  */
 +       Ex: We change this: "...abc\302 _GAP_ \241def..."
 +           to: "...abc _GAP_ \302\241def..."  */
  
 -      if (GPT_BYTE > 1 && GPT_BYTE < Z_BYTE
 +      if (EQ (flag, Qt)
 +        && GPT_BYTE > 1 && GPT_BYTE < Z_BYTE
          && ! CHAR_HEAD_P (*(GAP_END_ADDR)))
        {
          unsigned char *p = GPT_ADDR - 1;
        pos = BEG;
        stop = GPT;
        p = BEG_ADDR;
 +      pend = GPT_ADDR;
        while (1)
        {
          int bytes;
              if (pos == Z)
                break;
              p = GAP_END_ADDR;
 +            pend = Z_ADDR;
              stop = Z;
            }
  
 -        if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes))
 +        if (ASCII_BYTE_P (*p))
 +          p++, pos++;
 +        else if (EQ (flag, Qt) && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
            p += bytes, pos += bytes;
          else
            {
              unsigned char tmp[MAX_MULTIBYTE_LENGTH];
 +            int c;
  
 -            bytes = CHAR_STRING (*p, tmp);
 +            c = BYTE8_TO_CHAR (*p);
 +            bytes = CHAR_STRING (c, tmp);
              *p = tmp[0];
              TEMP_SET_PT_BOTH (pos + 1, pos + 1);
              bytes--;
                zv += bytes;
              if (pos <= pt)
                pt += bytes;
 +            pend = Z_ADDR;
              stop = Z;
            }
        }
@@@ -2898,7 -2883,7 +2899,7 @@@ overlay_touches_p (pos
        int endpos;
  
        XSETMISC (overlay ,tail);
 -      if (!GC_OVERLAYP (overlay))
 +      if (!OVERLAYP (overlay))
        abort ();
  
        endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
        int startpos;
  
        XSETMISC (overlay, tail);
 -      if (!GC_OVERLAYP (overlay))
 +      if (!OVERLAYP (overlay))
        abort ();
  
        startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
@@@ -4233,15 -4218,8 +4234,8 @@@ add_overlay_mod_hooklist (functionlist
    int oldsize = XVECTOR (last_overlay_modification_hooks)->size;
  
    if (last_overlay_modification_hooks_used == oldsize)
-     {
-       Lisp_Object old;
-       old = last_overlay_modification_hooks;
-       last_overlay_modification_hooks
-       = Fmake_vector (make_number (oldsize * 2), Qnil);
-       bcopy (XVECTOR (old)->contents,
-            XVECTOR (last_overlay_modification_hooks)->contents,
-            sizeof (Lisp_Object) * oldsize);
-     }
+     last_overlay_modification_hooks = larger_vector 
+       (last_overlay_modification_hooks, oldsize * 2, Qnil);
    AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist;
    AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay;
  }
diff --combined src/ccl.c
index d51743c243ab5cc8b8ccdbabe03e57127fcae128,3ef342f455e6c724316990965ef8457892788f73..5e4a6632d1dd005811b8cb56c7431a589d3fc39c
+++ b/src/ccl.c
@@@ -5,9 -5,6 +5,9 @@@
       2005, 2006, 2007
       National Institute of Advanced Industrial Science and Technology (AIST)
       Registration Number H14PRO021
 +   Copyright (C) 2003
 +     National Institute of Advanced Industrial Science and Technology (AIST)
 +     Registration Number H13PRO009
  
  This file is part of GNU Emacs.
  
@@@ -31,13 -28,10 +31,13 @@@ Boston, MA 02110-1301, USA.  *
  #include <stdio.h>
  
  #include "lisp.h"
 +#include "character.h"
  #include "charset.h"
  #include "ccl.h"
  #include "coding.h"
  
 +Lisp_Object Qccl, Qcclp;
 +
  /* This contains all code conversion map available to CCL.  */
  Lisp_Object Vcode_conversion_map_vector;
  
@@@ -73,8 -67,6 +73,8 @@@ Lisp_Object Vtranslation_hash_table_vec
  #define GET_HASH_TABLE(id) \
    (XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)])))
  
 +extern int charset_unicode;
 +
  /* CCL (Code Conversion Language) is a simple language which has
     operations on one input buffer, one output buffer, and 7 registers.
     The syntax of CCL is described in `ccl.el'.  Emacs Lisp function
  #define CCL_WriteStringJump   0x0A /* Write string and jump:
                                        1:A--D--D--R--E--S--S-000XXXXX
                                        2:LENGTH
 -                                      3:0000STRIN[0]STRIN[1]STRIN[2]
 +                                      3:000MSTRIN[0]STRIN[1]STRIN[2]
                                        ...
                                        ------------------------------
 -                                      write_string (STRING, LENGTH);
 +                                      if (M)
 +                                        write_multibyte_string (STRING, LENGTH);
 +                                      else
 +                                        write_string (STRING, LENGTH);
                                        IC += ADDRESS;
                                        */
  
  
  #define CCL_WriteConstString  0x14 /* Write a constant or a string:
                                        1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
 -                                      [2:0000STRIN[0]STRIN[1]STRIN[2]]
 +                                      [2:000MSTRIN[0]STRIN[1]STRIN[2]]
                                        [...]
                                        -----------------------------
                                        if (!rrr)
                                          write (CC..C)
                                        else
 -                                        write_string (STRING, CC..C);
 +                                        if (M)
 +                                          write_multibyte_string (STRING, CC..C);
 +                                        else
 +                                          write_string (STRING, CC..C);
                                          IC += (CC..C + 2) / 3;
                                        */
  
@@@ -757,87 -743,136 +757,87 @@@ while(0
  
  /* Encode one character CH to multibyte form and write to the current
     output buffer.  If CH is less than 256, CH is written as is.  */
 -#define CCL_WRITE_CHAR(ch)                                            \
 -  do {                                                                        \
 -    int bytes = SINGLE_BYTE_CHAR_P (ch) ? 1: CHAR_BYTES (ch);         \
 -    if (!dst)                                                         \
 -      CCL_INVALID_CMD;                                                        \
 -    else if (dst + bytes + extra_bytes < (dst_bytes ? dst_end : src)) \
 -      {                                                                       \
 -      if (bytes == 1)                                                 \
 -        {                                                             \
 -          *dst++ = (ch);                                              \
 -          if (extra_bytes && (ch) >= 0x80 && (ch) < 0xA0)             \
 -            /* We may have to convert this eight-bit char to          \
 -               multibyte form later.  */                              \
 -            extra_bytes++;                                            \
 -        }                                                             \
 -      else if (CHAR_VALID_P (ch, 0))                                  \
 -        dst += CHAR_STRING (ch, dst);                                 \
 -      else                                                            \
 -        CCL_INVALID_CMD;                                              \
 -      }                                                                       \
 -    else                                                              \
 -      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST);                          \
 -  } while (0)
 -
 -/* Encode one character CH to multibyte form and write to the current
 -   output buffer.  The output bytes always forms a valid multibyte
 -   sequence.  */
 -#define CCL_WRITE_MULTIBYTE_CHAR(ch)                                  \
 -  do {                                                                        \
 -    int bytes = CHAR_BYTES (ch);                                      \
 -    if (!dst)                                                         \
 -      CCL_INVALID_CMD;                                                        \
 -    else if (dst + bytes + extra_bytes < (dst_bytes ? dst_end : src)) \
 -      {                                                                       \
 -      if (CHAR_VALID_P ((ch), 0))                                     \
 -        dst += CHAR_STRING ((ch), dst);                               \
 -      else                                                            \
 -        CCL_INVALID_CMD;                                              \
 -      }                                                                       \
 -    else                                                              \
 -      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST);                          \
 +#define CCL_WRITE_CHAR(ch)                    \
 +  do {                                                \
 +    if (! dst)                                        \
 +      CCL_INVALID_CMD;                                \
 +    else if (dst < dst_end)                   \
 +      *dst++ = (ch);                          \
 +    else                                      \
 +      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST);  \
    } while (0)
  
  /* Write a string at ccl_prog[IC] of length LEN to the current output
     buffer.  */
 -#define CCL_WRITE_STRING(len)                         \
 -  do {                                                        \
 -    if (!dst)                                         \
 -      CCL_INVALID_CMD;                                        \
 -    else if (dst + len <= (dst_bytes ? dst_end : src))        \
 -      for (i = 0; i < len; i++)                               \
 -      *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)]))   \
 -                >> ((2 - (i % 3)) * 8)) & 0xFF;       \
 -    else                                              \
 -      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST);          \
 -  } while (0)
 -
 -/* Read one byte from the current input buffer into REGth register.  */
 -#define CCL_READ_CHAR(REG)                            \
 -  do {                                                        \
 -    if (!src)                                         \
 -      CCL_INVALID_CMD;                                        \
 -    else if (src < src_end)                           \
 -      {                                                       \
 -      REG = *src++;                                   \
 -      if (REG == '\n'                                 \
 -          && ccl->eol_type != CODING_EOL_LF)          \
 -        {                                             \
 -          /* We are encoding.  */                     \
 -          if (ccl->eol_type == CODING_EOL_CRLF)       \
 -            {                                         \
 -              if (ccl->cr_consumed)                   \
 -                ccl->cr_consumed = 0;                 \
 -              else                                    \
 -                {                                     \
 -                  ccl->cr_consumed = 1;               \
 -                  REG = '\r';                         \
 -                  src--;                              \
 -                }                                     \
 -            }                                         \
 -          else                                        \
 -            REG = '\r';                               \
 -        }                                             \
 -      if (REG == LEADING_CODE_8_BIT_CONTROL           \
 -          && ccl->multibyte)                          \
 -        REG = *src++ - 0x20;                          \
 -      }                                                       \
 -    else if (ccl->last_block)                         \
 -      {                                                       \
 -      REG = -1;                                       \
 -        ic = eof_ic;                                  \
 -        goto ccl_repeat;                              \
 -      }                                                       \
 -    else                                              \
 -      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);          \
 -  } while (0)
 -
 -
 -/* Set C to the character code made from CHARSET and CODE.  This is
 -   like MAKE_CHAR but check the validity of CHARSET and CODE.  If they
 -   are not valid, set C to (CODE & 0xFF) because that is usually the
 -   case that CCL_ReadMultibyteChar2 read an invalid code and it set
 -   CODE to that invalid byte.  */
 -
 -#define CCL_MAKE_CHAR(charset, code, c)                               \
 +#define CCL_WRITE_STRING(len)                                 \
    do {                                                                \
 -    if (charset == CHARSET_ASCII)                             \
 -      c = code & 0xFF;                                                \
 -    else if (CHARSET_DEFINED_P (charset)                      \
 -           && (code & 0x7F) >= 32                             \
 -           && (code < 256 || ((code >> 7) & 0x7F) >= 32))     \
 +    int i;                                                    \
 +    if (!dst)                                                 \
 +      CCL_INVALID_CMD;                                                \
 +    else if (dst + len <= dst_end)                            \
        {                                                               \
 -      int c1 = code & 0x7F, c2 = 0;                           \
 -                                                              \
 -      if (code >= 256)                                        \
 -        c2 = c1, c1 = (code >> 7) & 0x7F;                     \
 -      c = MAKE_CHAR (charset, c1, c2);                        \
 +      if (XFASTINT (ccl_prog[ic]) & 0x1000000)                \
 +        for (i = 0; i < len; i++)                             \
 +          *dst++ = XFASTINT (ccl_prog[ic + i]) & 0xFFFFFF;    \
 +      else                                                    \
 +        for (i = 0; i < len; i++)                             \
 +          *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)]))       \
 +                    >> ((2 - (i % 3)) * 8)) & 0xFF;           \
        }                                                               \
      else                                                      \
 -      c = code & 0xFF;                                                \
 +      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST);                  \
    } while (0)
  
 +/* Read one byte from the current input buffer into Rth register.  */
 +#define CCL_READ_CHAR(r)                      \
 +  do {                                                \
 +    if (! src)                                        \
 +      CCL_INVALID_CMD;                                \
 +    else if (src < src_end)                   \
 +      r = *src++;                             \
 +    else if (ccl->last_block)                 \
 +      {                                               \
 +      r = -1;                                 \
 +      ic = ccl->eof_ic;                       \
 +      goto ccl_repeat;                        \
 +      }                                               \
 +    else                                      \
 +      CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);  \
 +    } while (0)
 +
 +/* Decode CODE by a charset whose id is ID.  If ID is 0, return CODE
 +   as is for backward compatibility.  Assume that we can use the
 +   variable `charset'.  */
 +
 +#define CCL_DECODE_CHAR(id, code)     \
 +  ((id) == 0 ? (code)                 \
 +   : (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code))))
 +
 +/* Encode character C by some of charsets in CHARSET_LIST.  Set ID to
 +   the id of the used charset, ENCODED to the resulf of encoding.
 +   Assume that we can use the variable `charset'.  */
 +
 +#define CCL_ENCODE_CHAR(c, charset_list, id, encoded)         \
 +  do {                                                                \
 +    unsigned code;                                            \
 +                                                              \
 +    charset = char_charset ((c), (charset_list), &code);      \
 +    if (! charset && ! NILP (charset_list))                   \
 +      charset = char_charset ((c), Qnil, &code);              \
 +    if (charset)                                              \
 +      {                                                               \
 +      (id) = CHARSET_ID (charset);                            \
 +      (encoded) = code;                                       \
 +      }                                                               \
 +   } while (0)
  
 -/* Execute CCL code on SRC_BYTES length text at SOURCE.  The resulting
 -   text goes to a place pointed by DESTINATION, the length of which
 -   should not exceed DST_BYTES.  The bytes actually processed is
 -   returned as *CONSUMED.  The return value is the length of the
 -   resulting text.  As a side effect, the contents of CCL registers
 -   are updated.  If SOURCE or DESTINATION is NULL, only operations on
 -   registers are permitted.  */
 +/* Execute CCL code on characters at SOURCE (length SRC_SIZE).  The
 +   resulting text goes to a place pointed by DESTINATION, the length
 +   of which should not exceed DST_SIZE.  As a side effect, how many
 +   characters are consumed and produced are recorded in CCL->consumed
 +   and CCL->produced, and the contents of CCL registers are updated.
 +   If SOURCE or DESTINATION is NULL, only operations on registers are
 +   permitted.  */
  
  #ifdef CCL_DEBUG
  #define CCL_DEBUG_BACKTRACE_LEN 256
@@@ -862,32 -897,36 +862,32 @@@ struct ccl_prog_stac
  /* For the moment, we only support depth 256 of stack.  */
  static struct ccl_prog_stack ccl_prog_stack_struct[256];
  
 -int
 -ccl_driver (ccl, source, destination, src_bytes, dst_bytes, consumed)
 +void
 +ccl_driver (ccl, source, destination, src_size, dst_size, charset_list)
       struct ccl_program *ccl;
 -     unsigned char *source, *destination;
 -     int src_bytes, dst_bytes;
 -     int *consumed;
 +     int *source, *destination;
 +     int src_size, dst_size;
 +     Lisp_Object charset_list;
  {
    register int *reg = ccl->reg;
    register int ic = ccl->ic;
    register int code = 0, field1, field2;
    register Lisp_Object *ccl_prog = ccl->prog;
 -  unsigned char *src = source, *src_end = src + src_bytes;
 -  unsigned char *dst = destination, *dst_end = dst + dst_bytes;
 +  int *src = source, *src_end = src + src_size;
 +  int *dst = destination, *dst_end = dst + dst_size;
    int jump_address;
    int i = 0, j, op;
    int stack_idx = ccl->stack_idx;
    /* Instruction counter of the current CCL code. */
    int this_ic = 0;
 -  /* CCL_WRITE_CHAR will produce 8-bit code of range 0x80..0x9F.  But,
 -     each of them will be converted to multibyte form of 2-byte
 -     sequence.  For that conversion, we remember how many more bytes
 -     we must keep in DESTINATION in this variable.  */
 -  int extra_bytes = ccl->eight_bit_control;
 +  struct charset *charset;
    int eof_ic = ccl->eof_ic;
    int eof_hit = 0;
  
    if (ic >= eof_ic)
      ic = CCL_HEADER_MAIN;
  
 -  if (ccl->buf_magnification == 0) /* We can't produce any bytes.  */
 +  if (ccl->buf_magnification == 0) /* We can't read/produce any bytes.  */
      dst = NULL;
  
    /* Set mapping stack pointer. */
          /* We can't just signal Qquit, instead break the loop as if
               the whole data is processed.  Don't reset Vquit_flag, it
               must be handled later at a safer place.  */
 -        if (consumed)
 -          src = source + src_bytes;
 +        if (src)
 +          src = source + src_size;
          ccl->status = CCL_STAT_QUIT;
          break;
        }
            case CCL_LE: reg[rrr] = i <= j; break;
            case CCL_GE: reg[rrr] = i >= j; break;
            case CCL_NE: reg[rrr] = i != j; break;
 -          case CCL_DECODE_SJIS: DECODE_SJIS (i, j, reg[rrr], reg[7]); break;
 -          case CCL_ENCODE_SJIS: ENCODE_SJIS (i, j, reg[rrr], reg[7]); break;
 +          case CCL_DECODE_SJIS:
 +            {
 +              i = (i << 8) | j;
 +              SJIS_TO_JIS (i);
 +              reg[rrr] = i >> 8;
 +              reg[7] = i & 0xFF;
 +              break;
 +            }
 +          case CCL_ENCODE_SJIS:
 +            {
 +              i = (i << 8) | j;
 +              JIS_TO_SJIS (i);
 +              reg[rrr] = i >> 8;
 +              reg[7] = i & 0xFF;
 +              break;
 +            }
            default: CCL_INVALID_CMD;
            }
          code &= 0x1F;
            case CCL_ReadMultibyteChar2:
              if (!src)
                CCL_INVALID_CMD;
 -
 -            if (src >= src_end)
 -              {
 -                src++;
 -                goto ccl_read_multibyte_character_suspend;
 -              }
 -
 -            if (!ccl->multibyte)
 -              {
 -                int bytes;
 -                if (!UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes))
 -                  {
 -                    reg[RRR] = CHARSET_8_BIT_CONTROL;
 -                    reg[rrr] = *src++;
 -                    break;
 -                  }
 -              }
 -            i = *src++;
 -            if (i == '\n' && ccl->eol_type != CODING_EOL_LF)
 -              {
 -                /* We are encoding.  */
 -                if (ccl->eol_type == CODING_EOL_CRLF)
 -                  {
 -                    if (ccl->cr_consumed)
 -                      ccl->cr_consumed = 0;
 -                    else
 -                      {
 -                        ccl->cr_consumed = 1;
 -                        i = '\r';
 -                        src--;
 -                      }
 -                  }
 -                else
 -                  i = '\r';
 -                reg[rrr] = i;
 -                reg[RRR] = CHARSET_ASCII;
 -              }
 -            else if (i < 0x80)
 -              {
 -                /* ASCII */
 -                reg[rrr] = i;
 -                reg[RRR] = CHARSET_ASCII;
 -              }
 -            else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION2)
 -              {
 -                int dimension = BYTES_BY_CHAR_HEAD (i) - 1;
 -
 -                if (dimension == 0)
 -                  {
 -                    /* `i' is a leading code for an undefined charset.  */
 -                    reg[RRR] = CHARSET_8_BIT_GRAPHIC;
 -                    reg[rrr] = i;
 -                  }
 -                else if (src + dimension > src_end)
 -                  goto ccl_read_multibyte_character_suspend;
 -                else
 -                  {
 -                    reg[RRR] = i;
 -                    i = (*src++ & 0x7F);
 -                    if (dimension == 1)
 -                      reg[rrr] = i;
 -                    else
 -                      reg[rrr] = ((i << 7) | (*src++ & 0x7F));
 -                  }
 -              }
 -            else if ((i == LEADING_CODE_PRIVATE_11)
 -                     || (i == LEADING_CODE_PRIVATE_12))
 -              {
 -                if ((src + 1) >= src_end)
 -                  goto ccl_read_multibyte_character_suspend;
 -                reg[RRR] = *src++;
 -                reg[rrr] = (*src++ & 0x7F);
 -              }
 -            else if ((i == LEADING_CODE_PRIVATE_21)
 -                     || (i == LEADING_CODE_PRIVATE_22))
 -              {
 -                if ((src + 2) >= src_end)
 -                  goto ccl_read_multibyte_character_suspend;
 -                reg[RRR] = *src++;
 -                i = (*src++ & 0x7F);
 -                reg[rrr] = ((i << 7) | (*src & 0x7F));
 -                src++;
 -              }
 -            else if (i == LEADING_CODE_8_BIT_CONTROL)
 -              {
 -                if (src >= src_end)
 -                  goto ccl_read_multibyte_character_suspend;
 -                reg[RRR] = CHARSET_8_BIT_CONTROL;
 -                reg[rrr] = (*src++ - 0x20);
 -              }
 -            else if (i >= 0xA0)
 -              {
 -                reg[RRR] = CHARSET_8_BIT_GRAPHIC;
 -                reg[rrr] = i;
 -              }
 -            else
 -              {
 -                /* INVALID CODE.  Return a single byte character.  */
 -                reg[RRR] = CHARSET_ASCII;
 -                reg[rrr] = i;
 -              }
 -            break;
 -
 -          ccl_read_multibyte_character_suspend:
 -            if (src <= src_end && !ccl->multibyte && ccl->last_block)
 -              {
 -                reg[RRR] = CHARSET_8_BIT_CONTROL;
 -                reg[rrr] = i;
 -                break;
 -              }
 -            src--;
 -            if (ccl->last_block)
 -              {
 -                ic = eof_ic;
 -                eof_hit = 1;
 -                goto ccl_repeat;
 -              }
 -            else
 -              CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);
 -
 +            CCL_READ_CHAR (i);
 +            CCL_ENCODE_CHAR (i, charset_list, reg[RRR], reg[rrr]);
              break;
  
            case CCL_WriteMultibyteChar2:
 -            i = reg[RRR]; /* charset */
 -            if (i == CHARSET_ASCII
 -                || i == CHARSET_8_BIT_CONTROL
 -                || i == CHARSET_8_BIT_GRAPHIC)
 -              i = reg[rrr] & 0xFF;
 -            else if (CHARSET_DIMENSION (i) == 1)
 -              i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
 -            else if (i < MIN_CHARSET_PRIVATE_DIMENSION2)
 -              i = ((i - 0x8F) << 14) | reg[rrr];
 -            else
 -              i = ((i - 0xE0) << 14) | reg[rrr];
 -
 -            CCL_WRITE_MULTIBYTE_CHAR (i);
 -
 +            if (! dst)
 +              CCL_INVALID_CMD;
 +            i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
 +            CCL_WRITE_CHAR (i);
              break;
  
            case CCL_TranslateCharacter:
 -            CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
 -            op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]),
 -                                 i, -1, 0, 0);
 -            SPLIT_CHAR (op, reg[RRR], i, j);
 -            if (j != -1)
 -              i = (i << 7) | j;
 -
 -            reg[rrr] = i;
 +            i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
 +            op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]), i);
 +            CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
              break;
  
            case CCL_TranslateCharacterConstTbl:
              op = XINT (ccl_prog[ic]); /* table */
              ic++;
 -            CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
 -            op = translate_char (GET_TRANSLATION_TABLE (op), i, -1, 0, 0);
 -            SPLIT_CHAR (op, reg[RRR], i, j);
 -            if (j != -1)
 -              i = (i << 7) | j;
 -
 -            reg[rrr] = i;
 +            i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
 +            op = translate_char (GET_TRANSLATION_TABLE (op), i);
 +            CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
              break;
  
            case CCL_LookupIntConstTbl:
                  {
                    Lisp_Object opl;
                    opl = HASH_VALUE (h, op);
 -                  if (!CHAR_VALID_P (XINT (opl), 0))
 +                  if (! CHARACTERP (opl))
                      CCL_INVALID_CMD;
 -                  SPLIT_CHAR (XINT (opl), reg[RRR], i, j);
 -                  if (j != -1)
 -                    i = (i << 7) | j;
 -                  reg[rrr] = i;
 +                  reg[RRR] = charset_unicode;
 +                  reg[rrr] = op;
                    reg[7] = 1; /* r7 true for success */
                  }
                else
            case CCL_LookupCharConstTbl:
              op = XINT (ccl_prog[ic]); /* table */
              ic++;
 -            CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
 +            i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
              {
                struct Lisp_Hash_Table *h = GET_HASH_TABLE (op);
  
        }
  
        msglen = strlen (msg);
 -      if (dst + msglen <= (dst_bytes ? dst_end : src))
 +      if (dst + msglen <= dst_end)
        {
 -        bcopy (msg, dst, msglen);
 -        dst += msglen;
 +        for (i = 0; i < msglen; i++)
 +          *dst++ = msg[i];
        }
  
        if (ccl->status == CCL_STAT_INVALID_CMD)
    ccl->ic = ic;
    ccl->stack_idx = stack_idx;
    ccl->prog = ccl_prog;
 -  ccl->eight_bit_control = (extra_bytes > 1);
 -  if (consumed)
 -    *consumed = src - source;
 -  return (dst ? dst - destination : 0);
 +  ccl->consumed = src - source;
 +  if (dst != NULL)
 +    ccl->produced = dst - destination;
 +  else
 +    ccl->produced = 0;
  }
  
  /* Resolve symbols in the specified CCL code (Lisp vector).  This
@@@ -1946,6 -2109,7 +1946,6 @@@ setup_ccl_program (ccl, ccl_prog
    ccl->private_state = 0;
    ccl->status = 0;
    ccl->stack_idx = 0;
 -  ccl->eol_type = CODING_EOL_LF;
    ccl->suppress_error = 0;
    ccl->eight_bit_control = 0;
    return 0;
@@@ -2033,7 -2197,7 +2033,7 @@@ programs.  */
                  ? XINT (AREF (reg, i))
                  : 0);
  
 -  ccl_driver (&ccl, (unsigned char *)0, (unsigned char *)0, 0, 0, (int *)0);
 +  ccl_driver (&ccl, NULL, NULL, 0, 0, Qnil);
    QUIT;
    if (ccl.status != CCL_STAT_SUCCESS)
      error ("Error in CCL program at %dth code", ccl.ic);
@@@ -2075,13 -2239,10 +2075,13 @@@ usage: (ccl-execute-on-string CCL-PROGR
  {
    Lisp_Object val;
    struct ccl_program ccl;
 -  int i, produced;
 +  int i;
    int outbufsize;
 -  char *outbuf;
 -  struct gcpro gcpro1, gcpro2;
 +  unsigned char *outbuf, *outp;
 +  int str_chars, str_bytes;
 +#define CCL_EXECUTE_BUF_SIZE 1024
 +  int source[CCL_EXECUTE_BUF_SIZE], destination[CCL_EXECUTE_BUF_SIZE];
 +  int consumed_chars, consumed_bytes, produced_chars;
  
    if (setup_ccl_program (&ccl, ccl_prog) < 0)
      error ("Invalid CCL program");
      error ("Length of vector STATUS is not 9");
    CHECK_STRING (str);
  
 -  GCPRO2 (status, str);
 +  str_chars = SCHARS (str);
 +  str_bytes = SBYTES (str);
  
    for (i = 0; i < 8; i++)
      {
        if (ccl.ic < i && i < ccl.size)
        ccl.ic = i;
      }
 -  outbufsize = SBYTES (str) * ccl.buf_magnification + 256;
 -  outbuf = (char *) xmalloc (outbufsize);
 -  ccl.last_block = NILP (contin);
 -  ccl.multibyte = STRING_MULTIBYTE (str);
 -  produced = ccl_driver (&ccl, SDATA (str), outbuf,
 -                       SBYTES (str), outbufsize, (int *) 0);
 +
 +  outbufsize = (ccl.buf_magnification
 +              ? str_bytes * ccl.buf_magnification + 256
 +              : str_bytes + 256);
 +  outp = outbuf = (unsigned char *) xmalloc (outbufsize);
 +
 +  consumed_chars = consumed_bytes = 0;
 +  produced_chars = 0;
 +  while (1)
 +    {
 +      const unsigned char *p = SDATA (str) + consumed_bytes;
 +      const unsigned char *endp = SDATA (str) + str_bytes;
 +      int i = 0;
 +      int *src, src_size;
 +
 +      if (endp - p == str_chars - consumed_chars)
 +      while (i < CCL_EXECUTE_BUF_SIZE && p < endp)
 +        source[i++] = *p++;
 +      else
 +      while (i < CCL_EXECUTE_BUF_SIZE && p < endp)
 +        source[i++] = STRING_CHAR_ADVANCE (p);
 +      consumed_chars += i;
 +      consumed_bytes = p - SDATA (str);
 +
 +      if (consumed_bytes == str_bytes)
 +      ccl.last_block = NILP (contin);
 +      src = source;
 +      src_size = i;
 +      while (1)
 +      {
 +        ccl_driver (&ccl, src, destination, src_size, CCL_EXECUTE_BUF_SIZE,
 +                    Qnil);
 +        produced_chars += ccl.produced;
 +        if (NILP (unibyte_p))
 +          {
 +            if (outp - outbuf + MAX_MULTIBYTE_LENGTH * ccl.produced
 +                > outbufsize)
 +              {
 +                int offset = outp - outbuf;
 +                outbufsize += MAX_MULTIBYTE_LENGTH * ccl.produced;
 +                outbuf = (unsigned char *) xrealloc (outbuf, outbufsize);
 +                outp = outbuf + offset;
 +              }
 +            for (i = 0; i < ccl.produced; i++)
 +              CHAR_STRING_ADVANCE (destination[i], outp);
 +          }
 +        else
 +          {
 +            if (outp - outbuf + ccl.produced > outbufsize)
 +              {
 +                int offset = outp - outbuf;
 +                outbufsize += ccl.produced;
 +                outbuf = (unsigned char *) xrealloc (outbuf, outbufsize);
 +                outp = outbuf + offset;
 +              }
 +            for (i = 0; i < ccl.produced; i++)
 +              *outp++ = destination[i];
 +          }
 +        src += ccl.consumed;
 +        src_size -= ccl.consumed;
 +        if (ccl.status != CCL_STAT_SUSPEND_BY_DST)
 +          break;
 +      }
 +
 +      if (ccl.status != CCL_STAT_SUSPEND_BY_SRC
 +        || str_chars == consumed_chars)
 +      break;
 +    }
 +
 +  if (ccl.status == CCL_STAT_INVALID_CMD)
 +    error ("Error in CCL program at %dth code", ccl.ic);
 +  if (ccl.status == CCL_STAT_QUIT)
 +    error ("CCL program interrupted at %dth code", ccl.ic);
 +
    for (i = 0; i < 8; i++)
      ASET (status, i, make_number (ccl.reg[i]));
    ASET (status, 8, make_number (ccl.ic));
 -  UNGCPRO;
  
    if (NILP (unibyte_p))
 -    {
 -      int nchars;
 -
 -      produced = str_as_multibyte (outbuf, outbufsize, produced, &nchars);
 -      val = make_multibyte_string (outbuf, nchars, produced);
 -    }
 +    val = make_multibyte_string ((char *) outbuf, produced_chars,
 +                               outp - outbuf);
    else
 -    val = make_unibyte_string (outbuf, produced);
 +    val = make_unibyte_string ((char *) outbuf, produced_chars);
    xfree (outbuf);
 -  QUIT;
 -  if (ccl.status == CCL_STAT_SUSPEND_BY_DST)
 -    error ("Output buffer for the CCL programs overflow");
 -  if (ccl.status != CCL_STAT_SUCCESS
 -      && ccl.status != CCL_STAT_SUSPEND_BY_SRC)
 -    error ("Error in CCL program at %dth code", ccl.ic);
  
    return val;
  }
@@@ -2245,16 -2348,8 +2245,8 @@@ Return index number of the registered C
      }
  
    if (idx == len)
-     {
-       /* Extend the table.  */
-       Lisp_Object new_table;
-       int j;
-       new_table = Fmake_vector (make_number (len * 2), Qnil);
-       for (j = 0; j < len; j++)
-       ASET (new_table, j, AREF (Vccl_program_table, j));
-       Vccl_program_table = new_table;
-     }
+     /* Extend the table.  */
+     Vccl_program_table = larger_vector (Vccl_program_table, len * 2, Qnil);
  
    {
      Lisp_Object elt;
@@@ -2313,15 -2408,8 +2305,8 @@@ Return index number of the registered m
      }
  
    if (i == len)
-     {
-       Lisp_Object new_vector = Fmake_vector (make_number (len * 2), Qnil);
-       int j;
-       for (j = 0; j < len; j++)
-       AREF (new_vector, j)
-         = AREF (Vcode_conversion_map_vector, j);
-       Vcode_conversion_map_vector = new_vector;
-     }
+     Vcode_conversion_map_vector = larger_vector (Vcode_conversion_map_vector,
+                                                len * 2, Qnil);
  
    index = make_number (i);
    Fput (symbol, Qcode_conversion_map, map);
@@@ -2337,12 -2425,6 +2322,12 @@@ syms_of_ccl (
    staticpro (&Vccl_program_table);
    Vccl_program_table = Fmake_vector (make_number (32), Qnil);
  
 +  Qccl = intern ("ccl");
 +  staticpro (&Qccl);
 +
 +  Qcclp = intern ("cclp");
 +  staticpro (&Qcclp);
 +
    Qccl_program = intern ("ccl-program");
    staticpro (&Qccl_program);
  
diff --combined src/data.c
index 6439686dcd9fe36fac0dd32a270445e590607d0b,c8c40aa6df0d8ba1e29b05db5d133e6256025b3f..81cffcb38deee72dda7f45700c203a549ac9a79b
@@@ -25,7 -25,7 +25,7 @@@ Boston, MA 02110-1301, USA.  *
  #include <stdio.h>
  #include "lisp.h"
  #include "puresize.h"
 -#include "charset.h"
 +#include "character.h"
  #include "buffer.h"
  #include "keyboard.h"
  #include "frame.h"
@@@ -116,7 -116,7 +116,7 @@@ wrong_type_argument (predicate, value
  {
    /* If VALUE is not even a valid Lisp object, abort here
       where we can get a backtrace showing where it came from.  */
 -  if ((unsigned int) XGCTYPE (value) >= Lisp_Type_Limit)
 +  if ((unsigned int) XTYPE (value) >= Lisp_Type_Limit)
      abort ();
  
    xsignal2 (Qwrong_type_argument, predicate, value);
@@@ -188,7 -188,7 +188,7 @@@ for example, (type-of 1) returns `integ
       (object)
       Lisp_Object object;
  {
 -  switch (XGCTYPE (object))
 +  switch (XTYPE (object))
      {
      case Lisp_Int:
        return Qinteger;
        abort ();
  
      case Lisp_Vectorlike:
 -      if (GC_WINDOW_CONFIGURATIONP (object))
 +      if (WINDOW_CONFIGURATIONP (object))
        return Qwindow_configuration;
 -      if (GC_PROCESSP (object))
 +      if (PROCESSP (object))
        return Qprocess;
 -      if (GC_WINDOWP (object))
 +      if (WINDOWP (object))
        return Qwindow;
 -      if (GC_SUBRP (object))
 +      if (SUBRP (object))
        return Qsubr;
 -      if (GC_COMPILEDP (object))
 +      if (COMPILEDP (object))
        return Qcompiled_function;
 -      if (GC_BUFFERP (object))
 +      if (BUFFERP (object))
        return Qbuffer;
 -      if (GC_CHAR_TABLE_P (object))
 +      if (CHAR_TABLE_P (object))
        return Qchar_table;
 -      if (GC_BOOL_VECTOR_P (object))
 +      if (BOOL_VECTOR_P (object))
        return Qbool_vector;
 -      if (GC_FRAMEP (object))
 +      if (FRAMEP (object))
        return Qframe;
 -      if (GC_HASH_TABLE_P (object))
 +      if (HASH_TABLE_P (object))
        return Qhash_table;
        return Qvector;
  
@@@ -436,11 -436,11 +436,11 @@@ DEFUN ("byte-code-function-p", Fbyte_co
  }
  
  DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
 -       doc: /* Return t if OBJECT is a character (an integer) or a string.  */)
 +       doc: /* Return t if OBJECT is a character or a string.  */)
       (object)
       register Lisp_Object object;
  {
 -  if (INTEGERP (object) || STRINGP (object))
 +  if (CHARACTERP (object) || STRINGP (object))
      return Qt;
    return Qnil;
  }
@@@ -663,12 -663,20 +663,20 @@@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0
       (symbol, definition)
       register Lisp_Object symbol, definition;
  {
+   register Lisp_Object function;
    CHECK_SYMBOL (symbol);
    if (NILP (symbol) || EQ (symbol, Qt))
      xsignal1 (Qsetting_constant, symbol);
-   if (!NILP (Vautoload_queue) && !EQ (XSYMBOL (symbol)->function, Qunbound))
-     Vautoload_queue = Fcons (Fcons (symbol, XSYMBOL (symbol)->function),
-                            Vautoload_queue);
+   function = XSYMBOL (symbol)->function;
+   if (!NILP (Vautoload_queue) && !EQ (function, Qunbound))
+     Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue);
+   if (CONSP (function) && EQ (XCAR (function), Qautoload))
+     Fput (symbol, Qautoload, XCDR (function));
    XSYMBOL (symbol)->function = definition;
    /* Handle automatic advice activation */
    if (CONSP (XSYMBOL (symbol)->plist) && !NILP (Fget (symbol, Qad_advice_info)))
@@@ -752,7 -760,7 +760,7 @@@ Value, if non-nil, is a list \(interact
       Lisp_Object cmd;
  {
    Lisp_Object fun = indirect_function (cmd); /* Check cycles.  */
-   
    if (NILP (fun) || EQ (fun, Qunbound))
      return Qnil;
  
@@@ -2032,8 -2040,96 +2040,8 @@@ or a byte-code object.  IDX starts at 0
      }
    else if (CHAR_TABLE_P (array))
      {
 -      Lisp_Object val;
 -
 -      val = Qnil;
 -
 -      if (idxval < 0)
 -      args_out_of_range (array, idx);
 -      if (idxval < CHAR_TABLE_ORDINARY_SLOTS)
 -      {
 -        if (! SINGLE_BYTE_CHAR_P (idxval))
 -          args_out_of_range (array, idx);
 -        /* For ASCII and 8-bit European characters, the element is
 -             stored in the top table.  */
 -        val = XCHAR_TABLE (array)->contents[idxval];
 -        if (NILP (val))
 -          {
 -            int default_slot
 -              = (idxval < 0x80 ? CHAR_TABLE_DEFAULT_SLOT_ASCII
 -                 : idxval < 0xA0 ? CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
 -                 : CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC);
 -            val = XCHAR_TABLE (array)->contents[default_slot];
 -          }
 -        if (NILP (val))
 -          val = XCHAR_TABLE (array)->defalt;
 -        while (NILP (val))    /* Follow parents until we find some value.  */
 -          {
 -            array = XCHAR_TABLE (array)->parent;
 -            if (NILP (array))
 -              return Qnil;
 -            val = XCHAR_TABLE (array)->contents[idxval];
 -            if (NILP (val))
 -              val = XCHAR_TABLE (array)->defalt;
 -          }
 -        return val;
 -      }
 -      else
 -      {
 -        int code[4], i;
 -        Lisp_Object sub_table;
 -        Lisp_Object current_default;
 -
 -        SPLIT_CHAR (idxval, 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 */
 -
 -      try_parent_char_table:
 -        current_default = XCHAR_TABLE (array)->defalt;
 -        sub_table = array;
 -        for (i = 0; code[i] >= 0; i++)
 -          {
 -            val = XCHAR_TABLE (sub_table)->contents[code[i]];
 -            if (SUB_CHAR_TABLE_P (val))
 -              {
 -                sub_table = val;
 -                if (! NILP (XCHAR_TABLE (sub_table)->defalt))
 -                  current_default = XCHAR_TABLE (sub_table)->defalt;
 -              }
 -            else
 -              {
 -                if (NILP (val))
 -                  val = current_default;
 -                if (NILP (val))
 -                  {
 -                    array = XCHAR_TABLE (array)->parent;
 -                    if (!NILP (array))
 -                      goto try_parent_char_table;
 -                  }
 -                return val;
 -              }
 -          }
 -        /* Reaching here means IDXVAL is a generic character in
 -           which each character or a group has independent value.
 -           Essentially it's nonsense to get a value for such a
 -           generic character, but for backward compatibility, we try
 -           the default value and parent.  */
 -        val = current_default;
 -        if (NILP (val))
 -          {
 -            array = XCHAR_TABLE (array)->parent;
 -            if (!NILP (array))
 -              goto try_parent_char_table;
 -          }
 -        return val;
 -      }
 +      CHECK_CHARACTER (idx);
 +      return CHAR_TABLE_REF (array, idxval);
      }
    else
      {
@@@ -2089,8 -2185,45 +2097,8 @@@ bool-vector.  IDX starts at 0.  */
      }
    else if (CHAR_TABLE_P (array))
      {
 -      if (idxval < 0)
 -      args_out_of_range (array, idx);
 -      if (idxval < CHAR_TABLE_ORDINARY_SLOTS)
 -      {
 -        if (! SINGLE_BYTE_CHAR_P (idxval))
 -          args_out_of_range (array, idx);
 -        XCHAR_TABLE (array)->contents[idxval] = newelt;
 -      }
 -      else
 -      {
 -        int code[4], i;
 -        Lisp_Object val;
 -
 -        SPLIT_CHAR (idxval, code[0], code[1], code[2]);
 -        if (code[1] < 32) code[1] = -1;
 -        else if (code[2] < 32) code[2] = -1;
 -
 -        /* See the comment of the corresponding part in Faref.  */
 -        code[0] += 128;
 -        code[3] = -1;         /* anchor */
 -        for (i = 0; code[i + 1] >= 0; i++)
 -          {
 -            val = XCHAR_TABLE (array)->contents[code[i]];
 -            if (SUB_CHAR_TABLE_P (val))
 -              array = val;
 -            else
 -              {
 -                Lisp_Object temp;
 -
 -                /* VAL is a leaf.  Create a sub char table with the
 -                   initial value VAL and look into it.  */
 -
 -                temp = make_sub_char_table (val);
 -                XCHAR_TABLE (array)->contents[code[i]] = temp;
 -                array = temp;
 -              }
 -          }
 -        XCHAR_TABLE (array)->contents[code[i]] = newelt;
 -      }
 +      CHECK_CHARACTER (idx);
 +      CHAR_TABLE_SET (array, idxval, newelt);
      }
    else if (STRING_MULTIBYTE (array))
      {
  
        if (idxval < 0 || idxval >= SCHARS (array))
        args_out_of_range (array, idx);
 -      CHECK_NUMBER (newelt);
 +      CHECK_CHARACTER (newelt);
  
        nbytes = SBYTES (array);
  
        args_out_of_range (array, idx);
        CHECK_NUMBER (newelt);
  
 -      if (XINT (newelt) < 0 || SINGLE_BYTE_CHAR_P (XINT (newelt)))
 -      SSET (array, idxval, XINT (newelt));
 -      else
 -      {
 -        /* We must relocate the string data while converting it to
 -           multibyte.  */
 -        int idxval_byte, prev_bytes, new_bytes;
 -        unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
 -        unsigned char *origstr = SDATA (array), *str;
 -        int nchars, nbytes;
 -        USE_SAFE_ALLOCA;
 -
 -        nchars = SCHARS (array);
 -        nbytes = idxval_byte = count_size_as_multibyte (origstr, idxval);
 -        nbytes += count_size_as_multibyte (origstr + idxval,
 -                                           nchars - idxval);
 -        SAFE_ALLOCA (str, unsigned char *, nbytes);
 -        copy_text (SDATA (array), str, nchars, 0, 1);
 -        PARSE_MULTIBYTE_SEQ (str + idxval_byte, nbytes - idxval_byte,
 -                             prev_bytes);
 -        new_bytes = CHAR_STRING (XINT (newelt), p0);
 -        allocate_string_data (XSTRING (array), nchars,
 -                              nbytes + new_bytes - prev_bytes);
 -        bcopy (str, SDATA (array), idxval_byte);
 -        p1 = SDATA (array) + idxval_byte;
 -        while (new_bytes--)
 -          *p1++ = *p0++;
 -        bcopy (str + idxval_byte + prev_bytes, p1,
 -               nbytes - (idxval_byte + prev_bytes));
 -        SAFE_FREE ();
 -        clear_string_char_byte_cache ();
 -      }
 +      if (XINT (newelt) >= 0 && ! SINGLE_BYTE_CHAR_P (XINT (newelt)))
 +      args_out_of_range (array, newelt);
 +      SSET (array, idxval, XINT (newelt));
      }
  
    return newelt;
diff --combined src/dispextern.h
index 32ecee96f607aea3dfc22a5e243c4161c3331d95,fd4d8ebec9da9b35545333b7d1b82249dba0d835..e89d0d7e39006566b5079d965f829fe416a799e5
@@@ -680,9 -680,9 +680,9 @@@ struct glyph_ro
    short used[LAST_AREA];
  
    /* Window-relative x and y-position of the top-left corner of this
-      row.  If y < 0, this means that abs (y) pixels of the row are
+      row.  If y < 0, this means that eabs (y) pixels of the row are
       invisible because it is partially visible at the top of a window.
-      If x < 0, this means that abs (x) pixels of the first glyph of
+      If x < 0, this means that eabs (x) pixels of the first glyph of
       the text area of the row are invisible because the glyph is
       partially visible.  */
    int x, y;
  
    /* Continuation lines width at the start of the row.  */
    int continuation_lines_width;
 +
 +#ifdef HAVE_WINDOW_SYSTEM
 +  /* Non-NULL means the current clipping area.  This is temporarily
 +     set while exposing a region.  Coordinates are frame-relative.  */
 +  XRectangle *clip;
 +#endif
  };
  
  
@@@ -1221,14 -1215,6 +1221,14 @@@ struct glyph_strin
       *clip_tail, not including their overhangs.  */
    struct glyph_string *clip_head, *clip_tail;
  
 +#ifdef USE_FONT_BACKEND
 +  /* The current clipping areas.  */
 +  NativeRectangle clip[2];
 +
 +  /* Number of clipping areas. */
 +  int num_clips;
 +#endif        /* USE_FONT_BACKEND */
 +
    struct glyph_string *next, *prev;
  };
  
@@@ -1400,7 -1386,6 +1400,7 @@@ enum lface_attribute_inde
    LFACE_FONT_INDEX,
    LFACE_INHERIT_INDEX,
    LFACE_AVGWIDTH_INDEX,
 +  LFACE_FONTSET_INDEX,
    LFACE_VECTOR_SIZE
  };
  
@@@ -1485,12 -1470,10 +1485,12 @@@ struct fac
       reallocated.  */
    int font_info_id;
  
 -  /* Fontset ID if this face uses a fontset, or -1.  This is only >= 0
 -     if the face was realized for a composition sequence.
 -     Otherwise, a specific font is loaded from the set of fonts
 -     specified by the fontset given by the family attribute of the face.  */
 +#ifdef USE_FONT_BACKEND
 +  struct font_info *font_info;
 +#endif        /* USE_FONT_BACKEND */
 +
 +  /* Fontset ID if for this face's fontset.  Non-ASCII faces derived
 +     from the same ASCII face have the same fontset.  */
    int fontset;
  
    /* Pixmap width and height.  */
    /* The hash value of this face.  */
    unsigned hash;
  
 -  /* The charset for which this face was realized if it was realized
 -     for use in multibyte text.  If fontset >= 0, this is the charset
 -     of the first character of the composition sequence.  A value of
 -     charset < 0 means the face was realized for use in unibyte text
 -     where the idea of Emacs charsets isn't applicable.  */
 -  int charset;
 -
    /* Non-zero if text in this face should be underlined, overlined,
       strike-through or have a box drawn around it.  */
    unsigned underline_p : 1;
    /* Next and previous face in hash collision list of face cache.  */
    struct face *next, *prev;
  
 -  /* If this face is for ASCII characters, this points this face
 -     itself.  Otherwise, this points a face for ASCII characters.  */
 +  /* If this face is an ASCII face, this points to this face itself.
 +     Otherwise, this points to an ASCII face that has the same
 +     attributes except the font.  */
    struct face *ascii_face;
 +
 +#ifdef USE_FONT_BACKEND
 +  /* Extra member that a font-driver uses privately.  */
 +  void *extra;
 +#endif        /* USE_FONT_BACKEND */
  };
  
  
@@@ -1663,7 -1647,7 +1663,7 @@@ struct face_cach
  /* Non-zero if FACE is suitable for displaying character CHAR.  */
  
  #define FACE_SUITABLE_FOR_CHAR_P(FACE, CHAR)  \
 -  (SINGLE_BYTE_CHAR_P (CHAR)                  \
 +  (ASCII_CHAR_P (CHAR)                                \
     ? (FACE) == (FACE)->ascii_face             \
     : face_suitable_for_char_p ((FACE), (CHAR)))
  
     with id ID but is suitable for displaying character CHAR.
     This macro is only meaningful for multibyte character CHAR.  */
  
 -#define FACE_FOR_CHAR(F, FACE, CHAR)  \
 -  (SINGLE_BYTE_CHAR_P (CHAR)          \
 -   ? (FACE)->ascii_face->id           \
 -   : face_for_char ((F), (FACE), (CHAR)))
 +#define FACE_FOR_CHAR(F, FACE, CHAR, POS, OBJECT)     \
 +  (ASCII_CHAR_P (CHAR)                                        \
 +   ? (FACE)->ascii_face->id                           \
 +   : face_for_char ((F), (FACE), (CHAR), (POS), (OBJECT)))
  
  #else /* not HAVE_WINDOW_SYSTEM */
  
  #define FACE_SUITABLE_FOR_CHAR_P(FACE, CHAR) 1
 -#define FACE_FOR_CHAR(F, FACE, CHAR) ((FACE)->id)
 +#define FACE_FOR_CHAR(F, FACE, CHAR, POS, OBJECT) ((FACE)->id)
  
  #endif /* not HAVE_WINDOW_SYSTEM */
  
@@@ -1797,7 -1781,6 +1797,7 @@@ enum display_element_typ
  
  enum prop_idx
  {
 +  AUTO_COMPOSED_PROP_IDX,
    FONTIFIED_PROP_IDX,
    FACE_PROP_IDX,
    INVISIBLE_PROP_IDX,
@@@ -2339,9 -2322,7 +2339,9 @@@ struct redisplay_interfac
     the two-byte form of C.  Encoding is returned in *CHAR2B.  If
     TWO_BYTE_P is non-null, return non-zero there if font is two-byte.  */
    int (*encode_char) P_ ((int c, XChar2b *char2b,
 -                        struct font_info *font_into, int *two_byte_p));
 +                        struct font_info *font_into,
 +                        struct charset *charset,
 +                        int *two_byte_p));
  
  /* Compute left and right overhang of glyph string S.
     A NULL pointer if platform does not support this. */
@@@ -2850,17 -2831,15 +2850,17 @@@ void clear_face_cache P_ ((int))
  unsigned long load_color P_ ((struct frame *, struct face *, Lisp_Object,
                              enum lface_attribute_index));
  void unload_color P_ ((struct frame *, unsigned long));
 -int face_font_available_p P_ ((struct frame *, Lisp_Object));
 +char *choose_face_font P_ ((struct frame *, Lisp_Object *, Lisp_Object,
 +                          int *));
  int ascii_face_of_lisp_face P_ ((struct frame *, int));
  void prepare_face_for_display P_ ((struct frame *, struct face *));
  int xstricmp P_ ((const unsigned char *, const unsigned char *));
 -int lookup_face P_ ((struct frame *, Lisp_Object *, int, struct face *));
 -int lookup_named_face P_ ((struct frame *, Lisp_Object, int, int));
 +int lookup_face P_ ((struct frame *, Lisp_Object *));
 +int lookup_non_ascii_face P_ ((struct frame *, int, struct face *));
 +int lookup_named_face P_ ((struct frame *, Lisp_Object, int));
  int smaller_face P_ ((struct frame *, int, int));
  int face_with_height P_ ((struct frame *, int, int));
 -int lookup_derived_face P_ ((struct frame *, Lisp_Object, int, int, int));
 +int lookup_derived_face P_ ((struct frame *, Lisp_Object, int, int));
  void init_frame_faces P_ ((struct frame *));
  void free_frame_faces P_ ((struct frame *));
  void recompute_basic_faces P_ ((struct frame *));
@@@ -2871,12 -2850,10 +2871,12 @@@ int face_at_string_position P_ ((struc
  int merge_faces P_ ((struct frame *, Lisp_Object, int, int));
  int compute_char_face P_ ((struct frame *, int, Lisp_Object));
  void free_all_realized_faces P_ ((Lisp_Object));
 +void free_realized_face P_ ((struct frame *, struct face *));
  extern Lisp_Object Qforeground_color, Qbackground_color;
  extern Lisp_Object Qframe_set_background_mode;
  extern char unspecified_fg[], unspecified_bg[];
 -void free_realized_multibyte_face P_ ((struct frame *, int));
 +extern Lisp_Object split_font_name_into_vector P_ ((Lisp_Object));
 +extern Lisp_Object build_font_name_from_vector P_ ((Lisp_Object));
  
  /* Defined in xfns.c  */
  
diff --combined src/dispnew.c
index ab2c1518dce3a3beca2d22bbc2f9a94a8720738a,1778d5c818b6227e4e97f351b05796d400cff748..79bb81abfebf7e1361fe6d656bcf67fd9fa09ea1
@@@ -36,7 -36,7 +36,7 @@@ Boston, MA 02110-1301, USA.  *
  #include "dispextern.h"
  #include "cm.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "keyboard.h"
  #include "frame.h"
  #include "termhooks.h"
@@@ -1993,7 -1993,7 +1993,7 @@@ required_matrix_height (w
    if (FRAME_WINDOW_P (f))
      {
        int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
-       int window_pixel_height = window_box_height (w) + abs (w->vscroll);
+       int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
        return (((window_pixel_height + ch_height - 1)
               / ch_height) * w->nrows_scale_factor
              /* One partially visible line at the top and
diff --combined src/editfns.c
index 152c5b669d97e276efb73b475795c90f2c54217c,98ab2f9008149f7a022bd447d8965113c88450f5..66e3883494ff0ddd8a37bedd2c9bcd6057fd0072
@@@ -52,7 -52,7 +52,7 @@@ Boston, MA 02110-1301, USA.  *
  
  #include "intervals.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "coding.h"
  #include "frame.h"
  #include "window.h"
@@@ -210,9 -210,11 +210,9 @@@ usage: (char-to-string CHAR)  */
    int len;
    unsigned char str[MAX_MULTIBYTE_LENGTH];
  
 -  CHECK_NUMBER (character);
 +  CHECK_CHARACTER (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);
  }
  
@@@ -1846,7 -1848,7 +1846,7 @@@ usage: (encode-time SECOND MINUTE HOUR 
        tzstring = (char *) SDATA (zone);
        else if (INTEGERP (zone))
        {
-         int abszone = abs (XINT (zone));
+         int abszone = eabs (XINT (zone));
          sprintf (tzbuf, "XXX%s%d:%02d:%02d", "-" + (XINT (zone) < 0),
                   abszone / (60*60), (abszone/60) % 60, abszone % 60);
          tzstring = tzbuf;
@@@ -2153,7 -2155,7 +2153,7 @@@ general_insert_function (insert_func, i
    for (argnum = 0; argnum < nargs; argnum++)
      {
        val = args[argnum];
 -      if (INTEGERP (val))
 +      if (CHARACTERP (val))
        {
          unsigned char str[MAX_MULTIBYTE_LENGTH];
          int len;
            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;
@@@ -2329,29 -2331,6 +2329,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.  */
  
@@@ -2913,73 -2892,12 +2913,73 @@@ Both characters must have the same leng
    return Qnil;
  }
  
 +
 +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; the Nth character in it is the mapping
 -for the character with code N.
 +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;
    int pos, pos_byte, end_pos;
    int multibyte = !NILP (current_buffer->enable_multibyte_characters);
    int string_multibyte;
 +  Lisp_Object val;
  
    validate_region (&start, &end);
    if (CHAR_TABLE_P (table))
      {
 +      if (! EQ (XCHAR_TABLE (table)->purpose, Qtranslation_table))
 +      error ("Not a translation table");
        size = MAX_CHAR;
        tt = NULL;
      }
        if (! multibyte && (SCHARS (table) < SBYTES (table)))
        table = string_make_unibyte (table);
        string_multibyte = SCHARS (table) < SBYTES (table);
 -      size = SCHARS (table);
 +      size = SBYTES (table);
        tt = SDATA (table);
      }
  
    pos = XINT (start);
    pos_byte = CHAR_TO_BYTE (pos);
    end_pos = XINT (end);
 -  modify_region (current_buffer, pos, XINT (end), 0);
 +  modify_region (current_buffer, pos, end_pos, 0);
  
    cnt = 0;
    for (; pos < end_pos; )
        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);
              if (string_multibyte)
                {
                  str = tt + string_char_to_byte (table, oc);
 -                nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH,
 +                nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, 
                                               str_len);
                }
              else
                  nc = tt[oc];
                  if (! ASCII_BYTE_P (nc) && multibyte)
                    {
 -                    str_len = CHAR_STRING (nc, buf);
 +                    str_len = BYTE8_STRING (nc, buf);
                      str = buf;
                    }
                  else
            }
          else
            {
 -            Lisp_Object val;
              int c;
  
              nc = oc;
              val = CHAR_TABLE_REF (table, oc);
 -            if (INTEGERP (val)
 +            if (CHARACTERP (val)
                  && (c = XINT (val), CHAR_VALID_P (c, 0)))
                {
                  nc = c;
                  str_len = CHAR_STRING (nc, buf);
                  str = buf;
                }
 +            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 != oc && 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 if (nc < 0)
 +          {
 +            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++;
@@@ -3738,8 -3606,8 +3738,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.  */
@@@ -4143,20 -4011,8 +4143,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
@@@ -4651,7 -4507,6 +4651,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);
diff --combined src/fontset.c
index a9cf53c4913de8a516043adb57ef0274abe33c9e,2c0f0ac161ce6820020e36e84e9f8e8d856b21f1..045e632778ebfeb7abf22980f25dbc6312b0837b
@@@ -5,10 -5,7 +5,10 @@@
       2005, 2006, 2007
       National Institute of Advanced Industrial Science and Technology (AIST)
       Registration Number H14PRO021
 -
 +   Copyright (C) 2003, 2006
 +     National Institute of Advanced Industrial Science and Technology (AIST)
 +     Registration Number H13PRO009
 + 
  This file is part of GNU Emacs.
  
  GNU Emacs is free software; you can redistribute it and/or modify
@@@ -35,15 -32,12 +35,15 @@@ Boston, MA 02110-1301, USA.  *
  #endif
  
  #include "lisp.h"
 +#include "blockinput.h"
  #include "buffer.h"
 +#include "character.h"
  #include "charset.h"
  #include "ccl.h"
  #include "keyboard.h"
  #include "frame.h"
  #include "dispextern.h"
 +#include "intervals.h"
  #include "fontset.h"
  #include "window.h"
  #ifdef HAVE_X_WINDOWS
  #endif
  #include "termhooks.h"
  
 -#ifdef FONTSET_DEBUG
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +
  #undef xassert
 +#ifdef FONTSET_DEBUG
  #define xassert(X)    do {if (!(X)) abort ();} while (0)
  #undef INLINE
  #define INLINE
 -#endif
 +#else   /* not FONTSET_DEBUG */
 +#define xassert(X)    (void) 0
 +#endif        /* not FONTSET_DEBUG */
  
 +EXFUN (Fclear_face_cache, 1);
  
  /* FONTSET
  
     A fontset is a collection of font related information to give
 -   similar appearance (style, size, etc) of characters.  There are two
 -   kinds of fontsets; base and realized.  A base fontset is created by
 -   new-fontset from Emacs Lisp explicitly.  A realized fontset is
 -   created implicitly when a face is realized for ASCII characters.  A
 -   face is also realized for multibyte characters based on an ASCII
 -   face.  All of the multibyte faces based on the same ASCII face
 -   share the same realized fontset.
 +   similar appearance (style, etc) of characters.  A fontset has two
 +   roles.  One is to use for the frame parameter `font' as if it is an
 +   ASCII font.  In that case, Emacs uses the font specified for
 +   `ascii' script for the frame's default font.
 +
 +   Another role, the more important one, is to provide information
 +   about which font to use for each non-ASCII character.
 +
 +   There are two kinds of fontsets; base and realized.  A base fontset
 +   is created by `new-fontset' from Emacs Lisp explicitly.  A realized
 +   fontset is created implicitly when a face is realized for ASCII
 +   characters.  A face is also realized for non-ASCII characters based
 +   on an ASCII face.  All of non-ASCII faces based on the same ASCII
 +   face share the same realized fontset.
 +
 +   A fontset object is implemented by a char-table whose default value
 +   and parent are always nil.
 +
 +   An element of a base fontset is a vector of FONT-DEFs which itself
 +   is a vector [ FONT-SPEC ENCODING REPERTORY ].
 +
 +   FONT-SPEC is:
 +      [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
 +   or
 +      FONT-NAME
 +   where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
 +   FONT-NAME are strings.
 +
 +   Note: Currently WEIGHT through ADSTYLE are ignored.
 +
 +   ENCODING is a charset ID that can convert characters to glyph codes
 +   of the corresponding font.
 +
 +   REPERTORY is a charset ID, a char-table, or nil.  If REPERTORY is a
 +   charset ID, the repertory of the charset exactly matches with that
 +   of the font.  If REPERTORY is a char-table, all characters who have
 +   a non-nil value in the table are supported.  If REPERTORY is nil,
 +   we consult with the font itself to get the repertory.
  
 -   A fontset object is implemented by a char-table.
 +   ENCODING and REPERTORY are extracted from the variable
 +   Vfont_encoding_alist by using a font name generated from FONT-SPEC
 +   (if it is a vector) or FONT-NAME as a matching target.
  
 -   An element of a base fontset is:
 -      (INDEX . FONTNAME) or
 -      (INDEX . (FOUNDRY . REGISTRY ))
 -   FONTNAME is a font name pattern for the corresponding character.
 -   FOUNDRY and REGISTRY are respectively foundry and registry fields of
 -   a font name for the corresponding character.  INDEX specifies for
 -   which character (or generic character) the element is defined.  It
 -   may be different from an index to access this element.  For
 -   instance, if a fontset defines some font for all characters of
 -   charset `japanese-jisx0208', INDEX is the generic character of this
 -   charset.  REGISTRY is the
  
 -   An element of a realized fontset is FACE-ID which is a face to use
 -   for displaying the corresponding character.
 +   An element of a realized fontset is nil or t, or has this form:
  
 -   All single byte characters (ASCII and 8bit-unibyte) share the same
 -   element in a fontset.  The element is stored in the first element
 -   of the fontset.
 +      [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
 +       PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
  
 -   To access or set each element, use macros FONTSET_REF and
 -   FONTSET_SET respectively for efficiency.
 +   RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
  
 -   A fontset has 3 extra slots.
 +      [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ]
  
 -   The 1st slot is an ID number of the fontset.
 +   RFONT-DEFn is automatically reordered by the current charset
 +   priority list.
  
 -   The 2nd slot is a name of the fontset.  This is nil for a realized
 -   face.
 +   The value nil means that we have not yet generated the above vector
 +   from the base of the fontset.
  
 -   The 3rd slot is a frame that the fontset belongs to.  This is nil
 -   for a default face.
 +   The value t means that no font is available for the corresponding
 +   range of characters.
  
 -   A parent of a base fontset is nil.  A parent of a realized fontset
 -   is a base fontset.
  
 -   All fontsets are recorded in Vfontset_table.
 +   A fontset has 9 extra slots.
 +
 +   The 1st slot: the ID number of the fontset
 +
 +   The 2nd slot:
 +      base: the name of the fontset
 +      realized: nil
 +
 +   The 3rd slot:
 +      base: nil
 +      realized: the base fontset
 +
 +   The 4th slot:
 +      base: nil
 +      realized: the frame that the fontset belongs to
 +
 +   The 5th slot:
 +      base: the font name for ASCII characters
 +      realized: nil
 +
 +   The 6th slot:
 +      base: nil
 +      realized: the ID number of a face to use for characters that
 +                has no font in a realized fontset.
 +
 +   The 7th slot:
 +      base: nil
 +      realized: Alist of font index vs the corresponding repertory
 +      char-table.
 +      
 +   The 8th slot:
 +      base: nil
 +      realized: If the base is not the default fontset, a fontset
 +      realized from the default fontset, else nil.
 +
 +   The 9th slot:
 +      base: Same as element value (but for fallback fonts).
 +      realized: Likewise.
 +
 +   All fontsets are recorded in the vector Vfontset_table.
  
  
     DEFAULT FONTSET
  
 -   There's a special fontset named `default fontset' which defines a
 -   default fontname pattern.  When a base fontset doesn't specify a
 -   font for a specific character, the corresponding value in the
 -   default fontset is used.  The format is the same as a base fontset.
 +   There's a special base fontset named `default fontset' which
 +   defines the default font specifications.  When a base fontset
 +   doesn't specify a font for a specific character, the corresponding
 +   value in the default fontset is used.
  
     The parent of a realized fontset created for such a face that has
     no fontset is the default fontset.
  
     These structures are hidden from the other codes than this file.
     The other codes handle fontsets only by their ID numbers.  They
 -   usually use variable name `fontset' for IDs.  But, in this file, we
 -   always use variable name `id' for IDs, and name `fontset' for the
 -   actual fontset objects.
 +   usually use the variable name `fontset' for IDs.  But, in this
 +   file, we always use varialbe name `id' for IDs, and name `fontset'
 +   for an actual fontset object, i.e., char-table.
  
  */
  
  /********** VARIABLES and FUNCTION PROTOTYPES **********/
  
  extern Lisp_Object Qfont;
 -Lisp_Object Qfontset;
 +static Lisp_Object Qfontset;
 +static Lisp_Object Qfontset_info;
 +static Lisp_Object Qprepend, Qappend;
 +static Lisp_Object Qlatin;
  
  /* Vector containing all fontsets.  */
  static Lisp_Object Vfontset_table;
  static int next_fontset_id;
  
  /* The default fontset.  This gives default FAMILY and REGISTRY of
 -   font for each characters.  */
 +   font for each character.  */
  static Lisp_Object Vdefault_fontset;
  
 -/* Alist of font specifications.  It override the font specification
 -   in the default fontset.  */
 -static Lisp_Object Voverriding_fontspec_alist;
 -
  Lisp_Object Vfont_encoding_alist;
  Lisp_Object Vuse_default_ascent;
  Lisp_Object Vignore_relative_composition;
  Lisp_Object Valternate_fontname_alist;
  Lisp_Object Vfontset_alias_alist;
  Lisp_Object Vvertical_centering_font_regexp;
 +Lisp_Object Votf_script_alist;
  
  /* The following six are declarations of callback functions depending
     on window system.  See the comments in src/fontset.h for more
@@@ -257,38 -187,19 +257,38 @@@ void (*set_frame_fontset_func) P_ ((FRA
     This function set the member `encoder' of the structure.  */
  void (*find_ccl_program_func) P_ ((struct font_info *));
  
 +Lisp_Object (*get_font_repertory_func) P_ ((struct frame *,
 +                                          struct font_info *));
 +
  /* Check if any window system is used now.  */
  void (*check_window_system_func) P_ ((void));
  
  
  /* Prototype declarations for static functions.  */
 -static Lisp_Object fontset_ref P_ ((Lisp_Object, int));
 -static Lisp_Object lookup_overriding_fontspec P_ ((Lisp_Object, int));
 -static void fontset_set P_ ((Lisp_Object, int, Lisp_Object));
 +static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
 +                                  Lisp_Object));
 +static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
  static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 -static int fontset_id_valid_p P_ ((int));
  static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
 -static Lisp_Object font_family_registry P_ ((Lisp_Object, int));
 -static Lisp_Object regularize_fontname P_ ((Lisp_Object));
 +static void accumulate_script_ranges P_ ((Lisp_Object, Lisp_Object,
 +                                        Lisp_Object));
 +Lisp_Object find_font_encoding P_ ((Lisp_Object));
 +
 +static void set_fontset_font P_ ((Lisp_Object, Lisp_Object));
 +
 +#ifdef FONTSET_DEBUG
 +
 +/* Return 1 if ID is a valid fontset id, else return 0.  */
 +
 +static int
 +fontset_id_valid_p (id)
 +     int id;
 +{
 +  return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
 +}
 +
 +#endif
 +
  
  \f
  /********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
  
  /* Macros to access special values of FONTSET.  */
  #define FONTSET_ID(fontset)           XCHAR_TABLE (fontset)->extras[0]
 +
 +/* Macros to access special values of (base) FONTSET.  */
  #define FONTSET_NAME(fontset)         XCHAR_TABLE (fontset)->extras[1]
 -#define FONTSET_FRAME(fontset)                XCHAR_TABLE (fontset)->extras[2]
 -#define FONTSET_ASCII(fontset)                XCHAR_TABLE (fontset)->contents[0]
 -#define FONTSET_BASE(fontset)         XCHAR_TABLE (fontset)->parent
 +#define FONTSET_ASCII(fontset)                XCHAR_TABLE (fontset)->extras[4]
 +
 +/* Macros to access special values of (realized) FONTSET.  */
 +#define FONTSET_BASE(fontset)         XCHAR_TABLE (fontset)->extras[2]
 +#define FONTSET_FRAME(fontset)                XCHAR_TABLE (fontset)->extras[3]
 +#define FONTSET_NOFONT_FACE(fontset)  XCHAR_TABLE (fontset)->extras[5]
 +#define FONTSET_REPERTORY(fontset)    XCHAR_TABLE (fontset)->extras[6]
 +#define FONTSET_DEFAULT(fontset)      XCHAR_TABLE (fontset)->extras[7]
  
 -#define BASE_FONTSET_P(fontset)               NILP (FONTSET_BASE(fontset))
 +/* For both base and realized fontset.  */
 +#define FONTSET_FALLBACK(fontset)     XCHAR_TABLE (fontset)->extras[8]
  
 +#define BASE_FONTSET_P(fontset)               (NILP (FONTSET_BASE (fontset)))
  
 -/* Return the element of FONTSET (char-table) at index C (character).  */
  
 -#define FONTSET_REF(fontset, c)       fontset_ref (fontset, c)
 +/* Return the element of FONTSET for the character C.  If FONTSET is a
 +   base fontset other then the default fontset and FONTSET doesn't
 +   contain information for C, return the information in the default
 +   fontset.  */
 +
 +#define FONTSET_REF(fontset, c)               \
 +  (EQ (fontset, Vdefault_fontset)     \
 +   ? CHAR_TABLE_REF (fontset, c)      \
 +   : fontset_ref ((fontset), (c)))
  
  static Lisp_Object
  fontset_ref (fontset, c)
       Lisp_Object fontset;
       int c;
  {
 -  int charset, c1, c2;
 -  Lisp_Object elt, defalt;
 -
 -  if (SINGLE_BYTE_CHAR_P (c))
 -    return FONTSET_ASCII (fontset);
 -
 -  SPLIT_CHAR (c, charset, c1, c2);
 -  elt = XCHAR_TABLE (fontset)->contents[charset + 128];
 -  if (!SUB_CHAR_TABLE_P (elt))
 -    return elt;
 -  defalt = XCHAR_TABLE (elt)->defalt;
 -  if (c1 < 32
 -      || (elt = XCHAR_TABLE (elt)->contents[c1],
 -        NILP (elt)))
 -    return defalt;
 -  if (!SUB_CHAR_TABLE_P (elt))
 -    return elt;
 -  defalt = XCHAR_TABLE (elt)->defalt;
 -  if (c2 < 32
 -      || (elt = XCHAR_TABLE (elt)->contents[c2],
 -        NILP (elt)))
 -    return defalt;
 +  Lisp_Object elt;
 +
 +  elt = CHAR_TABLE_REF (fontset, c);
 +  if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
 +      /* Don't check Vdefault_fontset for a realized fontset.  */
 +      && NILP (FONTSET_BASE (fontset)))
 +    elt = CHAR_TABLE_REF (Vdefault_fontset, c);
    return elt;
  }
  
  
 +/* Return the element of FONTSET for the character C, set FROM and TO
 +   to the range of characters around C that have the same value as C.
 +   If FONTSET is a base fontset other then the default fontset and
 +   FONTSET doesn't contain information for C, return the information
 +   in the default fontset.  */
 +
 +#define FONTSET_REF_AND_RANGE(fontset, c, form, to)   \
 +  (EQ (fontset, Vdefault_fontset)                     \
 +   ? char_table_ref_and_range (fontset, c, &from, &to)        \
 +   : fontset_ref_and_range (fontset, c, &from, &to))
 +
  static Lisp_Object
 -lookup_overriding_fontspec (frame, c)
 -     Lisp_Object frame;
 +fontset_ref_and_range (fontset, c, from, to)
 +     Lisp_Object fontset;
       int c;
 +     int *from, *to;
  {
 -  Lisp_Object tail;
 +  Lisp_Object elt;
  
 -  for (tail = Voverriding_fontspec_alist; CONSP (tail); tail = XCDR (tail))
 +  elt = char_table_ref_and_range (fontset, c, from, to);
 +  if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
 +      /* Don't check Vdefault_fontset for a realized fontset.  */
 +      && NILP (FONTSET_BASE (fontset)))
      {
 -      Lisp_Object val, target, elt;
 -
 -      val = XCAR (tail);
 -      target = XCAR (val);
 -      val = XCDR (val);
 -      /* Now VAL is (NO-FRAME-LIST OK-FRAME-LIST CHAR FONTNAME).  */
 -      if (NILP (Fmemq (frame, XCAR (val)))
 -        && (CHAR_TABLE_P (target)
 -            ? ! NILP (CHAR_TABLE_REF (target, c))
 -            : XINT (target) == CHAR_CHARSET (c)))
 -      {
 -        val = XCDR (val);
 -        elt = XCDR (val);
 -        if (NILP (Fmemq (frame, XCAR (val))))
 -          {
 -            if (! face_font_available_p (XFRAME (frame), XCDR (elt)))
 -              {
 -                val = XCDR (XCAR (tail));
 -                XSETCAR (val, Fcons (frame, XCAR (val)));
 -                continue;
 -              }
 -            XSETCAR (val, Fcons (frame, XCAR (val)));
 -          }
 -        if (NILP (XCAR (elt)))
 -          XSETCAR (elt, make_number (c));
 -        return elt;
 -      }
 +      int from1, to1;
 +
 +      elt = char_table_ref_and_range (Vdefault_fontset, c, &from1, &to1);
 +      if (*from < from1)
 +      *from = from1;
 +      if (*to > to1)
 +      *to = to1;
      }
 -  return Qnil;
 +  return elt;
  }
  
 -#define FONTSET_REF_VIA_BASE(fontset, c) fontset_ref_via_base (fontset, &c)
 +
 +/* Set elements of FONTSET for characters in RANGE to the value ELT.
 +   RANGE is a cons (FROM . TO), where FROM and TO are character codes
 +   specifying a range.  */
 +
 +#define FONTSET_SET(fontset, range, elt)      \
 +  Fset_char_table_range ((fontset), (range), (elt))
 +
 +
 +/* Modify the elements of FONTSET for characters in RANGE by replacing
 +   with ELT or adding ELT.  RANGE is a cons (FROM . TO), where FROM
 +   and TO are character codes specifying a range.  If ADD is nil,
 +   replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
 +   append ELT.  */
 +
 +#define FONTSET_ADD(fontset, range, elt, add)                              \
 +  (NILP (add)                                                              \
 +   ? (NILP (range)                                                         \
 +      ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
 +      : Fset_char_table_range ((fontset), (range),                         \
 +                             Fmake_vector (make_number (1), (elt))))       \
 +   : fontset_add ((fontset), (range), (elt), (add)))
  
  static Lisp_Object
 -fontset_ref_via_base (fontset, c)
 -     Lisp_Object fontset;
 -     int *c;
 +fontset_add (fontset, range, elt, add)
 +     Lisp_Object fontset, range, elt, add;
  {
 -  int charset, c1, c2;
 -  Lisp_Object elt;
 +  Lisp_Object args[2];
 +  int idx = (EQ (add, Qappend) ? 0 : 1);
  
 -  if (SINGLE_BYTE_CHAR_P (*c))
 -    return FONTSET_ASCII (fontset);
 -
 -  elt = Qnil;
 -  if (! EQ (FONTSET_BASE (fontset), Vdefault_fontset))
 -    elt = FONTSET_REF (FONTSET_BASE (fontset), *c);
 -  if (NILP (elt))
 -    elt = lookup_overriding_fontspec (FONTSET_FRAME (fontset), *c);
 -  if (NILP (elt))
 -    elt = FONTSET_REF (Vdefault_fontset, *c);
 -  if (NILP (elt))
 -    return Qnil;
 +  args[1 - idx] = Fmake_vector (make_number (1), elt);
  
 -  *c = XINT (XCAR (elt));
 -  SPLIT_CHAR (*c, charset, c1, c2);
 -  elt = XCHAR_TABLE (fontset)->contents[charset + 128];
 -  if (c1 < 32)
 -    return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
 -  if (!SUB_CHAR_TABLE_P (elt))
 -    return Qnil;
 -  elt = XCHAR_TABLE (elt)->contents[c1];
 -  if (c2 < 32)
 -    return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
 -  if (!SUB_CHAR_TABLE_P (elt))
 -    return Qnil;
 -  elt = XCHAR_TABLE (elt)->contents[c2];
 -  return elt;
 +  if (CONSP (range))
 +    {
 +      int from = XINT (XCAR (range));
 +      int to = XINT (XCDR (range));
 +      int from1, to1;
 +
 +      do {
 +      args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
 +      if (to < to1)
 +        to1 = to;
 +      char_table_set_range (fontset, from, to1,
 +                            NILP (args[idx]) ? args[1 - idx]
 +                            : Fvconcat (2, args));
 +      from = to1 + 1;
 +      } while (from < to);
 +    }
 +  else
 +    {
 +      args[idx] = FONTSET_FALLBACK (fontset);
 +      FONTSET_FALLBACK (fontset)
 +      = NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
 +    }
 +  return Qnil;
  }
  
  
 -/* Store into the element of FONTSET at index C the value NEWELT.  */
 -#define FONTSET_SET(fontset, c, newelt) fontset_set(fontset, c, newelt)
 +/* Update FONTSET_ELEMENT which has this form:
 +      [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
 +       RFONT-DEF0 RFONT-DEF1 ...].
 +   Reorder RFONT-DEFs according to the current order of charset
 +   (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
 +   the latest value.  */
  
  static void
 -fontset_set (fontset, c, newelt)
 +reorder_font_vector (fontset_element)
 +     Lisp_Object fontset_element;
 +{
 +  Lisp_Object list, *new_vec;
 +  Lisp_Object font_def;
 +  int size;
 +  int *charset_id_table;
 +  int i, idx;
 +
 +  ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
 +  size = ASIZE (fontset_element) - 3;
 +  if (size <= 1)
 +    /* No need to reorder VEC.  */
 +    return;
 +  charset_id_table = (int *) alloca (sizeof (int) * size);
 +  new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
 +
 +  /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
 +     FONT-DEF has this form:
 +      [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
 +  for (i = 0; i < size; i++)
 +    {
 +      font_def = AREF (fontset_element, i + 3);
 +      if (VECTORP (AREF (font_def, 2))
 +        && INTEGERP (AREF (AREF (font_def, 2), 1)))
 +      charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
 +      else
 +      charset_id_table[i] = -1;
 +    }
 +
 +  /* Then, store FONT-DEFs in NEW_VEC in the correct order.  */
 +  for (idx = 0, list = Vcharset_ordered_list;
 +       idx < size && CONSP (list); list = XCDR (list))
 +    {
 +      for (i = 0; i < size; i++)
 +      if (charset_id_table[i] == XINT (XCAR (list)))
 +        new_vec[idx++] = AREF (fontset_element, i + 3);
 +    }
 +  for (i = 0; i < size; i++)
 +    if (charset_id_table[i] < 0)
 +      new_vec[idx++] = AREF (fontset_element, i + 3);
 +
 +  /* At last, update FONT-DEFs.  */
 +  for (i = 0; i < size; i++)
 +    ASET (fontset_element, i + 3, new_vec[i]);
 +}
 +
 +
 +/* Load a font matching the font related attributes in FACE->lface and
 +   font pattern in FONT_DEF of FONTSET, and return an index of the
 +   font.  FONT_DEF has this form:
 +      [ FONT-SPEC ENCODING REPERTORY ]
 +   If REPERTORY is nil, generate a char-table representing the font
 +   repertory by looking into the font itself.  */
 +
 +static int
 +load_font_get_repertory (f, face, font_def, fontset)
 +     FRAME_PTR f;
 +     struct face *face;
 +     Lisp_Object font_def;
 +     Lisp_Object fontset;
 +{
 +  char *font_name;
 +  struct font_info *font_info;
 +  int charset;
 +
 +  font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
 +  charset = XINT (AREF (font_def, 1));
 +  if (! (font_info = fs_load_font (f, font_name, charset)))
 +    return -1;
 +
 +  if (NILP (AREF (font_def, 2))
 +      && NILP (Fassq (make_number (font_info->font_idx),
 +                    FONTSET_REPERTORY (fontset))))
 +    {
 +      /* We must look into the font to get the correct repertory as a
 +       char-table.  */
 +      Lisp_Object repertory;
 +
 +      repertory = (*get_font_repertory_func) (f, font_info);
 +      FONTSET_REPERTORY (fontset)
 +      = Fcons (Fcons (make_number (font_info->font_idx), repertory),
 +               FONTSET_REPERTORY (fontset));
 +    }
 +      
 +  return font_info->font_idx;
 +}
 +
 +static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *,
 +                                        int, int));
 +
 +/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
 +   character C.  If the corresponding font is not yet opened, open it
 +   (if FACE is not NULL) or return Qnil (if FACE is NULL).
 +   If no proper font is found for C, return Qnil.
 +   ID is a charset-id that must be preferred, or -1 meaning no
 +   preference.
 +   If FALLBACK if nonzero, search only fallback fonts.  */
 +
 +static Lisp_Object
 +fontset_find_font (fontset, c, face, id, fallback)
       Lisp_Object fontset;
       int c;
 -     Lisp_Object newelt;
 +     struct face *face;
 +     int id, fallback;
  {
 -  int charset, code[3];
 -  Lisp_Object *elt;
 -  int i;
 +  Lisp_Object base_fontset, elt, vec, font_def;
 +  int i, from, to;
 +  int font_idx;
 +  FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
 +
 +  base_fontset = FONTSET_BASE (fontset);
 +  if (! fallback)
 +    vec = CHAR_TABLE_REF (fontset, c);
 +  else
 +    vec = FONTSET_FALLBACK (fontset);
 +  if (NILP (vec))
 +    {
 +      /* We have not yet decided a font for C.  */
 +      Lisp_Object range;
  
 -  if (SINGLE_BYTE_CHAR_P (c))
 +      if (! face)
 +      return Qnil;
 +      if (! fallback)
 +      elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
 +      else
 +      elt = FONTSET_FALLBACK (base_fontset);
 +      range = Fcons (make_number (from), make_number (to));
 +      if (NILP (elt))
 +      {
 +        /* Qt means we have no font for characters of this range.  */
 +        vec = Qt;
 +      }
 +      else
 +      {
 +        /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
 +           where the first -1 is to force reordering of NEW-ELTn,
 +           NEW-ELTn is [nil nil AREF (elt, n) nil].  */
 +#ifdef USE_FONT_BACKEND
 +        if (! fallback
 +            && enable_font_backend
 +            && EQ (base_fontset, Vdefault_fontset))
 +          /* Extra one element is for an automatically added
 +             font-def specifying only a script.  */
 +          vec = Fmake_vector (make_number (ASIZE (elt) + 4), Qnil);
 +        else
 +#endif        /* not USE_FONT_BACKEND */
 +          vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
 +        ASET (vec, 0, make_number (-1));
 +        ASET (vec, 1, make_number (-1));
 +        for (i = 0; i < ASIZE (elt); i++)
 +          {
 +            Lisp_Object tmp;
 +
 +            tmp = Fmake_vector (make_number (5), Qnil);
 +            ASET (tmp, 2, AREF (elt, i));
 +            ASET (vec, 3 + i, tmp);
 +          }
 +#ifdef USE_FONT_BACKEND
 +        if (! fallback
 +            && enable_font_backend
 +            && EQ (base_fontset, Vdefault_fontset))
 +          {
 +            Lisp_Object script, font_spec;
 +
 +            script = CHAR_TABLE_REF (Vchar_script_table, c);
 +            if (NILP (script))
 +              script = intern ("latin");
 +            font_spec = Ffont_spec (0, NULL);
 +            ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
 +            ASET (font_spec, FONT_EXTRA_INDEX,
 +                  Fcons (Fcons (QCscript, script), Qnil));
 +            font_def = Fmake_vector (make_number (3), Qnil);
 +            ASET (font_def, 0, font_spec);
 +            elt = Fmake_vector (make_number (5), Qnil);
 +            ASET (elt, 2, font_def);
 +            ASET (vec, 3 + i, elt);
 +          }
 +#endif        /* USE_FONT_BACKEND */
 +
 +        /* Then store it in the fontset.  */
 +        if (! fallback)
 +          FONTSET_SET (fontset, range, vec);
 +        else
 +          FONTSET_FALLBACK (fontset) = vec;
 +      }
 +    }
 +  if (EQ (vec, Qt))
 +    return Qnil;
 +
 +  if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
 +    /* The priority of charsets is changed after we selected a face
 +       for C last time.  */
 +    reorder_font_vector (vec);
 +
 +  if (id < 0)
 +    i = 3;
 +  else if (id == XFASTINT (AREF (vec, 1)))
 +    i = 2;
 +  else
      {
 -      FONTSET_ASCII (fontset) = newelt;
 -      return;
 +      ASET (vec, 1, make_number (id));
 +      for (i = 3; i < ASIZE (vec); i++)
 +      if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
 +        break;
 +      if (i < ASIZE (vec))
 +      {
 +        ASET (vec, 2, AREF (vec, i));
 +        i = 2;
 +      }
 +      else
 +      {
 +        ASET (vec, 2, Qnil);
 +        i = 3;
 +      }
      }
  
 -  SPLIT_CHAR (c, charset, code[0], code[1]);
 -  code[2] = 0;                        /* anchor */
 -  elt = &XCHAR_TABLE (fontset)->contents[charset + 128];
 -  for (i = 0; code[i] > 0; i++)
 +  /* Find the first available font in the vector of RFONT-DEF.  */
 +  for (; i < ASIZE (vec); i++)
      {
 -      if (!SUB_CHAR_TABLE_P (*elt))
 +      elt = AREF (vec, i);
 +      if (NILP (elt))
 +      continue;
 +      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
 +      if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
 +      /* We couldn't open this font last time.  */
 +      continue;
 +
 +      if (!face && NILP (AREF (elt, 1)))
 +      /* We have not yet opened the font.  */
 +      return Qnil;
 +
 +      font_def = AREF (elt, 2);
 +      /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */
 +
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend)
        {
 -        Lisp_Object val = *elt;
 -        *elt = make_sub_char_table (Qnil);
 -        XCHAR_TABLE (*elt)->defalt = val;
 +        /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY FONT-OBJECT ] */
 +        Lisp_Object font_entity = AREF (elt, 3);
 +        Lisp_Object font_object = AREF (elt, 4);
 +        Lisp_Object font_spec = AREF (font_def, 0);
 +        int has_char;
 +
 +        if (NILP (font_entity))
 +          {
 +            if (! FONT_SPEC_P (font_spec))
 +              {
 +                /* FONT_SPEC is FONT-NAME or (FAMILY . REGISTRY).  */
 +                font_spec = Ffont_spec (0, NULL);
 +                if (STRINGP (AREF (font_def, 0)))
 +                  font_merge_old_spec (AREF (font_def, 0), Qnil, Qnil,
 +                                       font_spec);
 +                else
 +                  {
 +                    Lisp_Object family = AREF (AREF (font_def, 0), 0);
 +                    Lisp_Object registry = AREF (AREF (font_def, 0), 5);;
 +
 +                    font_merge_old_spec (Qnil, family, registry, font_spec);
 +                  }
 +                ASET (font_def, 0, font_spec);
 +              }
 +            font_entity = font_find_for_lface (f, face->lface, font_spec);
 +            ASET (elt, 3, font_entity);
 +            if (NILP (font_entity))
 +              {
 +                ASET (elt, 1, make_number (-1));
 +                continue;
 +              }
 +            font_object = Qnil;
 +          }
 +        has_char = font_has_char (f, font_entity, c);
 +        if (has_char == 0)
 +          continue;
 +        if (NILP (font_object))
 +          {
 +            font_object = font_open_for_lface (f, font_entity,
 +                                               face->lface, font_spec);
 +            ASET (elt, 4, font_object);
 +            if (NILP (font_object))
 +              {
 +                ASET (elt, 1, make_number (-1));
 +                continue;
 +              }
 +          }
 +        ASET (elt, 1, make_number (0));
 +        ASET (elt, 4, font_object);
 +        if (has_char < 0
 +            && font_encode_char (font_object, c) == FONT_INVALID_CODE)
 +          continue;
        }
 -      elt = &XCHAR_TABLE (*elt)->contents[code[i]];
 +      else
 +#endif        /* USE_FONT_BACKEND */
 +
 +      if (INTEGERP (AREF (font_def, 2)))
 +      {
 +        /* The repertory is specified by charset ID.  */
 +        struct charset *charset
 +          = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));
 +
 +        if (! CHAR_CHARSET_P (c, charset))
 +          /* This font can't display C.  */
 +          continue;
 +      }
 +      else if (CHAR_TABLE_P (AREF (font_def, 2)))
 +      {
 +        /* The repertory is specified by a char table.  */
 +        if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c)))
 +          /* This font can't display C.  */
 +          continue;
 +      }
 +      else
 +      {
 +        Lisp_Object slot;
 +
 +        if (! INTEGERP (AREF (elt, 1)))
 +          {
 +            /* We have not yet opened a font matching this spec.
 +               Open the best matching font now and register the
 +               repertory.  */
 +            struct font_info *font_info;
 +
 +            font_idx = load_font_get_repertory (f, face, font_def, fontset);
 +            ASET (elt, 1, make_number (font_idx));
 +            if (font_idx < 0)
 +              /* This means that we couldn't find a font matching
 +                 FONT_DEF.  */
 +              continue;
 +            font_info = (*get_font_info_func) (f, font_idx);
 +            ASET (elt, 3, build_string (font_info->full_name));
 +          }
 +
 +        slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
 +        xassert (CONSP (slot));
 +        if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
 +          /* This font can't display C.  */
 +          continue;
 +      }
 +
 +      /* Now we have decided to use this font spec to display C.  */
 +      if (! INTEGERP (AREF (elt, 1)))
 +      {
 +        /* But not yet opened the best matching font.  */
 +        struct font_info *font_info;
 +
 +        font_idx = load_font_get_repertory (f, face, font_def, fontset);
 +        ASET (elt, 1, make_number (font_idx));
 +        if (font_idx < 0)
 +          /* Can't open it.  Try the other one.  */
 +          continue;
 +        font_info = (*get_font_info_func) (f, font_idx);
 +        ASET (elt, 3, build_string (font_info->full_name));
 +      }
 +
 +      /* Now we have the opened font.  */
 +      return elt;
      }
 -  if (SUB_CHAR_TABLE_P (*elt))
 -    XCHAR_TABLE (*elt)->defalt = newelt;
 -  else
 -    *elt = newelt;
 +  return Qnil;
  }
  
  
 +static Lisp_Object
 +fontset_font (fontset, c, face, id)
 +     Lisp_Object fontset;
 +     int c;
 +     struct face *face;
 +     int id;
 +{
 +  Lisp_Object rfont_def;
 +  Lisp_Object base_fontset;
 +
 +  /* Try a font-group for C. */
 +  rfont_def = fontset_find_font (fontset, c, face, id, 0);
 +  if (! NILP (rfont_def))
 +    return rfont_def;
 +  base_fontset = FONTSET_BASE (fontset);
 +  /* Try a font-group for C of the default fontset. */
 +  if (! EQ (base_fontset, Vdefault_fontset))
 +    {
 +      if (NILP (FONTSET_DEFAULT (fontset)))
 +      FONTSET_DEFAULT (fontset)
 +        = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
 +      rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
 +    }
 +  if (! NILP (rfont_def))
 +    return rfont_def;
 +  /* Try a fallback font-group. */
 +  rfont_def = fontset_find_font (fontset, c, face, id, 1);
 +  if (! NILP (rfont_def))
 +    return rfont_def;
 +  /* Try a fallback font-group of the default fontset . */
 +  if (! EQ (base_fontset, Vdefault_fontset))
 +    rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
 +  return rfont_def;
 +}
 +
  /* Return a newly created fontset with NAME.  If BASE is nil, make a
 -   base fontset.  Otherwise make a realized fontset whose parent is
 +   base fontset.  Otherwise make a realized fontset whose base is
     BASE.  */
  
  static Lisp_Object
@@@ -859,114 -391,103 +859,105 @@@ make_fontset (frame, name, base
    while (!NILP (AREF (Vfontset_table, id))) id++;
  
    if (id + 1 == size)
-     {
-       /* We must grow Vfontset_table.  */
-       Lisp_Object tem;
-       int i;
-       tem = Fmake_vector (make_number (size + 32), Qnil);
-       for (i = 0; i < size; i++)
-       AREF (tem, i) = AREF (Vfontset_table, i);
-       Vfontset_table = tem;
-     }
 -    Vfontset_table = larger_vector (Vfontset_table, size + 8, Qnil);
++    Vfontset_table = larger_vector (Vfontset_table, size + 32, Qnil);
  
    fontset = Fmake_char_table (Qfontset, Qnil);
  
    FONTSET_ID (fontset) = make_number (id);
 -  FONTSET_NAME (fontset) = name;
 -  FONTSET_FRAME (fontset) = frame;
 -  FONTSET_BASE (fontset) = base;
 +  if (NILP (base))
 +    {
 +      FONTSET_NAME (fontset) = name;
 +    }
 +  else
 +    {
 +      FONTSET_NAME (fontset) = Qnil;
 +      FONTSET_FRAME (fontset) = frame;
 +      FONTSET_BASE (fontset) = base;
 +    }
  
 -  AREF (Vfontset_table, id) = fontset;
 +  ASET (Vfontset_table, id, fontset);
    next_fontset_id = id + 1;
    return fontset;
  }
  
  
 -/* Return 1 if ID is a valid fontset id, else return 0.  */
 -
 -static INLINE int
 -fontset_id_valid_p (id)
 -     int id;
 -{
 -  return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
 -}
 -
 -
 -/* Extract `family' and `registry' string from FONTNAME and a cons of
 -   them.  Actually, `family' may also contain `foundry', `registry'
 -   may also contain `encoding' of FONTNAME.  But, if FONTNAME doesn't
 -   conform to XLFD nor explicitely specifies the other fields
 -   (i.e. not using wildcard `*'), return FONTNAME.  If FORCE is
 -   nonzero, specifications of the other fields are ignored, and return
 -   a cons as far as FONTNAME conform to XLFD.  */
 -
 -static Lisp_Object
 -font_family_registry (fontname, force)
 +/* Set the ASCII font of the default fontset to FONTNAME if that is
 +   not yet set.  */
 +void
 +set_default_ascii_font (fontname)
       Lisp_Object fontname;
 -     int force;
  {
 -  Lisp_Object family, registry;
 -  const char *p = SDATA (fontname);
 -  const char *sep[15];
 -  int i = 0;
 -
 -  while (*p && i < 15)
 -    if (*p++ == '-')
 -      {
 -      if (!force && i >= 2 && i <= 11 && *p != '*' && p[1] != '-')
 -        return fontname;
 -      sep[i++] = p;
 -      }
 -  if (i != 14)
 -    return fontname;
 +  if (! STRINGP (FONTSET_ASCII (Vdefault_fontset)))
 +    {
 +      int id = fs_query_fontset (fontname, 2);
  
 -  family = make_unibyte_string (sep[0], sep[2] - 1 - sep[0]);
 -  registry = make_unibyte_string (sep[12], p - sep[12]);
 -  return Fcons (family, registry);
 +      if (id >= 0)
 +      fontname = FONTSET_ASCII (FONTSET_FROM_ID (id));
 +      FONTSET_ASCII (Vdefault_fontset)= fontname;
 +    }
  }
  
  \f
 -/********** INTERFACES TO xfaces.c and dispextern.h **********/
 +/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
  
 -/* Return name of the fontset with ID.  */
 +/* Return the name of the fontset who has ID.  */
  
  Lisp_Object
  fontset_name (id)
       int id;
  {
    Lisp_Object fontset;
 +
    fontset = FONTSET_FROM_ID (id);
    return FONTSET_NAME (fontset);
  }
  
  
 -/* Return ASCII font name of the fontset with ID.  */
 +/* Return the ASCII font name of the fontset who has ID.  */
  
  Lisp_Object
  fontset_ascii (id)
       int id;
  {
    Lisp_Object fontset, elt;
 +
    fontset= FONTSET_FROM_ID (id);
    elt = FONTSET_ASCII (fontset);
 -  return XCDR (elt);
 +#ifdef USE_FONT_BACKEND
 +  if (CONSP (elt))
 +    elt = XCAR (elt);
 +#endif  /* USE_FONT_BACKEND */
 +  /* It is assured that ELT is always a string (i.e. fontname
 +     pattern).  */
 +  return elt;
  }
  
  
 -/* Free fontset of FACE.  Called from free_realized_face.  */
 +/* Free fontset of FACE defined on frame F.  Called from
 +   free_realized_face.  */
  
  void
  free_face_fontset (f, face)
       FRAME_PTR f;
       struct face *face;
  {
 -  if (fontset_id_valid_p (face->fontset))
 +  Lisp_Object fontset;
 +
 +  fontset = AREF (Vfontset_table, face->fontset);
 +  xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
 +  xassert (f == XFRAME (FONTSET_FRAME (fontset)));
 +  ASET (Vfontset_table, face->fontset, Qnil);
 +  if (face->fontset < next_fontset_id)
 +    next_fontset_id = face->fontset;
 +  if (! NILP (FONTSET_DEFAULT (fontset)))
      {
 -      AREF (Vfontset_table, face->fontset) = Qnil;
 -      if (face->fontset < next_fontset_id)
 +      int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
 +      
 +      fontset = AREF (Vfontset_table, id);
 +      xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
 +      xassert (f == XFRAME (FONTSET_FRAME (fontset)));
 +      ASET (Vfontset_table, id, Qnil);
 +      if (id < next_fontset_id)
        next_fontset_id = face->fontset;
      }
  }
  
  /* Return 1 if FACE is suitable for displaying character C.
     Otherwise return 0.  Called from the macro FACE_SUITABLE_FOR_CHAR_P
 -   when C is not a single byte character..  */
 +   when C is not an ASCII character.  */
  
  int
  face_suitable_for_char_p (face, c)
       struct face *face;
       int c;
  {
 -  Lisp_Object fontset, elt;
 -
 -  if (SINGLE_BYTE_CHAR_P (c))
 -    return (face == face->ascii_face);
 +  Lisp_Object fontset, rfont_def;
  
 -  xassert (fontset_id_valid_p (face->fontset));
    fontset = FONTSET_FROM_ID (face->fontset);
 -  xassert (!BASE_FONTSET_P (fontset));
 -
 -  elt = FONTSET_REF_VIA_BASE (fontset, c);
 -  return (!NILP (elt) && face->id == XFASTINT (elt));
 +  rfont_def = fontset_font (fontset, c, NULL, -1);
 +  return (VECTORP (rfont_def)
 +        && INTEGERP (AREF (rfont_def, 0))
 +        && face->id == XINT (AREF (rfont_def, 0)));
  }
  
  
  /* Return ID of face suitable for displaying character C on frame F.
 -   The selection of face is done based on the fontset of FACE.  FACE
 -   should already have been realized for ASCII characters.  Called
 -   from the macro FACE_FOR_CHAR when C is not a single byte character.  */
 +   FACE must be reazlied for ASCII characters in advance.  Called from
 +   the macro FACE_FOR_CHAR.  */
  
  int
 -face_for_char (f, face, c)
 +face_for_char (f, face, c, pos, object)
       FRAME_PTR f;
       struct face *face;
 -     int c;
 +     int c, pos;
 +     Lisp_Object object;
  {
 -  Lisp_Object fontset, elt;
 +  Lisp_Object fontset, charset, rfont_def;
    int face_id;
 +  int id;
 +
 +  if (ASCII_CHAR_P (c))
 +    return face->ascii_face->id;
  
    xassert (fontset_id_valid_p (face->fontset));
    fontset = FONTSET_FROM_ID (face->fontset);
    xassert (!BASE_FONTSET_P (fontset));
 +  if (pos < 0)
 +    id = -1;
 +  else
 +    {
 +      charset = Fget_char_property (make_number (pos), Qcharset, object);
 +      if (NILP (charset))
 +      id = -1;
 +      else if (CHARSETP (charset))
 +      id = XINT (CHARSET_SYMBOL_ID (charset));
 +    }
 +  rfont_def = fontset_font (fontset, c, face, id);
 +  if (VECTORP (rfont_def))
 +    {
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend
 +        && NILP (AREF (rfont_def, 0)))
 +      {
 +        struct font *font = XSAVE_VALUE (AREF (rfont_def, 4))->pointer;
  
 -  elt = FONTSET_REF_VIA_BASE (fontset, c);
 -  if (!NILP (elt))
 -    return XINT (elt);
 +        face_id = face_for_font (f, font, face);
 +        ASET (rfont_def, 0, make_number (face_id));
 +      }
 +      else
 +#endif        /* USE_FONT_BACKEND */
 +      if (NILP (AREF (rfont_def, 0)))
 +      {
 +        /* We have not yet made a realized face that uses this font.  */
 +        int font_idx = XINT (AREF (rfont_def, 1));
  
 -  /* No face is recorded for C in the fontset of FACE.  Make a new
 -     realized face for C that has the same fontset.  */
 -  face_id = lookup_face (f, face->lface, c, face);
 +        face_id = lookup_non_ascii_face (f, font_idx, face);
 +        ASET (rfont_def, 0, make_number (face_id));
 +      }
 +      return XINT (AREF (rfont_def, 0));
 +    }
  
 -  /* Record the face ID in FONTSET at the same index as the
 -     information in the base fontset.  */
 -  FONTSET_SET (fontset, c, make_number (face_id));
 -  return face_id;
 +  if (NILP (FONTSET_NOFONT_FACE (fontset)))
 +    {
 +      face_id = lookup_non_ascii_face (f, -1, face);
 +      FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
 +    }
 +  return XINT (FONTSET_NOFONT_FACE (fontset));
  }
  
  
     Called from realize_x_face.  */
  
  int
 -make_fontset_for_ascii_face (f, base_fontset_id)
 +make_fontset_for_ascii_face (f, base_fontset_id, face)
       FRAME_PTR f;
       int base_fontset_id;
 +     struct face *face;
  {
    Lisp_Object base_fontset, fontset, frame;
  
        if (!BASE_FONTSET_P (base_fontset))
        base_fontset = FONTSET_BASE (base_fontset);
        xassert (BASE_FONTSET_P (base_fontset));
 +      if (! BASE_FONTSET_P (base_fontset))
 +      abort ();
      }
    else
      base_fontset = Vdefault_fontset;
  
    fontset = make_fontset (frame, Qnil, base_fontset);
 -  return XINT (FONTSET_ID (fontset));
 -}
 -
 -
 -/* Return the font name pattern for C that is recorded in the fontset
 -   with ID.  If a font name pattern is specified (instead of a cons of
 -   family and registry), check if a font can be opened by that pattern
 -   to get the fullname.  If a font is opened, return that name.
 -   Otherwise, return nil.  If ID is -1, or the fontset doesn't contain
 -   information about C, get the registry and encoding of C from the
 -   default fontset.  Called from choose_face_font.  */
 +  {
 +    Lisp_Object elt, rfont_def, val;
  
 -Lisp_Object
 -fontset_font_pattern (f, id, c)
 -     FRAME_PTR f;
 -     int id, c;
 -{
 -  Lisp_Object fontset, elt;
 -  struct font_info *fontp;
 +    elt = FONTSET_REF (base_fontset, 0);
 +    xassert (VECTORP (elt) && ASIZE (elt) > 0);
 +#ifdef USE_FONT_BACKEND
 +    rfont_def = Fmake_vector (make_number (5), Qnil);
 +    if (enable_font_backend && face->font_info)
 +      {
 +      struct font *font = (struct font *) face->font_info;
  
 -  elt = Qnil;
 -  if (fontset_id_valid_p (id))
 -    {
 -      fontset = FONTSET_FROM_ID (id);
 -      xassert (!BASE_FONTSET_P (fontset));
 -      fontset = FONTSET_BASE (fontset);
 -      if (! EQ (fontset, Vdefault_fontset))
 -      elt = FONTSET_REF (fontset, c);
 -    }
 -  if (NILP (elt))
 +      ASET (rfont_def, 3, font->entity);
 +      ASET (rfont_def, 4, font_find_object (font));
 +      }
 +    else
 +#endif  /* USE_FONT_BACKEND */
      {
 -      Lisp_Object frame;
 -
 -      XSETFRAME (frame, f);
 -      elt = lookup_overriding_fontspec (frame, c);
 +      rfont_def = Fmake_vector (make_number (4), Qnil);
 +      ASET (rfont_def, 3, build_string (face->font_name));
      }
 -  if (NILP (elt))
 -    elt = FONTSET_REF (Vdefault_fontset, c);
 -
 -  if (!CONSP (elt))
 -    return Qnil;
 -  if (CONSP (XCDR (elt)))
 -    return XCDR (elt);
 -
 -  /* The fontset specifies only a font name pattern (not cons of
 -     family and registry).  If a font can be opened by that pattern,
 -     return the name of opened font.  Otherwise return nil.  The
 -     exception is a font for single byte characters.  In that case, we
 -     return a cons of FAMILY and REGISTRY extracted from the opened
 -     font name.  */
 -  elt = XCDR (elt);
 -  xassert (STRINGP (elt));
 -  fontp = FS_LOAD_FONT (f, c, SDATA (elt), -1);
 -  if (!fontp)
 -    return Qnil;
 -
 -  return font_family_registry (build_string (fontp->full_name),
 -                             SINGLE_BYTE_CHAR_P (c));
 +    ASET (rfont_def, 1, make_number (face->font_info_id));
 +    ASET (rfont_def, 2, AREF (elt, 0));
 +    elt = Fmake_vector (make_number (4), Qnil);
 +    ASET (elt, 0, make_number (charset_ordered_list_tick));
 +    ASET (elt, 1, make_number (charset_ascii));
 +    ASET (elt, 2, rfont_def);
 +    ASET (elt, 3, rfont_def);
 +
 +    val = Fcons (Qlatin, Qnil);
 +    map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table, val);
 +    for (val = XCDR (val); CONSP (val); val = XCDR (val))
 +      char_table_set_range (fontset, XINT (XCAR (XCAR (val))),
 +                          XINT (XCDR (XCAR (val))), elt);
 +    FONTSET_FALLBACK (fontset) = elt;
 +  }
 +  return XINT (FONTSET_ID (fontset));
  }
  
  
  #pragma optimize("", off)
  #endif
  
 -/* Load a font named FONTNAME to display character C on frame F.
 -   Return a pointer to the struct font_info of the loaded font.  If
 -   loading fails, return NULL.  If FACE is non-zero and a fontset is
 -   assigned to it, record FACE->id in the fontset for C.  If FONTNAME
 -   is NULL, the name is taken from the fontset of FACE or what
 -   specified by ID.  */
 +/* Load a font named FONTNAME on frame F.  Return a pointer to the
 +   struct font_info of the loaded font.  If loading fails, return
 +   NULL.  CHARSET is an ID of charset to encode characters for this
 +   font.  If it is -1, find one from Vfont_encoding_alist.  */
  
  struct font_info *
 -fs_load_font (f, c, fontname, id, face)
 +fs_load_font (f, fontname, charset)
       FRAME_PTR f;
 -     int c;
       char *fontname;
 -     int id;
 -     struct face *face;
 +     int charset;
  {
 -  Lisp_Object fontset;
 -  Lisp_Object list, elt, fullname;
 -  int size = 0;
    struct font_info *fontp;
 -  int charset = CHAR_CHARSET (c);
 -
 -  if (face)
 -    id = face->fontset;
 -  if (id < 0)
 -    fontset = Qnil;
 -  else
 -    fontset = FONTSET_FROM_ID (id);
 -
 -  if (!NILP (fontset)
 -      && !BASE_FONTSET_P (fontset))
 -    {
 -      elt = FONTSET_REF_VIA_BASE (fontset, c);
 -      if (!NILP (elt))
 -      {
 -        /* A suitable face for C is already recorded, which means
 -           that a proper font is already loaded.  */
 -        int face_id = XINT (elt);
 -
 -        xassert (face_id == face->id);
 -        face = FACE_FROM_ID (f, face_id);
 -        return (*get_font_info_func) (f, face->font_info_id);
 -      }
 -
 -      if (!fontname && charset == CHARSET_ASCII)
 -      {
 -        elt = FONTSET_ASCII (fontset);
 -        fontname = SDATA (XCDR (elt));
 -      }
 -    }
 +  Lisp_Object fullname;
  
    if (!fontname)
      /* No way to get fontname.  */
 -    return 0;
 -
 -  fontp = (*load_font_func) (f, fontname, size);
 -  if (!fontp)
 -    return 0;
 +    return NULL;
  
 -  /* Fill in members (charset, vertical_centering, encoding, etc) of
 -     font_info structure that are not set by (*load_font_func).  */
 -  fontp->charset = charset;
 +  fontp = (*load_font_func) (f, fontname, 0);
 +  if (! fontp || fontp->charset >= 0)
 +    return fontp;
  
 +  fontname = fontp->full_name;
    fullname = build_string (fontp->full_name);
 -  fontp->vertical_centering
 -    = (STRINGP (Vvertical_centering_font_regexp)
 -       && (fast_string_match_ignore_case
 -         (Vvertical_centering_font_regexp, fullname) >= 0));
  
 -  if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
 +  if (charset < 0)
      {
 -      /* The font itself tells which code points to be used.  Use this
 -       encoding for all other charsets.  */
 -      int i;
 -
 -      fontp->encoding[0] = fontp->encoding[1];
 -      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
 -      fontp->encoding[i] = fontp->encoding[1];
 +      Lisp_Object charset_symbol;
 +
 +      charset_symbol = find_font_encoding (fullname);
 +      if (CONSP (charset_symbol))
 +      charset_symbol = XCAR (charset_symbol);
 +      if (NILP (charset_symbol))
 +      charset_symbol = Qascii;
 +      charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
      }
 -  else
 -    {
 -      /* The font itself doesn't have information about encoding.  */
 -      int i;
 +  fontp->charset = charset;
 +  fontp->vertical_centering = 0;
 +  fontp->font_encoder = NULL;
  
 -      /* By default, encoding of ASCII chars is 0 (i.e. 0x00..0x7F),
 -       others is 1 (i.e. 0x80..0xFF).  */
 -      fontp->encoding[0] = 0;
 -      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
 -      fontp->encoding[i] = 1;
 -      /* Then override them by a specification in Vfont_encoding_alist.  */
 -      for (list = Vfont_encoding_alist; CONSP (list); list = XCDR (list))
 -      {
 -        elt = XCAR (list);
 -        if (CONSP (elt)
 -            && STRINGP (XCAR (elt)) && CONSP (XCDR (elt))
 -            && (fast_string_match_ignore_case (XCAR (elt), fullname) >= 0))
 -          {
 -            Lisp_Object tmp;
 +  if (charset != charset_ascii)
 +    {
 +      fontp->vertical_centering
 +      = (STRINGP (Vvertical_centering_font_regexp)
 +         && (fast_string_match_ignore_case
 +             (Vvertical_centering_font_regexp, fullname) >= 0));
  
 -            for (tmp = XCDR (elt); CONSP (tmp); tmp = XCDR (tmp))
 -              if (CONSP (XCAR (tmp))
 -                  && ((i = get_charset_id (XCAR (XCAR (tmp))))
 -                      >= 0)
 -                  && INTEGERP (XCDR (XCAR (tmp)))
 -                  && XFASTINT (XCDR (XCAR (tmp))) < 4)
 -                fontp->encoding[i]
 -                  = XFASTINT (XCDR (XCAR (tmp)));
 -          }
 -      }
 +      if (find_ccl_program_func)
 +      (*find_ccl_program_func) (fontp);
      }
  
 -  if (! fontp->font_encoder && find_ccl_program_func)
 -    (*find_ccl_program_func) (fontp);
 -
 -  /* If we loaded a font for a face that has fontset, record the face
 -     ID in the fontset for C.  */
 -  if (face
 -      && !NILP (fontset)
 -      && !BASE_FONTSET_P (fontset))
 -    FONTSET_SET (fontset, c, make_number (face->id));
    return fontp;
  }
  
  #pragma optimize("", on)
  #endif
  
 -/* Set the ASCII font of the default fontset to FONTNAME if that is
 -   not yet set.  */
 -void
 -set_default_ascii_font (fontname)
 +\f
 +/* Return ENCODING or a cons of ENCODING and REPERTORY of the font
 +   FONTNAME.  ENCODING is a charset symbol that specifies the encoding
 +   of the font.  REPERTORY is a charset symbol or nil.  */
 +
 +
 +Lisp_Object
 +find_font_encoding (fontname)
       Lisp_Object fontname;
  {
 -  if (! CONSP (FONTSET_ASCII (Vdefault_fontset)))
 -    {
 -      int id = fs_query_fontset (fontname, 2);
 +  Lisp_Object tail, elt;
  
 -      if (id >= 0)
 -      fontname = XCDR (FONTSET_ASCII (FONTSET_FROM_ID (id)));
 -      FONTSET_ASCII (Vdefault_fontset)
 -      = Fcons (make_number (0), fontname);
 +  for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
 +    {
 +      elt = XCAR (tail);
 +      if (CONSP (elt)
 +        && STRINGP (XCAR (elt))
 +        && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
 +        && (SYMBOLP (XCDR (elt))
 +            ? CHARSETP (XCDR (elt))
 +            : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
 +      return (XCDR (elt));
      }
 +  /* We don't know the encoding of this font.  Let's assume `ascii'.  */
 +  return Qascii;
  }
  
 -\f
 +
  /* Cache data used by fontset_pattern_regexp.  The car part is a
     pattern string containing at least one wild card, the cdr part is
     the corresponding regular expression.  */
@@@ -1300,8 -870,6 +1291,8 @@@ fs_query_fontset (name, name_pattern
    if (name_pattern != 1)
      {
        tem = Frassoc (name, Vfontset_alias_alist);
 +      if (NILP (tem))
 +      tem = Fassoc (name, Vfontset_alias_alist);
        if (CONSP (tem) && STRINGP (XCAR (tem)))
        name = XCAR (tem);
        else if (name_pattern == 0)
@@@ -1361,7 -929,9 +1352,7 @@@ If REGEXPP is non-nil, PATTERN is a reg
    return FONTSET_NAME (fontset);
  }
  
 -/* Return a list of base fontset names matching PATTERN on frame F.
 -   If SIZE is not 0, it is the size (maximum bound width) of fontsets
 -   to be listed.  */
 +/* Return a list of base fontset names matching PATTERN on frame F.  */
  
  Lisp_Object
  list_fontsets (f, pattern, size)
    Lisp_Object frame, regexp, val;
    int id;
  
 -  XSETFRAME (frame, f);
 +  XSETFRAME (frame, f);
 +
 +  regexp = fontset_pattern_regexp (pattern);
 +  val = Qnil;
 +
 +  for (id = 0; id < ASIZE (Vfontset_table); id++)
 +    {
 +      Lisp_Object fontset, name;
 +
 +      fontset = FONTSET_FROM_ID (id);
 +      if (NILP (fontset)
 +        || !BASE_FONTSET_P (fontset)
 +        || !EQ (frame, FONTSET_FRAME (fontset)))
 +      continue;
 +      name = FONTSET_NAME (fontset);
 +
 +      if (STRINGP (regexp)
 +        ? (fast_string_match (regexp, name) < 0)
 +        : strcmp (SDATA (pattern), SDATA (name)))
 +      continue;
 +
 +      val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
 +    }
 +
 +  return val;
 +}
 +
 +
 +/* Free all realized fontsets whose base fontset is BASE.  */
 +
 +static void
 +free_realized_fontsets (base)
 +     Lisp_Object base;
 +{
 +  int id;
 +
 +#if 0
 +  /* For the moment, this doesn't work because free_realized_face
 +     doesn't remove FACE from a cache.  Until we find a solution, we
 +     suppress this code, and simply use Fclear_face_cache even though
 +     that is not efficient.  */
 +  BLOCK_INPUT;
 +  for (id = 0; id < ASIZE (Vfontset_table); id++)
 +    {
 +      Lisp_Object this = AREF (Vfontset_table, id);
 +
 +      if (EQ (FONTSET_BASE (this), base))
 +      {
 +        Lisp_Object tail;
 +
 +        for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
 +             tail = XCDR (tail))
 +          {
 +            FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
 +            int face_id = XINT (XCDR (XCAR (tail)));
 +            struct face *face = FACE_FROM_ID (f, face_id);
 +
 +            /* Face THIS itself is also freed by the following call.  */
 +            free_realized_face (f, face);
 +          }
 +      }
 +    }
 +  UNBLOCK_INPUT;
 +#else  /* not 0 */
 +  /* But, we don't have to call Fclear_face_cache if no fontset has
 +     been realized from BASE.  */
 +  for (id = 0; id < ASIZE (Vfontset_table); id++)
 +    {
 +      Lisp_Object this = AREF (Vfontset_table, id);
 +
 +      if (CHAR_TABLE_P (this) && EQ (FONTSET_BASE (this), base))
 +      {
 +        Fclear_face_cache (Qt);
 +        break;
 +      }
 +    }
 +#endif /* not 0 */
 +}
 +
 +
 +/* Check validity of NAME as a fontset name and return the
 +   corresponding fontset.  If not valid, signal an error.
 +   If NAME is t, return Vdefault_fontset.  */
 +
 +static Lisp_Object
 +check_fontset_name (name)
 +     Lisp_Object name;
 +{
 +  int id;
 +
 +  if (EQ (name, Qt))
 +    return Vdefault_fontset;
 +
 +  CHECK_STRING (name);
 +  /* First try NAME as literal.  */
 +  id = fs_query_fontset (name, 2);
 +  if (id < 0)
 +    /* For backward compatibility, try again NAME as pattern.  */
 +    id = fs_query_fontset (name, 0);
 +  if (id < 0)
 +    error ("Fontset `%s' does not exist", SDATA (name));
 +  return FONTSET_FROM_ID (id);
 +}
 +
 +static void
 +accumulate_script_ranges (arg, range, val)
 +     Lisp_Object arg, range, val;
 +{
 +  if (EQ (XCAR (arg), val))
 +    {
 +      if (CONSP (range))
 +      XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
 +      else
 +      XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
 +    }
 +}
 +
 +
 +/* Return an ASCII font name generated from fontset name NAME and
 +   ASCII font specification ASCII_SPEC.  NAME is a string conforming
 +   to XLFD.  ASCII_SPEC is a vector:
 +      [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY].  */
 +
 +static INLINE Lisp_Object
 +generate_ascii_font_name (name, ascii_spec)
 +     Lisp_Object name, ascii_spec;
 +{
 +  Lisp_Object vec;
 +  int i;
 +
 +  vec = split_font_name_into_vector (name);
 +  for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
 +    if (! NILP (AREF (ascii_spec, i)))
 +      ASET (vec, 1 + i, AREF (ascii_spec, i));
 +  if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
 +    ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
 +  return build_font_name_from_vector (vec);
 +}
 +
 +/* Variables referred in set_fontset_font.  They are set before
 +   map_charset_chars is called in Fset_fontset_font.  */
 +static Lisp_Object font_def_arg, add_arg;
 +static int from_arg, to_arg;
 +
 +/* Callback function for map_charset_chars in Fset_fontset_font.  In
 +   FONTSET, set font_def_arg in a fashion specified by add_arg for
 +   characters in RANGE while ignoring the range between from_arg and
 +   to_arg.  */
 +
 +static void
 +set_fontset_font (fontset, range)
 +     Lisp_Object fontset, range;
 +{
 +  if (from_arg < to_arg)
 +    {
 +      int from = XINT (XCAR (range)), to = XINT (XCDR (range));
 +
 +      if (from < from_arg)
 +      {
 +        if (to > to_arg)
 +          {
 +            Lisp_Object range2;
 +
 +            range2 = Fcons (make_number (to_arg), XCDR (range));
 +            FONTSET_ADD (fontset, range, font_def_arg, add_arg);
 +            to = to_arg;
 +          }
 +        if (to > from_arg)
 +          range = Fcons (XCAR (range), make_number (from_arg));
 +      }
 +      else if (to <= to_arg)
 +      return;
 +      else
 +      {
 +        if (from < to_arg)
 +          range = Fcons (make_number (to_arg), XCDR (range));
 +      }
 +    }
 +  FONTSET_ADD (fontset, range, font_def_arg, add_arg);
 +}
 +
  
 -  regexp = fontset_pattern_regexp (pattern);
 -  val = Qnil;
 +DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
 +       doc: /*
 +Modify fontset NAME to use FONT-SPEC for TARGET characters.
  
 -  for (id = 0; id < ASIZE (Vfontset_table); id++)
 -    {
 -      Lisp_Object fontset, name;
 +TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
 +In that case, use FONT-SPEC for all characters in the range FROM and
 +TO (inclusive).
  
 -      fontset = FONTSET_FROM_ID (id);
 -      if (NILP (fontset)
 -        || !BASE_FONTSET_P (fontset)
 -        || !EQ (frame, FONTSET_FRAME (fontset)))
 -      continue;
 -      name = FONTSET_NAME (fontset);
 +TARGET may be a script name symbol.  In that case, use FONT-SPEC for
 +all characters that belong to the script.
  
 -      if (!NILP (regexp)
 -        ? (fast_string_match (regexp, name) < 0)
 -        : strcmp (SDATA (pattern), SDATA (name)))
 -      continue;
 +TARGET may be a charset.  In that case, use FONT-SPEC for all
 +characters in the charset.
  
 -      if (size)
 -      {
 -        struct font_info *fontp;
 -        fontp = FS_LOAD_FONT (f, 0, NULL, id);
 -        if (!fontp || size != fontp->size)
 -          continue;
 -      }
 -      val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
 -    }
 +TARGET may be nil.  In that case, use FONT-SPEC for any characters for
 +that no FONT-SPEC is specified.
  
 -  return val;
 -}
 +FONT-SPEC may one of these:
 + * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
 +   REGISTRY is a font registry name.  FAMILY may contains foundry
 +   name, and REGISTRY may contains encoding name.
 + * A font name string.
  
 -DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
 -       doc: /* Create a new fontset NAME that contains font information in FONTLIST.
 -FONTLIST is an alist of charsets vs corresponding font name patterns.  */)
 -     (name, fontlist)
 -     Lisp_Object name, fontlist;
 +Optional 4th argument FRAME, if non-nil, is a frame.  This argument is
 +kept for backward compatibility and has no meaning.
 +
 +Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
 +to the font specifications for TARGET previously set.  If it is
 +`prepend', FONT-SPEC is prepended.  If it is `append', FONT-SPEC is
 +appended.  By default, FONT-SPEC overrides the previous settings.  */)
 +     (name, target, font_spec, frame, add)
 +     Lisp_Object name, target, font_spec, frame, add;
  {
 -  Lisp_Object fontset, elements, ascii_font;
 -  Lisp_Object tem, tail, elt;
 -  int id;
 +  Lisp_Object fontset;
 +  Lisp_Object font_def, registry, family;
 +  Lisp_Object encoding, repertory;
 +  Lisp_Object range_list;
 +  struct charset *charset = NULL;
  
 -  (*check_window_system_func) ();
 +  fontset = check_fontset_name (name);
  
 -  CHECK_STRING (name);
 -  CHECK_LIST (fontlist);
 +  /* The arg FRAME is kept for backward compatibility.  We only check
 +     the validity.  */
 +  if (!NILP (frame))
 +    CHECK_LIVE_FRAME (frame);
  
 -  name = Fdowncase (name);
 -  id = fs_query_fontset (name, 2);
 -  if (id >= 0)
 +  if (VECTORP (font_spec))
      {
 -      fontset = FONTSET_FROM_ID (id);
 -      tem = FONTSET_NAME (fontset);
 -      error ("Fontset `%s' matches the existing fontset `%s'",
 -           SDATA (name),  SDATA (tem));
 +      /* FONT_SPEC should have this form:
 +              [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
 +       This is a feature not yet documented because WEIGHT thru
 +       ADSTYLE are ignored for the moment.  */
 +      int j;
 +
 +      if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
 +      args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
 +                         make_number (ASIZE (font_spec)));
 +
 +      font_spec = Fcopy_sequence (font_spec);
 +      for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
 +      if (! NILP (AREF (font_spec, j)))
 +        {
 +          CHECK_STRING (AREF (font_spec, j));
 +          ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
 +        }
 +      family = AREF (font_spec, FONT_SPEC_FAMILY_INDEX);
 +      /* REGISTRY should not be omitted.  */
 +      CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
 +      registry = AREF (font_spec, FONT_SPEC_REGISTRY_INDEX);
      }
 +  else if (CONSP (font_spec))
 +    {
 +      family = XCAR (font_spec);
 +      registry = XCDR (font_spec);
  
 -  /* Check the validity of FONTLIST while creating a template for
 -     fontset elements.  */
 -  elements = ascii_font = Qnil;
 -  for (tail = fontlist; CONSP (tail); tail = XCDR (tail))
 +      if (! NILP (family))
 +      {
 +        CHECK_STRING (family);
 +        family = Fdowncase (family);
 +      }
 +      CHECK_STRING (registry);
 +      registry = Fdowncase (registry);
 +      font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
 +      ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
 +      ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
 +    }
 +  else
      {
 -      int c, charset;
 +      CHECK_STRING (font_spec);
 +      font_spec = Fdowncase (font_spec);
 +    }
  
 -      tem = XCAR (tail);
 -      if (!CONSP (tem)
 -        || (charset = get_charset_id (XCAR (tem))) < 0
 -        || (!STRINGP (XCDR (tem)) && !CONSP (XCDR (tem))))
 -      error ("Elements of fontlist must be a cons of charset and font name pattern");
 +  if (STRINGP (font_spec))
 +    encoding = find_font_encoding (font_spec);
 +  else
 +    encoding = find_font_encoding (concat2 (family, registry));
 +  if (NILP (encoding))
 +    encoding = Qascii;
  
 -      tem = XCDR (tem);
 -      if (STRINGP (tem))
 -      tem = Fdowncase (tem);
 -      else
 -      tem = Fcons (Fdowncase (Fcar (tem)), Fdowncase (Fcdr (tem)));
 -      if (charset == CHARSET_ASCII)
 -      ascii_font = tem;
 -      else
 +  if (SYMBOLP (encoding))
 +    {
 +      CHECK_CHARSET (encoding);
 +      encoding = repertory = CHARSET_SYMBOL_ID (encoding);
 +    }
 +  else
 +    {
 +      repertory = XCDR (encoding);
 +      encoding = XCAR (encoding);
 +      CHECK_CHARSET (encoding);
 +      encoding = CHARSET_SYMBOL_ID (encoding);
 +      if (! NILP (repertory) && SYMBOLP (repertory))
        {
 -        c = MAKE_CHAR (charset, 0, 0);
 -        elements = Fcons (Fcons (make_number (c), tem), elements);
 +        CHECK_CHARSET (repertory);
 +        repertory = CHARSET_SYMBOL_ID (repertory);
        }
      }
 +  font_def = Fmake_vector (make_number (3), font_spec);
 +  ASET (font_def, 1, encoding);
 +  ASET (font_def, 2, repertory);
  
 -  if (NILP (ascii_font))
 -    error ("No ASCII font in the fontlist");
 +  if (CHARACTERP (target))
 +    range_list = Fcons (Fcons (target, target), Qnil);
 +  else if (CONSP (target))
 +    {
 +      Lisp_Object from, to;
  
 -  fontset = make_fontset (Qnil, name, Qnil);
 -  FONTSET_ASCII (fontset) = Fcons (make_number (0), ascii_font);
 -  for (; CONSP (elements); elements = XCDR (elements))
 +      from = Fcar (target);
 +      to = Fcdr (target);
 +      CHECK_CHARACTER (from);
 +      CHECK_CHARACTER (to);
 +      range_list = Fcons (target, Qnil);
 +    }
 +  else if (SYMBOLP (target) && !NILP (target))
      {
 -      elt = XCAR (elements);
 -      tem = XCDR (elt);
 -      if (STRINGP (tem))
 -      tem = font_family_registry (tem, 0);
 -      tem = Fcons (XCAR (elt), tem);
 -      FONTSET_SET (fontset, XINT (XCAR (elt)), tem);
 +      Lisp_Object script_list;
 +      Lisp_Object val;
 +
 +      range_list = Qnil;
 +      script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
 +      if (! NILP (Fmemq (target, script_list)))
 +      {
 +        val = Fcons (target, Qnil);
 +        map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
 +                        val);
 +        range_list = XCDR (val);
 +        if (EQ (target, Qlatin))
 +          {
 +            if (VECTORP (font_spec))
 +              val = generate_ascii_font_name (FONTSET_NAME (fontset),
 +                                              font_spec);
 +            else
 +              val = font_spec;
 +            FONTSET_ASCII (fontset) = val;
 +          }
 +      }
 +      if (CHARSETP (target))
 +      {
 +        if (EQ (target, Qascii))
 +          {
 +            if (VECTORP (font_spec))
 +              font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
 +                                                    font_spec);
 +            FONTSET_ASCII (fontset) = font_spec;
 +            range_list = Fcons (Fcons (make_number (0), make_number (127)),
 +                                Qnil);
 +          }
 +        else
 +          {
 +            CHECK_CHARSET_GET_CHARSET (target, charset);
 +          }
 +      }
 +      else if (NILP (range_list))
 +      error ("Invalid script or charset name: %s",
 +             SDATA (SYMBOL_NAME (target)));
      }
 +  else if (NILP (target))
 +    range_list = Fcons (Qnil, Qnil);
 +  else
 +    error ("Invalid target for setting a font");
  
 -  return Qnil;
 -}
  
 +  if (charset)
 +    {
 +      font_def_arg = font_def;
 +      add_arg = add;
 +      if (NILP (range_list))
 +      from_arg = to_arg = 0;
 +      else
 +      from_arg = XINT (XCAR (XCAR (range_list))),
 +        to_arg = XINT (XCDR (XCAR (range_list)));
  
 -/* Clear all elements of FONTSET for multibyte characters.  */
 +      map_charset_chars (set_fontset_font, Qnil, fontset, charset,
 +                       CHARSET_MIN_CODE (charset),
 +                       CHARSET_MAX_CODE (charset));
 +    }
 +  for (; CONSP (range_list); range_list = XCDR (range_list))
 +    FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
  
 -static void
 -clear_fontset_elements (fontset)
 -     Lisp_Object fontset;
 -{
 -  int i;
 +  /* Free all realized fontsets whose base is FONTSET.  This way, the
 +     specified character(s) are surely redisplayed by a correct
 +     font.  */
 +  free_realized_fontsets (fontset);
  
 -  for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
 -    XCHAR_TABLE (fontset)->contents[i] = Qnil;
 +  return Qnil;
  }
  
  
 -/* Check validity of NAME as a fontset name and return the
 -   corresponding fontset.  If not valid, signal an error.
 -   If NAME is nil, return Vdefault_fontset.  */
 -
 -static Lisp_Object
 -check_fontset_name (name)
 -     Lisp_Object name;
 -{
 -  int id;
 -
 -  if (EQ (name, Qnil))
 -    return Vdefault_fontset;
 +DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
 +       doc: /* Create a new fontset NAME from font information in FONTLIST.
  
 -  CHECK_STRING (name);
 -  /* First try NAME as literal.  */
 -  id = fs_query_fontset (name, 2);
 -  if (id < 0)
 -    /* For backward compatibility, try again NAME as pattern.  */
 -    id = fs_query_fontset (name, 0);
 -  if (id < 0)
 -    error ("Fontset `%s' does not exist", SDATA (name));
 -  return FONTSET_FROM_ID (id);
 -}
 +FONTLIST is an alist of scripts vs the corresponding font specification list.
 +Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
 +character of SCRIPT is displayed by a font that matches one of
 +FONT-SPEC.
  
 -/* Downcase FONTNAME or car and cdr of FONTNAME.  If FONTNAME is a
 -   string, maybe change FONTNAME to (FAMILY . REGISTRY).  */
 +SCRIPT is a symbol that appears in the first extra slot of the
 +char-table `char-script-table'.
  
 -static Lisp_Object
 -regularize_fontname (Lisp_Object fontname)
 +FONT-SPEC is a vector, a cons, or a string.  See the documentation of
 +`set-fontset-font' for the meaning.  */)
 +  (name, fontlist)
 +     Lisp_Object name, fontlist;
  {
 -  Lisp_Object family, registry;
 +  Lisp_Object fontset;
 +  Lisp_Object val;
 +  int id;
  
 -  if (STRINGP (fontname))
 -    return font_family_registry (Fdowncase (fontname), 0);
 +  CHECK_STRING (name);
 +  CHECK_LIST (fontlist);
  
 -  CHECK_CONS (fontname);
 -  family = XCAR (fontname);
 -  registry = XCDR (fontname);
 -  if (!NILP (family))
 +  id = fs_query_fontset (name, 0);
 +  if (id < 0)
      {
 -      CHECK_STRING (family);
 -      family = Fdowncase (family);
 +      name = Fdowncase (name);
 +      val = split_font_name_into_vector (name);
 +      if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13)))
 +      error ("Fontset name must be in XLFD format");
 +      if (strcmp (SDATA (AREF (val, 12)), "fontset"))
 +      error ("Registry field of fontset name must be \"fontset\"");
 +      Vfontset_alias_alist
 +      = Fcons (Fcons (name,
 +                      concat2 (concat2 (AREF (val, 12), build_string ("-")),
 +                               AREF (val, 13))),
 +               Vfontset_alias_alist);
 +      ASET (val, 12, build_string ("iso8859-1"));
 +      fontset = make_fontset (Qnil, name, Qnil);
 +      FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
      }
 -  if (!NILP (registry))
 +  else
      {
 -      CHECK_STRING (registry);
 -      registry = Fdowncase (registry);
 +      fontset = FONTSET_FROM_ID (id);;
 +      free_realized_fontsets (fontset);
 +      Fset_char_table_range (fontset, Qt, Qnil);
 +    }
 +
 +  for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
 +    {
 +      Lisp_Object elt, script;
 +
 +      elt = Fcar (fontlist);
 +      script = Fcar (elt);
 +      elt = Fcdr (elt);
 +      if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
 +      for (; CONSP (elt); elt = XCDR (elt))
 +        Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
 +      else
 +      Fset_fontset_font (name, script, elt, Qnil, Qappend);
      }
 -  return Fcons (family, registry);
 +  return name;
  }
  
 -DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
 -       doc: /* Modify fontset NAME to use FONTNAME for CHARACTER.
  
 -If NAME is nil, modify the default fontset.
 -CHARACTER may be a cons; (FROM . TO), where FROM and TO are
 -non-generic characters.  In that case, use FONTNAME
 -for all characters in the range FROM and TO (inclusive).
 -CHARACTER may be a charset.  In that case, use FONTNAME
 -for all character in the charsets.
 +/* Alist of automatically created fontsets.  Each element is a cons
 +   (FONTNAME . FONTSET-ID).  */
 +static Lisp_Object auto_fontset_alist;
  
 -FONTNAME may be a cons; (FAMILY . REGISTRY), where FAMILY is a family
 -name of a font, REGISTRY is a registry name of a font.  */)
 -     (name, character, fontname, frame)
 -     Lisp_Object name, character, fontname, frame;
 +int
 +new_fontset_from_font_name (Lisp_Object fontname)
  {
 -  Lisp_Object fontset, elt;
 -  Lisp_Object realized;
 -  int from, to;
 +  Lisp_Object val;
 +  Lisp_Object name;
 +  Lisp_Object vec;
    int id;
  
 -  fontset = check_fontset_name (name);
 +  fontname = Fdowncase (fontname);
 +  val = Fassoc (fontname, auto_fontset_alist);
 +  if (CONSP (val))
 +    return XINT (XCDR (val));
  
 -  if (CONSP (character))
 +  vec = split_font_name_into_vector (fontname);
 +  if ( NILP (vec))
 +    vec = Fmake_vector (make_number (14), build_string (""));
 +  ASET (vec, 12, build_string ("fontset"));
 +  if (NILP (auto_fontset_alist))
      {
 -      /* CH should be (FROM . TO) where FROM and TO are non-generic
 -       characters.  */
 -      CHECK_NUMBER_CAR (character);
 -      CHECK_NUMBER_CDR (character);
 -      from = XINT (XCAR (character));
 -      to = XINT (XCDR (character));
 -      if (!char_valid_p (from, 0) || !char_valid_p (to, 0))
 -      error ("Character range should be by non-generic characters");
 -      if (!NILP (name)
 -        && (SINGLE_BYTE_CHAR_P (from) || SINGLE_BYTE_CHAR_P (to)))
 -      error ("Can't change font for a single byte character");
 +      ASET (vec, 13, build_string ("startup"));
 +      name = build_font_name_from_vector (vec);
      }
 -  else if (SYMBOLP (character))
 +  else
      {
 -      elt = Fget (character, Qcharset);
 -      if (!VECTORP (elt) || ASIZE (elt) < 1 || !NATNUMP (AREF (elt, 0)))
 -      error ("Invalid charset: %s", SDATA (SYMBOL_NAME (character)));
 -      from = MAKE_CHAR (XINT (AREF (elt, 0)), 0, 0);
 -      to = from;
 +      char temp[20];
 +      int len = XINT (Flength (auto_fontset_alist));
 +
 +      sprintf (temp, "auto%d", len);
 +      ASET (vec, 13, build_string (temp));
 +      name = build_font_name_from_vector (vec);
      }
 +  name = Fnew_fontset (name, list2 (list2 (Qascii, fontname),
 +                                  list2 (Fcons (make_number (0),
 +                                                make_number (MAX_CHAR)),
 +                                         fontname)));
 +  id = fs_query_fontset (name, 0);
 +  auto_fontset_alist
 +    = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist);
 +  return id;
 +}
 +
 +#ifdef USE_FONT_BACKEND
 +int
 +new_fontset_from_font (font_object)
 +     Lisp_Object font_object;
 +{
 +  Lisp_Object font_name = font_get_name (font_object);
 +  Lisp_Object font_spec = font_get_spec (font_object);
 +  Lisp_Object fontset_spec, short_name, name, fontset;
 +
 +  if (NILP (auto_fontset_alist))
 +    short_name = build_string ("fontset-startup");
    else
      {
 -      CHECK_NUMBER (character);
 -      from = XINT (character);
 -      to = from;
 +      char temp[32];
 +      int len = XINT (Flength (auto_fontset_alist));
 +
 +      sprintf (temp, "fontset-auto%d", len);
 +      short_name = build_string (temp);
      }
 -  if (!char_valid_p (from, 1))
 -    invalid_character (from);
 -  if (SINGLE_BYTE_CHAR_P (from))
 -    error ("Can't change font for a single byte character");
 -  if (from < to)
 +  fontset_spec = Fcopy_sequence (font_spec);
 +  ASET (fontset_spec, FONT_REGISTRY_INDEX, short_name);
 +  name = Ffont_xlfd_name (fontset_spec);
 +  if (NILP (name))
      {
 -      if (!char_valid_p (to, 1))
 -      invalid_character (to);
 -      if (SINGLE_BYTE_CHAR_P (to))
 -      error ("Can't change font for a single byte character");
 -    }
 +      int i;
  
 -  /* The arg FRAME is kept for backward compatibility.  We only check
 -     the validity.  */
 -  if (!NILP (frame))
 -    CHECK_LIVE_FRAME (frame);
 +      for (i = 0; i < FONT_SIZE_INDEX; i++)
 +      if ((i != FONT_FAMILY_INDEX) && (i != FONT_REGISTRY_INDEX))
 +        ASET (fontset_spec, i, Qnil);
 +      name = Ffont_xlfd_name (fontset_spec);
 +      if (NILP (name))
 +      abort ();
 +    }
 +  fontset = make_fontset (Qnil, name, Qnil);
 +  FONTSET_ASCII (fontset) = font_name;
 +  font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
 +                   SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
 +  Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
 +  Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
 +  return XINT (FONTSET_ID (fontset));
 +}
  
 -  elt = Fcons (make_number (from), regularize_fontname (fontname));
 -  for (; from <= to; from++)
 -    FONTSET_SET (fontset, from, elt);
 -  Foptimize_char_table (fontset);
 +struct font *
 +fontset_ascii_font (f, id)
 +     FRAME_PTR f;
 +     int id;
 +{
 +  Lisp_Object fontset = FONTSET_FROM_ID (id);
 +  Lisp_Object ascii_slot = FONTSET_ASCII (fontset);
 +  Lisp_Object val, font_object;
  
 -  /* If there's a realized fontset REALIZED whose parent is FONTSET,
 -     clear all the elements of REALIZED and free all multibyte faces
 -     whose fontset is REALIZED.  This way, the specified character(s)
 -     are surely redisplayed by a correct font.  */
 -  for (id = 0; id < ASIZE (Vfontset_table); id++)
 +  if (CONSP (ascii_slot))
      {
 -      realized = AREF (Vfontset_table, id);
 -      if (!NILP (realized)
 -        && !BASE_FONTSET_P (realized)
 -        && EQ (FONTSET_BASE (realized), fontset))
 +      Lisp_Object ascii_font_name = XCAR (ascii_slot);
 +
 +      font_object = Qnil;
 +      for (val = XCDR (ascii_slot); ! NILP (val); val = XCDR (val))
 +      {
 +        Lisp_Object frame = font_get_frame (XCAR (val));
 +
 +        if (NILP (frame) || XFRAME (frame) == f)
 +          {
 +            font_object = XCAR (val);
 +            if (XSAVE_VALUE (font_object)->integer == 0)
 +              {
 +                font_object = font_open_by_name (f, SDATA (ascii_font_name));
 +                XSETCAR (val, font_object);
 +              }
 +            break;
 +          }
 +      }
 +      if (NILP (font_object))
        {
 -        FRAME_PTR f = XFRAME (FONTSET_FRAME (realized));
 -        clear_fontset_elements (realized);
 -        free_realized_multibyte_face (f, id);
 +        font_object = font_open_by_name (f, SDATA (ascii_font_name));
 +        XSETCDR (ascii_slot, Fcons (font_object, XCDR (ascii_slot)));
        }
      }
 -
 -  return Qnil;
 +  else
 +    {
 +      font_object = font_open_by_name (f, SDATA (ascii_slot));
 +      FONTSET_ASCII (fontset) = Fcons (ascii_slot, Fcons (font_object, Qnil));
 +    }
 +  if (NILP (font_object))
 +    return NULL;
 +  return XSAVE_VALUE (font_object)->pointer;
  }
  
 +#endif        /* USE_FONT_BACKEND */
 +
  DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
         doc: /* Return information about a font named NAME on frame FRAME.
  If FRAME is omitted or nil, use the selected frame.
@@@ -1980,7 -1223,6 +1971,7 @@@ If the named font is not yet loaded, re
    FRAME_PTR f;
    struct font_info *fontp;
    Lisp_Object info;
 +  Lisp_Object font_object;
  
    (*check_window_system_func) ();
  
    if (!query_font_func)
      error ("Font query function is not supported");
  
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      font_object = font_open_by_name (f, SDATA (name));
 +      if (NILP (font_object))
 +      fontp = NULL;
 +      else
 +      fontp = (struct font_info *) XSAVE_VALUE (font_object)->pointer;
 +    }
 +  else
 +#endif        /* USE_FONT_BACKEND */
    fontp = (*query_font_func) (f, SDATA (name));
    if (!fontp)
      return Qnil;
    XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
    XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
  
 +#ifdef USE_FONT_BACKEND
 +  if (! NILP (font_object))
 +    font_close_object (f, font_object);
 +#endif        /* USE_FONT_BACKEND */
    return info;
  }
  
@@@ -2061,24 -1288,20 +2052,24 @@@ DEFUN ("internal-char-font", Finternal_
  {
    int pos, pos_byte, dummy;
    int face_id;
 -  int c, code;
 +  int c;
    struct frame *f;
    struct face *face;
 +  Lisp_Object charset, rfont_def;
 +  int cs_id;
  
    if (NILP (position))
      {
 -      CHECK_NATNUM (ch);
 +      CHECK_CHARACTER (ch);
        c = XINT (ch);
        f = XFRAME (selected_frame);
        face_id = DEFAULT_FACE_ID;
 +      pos = -1;
 +      cs_id = -1;
      }
    else
      {
 -      Lisp_Object window;
 +      Lisp_Object window, charset;
        struct window *w;
  
        CHECK_NUMBER_COERCE_MARKER (position);
        w = XWINDOW (window);
        f = XFRAME (w->frame);
        face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
 +      charset = Fget_char_property (position, Qcharset, Qnil);
 +      if (CHARSETP (charset))
 +      cs_id = XINT (CHARSET_SYMBOL_ID (charset));
 +      else
 +      cs_id = -1;
      }
    if (! CHAR_VALID_P (c, 0))
      return Qnil;
 -  face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
 +  face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
    face = FACE_FROM_ID (f, face_id);
 -  if (! face->font || ! face->font_name)
 -    return Qnil;
 -
 -  {
 -    struct font_info *fontp = (*get_font_info_func) (f, face->font_info_id);
 -    XChar2b char2b;
 -    int c1, c2, charset;
 -
 -    SPLIT_CHAR (c, charset, c1, c2);
 -    if (c2 > 0)
 -      STORE_XCHAR2B (&char2b, c1, c2);
 -    else
 -      STORE_XCHAR2B (&char2b, 0, c1);
 -    FRAME_RIF (f)->encode_char (c, &char2b, fontp, NULL);
 -    code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
 -  }
 -  return Fcons (build_string (face->font_name), make_number (code));
 +  rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset), c, face, cs_id);
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 4)))
 +      {
 +        Lisp_Object font_object = AREF (rfont_def, 4);
 +        struct font *font = XSAVE_VALUE (font_object)->pointer;
 +        unsigned code = font->driver->encode_char (font, c);
 +        Lisp_Object fontname = font_get_name (font_object);
 +
 +        if (code == FONT_INVALID_CODE)
 +          return Fcons (fontname, Qnil);
 +        if (code <= MOST_POSITIVE_FIXNUM)
 +          return Fcons (fontname, make_number (code));
 +        return Fcons (fontname, Fcons (make_number (code >> 16),
 +                                       make_number (code & 0xFFFF)));
 +      }
 +      return Qnil;
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +  if (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3)))
 +    {
 +      Lisp_Object font_def;
 +      struct font_info *fontp;
 +      struct charset *charset;
 +      XChar2b char2b;
 +      int code;
 +
 +      font_def = AREF (rfont_def, 2);
 +      charset = CHARSET_FROM_ID (XINT (AREF (font_def, 1)));
 +      code = ENCODE_CHAR (charset, c);
 +      if (code == CHARSET_INVALID_CODE (charset))
 +      return (Fcons (AREF (rfont_def, 3), Qnil));
 +      STORE_XCHAR2B (&char2b, ((code >> 8) & 0xFF), (code & 0xFF));
 +      fontp = (*get_font_info_func) (f, XINT (AREF (rfont_def, 1)));
 +      FRAME_RIF (f)->encode_char (c, &char2b, fontp, charset, NULL);
 +      code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
 +      return (Fcons (AREF (rfont_def, 3), make_number (code)));
 +    }
 +  return Qnil;
  }
  
  
 -/* Called from Ffontset_info via map_char_table on each leaf of
 -   fontset.  ARG is a copy of the default fontset.  The current leaf
 -   is indexed by CHARACTER and has value ELT.  This function override
 -   the copy by ELT if ELT is not nil.  */
 -
 -static void
 -override_font_info (fontset, character, elt)
 -     Lisp_Object fontset, character, elt;
 -{
 -  if (! NILP (elt))
 -    Faset (fontset, character, elt);
 -}
 +DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
 +       doc: /* Return information about a fontset FONTSET on frame FRAME.
 +The value is a char-table of which elements has this form.
  
 -/* Called from Ffontset_info via map_char_table on each leaf of
 -   fontset.  ARG is a list (LAST FONT-INFO ...), where LAST is `(last
 -   ARG)' and FONT-INFOs have this form:
 -      (CHAR FONT-SPEC) or ((FROM . TO) FONT-SPEC)
 -   The current leaf is indexed by CHARACTER and has value ELT.  This
 -   function add the information of the current leaf to ARG by
 -   appending a new element or modifying the last element.  */
 +    ((FONT-PATTERN OPENED-FONT ...) ...)
  
 -static void
 -accumulate_font_info (arg, character, elt)
 -     Lisp_Object arg, character, elt;
 -{
 -  Lisp_Object last, last_char, last_elt;
 +FONT-PATTERN is a vector:
  
 -  if (!CONSP (elt) && !SINGLE_BYTE_CHAR_P (XINT (character)))
 -    elt = FONTSET_REF (Vdefault_fontset, XINT (character));
 -  if (!CONSP (elt))
 -    return;
 -  last = XCAR (arg);
 -  last_char = XCAR (XCAR (last));
 -  last_elt = XCAR (XCDR (XCAR (last)));
 -  elt = XCDR (elt);
 -  if (!NILP (Fequal (elt, last_elt)))
 -    {
 -      int this_charset = CHAR_CHARSET (XINT (character));
 +      [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
  
 -      if (CONSP (last_char))  /* LAST_CHAR == (FROM . TO)  */
 -      {
 -        if (this_charset == CHAR_CHARSET (XINT (XCAR (last_char))))
 -          {
 -            XSETCDR (last_char, character);
 -            return;
 -          }
 -      }
 -      else if (XINT (last_char) == XINT (character))
 -      return;
 -      else if (this_charset == CHAR_CHARSET (XINT (last_char)))
 -      {
 -        XSETCAR (XCAR (last), Fcons (last_char, character));
 -        return;
 -      }
 -    }
 -  XSETCDR (last, Fcons (Fcons (character, Fcons (elt, Qnil)), Qnil));
 -  XSETCAR (arg, XCDR (last));
 -}
 +or a string of font name pattern.
  
 +OPENED-FONT is a name of a font actually opened.
  
 -DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
 -       doc: /* Return information about a fontset named NAME on frame FRAME.
 -If NAME is nil, return information about the default fontset.
 -The value is a vector:
 -  [ SIZE HEIGHT ((CHARSET-OR-RANGE FONT-SPEC OPENED ...) ...) ],
 -where,
 -  SIZE is the maximum bound width of ASCII font in the fontset,
 -  HEIGHT is the maximum bound height of ASCII font in the fontset,
 -  CHARSET-OR-RANGE is a charset, a character (may be a generic character)
 -    or a cons of two characters specifying the range of characters.
 -  FONT-SPEC is a fontname pattern string or a cons (FAMILY . REGISTRY),
 -    where FAMILY is a `FAMILY' field of a XLFD font name,
 -    REGISTRY is a `CHARSET_REGISTRY' field of a XLFD font name.
 -    FAMILY may contain a `FOUNDRY' field at the head.
 -    REGISTRY may contain a `CHARSET_ENCODING' field at the tail.
 -  OPENEDs are names of fonts actually opened.
 -If the ASCII font is not yet opened, SIZE and HEIGHT are 0.
 -If FRAME is omitted, it defaults to the currently selected frame.  */)
 -     (name, frame)
 -     Lisp_Object name, frame;
 +The char-table has one extra slot.  The value is a char-table
 +containing the information about the derived fonts from the default
 +fontset.  The format is the same as abobe.  */)
 +     (fontset, frame)
 +     Lisp_Object fontset, frame;
  {
 -  Lisp_Object fontset;
    FRAME_PTR f;
 -  int indices[3];
 -  Lisp_Object val, tail, elt;
 -  Lisp_Object *realized;
 -  struct font_info *fontp = NULL;
 -  int n_realized = 0;
 -  int i;
 +  Lisp_Object *realized[2], fontsets[2], tables[2];
 +  Lisp_Object val, elt;
 +  int c, i, j, k;
  
    (*check_window_system_func) ();
  
 -  fontset = check_fontset_name (name);
 +  fontset = check_fontset_name (fontset);
  
    if (NILP (frame))
      frame = selected_frame;
    CHECK_LIVE_FRAME (frame);
    f = XFRAME (frame);
  
 -  /* Recode realized fontsets whose base is FONTSET in the table
 -     `realized'.  */
 -  realized = (Lisp_Object *) alloca (sizeof (Lisp_Object)
 -                                   * ASIZE (Vfontset_table));
 -  for (i = 0; i < ASIZE (Vfontset_table); i++)
 +  /* Recode fontsets realized on FRAME from the base fontset FONTSET
 +     in the table `realized'.  */
 +  realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
 +                                      * ASIZE (Vfontset_table));
 +  for (i = j = 0; i < ASIZE (Vfontset_table); i++)
      {
        elt = FONTSET_FROM_ID (i);
        if (!NILP (elt)
 -        && EQ (FONTSET_BASE (elt), fontset))
 -      realized[n_realized++] = elt;
 +        && EQ (FONTSET_BASE (elt), fontset)
 +        && EQ (FONTSET_FRAME (elt), frame))
 +      realized[0][j++] = elt;
      }
 +  realized[0][j] = Qnil;
  
 -  if (! EQ (fontset, Vdefault_fontset))
 +  realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
 +                                      * ASIZE (Vfontset_table));
 +  for (i = j = 0; ! NILP (realized[0][i]); i++)
      {
 -      /* Merge FONTSET onto the default fontset.  */
 -      val = Fcopy_sequence (Vdefault_fontset);
 -      map_char_table (override_font_info, Qnil, fontset, fontset, val, 0, indices);
 -      fontset = val;
 +      elt = FONTSET_DEFAULT (realized[0][i]);
 +      if (! NILP (elt))
 +      realized[1][j++] = elt;
      }
 +  realized[1][j] = Qnil;
  
 -  /* Accumulate information of the fontset in VAL.  The format is
 -     (LAST FONT-INFO FONT-INFO ...), where FONT-INFO is (CHAR-OR-RANGE
 -     FONT-SPEC).  See the comment for accumulate_font_info for the
 -     detail.  */
 -  val = Fcons (Fcons (make_number (0),
 -                    Fcons (XCDR (FONTSET_ASCII (fontset)), Qnil)),
 -             Qnil);
 -  val = Fcons (val, val);
 -  map_char_table (accumulate_font_info, Qnil, fontset, fontset, val, 0, indices);
 -  val = XCDR (val);
 -
 -  /* For each FONT-INFO, if CHAR_OR_RANGE (car part) is a generic
 -     character for a charset, replace it with the charset symbol.  If
 -     fonts are opened for FONT-SPEC, append the names of the fonts to
 -     FONT-SPEC.  */
 -  for (tail = val; CONSP (tail); tail = XCDR (tail))
 +  tables[0] = Fmake_char_table (Qfontset_info, Qnil);
 +  tables[1] = Fmake_char_table (Qnil, Qnil);
 +  XCHAR_TABLE (tables[0])->extras[0] = tables[1];
 +  fontsets[0] = fontset;
 +  fontsets[1] = Vdefault_fontset;
 +
 +  /* Accumulate information of the fontset in TABLE.  The format of
 +     each element is ((FONT-SPEC OPENED-FONT ...) ...).  */
 +  for (k = 0; k <= 1; k++)
      {
 -      int c;
 -      elt = XCAR (tail);
 -      if (INTEGERP (XCAR (elt)))
 +      for (c = 0; c <= MAX_CHAR; )
        {
 -        int charset, c1, c2;
 -        c = XINT (XCAR (elt));
 -        SPLIT_CHAR (c, charset, c1, c2);
 -        if (c1 == 0)
 -          XSETCAR (elt, CHARSET_SYMBOL (charset));
 -      }
 -      else
 -      c = XINT (XCAR (XCAR (elt)));
 -      for (i = 0; i < n_realized; i++)
 -      {
 -        Lisp_Object face_id, font;
 -        struct face *face;
 +        int from, to;
  
 -        face_id = FONTSET_REF_VIA_BASE (realized[i], c);
 -        if (INTEGERP (face_id))
 +        if (c <= MAX_5_BYTE_CHAR)
 +          {
 +            val = char_table_ref_and_range (fontsets[k], c, &from, &to);
 +            if (to > MAX_5_BYTE_CHAR)
 +              to = MAX_5_BYTE_CHAR;
 +          }
 +        else
 +          {
 +            val = FONTSET_FALLBACK (fontsets[k]);
 +            to = MAX_CHAR;
 +          }
 +        if (VECTORP (val))
            {
 -            face = FACE_FROM_ID (f, XINT (face_id));
 -            if (face && face->font && face->font_name)
 +            Lisp_Object alist;
 +
 +            /* At first, set ALIST to ((FONT-SPEC) ...).  */
 +            for (alist = Qnil, i = 0; i < ASIZE (val); i++)
 +              alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
 +            alist = Fnreverse (alist);
 +
 +            /* Then store opend font names to cdr of each elements.  */
 +            for (i = 0; ! NILP (realized[k][i]); i++)
                {
 -                font = build_string (face->font_name);
 -                if (NILP (Fmember (font, XCDR (XCDR (elt)))))
 -                  XSETCDR (XCDR (elt), Fcons (font, XCDR (XCDR (elt))));
 +                if (c <= MAX_5_BYTE_CHAR)
 +                  val = FONTSET_REF (realized[k][i], c);
 +                else
 +                  val = FONTSET_FALLBACK (realized[k][i]);
 +                if (! VECTORP (val))
 +                  continue;
 +                /* VAL is [int int ?
 +                           [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
 +                   If a font of an element is already opened,
 +                   FONT-NAME is the name of a opened font.  */
 +                for (j = 3; j < ASIZE (val); j++)
 +                  if (STRINGP (AREF (AREF (val, j), 3)))
 +                    {
 +                      Lisp_Object font_idx;
 +
 +                      font_idx = AREF (AREF (val, j), 1);
 +                      elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
 +                      if (CONSP (elt)
 +                          && NILP (Fmemq (font_idx, XCDR(elt))))
 +                        nconc2 (elt, Fcons (font_idx, Qnil));
 +                    }
                }
 +            for (val = alist; CONSP (val); val = XCDR (val))
 +              for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
 +                {
 +                  struct font_info *font_info
 +                    = (*get_font_info_func) (f, XINT (XCAR (elt)));
 +                  XSETCAR (elt, build_string (font_info->full_name));
 +                }
 +
 +            /* Store ALIST in TBL for characters C..TO.  */
 +            if (c <= MAX_5_BYTE_CHAR)
 +              char_table_set_range (tables[k], c, to, alist);
 +            else
 +              XCHAR_TABLE (tables[k])->defalt = alist;
            }
 +        c = to + 1;
        }
      }
  
 -  elt = Fcdr (Fcdr (Fassq (CHARSET_SYMBOL (CHARSET_ASCII), val)));
 -  if (CONSP (elt))
 -    {
 -      elt = XCAR (elt);
 -      fontp = (*query_font_func) (f, SDATA (elt));
 -    }
 -  val = Fmake_vector (make_number (3), val);
 -  AREF (val, 0) = fontp ? make_number (fontp->size) : make_number (0);
 -  AREF (val, 1) = fontp ? make_number (fontp->height) : make_number (0);
 -  return val;
 +  return tables[0];
  }
  
 -DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 2, 0,
 +
 +DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
         doc: /* Return a font name pattern for character CH in fontset NAME.
 -If NAME is nil, find a font name pattern in the default fontset.  */)
 -     (name, ch)
 -     Lisp_Object name, ch;
 +If NAME is t, find a pattern in the default fontset.
 +
 +The value has the form (FAMILY . REGISTRY), where FAMILY is a font
 +family name and REGISTRY is a font registry name.  This is actually
 +the first font name pattern for CH in the fontset or in the default
 +fontset.
 +
 +If the 2nd optional arg ALL is non-nil, return a list of all font name
 +patterns.  */)
 +  (name, ch, all)
 +     Lisp_Object name, ch, all;
  {
    int c;
 -  Lisp_Object fontset, elt;
 +  Lisp_Object fontset, elt, list, repertory, val;
 +  int i, j;
  
    fontset = check_fontset_name (name);
  
 -  CHECK_NUMBER (ch);
 +  CHECK_CHARACTER (ch);
    c = XINT (ch);
 -  if (!char_valid_p (c, 1))
 -    invalid_character (c);
 -
 -  elt = FONTSET_REF (fontset, c);
 -  if (CONSP (elt))
 -    elt = XCDR (elt);
 +  list = Qnil;
 +  while (1)
 +    {
 +      for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
 +         i++, elt = FONTSET_FALLBACK (fontset))
 +      if (VECTORP (elt))
 +        for (j = 0; j < ASIZE (elt); j++)
 +          {
 +            val = AREF (elt, j);
 +            repertory = AREF (val, 1);
 +            if (INTEGERP (repertory))
 +              {
 +                struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
  
 -  return elt;
 +                if (! CHAR_CHARSET_P (c, charset))
 +                  continue;
 +              }
 +            else if (CHAR_TABLE_P (repertory))
 +              {
 +                if (NILP (CHAR_TABLE_REF (repertory, c)))
 +                  continue;
 +              }
 +            val = AREF (val, 0);
 +            val = Fcons (AREF (val, 0), AREF (val, 5));
 +            if (NILP (all))
 +              return val;
 +            list = Fcons (val, list);
 +          }
 +      if (EQ (fontset, Vdefault_fontset))
 +      break;
 +      fontset = Vdefault_fontset;
 +    }
 +  return (Fnreverse (list));
  }
  
  DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
    return list;
  }
  
 -DEFUN ("set-overriding-fontspec-internal", Fset_overriding_fontspec_internal,
 -       Sset_overriding_fontspec_internal, 1, 1, 0,
 -       doc: /* Internal use only.
 -
 -FONTLIST is an alist of TARGET vs FONTNAME, where TARGET is a charset
 -or a char-table, FONTNAME have the same meanings as in
 -`set-fontset-font'.
  
 -It overrides the font specifications for each TARGET in the default
 -fontset by the corresponding FONTNAME.
 -
 -If TARGET is a charset, targets are all characters in the charset.  If
 -TARGET is a char-table, targets are characters whose value is non-nil
 -in the table.
 +#ifdef FONTSET_DEBUG
  
 -It is intended that this function is called only from
 -`set-language-environment'.  */)
 -     (fontlist)
 -     Lisp_Object fontlist;
 +Lisp_Object
 +dump_fontset (fontset)
 +     Lisp_Object fontset;
  {
 -  Lisp_Object tail;
 +  Lisp_Object vec;
  
 -  fontlist = Fcopy_sequence (fontlist);
 -  /* Now FONTLIST is ((TARGET . FONTNAME) ...).  Reform it to ((TARGET
 -     nil nil nil FONTSPEC) ...), where TARGET is a charset-id or a
 -     char-table.  */
 -  for (tail = fontlist; CONSP (tail); tail = XCDR (tail))
 +  vec = Fmake_vector (make_number (3), Qnil);
 +  ASET (vec, 0, FONTSET_ID (fontset));
 +
 +  if (BASE_FONTSET_P (fontset))
 +    {
 +      ASET (vec, 1, FONTSET_NAME (fontset));
 +    }
 +  else
      {
 -      Lisp_Object elt, target;
 +      Lisp_Object frame;
  
 -      elt = XCAR (tail);
 -      target = Fcar (elt);
 -      elt = Fcons (Qnil, regularize_fontname (Fcdr (elt)));
 -      if (! CHAR_TABLE_P (target))
 +      frame = FONTSET_FRAME (fontset);
 +      if (FRAMEP (frame))
        {
 -        int charset, c;
 -
 -        CHECK_SYMBOL (target);
 -        charset = get_charset_id (target);
 -        if (charset < 0)
 -          error ("Invalid charset %s", SDATA (SYMBOL_NAME (target)));
 -        target = make_number (charset);
 -        c = MAKE_CHAR (charset, 0, 0);
 -        XSETCAR (elt, make_number (c));
 +        FRAME_PTR f = XFRAME (frame);
 +
 +        if (FRAME_LIVE_P (f))
 +          ASET (vec, 1,
 +                Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
 +        else
 +          ASET (vec, 1,
 +                Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
        }
 -      elt = Fcons (target, Fcons (Qnil, Fcons (Qnil, elt)));
 -      XSETCAR (tail, elt);
 +      if (!NILP (FONTSET_DEFAULT (fontset)))
 +      ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
      }
 -  if (! NILP (Fequal (fontlist, Voverriding_fontspec_alist)))
 -    return Qnil;
 -  Voverriding_fontspec_alist = fontlist;
 -  clear_face_cache (0);
 -  ++windows_or_buffers_changed;
 -  return Qnil;
 +  return vec;
 +}
 +
 +DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
 +       doc: /* Return a brief summary of all fontsets for debug use.  */)
 +     ()
 +{
 +  Lisp_Object val;
 +  int i;
 +
 +  for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
 +    if (! NILP (AREF (Vfontset_table, i)))
 +      val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
 +  return (Fnreverse (val));
  }
 +#endif        /* FONTSET_DEBUG */
  
  void
  syms_of_fontset ()
      /* Window system initializer should have set proper functions.  */
      abort ();
  
 -  Qfontset = intern ("fontset");
 -  staticpro (&Qfontset);
 -  Fput (Qfontset, Qchar_table_extra_slots, make_number (3));
 +  DEFSYM (Qfontset, "fontset");
 +  Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
 +  DEFSYM (Qfontset_info, "fontset-info");
 +  Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
 +
 +  DEFSYM (Qprepend, "prepend");
 +  DEFSYM (Qappend, "append");
 +  DEFSYM (Qlatin, "latin");
  
    Vcached_fontset_data = Qnil;
    staticpro (&Vcached_fontset_data);
    AREF (Vfontset_table, 0) = Vdefault_fontset;
    next_fontset_id = 1;
  
 -  Voverriding_fontspec_alist = Qnil;
 -  staticpro (&Voverriding_fontspec_alist);
 +  auto_fontset_alist = Qnil;
 +  staticpro (&auto_fontset_alist);
  
    DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
 -             doc: /* Alist of fontname patterns vs corresponding encoding info.
 -Each element looks like (REGEXP . ENCODING-INFO),
 - where ENCODING-INFO is an alist of CHARSET vs ENCODING.
 -ENCODING is one of the following integer values:
 -      0: code points 0x20..0x7F or 0x2020..0x7F7F are used,
 -      1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,
 -      2: code points 0x20A0..0x7FFF are used,
 -      3: code points 0xA020..0xFF7F are used.  */);
 +             doc: /*
 +Alist of fontname patterns vs the corresponding encoding and repertory info.
 +Each element looks like (REGEXP . (ENCODING . REPERTORY)),
 +where ENCODING is a charset or a char-table,
 +and REPERTORY is a charset, a char-table, or nil.
 +
 +ENCODING is for converting a character to a glyph code of the font.
 +If ENCODING is a charset, encoding a character by the charset gives
 +the corresponding glyph code.  If ENCODING is a char-table, looking up
 +the table by a character gives the corresponding glyph code.
 +
 +REPERTORY specifies a repertory of characters supported by the font.
 +If REPERTORY is a charset, all characters beloging to the charset are
 +supported.  If REPERTORY is a char-table, all characters who have a
 +non-nil value in the table are supported.  It REPERTORY is nil, Emacs
 +gets the repertory information by an opened font and ENCODING.  */);
    Vfont_encoding_alist = Qnil;
 -  Vfont_encoding_alist
 -    = Fcons (Fcons (build_string ("JISX0201"),
 -                  Fcons (Fcons (intern ("latin-jisx0201"), make_number (0)),
 -                         Qnil)),
 -           Vfont_encoding_alist);
 -  Vfont_encoding_alist
 -    = Fcons (Fcons (build_string ("ISO8859-1"),
 -                  Fcons (Fcons (intern ("ascii"), make_number (0)),
 -                         Qnil)),
 -           Vfont_encoding_alist);
  
    DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
 -             doc: /* Char table of characters whose ascent values should be ignored.
 +             doc: /*
 +Char table of characters whose ascent values should be ignored.
  If an entry for a character is non-nil, the ascent value of the glyph
  is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
  
@@@ -2483,8 -1683,7 +2474,8 @@@ such a character is displayed on screen
    Vuse_default_ascent = Qnil;
  
    DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
 -             doc: /* Char table of characters which is not composed relatively.
 +             doc: /*
 +Char table of characters which is not composed relatively.
  If an entry for a character is non-nil, a composition sequence
  which contains that character is displayed so that
  the glyph of that character is put without considering
@@@ -2510,10 -1709,6 +2501,10 @@@ When a character is displayed with suc
  at the vertical center of lines.  */);
    Vvertical_centering_font_regexp = Qnil;
  
 +  DEFVAR_LISP ("otf-script-alist", &Votf_script_alist,
 +             doc: /* Alist of OpenType script tags vs the corresponding script names.  */);
 +  Votf_script_alist = Qnil;
 +
    defsubr (&Squery_fontset);
    defsubr (&Snew_fontset);
    defsubr (&Sset_fontset_font);
    defsubr (&Sfontset_info);
    defsubr (&Sfontset_font);
    defsubr (&Sfontset_list);
 -  defsubr (&Sset_overriding_fontspec_internal);
 +#ifdef FONTSET_DEBUG
 +  defsubr (&Sfontset_list_all);
 +#endif
  }
  
  /* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
diff --combined src/frame.c
index 5f4e12cd705bd538cf5f191abc55e052f102ae48,ff860d83509286abaa970a0e44a262a60af796ca..389a94ae3e842afe7688e08176f529c6ab957ac9
@@@ -23,7 -23,7 +23,7 @@@ Boston, MA 02110-1301, USA.  *
  
  #include <stdio.h>
  #include "lisp.h"
 -#include "charset.h"
 +#include "character.h"
  #ifdef HAVE_X_WINDOWS
  #include "xterm.h"
  #endif
  
  #ifdef HAVE_WINDOW_SYSTEM
  
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +
  /* The name we're using in resource queries.  Most often "emacs".  */
  
  Lisp_Object Vx_resource_name;
@@@ -107,6 -103,7 +107,7 @@@ Lisp_Object Qouter_window_id
  #endif
  Lisp_Object Qparent_id;
  Lisp_Object Qtitle, Qname;
+ Lisp_Object Qexplicit_name;
  Lisp_Object Qunsplittable;
  Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
  Lisp_Object Qleft_fringe, Qright_fringe;
@@@ -116,9 -113,6 +117,9 @@@ Lisp_Object Qtty, Qtty_type
  Lisp_Object Qwindow_system;
  
  Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 +#ifdef USE_FONT_BACKEND
 +Lisp_Object Qfont_backend;
 +#endif        /* USE_FONT_BACKEND */
  
  Lisp_Object Qinhibit_face_set_after_frame_default;
  Lisp_Object Qface_set_after_frame_default;
@@@ -333,9 -327,6 +334,9 @@@ make_frame (mini_p
  #endif
    f->size_hint_flags = 0;
    f->win_gravity = 0;
 +#ifdef USE_FONT_BACKEND
 +  f->font_driver_list = NULL;
 +#endif        /* USE_FONT_BACKEND */
  
    root_window = make_window ();
    if (mini_p)
@@@ -2213,7 -2204,7 +2214,7 @@@ store_in_alist (alistptr, prop, val
  static int
  frame_name_fnn_p (str, len)
       char *str;
 -     int len;
 +     EMACS_INT len;
  {
    if (len > 1 && str[0] == 'F')
      {
@@@ -2855,9 -2846,6 +2856,9 @@@ static struct frame_parm_table frame_pa
    {"right-fringe",            &Qright_fringe},
    {"wait-for-wm",             &Qwait_for_wm},
    {"fullscreen",                &Qfullscreen},
 +#ifdef USE_FONT_BACKEND
 +  {"font-backend",            &Qfont_backend}
 +#endif        /* USE_FONT_BACKEND */
  };
  
  #ifdef HAVE_WINDOW_SYSTEM
@@@ -3281,6 -3269,7 +3282,7 @@@ x_report_frame_params (f, alistptr
      tem = Qnil;
    else
      XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
+   store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
    store_in_alist (alistptr, Qparent_id, tem);
  }
  
@@@ -3371,60 -3360,20 +3373,60 @@@ x_set_font (f, arg, oldval
    Lisp_Object frame;
    int old_fontset = FRAME_FONTSET(f);
  
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      int fontset = -1;
 +      Lisp_Object font_object;
 +
 +      /* ARG is a fontset name, a font name, or a font object.
 +       In the last case, this function never fail.  */
 +      if (STRINGP (arg))
 +      {
 +        fontset = fs_query_fontset (arg, 0);
 +        if (fontset < 0)
 +          font_object = font_open_by_name (f, SDATA (arg));
 +        else if (fontset > 0)
 +          {
 +            Lisp_Object ascii_font = fontset_ascii (fontset);
 +
 +            font_object = font_open_by_name (f, SDATA (ascii_font));
 +          }
 +      }
 +      else
 +      font_object = arg;
 +
 +      if (fontset < 0 && ! NILP (font_object))
 +      fontset = new_fontset_from_font (font_object);
 +
 +      if (fontset == 0)
 +      /* Refuse the default fontset.  */
 +      result = Qt;
 +      else if (NILP (font_object))
 +      result = Qnil;
 +      else
 +      result = x_new_fontset2 (f, fontset, font_object);
 +    }
 +  else
 +    {
 +#endif        /* USE_FONT_BACKEND */
    CHECK_STRING (arg);
  
    fontset_name = Fquery_fontset (arg, Qnil);
  
    BLOCK_INPUT;
    result = (STRINGP (fontset_name)
 -            ? x_new_fontset (f, SDATA (fontset_name))
 -            : x_new_font (f, SDATA (arg)));
 +            ? x_new_fontset (f, fontset_name)
 +            : x_new_fontset (f, arg));
    UNBLOCK_INPUT;
 +#ifdef USE_FONT_BACKEND
 +    }
 +#endif
  
    if (EQ (result, Qnil))
      error ("Font `%s' is not defined", SDATA (arg));
    else if (EQ (result, Qt))
 -    error ("The characters of the given font have varying widths");
 +    error ("The default fontset can't be used for a frame font");
    else if (STRINGP (result))
      {
        set_default_ascii_font (result);
          if (old_fontset == FRAME_FONTSET (f))
            return;
        }
 -      else if (!NILP (Fequal (result, oldval)))
 +      store_frame_param (f, Qfont, result);
 +
 +      if (!NILP (Fequal (result, oldval)))
          return;
  
        /* Recalculate toolbar height.  */
        /* Ensure we redraw it.  */
        clear_current_matrices (f);
  
 -      store_frame_param (f, Qfont, result);
        recompute_basic_faces (f);
      }
    else
  }
  
  
 +#ifdef USE_FONT_BACKEND
 +void
 +x_set_font_backend (f, new_value, old_value)
 +     struct frame *f;
 +     Lisp_Object new_value, old_value;
 +{
 +  if (! NILP (new_value)
 +      && !CONSP (new_value))
 +    {
 +      char *p0, *p1;
 +      
 +      CHECK_STRING (new_value);
 +      p0 = p1 = SDATA (new_value);
 +      new_value = Qnil;
 +      while (*p0)
 +      {
 +        while (*p1 && *p1 != ',') p1++;
 +        if (p0 < p1)
 +          new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
 +                             new_value);
 +        if (*p1)
 +          p1++;
 +        p0 = p1;
 +      }
 +      new_value = Fnreverse (new_value);
 +    }
 +
 +  if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
 +    return;
 +
 +  if (FRAME_FONT_OBJECT (f))
 +    {
 +      free_all_realized_faces (Qnil);
 +      Fclear_font_cache ();
 +    }
 +
 +  new_value = font_update_drivers (f, new_value);
 +  if (NILP (new_value))
 +    error ("No font backend available");
 +  store_frame_param (f, Qfont_backend, new_value);
 +
 +  if (FRAME_FONT_OBJECT (f))
 +    {
 +      Lisp_Object frame;
 +
 +      XSETFRAME (frame, f);
 +      x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
 +      ++face_change_count;
 +      ++windows_or_buffers_changed;
 +    }
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
 +
  void
  x_set_fringe_width (f, new_value, old_value)
       struct frame *f;
@@@ -4337,6 -4231,8 +4339,8 @@@ syms_of_frame (
    staticpro (&Qframep);
    Qframe_live_p = intern ("frame-live-p");
    staticpro (&Qframe_live_p);
+   Qexplicit_name = intern ("explicit-name");
+   staticpro (&Qexplicit_name);
    Qheight = intern ("height");
    staticpro (&Qheight);
    Qicon = intern ("icon");
diff --combined src/intervals.c
index 74269c7d40664e19ebd4bd1b8f46edce1161f61d,639abcf349181497421330a7fbd00bf8a37436e3..1190ad11cea0d30eb9890c696693d3c48ca1db50
@@@ -427,7 -427,7 +427,7 @@@ balance_an_interval (i
          /* Since the left child is longer, there must be one.  */
          new_diff = i->total_length - i->left->total_length
            + RIGHT_TOTAL_LENGTH (i->left) - LEFT_TOTAL_LENGTH (i->left);
-         if (abs (new_diff) >= old_diff)
+         if (eabs (new_diff) >= old_diff)
            break;
          i = rotate_right (i);
          balance_an_interval (i->right);
          /* Since the right child is longer, there must be one.  */
          new_diff = i->total_length - i->right->total_length
            + LEFT_TOTAL_LENGTH (i->right) - RIGHT_TOTAL_LENGTH (i->right);
-         if (abs (new_diff) >= -old_diff)
+         if (eabs (new_diff) >= -old_diff)
            break;
          i = rotate_left (i);
          balance_an_interval (i->left);
@@@ -2316,7 -2316,7 +2316,7 @@@ in
  get_property_and_range (pos, prop, val, start, end, object)
       int pos;
       Lisp_Object prop, *val;
 -     int *start, *end;
 +     EMACS_INT *start, *end;
       Lisp_Object object;
  {
    INTERVAL i, prev, next;
diff --combined src/keyboard.c
index d64091db5067cc37e3ab276a5fddc465ff5a6f00,bd8263f9b040dff05dae300a7899dbb955e06f2b..6d6ba6e0cc0e67d19920106d931ca3c2616bced1
@@@ -33,7 -33,7 +33,7 @@@ Boston, MA 02110-1301, USA.  *
  #include "window.h"
  #include "commands.h"
  #include "buffer.h"
 -#include "charset.h"
 +#include "character.h"
  #include "disptab.h"
  #include "dispextern.h"
  #include "syntax.h"
@@@ -160,14 -160,7 +160,7 @@@ int raw_keybuf_count
  
  #define GROW_RAW_KEYBUF                                                       \
   if (raw_keybuf_count == XVECTOR (raw_keybuf)->size)                  \
-   {                                                                   \
-     int newsize = 2 * XVECTOR (raw_keybuf)->size;                     \
-     Lisp_Object new;                                                  \
-     new = Fmake_vector (make_number (newsize), Qnil);                 \
-     bcopy (XVECTOR (raw_keybuf)->contents, XVECTOR (new)->contents,   \
-          raw_keybuf_count * sizeof (Lisp_Object));                    \
-     raw_keybuf = new;                                                 \
-   }
+    raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
  
  /* Number of elements of this_command_keys
     that precede this key sequence.  */
@@@ -1824,7 -1817,7 +1817,7 @@@ command_loop_1 (
                          : (lose >= 0x20 && lose < 0x7f))
                      /* To extract the case of continuation on
                           wide-column characters.  */
 -                    && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT_BYTE)) == 1)
 +                    && ASCII_BYTE_P (lose)
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
                {
                  unsigned int c
                    = translate_char (Vtranslation_table_for_input,
 -                                    XFASTINT (last_command_char), 0, 0, 0);
 +                                    XFASTINT (last_command_char));
                  int value;
                  if (NILP (Vexecuting_kbd_macro)
                      && !EQ (minibuf_window, selected_window))
@@@ -2060,7 -2053,7 +2053,7 @@@ adjust_point_for_property (last_pt, mod
       int last_pt;
       int modified;
  {
 -  int beg, end;
 +  EMACS_INT beg, end;
    Lisp_Object val, overlay, tmp;
    int check_composition = 1, check_display = 1, check_invisible = 1;
    int orig_pt = PT;
@@@ -3221,7 -3214,7 +3214,7 @@@ read_char (commandflag, nmaps, maps, pr
          || (VECTORP (current_kboard->Vkeyboard_translate_table)
              && XVECTOR (current_kboard->Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
          || (CHAR_TABLE_P (current_kboard->Vkeyboard_translate_table)
 -            && CHAR_VALID_P (XINT (c), 0)))
 +            && CHARACTERP (c)))
        {
          Lisp_Object d;
          d = Faref (current_kboard->Vkeyboard_translate_table, c);
@@@ -5714,8 -5707,8 +5707,8 @@@ make_lispy_event (event
            fuzz = double_click_fuzz / 8;
  
          is_double = (button == last_mouse_button
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
            fuzz = double_click_fuzz / 8;
  
          is_double = (last_mouse_button < 0
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
@@@ -7598,13 -7591,7 +7591,7 @@@ menu_bar_items (old
    /* Add nil, nil, nil, nil at the end.  */
    i = menu_bar_items_index;
    if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-     {
-       Lisp_Object tem;
-       tem = Fmake_vector (make_number (2 * i), Qnil);
-       bcopy (XVECTOR (menu_bar_items_vector)->contents,
-            XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-       menu_bar_items_vector = tem;
-     }
+     menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
    /* Add this item.  */
    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
@@@ -7676,14 -7663,7 +7663,7 @@@ menu_bar_item (key, item, dummy1, dummy
      {
        /* If vector is too small, get a bigger one.  */
        if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-       {
-         Lisp_Object tem;
-         tem = Fmake_vector (make_number (2 * i), Qnil);
-         bcopy (XVECTOR (menu_bar_items_vector)->contents,
-                XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-         menu_bar_items_vector = tem;
-       }
+       menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
        /* Add this item.  */
        XVECTOR (menu_bar_items_vector)->contents[i++] = key;
        XVECTOR (menu_bar_items_vector)->contents[i++]
@@@ -8452,16 -8432,9 +8432,9 @@@ append_tool_bar_item (
    /* Enlarge tool_bar_items_vector if necessary.  */
    if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
        >= XVECTOR (tool_bar_items_vector)->size)
-     {
-       Lisp_Object new_vector;
-       int old_size = XVECTOR (tool_bar_items_vector)->size;
-       new_vector = Fmake_vector (make_number (2 * old_size), Qnil);
-       bcopy (XVECTOR (tool_bar_items_vector)->contents,
-            XVECTOR (new_vector)->contents,
-            old_size * sizeof (Lisp_Object));
-       tool_bar_items_vector = new_vector;
-     }
+     tool_bar_items_vector
+       = larger_vector (tool_bar_items_vector,
+                      2 * XVECTOR (tool_bar_items_vector)->size, Qnil);
  
    /* Append entries from tool_bar_item_properties to the end of
       tool_bar_items_vector.  */
@@@ -10033,8 -10006,9 +10006,8 @@@ read_key_sequence (keybuf, bufsize, pro
        if (first_binding >= nmaps
          && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
          && INTEGERP (key)
 -        && ((((XINT (key) & 0x3ffff)
 -              < XCHAR_TABLE (current_buffer->downcase_table)->size)
 -             && UPPERCASEP (XINT (key) & 0x3ffff))
 +        && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
 +             && UPPERCASEP (XINT (key) & ~CHAR_MODIFIER_MASK))
              || (XINT (key) & shift_modifier)))
        {
          Lisp_Object new_key;
          if (XINT (key) & shift_modifier)
            XSETINT (new_key, XINT (key) & ~shift_modifier);
          else
 -          XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff)
 -                             | (XINT (key) & ~0x3ffff)));
 +          XSETINT (new_key, (DOWNCASE (XINT (key) & ~CHAR_MODIFIER_MASK)
 +                             | (XINT (key) & ~CHAR_MODIFIER_MASK)));
  
          /* We have to do this unconditionally, regardless of whether
             the lower-case char is defined in the keymaps, because they
diff --combined src/lisp.h
index 50750af3c4f497decd649558927d2920ce9d0e08,70329a077645aa2ae35534ef867f254273705b2d..231cfcc73790839bcef525a5f5828e600466d49b
@@@ -335,8 -335,7 +335,8 @@@ enum pvec_typ
    PVEC_BUFFER = 0x20000,
    PVEC_HASH_TABLE = 0x40000,
    PVEC_TERMINAL = 0x80000,
 -  PVEC_TYPE_MASK = 0xffe00
 +  PVEC_SUB_CHAR_TABLE = 0x100000,
 +  PVEC_TYPE_MASK = 0x1ffe00
  
  #if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
         GDB.  It doesn't work on OS Alpha.  Moved to a variable in
@@@ -462,6 -461,17 +462,6 @@@ extern Lisp_Object make_number P_ ((EMA
  
  #define EQ(x, y) (XHASH (x) == XHASH (y))
  
 -/* During garbage collection, XGCTYPE must be used for extracting types
 - so that the mark bit is ignored.  XMARKBIT accesses the markbit.
 - Markbits are used only in particular slots of particular structure types.
 - Other markbits are always zero.
 - Outside of garbage collection, all mark bits are always zero.  */
 -
 -#ifndef XGCTYPE
 -/* The distinction does not exist now that the MARKBIT has been eliminated.  */
 -#define XGCTYPE(a) XTYPE (a)
 -#endif
 -
  #ifndef XPNTR
  #ifdef HAVE_SHM
  /* In this representation, data is found in two widely separated segments.  */
@@@ -503,11 -513,11 +503,11 @@@ extern size_t pure_size
  
  /* Extract a value or address from a Lisp_Object.  */
  
 -#define XCONS(a) (eassert (GC_CONSP(a)),(struct Lisp_Cons *) XPNTR(a))
 -#define XVECTOR(a) (eassert (GC_VECTORLIKEP(a)),(struct Lisp_Vector *) XPNTR(a))
 -#define XSTRING(a) (eassert (GC_STRINGP(a)),(struct Lisp_String *) XPNTR(a))
 -#define XSYMBOL(a) (eassert (GC_SYMBOLP(a)),(struct Lisp_Symbol *) XPNTR(a))
 -#define XFLOAT(a) (eassert (GC_FLOATP(a)),(struct Lisp_Float *) XPNTR(a))
 +#define XCONS(a) (eassert (CONSP(a)),(struct Lisp_Cons *) XPNTR(a))
 +#define XVECTOR(a) (eassert (VECTORLIKEP(a)),(struct Lisp_Vector *) XPNTR(a))
 +#define XSTRING(a) (eassert (STRINGP(a)),(struct Lisp_String *) XPNTR(a))
 +#define XSYMBOL(a) (eassert (SYMBOLP(a)),(struct Lisp_Symbol *) XPNTR(a))
 +#define XFLOAT(a) (eassert (FLOATP(a)),(struct Lisp_Float *) XPNTR(a))
  
  /* Misc types.  */
  
  
  /* Pseudovector types.  */
  
 -#define XPROCESS(a) (eassert (GC_PROCESSP(a)),(struct Lisp_Process *) XPNTR(a))
 -#define XWINDOW(a) (eassert (GC_WINDOWP(a)),(struct window *) XPNTR(a))
 -#define XTERMINAL(a) (eassert (GC_TERMINALP(a)),(struct terminal *) XPNTR(a))
 -#define XSUBR(a) (eassert (GC_SUBRP(a)),(struct Lisp_Subr *) XPNTR(a))
 -#define XBUFFER(a) (eassert (GC_BUFFERP(a)),(struct buffer *) XPNTR(a))
 -#define XCHAR_TABLE(a) (eassert (GC_CHAR_TABLE_P (a)), (struct Lisp_Char_Table *) XPNTR(a))
 -#define XBOOL_VECTOR(a) (eassert (GC_BOOL_VECTOR_P (a)), (struct Lisp_Bool_Vector *) XPNTR(a))
 +#define XPROCESS(a) (eassert (PROCESSP(a)),(struct Lisp_Process *) XPNTR(a))
 +#define XWINDOW(a) (eassert (WINDOWP(a)),(struct window *) XPNTR(a))
 +#define XTERMINAL(a) (eassert (TERMINALP(a)),(struct terminal *) XPNTR(a))
 +#define XSUBR(a) (eassert (SUBRP(a)),(struct Lisp_Subr *) XPNTR(a))
 +#define XBUFFER(a) (eassert (BUFFERP(a)),(struct buffer *) XPNTR(a))
 +#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), (struct Lisp_Char_Table *) XPNTR(a))
 +#define XSUB_CHAR_TABLE(a) (eassert (SUB_CHAR_TABLE_P (a)), (struct Lisp_Sub_Char_Table *) XPNTR(a))
 +#define XBOOL_VECTOR(a) (eassert (BOOL_VECTOR_P (a)), (struct Lisp_Bool_Vector *) XPNTR(a))
  
  /* Construct a Lisp_Object from a value or address.  */
  
  #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
  #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
  #define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
 +#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
  
  /* Convenience macros for dealing with Lisp arrays.  */
  
@@@ -746,20 -754,49 +746,20 @@@ struct Lisp_Vecto
    ((OFFSETOF(type, nonlispfield) - OFFSETOF(struct Lisp_Vector, contents[0])) \
     / sizeof (Lisp_Object))
  
 -/* A char table is a kind of vectorlike, with contents are like a
 +/* A char-table is a kind of vectorlike, with contents are like a
     vector but with a few other slots.  For some purposes, it makes
 -   sense to handle a chartable with type struct Lisp_Vector.  An
 +   sense to handle a char-table with type struct Lisp_Vector.  An
     element of a char table can be any Lisp objects, but if it is a sub
     char-table, we treat it a table that contains information of a
 -   group of characters of the same charsets or a specific character of
 -   a charset.  A sub char-table has the same structure as a char table
 -   except for that the former omits several slots at the tail.  A sub
 -   char table appears only in an element of a char table, and there's
 -   no way to access it directly from Emacs Lisp program.  */
 -
 -/* This is the number of slots that apply to characters or character
 -   sets.  The first 128 are for ASCII, the next 128 are for 8-bit
 -   European characters, and the last 128 are for multibyte characters.
 -   The first 256 are indexed by the code itself, but the last 128 are
 -   indexed by (charset-id + 128).  */
 -#define CHAR_TABLE_ORDINARY_SLOTS 384
 -
 -/* These are the slot of the default values for single byte
 -   characters.  As 0x9A is never be a charset-id, it is safe to use
 -   that slot for ASCII.  0x9E and 0x80 are charset-ids of
 -   eight-bit-control and eight-bit-graphic respectively.  */
 -#define CHAR_TABLE_DEFAULT_SLOT_ASCII (0x9A + 128)
 -#define CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL (0x9E + 128)
 -#define CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC (0x80 + 128)
 -
 -/* This is the number of slots that apply to characters of ASCII and
 -   8-bit Europeans only.  */
 -#define CHAR_TABLE_SINGLE_BYTE_SLOTS 256
 +   specific range of characters.  A sub char-table has the same
 +   structure as a vector.  A sub char table appears only in an element
 +   of a char-table, and there's no way to access it directly from
 +   Emacs Lisp program.  */
  
  /* This is the number of slots that every char table must have.  This
     counts the ordinary slots and the top, defalt, parent, and purpose
     slots.  */
 -#define CHAR_TABLE_STANDARD_SLOTS (CHAR_TABLE_ORDINARY_SLOTS + 4)
 -
 -/* This is the number of slots that apply to position-code-1 and
 -   position-code-2 of a multibyte character at the 2nd and 3rd level
 -   sub char tables respectively.  */
 -#define SUB_CHAR_TABLE_ORDINARY_SLOTS 128
 -
 -/* This is the number of slots that every sub char table must have.
 -   This counts the ordinary slots and the top and defalt slot.  */
 -#define SUB_CHAR_TABLE_STANDARD_SLOTS (SUB_CHAR_TABLE_ORDINARY_SLOTS + 2)
 +#define CHAR_TABLE_STANDARD_SLOTS (VECSIZE (struct Lisp_Char_Table) - 1)
  
  /* Return the number of "extra" slots in the char table CT.  */
  
    (((CT)->size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
  
  /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
 -   and 8-bit Europeans characters.  For these characters, do not check
 -   validity of CT.  Do not follow parent.  */
 -#define CHAR_TABLE_REF(CT, IDX)                               \
 -  ((IDX) >= 0 && (IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS \
 -   ? (!NILP (XCHAR_TABLE (CT)->contents[IDX])         \
 -      ? XCHAR_TABLE (CT)->contents[IDX]                       \
 -      : XCHAR_TABLE (CT)->defalt)                     \
 -   : Faref (CT, make_number (IDX)))
 +   characters.  Do not check validity of CT.  */
 +#define CHAR_TABLE_REF(CT, IDX)                                                \
 +  ((ASCII_CHAR_P (IDX)                                                         \
 +    && SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii)                      \
 +    && !NILP (XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX])) \
 +   ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX]          \
 +   : char_table_ref ((CT), (IDX)))
  
 -/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
 -   and 8-bit Europeans characters.  However, if the result is nil,
 -   return IDX.
 +/* Almost equivalent to Faref (CT, IDX).  However, if the result is
 +   not a character, return IDX.
  
     For these characters, do not check validity of CT
     and do not follow parent.  */
 -#define CHAR_TABLE_TRANSLATE(CT, IDX)                 \
 -  ((IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS                       \
 -   ? (!NILP (XCHAR_TABLE (CT)->contents[IDX])         \
 -      ? XINT (XCHAR_TABLE (CT)->contents[IDX])                \
 -      : IDX)                                          \
 -   : char_table_translate (CT, IDX))
 +#define CHAR_TABLE_TRANSLATE(CT, IDX) \
 +  char_table_translate (CT, IDX)
  
  /* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
 -   8-bit Europeans characters.  Do not check validity of CT.  */
 -#define CHAR_TABLE_SET(CT, IDX, VAL)                  \
 -  do {                                                        \
 -    if (XFASTINT (IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS)        \
 -      XCHAR_TABLE (CT)->contents[XFASTINT (IDX)] = VAL;       \
 -    else                                              \
 -      Faset (CT, IDX, VAL);                           \
 -  } while (0)
 +   8-bit European characters.  Do not check validity of CT.  */
 +#define CHAR_TABLE_SET(CT, IDX, VAL)                                  \
 +  (((IDX) >= 0 && ASCII_CHAR_P (IDX)                                  \
 +    && SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii))                    \
 +   ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX] = VAL   \
 +   : char_table_set (CT, IDX, VAL))
 +
 +#define CHARTAB_SIZE_BITS_0 6
 +#define CHARTAB_SIZE_BITS_1 4
 +#define CHARTAB_SIZE_BITS_2 5
 +#define CHARTAB_SIZE_BITS_3 7
 +
 +extern const int chartab_size[4];
 +
 +struct Lisp_Sub_Char_Table;
  
  struct Lisp_Char_Table
    {
      /* This is the vector's size field, which also holds the
         pseudovector type information.  It holds the size, too.
 -       The size counts the top, defalt, purpose, and parent slots.
 -       The last three are not counted if this is a sub char table.  */
 +       The size counts the defalt, parent, purpose, ascii,
 +       contents, and extras slots.  */
      EMACS_UINT size;
      struct Lisp_Vector *next;
 -    /* This holds a flag to tell if this is a top level char table (t)
 -       or a sub char table (nil).  */
 -    Lisp_Object top;
 +
      /* This holds a default value,
         which is used whenever the value for a specific character is nil.  */
      Lisp_Object defalt;
 -    /* This holds an actual value of each element.  A sub char table
 -       has only SUB_CHAR_TABLE_ORDINARY_SLOTS number of elements.  */
 -    Lisp_Object contents[CHAR_TABLE_ORDINARY_SLOTS];
  
 -    /* A sub char table doesn't has the following slots.  */
 -
 -    /* This points to another char table, which we inherit from
 -       when the value for a specific character is nil.
 -       The `defalt' slot takes precedence over this.  */
 +    /* This points to another char table, which we inherit from when the
 +       value for a specific character is nil.  The `defalt' slot takes
 +       precedence over this.  */
      Lisp_Object parent;
 -    /* This should be a symbol which says what kind of use
 -       this char-table is meant for.
 -       Typically now the values can be `syntax-table' and `display-table'.  */
 +
 +    /* This is a symbol which says what kind of use this char-table is
 +       meant for.  */
      Lisp_Object purpose;
 -    /* These hold additional data.  */
 +
 +    /* The bottom sub char-table for characters of the range 0..127.  It
 +       is nil if none of ASCII character has a specific value.  */
 +    Lisp_Object ascii;
 +
 +    Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)];
 +
 +    /* These hold additional data.  It is a vector.  */
      Lisp_Object extras[1];
    };
  
 +struct Lisp_Sub_Char_Table
 +  {
 +    /* This is the vector's size field, which also holds the
 +       pseudovector type information.  It holds the size, too.  */
 +    EMACS_INT size;
 +    struct Lisp_Vector *next;
 +
 +    /* Depth of this sub char-table.  It should be 1, 2, or 3.  A sub
 +       char-table of depth 1 contains 16 elments, and each element
 +       covers 4096 (128*32) characters.  A sub char-table of depth 2
 +       contains 32 elements, and each element covers 128 characters.  A
 +       sub char-table of depth 3 contains 128 elements, and each element
 +       is for one character.  */
 +    Lisp_Object depth;
 +
 +    /* Minimum character covered by the sub char-table.  */
 +    Lisp_Object min_char;
 +
 +    Lisp_Object contents[1];
 +  };
 +
  /* A boolvector is a kind of vectorlike, with contents are like a string.  */
  struct Lisp_Bool_Vector
    {
@@@ -1061,6 -1076,7 +1061,6 @@@ struct Lisp_Hash_Tabl
       (XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE))
  
  #define HASH_TABLE_P(OBJ)  PSEUDOVECTORP (OBJ, PVEC_HASH_TABLE)
 -#define GC_HASH_TABLE_P(x) GC_PSEUDOVECTORP (x, PVEC_HASH_TABLE)
  
  #define CHECK_HASH_TABLE(x) \
    CHECK_TYPE (HASH_TABLE_P (x), Qhash_table_p, x)
@@@ -1373,9 -1389,9 +1373,9 @@@ typedef unsigned char UCHAR
    (CHAR_ALT | CHAR_SUPER | CHAR_HYPER  | CHAR_SHIFT | CHAR_CTL | CHAR_META)
  
  
 -/* Actually, the current Emacs uses 19 bits for the character value
 +/* Actually, the current Emacs uses 22 bits for the character value
     itself.  */
 -#define CHARACTERBITS 19
 +#define CHARACTERBITS 22
  
  /* The maximum byte size consumed by push_key_description.
     All callers should assure that at least this size of memory is
  #define GLYPH int
  
  /* Mask bits for face.  */
 -#define GLYPH_MASK_FACE    0x7FF80000
 +#define GLYPH_MASK_FACE    0x7FC00000
   /* Mask bits for character code.  */
 -#define GLYPH_MASK_CHAR    0x0007FFFF /* The lowest 19 bits */
 +#define GLYPH_MASK_CHAR    0x003FFFFF /* The lowest 22 bits */
  
  /* The FAST macros assume that we already know we're in an X window.  */
  
  /* Data type checking */
  
  #define NILP(x)  EQ (x, Qnil)
 -#define GC_NILP(x) GC_EQ (x, Qnil)
  
  #define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
 -#define GC_NUMBERP(x) (GC_INTEGERP (x) || GC_FLOATP (x))
  #define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
 -#define GC_NATNUMP(x) (GC_INTEGERP (x) && XINT (x) >= 0)
  
  #define INTEGERP(x) (XTYPE ((x)) == Lisp_Int)
 -#define GC_INTEGERP(x) INTEGERP (x)
  #define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
 -#define GC_SYMBOLP(x) (XGCTYPE ((x)) == Lisp_Symbol)
  #define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
 -#define GC_MISCP(x) (XGCTYPE ((x)) == Lisp_Misc)
  #define VECTORLIKEP(x) (XTYPE ((x)) == Lisp_Vectorlike)
 -#define GC_VECTORLIKEP(x) (XGCTYPE ((x)) == Lisp_Vectorlike)
  #define STRINGP(x) (XTYPE ((x)) == Lisp_String)
 -#define GC_STRINGP(x) (XGCTYPE ((x)) == Lisp_String)
  #define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
 -#define GC_CONSP(x) (XGCTYPE ((x)) == Lisp_Cons)
  
  #define FLOATP(x) (XTYPE ((x)) == Lisp_Float)
 -#define GC_FLOATP(x) (XGCTYPE ((x)) == Lisp_Float)
 -#define VECTORP(x) (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
 -#define GC_VECTORP(x) (GC_VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
 +#define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
  #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
 -#define GC_OVERLAYP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
  #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 -#define GC_MARKERP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
  #define INTFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
 -#define GC_INTFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
  #define BOOLFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
 -#define GC_BOOLFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
  #define OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
 -#define GC_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
  #define BUFFER_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
 -#define GC_BUFFER_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
  #define BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
 -#define GC_BUFFER_LOCAL_VALUEP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
  #define SOME_BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
 -#define GC_SOME_BUFFER_LOCAL_VALUEP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
  #define KBOARD_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
 -#define GC_KBOARD_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
  
  
  /* True if object X is a pseudovector whose code is CODE.  */
     && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code))))   \
         == (PSEUDOVECTOR_FLAG | (code))))
  
 -/* True if object X is a pseudovector whose code is CODE.
 -   This one works during GC.  */
 -#define GC_PSEUDOVECTORP(x, code)                             \
 -  (GC_VECTORLIKEP (x)                                         \
 -   && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code))))   \
 -       == (PSEUDOVECTOR_FLAG | (code))))
 -
  /* Test for specific pseudovector types.  */
  #define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
 -#define GC_WINDOW_CONFIGURATIONP(x) GC_PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
  #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
 -#define GC_PROCESSP(x) GC_PSEUDOVECTORP (x, PVEC_PROCESS)
  #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
 -#define GC_WINDOWP(x) GC_PSEUDOVECTORP (x, PVEC_WINDOW)
  #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
 -#define GC_TERMINALP(x) GC_PSEUDOVECTORP (x, PVEC_TERMINAL)
  #define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
 -#define GC_SUBRP(x) GC_PSEUDOVECTORP (x, PVEC_SUBR)
  #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
 -#define GC_COMPILEDP(x) GC_PSEUDOVECTORP (x, PVEC_COMPILED)
  #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
 -#define GC_BUFFERP(x) GC_PSEUDOVECTORP (x, PVEC_BUFFER)
  #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
 -#define GC_CHAR_TABLE_P(x) GC_PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
 +#define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE)
  #define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
 -#define GC_BOOL_VECTOR_P(x) GC_PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
  #define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
 -#define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME)
 -
 -#define SUB_CHAR_TABLE_P(x) (CHAR_TABLE_P (x) && NILP (XCHAR_TABLE (x)->top))
  
  /* Test for image (image . spec)  */
  #define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage))
  #define ARRAYP(x) \
    (VECTORP (x) || STRINGP (x) || CHAR_TABLE_P (x) || BOOL_VECTOR_P (x))
  \f
 -#define GC_EQ(x, y) EQ (x, y)
 -
  #define CHECK_LIST(x) \
    CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x)
  
      XSETCDR ((x), tmp);                       \
    } while (0)
  
 +#define CHECK_NATNUM_CAR(x) \
 +  do {                                        \
 +    Lisp_Object tmp = XCAR (x);               \
 +    CHECK_NATNUM (tmp);                       \
 +    XSETCAR ((x), tmp);                       \
 +  } while (0)
 +
 +#define CHECK_NATNUM_CDR(x) \
 +  do {                                        \
 +    Lisp_Object tmp = XCDR (x);               \
 +    CHECK_NATNUM (tmp);                       \
 +    XSETCDR ((x), tmp);                       \
 +  } while (0)
 +
  /* Cast pointers to this type to compare them.  Some machines want int.  */
  #ifndef PNTR_COMPARISON_TYPE
  #define PNTR_COMPARISON_TYPE EMACS_UINT
@@@ -2236,44 -2278,34 +2236,44 @@@ extern void keys_of_cmds P_ ((void))
  
  /* Defined in coding.c */
  EXFUN (Fcoding_system_p, 1);
 +EXFUN (Fcoding_system_base, 1);
 +EXFUN (Fcoding_system_eol_type, 1);
 +EXFUN (Fcheck_coding_system, 1);
  EXFUN (Fcheck_coding_system, 1);
  EXFUN (Fread_coding_system, 2);
  EXFUN (Fread_non_nil_coding_system, 1);
  EXFUN (Ffind_operation_coding_system, MANY);
  EXFUN (Fupdate_coding_systems_internal, 0);
 -EXFUN (Fencode_coding_string, 3);
 -EXFUN (Fdecode_coding_string, 3);
 -extern Lisp_Object detect_coding_system P_ ((const unsigned char *, int, int,
 -                                           int));
 +EXFUN (Fencode_coding_string, 4);
 +EXFUN (Fdecode_coding_string, 4);
 +extern Lisp_Object detect_coding_system P_ ((const unsigned char *, int,
 +                                           int, int, int, Lisp_Object));
  extern void init_coding P_ ((void));
  extern void init_coding_once P_ ((void));
  extern void syms_of_coding P_ ((void));
 -extern Lisp_Object code_convert_string_norecord P_ ((Lisp_Object, Lisp_Object,
 -                                                   int));
 +
 +/* Defined in character.c */
 +extern void init_character_once P_ ((void));
 +extern void syms_of_character P_ ((void));
 +EXFUN (Funibyte_char_to_multibyte, 1);
  
  /* Defined in charset.c */
 -extern EMACS_INT nonascii_insert_offset;
 -extern Lisp_Object Vnonascii_translation_table;
  EXFUN (Fchar_bytes, 1);
  EXFUN (Fchar_width, 1);
  EXFUN (Fstring, MANY);
  extern int chars_in_text P_ ((const unsigned char *, int));
  extern int multibyte_chars_in_text P_ ((const unsigned char *, int));
 -extern int unibyte_char_to_multibyte P_ ((int));
  extern int multibyte_char_to_unibyte P_ ((int, Lisp_Object));
 +extern int multibyte_char_to_unibyte_safe P_ ((int));
  extern Lisp_Object Qcharset;
 +extern void init_charset P_ ((void));
  extern void init_charset_once P_ ((void));
  extern void syms_of_charset P_ ((void));
 +/* Structure forward declarations.  */
 +struct charset;
 +
 +/* Defined in composite.c */
 +extern void syms_of_composite P_ ((void));
  
  /* Defined in syntax.c */
  EXFUN (Fforward_word, 1);
@@@ -2291,8 -2323,9 +2291,8 @@@ extern int next_almost_prime P_ ((int))
  extern Lisp_Object larger_vector P_ ((Lisp_Object, int, Lisp_Object));
  extern void sweep_weak_hash_tables P_ ((void));
  extern Lisp_Object Qstring_lessp;
 -EXFUN (Foptimize_char_table, 1);
  extern Lisp_Object Vfeatures;
 -extern Lisp_Object QCtest, QCweakness, Qequal;
 +extern Lisp_Object QCtest, QCweakness, Qequal, Qeq;
  unsigned sxhash P_ ((Lisp_Object, int));
  Lisp_Object make_hash_table P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
                                 Lisp_Object, Lisp_Object, Lisp_Object,
@@@ -2307,7 -2340,6 +2307,7 @@@ void remove_hash_entry P_ ((struct Lisp
  extern void init_fns P_ ((void));
  EXFUN (Fsxhash, 1);
  EXFUN (Fmake_hash_table, MANY);
 +EXFUN (Fmakehash, 1);
  EXFUN (Fcopy_hash_table, 1);
  EXFUN (Fhash_table_count, 1);
  EXFUN (Fhash_table_rehash_size, 1);
@@@ -2366,7 -2398,6 +2366,7 @@@ extern Lisp_Object concat2 P_ ((Lisp_Ob
  extern Lisp_Object concat3 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
  extern Lisp_Object nconc2 P_ ((Lisp_Object, Lisp_Object));
  extern Lisp_Object assq_no_quit P_ ((Lisp_Object, Lisp_Object));
 +extern Lisp_Object assoc_no_quit P_ ((Lisp_Object, Lisp_Object));
  extern void clear_string_char_byte_cache P_ ((void));
  extern int string_char_to_byte P_ ((Lisp_Object, int));
  extern int string_byte_to_char P_ ((Lisp_Object, int));
@@@ -2377,10 -2408,18 +2377,10 @@@ EXFUN (Fcopy_alist, 1)
  EXFUN (Fplist_get, 2);
  EXFUN (Fplist_put, 3);
  EXFUN (Fplist_member, 2);
 -EXFUN (Fset_char_table_parent, 2);
 -EXFUN (Fchar_table_extra_slot, 2);
 -EXFUN (Fset_char_table_extra_slot, 3);
  EXFUN (Frassoc, 2);
  EXFUN (Fstring_equal, 2);
  EXFUN (Fcompare_strings, 7);
  EXFUN (Fstring_lessp, 2);
 -extern int char_table_translate P_ ((Lisp_Object, int));
 -extern void map_char_table P_ ((void (*) (Lisp_Object, Lisp_Object, Lisp_Object),
 -                              Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int,
 -                              int *));
 -extern Lisp_Object char_table_ref_and_index P_ ((Lisp_Object, int, int *));
  extern void syms_of_fns P_ ((void));
  
  /* Defined in floatfns.c */
@@@ -2413,7 -2452,6 +2413,7 @@@ extern void insert P_ ((const unsigned 
  extern void insert_and_inherit P_ ((const unsigned char *, int));
  extern void insert_1 P_ ((const unsigned char *, int, int, int, int));
  extern void insert_1_both P_ ((const unsigned char *, int, int, int, int, int));
 +extern void insert_from_gap P_ ((int, int));
  extern void insert_from_string P_ ((Lisp_Object, int, int, int, int, int));
  extern void insert_from_buffer P_ ((struct buffer *, int, int, int));
  extern void insert_char P_ ((int));
@@@ -2540,6 -2578,8 +2540,6 @@@ extern Lisp_Object make_pure_vector P_ 
  EXFUN (Fgarbage_collect, 0);
  EXFUN (Fmake_byte_code, MANY);
  EXFUN (Fmake_bool_vector, 2);
 -EXFUN (Fmake_char_table, 2);
 -extern Lisp_Object make_sub_char_table P_ ((Lisp_Object));
  extern Lisp_Object Qchar_table_extra_slots;
  extern struct Lisp_Vector *allocate_vector P_ ((EMACS_INT));
  extern struct Lisp_Vector *allocate_other_vector P_ ((EMACS_INT));
@@@ -2563,31 -2603,6 +2563,31 @@@ extern void syms_of_alloc P_ ((void))
  extern struct buffer * allocate_buffer P_ ((void));
  extern int valid_lisp_object_p P_ ((Lisp_Object));
  
 +/* Defined in chartab.c */
 +EXFUN (Fmake_char_table, 2);
 +EXFUN (Fchar_table_parent, 1);
 +EXFUN (Fset_char_table_parent, 2);
 +EXFUN (Fchar_table_extra_slot, 2);
 +EXFUN (Fset_char_table_extra_slot, 3);
 +EXFUN (Fchar_table_range, 2);
 +EXFUN (Fset_char_table_range, 3);
 +EXFUN (Fset_char_table_default, 3);
 +EXFUN (Foptimize_char_table, 1);
 +EXFUN (Fmap_char_table, 2);
 +extern Lisp_Object copy_char_table P_ ((Lisp_Object));
 +extern Lisp_Object sub_char_table_ref P_ ((Lisp_Object, int));
 +extern Lisp_Object char_table_ref P_ ((Lisp_Object, int));
 +extern Lisp_Object char_table_ref_and_range P_ ((Lisp_Object, int,
 +                                               int *, int *));
 +extern Lisp_Object char_table_set P_ ((Lisp_Object, int, Lisp_Object));
 +extern Lisp_Object char_table_set_range P_ ((Lisp_Object, int, int,
 +                                           Lisp_Object));
 +extern int char_table_translate P_ ((Lisp_Object, int));
 +extern void map_char_table P_ ((void (*) (Lisp_Object, Lisp_Object,
 +                                        Lisp_Object),
 +                              Lisp_Object, Lisp_Object, Lisp_Object));
 +extern void syms_of_chartab P_ ((void));
 +
  /* Defined in print.c */
  extern Lisp_Object Vprin1_to_string_buffer;
  extern void debug_print P_ ((Lisp_Object));
@@@ -2801,7 -2816,6 +2801,7 @@@ extern int overlay_touches_p P_ ((int))
  extern Lisp_Object Vbuffer_alist, Vinhibit_read_only;
  EXFUN (Fget_buffer, 1);
  EXFUN (Fget_buffer_create, 1);
 +EXFUN (Fgenerate_new_buffer_name, 2);
  EXFUN (Fset_buffer, 1);
  EXFUN (set_buffer_if_live, 1);
  EXFUN (Fbarf_if_buffer_read_only, 0);
@@@ -3145,7 -3159,6 +3145,7 @@@ extern Lisp_Object Qinsert_in_front_hoo
  EXFUN (Fnext_single_property_change, 4);
  EXFUN (Fnext_single_char_property_change, 4);
  EXFUN (Fprevious_single_property_change, 4);
 +EXFUN (Fget_text_property, 3);
  EXFUN (Fput_text_property, 5);
  EXFUN (Fprevious_char_property_change, 2);
  EXFUN (Fnext_char_property_change, 2);
@@@ -3206,7 -3219,6 +3206,7 @@@ extern void init_sound P_ ((void))
  
  /* Defined in category.c */
  extern void init_category_once P_ ((void));
 +extern Lisp_Object char_category_set P_ ((int));
  extern void syms_of_category P_ ((void));
  
  /* Defined in ccl.c */
@@@ -3226,8 -3238,7 +3226,8 @@@ extern void syms_of_terminal P_ ((void)
  #ifdef HAVE_WINDOW_SYSTEM
  /* Defined in fontset.c */
  extern void syms_of_fontset P_ ((void));
 -EXFUN (Fset_fontset_font, 4);
 +EXFUN (Fset_fontset_font, 5);
 +EXFUN (Fnew_fontset, 2);
  
  /* Defined in xfns.c, w32fns.c, or macfns.c */
  EXFUN (Fxw_display_color_p, 1);
@@@ -3368,9 -3379,11 +3368,11 @@@ extern Lisp_Object Vdirectory_sep_char
  #define min(a, b)     ((a) < (b) ? (a) : (b))
  #define max(a, b)     ((a) > (b) ? (a) : (b))
  
- /* Make sure we have abs defined */
- #if !defined(abs)
- #define abs(x)         ((x) < 0 ? -(x) : (x))
+ /* We used to use `abs', but that clashes with system headers on some
+    platforms, and using a name reserved by Standard C is a bad idea
+    anyway.  */
+ #if !defined(eabs)
+ #define eabs(x)         ((x) < 0 ? -(x) : (x))
  #endif
  
  /* Return a fixnum or float, depending on whether VAL fits in a Lisp
diff --combined src/macfns.c
index 0330ccd0d441973fa97a866937c0922b6c6a6a27,6a12c071ceef98c20cfe7f4c83e79dc08efcbc6b..9a9eb69fa6354f805ce9794ca148863fa56e050c
@@@ -1868,15 -1868,7 +1868,7 @@@ x_implicitly_set_name (f, arg, oldval
  }
  \f
  /* Change the title of frame F to NAME.
-    If NAME is nil, use the frame name as the title.
-    If EXPLICIT is non-zero, that indicates that lisp code is setting the
-        name; if NAME is a string, set F's name to NAME and set
-        F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-    If EXPLICIT is zero, that indicates that Emacs redisplay code is
-        suggesting a new name, which lisp code should override; if
-        F->explicit_name is set, ignore the new name; otherwise, set it.  */
+    If NAME is nil, use the frame name as the title.  */
  
  void
  x_set_title (f, name, old_name)
@@@ -2668,7 -2660,7 +2660,7 @@@ This function is an internal primitive-
        {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
 -        font = x_new_fontset (f, SDATA (tem));
 +        font = x_new_fontset (f, tem);
        else
          font = x_new_font (f, SDATA (font));
        }
        font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
      /* If those didn't work, look for something which will at least work.  */
      if (! STRINGP (font))
 -      font = x_new_fontset (f, "fontset-standard");
 +      font = x_new_fontset (f, build_string ("fontset-standard"));
      if (! STRINGP (font))
        font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
      if (! STRINGP (font))
@@@ -3903,7 -3895,7 +3895,7 @@@ x_create_tip_frame (dpyinfo, parms, tex
        {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
 -        font = x_new_fontset (f, SDATA (tem));
 +        font = x_new_fontset (f, tem);
        else
          font = x_new_font (f, SDATA (font));
        }
        font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
      /* If those didn't work, look for something which will at least work.  */
      if (! STRINGP (font))
 -      font = x_new_fontset (f, "fontset-standard");
 +      font = x_new_fontset (f, build_string ("fontset-standard"));
      if (! STRINGP (font))
        font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
      if (! STRINGP (font))
diff --combined src/macterm.c
index ed7411615f52668fbad7fa99aa2ca49300df098b,e4b9cca819c39b7374414c870b0b502243f9acc6..a15f0b0fcfc882a0ae9914b1870c9c42b50d62a6
@@@ -80,8 -80,6 +80,8 @@@ Boston, MA 02110-1301, USA.  *
  #include "intervals.h"
  #include "atimer.h"
  #include "keymap.h"
 +#include "character.h"
 +#include "ccl.h"
  
  \f
  
@@@ -2423,8 -2421,7 +2423,8 @@@ XTreset_terminal_modes (struct termina
  /* Function prototypes of this page.  */
  
  static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
 -static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 +static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, 
 +                              struct charset *, int *));
  
  
  static void
@@@ -2568,13 -2565,13 +2568,13 @@@ mac_per_char_metric (font, char2b, font
     the two-byte form of C.  Encoding is returned in *CHAR2B.  */
  
  static int
 -mac_encode_char (c, char2b, font_info, two_byte_p)
 +mac_encode_char (c, char2b, font_info, charset, two_byte_p)
       int c;
       XChar2b *char2b;
       struct font_info *font_info;
 +     struct charset *charset;
       int *two_byte_p;
  {
 -  int charset = CHAR_CHARSET (c);
    XFontStruct *font = font_info->font;
  
    /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
        check_ccl_update (ccl);
        if (CHARSET_DIMENSION (charset) == 1)
        {
 -        ccl->reg[0] = charset;
 -        ccl->reg[1] = char2b->byte2;
 +        ccl->reg[0] = CHARSET_ID (charset);
 +        ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
        else
        {
 -        ccl->reg[0] = charset;
 -        ccl->reg[1] = char2b->byte1;
 -        ccl->reg[2] = char2b->byte2;
 +        ccl->reg[0] = CHARSET_ID (charset);
 +        ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
 +        ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
  
 -      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
 +      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
  
        /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
        if (font->max_byte1 == 0)       /* 1-byte font */
 -      char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
 +      STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
        else
 -      char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
 +      STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
      }
 -  else if (font_info->encoding[charset])
 +  else if (font_info->encoding_type)
      {
        /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
 -      int enc = font_info->encoding[charset];
 +      unsigned char enc = font_info->encoding_type;
  
        if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
        char2b->byte2 |= 0x80;
  
        if (enc == 4)
 -        {
 -          int sjis1, sjis2;
 +      {
 +        int code = (char2b->byte1 << 8) | char2b->byte2;
  
 -          ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
 -          char2b->byte1 = sjis1;
 -          char2b->byte2 = sjis2;
 -        }
 +        JIS_TO_SJIS (code);
 +        STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 +      }
      }
  
    if (two_byte_p)
@@@ -2746,9 -2744,9 +2746,9 @@@ x_set_mouse_face_gc (s
      face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
  
    if (s->first_glyph->type == CHAR_GLYPH)
 -    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
 +    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
    else
 -    face_id = FACE_FOR_CHAR (s->f, face, 0);
 +    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
    s->face = FACE_FROM_ID (s->f, face_id);
    PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
  
@@@ -2970,7 -2968,7 +2970,7 @@@ x_draw_glyph_string_foreground (s
       of S to the right of that box line.  */
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
@@@ -3049,7 -3047,7 +3049,7 @@@ x_draw_composite_glyph_string_foregroun
       of S to the right of that box line.  */
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
@@@ -3111,8 -3109,8 +3111,8 @@@ x_frame_of_widget (widget
  
    /* Look for a frame with that top-level widget.  Allocate the color
       on that frame to get the right gamma correction value.  */
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 -    if (GC_FRAMEP (XCAR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
 +    if (FRAMEP (XCAR (tail))
        && (f = XFRAME (XCAR (tail)),
            (f->output_data.nothing != 1
             && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
@@@ -3544,7 -3542,7 +3544,7 @@@ x_draw_glyph_string_box (s
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
  
-   width = abs (s->face->box_line_width);
+   width = eabs (s->face->box_line_width);
    raised_p = s->face->box == FACE_RAISED_BOX;
    left_x = s->x;
    right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@@@ -3590,7 -3588,7 +3590,7 @@@ x_draw_image_foreground (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
@@@ -3663,7 -3661,7 +3663,7 @@@ x_draw_image_relief (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
      }
    else
      {
-       thick = abs (s->img->relief);
+       thick = eabs (s->img->relief);
        raised_p = s->img->relief > 0;
      }
  
@@@ -3741,7 -3739,7 +3741,7 @@@ x_draw_image_glyph_string (s
       struct glyph_string *s;
  {
    int x, y;
-   int box_line_hwidth = abs (s->face->box_line_width);
+   int box_line_hwidth = eabs (s->face->box_line_width);
    int box_line_vwidth = max (s->face->box_line_width, 0);
    int height;
  
@@@ -4421,9 -4419,9 +4421,9 @@@ mac_focus_changed (type, dpyinfo, frame
  
            /* Don't stop displaying the initial startup message
               for a switch-frame event we don't need.  */
 -          if (GC_NILP (Vterminal_frame)
 -              && GC_CONSP (Vframe_list)
 -              && !GC_NILP (XCDR (Vframe_list)))
 +          if (NILP (Vterminal_frame)
 +              && CONSP (Vframe_list)
 +              && !NILP (XCDR (Vframe_list)))
              {
                bufp->kind = FOCUS_IN_EVENT;
                XSETFRAME (bufp->frame_or_window, frame);
@@@ -4496,7 -4494,7 +4496,7 @@@ x_frame_rehighlight (dpyinfo
    if (dpyinfo->x_focus_frame)
      {
        dpyinfo->x_highlight_frame
 -      = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
 +      = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
           : dpyinfo->x_focus_frame);
        if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@@ -5526,7 -5524,7 +5526,7 @@@ x_scroll_bar_handle_click (bar, part_co
  {
    int win_y, top_range;
  
 -  if (! GC_WINDOWP (bar->window))
 +  if (! WINDOWP (bar->window))
      abort ();
  
    bufp->kind = SCROLL_BAR_CLICK_EVENT;
@@@ -5601,7 -5599,7 +5601,7 @@@ x_scroll_bar_note_movement (bar, y_pos
    XSETVECTOR (last_mouse_scroll_bar, bar);
  
    /* If we're dragging the bar, display it.  */
 -  if (! GC_NILP (bar->dragging))
 +  if (! NILP (bar->dragging))
      {
        /* Where should the handle be now?  */
        int new_start = y_pos - 24;
@@@ -6560,16 -6558,11 +6560,16 @@@ x_new_font (f, fontname
       register char *fontname;
  {
    struct font_info *fontp
 -    = FS_LOAD_FONT (f, 0, fontname, -1);
 +    = FS_LOAD_FONT (f, fontname);
  
    if (!fontp)
      return Qnil;
  
 +  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
 +    /* This font is already set in frame F.  There's nothing more to
 +       do.  */
 +    return build_string (fontp->full_name);
 +
    FRAME_FONT (f) = (XFontStruct *) (fontp->font);
    FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
    FRAME_FONTSET (f) = -1;
  
    return build_string (fontp->full_name);
  }
 +\f
 +/* Give frame F the fontset named FONTSETNAME as its default fontset,
 +   and return the full name of that fontset.  FONTSETNAME may be a
 +   wildcard pattern; in that case, we choose some fontset that fits
 +   the pattern.  FONTSETNAME may be a font name for ASCII characters;
 +   in that case, we create a fontset from that font name.
  
 -/* Give frame F the fontset named FONTSETNAME as its default font, and
 -   return the full name of that fontset.  FONTSETNAME may be a wildcard
 -   pattern; in that case, we choose some fontset that fits the pattern.
 -   The return value shows which fontset we chose.  */
 +   The return value shows which fontset we chose.
 +   If FONTSETNAME specifies the default fontset, return Qt.
 +   If an ASCII font in the specified fontset can't be loaded, return
 +   Qnil.  */
  
  Lisp_Object
  x_new_fontset (f, fontsetname)
       struct frame *f;
 -     char *fontsetname;
 +     Lisp_Object fontsetname;
  {
 -  int fontset = fs_query_fontset (build_string (fontsetname), 0);
 +  int fontset = fs_query_fontset (fontsetname, 0);
    Lisp_Object result;
  
 -  if (fontset < 0)
 -    return Qnil;
 -
 -  if (FRAME_FONTSET (f) == fontset)
 +  if (fontset > 0 && FRAME_FONTSET(f) == fontset)
      /* This fontset is already set in frame F.  There's nothing more
         to do.  */
      return fontset_name (fontset);
 +  else if (fontset == 0)
 +    /* The default fontset can't be the default font.   */
 +    return Qt;
  
 -  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  if (fontset > 0)
 +    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  else
 +    result = x_new_font (f, SDATA (fontsetname));
  
    if (!STRINGP (result))
      /* Can't load ASCII font.  */
      return Qnil;
  
 +  if (fontset < 0)
 +    fontset = new_fontset_from_font_name (result);
 +
    /* Since x_new_font doesn't update any fontset information, do it now.  */
    FRAME_FONTSET (f) = fontset;
  
 -  return build_string (fontsetname);
 +  return fontset_name (fontset);
  }
  
  \f
@@@ -7869,12 -7850,12 +7869,12 @@@ decode_mac_font_name (name, size, codin
          coding.src_multibyte = 0;
          coding.dst_multibyte = 1;
          coding.mode |= CODING_MODE_LAST_BLOCK;
 -        coding.composing = COMPOSITION_DISABLED;
 -        buf = (char *) alloca (size);
 +        coding.dst_bytes = size;
 +        coding.destination = (unsigned char *) alloca (coding.dst_bytes);
  
 -        decode_coding (&coding, name, buf, strlen (name), size - 1);
 -        bcopy (buf, name, coding.produced);
 -        name[coding.produced] = '\0';
 +        decode_coding_c_string (&coding, name, strlen (name), Qnil);
 +        bcopy (coding.destination, name, min (coding.produced, size));
 +        name[min (coding.produced, size)] = '\0';
        }
      }
  
@@@ -9211,7 -9192,6 +9211,7 @@@ x_load_font (f, fontname, size
      bzero (fontp, sizeof (*fontp));
      fontp->font = font;
      fontp->font_idx = i;
 +    fontp->charset = -1;      /* fs_load_font sets it.  */
      fontp->name = (char *) xmalloc (strlen (fontname) + 1);
      bcopy (fontname, fontp->name, strlen (fontname) + 1);
  
        fontp->height = max_height;
      }
  
 +    /* MAC_TODO: The script encoding is irrelevant in unicode? */
      /* The slot `encoding' specifies how to map a character
         code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
         the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
         (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
         2:0xA020..0xFF7F).  For the moment, we don't know which charset
 -       uses this font.  So, we set information in fontp->encoding[1]
 +       uses this font.  So, we set information in fontp->encoding_type
         which is never used by any charset.  If mapping can't be
         decided, set FONT_ENCODING_NOT_DECIDED.  */
      if (font->mac_scriptcode == smJapanese)
 -      fontp->encoding[1] = 4;
 +      fontp->encoding_type = 4;
      else
        {
 -        fontp->encoding[1]
 +        fontp->encoding_type
             = (font->max_byte1 == 0
              /* 1-byte font */
              ? (font->min_char_or_byte2 < 0x80
diff --combined src/msdos.c
index 02bd2748b8f0e02d121525d217807ca8072abe7f,fc14be2705c7b131309d3524ca9864f052eadc26..2e3ce3cf146c79b324af8aa758e0cd8498ac8c68
@@@ -56,7 -56,7 +56,7 @@@ Boston, MA 02110-1301, 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"
@@@ -3393,13 -3393,7 +3393,7 @@@ dos_rawgetc (
                 it is active.  */
              if (WINDOWP (mouse_window)
                  && !EQ (mouse_window, last_mouse_window)
-                 && !EQ (window, selected_window)
-                 /* For click-to-focus window managers
-                    create event iff we don't leave the
-                    selected frame.  */
-                 && (focus_follows_mouse
-                     || (EQ (XWINDOW (window)->frame,
-                             XWINDOW (selected_window)->frame))))
+                 && !EQ (mouse_window, selected_window))
                {
                  event.kind = SELECT_WINDOW_EVENT;
                  event.frame_or_window = mouse_window;
@@@ -3805,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, 1);
 +                         DEFAULT_FACE_ID, 1);
    faces[1]
      = lookup_derived_face (sf, intern ("msdos-menu-active-face"),
 -                         0, DEFAULT_FACE_ID, 1);
 +                         DEFAULT_FACE_ID, 1);
    selectface = intern ("msdos-menu-select-face");
    faces[2] = lookup_derived_face (sf, selectface,
 -                                0, faces[0], 1);
 +                                faces[0], 1);
    faces[3] = lookup_derived_face (sf, selectface,
 -                                0, faces[1], 1);
 +                                faces[1], 1);
  
    /* Make sure the menu title is always displayed with
       `msdos-menu-active-face', no matter where the mouse pointer is.  */
diff --combined src/w32fns.c
index 1fbde99f30683ed16d5ca4ef733f16bc3623a8e7,8af99a2d0b98ba04917a729c95621d1801885087..74b2a0ed655dd813144950c3cdbe99f4c63ddccd
@@@ -29,23 -29,22 +29,23 @@@ Boston, MA 02110-1301, USA.  *
  #include <errno.h>
  
  #include "lisp.h"
 -#include "charset.h"
 -#include "dispextern.h"
  #include "w32term.h"
 -#include "keyboard.h"
  #include "frame.h"
  #include "window.h"
  #include "buffer.h"
 -#include "fontset.h"
  #include "intervals.h"
 +#include "dispextern.h"
 +#include "keyboard.h"
  #include "blockinput.h"
  #include "epaths.h"
 -#include "w32heap.h"
 -#include "termhooks.h"
 +#include "character.h"
 +#include "charset.h"
  #include "coding.h"
  #include "ccl.h"
 +#include "fontset.h"
  #include "systime.h"
 +#include "termhooks.h"
 +#include "w32heap.h"
  
  #include "bitmaps/gray.xbm"
  
  #include <dlgs.h>
  #define FILE_NAME_TEXT_FIELD edt1
  
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif
 +
  void syms_of_w32fns ();
  void globals_of_w32fns ();
  
@@@ -388,10 -383,10 +388,10 @@@ x_window_to_frame (dpyinfo, wdesc
    Lisp_Object tail, frame;
    struct frame *f;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
@@@ -1940,15 -1935,7 +1940,7 @@@ x_implicitly_set_name (f, arg, oldval
  }
  \f
  /* Change the title of frame F to NAME.
-    If NAME is nil, use the frame name as the title.
-    If EXPLICIT is non-zero, that indicates that lisp code is setting the
-        name; if NAME is a string, set F's name to NAME and set
-        F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-    If EXPLICIT is zero, that indicates that Emacs redisplay code is
-        suggesting a new name, which lisp code should override; if
-        F->explicit_name is set, ignore the new name; otherwise, set it.  */
+    If NAME is nil, use the frame name as the title.  */
  
  void
  x_set_title (f, name, old_name)
@@@ -2467,8 -2454,8 +2459,8 @@@ register_hot_keys (hwnd
  {
    Lisp_Object keylist;
  
 -  /* Use GC_CONSP, since we are called asynchronously.  */
 -  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
 +  /* Use CONSP, since we are called asynchronously.  */
 +  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
      {
        Lisp_Object key = XCAR (keylist);
  
@@@ -2487,7 -2474,8 +2479,7 @@@ unregister_hot_keys (hwnd
  {
    Lisp_Object keylist;
  
 -  /* Use GC_CONSP, since we are called asynchronously.  */
 -  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
 +  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
      {
        Lisp_Object key = XCAR (keylist);
  
@@@ -4148,38 -4136,6 +4140,38 @@@ unwind_create_frame (frame
    return Qnil;
  }
  
 +#ifdef USE_FONT_BACKEND
 +static void
 +x_default_font_parameter (f, parms)
 +     struct frame *f;
 +     Lisp_Object parms;
 +{
 +  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 +  Lisp_Object font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font",
 +                                RES_TYPE_STRING);
 +
 +  if (!STRINGP (font))
 +    {
 +      int i;
 +      static char *names[]
 +        = { "Courier New-10",
 +            "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
 +            "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
 +            "Fixedsys",
 +            NULL };
 +
 +      for (i = 0; names[i]; i++)
 +        {
 +          font = font_open_by_name (f, names[i]);
 +          if (! NILP (font))
 +            break;
 +        }
 +      if (NILP (font))
 +        error ("No suitable font was found");
 +    }
 +  x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
 +}
 +#endif
  
  DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
         1, 1, 0,
@@@ -4315,28 -4271,8 +4307,28 @@@ This function is an internal primitive-
        specbind (Qx_resource_name, name);
      }
  
 +  f->resx = dpyinfo->resx;
 +  f->resy = dpyinfo->resy;
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      /* Perhaps, we must allow frame parameter, say `font-backend',
 +       to specify which font backends to use.  */
 +      register_font_driver (&w32font_driver, f);
 +
 +      x_default_parameter (f, parameters, Qfont_backend, Qnil,
 +                         "fontBackend", "FontBackend", RES_TYPE_STRING);
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +
    /* Extract the window parameters from the supplied values
       that are needed to determine window geometry.  */
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    x_default_font_parameter (f, parameters);
 +  else
 +#endif 
    {
      Lisp_Object font;
  
        {
          tem = Fquery_fontset (font, Qnil);
          if (STRINGP (tem))
 -          font = x_new_fontset (f, SDATA (tem));
 +          font = x_new_fontset (f, tem);
          else
            font = x_new_font (f, SDATA (font));
        }
@@@ -4744,10 -4680,10 +4736,10 @@@ w32_load_system_font (f,fontname,size
      fontp->name = (char *) xmalloc (strlen (fontname) + 1);
      bcopy (fontname, fontp->name, strlen (fontname) + 1);
  
 -    if (lf.lfPitchAndFamily == FIXED_PITCH)
 +    if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH)
        {
        /* Fixed width font.  */
 -      fontp->average_width = fontp->space_width = FONT_WIDTH (font);
 +      fontp->average_width = fontp->space_width = FONT_AVG_WIDTH (font);
        }
      else
        {
        if (pcm)
          fontp->space_width = pcm->width;
        else
 -        fontp->space_width = FONT_WIDTH (font);
 +        fontp->space_width = FONT_AVG_WIDTH (font);
  
        fontp->average_width = font->tm.tmAveCharWidth;
        }
  
 +    fontp->charset = -1;
      charset = xlfd_charset_of_font (fontname);
  
    /* Cache the W32 codepage for a font.  This makes w32_encode_char
         (0:0x20..0x7F, 1:0xA0..0xFF,
         (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
         2:0xA020..0xFF7F).  For the moment, we don't know which charset
 -       uses this font.  So, we set information in fontp->encoding[1]
 +       uses this font.  So, we set information in fontp->encoding_type
         which is never used by any charset.  If mapping can't be
         decided, set FONT_ENCODING_NOT_DECIDED.  */
  
         type FONT_ENCODING_NOT_DECIDED.  */
      encoding = strrchr (fontp->name, '-');
      if (encoding && strnicmp (encoding+1, "sjis", 4) == 0)
 -      fontp->encoding[1] = 4;
 +      fontp->encoding_type = 4;
      else
 -      fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
 +      fontp->encoding_type = FONT_ENCODING_NOT_DECIDED;
  
      /* The following three values are set to 0 under W32, which is
         what they get set to if XGetFontProperty fails under X.  */
@@@ -4941,7 -4876,7 +4933,7 @@@ w32_to_x_weight (fnweight
      return "*";
  }
  
 -static LONG
 +LONG
  x_to_w32_charset (lpcs)
      char * lpcs;
  {
    if (strncmp (lpcs, "*-#", 3) == 0)
      return atoi (lpcs + 3);
  
 +  /* All Windows fonts qualify as unicode.  */
 +  if (!strncmp (lpcs, "iso10646", 8))
 +    return DEFAULT_CHARSET;
 +
    /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5".  */
    charset = alloca (len + 1);
    strcpy (charset, lpcs);
    lpcs = strchr (charset, '*');
    if (lpcs)
 -    *lpcs = 0;
 +    *lpcs = '\0';
  
    /* Look through w32-charset-info-alist for the character set.
       Format of each entry is
  }
  
  
 -static char *
 -w32_to_x_charset (fncharset)
 +char *
 +w32_to_x_charset (fncharset, matching)
      int fncharset;
 +    char *matching;
  {
    static char buf[32];
    Lisp_Object charset_type;
 +  int match_len = 0;
 +
 +  if (matching)
 +    {
 +      /* If fully specified, accept it as it is.  Otherwise use a
 +       substring match. */
 +      char *wildcard = strchr (matching, '*');
 +      if (wildcard)
 +      *wildcard = '\0';
 +      else if (strchr (matching, '-'))
 +      return matching;
 +
 +      match_len = strlen (matching);
 +    }
  
    switch (fncharset)
      {
    {
      Lisp_Object rest;
      char * best_match = NULL;
 +    int matching_found = 0;
  
      /* Look through w32-charset-info-alist for the character set.
         Prefer ISO codepages, and prefer lower numbers in the ISO
              /* If we don't have a match already, then this is the
                 best.  */
              if (!best_match)
 -              best_match = x_charset;
 -            /* If this is an ISO codepage, and the best so far isn't,
 -               then this is better.  */
 -            else if (strnicmp (best_match, "iso", 3) != 0
 -                     && strnicmp (x_charset, "iso", 3) == 0)
 -              best_match = x_charset;
 +            {
 +              best_match = x_charset;
 +              if (matching && !strnicmp (x_charset, matching, match_len))
 +                matching_found = 1;
 +            }
 +          /* If we already found a match for MATCHING, then
 +             only consider other matches.  */
 +          else if (matching_found
 +                   && strnicmp (x_charset, matching, match_len))
 +            continue;
 +          /* If this matches what we want, and the best so far doesn't,
 +             then this is better.  */
 +          else if (!matching_found && matching
 +                   && !strnicmp (x_charset, matching, match_len))
 +            {
 +              best_match = x_charset;
 +              matching_found = 1;
 +            }
 +          /* If this is fully specified, and the best so far isn't,
 +             then this is better.  */
 +          else if ((!strchr (best_match, '-') && strchr (x_charset, '-'))
 +          /* If this is an ISO codepage, and the best so far isn't,
 +             then this is better, but only if it fully specifies the
 +             encoding.  */
 +              || (strnicmp (best_match, "iso", 3) != 0
 +                  && strnicmp (x_charset, "iso", 3) == 0
 +                  && strchr (x_charset, '-')))
 +              best_match = x_charset;
              /* If both are ISO8859 codepages, choose the one with the
                 lowest number in the encoding field.  */
              else if (strnicmp (best_match, "iso8859-", 8) == 0
          return buf;
        }
  
 -    strncpy(buf, best_match, 31);
 +    strncpy (buf, best_match, 31);
 +    /* If the charset is not fully specified, put -0 on the end.  */
 +    if (!strchr (best_match, '-'))
 +      {
 +      int pos = strlen (best_match);
 +      /* Charset specifiers shouldn't be very long.  If it is a made
 +         up one, truncating it should not do any harm since it isn't
 +         recognized anyway.  */
 +      if (pos > 29)
 +        pos = 29;
 +      strcpy (buf + pos, "-0");
 +      }
      buf[31] = '\0';
      return buf;
    }
@@@ -5329,8 -5211,7 +5321,8 @@@ w32_to_all_x_charsets (fncharset
    {
      Lisp_Object rest;
      /* Look through w32-charset-info-alist for the character set.
 -       Only return charsets for codepages which are installed.
 +       Only return fully specified charsets for codepages which are
 +       installed.
  
         Format of each entry in Vw32_charset_info_alist is
           (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
          w32_charset = XCAR (XCDR (this_entry));
          codepage = XCDR (XCDR (this_entry));
  
 +      if (!strchr (SDATA (x_charset), '-'))
 +        continue;
 +
          /* Look for Same charset and a valid codepage (or non-int
             which means ignore).  */
          if (EQ (w32_charset, charset_type)
@@@ -5386,6 -5264,9 +5378,6 @@@ w32_codepage_for_font (char *fontname
    Lisp_Object codepage, entry;
    char *charset_str, *charset, *end;
  
 -  if (NILP (Vw32_charset_info_alist))
 -    return CP_DEFAULT;
 -
    /* Extract charset part of font string.  */
    charset = xlfd_charset_of_font (fontname);
  
          *end = '\0';
        }
  
 +  if (!strcmp (charset, "iso10646"))
 +    return CP_UNICODE;
 +
 +  if (NILP (Vw32_charset_info_alist))
 +    return CP_DEFAULT;
 +
    entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
    if (NILP (entry))
      return CP_UNKNOWN;
@@@ -5449,6 -5324,7 +5441,6 @@@ w32_to_x_font (lplogfont, lpxstr, len, 
    char *fontname_dash;
    int display_resy = (int) one_w32_display_info.resy;
    int display_resx = (int) one_w32_display_info.resx;
 -  int bufsz;
    struct coding_system coding;
  
    if (!lpxstr) abort ();
    coding.mode |= CODING_MODE_LAST_BLOCK;
    /* We explicitely disable composition handling because selection
       data should not contain any composition sequence.  */
 -  coding.composing = COMPOSITION_DISABLED;
 -  bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
 +  coding.common_flags &= ~CODING_ANNOTATION_MASK;
 +
 +  coding.dst_bytes = LF_FACESIZE * 2;
 +  coding.destination = (unsigned char *) xmalloc (coding.dst_bytes + 1);
 +  decode_coding_c_string (&coding, lplogfont->lfFaceName,
 +                        strlen(lplogfont->lfFaceName), Qnil);
 +  fontname = coding.destination;
  
 -  fontname = alloca(sizeof(*fontname) * bufsz);
 -  decode_coding (&coding, lplogfont->lfFaceName, fontname,
 -                 strlen(lplogfont->lfFaceName), bufsz - 1);
    *(fontname + coding.produced) = '\0';
  
    /* Replace dashes with underscores so the dashes are not
  
    if (lplogfont->lfHeight)
      {
-       sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
+       sprintf (height_pixels, "%u", eabs (lplogfont->lfHeight));
        sprintf (height_dpi, "%u",
-              abs (lplogfont->lfHeight) * 720 / display_resy);
+              eabs (lplogfont->lfHeight) * 720 / display_resy);
      }
    else
      {
             ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
               ? 'p' : 'c',                            /* spacing */
             width_pixels,                           /* avg width */
 -           specific_charset ? specific_charset
 -             : w32_to_x_charset (lplogfont->lfCharSet)
 +             w32_to_x_charset (lplogfont->lfCharSet, specific_charset)
               /* charset registry and encoding */
             );
  
@@@ -5599,24 -5474,26 +5591,24 @@@ x_to_w32_font (lpxstr, lplogfont
  
        if (fields > 0 && name[0] != '*')
          {
 -        int bufsize;
 -        unsigned char *buf;
 -
 +        Lisp_Object string = build_string (name);
            setup_coding_system
              (Fcheck_coding_system (Vlocale_coding_system), &coding);
 -        coding.src_multibyte = 1;
 -        coding.dst_multibyte = 0;
 -        /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in
 -           encode_coding_iso2022 trying to dereference a null pointer.  */
 -        coding.composing = COMPOSITION_DISABLED;
 -        if (coding.type == coding_type_iso2022)
 -          coding.flags |= CODING_FLAG_ISO_SAFE;
 -        bufsize = encoding_buffer_size (&coding, strlen (name));
 -        buf = (unsigned char *) alloca (bufsize);
 -          coding.mode |= CODING_MODE_LAST_BLOCK;
 -          encode_coding (&coding, name, buf, strlen (name), bufsize);
 +          coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
 +        /* Disable composition/charset annotation.   */
 +        coding.common_flags &= ~CODING_ANNOTATION_MASK;
 +        coding.dst_bytes = SCHARS (string) * 2;
 +
 +        coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
 +          encode_coding_object (&coding, string, 0, 0,
 +                              SCHARS (string), SBYTES (string), Qnil);
          if (coding.produced >= LF_FACESIZE)
            coding.produced = LF_FACESIZE - 1;
 -        buf[coding.produced] = 0;
 -        strcpy (lplogfont->lfFaceName, buf);
 +
 +        coding.destination[coding.produced] = '\0';
 +
 +        strcpy (lplogfont->lfFaceName, coding.destination);
 +        xfree (coding.destination);
        }
        else
          {
        lplogfont->lfHeight = atoi (height) * dpi / 720;
  
        if (fields > 0)
 -      lplogfont->lfPitchAndFamily =
 -      (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
 +        {
 +          if (pitch == 'p')
 +            lplogfont->lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
 +          else if (pitch == 'c')
 +            lplogfont->lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
 +        }
  
        fields--;
  
      }
  
    /* This makes TrueType fonts work better. */
-   lplogfont->lfHeight = - abs (lplogfont->lfHeight);
+   lplogfont->lfHeight = - eabs (lplogfont->lfHeight);
  
    return (TRUE);
  }
@@@ -5998,17 -5871,14 +5990,17 @@@ enum_font_cb2 (lplf, lptm, FontType, lp
        if (charset
            && strncmp (charset, "*-*", 3) != 0
            && lpef->logfont.lfCharSet == DEFAULT_CHARSET
 -          && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET)) != 0)
 +          && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET, NULL)) != 0)
          return 1;
        }
  
      if (charset)
        charset_list = Fcons (build_string (charset), Qnil);
      else
 -      charset_list = w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet);
 +      /* Always prefer unicode.  */
 +      charset_list
 +      = Fcons (build_string ("iso10646-1"),
 +               w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet));
  
      /* Loop through the charsets.  */
      for ( ; CONSP (charset_list); charset_list = Fcdr (charset_list))
        Lisp_Object this_charset = Fcar (charset_list);
        charset = SDATA (this_charset);
  
 +      enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
 +                                   charset, width);
 +
        /* List bold and italic variations if w32-enable-synthesized-fonts
           is non-nil and this is a plain font.  */
        if (w32_enable_synthesized_fonts
            && lplf->elfLogFont.lfWeight == FW_NORMAL
            && lplf->elfLogFont.lfItalic == FALSE)
          {
 -          enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
 -                                       charset, width);
            /* bold.  */
            lplf->elfLogFont.lfWeight = FW_BOLD;
            enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
            enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
                                         charset, width);
          }
 -      else
 -        enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
 -                                     charset, width);
        }
    }
  
@@@ -6301,7 -6173,7 +6293,7 @@@ w32_list_fonts (f, pattern, size, maxna
                hdc = GetDC (dpyinfo->root_window);
                oldobj = SelectObject (hdc, thisinfo.hfont);
                if (GetTextMetrics (hdc, &thisinfo.tm))
 -                XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
 +                XSETCDR (tem, make_number (FONT_AVG_WIDTH (&thisinfo)));
                else
                  XSETCDR (tem, make_number (0));
                SelectObject (hdc, oldobj);
@@@ -7436,28 -7308,8 +7428,28 @@@ x_create_tip_frame (dpyinfo, parms, tex
        specbind (Qx_resource_name, name);
      }
  
 +  f->resx = dpyinfo->resx;
 +  f->resy = dpyinfo->resy;
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      /* Perhaps, we must allow frame parameter, say `font-backend',
 +       to specify which font backends to use.  */
 +      register_font_driver (&w32font_driver, f);
 +
 +      x_default_parameter (f, parms, Qfont_backend, Qnil,
 +                         "fontBackend", "FontBackend", RES_TYPE_STRING);
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +
    /* Extract the window parameters from the supplied values
       that are needed to determine window geometry.  */
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    x_default_font_parameter (f, parms);
 +  else
 +#endif        /* USE_FONT_BACKEND */
    {
      Lisp_Object font;
  
        {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
 -        font = x_new_fontset (f, SDATA (tem));
 +        font = x_new_fontset (f, tem);
        else
          font = x_new_font (f, SDATA (font));
        }
@@@ -8774,9 -8626,6 +8766,9 @@@ frame_parm_handler w32_frame_parm_handl
    x_set_fringe_width,
    0, /* x_set_wait_for_wm, */
    x_set_fullscreen,
 +#ifdef USE_FONT_BACKEND
 +  x_set_font_backend
 +#endif
  };
  
  void
@@@ -8789,17 -8638,29 +8781,17 @@@ syms_of_w32fns (
  
    w32_visible_system_caret_hwnd = NULL;
  
 -  Qnone = intern ("none");
 -  staticpro (&Qnone);
 -  Qsuppress_icon = intern ("suppress-icon");
 -  staticpro (&Qsuppress_icon);
 -  Qundefined_color = intern ("undefined-color");
 -  staticpro (&Qundefined_color);
 -  Qcancel_timer = intern ("cancel-timer");
 -  staticpro (&Qcancel_timer);
 -
 -  Qhyper = intern ("hyper");
 -  staticpro (&Qhyper);
 -  Qsuper = intern ("super");
 -  staticpro (&Qsuper);
 -  Qmeta = intern ("meta");
 -  staticpro (&Qmeta);
 -  Qalt = intern ("alt");
 -  staticpro (&Qalt);
 -  Qctrl = intern ("ctrl");
 -  staticpro (&Qctrl);
 -  Qcontrol = intern ("control");
 -  staticpro (&Qcontrol);
 -  Qshift = intern ("shift");
 -  staticpro (&Qshift);
 +  DEFSYM (Qnone, "none");
 +  DEFSYM (Qsuppress_icon, "suppress-icon");
 +  DEFSYM (Qundefined_color, "undefined-color");
 +  DEFSYM (Qcancel_timer, "cancel-timer");
 +  DEFSYM (Qhyper, "hyper");
 +  DEFSYM (Qsuper, "super");
 +  DEFSYM (Qmeta, "meta");
 +  DEFSYM (Qalt, "alt");
 +  DEFSYM (Qctrl, "ctrl");
 +  DEFSYM (Qcontrol, "control");
 +  DEFSYM (Qshift, "shift");
    /* This is the end of symbol initialization.  */
  
    /* Text property `display' should be nonsticky by default.  */
@@@ -9066,16 -8927,24 +9058,16 @@@ CODEPAGE should be an integer specifyin
  to display the character set, t to do no translation and output as Unicode,
  or nil to do no translation and output as 8 bit (or multibyte on far-east
  versions of Windows) characters.  */);
 -    Vw32_charset_info_alist = Qnil;
 -
 -  staticpro (&Qw32_charset_ansi);
 -  Qw32_charset_ansi = intern ("w32-charset-ansi");
 -  staticpro (&Qw32_charset_symbol);
 -  Qw32_charset_default = intern ("w32-charset-default");
 -  staticpro (&Qw32_charset_default);
 -  Qw32_charset_symbol = intern ("w32-charset-symbol");
 -  staticpro (&Qw32_charset_shiftjis);
 -  Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
 -  staticpro (&Qw32_charset_hangeul);
 -  Qw32_charset_hangeul = intern ("w32-charset-hangeul");
 -  staticpro (&Qw32_charset_chinesebig5);
 -  Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
 -  staticpro (&Qw32_charset_gb2312);
 -  Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
 -  staticpro (&Qw32_charset_oem);
 -  Qw32_charset_oem = intern ("w32-charset-oem");
 +  Vw32_charset_info_alist = Qnil;
 +
 +  DEFSYM (Qw32_charset_ansi, "w32-charset-ansi");
 +  DEFSYM (Qw32_charset_symbol, "w32-charset-symbol");
 +  DEFSYM (Qw32_charset_default, "w32-charset-default");
 +  DEFSYM (Qw32_charset_shiftjis, "w32-charset-shiftjis");
 +  DEFSYM (Qw32_charset_hangeul, "w32-charset-hangeul");
 +  DEFSYM (Qw32_charset_chinesebig5, "w32-charset-chinesebig5");
 +  DEFSYM (Qw32_charset_gb2312, "w32-charset-gb2312");
 +  DEFSYM (Qw32_charset_oem, "w32-charset-oem");
  
  #ifdef JOHAB_CHARSET
    {
      DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
                 doc: /* Internal variable.  */);
  
 -    staticpro (&Qw32_charset_johab);
 -    Qw32_charset_johab = intern ("w32-charset-johab");
 -    staticpro (&Qw32_charset_easteurope);
 -    Qw32_charset_easteurope = intern ("w32-charset-easteurope");
 -    staticpro (&Qw32_charset_turkish);
 -    Qw32_charset_turkish = intern ("w32-charset-turkish");
 -    staticpro (&Qw32_charset_baltic);
 -    Qw32_charset_baltic = intern ("w32-charset-baltic");
 -    staticpro (&Qw32_charset_russian);
 -    Qw32_charset_russian = intern ("w32-charset-russian");
 -    staticpro (&Qw32_charset_arabic);
 -    Qw32_charset_arabic = intern ("w32-charset-arabic");
 -    staticpro (&Qw32_charset_greek);
 -    Qw32_charset_greek = intern ("w32-charset-greek");
 -    staticpro (&Qw32_charset_hebrew);
 -    Qw32_charset_hebrew = intern ("w32-charset-hebrew");
 -    staticpro (&Qw32_charset_vietnamese);
 -    Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
 -    staticpro (&Qw32_charset_thai);
 -    Qw32_charset_thai = intern ("w32-charset-thai");
 -    staticpro (&Qw32_charset_mac);
 -    Qw32_charset_mac = intern ("w32-charset-mac");
 +    DEFSYM (Qw32_charset_johab, "w32-charset-johab");
 +    DEFSYM (Qw32_charset_easteurope, "w32-charset-easteurope");
 +    DEFSYM (Qw32_charset_turkish, "w32-charset-turkish");
 +    DEFSYM (Qw32_charset_baltic, "w32-charset-baltic");
 +    DEFSYM (Qw32_charset_russian, "w32-charset-russian");
 +    DEFSYM (Qw32_charset_arabic, "w32-charset-arabic");
 +    DEFSYM (Qw32_charset_greek, "w32-charset-greek");
 +    DEFSYM (Qw32_charset_hebrew, "w32-charset-hebrew");
 +    DEFSYM (Qw32_charset_vietnamese, "w32-charset-vietnamese");
 +    DEFSYM (Qw32_charset_thai, "w32-charset-thai");
 +    DEFSYM (Qw32_charset_mac, "w32-charset-mac");
    }
  #endif
  
      DEFVAR_BOOL ("w32-unicode-charset-defined",
                   &w32_unicode_charset_defined,
                 doc: /* Internal variable.  */);
 -
 -    staticpro (&Qw32_charset_unicode);
 -    Qw32_charset_unicode = intern ("w32-charset-unicode");
 +    DEFSYM (Qw32_charset_unicode, "w32-charset-unicode");
    }
  #endif
  
    find_ccl_program_func = w32_find_ccl_program;
    query_font_func = w32_query_font;
    set_frame_fontset_func = x_set_font;
 +  get_font_repertory_func = x_get_font_repertory;
    check_window_system_func = check_w32;
  
  
diff --combined src/w32menu.c
index d4c92d4dcd54075c31e46f390970a33afad7a21c,a94be08902d5cc3cae4a6d39de788903846017fc..986832b3e7c14bf42bf1afc5bd3344c4c6fd0b3d
@@@ -34,7 -34,6 +34,7 @@@ Boston, MA 02110-1301, USA.  *
  #include "blockinput.h"
  #include "buffer.h"
  #include "charset.h"
 +#include "character.h"
  #include "coding.h"
  
  /* This may include sys/types.h, and that somehow loses
@@@ -260,10 -259,10 +260,10 @@@ menubar_id_to_frame (id
    Lisp_Object tail, frame;
    FRAME_PTR f;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_WINDOW_P (f))
@@@ -319,14 -318,8 +319,8 @@@ discard_menu_items (
  static void
  grow_menu_items ()
  {
-   Lisp_Object old;
-   int old_size = menu_items_allocated;
-   old = menu_items;
    menu_items_allocated *= 2;
-   menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
-   bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
-        old_size * sizeof (Lisp_Object));
+   menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
  }
  
  /* Begin a submenu.  */
@@@ -2598,13 -2591,14 +2592,13 @@@ DEFUN ("menu-or-popup-active-p", Fmenu_
  
  void syms_of_w32menu ()
  {
 -      globals_of_w32menu ();
 +  globals_of_w32menu ();
    staticpro (&menu_items);
    menu_items = Qnil;
  
    current_popup_menu = NULL;
  
 -  Qdebug_on_next_call = intern ("debug-on-next-call");
 -  staticpro (&Qdebug_on_next_call);
 +  DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
  
    defsubr (&Sx_popup_menu);
    defsubr (&Smenu_or_popup_active_p);
diff --combined src/w32term.c
index a7fca780d3c26a9877a1c0bc5f71bb347cedf7e7,80ea9983cef11eb47559726f99398e3b9b520004..f174d25720add024816b2eca582e9d69de0ad084
@@@ -25,21 -25,25 +25,21 @@@ Boston, MA 02110-1301, USA.  *
  #include <stdio.h>
  #include <stdlib.h>
  #include "lisp.h"
 -#include "charset.h"
  #include "blockinput.h"
 -
 -#include "w32heap.h"
  #include "w32term.h"
 -#include "w32bdf.h"
 -#include <shellapi.h>
  
  #include "systty.h"
  #include "systime.h"
 -#include "atimer.h"
 -#include "keymap.h"
  
  #include <ctype.h>
  #include <errno.h>
  #include <setjmp.h>
  #include <sys/stat.h>
  
 -#include "keyboard.h"
 +#include "charset.h"
 +#include "character.h"
 +#include "coding.h"
 +#include "ccl.h"
  #include "frame.h"
  #include "dispextern.h"
  #include "fontset.h"
  #include "disptab.h"
  #include "buffer.h"
  #include "window.h"
 +#include "keyboard.h"
  #include "intervals.h"
 -#include "composite.h"
 -#include "coding.h"
 +#include "process.h"
 +#include "atimer.h"
 +#include "keymap.h"
 +
 +#include "w32heap.h"
 +#include "w32bdf.h"
 +#include <shellapi.h>
 +
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
  
  \f
  /* Fringe bitmaps.  */
@@@ -125,31 -119,6 +125,31 @@@ struct w32_display_info *x_display_list
     FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
  Lisp_Object w32_display_name_list;
  
 +
 +#ifndef GLYPHSET
 +/* Pre Windows 2000, this was not available, but define it here so
 +   that Emacs compiled on such a platform will run on newer versions.  */
 +
 +typedef struct tagWCRANGE
 +{
 +  WCHAR wcLow;
 +  USHORT cGlyphs;
 +} WCRANGE;
 +
 +typedef struct tagGLYPHSET 
 +{
 +  DWORD cbThis;
 +  DWORD flAccel;
 +  DWORD cGlyphsSupported;
 +  DWORD cRanges;
 +  WCRANGE ranges[1];
 +} GLYPHSET;  
 +
 +#endif
 +
 +/* Dynamic linking to GetFontUnicodeRanges (not available on 95, 98, ME).  */
 +DWORD (PASCAL *pfnGetFontUnicodeRanges) (HDC device, GLYPHSET *ranges);
 +
  /* Frame being updated by update_frame.  This is declared in term.c.
     This is set by update_begin and looked at by all the
     w32 functions.  It is zero while not inside an update.
@@@ -898,8 -867,7 +898,8 @@@ w32_reset_terminal_modes (struct termin
  /* Function prototypes of this page.  */
  
  XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
 -static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
 +static int w32_encode_char P_ ((int, wchar_t *, struct font_info *,
 +                              struct charset *, int *));
  
  
  /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
@@@ -1024,8 -992,8 +1024,8 @@@ w32_native_per_char_metric (font, char2
  
        if (retval)
        {
 -        pcm->width = sz.cx - font->tm.tmOverhang;
 -        pcm->rbearing = sz.cx;
 +        pcm->width = sz.cx;
 +        pcm->rbearing = sz.cx + font->tm.tmOverhang;
          pcm->lbearing = 0;
          pcm->ascent = FONT_BASE (font);
          pcm->descent = FONT_DESCENT (font);
@@@ -1106,9 -1074,9 +1106,9 @@@ w32_cache_char_metrics (font
          {
            /* Use the font width and height as max bounds, as not all BDF
               fonts contain the letter 'x'. */
 -          font->max_bounds.width = FONT_MAX_WIDTH (font);
 +          font->max_bounds.width = FONT_WIDTH (font);
            font->max_bounds.lbearing = -font->bdf->llx;
 -          font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
 +          font->max_bounds.rbearing = FONT_WIDTH (font) - font->bdf->urx;
            font->max_bounds.ascent = FONT_BASE (font);
            font->max_bounds.descent = FONT_DESCENT (font);
          }
  
  
  /* Determine if a font is double byte. */
- int w32_font_is_double_byte (XFontStruct *font)
+ static int
+ w32_font_is_double_byte (XFontStruct *font)
  {
    return font->double_byte_p;
  }
@@@ -1163,13 -1132,13 +1164,13 @@@ w32_use_unicode_for_codepage (codepage
     the two-byte form of C.  Encoding is returned in *CHAR2B.  */
  
  static int /* enum w32_char_font_type */
 -w32_encode_char (c, char2b, font_info, two_byte_p)
 +w32_encode_char (c, char2b, font_info, charset, two_byte_p)
       int c;
       wchar_t *char2b;
       struct font_info *font_info;
 +     struct charset *charset;
       int * two_byte_p;
  {
 -  int charset = CHAR_CHARSET (c);
    int codepage;
    int unicode_p = 0;
    int internal_two_byte_p = 0;
    XFontStruct *font = font_info->font;
  
    internal_two_byte_p = w32_font_is_double_byte (font);
 +  codepage = font_info->codepage;
 +
 +  /* If font can output unicode, use the original unicode character.  */
 +  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
 +       && c >= 0x100)
 +    {
 +      *char2b = c;
 +      unicode_p = 1;
 +      internal_two_byte_p = 1;
 +    }
  
    /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
       This may be either a program in a special encoder language or a
       fixed encoding.  */
 -  if (font_info->font_encoder)
 +  else if (font_info->font_encoder)
      {
        /* It's a program.  */
        struct ccl_program *ccl = font_info->font_encoder;
  
        if (CHARSET_DIMENSION (charset) == 1)
        {
 -        ccl->reg[0] = charset;
 +        ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
        else
        {
 -        ccl->reg[0] = charset;
 +        ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
          ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
  
 -      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
 +      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
  
        /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
        else
        STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
      }
 -  else if (font_info->encoding[charset])
 +  else if (font_info->encoding_type)
      {
        /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
 -      int enc = font_info->encoding[charset];
 +      unsigned char enc = font_info->encoding_type;
  
        if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
  
 -      if (enc == 1 || enc == 3
 -          || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
 +      if (enc == 1 || enc == 3          || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
        else if (enc == 4)
          {
 -          int sjis1, sjis2;
 -
 -          ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
 -                       sjis1, sjis2);
 -          STORE_XCHAR2B (char2b, sjis1, sjis2);
 -        }
 -    }
 -  codepage = font_info->codepage;
 +          int code = (int) (*char2b);
  
 -  /* If charset is not ASCII or Latin-1, may need to move it into
 -     Unicode space.  */
 -  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
 -       && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
 -       && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
 -    {
 -      char temp[3];
 -      temp[0] = XCHAR2B_BYTE1 (char2b);
 -      temp[1] = XCHAR2B_BYTE2 (char2b);
 -      temp[2] = '\0';
 -      if (codepage != CP_UNICODE)
 -        {
 -          if (temp[0])
 -            MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
 -          else
 -            MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
 +        JIS_TO_SJIS (code);
 +          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
          }
 -      unicode_p = 1;
 -      internal_two_byte_p = 1;
      }
  
    if (two_byte_p)
  }
  
  
 +/* Return a char-table whose elements are t if the font FONT_INFO
 +   contains a glyph for the corresponding character, and nil if not.
 +
 +   Fixme: For the moment, this function works only for fonts whose
 +   glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts).  */
 +
 +Lisp_Object
 +x_get_font_repertory (f, font_info)
 +     FRAME_PTR f;
 +     struct font_info *font_info;
 +{
 +  XFontStruct *font = (XFontStruct *) font_info->font;
 +  Lisp_Object table;
 +  int min_byte1, max_byte1, min_byte2, max_byte2;
 +  int c;
 +  struct charset *charset = CHARSET_FROM_ID (font_info->charset);
 +  int offset = CHARSET_OFFSET (charset);
 +
 +  table = Fmake_char_table (Qnil, Qnil);
 +
 +  if (!font->bdf && pfnGetFontUnicodeRanges)
 +    {
 +      GLYPHSET *glyphset;
 +      DWORD glyphset_size;
 +      HDC display = get_frame_dc (f);
 +      HFONT prev_font;
 +      int i;
 +
 +      prev_font = SelectObject (display, font->hfont);
 +
 +      /* First call GetFontUnicodeRanges to find out how big a structure
 +       we need.  */
 +      glyphset_size = pfnGetFontUnicodeRanges (display, NULL);
 +      if (glyphset_size)
 +      {
 +        glyphset = (GLYPHSET *) alloca (glyphset_size);
 +        glyphset->cbThis = glyphset_size;
 +
 +        /* Now call it again to get the ranges.  */
 +        glyphset_size = pfnGetFontUnicodeRanges (display, glyphset);
 +
 +        if (glyphset_size)
 +          {
 +            /* Store the ranges in TABLE.  */
 +            for (i = 0; i < glyphset->cRanges; i++)
 +              {
 +                int from = glyphset->ranges[i].wcLow;
 +                int to = from + glyphset->ranges[i].cGlyphs - 1;
 +                char_table_set_range (table, from, to, Qt);
 +              }
 +          }
 +      }
 +
 +      SelectObject (display, prev_font);
 +      release_frame_dc (f, display);
 +
 +      /* If we got the information we wanted above, then return it.  */
 +      if (glyphset_size)
 +      return table;
 +    }
 +
 +#if 0 /* TODO: Convert to work on Windows so BDF and older platforms work.  */
 +  /* When GetFontUnicodeRanges is not available or does not work,
 +     work it out manually.  */
 +  min_byte1 = font->min_byte1;
 +  max_byte1 = font->max_byte1;
 +  min_byte2 = font->min_char_or_byte2;
 +  max_byte2 = font->max_char_or_byte2;
 +  if (min_byte1 == 0 && max_byte1 == 0)
 +    {
 +      if (! font->per_char || font->all_chars_exist == True)
 +        {
 +          if (offset >= 0)
 +            char_table_set_range (table, offset + min_byte2,
 +                                  offset + max_byte2, Qt);
 +          else
 +            for (; min_byte2 <= max_byte2; min_byte2++)
 +              {
 +                c = DECODE_CHAR (charset, min_byte2);
 +                CHAR_TABLE_SET (table, c, Qt);
 +              }
 +        }
 +      else
 +      {
 +        XCharStruct *pcm = font->per_char;
 +        int from = -1;
 +        int i;
 +
 +        for (i = min_byte2; i <= max_byte2; i++, pcm++)
 +          {
 +            if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
 +              {
 +                if (from >= 0)
 +                  {
 +                      if (offset >= 0)
 +                        char_table_set_range (table, offset + from,
 +                                              offset + i - 1, Qt);
 +                      else
 +                        for (; from < i; from++)
 +                          {
 +                            c = DECODE_CHAR (charset, from);
 +                            CHAR_TABLE_SET (table, c, Qt);
 +                          }
 +                    from = -1;
 +                  }
 +              }
 +            else if (from < 0)
 +              from = i;
 +          }
 +        if (from >= 0)
 +            {
 +              if (offset >= 0)
 +                char_table_set_range (table, offset + from, offset + i - 1,
 +                                      Qt);
 +              else
 +                for (; from < i; from++)
 +                  {
 +                    c = DECODE_CHAR (charset, from);
 +                    CHAR_TABLE_SET (table, c, Qt);
 +                  }
 +            }
 +      }
 +    }
 +  else
 +    {
 +      if (! font->per_char || font->all_chars_exist == True)
 +      {
 +        int i, j;
 +
 +          if (offset >= 0)
 +            for (i = min_byte1; i <= max_byte1; i++)
 +              char_table_set_range
 +                (table, offset + ((i << 8) | min_byte2),
 +                 offset + ((i << 8) | max_byte2), Qt);
 +          else
 +            for (i = min_byte1; i <= max_byte1; i++)
 +              for (j = min_byte2; j <= max_byte2; j++)
 +                {
 +                  unsiged code = (i << 8) | j;
 +                  c = DECODE_CHAR (charset, code);
 +                  CHAR_TABLE_SET (table, c, Qt);
 +                }
 +      }
 +      else
 +      {
 +        XCharStruct *pcm = font->per_char;
 +        int i;
 +
 +        for (i = min_byte1; i <= max_byte1; i++)
 +          {
 +            int from = -1;
 +            int j;
 +
 +            for (j = min_byte2; j <= max_byte2; j++, pcm++)
 +              {
 +                if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
 +                  {
 +                    if (from >= 0)
 +                      {
 +                          if (offset >= 0)
 +                            char_table_set_range
 +                              (table, offset + ((i << 8) | from),
 +                               offset + ((i << 8) | (j - 1)), Qt);
 +                          else
 +                            {
 +                              for (; from < j; from++)
 +                                {
 +                                  unsigned code = (i << 8) | from;
 +                                  c = ENCODE_CHAR (charset, code);
 +                                  CHAR_TABLE_SET (table, c, Qt);
 +                                }
 +                            }
 +                        from = -1;
 +                      }
 +                  }
 +                else if (from < 0)
 +                  from = j;
 +              }
 +            if (from >= 0)
 +                {
 +                  if (offset >= 0)
 +                    char_table_set_range
 +                      (table, offset + ((i << 8) | from),
 +                       offset + ((i << 8) | (j - 1)), Qt);
 +                  else
 +                    {
 +                      for (; from < j; from++)
 +                        {
 +                          unsigned code = (i << 8) | from;
 +                          c = DECODE_CHAR (charset, code);
 +                          CHAR_TABLE_SET (table, c, Qt);
 +                        }
 +                    }
 +                }
 +          }
 +      }
 +    }
 +#endif
 +  return table;
 +}
 +
  \f
  /***********************************************************************
                            Glyph display
@@@ -1585,20 -1367,15 +1586,20 @@@ x_set_mouse_face_gc (s
      face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
  
    if (s->first_glyph->type == CHAR_GLYPH)
 -    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
 +    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
    else
 -    face_id = FACE_FOR_CHAR (s->f, face, 0);
 +    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
    s->face = FACE_FROM_ID (s->f, face_id);
    PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
  
    /* If font in this face is same as S->font, use it.  */
    if (s->font == s->face->font)
      s->gc = s->face->gc;
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
 +    /* No need of setting a font for s->gc.  */
 +    s->gc = s->face->gc;
 +#endif        /* USE_FONT_BACKEND */
    else
      {
        /* Otherwise construct scratch_cursor_gc with values from FACE
@@@ -1692,68 -1469,11 +1693,68 @@@ static INLINE voi
  x_set_glyph_string_clipping (s)
       struct glyph_string *s;
  {
 -  RECT r;
 -  get_glyph_string_clip_rect (s, &r);
 -  w32_set_clip_rectangle (s->hdc, &r);
 +#ifdef USE_FONT_BACKEND
 +  RECT *r = s->clip;
 +#else
 +  RECT r[2];
 +#endif
 +  int n = get_glyph_string_clip_rects (s, r, 2);
 +
 +  if (n == 1)
 +    w32_set_clip_rectangle (s->hdc, r);
 +  else if (n > 1)
 +    {
 +      HRGN full_clip, clip1, clip2;
 +      clip1 = CreateRectRgnIndirect (r);
 +      clip2 = CreateRectRgnIndirect (r + 1);
 +      if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
 +        {
 +          SelectClipRgn (s->hdc, full_clip);
 +        }
 +      DeleteObject (clip1);
 +      DeleteObject (clip2);
 +      DeleteObject (full_clip);
 +    }
 +#ifdef USE_FONT_BACKEND
 +    s->num_clips = n;
 +#endif        /* USE_FONT_BACKEND */
  }
  
 +/* Set SRC's clipping for output of glyph string DST.  This is called
 +   when we are drawing DST's left_overhang or right_overhang only in
 +   the area of SRC.  */
 +
 +static void
 +x_set_glyph_string_clipping_exactly (src, dst)
 +     struct glyph_string *src, *dst;
 +{
 +  RECT r;
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      r.left = src->x;
 +      r.right = r.left + src->width;
 +      r.top = src->y;
 +      r.bottom = r.top + src->height;
 +      dst->clip[0] = r;
 +      dst->num_clips = 1;
 +    }
 +  else
 +    {
 +#endif        /* USE_FONT_BACKEND */
 +  struct glyph_string *clip_head = src->clip_head;
 +  struct glyph_string *clip_tail = src->clip_tail;
 +
 +  /* This foces clipping just this glyph string.  */
 +  src->clip_head = src->clip_tail = src;
 +  get_glyph_string_clip_rect (src, &r);
 +  src->clip_head = clip_head, src->clip_tail = clip_tail;
 +#ifdef USE_FONT_BACKEND
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +  w32_set_clip_rectangle (dst->hdc, &r);
 +}
  
  /* RIF:
     Compute left and right overhang of glyph string S.  If S is a glyph
@@@ -1869,7 -1589,7 +1870,7 @@@ x_draw_glyph_string_foreground (s
       of S to the right of that box line.  */
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
            x += g->pixel_width;
          }
      }
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
 +    {
 +      int boff = s->font_info->baseline_offset;
 +      struct font *font = (struct font *) s->font_info;
 +      int y;
 +
 +      if (s->font_info->vertical_centering)
 +      boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
 +
 +      y = s->ybase - boff;
 +      if (s->for_overlaps
 +        || (s->background_filled_p && s->hl != DRAW_CURSOR))
 +      font->driver->draw (s, 0, s->nchars, x, y, 0);
 +      else
 +      font->driver->draw (s, 0, s->nchars, x, y, 1);
 +      if (s->face->overstrike)
 +      font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
 +    }
 +#endif        /* USE_FONT_BACKEND */
    else
      {
        char *char1b = (char *) s->char2b;
@@@ -1954,14 -1654,14 +1955,14 @@@ static voi
  x_draw_composite_glyph_string_foreground (s)
       struct glyph_string *s;
  {
 -  int i, x;
 +  int i, j, x;
    HFONT old_font;
  
    /* If first glyph of S has a left box line, start drawing the text
       of S to the right of that box line.  */
 -  if (s->face->box != FACE_NO_BOX
 +  if (s->face && s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
          w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
                              s->height - 1);
      }
 -  else
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
      {
 -      for (i = 0; i < s->nchars; i++, ++s->gidx)
 +      struct font *font = (struct font *) s->font_info;
 +      int y = s->ybase;
 +      int width = 0;
 +
 +      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
 +      {
 +        Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
 +                                    ->key_and_value,
 +                                    s->cmp->hash_index * 2);
 +        int from;
 +
 +        for (i = from = 0; i < s->nchars; i++)
 +          {
 +            Lisp_Object g = LGSTRING_GLYPH (gstring, i);
 +            Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
 +            int xoff, yoff, wadjust;
 +
 +            if (! VECTORP (adjustment))
 +              {
 +                width += XINT (LGLYPH_WIDTH (g));
 +                continue;
 +              }
 +            if (from < i)
 +              {
 +                font->driver->draw (s, from, i, x, y, 0);
 +                x += width;
 +              }
 +            xoff = XINT (AREF (adjustment, 0));
 +            yoff = XINT (AREF (adjustment, 1));
 +            wadjust = XINT (AREF (adjustment, 2));
 +
 +            font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
 +            x += XINT (LGLYPH_WIDTH (g)) + wadjust;
 +            from = i + 1;
 +            width = 0;
 +          }
 +        if (from < i)
 +          font->driver->draw (s, from, i, x, y, 0);
 +      }
 +      else
        {
 -        w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
 -                      s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
 -                      s->char2b + i, 1);
 -        if (s->face->overstrike)
 -          w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
 -                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
 -                        s->char2b + i, 1);
 +        for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
 +          if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
 +            {
 +              int xx = x + s->cmp->offsets[j * 2];
 +              int yy = y - s->cmp->offsets[j * 2 + 1];
 +
 +              font->driver->draw (s, j, j + 1, xx, yy, 0);
 +              if (s->face->overstrike)
 +                font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
 +            }
        }
      }
 +#endif        /* USE_FONT_BACKEND */
 +  else
 +    {
 +      for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
 +      if (s->face)
 +          {
 +            w32_text_out (s, x + s->cmp->offsets[j * 2],
 +                          s->ybase - s->cmp->offsets[j * 2 + 1],
 +                          s->char2b + j, 1);
 +            if (s->face->overstrike)
 +          w32_text_out (s, x + s->cmp->offsets[j * 2] + 1,
 +                        s->ybase - s->cmp->offsets[j + 1],
 +                        s->char2b + j, 1);
 +          }
 +    }
  
    if (s->font && s->font->hfont)
      SelectObject (s->hdc, old_font);
@@@ -2349,7 -1991,7 +2350,7 @@@ x_draw_glyph_string_box (s
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
  
-   width = abs (s->face->box_line_width);
+   width = eabs (s->face->box_line_width);
    raised_p = s->face->box == FACE_RAISED_BOX;
    left_x = s->x;
    right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@@ -2395,7 -2037,7 +2396,7 @@@ x_draw_image_foreground (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
@@@ -2488,7 -2130,7 +2489,7 @@@ x_draw_image_relief (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
      }
    else
      {
-       thick = abs (s->img->relief);
+       thick = eabs (s->img->relief);
        raised_p = s->img->relief > 0;
      }
  
@@@ -2542,7 -2184,7 +2543,7 @@@ w32_draw_image_foreground_1 (s, pixmap
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
@@@ -2654,7 -2296,7 +2655,7 @@@ x_draw_image_glyph_string (s
       struct glyph_string *s;
  {
    int x, y;
-   int box_line_hwidth = abs (s->face->box_line_width);
+   int box_line_hwidth = eabs (s->face->box_line_width);
    int box_line_vwidth = max (s->face->box_line_width, 0);
    int height;
    HBITMAP pixmap = 0;
@@@ -2858,19 -2500,10 +2859,19 @@@ x_draw_glyph_string (s
       This makes S->next use XDrawString instead of XDrawImageString.  */
    if (s->next && s->right_overhang && !s->for_overlaps)
      {
 -      xassert (s->next->img == NULL);
 -      x_set_glyph_string_gc (s->next);
 -      x_set_glyph_string_clipping (s->next);
 -      x_draw_glyph_string_background (s->next, 1);
 +      int width;
 +      struct glyph_string *next;
 +      for (width = 0, next = s->next; next;
 +           width += next->width, next = next->next)
 +        if (next->first_glyph->type != IMAGE_GLYPH)
 +          {
 +            x_set_glyph_string_gc (next);
 +            x_set_glyph_string_clipping (next);
 +            x_draw_glyph_string_background (next, 1);
 +#ifdef USE_FONT_BACKEND
 +            next->num_clips = 0;
 +#endif /* USE_FONT_BACKEND */
 +          }
      }
  
    /* Set up S->gc, set clipping and draw S.  */
        x_set_glyph_string_clipping (s);
        relief_drawn_p = 1;
      }
 +  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
 +         || (s->next && s->next->hl != s->hl && s->right_overhang))
 +    /* We must clip just this glyph.  left_overhang part has already
 +       drawn when s->prev was drawn, and right_overhang part will be
 +       drawn later when s->next is drawn. */
 +    x_set_glyph_string_clipping_exactly (s, s);
    else
      x_set_glyph_string_clipping (s);
  
        if (s->face->underline_p
            && (s->font->bdf || !s->font->tm.tmUnderlined))
          {
 -          unsigned long h = 1;
 -          unsigned long dy = 0;
 +          unsigned long h;
 +          int y;
 +        /* Get the underline thickness.  Default is 1 pixel.  */
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend)
 +          /* In the future, we must use information of font.  */
 +          h = 1;
 +        else
 +#endif        /* USE_FONT_BACKEND */
 +            h = 1;
  
 -          if (x_underline_at_descent_line)
 -            dy = s->height - h;
 -          else
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend)
 +          {
 +            if (s->face->font)
 +              /* In the future, we must use information of font.  */
 +              y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
 +            else
 +              y = s->y + s->height - h;
 +          }
 +        else
 +#endif
              {
 -              /* TODO: Use font information for positioning and thickness of
 -                 underline.  See OUTLINETEXTMETRIC, and xterm.c.  Note: If
 -                 you make this work, don't forget to change the doc string of
 -                 x-use-underline-position-properties below.  */
 -              dy = s->height - h;
 +                y = s->y + s->height - h;
 +                /* TODO: Use font information for positioning and
 +                   thickness of underline.  See OUTLINETEXTMETRIC,
 +                   and xterm.c.  Note: If you make this work,
 +                   don't forget to change the doc string of
 +                   x-use-underline_color-position-properties
 +                   below.  */
 +#if 0
 +              if (!x_underline_at_descent_line)
 +                {
 +                  ...
 +                }
 +#endif
              }
            if (s->face->underline_defaulted_p)
              {
                w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
 -                             s->y + dy, s->background_width, 1);
 +                             y, s->background_width, 1);
              }
            else
              {
                w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
 -                             s->y + dy, s->background_width, 1);
 +                             y, s->background_width, 1);
              }
          }
 -
        /* Draw overline.  */
        if (s->face->overline_p)
          {
            unsigned long dy = 0, h = 1;
  
            if (s->face->overline_color_defaulted_p)
 -          {
 -            w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
 -                         s->y + dy, s->background_width, h);
 -          }
 +            {
 +              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
 +                             s->y + dy, s->background_width, h);
 +            }
            else
              {
                w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
              }
          }
  
 -      /* Draw relief.  */
 +      /* Draw relief if not yet drawn.  */
        if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
          x_draw_glyph_string_box (s);
 +
 +      if (s->prev)
 +        {
 +          struct glyph_string *prev;
 +
 +          for (prev = s->prev; prev; prev = prev->prev)
 +            if (prev->hl != s->hl
 +                && prev->x + prev->width + prev->right_overhang > s->x)
 +              {
 +                /* As prev was drawn while clipped to its own area, we
 +                   must draw the right_overhang part using s->hl now.  */
 +              enum draw_glyphs_face save = prev->hl;
 +
 +              prev->hl = s->hl;
 +              x_set_glyph_string_gc (prev);
 +              x_set_glyph_string_clipping_exactly (s, prev);
 +              if (prev->first_glyph->type == CHAR_GLYPH)
 +                x_draw_glyph_string_foreground (prev);
 +              else
 +                x_draw_composite_glyph_string_foreground (prev);
 +                w32_set_clip_rectangle (prev->hdc, NULL);
 +              prev->hl = save;
 +#ifdef USE_FONT_BACKEND
 +              prev->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
 +            }
 +      }
 +
 +      if (s->next)
 +      {
 +        struct glyph_string *next;
 +
 +        for (next = s->next; next; next = next->next)
 +          if (next->hl != s->hl
 +              && next->x - next->left_overhang < s->x + s->width)
 +            {
 +              /* As next will be drawn while clipped to its own area,
 +                 we must draw the left_overhang part using s->hl now.  */
 +              enum draw_glyphs_face save = next->hl;
 +
 +              next->hl = s->hl;
 +              x_set_glyph_string_gc (next);
 +              x_set_glyph_string_clipping_exactly (s, next);
 +              if (next->first_glyph->type == CHAR_GLYPH)
 +                x_draw_glyph_string_foreground (next);
 +              else
 +                x_draw_composite_glyph_string_foreground (next);
 +                w32_set_clip_rectangle (next->hdc, NULL);
 +              next->hl = save;
 +#ifdef USE_FONT_BACKEND
 +              next->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
 +            }
 +      }
      }
  
    /* Reset clipping.  */
    w32_set_clip_rectangle (s->hdc, NULL);
 +#ifdef USE_FONT_BACKEND
 +  s->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
  }
  
  
@@@ -3358,9 -2905,9 +3359,9 @@@ x_focus_changed (type, state, dpyinfo, 
  
            /* Don't stop displaying the initial startup message
               for a switch-frame event we don't need.  */
 -          if (GC_NILP (Vterminal_frame)
 -              && GC_CONSP (Vframe_list)
 -              && !GC_NILP (XCDR (Vframe_list)))
 +          if (NILP (Vterminal_frame)
 +              && CONSP (Vframe_list)
 +              && !NILP (XCDR (Vframe_list)))
              {
                bufp->kind = FOCUS_IN_EVENT;
                XSETFRAME (bufp->frame_or_window, frame);
@@@ -3446,7 -2993,7 +3447,7 @@@ x_frame_rehighlight (dpyinfo
    if (dpyinfo->w32_focus_frame)
      {
        dpyinfo->x_highlight_frame
 -      = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
 +      = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
           : dpyinfo->w32_focus_frame);
        if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@@ -3705,9 -3252,6 +3706,9 @@@ note_mouse_movement (frame, msg
    memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
    XSETFRAME (last_mouse_motion_frame, frame);
  
 +  if (!FRAME_X_OUTPUT (frame))
 +    return 0;
 +
    if (msg->hwnd != FRAME_W32_WINDOW (frame))
      {
        frame->mouse_moved = 1;
@@@ -3915,13 -3459,15 +3916,13 @@@ x_window_to_scroll_bar (window_id
  {
    Lisp_Object tail;
  
 -  for (tail = Vframe_list;
 -       XGCTYPE (tail) == Lisp_Cons;
 -       tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        Lisp_Object frame, bar, condemned;
  
        frame = XCAR (tail);
        /* All elements of Vframe_list should be frames.  */
 -      if (! GC_FRAMEP (frame))
 +      if (! FRAMEP (frame))
        abort ();
  
        /* Scan this frame's scroll bar list for a scroll bar with the
        for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
           /* This trick allows us to search both the ordinary and
              condemned scroll bar lists with one loop.  */
 -         ! GC_NILP (bar) || (bar = condemned,
 +         ! NILP (bar) || (bar = condemned,
                               condemned = Qnil,
 -                             ! GC_NILP (bar));
 +                             ! NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
@@@ -4023,7 -3569,7 +4024,7 @@@ w32_set_scroll_bar_thumb (bar, portion
                         Scroll bars, general
   ************************************************************************/
  
- HWND
static HWND
  my_create_scrollbar (f, bar)
       struct frame * f;
       struct scroll_bar * bar;
@@@ -4422,7 -3968,7 +4423,7 @@@ w32_scroll_bar_handle_click (bar, msg, 
       W32Msg *msg;
       struct input_event *emacs_event;
  {
 -  if (! GC_WINDOWP (bar->window))
 +  if (! WINDOWP (bar->window))
      abort ();
  
    emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
@@@ -4637,7 -4183,7 +4638,7 @@@ static short temp_buffer[100]
  
     Some of these messages are reposted back to the message queue since the
     system calls the windows proc directly in a context where we cannot return
-    the data nor can we guarantee the state we are in.  So if we dispatch  them
+    the data nor can we guarantee the state we are in.  So if we dispatch them
     we will get into an infinite loop.  To prevent this from ever happening we
     will set a variable to indicate we are in the read_socket call and indicate
     which message we are processing since the windows proc gets called
@@@ -5758,16 -5304,11 +5759,16 @@@ x_new_font (f, fontname
       register char *fontname;
  {
    struct font_info *fontp
 -    = FS_LOAD_FONT (f, 0, fontname, -1);
 +    = FS_LOAD_FONT (f, fontname);
  
    if (!fontp)
      return Qnil;
  
 +  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
 +    /* This font is already set in frame F.  There's nothing more to
 +       do.  */
 +    return build_string (fontp->full_name);
 +
    FRAME_FONT (f) = (XFontStruct *) (fontp->font);
    FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
    FRAME_FONTSET (f) = -1;
    return build_string (fontp->full_name);
  }
  \f
 -/* Give frame F the fontset named FONTSETNAME as its default font, and
 -   return the full name of that fontset.  FONTSETNAME may be a wildcard
 -   pattern; in that case, we choose some fontset that fits the pattern.
 -   The return value shows which fontset we chose.  */
 +/* Give frame F the fontset named FONTSETNAME as its default fontset,
 +   and return the full name of that fontset.  FONTSETNAME may be a
 +   wildcard pattern; in that case, we choose some fontset that fits
 +   the pattern.  FONTSETNAME may be a font name for ASCII characters;
 +   in that case, we create a fontset from that font name.
 +
 +   The return value shows which fontset we chose.
 +   If FONTSETNAME specifies the default fontset, return Qt.
 +   If an ASCII font in the specified fontset can't be loaded, return
 +   Qnil.  */
  
  Lisp_Object
  x_new_fontset (f, fontsetname)
       struct frame *f;
 -     char *fontsetname;
 +     Lisp_Object fontsetname;
  {
 -  int fontset = fs_query_fontset (build_string (fontsetname), 0);
 +  int fontset = fs_query_fontset (fontsetname, 0);
    Lisp_Object result;
  
 -  if (fontset < 0)
 -    return Qnil;
 -
 -  if (FRAME_FONTSET (f) == fontset)
 +  if (fontset > 0 && FRAME_FONTSET(f) == fontset)
      /* This fontset is already set in frame F.  There's nothing more
         to do.  */
      return fontset_name (fontset);
 +  else if (fontset == 0)
 +    /* The default fontset can't be the default font.   */
 +    return Qt;
  
 -  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  if (fontset > 0)
 +    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  else
 +    result = x_new_font (f, SDATA (fontsetname));
  
    if (!STRINGP (result))
      /* Can't load ASCII font.  */
      return Qnil;
  
 +  if (fontset < 0)
 +    fontset = new_fontset_from_font_name (result);
 +
    /* Since x_new_font doesn't update any fontset information, do it now.  */
    FRAME_FONTSET(f) = fontset;
  
 -  return build_string (fontsetname);
 +  return fontset_name (fontset);
 +}
 +
 +#ifdef USE_FONT_BACKEND
 +Lisp_Object
 +x_new_fontset2 (f, fontset, font_object)
 +     struct frame *f;
 +     int fontset;
 +     Lisp_Object font_object;
 +{
 +  struct font *font = XSAVE_VALUE (font_object)->pointer;
 +
 +  if (FRAME_FONT_OBJECT (f) == font)
 +    /* This font is already set in frame F.  There's nothing more to
 +       do.  */
 +    return fontset_name (fontset);
 +
 +  BLOCK_INPUT;
 +
 +  FRAME_FONT_OBJECT (f) = font;
 +  FRAME_FONT (f) = font->font.font;
 +  FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
 +  FRAME_FONTSET (f) = fontset;
 +
 +  FRAME_COLUMN_WIDTH (f) = font->font.average_width;
 +  FRAME_SPACE_WIDTH (f) = font->font.space_width;
 +  FRAME_LINE_HEIGHT (f) = font->font.height;
 +
 +  compute_fringe_widths (f, 1);
 +
 +  /* Compute the scroll bar width in character columns.  */
 +  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
 +    {
 +      int wid = FRAME_COLUMN_WIDTH (f);
 +      FRAME_CONFIG_SCROLL_BAR_COLS (f)
 +      = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
 +    }
 +  else
 +    {
 +      int wid = FRAME_COLUMN_WIDTH (f);
 +      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
 +    }
 +
 +  /* Now make the frame display the given font.  */
 +  if (FRAME_X_WINDOW (f) != 0)
 +    {
 +      /* Don't change the size of a tip frame; there's no point in
 +       doing it because it's done in Fx_show_tip, and it leads to
 +       problems because the tip frame has no widget.  */
 +      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
 +      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
 +    }
 +
 +#ifdef HAVE_X_I18N
 +  if (FRAME_XIC (f)
 +      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
 +    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 +#endif
 +
 +  UNBLOCK_INPUT;
 +
 +  return fontset_name (fontset);
  }
 +#endif        /* USE_FONT_BACKEND */
  
  \f
  /***********************************************************************
@@@ -6097,7 -5564,22 +6098,22 @@@ x_set_window_size (f, change_gravity, c
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
    }
  
-   /* Now, strictly speaking, we can't be sure that this is accurate,
+ #if 0
+   /* The following mirrors what is done in xterm.c. It appears to be
+      for informing lisp of the new size immediately, while the actual
+      resize will happen asynchronously. But on Windows, the menu bar
+      automatically wraps when the frame is too narrow to contain it,
+      and that causes any calculations made here to come out wrong. The
+      end is some nasty buggy behaviour, including the potential loss
+      of the minibuffer.
+      Disabling this code is either not sufficient to fix the problems
+      completely, or it causes fresh problems, but at least it removes
+      the most problematic symptom of the minibuffer becoming unusable.
+      -----------------------------------------------------------------
+      Now, strictly speaking, we can't be sure that this is accurate,
       but the window manager will get around to dealing with the size
       change request eventually, and we'll hear how it went when the
       ConfigureNotify event gets here.
       Actually checking whether it is outside is a pain in the neck,
       so don't try--just let the highlighting be done afresh with new size.  */
    cancel_mouse_face (f);
+ #endif
  
    UNBLOCK_INPUT;
  }
@@@ -6447,15 -5930,6 +6464,15 @@@ x_free_frame_resources (f
  
    BLOCK_INPUT;
  
 +#ifdef USE_FONT_BACKEND
 +      /* We must free faces before destroying windows because some
 +       font-driver (e.g. xft) access a window while finishing a
 +       face.  */
 +      if (enable_font_backend
 +        && FRAME_FACE_CACHE (f))
 +      free_frame_faces (f);
 +#endif        /* USE_FONT_BACKEND */
 +
    if (FRAME_W32_WINDOW (f))
      my_destroy_window (f, FRAME_W32_WINDOW (f));
  
@@@ -6608,7 -6082,7 +6625,7 @@@ x_font_min_bounds (font, w, h
     * average and maximum width, and maximum height.
     */
    *h = FONT_HEIGHT (font);
 -  *w = FONT_WIDTH (font);
 +  *w = FONT_AVG_WIDTH (font);
  }
  
  
@@@ -6714,7 -6188,7 +6731,7 @@@ w32_initialize_display_info (display_na
  
  /* Create an xrdb-style database of resources to supercede registry settings.
     The database is just a concatenation of C strings, finished by an additional
-    \0.  The string are submitted to some basic normalization, so
+    \0.  The strings are submitted to some basic normalization, so
  
       [ *]option[ *]:[ *]value...
  
@@@ -7090,22 -6564,13 +7107,22 @@@ w32_initialize (
    AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
  #endif
  
 -  /* Load system settings.  */
 +  /* Dynamically link to optional system components.  */
    {
      UINT smoothing_type;
      BOOL smoothing_enabled;
  
 -    /* If using proportional scroll bars, ensure handle is at least 5 pixels;
 -       otherwise use the fixed height.  */
 +    HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
 +
 +#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
 +
 +    LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
 +    
 +#undef LOAD_PROC
 +
 +    FreeLibrary (gdi_lib);
 +
 +    /* Ensure scrollbar handle is at least 5 pixels.  */
      vertical_scroll_bar_min_handle = 5;
  
      /* For either kind of scroll bar, take account of the arrows; these
@@@ -7146,7 -6611,8 +7163,7 @@@ syms_of_w32term (
    staticpro (&last_mouse_scroll_bar);
    last_mouse_scroll_bar = Qnil;
  
 -  staticpro (&Qvendor_specific_keysyms);
 -  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 +  DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
  
    DEFVAR_INT ("w32-num-mouse-buttons",
              &w32_num_mouse_buttons,
@@@ -7186,7 -6652,7 +7203,7 @@@ interpreted normally.  */)
  Unicode output may prevent some third party applications for displaying
  Far-East Languages on Windows 95/98 from working properly.
  NT uses Unicode internally anyway, so this flag will probably have no
affect on NT machines.  */);
effect on NT machines.  */);
    w32_enable_unicode_output = 1;
  
    DEFVAR_BOOL ("w32-use-visible-system-caret",
diff --combined src/window.c
index c51649679da97afc2fb9e33c1f635e992c13473f,efdf309121bf50fc333726a40dc5708d69426940..2fd4d286eba64334cfe8e595f63af2133589f01d
@@@ -799,7 -799,7 +799,7 @@@ coordinates_in_window (w, x, y
        if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
          || WINDOW_RIGHTMOST_P (w))
        {
-         if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
+         if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
            {
              /* Convert X and Y to window relative coordinates.
                 Vertical border is at the left edge of window.  */
        }
        else
        {
-         if (abs (*x - x1) < grabbable_width)
+         if (eabs (*x - x1) < grabbable_width)
            {
              /* Convert X and Y to window relative coordinates.
                 Vertical border is at the right edge of window.  */
        if (!w->pseudo_window_p
          && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
          && !WINDOW_RIGHTMOST_P (w)
-         && (abs (*x - right_x) < grabbable_width))
+         && (eabs (*x - right_x) < grabbable_width))
        {
          /* Convert X and Y to window relative coordinates.
             Vertical border is at the right edge of window.  */
@@@ -3790,7 -3790,7 +3790,7 @@@ displayed.  */
        window = call1 (Vsplit_window_preferred_function, window);
        else
        {
 -        Lisp_Object upper, lower, other;
 +        Lisp_Object upper, other;
  
          window = Fget_lru_window (frames, Qt);
          /* If the LRU window is tall enough, and either eligible for
            window = Fframe_selected_window (call0 (Vpop_up_frame_function));
          /* If window appears above or below another,
             even out their heights.  */
 -        other = upper = lower = Qnil;
 +        other = upper = Qnil;
          if (!NILP (XWINDOW (window)->prev))
 -          other = upper = XWINDOW (window)->prev, lower = window;
 +          other = upper = XWINDOW (window)->prev;
          if (!NILP (XWINDOW (window)->next))
 -          other = lower = XWINDOW (window)->next, upper = window;
 +          other = XWINDOW (window)->next, upper = window;
          if (!NILP (other)
              && !NILP (Veven_window_heights)
              /* Check that OTHER and WINDOW are vertically arrayed.  */
@@@ -5497,7 -5497,7 +5497,7 @@@ scroll_command (n, direction
  {
    int count = SPECPDL_INDEX ();
  
-   xassert (abs (direction) == 1);
+   xassert (eabs (direction) == 1);
  
    /* If selected window's buffer isn't current, make it current for
       the moment.  But don't screw up if window_scroll gets an error.  */
diff --combined src/xdisp.c
index 746fa2540f9899f9763dd31e9b7b95432f806a80,b907ea516d6d02e2116835d44297ed8b68658e34..fef50689ab536e03a582cb1b533d57696e2964c8
@@@ -177,7 -177,6 +177,7 @@@ Boston, MA 02110-1301, USA.  *
  #include "termchar.h"
  #include "dispextern.h"
  #include "buffer.h"
 +#include "character.h"
  #include "charset.h"
  #include "indent.h"
  #include "commands.h"
  #include "macterm.h"
  #endif
  
 +#ifdef HAVE_WINDOW_SYSTEM
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +#endif        /* HAVE_WINDOW_SYSTEM */
 +
  #ifndef FRAME_X_OUTPUT
  #define FRAME_X_OUTPUT(f) ((f)->output_data.x)
  #endif
@@@ -751,7 -744,6 +751,7 @@@ 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.  */
  
@@@ -763,7 -755,6 +763,7 @@@ static struct props it_props[] 
    {&Qface,            FACE_PROP_IDX,          handle_face_prop},
    {&Qdisplay,         DISPLAY_PROP_IDX,       handle_display_prop},
    {&Qinvisible,               INVISIBLE_PROP_IDX,     handle_invisible_prop},
 +  {&Qauto_composed,   AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop},
    {&Qcomposition,     COMPOSITION_PROP_IDX,   handle_composition_prop},
    {NULL,              0,                      NULL}
  };
@@@ -1932,14 -1923,6 +1932,14 @@@ get_glyph_string_clip_rects (s, rects, 
        }
      }
  
 +  if (s->row->clip)
 +    {
 +      XRectangle r_save = r;
 +
 +      if (! x_intersect_rectangles (&r_save, s->row->clip, &r))
 +      r.width = 0;
 +    }
 +
    if ((s->for_overlaps & OVERLAPS_BOTH) == 0
        || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
      {
@@@ -3508,7 -3491,7 +3508,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);
        }
      }
  
@@@ -3724,6 -3707,10 +3724,10 @@@ handle_invisible_prop (it
                  it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
                }
                setup_for_ellipsis (it, 0);
+             /* Let the ellipsis display before
+                considering any properties of the following char.
+                Fixes jasonr@gnu.org 01 Oct 07 bug.  */
+             handled = HANDLED_RETURN;
              }
        }
      }
@@@ -4123,7 -4110,7 +4127,7 @@@ handle_single_display_spec (it, spec, o
        {
          Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
          int face_id2 = lookup_derived_face (it->f, face_name,
 -                                            'A', FRINGE_FACE_ID, 0);
 +                                            FRINGE_FACE_ID, 0);
          if (face_id2 >= 0)
            face_id = face_id2;
        }
@@@ -4474,117 -4461,6 +4478,117 @@@ 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[4];
 +
 +        args[0] = Vauto_composition_function;
 +        specbind (Qauto_composition_function, Qnil);
 +        args[1] = make_number (pos);
 +        args[2] = it->string;
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend)
 +          {
 +            struct face *face = FACE_FROM_ID (it->f, it->face_id);
 +            int c;
 +
 +            if (STRINGP (it->string))
 +              {
 +                EMACS_INT pos_byte = IT_STRING_BYTEPOS (*it);
 +                const unsigned char *s = SDATA (it->string) + pos_byte;
 +
 +                if (STRING_MULTIBYTE (it->string))
 +                  it->c = STRING_CHAR (s, 0);
 +                else
 +                  it->c = *s;
 +              }
 +            else
 +              {
 +                EMACS_INT pos_byte = IT_BYTEPOS (*it);
 +
 +                it->c = FETCH_CHAR (pos_byte);
 +              }
 +            args[3] = font_at (it->c, this_pos, face, it->w, it->string);
 +          }
 +        else
 +#endif        /* USE_FONT_BACKEND */
 +          args[3] = Qnil;
 +        safe_call (4, 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.  */
  
@@@ -4593,7 -4469,7 +4597,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)
        {
          it->method = GET_FROM_COMPOSITION;
          it->cmp_id = id;
          it->cmp_len = COMPOSITION_LENGTH (prop);
 -        /* For a terminal, draw only the first character of the
 -             components.  */
 -        it->c = COMPOSITION_GLYPH (composition_table[id], 0);
 +        /* For a terminal, draw only the first (non-TAB) character
 +           of the components.  */
 +#ifdef USE_FONT_BACKEND
 +        if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING)
 +          {
 +            Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table)
 +                                         ->key_and_value,
 +                                         cmp->hash_index * 2);
 +
 +            it->c = XINT (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)));
 +          }
 +        else
 +#endif /* USE_FONT_BACKEND */
 +          {
 +            int i;
 +
 +            for (i = 0; i < cmp->glyph_len; i++)
 +              if ((it->c = COMPOSITION_GLYPH (composition_table[id], i))
 +                  != '\t')
 +                break;
 +          }
 +        if (it->c == '\t')
 +          it->c = ' ';
          it->len = (STRINGP (it->string)
                     ? string_char_to_byte (it->string, end)
                     : CHAR_TO_BYTE (end)) - pos_byte;
@@@ -5693,26 -5540,31 +5697,26 @@@ get_next_display_element (it
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
  
 -           If it->multibyte_p is nonzero, eight-bit characters and
 -           non-printable multibyte characters are also translated to
 -           octal form.
 +           If it->multibyte_p is nonzero, non-printable non-ASCII
 +           characters are also translated to octal form.
  
             If it->multibyte_p is zero, eight-bit characters that
             don't have corresponding multibyte char code are also
             translated to octal form.  */
          else if ((it->c < ' '
 -                  && (it->area != TEXT_AREA
 -                      /* In mode line, treat \n like other crl chars.  */
 -                      || (it->c != '\t'
 -                          && it->glyph_row && it->glyph_row->mode_line_p)
 -                      || (it->c != '\n' && it->c != '\t')))
 -                 || (it->multibyte_p
 -                     ? ((it->c >= 127
 -                         && it->len == 1)
 -                        || !CHAR_PRINTABLE_P (it->c)
 +                  ? (it->area != TEXT_AREA
 +                     /* In mode line, treat \n, \t like other crl chars.  */
 +                     || (it->c != '\t'
 +                         && it->glyph_row && it->glyph_row->mode_line_p)
 +                     || (it->c != '\n' && it->c != '\t'))
 +                  : (it->multibyte_p
 +                     ? (!CHAR_PRINTABLE_P (it->c)
                          || (!NILP (Vnobreak_char_display)
 -                            && (it->c == 0x8a0 || it->c == 0x8ad
 -                                || it->c == 0x920 || it->c == 0x92d
 -                                || it->c == 0xe20 || it->c == 0xe2d
 -                                || it->c == 0xf20 || it->c == 0xf2d)))
 +                            && (it->c == 0xA0 /* NO-BREAK SPACE */
 +                                || it->c == 0xAD /* SOFT HYPHEN */)))
                       : (it->c >= 127
 -                        && (!unibyte_display_via_language_environment
 -                            || it->c == unibyte_char_to_multibyte (it->c)))))
 +                        && (! unibyte_display_via_language_environment
 +                            || (UNIBYTE_CHAR_HAS_MULTIBYTE_P (it->c)))))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
                 highlighting.  */
  
              if (EQ (Vnobreak_char_display, Qt)
 -                && (it->c == 0x8a0 || it->c == 0x920
 -                    || it->c == 0xe20 || it->c == 0xf20))
 +                && it->c == 0xA0)
                {
                  /* Merge the no-break-space face into the current face.  */
                  face_id = merge_faces (it->f, Qnobreak_space, 0,
                 highlighting.  */
  
              if (EQ (Vnobreak_char_display, Qt)
 -                && (it->c == 0x8ad || it->c == 0x92d
 -                    || it->c == 0xe2d || it->c == 0xf2d))
 +                && it->c == 0xAD)
                {
                  g = it->c = '-';
                  XSETINT (it->ctl_chars[0], g);
              /* Handle non-break space and soft hyphen
                 with the escape glyph.  */
  
 -            if (it->c == 0x8a0 || it->c == 0x8ad
 -                || it->c == 0x920 || it->c == 0x92d
 -                || it->c == 0xe20 || it->c == 0xe2d
 -                || it->c == 0xf20 || it->c == 0xf2d)
 +            if (it->c == 0xA0 || it->c == 0xAD)
                {
                  XSETINT (it->ctl_chars[0], escape_glyph);
 -                g = it->c = ((it->c & 0xf) == 0 ? ' ' : '-');
 +                g = it->c = (it->c == 0xA0 ? ' ' : '-');
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
                  goto display_control;
                int i;
  
                /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
 -              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++)
              goto get_next;
            }
        }
 +    }
  
 -      /* Adjust face id for a multibyte character.  There are no
 -         multibyte character in unibyte text.  */
 -      if (it->multibyte_p
 -        && success_p
 -        && 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);
 -      }
 +  /* Adjust face id for a multibyte character.  There are no multibyte
 +     character in unibyte text.  */
 +  if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
 +      && it->multibyte_p
 +      && success_p
 +      && FRAME_WINDOW_P (it->f))
 +    {
 +      struct face *face = FACE_FROM_ID (it->f, it->face_id);
 +      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);
      }
  
    /* Is this character the last one of a run of characters with
@@@ -6913,16 -6761,6 +6917,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,
@@@ -7459,7 -7297,7 +7463,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);
             for the *Message* buffer.  */
          for (i = 0; i < nbytes; i++)
            {
 -            c = unibyte_char_to_multibyte (msg[i]);
 +            c = msg[i];
 +            c = unibyte_char_to_multibyte (c);
              char_bytes = CHAR_STRING (c, str);
              insert_1_both (str, 1, char_bytes, 1, 0, 0);
            }
@@@ -8761,7 -8598,7 +8765,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);
          /* Convert a single-byte string to multibyte.  */
          for (i = 0; i < nbytes; i++)
            {
 -            c = unibyte_char_to_multibyte (msg[i]);
 +            c = msg[i];
 +            c = unibyte_char_to_multibyte (c);
              n = CHAR_STRING (c, str);
              insert_1_both (str, 1, n, 1, 0, 0);
            }
@@@ -10877,7 -10713,7 +10881,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;
  
@@@ -11899,24 -11735,35 +11903,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;
  }
  
  
@@@ -12625,7 -12472,7 +12629,7 @@@ compute_window_start_on_continuation_li
             minimum distance from the old window start.  */
          pos = it.current.pos;
          min_distance = INFINITY;
-         while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
+         while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
                 distance < min_distance)
            {
              min_distance = distance;
@@@ -15842,7 -15689,7 +15846,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);
  
@@@ -15902,9 -15749,9 +15906,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))
@@@ -16010,7 -15857,7 +16014,7 @@@ highlight_trailing_whitespace (f, row
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
 -        int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
 +        int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
          if (face_id < 0)
            return;
  
@@@ -17537,7 -17384,7 +17541,7 @@@ are the selected window and the window'
      {
        if (EQ (face, Qt))
        face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
 -      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0, 0);
 +      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0);
      }
  
    if (face_id < 0)
@@@ -17760,7 -17607,7 +17764,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);
@@@ -18210,12 -18056,8 +18214,12 @@@ decode_mode_spec (w, c, field_width, pr
          {
            /* No need to mention EOL here--the terminal never needs
               to do EOL conversion.  */
 -          p = decode_mode_spec_coding (FRAME_KEYBOARD_CODING (f)->symbol, p, 0);
 -          p = decode_mode_spec_coding (FRAME_TERMINAL_CODING (f)->symbol, p, 0);
 +          p = decode_mode_spec_coding (CODING_ID_NAME
 +                                       (FRAME_KEYBOARD_CODING (f)->id),
 +                                       p, 0);
 +          p = decode_mode_spec_coding (CODING_ID_NAME
 +                                       (FRAME_TERMINAL_CODING (f)->id),
 +                                       p, 0);
          }
        p = decode_mode_spec_coding (b->buffer_file_coding_system,
                                     p, eol_flag);
@@@ -18487,7 -18329,7 +18491,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;
@@@ -19039,80 -18881,6 +19043,80 @@@ append_glyph_string (head, tail, s
  }
  
  
 +/* Get face and two-byte form of character C in face FACE_ID on frame
 +   F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
 +   means we want to display multibyte text.  DISPLAY_P non-zero means
 +   make sure that X resources for the face returned are allocated.
 +   Value is a pointer to a realized face that is ready for display if
 +   DISPLAY_P is non-zero.  */
 +
 +static INLINE struct face *
 +get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
 +     struct frame *f;
 +     int c, face_id;
 +     XChar2b *char2b;
 +     int multibyte_p, display_p;
 +{
 +  struct face *face = FACE_FROM_ID (f, face_id);
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      struct font *font = (struct font *) face->font_info;
 +
 +      if (font)
 +      {
 +        unsigned code = font->driver->encode_char (font, c);
 +
 +        if (code != FONT_INVALID_CODE)
 +          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 +        else
 +          STORE_XCHAR2B (char2b, 0, 0);
 +      }
 +    }
 +  else
 +#endif        /* USE_FONT_BACKEND */
 +  if (!multibyte_p)
 +    {
 +      /* 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, -1, Qnil);
 +      face = FACE_FROM_ID (f, face_id);
 +    }
 +  else if (c < 128)
 +    {
 +      /* Case of ASCII in a face known to fit ASCII.  */
 +      STORE_XCHAR2B (char2b, 0, c);
 +    }
 +  else if (face->font != NULL)
 +    {
 +      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);
 +
 +      if (CHARSET_DIMENSION (charset) == 1)
 +      STORE_XCHAR2B (char2b, 0, code);
 +      else
 +      STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 +       /* Maybe encode the character in *CHAR2B.  */
 +      FRAME_RIF (f)->encode_char (c, char2b, font_info, charset, NULL);
 +    }
 +
 +  /* Make sure X resources of the face are allocated.  */
 +#ifdef HAVE_X_WINDOWS
 +  if (display_p)
 +#endif
 +    {
 +      xassert (face != NULL);
 +      PREPARE_FACE_FOR_DISPLAY (f, face);
 +    }
 +
 +  return face;
 +}
 +
 +
  /* Get face and two-byte form of character glyph GLYPH on frame F.
     The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
     a pointer to a realized face that is ready for display.  */
@@@ -19132,23 -18900,6 +19136,23 @@@ get_glyph_face_and_encoding (f, glyph, 
    if (two_byte_p)
      *two_byte_p = 0;
  
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      struct font *font = (struct font *) face->font_info;
 +
 +      if (font)
 +      {
 +        unsigned code = font->driver->encode_char (font, glyph->u.ch);
 +
 +        if (code != FONT_INVALID_CODE)
 +          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 +        else
 +          STORE_XCHAR2B (char2b, 0, code);
 +      }
 +    }
 +  else
 +#endif        /* USE_FONT_BACKEND */
    if (!glyph->multibyte_p)
      {
        /* Unibyte case.  We don't have to encode, but we have to make
      }
    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
 -            = FRAME_RIF (f)->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
 +              = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info,
 +                                            charset, two_byte_p);
 +          }
        }
      }
  
  
  /* Fill glyph string S with composition components specified by S->cmp.
  
 -   FACES is an array of faces for all components of this composition.
 +   BASE_FACE is the base face of the composition.
     S->gidx is the index of the first component for S.
  
     OVERLAPS non-zero means S should draw the foreground only, and use
     Value is the index of a component not in S.  */
  
  static int
 -fill_composite_glyph_string (s, faces, overlaps)
 +fill_composite_glyph_string (s, base_face, overlaps)
       struct glyph_string *s;
 -     struct face **faces;
 +     struct face *base_face;
       int overlaps;
  {
    int i;
  
    s->for_overlaps = overlaps;
  
 -  s->face = faces[s->gidx];
 -  s->font = s->face->font;
 -  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend && s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
 +    {
 +      Lisp_Object gstring
 +      = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
 +              s->cmp->hash_index * 2);
  
 -  /* For all glyphs of this composition, starting at the offset
 -     S->gidx, until we reach the end of the definition or encounter a
 -     glyph that requires the different face, add it to S.  */
 -  ++s->nchars;
 -  for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
 -    ++s->nchars;
 +      s->face = base_face;
 +      s->font_info = s->cmp->font;
 +      s->font = s->font_info->font;
 +      for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++)
 +      {
 +        Lisp_Object g = LGSTRING_GLYPH (gstring, i);
 +        unsigned code;
 +          XChar2b * store_pos;
 +        if (NILP (LGLYPH_FROM (g)))
 +          break;
 +        code = XUINT (LGLYPH_CODE (g));
 +          store_pos = s->char2b + i;
 +        STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF);
 +      }
 +      s->width = s->cmp->pixel_width;
 +    }
 +  else
 +#endif        /* USE_FONT_BACKEND */
 +    {
 +      /* For all glyphs of this composition, starting at the offset
 +       S->gidx, until we reach the end of the definition or encounter a
 +       glyph that requires the different face, add it to S.  */
 +      struct face *face;
  
 -  /* All glyph strings for the same composition has the same width,
 -     i.e. the width set for the first component of the composition.  */
 +      s->face = NULL;
 +      s->font = NULL;
 +      s->font_info = NULL;
 +      for (i = s->gidx; i < s->cmp->glyph_len; i++)
 +      {
 +        int c = COMPOSITION_GLYPH (s->cmp, i);
  
 -  s->width = s->first_glyph->pixel_width;
 +        if (c != '\t')
 +          {
 +            int face_id = FACE_FOR_CHAR (s->f, base_face, c, -1, Qnil);
 +
 +            face = get_char_face_and_encoding (s->f, c, face_id,
 +                                               s->char2b + i, 1, 1);
 +            if (face)
 +              {
 +                if (! s->face)
 +                  {
 +                    s->face = face;
 +                    s->font = s->face->font;
 +                    s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
 +                  }
 +                else if (s->face != face)
 +                  break;
 +              }
 +          }
 +        ++s->nchars;
 +      }
 +
 +      /* All glyph strings for the same composition has the same width,
 +       i.e. the width set for the first component of the composition.  */
 +      s->width = s->first_glyph->pixel_width;
 +    }
  
    /* If the specified font could not be loaded, use the frame's
       default font, but record the fact that we couldn't load it in
    /* Adjust base line for subscript/superscript text.  */
    s->ybase += s->first_glyph->voffset;
  
 -  xassert (s->face && s->face->gc);
 -
    /* This glyph string must always be drawn with 16-bit functions.  */
    s->two_byte_p = 1;
  
@@@ -19347,7 -19051,7 +19351,7 @@@ fill_glyph_string (s, face_id, start, e
      }
  
    s->font = s->face->font;
 -  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
 +  s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
  
    /* If the specified font could not be loaded, use the frame's font,
       but record the fact that we couldn't load it in
@@@ -19411,7 -19115,7 +19415,7 @@@ fill_stretch_glyph_string (s, row, area
    face_id = glyph->face_id;
    s->face = FACE_FROM_ID (s->f, face_id);
    s->font = s->face->font;
 -  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
 +  s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
    s->width = glyph->pixel_width;
    s->nchars = 1;
    voffset = glyph->voffset;
    return glyph - s->row->glyphs[s->area];
  }
  
 +static XCharStruct *
 +get_per_char_metric (f, font, font_info, char2b, font_type)
 +     struct frame *f;
 +     XFontStruct *font;
 +     struct font_info *font_info;
 +     XChar2b *char2b;
 +     int font_type;
 +{
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      static XCharStruct pcm_value;
 +      unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b);
 +      struct font *fontp;
 +      struct font_metrics metrics;
 +
 +      if (! font_info || code == FONT_INVALID_CODE)
 +      return NULL;
 +      fontp = (struct font *) font_info;
 +      fontp->driver->text_extents (fontp, &code, 1, &metrics);
 +      pcm_value.lbearing = metrics.lbearing;
 +      pcm_value.rbearing = metrics.rbearing;
 +      pcm_value.ascent = metrics.ascent;
 +      pcm_value.descent = metrics.descent;
 +      pcm_value.width = metrics.width;
 +      return &pcm_value;
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +  return FRAME_RIF (f)->per_char_metric (font, char2b, font_type);
 +}
  
  /* EXPORT for RIF:
     Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
@@@ -19487,9 -19161,9 +19491,9 @@@ x_get_glyph_overhangs (glyph, f, left, 
  
        face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
        font = face->font;
 -      font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
 +      font_info = FONT_INFO_FROM_FACE (f, face);
        if (font  /* ++KFS: Should this be font_info ?  */
 -        && (pcm = FRAME_RIF (f)->per_char_metric (font, &char2b, glyph->font_type)))
 +        && (pcm = get_per_char_metric (f, font, font_info, &char2b, glyph->font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
            *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;
 +    }
  }
  
  
@@@ -19617,6 -19284,70 +19621,6 @@@ right_overwriting (s
  }
  
  
 -/* Get face and two-byte form of character C in face FACE_ID on frame
 -   F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
 -   means we want to display multibyte text.  DISPLAY_P non-zero means
 -   make sure that X resources for the face returned are allocated.
 -   Value is a pointer to a realized face that is ready for display if
 -   DISPLAY_P is non-zero.  */
 -
 -static INLINE struct face *
 -get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
 -     struct frame *f;
 -     int c, face_id;
 -     XChar2b *char2b;
 -     int multibyte_p, display_p;
 -{
 -  struct face *face = FACE_FROM_ID (f, face_id);
 -
 -  if (!multibyte_p)
 -    {
 -      /* 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 = FACE_FROM_ID (f, face_id);
 -    }
 -  else if (c < 128)
 -    {
 -      /* Case of ASCII in a face known to fit ASCII.  */
 -      STORE_XCHAR2B (char2b, 0, c);
 -    }
 -  else
 -    {
 -      int c1, c2, charset;
 -
 -      /* 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);
 -      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)
 -          FRAME_RIF (f)->encode_char (c, char2b, font_info, 0);
 -      }
 -    }
 -
 -  /* Make sure X resources of the face are allocated.  */
 -#ifdef HAVE_X_WINDOWS
 -  if (display_p)
 -#endif
 -    {
 -      xassert (face != NULL);
 -      PREPARE_FACE_FOR_DISPLAY (f, face);
 -    }
 -
 -  return face;
 -}
 -
 -
  /* Set background width of glyph string S.  START is the index of the
     first glyph following S.  LAST_X is the right-most x-position + 1
     in the drawing area.  */
@@@ -19756,9 -19487,10 +19760,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);                   \
     x-position of the drawing area.  */
  
  #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
 -  do {                                                                          \
 -    int cmp_id = (row)->glyphs[area][START].u.cmp_id;                   \
 -    int face_id = (row)->glyphs[area][START].face_id;                   \
 -    struct face *base_face = FACE_FROM_ID (f, face_id);                         \
 -    struct composition *cmp = composition_table[cmp_id];                \
 -    int glyph_len = cmp->glyph_len;                                     \
 -    XChar2b *char2b;                                                    \
 -    struct face **faces;                                                \
 -    struct glyph_string *first_s = NULL;                                \
 -    int n;                                                              \
 -                                                                        \
 -    base_face = base_face->ascii_face;                                          \
 -    char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);                 \
 -    faces = (struct face **) alloca ((sizeof *faces) * glyph_len);      \
 -    /* At first, fill in `char2b' and `faces'.  */                      \
 -    for (n = 0; n < glyph_len; n++)                                     \
 -      {                                                                         \
 -      int c = COMPOSITION_GLYPH (cmp, n);                               \
 -      int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
 -      faces[n] = FACE_FROM_ID (f, this_face_id);                        \
 -      get_char_face_and_encoding (f, c, this_face_id,                   \
 -                                  char2b + n, 1, 1);                    \
 -      }                                                                         \
 -                                                                        \
 -    /* Make glyph_strings for each glyph sequence that is drawable by   \
 -       the same face, and append them to HEAD/TAIL.  */                         \
 -    for (n = 0; n < cmp->glyph_len;)                                    \
 -      {                                                                         \
 -      s = (struct glyph_string *) alloca (sizeof *s);                   \
 -      INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL);       \
 -      append_glyph_string (&(HEAD), &(TAIL), s);                        \
 -      s->cmp = cmp;                                                     \
 -      s->gidx = n;                                                      \
 -      s->x = (X);                                                       \
 -                                                                        \
 -      if (n == 0)                                                       \
 -        first_s = s;                                                    \
 -                                                                        \
 -      n = fill_composite_glyph_string (s, faces, overlaps);             \
 -      }                                                                         \
 -                                                                        \
 -    ++START;                                                            \
 -    s = first_s;                                                        \
 +  do {                                                                            \
 +    int face_id = (row)->glyphs[area][START].face_id;                     \
 +    struct face *base_face = FACE_FROM_ID (f, face_id);                           \
 +    int cmp_id = (row)->glyphs[area][START].u.cmp_id;                     \
 +    struct composition *cmp = composition_table[cmp_id];                  \
 +    XChar2b *char2b;                                                      \
 +    struct glyph_string *first_s;                                         \
 +    int n;                                                                \
 +                                                                          \
 +    char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len);      \
 +    base_face = base_face->ascii_face;                                            \
 +                                                                          \
 +    /* Make glyph_strings for each glyph sequence that is drawable by     \
 +       the same face, and append them to HEAD/TAIL.  */                           \
 +    for (n = 0; n < cmp->glyph_len;)                                      \
 +      {                                                                           \
 +      s = (struct glyph_string *) alloca (sizeof *s);                     \
 +      INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);             \
 +      append_glyph_string (&(HEAD), &(TAIL), s);                          \
 +      s->cmp = cmp;                                                       \
 +      s->gidx = n;                                                        \
 +      s->x = (X);                                                         \
 +      if (n == 0)                                                         \
 +        first_s = s;                                                      \
 +      n = fill_composite_glyph_string (s, base_face, overlaps);           \
 +      }                                                                           \
 +                                                                          \
 +    ++START;                                                              \
 +    s = first_s;                                                          \
    } while (0)
  
  
                 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)
@@@ -19894,7 -19637,7 +19898,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;
  {
        if (i >= 0)
        {
          clip_tail = tail;
 +        i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x);
          for (s = h; s; s = s->next)
@@@ -20291,9 -20033,9 +20295,9 @@@ produce_image_glyph (it
        }
  
        if (it->start_of_box_run_p && slice.x == 0)
-       it->pixel_width += abs (face->box_line_width);
+       it->pixel_width += eabs (face->box_line_width);
        if (it->end_of_box_run_p && slice.x + slice.width == img->width)
-       it->pixel_width += abs (face->box_line_width);
+       it->pixel_width += eabs (face->box_line_width);
      }
  
    take_vertical_position_into_account (it);
@@@ -20604,7 -20346,7 +20608,7 @@@ calc_line_height_property (it, val, fon
        struct face *face;
        struct font_info *font_info;
  
 -      face_id = lookup_named_face (it->f, face_name, ' ', 0);
 +      face_id = lookup_named_face (it->f, face_name, 0);
        if (face_id < 0)
        return make_number (-1);
  
        if (font == NULL)
        return make_number (-1);
  
 -      font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
 +      font_info = FONT_INFO_FROM_FACE (it->f, face);
        boff = font_info->baseline_offset;
        if (font_info->vertical_centering)
        boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
@@@ -20677,17 -20419,23 +20681,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->char_to_display))
            {
              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);
            }
        }
        }
        else
        {
 -        font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
 +        font_info = FONT_INFO_FROM_FACE (it->f, face);
          boff = font_info->baseline_offset;
          if (font_info->vertical_centering)
            boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
  
          it->nglyphs = 1;
  
 -          pcm = FRAME_RIF (it->f)->per_char_metric
 -            (font, &char2b, FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
 +        pcm = get_per_char_metric (it->f, font, font_info, &char2b,
 +                                   FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
  
          if (it->override_ascent >= 0)
            {
  
          /* 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 = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
 -                                                    FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 +          pcm = get_per_char_metric (it->f, font, font_info, &char2b,
 +                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
  
          if (font_not_found_p || !pcm)
            {
 -            int charset = CHAR_CHARSET (it->char_to_display);
 +            int char_width = CHAR_WIDTH (it->char_to_display);
  
 +            if (char_width == 0)
 +              /* This is a non spacing character.  But, as we are
 +                 going to display an empty box, the box must occupy
 +                 at least one column.  */
 +              char_width = 1;
              it->glyph_not_available_p = 1;
 -            it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
 -                               * CHARSET_WIDTH (charset));
 +            it->pixel_width = FRAME_COLUMN_WIDTH (it->f) * char_width;
              it->phys_ascent = FONT_BASE (font) + boff;
              it->phys_descent = FONT_DESCENT (font) - boff;
            }
    else if (it->what == IT_COMPOSITION)
      {
        /* Note: A composition is represented as one glyph in the
 -       glyph matrix.  There are no padding glyphs.  */
 -      XChar2b char2b;
 -      XFontStruct *font;
 +       glyph matrix.  There are no padding glyphs.
 +
 +       Important is that pixel_width, ascent, and descent are the
 +       values of what is drawn by draw_glyphs (i.e. the values of
 +       the overall glyphs composed).  */
        struct face *face = FACE_FROM_ID (it->f, it->face_id);
 -      XCharStruct *pcm;
 -      int font_not_found_p;
 -      struct font_info *font_info;
        int boff;                       /* baseline offset */
        struct composition *cmp = composition_table[it->cmp_id];
 +      int glyph_len = cmp->glyph_len;
 +      XFontStruct *font = face->font;
  
 -      /* 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->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);
 -      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);
 -      font = face->font;
 +      it->nglyphs = 1;
  
 -      /* When no suitable font found, use the default font.  */
 -      font_not_found_p = font == NULL;
 -      if (font_not_found_p)
 +#ifdef USE_FONT_BACKEND
 +      if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
 -        font = FRAME_FONT (it->f);
 -        boff = FRAME_BASELINE_OFFSET (it->f);
 -        font_info = NULL;
 +        if (! cmp->font || cmp->font != font)
 +          font_prepare_composition (cmp);
        }
        else
 -      {
 -        font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
 -        boff = font_info->baseline_offset;
 -        if (font_info->vertical_centering)
 -          boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 -      }
 -
 -      /* There are no padding glyphs, so there is only one glyph to
 -       produce for the composition.  Important is that pixel_width,
 -       ascent and descent are the values of what is drawn by
 -       draw_glyphs (i.e. the values of the overall glyphs composed).  */
 -      it->nglyphs = 1;
 -
 +#endif        /* USE_FONT_BACKEND */
        /* If we have not yet calculated pixel size data of glyphs of
         the composition for the current face font, calculate them
         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)
 -      {
 -        /* Ascent and descent of the font of the first character of
 -           this composition (adjusted by baseline offset).  Ascent
 -           and descent of overall glyphs should not be less than
 -           them respectively.  */
 -        int font_ascent = FONT_BASE (font) + boff;
 -        int font_descent = FONT_DESCENT (font) - boff;
 +       to incorrect display, but it's very rare, and C-l (recenter)
 +       can correct the display anyway.  */
 +      if (! cmp->font || cmp->font != font)
 +      {
 +        /* Ascent and descent of the font of the first character
 +           of this composition (adjusted by baseline offset).
 +           Ascent and descent of overall glyphs should not be less
 +           than them respectively.  */
 +        int font_ascent, font_descent, font_height;
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
 +        int lbearing, rbearing;
          int i, width, ascent, descent;
 +        int left_padded = 0, right_padded = 0;
 +        int face_id;
 +        int c;
 +        XChar2b char2b;
 +        XCharStruct *pcm;
 +        int font_not_found_p;
 +        struct font_info *font_info;
 +        int pos;
 +
 +        for (glyph_len = cmp->glyph_len; glyph_len > 0; glyph_len--)
 +          if ((c = COMPOSITION_GLYPH (cmp, glyph_len - 1)) != '\t')
 +            break;
 +        if (glyph_len < cmp->glyph_len)
 +          right_padded = 1;
 +        for (i = 0; i < glyph_len; i++)
 +          {
 +            if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
 +              break;
 +            cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
 +          }
 +        if (i > 0)
 +          left_padded = 1;
 +
 +        pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
 +               : IT_CHARPOS (*it));
 +        /* When no suitable font found, use the default font.  */
 +        font_not_found_p = font == NULL;
 +        if (font_not_found_p)
 +          {
 +            face = face->ascii_face;
 +            font = face->font;
 +          }
 +        font_info = FONT_INFO_FROM_FACE (it->f, face);
 +        boff = font_info->baseline_offset;
 +        if (font_info->vertical_centering)
 +          boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 +        font_ascent = FONT_BASE (font) + boff;
 +        font_descent = FONT_DESCENT (font) - boff;
 +        font_height = FONT_HEIGHT (font);
  
          cmp->font = (void *) font;
  
 +        pcm = NULL;
 +        if (! font_not_found_p)
 +          {
 +            get_char_face_and_encoding (it->f, c, it->face_id,
 +                                        &char2b, it->multibyte_p, 0);
 +            pcm = get_per_char_metric (it->f, font, font_info, &char2b,
 +                                       FONT_TYPE_FOR_MULTIBYTE (font, c));
 +          }
 +
          /* Initialize the bounding box.  */
 -        if (font_info
 -            && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
 -                                                            FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
 +        if (pcm)
            {
              width = pcm->width;
              ascent = pcm->ascent;
              descent = pcm->descent;
 +            lbearing = pcm->lbearing;
 +            rbearing = pcm->rbearing;
            }
          else
            {
              width = FONT_WIDTH (font);
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
 +            lbearing = 0;
 +            rbearing = width;
            }
  
          rightmost = width;
 +        leftmost = 0;
          lowest = - descent + boff;
          highest = ascent + boff;
 -        leftmost = 0;
  
 -        if (font_info
 +        if (! font_not_found_p
              && font_info->default_ascent
              && CHAR_TABLE_P (Vuse_default_ascent)
              && !NILP (Faref (Vuse_default_ascent,
            highest = font_info->default_ascent + boff;
  
          /* Draw the first glyph at the normal position.  It may be
 -           shifted to right later if some other glyphs are drawn at
 -           the left.  */
 -        cmp->offsets[0] = 0;
 -        cmp->offsets[1] = boff;
 +           shifted to right later if some other glyphs are drawn
 +           at the left.  */
 +        cmp->offsets[i * 2] = 0;
 +        cmp->offsets[i * 2 + 1] = boff;
 +        cmp->lbearing = lbearing;
 +        cmp->rbearing = rbearing;
  
          /* Set cmp->offsets for the remaining glyphs.  */
 -        for (i = 1; i < cmp->glyph_len; i++)
 +        for (i++; i < 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;
 +            struct face *this_face;
 +            int this_boff;
 +
 +            if (ch == '\t')
 +              ch = ' ';
 +            face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
 +            this_face = FACE_FROM_ID (it->f, face_id);
 +            font = this_face->font;
  
 -            face = FACE_FROM_ID (it->f, face_id);
 -            get_char_face_and_encoding (it->f, ch, face->id,
 -                                        &char2b, it->multibyte_p, 0);
 -            font = face->font;
              if (font == NULL)
 -              {
 -                font = FRAME_FONT (it->f);
 -                boff = FRAME_BASELINE_OFFSET (it->f);
 -                font_info = NULL;
 -              }
 +              pcm = NULL;
              else
                {
 -                font_info
 -                  = FONT_INFO_FROM_ID (it->f, face->font_info_id);
 -                boff = font_info->baseline_offset;
 +                font_info = FONT_INFO_FROM_FACE (it->f, this_face);
 +                this_boff = font_info->baseline_offset;
                  if (font_info->vertical_centering)
 -                  boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 +                  this_boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 +                get_char_face_and_encoding (it->f, ch, face_id,
 +                                            &char2b, it->multibyte_p, 0);
 +                pcm = get_per_char_metric (it->f, font, font_info, &char2b,
 +                                           FONT_TYPE_FOR_MULTIBYTE (font,
 +                                                                    ch));
                }
 -
 -            if (font_info
 -                && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
 -                                                                FONT_TYPE_FOR_MULTIBYTE (font, ch))))
 +            if (! pcm)
 +              cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
 +            else
                {
                  width = pcm->width;
                  ascent = pcm->ascent;
                  descent = pcm->descent;
 -              }
 -            else
 -              {
 -                width = FONT_WIDTH (font);
 -                ascent = 1;
 -                descent = 0;
 -              }
 +                lbearing = pcm->lbearing;
 +                rbearing = pcm->rbearing;
 +                if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
 +                  {
 +                    /* Relative composition with or without
 +                       alternate chars.  */
 +                    left = (leftmost + rightmost - width) / 2;
 +                    btm = - descent + boff;
 +                    if (font_info->relative_compose
 +                        && (! CHAR_TABLE_P (Vignore_relative_composition)
 +                            || NILP (Faref (Vignore_relative_composition,
 +                                            make_number (ch)))))
 +                      {
  
 -            if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
 -              {
 -                /* Relative composition with or without
 -                   alternate chars.  */
 -                left = (leftmost + rightmost - width) / 2;
 -                btm = - descent + boff;
 -                if (font_info && font_info->relative_compose
 -                    && (! CHAR_TABLE_P (Vignore_relative_composition)
 -                        || NILP (Faref (Vignore_relative_composition,
 -                                        make_number (ch)))))
 +                        if (- descent >= font_info->relative_compose)
 +                          /* One extra pixel between two glyphs.  */
 +                          btm = highest + 1;
 +                        else if (ascent <= 0)
 +                          /* One extra pixel between two glyphs.  */
 +                          btm = lowest - 1 - ascent - descent;
 +                      }
 +                  }
 +                else
                    {
 +                    /* A composition rule is specified by an integer
 +                       value that encodes global and new reference
 +                       points (GREF and NREF).  GREF and NREF are
 +                       specified by numbers as below:
 +
 +                       0---1---2 -- ascent
 +                       |       |
 +                       |       |
 +                       |       |
 +                       9--10--11 -- center
 +                       |       |
 +                       ---3---4---5--- baseline
 +                       |       |
 +                       6---7---8 -- descent
 +                    */
 +                    int rule = COMPOSITION_RULE (cmp, i);
 +                    int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
 +
 +                    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
 +                            + xoff);
 +                
 +                    btm = ((grefy == 0 ? highest
 +                            : grefy == 1 ? 0
 +                            : grefy == 2 ? lowest
 +                            : (highest + lowest) / 2)
 +                           - (nrefy == 0 ? ascent + descent
 +                              : nrefy == 1 ? descent - boff
 +                              : nrefy == 2 ? 0
 +                              : (ascent + descent) / 2)
 +                           + yoff);
 +                  }
 +
 +                cmp->offsets[i * 2] = left;
 +                cmp->offsets[i * 2 + 1] = btm + descent;
  
 -                    if (- descent >= font_info->relative_compose)
 -                      /* One extra pixel between two glyphs.  */
 -                      btm = highest + 1;
 -                    else if (ascent <= 0)
 -                      /* One extra pixel between two glyphs.  */
 -                      btm = lowest - 1 - ascent - descent;
 +                /* Update the bounding box of the overall glyphs. */
 +                if (width > 0)
 +                  {
 +                    right = left + width;
 +                    if (left < leftmost)
 +                      leftmost = left;
 +                    if (right > rightmost)
 +                      rightmost = right;
                    }
 +                top = btm + descent + ascent;
 +                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;
                }
 -            else
 -              {
 -                /* A composition rule is specified by an integer
 -                   value that encodes global and new reference
 -                   points (GREF and NREF).  GREF and NREF are
 -                   specified by numbers as below:
 -
 -                      0---1---2 -- ascent
 -                      |       |
 -                      |       |
 -                      |       |
 -                      9--10--11 -- center
 -                      |       |
 -                   ---3---4---5--- baseline
 -                      |       |
 -                      6---7---8 -- descent
 -                */
 -                int rule = COMPOSITION_RULE (cmp, i);
 -                int gref, nref, grefx, grefy, nrefx, nrefy;
 -
 -                COMPOSITION_DECODE_RULE (rule, gref, nref);
 -                grefx = gref % 3, nrefx = nref % 3;
 -                grefy = gref / 3, nrefy = nref / 3;
 -
 -                left = (leftmost
 -                        + grefx * (rightmost - leftmost) / 2
 -                        - nrefx * width / 2);
 -                btm = ((grefy == 0 ? highest
 -                        : grefy == 1 ? 0
 -                        : grefy == 2 ? lowest
 -                        : (highest + lowest) / 2)
 -                       - (nrefy == 0 ? ascent + descent
 -                          : nrefy == 1 ? descent - boff
 -                          : nrefy == 2 ? 0
 -                          : (ascent + descent) / 2));
 -              }
 -
 -            cmp->offsets[i * 2] = left;
 -            cmp->offsets[i * 2 + 1] = btm + descent;
 -
 -            /* Update the bounding box of the overall glyphs. */
 -            right = left + width;
 -            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 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;
 +          }
 +
 +        if (left_padded && cmp->lbearing < 0)
 +          {
 +            for (i = 0; i < cmp->glyph_len; i++)
 +              cmp->offsets[i * 2] -= cmp->lbearing;
 +            rightmost -= cmp->lbearing;
 +            cmp->rbearing -= cmp->lbearing;
 +            cmp->lbearing = 0;
 +          }
 +        if (right_padded && rightmost < cmp->rbearing)
 +          {
 +            rightmost = cmp->rbearing;
            }
  
          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;
@@@ -21419,8 -21107,7 +21423,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;
@@@ -22378,7 -22065,7 +22382,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;
                goto found;
              }
            else if (best_glyph == NULL
-                    || ((abs (g->charpos - pos)
-                        < abs (best_glyph->charpos - pos))
+                    || ((eabs (g->charpos - pos)
+                        < eabs (best_glyph->charpos - pos))
                         && (right_p
                             ? g->charpos < pos
                             : g->charpos > pos)))
@@@ -23741,11 -23428,10 +23745,11 @@@ expose_line (w, row, r
     LAST_OVERLAPPING_ROW is the last such row.  */
  
  static void
 -expose_overlaps (w, first_overlapping_row, last_overlapping_row)
 +expose_overlaps (w, first_overlapping_row, last_overlapping_row, r)
       struct window *w;
       struct glyph_row *first_overlapping_row;
       struct glyph_row *last_overlapping_row;
 +     XRectangle *r;
  {
    struct glyph_row *row;
  
        {
        xassert (row->enabled_p && !row->mode_line_p);
  
 +      row->clip = r;
        if (row->used[LEFT_MARGIN_AREA])
          x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
  
  
        if (row->used[RIGHT_MARGIN_AREA])
          x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
 +      row->clip = NULL;
        }
  }
  
@@@ -23929,22 -23613,8 +23933,22 @@@ expose_window (w, fr
                  last_overlapping_row = row;
                }
  
 +            row->clip = fr;
              if (expose_line (w, row, &r))
                mouse_face_overwritten_p = 1;
 +            row->clip = NULL;
 +          }
 +        else if (row->overlapping_p)
 +          {
 +            /* We must redraw a row overlapping the exposed area.  */
 +            if (y0 < r.y
 +                ? y0 + row->phys_height > r.y
 +                : y0 + row->ascent - row->phys_ascent < r.y +r.height)
 +              {
 +                if (first_overlapping_row == NULL)
 +                  first_overlapping_row = row;
 +                last_overlapping_row = row;
 +              }
            }
  
          if (y1 >= yb)
        {
          /* Fix the display of overlapping rows.  */
          if (first_overlapping_row)
 -          expose_overlaps (w, first_overlapping_row, last_overlapping_row);
 +          expose_overlaps (w, first_overlapping_row, last_overlapping_row,
 +                           fr);
  
          /* Draw border between windows.  */
          x_draw_vertical_border (w);
diff --combined src/xfaces.c
index d3e7a105b60ea788633b4ffee6b3075f8f2930c4,5e396d8bf6e010fb7c4eb47d2019e1ed6cf9ef75..50d733c7d0b39f8686486e76bd8c4f864026734c
@@@ -56,7 -56,7 +56,7 @@@ Boston, MA 02110-1301, 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 <stdio.h>              /* This needs to be before termchar.h */
  
  #include "lisp.h"
 +#include "character.h"
  #include "charset.h"
  #include "keyboard.h"
  #include "frame.h"
  #include "intervals.h"
  #include "termchar.h"
  
 +#ifdef HAVE_WINDOW_SYSTEM
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +#endif        /* HAVE_WINDOW_SYSTEM */
 +
  #ifdef HAVE_X_WINDOWS
  
  /* Compensate for a bug in Xos.h on some systems, on which it requires
@@@ -314,7 -305,6 +314,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.  */
  
@@@ -498,7 -488,7 +498,7 @@@ static int get_lface_attributes P_ ((st
  static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
  static unsigned char *xstrlwr P_ ((unsigned char *));
  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 *));
@@@ -511,17 -501,18 +511,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));
@@@ -531,22 -522,23 +531,22 @@@ 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 *,
                               int, struct named_merge_point *));
  static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
                                         Lisp_Object, int, int));
 +static void set_lface_from_font_and_fontset P_ ((struct frame *, Lisp_Object,
 +                                               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));
@@@ -981,9 -973,6 +981,9 @@@ clear_face_cache (clear_fonts_p
      {
        struct x_display_info *dpyinfo;
  
 +#ifdef USE_FONT_BACKEND
 +      if (! enable_font_backend)
 +#endif        /* USE_FONT_BACKEND */
        /* Fonts are common for frames on one display, i.e. on
         one X screen.  */
        for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@@ -1230,32 -1219,30 +1230,32 @@@ 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;
    int needs_overstrike;
  
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    abort ();
 +#endif        /* USE_FONT_BACKEND */
    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)
@@@ -1396,7 -1383,7 +1396,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)
      {
@@@ -1501,11 -1488,11 +1501,11 @@@ face_color_gray_p (f, color_name
      gray_p = (/* Any color sufficiently close to black counts as grey.  */
              (color.red < 5000 && color.green < 5000 && color.blue < 5000)
              ||
-             ((abs (color.red - color.green)
+             ((eabs (color.red - color.green)
                < max (color.red, color.green) / 20)
-              && (abs (color.green - color.blue)
+              && (eabs (color.green - color.blue)
                   < max (color.green, color.blue) / 20)
-              && (abs (color.blue - color.red)
+              && (eabs (color.blue - color.red)
                   < max (color.blue, color.red) / 20)));
    else
      gray_p = 0;
@@@ -2144,7 -2131,7 +2144,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);
@@@ -2185,117 -2172,9 +2185,117 @@@ face_numeric_swidth (width
    return face_numeric_value (swidth_table, DIM (swidth_table), width);
  }
  
 -
  #ifdef HAVE_WINDOW_SYSTEM
  
 +#ifdef USE_FONT_BACKEND
 +static INLINE Lisp_Object
 +face_symbolic_value (table, dim, font_prop)
 +     struct table_entry *table;
 +     int dim;
 +     Lisp_Object font_prop;
 +{
 +  struct table_entry *p;
 +  char *s = SDATA (SYMBOL_NAME (font_prop));
 +  int low, mid, high, cmp;
 +
 +  low = 0;
 +  high = dim - 1;
 +
 +  while (low <= high)
 +    {
 +      mid = (low + high) / 2;
 +      cmp = strcmp (table[mid].name, s);
 +
 +      if (cmp < 0)
 +      low = mid + 1;
 +      else if (cmp > 0)
 +      high = mid - 1;
 +      else
 +      return *table[mid].symbol;
 +    }
 +
 +  return Qnil;
 +}
 +
 +static INLINE Lisp_Object
 +face_symbolic_weight (weight)
 +     Lisp_Object weight;
 +{
 +  return face_symbolic_value (weight_table, DIM (weight_table), weight);
 +}
 +
 +static INLINE Lisp_Object
 +face_symbolic_slant (slant)
 +     Lisp_Object slant;
 +{
 +  return face_symbolic_value (slant_table, DIM (slant_table), slant);
 +}
 +
 +static INLINE Lisp_Object
 +face_symbolic_swidth (width)
 +     Lisp_Object width;
 +{
 +  return face_symbolic_value (swidth_table, DIM (swidth_table), width);
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
 +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
@@@ -2318,9 -2197,7 +2318,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
@@@ -2838,7 -2714,7 +2838,7 @@@ cmp_font_names (a, b
          int resy = FRAME_X_DISPLAY_INFO (font_frame)->resy;
          int x_resy = x->numeric[XLFD_RESY];
          int y_resy = y->numeric[XLFD_RESY];
-         cmp = abs (resy - x_resy) - abs (resy - y_resy);
+         cmp = eabs (resy - x_resy) - eabs (resy - y_resy);
        }
      }
  
  }
  
  
 -/* 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)
@@@ -2912,11 -2788,10 +2912,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.
  
@@@ -2930,37 -2805,35 +2930,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;
 +          }
        }
      }
  
@@@ -3142,11 -3015,18 +3142,11 @@@ 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, 0);
 +      int face_id = lookup_named_face (f, face, 0);
        struct face *face = (face_id < 0
                           ? NULL
                           : FACE_FROM_ID (f, face_id));
  
 -#ifdef WINDOWSNT
 -/* For historic reasons, FONT_WIDTH refers to average width on W32,
 -   not maximum as on X.  Redefine here. */
 -#undef FONT_WIDTH
 -#define FONT_WIDTH FONT_MAX_WIDTH
 -#endif
 -
        if (face && face->font)
        size = FONT_WIDTH (face->font);
        else
  #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.  */
@@@ -3273,12 -3152,7 +3273,12 @@@ check_lface_attrs (attrs
    xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
           || NILP (attrs[LFACE_FONT_INDEX])
 +#ifdef USE_FONT_BACKEND
 +         || FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])
 +#endif        /* USE_FONT_BACKEND */
           || STRINGP (attrs[LFACE_FONT_INDEX]));
 +  xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
 +         || STRINGP (attrs[LFACE_FONTSET_INDEX]));
  #endif
  }
  
@@@ -3486,7 -3360,7 +3486,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]) || IGNORE_DEFFACE_P (attrs[i]))
  #ifdef MAC_OS
          /* MAC_TODO: No stipple support on Mac OS yet, this index is
@@@ -3530,15 -3404,8 +3530,15 @@@ 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;
  }
  
 +#ifdef USE_FONT_BACKEND
 +/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT and
 +   FONTSET.  If FORCE_P is zero, set only unspecified attributes of
 +   LFACE.  The exceptions are `font' and `fontset' attributes.  They
 +   are set regardless of FORCE_P.  */
 +
 +static void
 +set_lface_from_font_and_fontset (f, lface, font_object, fontset, force_p)
 +     struct frame *f;
 +     Lisp_Object lface, font_object;
 +     int fontset;
 +     int force_p;
 +{
 +  struct font *font = XSAVE_VALUE (font_object)->pointer;
 +  Lisp_Object entity = font->entity;
 +  Lisp_Object val;
 +
 +  /* Set attributes only if unspecified, otherwise face defaults for
 +     new frames would never take effect.  If the font doesn't have a
 +     specific property, set a normal value for that.  */
 +
 +  if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
 +    {
 +      Lisp_Object foundry = AREF (entity, FONT_FOUNDRY_INDEX);
 +      Lisp_Object family = AREF (entity, FONT_FAMILY_INDEX);
 +
 +      if (! NILP (foundry))
 +      {
 +        if (! NILP (family))
 +          val = concat3 (SYMBOL_NAME (foundry), build_string ("-"),
 +                         SYMBOL_NAME (family));
 +        else
 +          val = concat2 (SYMBOL_NAME (foundry), build_string ("-*"));
 +      }
 +      else
 +      {
 +        if (! NILP (family))
 +          val = SYMBOL_NAME (family);
 +        else
 +          val = build_string ("*");
 +      }
 +      LFACE_FAMILY (lface) = val;
 +    }
 +
 +  if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
 +    {
 +      int pt = pixel_point_size (f, font->pixel_size * 10);
 +
 +      xassert (pt > 0);
 +      LFACE_HEIGHT (lface) = make_number (pt);
 +    }
 +
 +  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
 +    LFACE_AVGWIDTH (lface) = make_number (font->font.average_width);
 +
 +  if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
 +    {
 +      Lisp_Object weight = font_symbolic_weight (entity);
 +
 +      val = NILP (weight) ? Qnormal : face_symbolic_weight (weight);
 +      LFACE_WEIGHT (lface) = ! NILP (val) ? val : weight;
 +    }
 +  if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
 +    {
 +      Lisp_Object slant = font_symbolic_slant (entity);
 +
 +      val = NILP (slant) ? Qnormal : face_symbolic_slant (slant);
 +      LFACE_SLANT (lface) = ! NILP (val) ? val : slant;
 +    }
 +  if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
 +    {
 +      Lisp_Object width = font_symbolic_width (entity);
 +
 +      val = NILP (width) ? Qnormal : face_symbolic_swidth (width);
 +      LFACE_SWIDTH (lface) = ! NILP (val) ? val : width;
 +    }
 +
 +  LFACE_FONT (lface) = font_object;
 +  LFACE_FONTSET (lface) = fontset_name (fontset);
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
  #endif /* HAVE_WINDOW_SYSTEM */
  
  
@@@ -4529,7 -4304,7 +4529,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)))
          else
            f = check_x_frame (frame);
  
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend
 +            && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
 +          {
 +            int fontset;
 +
 +            if (EQ (attr, QCfontset))
 +              {
 +                Lisp_Object fontset_name = Fquery_fontset (value, Qnil);
 +
 +                if (NILP (fontset_name))
 +                  signal_error ("Invalid fontset name", value);
 +                LFACE_FONTSET (lface) = value;
 +              }
 +            else
 +              {
 +                Lisp_Object font_object;
 +
 +                if (FONT_OBJECT_P (value))
 +                  {
 +                    font_object = value;
 +                    fontset = FRAME_FONTSET (f);
 +                  }
 +                else
 +                  {
 +                    CHECK_STRING (value);
 +
 +                    fontset = fs_query_fontset (value, 0);
 +                    if (fontset >= 0)
 +                      value = fontset_ascii (fontset);
 +                    else
 +                      fontset = FRAME_FONTSET (f);
 +                    font_object = font_open_by_name (f, SDATA (value));
 +                    if (NILP (font_object))
 +                      signal_error ("Invalid font", value);
 +                  }
 +                set_lface_from_font_and_fontset (f, lface, font_object,
 +                                                 fontset, 1);
 +              }
 +          }
 +        else
 +#endif        /* USE_FONT_BACKEND */
          if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
            {
              CHECK_STRING (value);
              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;
    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.  */
@@@ -4782,30 -4507,12 +4782,30 @@@ set_font_frame_param (frame, lface
  
        if (STRINGP (LFACE_FONT (lface)))
        font_name = LFACE_FONT (lface);
 +#ifdef USE_FONT_BACKEND
 +      else if (enable_font_backend)
 +      {
 +        /* We set FONT_NAME to a font-object.  */
 +        if (FONT_OBJECT_P (LFACE_FONT (lface)))
 +          font_name = LFACE_FONT (lface);
 +        else
 +          {
 +            font_name = font_find_for_lface (f, &AREF (lface, 0), Qnil);
 +            if (NILP (font_name))
 +              error ("No font matches the specified attribute");
 +            font_name = font_open_for_lface (f, font_name, &AREF (lface, 0),
 +                                             Qnil);
 +            if (NILP (font_name))
 +              error ("No font matches the specified attribute");
 +          }
 +      }
 +#endif
        else
        {
          /* 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);
@@@ -5188,8 -4895,6 +5188,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);
  
@@@ -5294,18 -4999,15 +5294,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, 1);
 +      int face_id = lookup_named_face (f, face, 1);
        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);
      }
  }
  
@@@ -5504,8 -5192,8 +5504,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]))))
 +        );
  }
  
  
@@@ -5557,7 -5239,7 +5557,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;
          if (face->gc)
            {
              BLOCK_INPUT;
 +#ifdef USE_FONT_BACKEND
 +            if (enable_font_backend && face->font_info)
 +              font_done_for_face (f, face);
 +#endif        /* USE_FONT_BACKEND */
              x_free_gc (f, face->gc);
              face->gc = 0;
              UNBLOCK_INPUT;
@@@ -5639,10 -5317,6 +5639,10 @@@ prepare_face_for_display (f, face
        }
  #endif
        face->gc = x_create_gc (f, mask, &xgcv);
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend && face->font)
 +      font_prepare_for_face (f, face);
 +#endif        /* USE_FONT_BACKEND */
        UNBLOCK_INPUT;
      }
  #endif /* HAVE_WINDOW_SYSTEM */
@@@ -5748,10 -5422,6 +5748,10 @@@ clear_face_gcs (c
          if (face && face->gc)
            {
              BLOCK_INPUT;
 +#ifdef USE_FONT_BACKEND
 +            if (enable_font_backend && face->font_info)
 +              font_done_for_face (c->f, face);
 +#endif        /* USE_FONT_BACKEND */
              x_free_gc (c->f, face->gc);
              face->gc = 0;
              UNBLOCK_INPUT;
@@@ -5806,10 -5476,11 +5806,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);
@@@ -5883,11 -5555,10 +5883,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)
@@@ -5991,14 -5662,17 +5991,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));
 +#endif /* GLYPH_DEBUG */
  
 -/* 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
 +  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;
  }
  
 +#ifdef USE_FONT_BACKEND
 +int
 +face_for_font (f, font, base_face)
 +     struct frame *f;
 +     struct font *font;
 +     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 == font->font.font
 +        && face->font_info == (struct font_info *) font)
 +      return face->id;
 +    }
 +
 +  /* If not found, realize a new face.  */
 +  face = realize_non_ascii_face (f, -1, base_face);
 +  face->font = font->font.font;
 +  face->font_info = (struct font_info *) font;
 +  face->font_info_id = 0;
 +  face->font_name = font->font.full_name;
 +  return face->id;
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
 +#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, signal_p)
 +lookup_named_face (f, symbol, signal_p)
       struct frame *f;
       Lisp_Object symbol;
 -     int c;
       int signal_p;
  {
    Lisp_Object 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);
  }
  
  
@@@ -6166,7 -5763,7 +6166,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, 1);
 +      face_id = lookup_named_face (f, face_name, 1);
      }
    else
      face_id = -1;
@@@ -6198,7 -5795,7 +6198,7 @@@ smaller_face (f, face_id, steps
  
    /* Try in increments of 1/2 pt.  */
    delta = steps < 0 ? 5 : -5;
-   steps = abs (steps);
+   steps = eabs (steps);
  
    face = FACE_FROM_ID (f, face_id);
    bcopy (face->lface, attrs, sizeof attrs);
    while (steps
         && pt + delta > 0
         /* Give up if we cannot find a font within 10pt.  */
-        && abs (last_pt - pt) < 100)
+        && eabs (last_pt - pt) < 100)
      {
        /* 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.  */
@@@ -6257,7 -5854,7 +6257,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, signal_p)
 +lookup_derived_face (f, symbol, face_id, signal_p)
       struct frame *f;
       Lisp_Object symbol;
 -     int c;
       int face_id;
       int signal_p;
  {
    get_lface_attributes (f, symbol, symbol_attrs, signal_p);
    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,
@@@ -6375,7 -5973,6 +6375,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");
@@@ -6666,7 -6262,7 +6666,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.
@@@ -6722,10 -6318,6 +6722,10 @@@ Value is ORDER.  */
        free_all_realized_faces (Qnil);
      }
  
 +#ifdef USE_FONT_BACKEND
 +  font_update_sort_order (font_sort_order);
 +#endif        /* USE_FONT_BACKEND */
 +
    return Qnil;
  }
  
@@@ -6822,17 -6414,17 +6822,17 @@@ better_font_p (values, font1, font2, co
  
          if (xlfd_idx == XLFD_POINT_SIZE)
            {
-             delta1 = abs (values[i] - (font1->numeric[xlfd_idx]
+             delta1 = eabs (values[i] - (font1->numeric[xlfd_idx]
                                         / font1->rescale_ratio));
-             delta2 = abs (values[i] - (font2->numeric[xlfd_idx]
+             delta2 = eabs (values[i] - (font2->numeric[xlfd_idx]
                                         / font2->rescale_ratio));
-             if (abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
+             if (eabs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
                continue;
            }
          else
            {
-             delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
-             delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
+             delta1 = eabs (values[i] - font1->numeric[xlfd_idx]);
+             delta2 = eabs (values[i] - font2->numeric[xlfd_idx]);
            }
  
          if (delta1 > delta2)
  
    if (avgwidth)
      {
-       int delta1 = abs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
-       int delta2 = abs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
+       int delta1 = eabs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
+       int delta2 = eabs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
        if (delta1 > delta2)
        return 0;
        else if (delta1 < delta2)
@@@ -6916,12 -6508,6 +6916,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.  */
@@@ -7194,62 -6780,78 +7194,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
 -  if (nfonts == 0 && STRINGP (try_family) && STRINGP (registry))
 -    {
 -      if (xstricmp (SDATA (registry), "mac-roman") == 0)
 -      /* 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.  */
 -      nfonts = try_alternative_families (f, try_family, Qnil, fonts);
 -      else if (SBYTES (try_family) > 0
 -             && SREF (try_family, SBYTES (try_family) - 1) != '*')
 -      /* Some Central European/Cyrillic font family names have the
 -         Roman counterpart name as their prefix.  */
 -      nfonts = try_alternative_families (f, concat2 (try_family,
 -                                                     build_string ("*")),
 -                                         registry, fonts);
 +  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);
 +      }
      }
 -#endif
 +  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;
  }
  
@@@ -7264,108 -6866,63 +7264,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;
  }
@@@ -7454,27 -7011,12 +7454,27 @@@ realize_default_face (f
  #ifdef HAVE_WINDOW_SYSTEM
    if (FRAME_WINDOW_P (f))
      {
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend)
 +      {
 +        frame_font = font_find_object (FRAME_FONT_OBJECT (f));
 +        xassert (FONT_OBJECT_P (frame_font));
 +        set_lface_from_font_and_fontset (f, lface, frame_font,
 +                                         FRAME_FONTSET (f),
 +                                         f->default_face_done_p);
 +      }
 +      else
 +      {
 +#endif        /* USE_FONT_BACKEND */
        /* Set frame_font to the value of the `font' frame parameter.  */
        frame_font = Fassq (Qfont, f->param_alist);
        xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
        frame_font = XCDR (frame_font);
        set_lface_from_font_name (f, lface, frame_font,
                                  f->default_face_done_p, 1);
 +#ifdef USE_FONT_BACKEND
 +      }
 +#endif        /* USE_FONT_BACKEND */
        f->default_face_done_p = 1;
      }
  #endif /* HAVE_WINDOW_SYSTEM */
    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);
  
  #ifdef HAVE_WINDOW_SYSTEM
  #ifdef HAVE_X_WINDOWS
@@@ -7601,19 -7143,23 +7601,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 if (FRAME_INITIAL_P (cache->f))
      {
        /* Create a dummy face. */
  
    /* 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;
 +#ifdef USE_FONT_BACKEND
 +  face->extra = NULL;
 +#endif
 +
 +  /* 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;
  {
    struct face *face = NULL;
  #ifdef HAVE_WINDOW_SYSTEM
    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;
 +#ifdef USE_FONT_BACKEND
 +      face->font_info = default_face->font_info;
 +#endif        /* USE_FONT_BACKEND */
        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 ();
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend)
 +      font_load_for_face (f, face);
 +      else
 +#endif        /* USE_FONT_BACKEND */
 +      load_face_font (f, face);
 +      if (face->font)
 +      face->fontset = make_fontset_for_ascii_face (f, fontset, face);
 +      else
 +      face->fontset = -1;
      }
  
    /* Load colors, and set remaining attributes.  */
    stipple = attrs[LFACE_STIPPLE_INDEX];
    if (!NILP (stipple))
      face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
 -
 -  xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
  #endif /* HAVE_WINDOW_SYSTEM */
 +
    return face;
  }
  
@@@ -7989,13 -7504,14 +7989,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;
@@@ -8088,7 -7604,7 +8088,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;
@@@ -8213,7 -7729,7 +8213,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);
  }
  
  
@@@ -8309,7 -7825,7 +8309,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);
  }
  
  
@@@ -8346,7 -7862,7 +8346,7 @@@ merge_faces (f, face_name, face_id, bas
        if (face_id < 0 || face_id >= lface_id_to_name_size)
        return base_face_id;
        face_name = lface_id_to_name[face_id];
 -      face_id = lookup_derived_face (f, face_name, 0, base_face_id, 1);
 +      face_id = lookup_derived_face (f, face_name, base_face_id, 1);
        if (face_id >= 0)
        return face_id;
        return base_face_id;
  
    /* 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);
  }
  
  \f
@@@ -8411,6 -7927,7 +8411,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);
  }
  
  
@@@ -8503,8 -8020,6 +8503,8 @@@ syms_of_xfaces (
    staticpro (&QCwidth);
    QCfont = intern (":font");
    staticpro (&QCfont);
 +  QCfontset = intern (":fontset");
 +  staticpro (&QCfontset);
    QCbold = intern (":bold");
    staticpro (&QCbold);
    QCitalic = intern (":italic");
diff --combined src/xfns.c
index 54d637d859b20ab96c76bdc0a1c39b13c6de9137,fe4d1c8335f7dda9aebb14fd1249761f41a13f61..8d21a69461a45005a7a3bf2ac40b40caf25930d2
@@@ -41,7 -41,6 +41,7 @@@ Boston, MA 02110-1301, USA.  *
  #include "keyboard.h"
  #include "blockinput.h"
  #include <epaths.h>
 +#include "character.h"
  #include "charset.h"
  #include "coding.h"
  #include "fontset.h"
  #include "atimer.h"
  #include "termchar.h"
  
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +
  #ifdef HAVE_X_WINDOWS
  
  #include <ctype.h>
@@@ -319,10 -314,10 +319,10 @@@ x_window_to_frame (dpyinfo, wdesc
  
    if (wdesc == None) return 0;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
@@@ -371,10 -366,10 +371,10 @@@ x_any_window_to_frame (dpyinfo, wdesc
    if (wdesc == None) return NULL;
  
    found = NULL;
 -  for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail) && !found; tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
  
        f = XFRAME (frame);
@@@ -426,10 -421,10 +426,10 @@@ x_non_menubar_window_to_frame (dpyinfo
  
    if (wdesc == None) return 0;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
@@@ -474,10 -469,10 +474,10 @@@ x_menubar_window_to_frame (dpyinfo, wde
  
    if (wdesc == None) return 0;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
@@@ -521,10 -516,10 +521,10 @@@ x_top_window_to_frame (dpyinfo, wdesc
  
    if (wdesc == None) return 0;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
  
  \f
  
 +static void x_default_font_parameter P_ ((struct frame *, Lisp_Object));
 +
  static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
  static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
  
@@@ -1562,30 -1555,55 +1562,30 @@@ x_encode_text (string, coding_system, s
       int selectionp;
       int *freep;
  {
 -  unsigned char *str = SDATA (string);
 -  int chars = SCHARS (string);
 -  int bytes = SBYTES (string);
 -  int charset_info;
 -  int bufsize;
 -  unsigned char *buf;
 +  int result = string_xstring_p (string);
    struct coding_system coding;
 -  extern Lisp_Object Qcompound_text_with_extensions;
  
 -  charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
 -  if (charset_info == 0)
 +  if (result == 0)
      {
        /* No multibyte character in OBJ.  We need not encode it.  */
 -      *text_bytes = bytes;
 +      *text_bytes = SBYTES (string);
        *stringp = 1;
        *freep = 0;
 -      return str;
 +      return SDATA (string);
      }
  
    setup_coding_system (coding_system, &coding);
 -  if (selectionp
 -      && SYMBOLP (coding.pre_write_conversion)
 -      && !NILP (Ffboundp (coding.pre_write_conversion)))
 -    {
 -      struct gcpro gcpro1;
 -      /* We don't need to GCPRO string.  */
 -      GCPRO1 (coding_system);
 -      string = run_pre_post_conversion_on_str (string, &coding, 1);
 -      UNGCPRO;
 -      str = SDATA (string);
 -      chars = SCHARS (string);
 -      bytes = SBYTES (string);
 -    }
 -  coding.src_multibyte = 1;
 -  coding.dst_multibyte = 0;
 -  coding.mode |= CODING_MODE_LAST_BLOCK;
 -  if (coding.type == coding_type_iso2022)
 -    coding.flags |= CODING_FLAG_ISO_SAFE;
 +  coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
    /* We suppress producing escape sequences for composition.  */
 -  coding.composing = COMPOSITION_DISABLED;
 -  bufsize = encoding_buffer_size (&coding, bytes);
 -  buf = (unsigned char *) xmalloc (bufsize);
 -  encode_coding (&coding, str, buf, bytes, bufsize);
 +  coding.common_flags &= ~CODING_ANNOTATION_MASK;
 +  coding.dst_bytes = SCHARS (string) * 2;
 +  coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
 +  encode_coding_object (&coding, string, 0, 0,
 +                      SCHARS (string), SBYTES (string), Qnil);
    *text_bytes = coding.produced;
 -  *stringp = (charset_info == 1
 -            || (!EQ (coding_system, Qcompound_text)
 -                && !EQ (coding_system, Qcompound_text_with_extensions)));
 +  *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
    *freep = 1;
 -  return buf;
 +  return coding.destination;
  }
  
  \f
@@@ -1760,15 -1778,7 +1760,7 @@@ x_implicitly_set_name (f, arg, oldval
  }
  \f
  /* Change the title of frame F to NAME.
-    If NAME is nil, use the frame name as the title.
-    If EXPLICIT is non-zero, that indicates that lisp code is setting the
-        name; if NAME is a string, set F's name to NAME and set
-        F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-    If EXPLICIT is zero, that indicates that Emacs redisplay code is
-        suggesting a new name, which lisp code should override; if
-        F->explicit_name is set, ignore the new name; otherwise, set it.  */
+    If NAME is nil, use the frame name as the title.  */
  
  void
  x_set_title (f, name, old_name)
@@@ -1964,7 -1974,6 +1956,7 @@@ hack_wm_protocols (f, widget
  #ifdef HAVE_X_I18N
  
  static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
 +static XFontSet xic_create_xfontset2 P_ ((struct frame *));
  static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
  
  
@@@ -2116,29 -2125,6 +2108,29 @@@ xic_create_fontsetname (base_fontname, 
    return fontsetname;
  }
  
 +#ifdef DEBUG_XIC_FONTSET
 +static void
 +print_fontset_result (xfs, name, missing_list, missing_count)
 +     XFontSet xfs;
 +     char *name;
 +     char **missing_list;
 +     int missing_count;
 +{
 +  if (xfs)
 +    fprintf (stderr, "XIC Fontset created: %s\n", name);
 +  else
 +    {
 +      fprintf (stderr, "XIC Fontset failed: %s\n", name);
 +      while (missing_count-- > 0)
 +      {
 +        fprintf (stderr, "  missing: %s\n", *missing_list);
 +        missing_list++;
 +      }
 +    }
 +
 +}
 +#endif
 +
  static XFontSet
  xic_create_xfontset (f, base_fontname)
       struct frame *f;
        xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
                            fontsetname, &missing_list,
                            &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +      print_fontset_result (xfs, fontsetname, missing_list, missing_count);
 +#endif
        if (missing_list)
        XFreeStringList (missing_list);
        if (! xfs)
              xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
                                    p0, &missing_list,
                                    &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +            print_fontset_result (xfs, p0, missing_list, missing_count);
 +#endif
              if (missing_list)
                XFreeStringList (missing_list);
              if (xfs)
            }
        }
        xfree (fontsetname);
 +      if (! xfs && base_fontname != xic_defaut_fontset)
 +      {
 +        /* Try the default fontset name at a last resort.  */
 +        fontsetname = xic_create_fontsetname (xic_defaut_fontset, False);
 +        xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
 +                              fontsetname, &missing_list,
 +                              &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +        print_fontset_result (xfs, fontsetname, missing_list, missing_count);
 +#endif
 +        if (missing_list)
 +          XFreeStringList (missing_list);
 +        xfree (fontsetname);
 +      }
      }
  
    if (FRAME_XIC_BASE_FONTNAME (f))
    return xfs;
  }
  
 +#ifdef USE_FONT_BACKEND
 +
 +static XFontSet
 +xic_create_xfontset2 (f)
 +     struct frame *f;
 +{
 +  XFontSet xfs = NULL;
 +  struct font *font = FRAME_FONT_OBJECT (f);
 +  int pixel_size = font->pixel_size;
 +  Lisp_Object rest, frame;
 +
 +  /* See if there is another frame already using same fontset.  */
 +  FOR_EACH_FRAME (rest, frame)
 +    {
 +      struct frame *cf = XFRAME (frame);
 +
 +      if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
 +          && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
 +        && FRAME_FONT_OBJECT (f)
 +        && FRAME_FONT_OBJECT (f)->pixel_size == pixel_size)
 +        {
 +          xfs = FRAME_XIC_FONTSET (cf);
 +          break;
 +        }
 +    }
 +
 +  if (! xfs)
 +    {
 +      char buf[256];
 +      char **missing_list;
 +      int missing_count;
 +      char *def_string;
 +      char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
 +
 +      sprintf (buf, xlfd_format, pixel_size);
 +      missing_list = NULL;
 +      xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
 +                          &missing_list, &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +      print_fontset_result (xfs, buf, missing_list, missing_count);
 +#endif
 +      if (missing_list)
 +      XFreeStringList (missing_list);
 +      if (! xfs)
 +      {
 +        /* List of pixel sizes most likely available.  Find one that
 +           is closest to pixel_size.  */
 +        int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
 +        int *smaller, *larger;
 +
 +        for (smaller = sizes; smaller[1]; smaller++)
 +          if (smaller[1] >= pixel_size)
 +            break;
 +        larger = smaller + 1;
 +        if (*larger == pixel_size)
 +          larger++;
 +        while (*smaller || *larger)
 +          {
 +            int this_size;
 +
 +            if (! *larger)
 +              this_size = *smaller--;
 +            else if (! *smaller)
 +              this_size = *larger++;
 +            else if (pixel_size - *smaller < *larger - pixel_size)
 +              this_size = *smaller--;
 +            else
 +              this_size = *larger++;
 +            sprintf (buf, xlfd_format, this_size);
 +            missing_list = NULL;
 +            xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
 +                                  &missing_list, &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +            print_fontset_result (xfs, buf, missing_list, missing_count);
 +#endif
 +            if (missing_list)
 +              XFreeStringList (missing_list);
 +            if (xfs)
 +              break;
 +          }
 +      }
 +      if (! xfs)
 +      {
 +        char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
 +
 +        missing_list = NULL;
 +        xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
 +                              &missing_list, &missing_count, &def_string);
 +#ifdef DEBUG_XIC_FONTSET
 +        print_fontset_result (xfs, last_resort, missing_list, missing_count);
 +#endif
 +        if (missing_list)
 +          XFreeStringList (missing_list);
 +      }
 +
 +    }
 +
 +  return xfs;
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
  /* Free the X fontset of frame F if it is the last frame using it.  */
  
  void
@@@ -2404,11 -2269,6 +2396,11 @@@ create_frame_xic (f
      return;
  
    /* Create X fontset. */
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    xfs = xic_create_xfontset2 (f);
 +  else
 +#endif
    xfs = xic_create_xfontset
      (f, (FRAME_FONTSET (f) < 0) ? NULL
          : (char *) SDATA (fontset_ascii (FRAME_FONTSET (f))));
@@@ -2567,11 -2427,6 +2559,11 @@@ xic_set_xfontset (f, base_fontname
  
    xic_free_xfontset (f);
  
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    xfs = xic_create_xfontset2 (f);
 +  else
 +#endif
    xfs = xic_create_xfontset (f, base_fontname);
  
    attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
@@@ -3199,44 -3054,6 +3191,44 @@@ unwind_create_frame (frame
    return Qnil;
  }
  
 +#ifdef USE_FONT_BACKEND
 +static void
 +x_default_font_parameter (f, parms)
 +     struct frame *f;
 +     Lisp_Object parms;
 +{
 +  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 +  Lisp_Object font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font",
 +                              RES_TYPE_STRING);
 +
 +  if (! STRINGP (font))
 +    {
 +      char *names[]
 +      = { "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
 +          "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
 +          "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
 +          /* This was formerly the first thing tried, but it finds
 +             too many fonts and takes too long.  */
 +          "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
 +          /* If those didn't work, look for something which will
 +             at least work.  */
 +          "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
 +          "fixed",
 +          NULL };
 +      int i;
 +
 +      for (i = 0; names[i]; i++)
 +      {
 +        font = font_open_by_name (f, names[i]);
 +        if (! NILP (font))
 +          break;
 +      }
 +      if (NILP (font))
 +      error ("No suitable font was found");
 +    }
 +  x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
 +}
 +#endif        /* USE_FONT_BACKEND */
  
  DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
         1, 1, 0,
@@@ -3417,75 -3234,43 +3409,75 @@@ This function is an internal primitive-
        specbind (Qx_resource_name, name);
      }
  
 +  f->resx = dpyinfo->resx;
 +  f->resy = dpyinfo->resy;
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      /* Perhaps, we must allow frame parameter, say `font-backend',
 +       to specify which font backends to use.  */
 +#ifdef HAVE_FREETYPE
 +#ifdef HAVE_XFT
 +      register_font_driver (&xftfont_driver, f);
 +#else /* not HAVE_XFT */
 +      register_font_driver (&ftxfont_driver, f);
 +#endif        /* not HAVE_XFT */
 +#endif        /* HAVE_FREETYPE */
 +      register_font_driver (&xfont_driver, f);
 +
 +      x_default_parameter (f, parms, Qfont_backend, Qnil,
 +                         "fontBackend", "FontBackend", RES_TYPE_STRING);
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +
    /* Extract the window parameters from the supplied values
       that are needed to determine window geometry.  */
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    x_default_font_parameter (f, parms);
 +else
 +#endif        /* USE_FONT_BACKEND */
    {
      Lisp_Object font;
  
      font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
  
 -    BLOCK_INPUT;
 -    /* First, try whatever font the caller has specified.  */
 -    if (STRINGP (font))
 -      {
 -      tem = Fquery_fontset (font, Qnil);
 -      if (STRINGP (tem))
 -        font = x_new_fontset (f, SDATA (tem));
 -      else
 -        font = x_new_font (f, SDATA (font));
 -      }
 -
 -    /* Try out a font which we hope has bold and italic variations.  */
 -    if (!STRINGP (font))
 -      font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
 +    /* If the caller has specified no font, try out fonts which we
 +       hope have bold and italic variations.  */
      if (!STRINGP (font))
 -      font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
 -    if (! STRINGP (font))
 -      font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
 -    if (! STRINGP (font))
 -      /* This was formerly the first thing tried, but it finds too many fonts
 -       and takes too long.  */
 -      font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
 -    /* If those didn't work, look for something which will at least work.  */
 -    if (! STRINGP (font))
 -      font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
 -    UNBLOCK_INPUT;
 -    if (! STRINGP (font))
 -      font = build_string ("fixed");
 +      {
 +      char *names[]
 +        = { "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
 +            "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
 +            "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
 +            /* This was formerly the first thing tried, but it finds
 +               too many fonts and takes too long.  */
 +            "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
 +            /* If those didn't work, look for something which will
 +               at least work.  */
 +            "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
 +            NULL };
 +      int i;
 +
 +      BLOCK_INPUT;
 +      for (i = 0; names[i]; i++)
 +        {
 +          Lisp_Object list;
  
 -    x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
 +          list = x_list_fonts (f, build_string (names[i]), 0, 1);
 +          if (CONSP (list))
 +            {
 +              font = XCAR (list);
 +              break;
 +            }
 +        }
 +      UNBLOCK_INPUT;
 +      if (! STRINGP (font))
 +        font = build_string ("fixed");
 +      }
 +    x_default_parameter (f, parms, Qfont, font,
 +                       "font", "Font", RES_TYPE_STRING);
    }
  
  #ifdef USE_LUCID
@@@ -5016,35 -4801,8 +5008,35 @@@ x_create_tip_frame (dpyinfo, parms, tex
        specbind (Qx_resource_name, name);
      }
  
 +  f->resx = dpyinfo->resx;
 +  f->resy = dpyinfo->resy;
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      /* Perhaps, we must allow frame parameter, say `font-backend',
 +       to specify which font backends to use.  */
 +#ifdef HAVE_FREETYPE
 +#ifdef HAVE_XFT
 +      register_font_driver (&xftfont_driver, f);
 +#else /* not HAVE_XFT */
 +      register_font_driver (&ftxfont_driver, f);
 +#endif        /* not HAVE_XFT */
 +#endif        /* HAVE_FREETYPE */
 +      register_font_driver (&xfont_driver, f);
 +
 +      x_default_parameter (f, parms, Qfont_backend, Qnil,
 +                         "fontBackend", "FontBackend", RES_TYPE_STRING);
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +
    /* Extract the window parameters from the supplied values that are
       needed to determine window geometry.  */
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    x_default_font_parameter (f, parms);
 +else
 +#endif        /* USE_FONT_BACKEND */
    {
      Lisp_Object font;
  
        {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
 -        font = x_new_fontset (f, SDATA (tem));
 +        font = x_new_fontset (f, tem);
        else
          font = x_new_font (f, SDATA (font));
        }
      if (! STRINGP (font))
        font = build_string ("fixed");
  
 -    x_default_parameter (f, parms, Qfont, font,
 -                       "font", "Font", RES_TYPE_STRING);
 +    x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
    }
  
    x_default_parameter (f, parms, Qborder_width, make_number (2),
      Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
                                            Qnil));
  
+   /* FIXME - can this be done in a similar way to normal frames?
+      http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
+   /* Set the `display-type' frame parameter before setting up faces. */
+   {
+     Lisp_Object disptype;
+     if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
+       disptype = intern ("mono");
+     else if (FRAME_X_DISPLAY_INFO (f)->visual->class == GrayScale
+              || FRAME_X_DISPLAY_INFO (f)->visual->class == StaticGray)
+       disptype = intern ("grayscale");
+     else
+       disptype = intern ("color");
+     if (NILP (Fframe_parameter (frame, Qdisplay_type)))
+       Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
+                                               Qnil));
+   }
    /* Set up faces after all frame parameters are known.  This call
       also merges in face attributes specified for new frames.
  
@@@ -6002,9 -5781,6 +6014,9 @@@ frame_parm_handler x_frame_parm_handler
    x_set_fringe_width,
    x_set_wait_for_wm,
    x_set_fullscreen,
 +#ifdef USE_FONT_BACKEND
 +  x_set_font_backend
 +#endif        /* USE_FONT_BACKEND */
  };
  
  void
@@@ -6215,7 -5991,6 +6227,7 @@@ the tool bar buttons.  */)
    find_ccl_program_func = x_find_ccl_program;
    query_font_func = x_query_font;
    set_frame_fontset_func = x_set_font;
 +  get_font_repertory_func = x_get_font_repertory;
    check_window_system_func = check_x;
  
    hourglass_atimer = NULL;
diff --combined src/xmenu.c
index 4e7f07c375a7500234b867af0e3edca687ab64a6,14c723971108450a6726dac140c774c86f0fdcba..15aab98f9c5eadde96cc1321f2d9e3eac7f2001e
@@@ -248,10 -248,10 +248,10 @@@ menubar_id_to_frame (id
    Lisp_Object tail, frame;
    FRAME_PTR f;
  
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        frame = XCAR (tail);
 -      if (!GC_FRAMEP (frame))
 +      if (!FRAMEP (frame))
          continue;
        f = XFRAME (frame);
        if (!FRAME_WINDOW_P (f))
@@@ -354,15 -354,8 +354,8 @@@ save_menu_items (
  static void
  grow_menu_items ()
  {
-   Lisp_Object old;
-   int old_size = menu_items_allocated;
-   old = menu_items;
    menu_items_allocated *= 2;
-   menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
-   bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
-        old_size * sizeof (Lisp_Object));
+   menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
  }
  
  /* Begin a submenu.  */
@@@ -1568,10 -1561,10 +1561,10 @@@ show_help_event (f, widget, help
        xt_or_gtk_widget frame_widget = XtParent (widget);
        Lisp_Object tail;
  
 -      for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 +      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
        {
          frame = XCAR (tail);
 -        if (GC_FRAMEP (frame)
 +        if (FRAMEP (frame)
              && (f = XFRAME (frame),
                  FRAME_X_P (f) && f->output_data.x->widget == frame_widget))
            break;
@@@ -1637,7 -1630,7 +1630,7 @@@ menu_highlight_callback (widget, id, ca
  static void
  find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
       FRAME_PTR f;
 -     int menu_bar_items_used;
 +     EMACS_INT menu_bar_items_used;
       Lisp_Object vector;
       void *client_data;
  {
diff --combined src/xterm.c
index a1beab492eee7f29f3524706e75c9502b3d1c07c,29c840ff79948ef3f54002d55653f7cde8f02ba6..68670795fa374210a13b4b7657c296d9057cf2c4
@@@ -67,7 -67,6 +67,7 @@@ Boston, MA 02110-1301, USA.  *
  /* #include <sys/param.h>  */
  
  #include "charset.h"
 +#include "character.h"
  #include "coding.h"
  #include "ccl.h"
  #include "frame.h"
  #include "gtkutil.h"
  #endif
  
 +#ifdef USE_FONT_BACKEND
 +#include "font.h"
 +#endif        /* USE_FONT_BACKEND */
 +
  #ifdef USE_LUCID
  extern int xlwmenu_window_p P_ ((Widget w, Window window));
  extern void xlwmenu_redisplay P_ ((Widget));
@@@ -877,8 -872,7 +877,8 @@@ XTreset_terminal_modes (struct termina
  
  /* Function prototypes of this page.  */
  
 -static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 +static int x_encode_char P_ ((int, XChar2b *, struct font_info *,
 +                            struct charset *, int *));
  
  
  /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
@@@ -957,13 -951,13 +957,13 @@@ x_per_char_metric (font, char2b, font_t
     the two-byte form of C.  Encoding is returned in *CHAR2B.  */
  
  static int
 -x_encode_char (c, char2b, font_info, two_byte_p)
 +x_encode_char (c, char2b, font_info, charset, two_byte_p)
       int c;
       XChar2b *char2b;
       struct font_info *font_info;
 +     struct charset *charset;
       int *two_byte_p;
  {
 -  int charset = CHAR_CHARSET (c);
    XFontStruct *font = font_info->font;
  
    /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
        check_ccl_update (ccl);
        if (CHARSET_DIMENSION (charset) == 1)
        {
 -        ccl->reg[0] = charset;
 +        ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = char2b->byte2;
          ccl->reg[2] = -1;
        }
        else
        {
 -        ccl->reg[0] = charset;
 +        ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = char2b->byte1;
          ccl->reg[2] = char2b->byte2;
        }
  
 -      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
 +      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
  
        /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
        if (font->max_byte1 == 0)       /* 1-byte font */
 -      char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
 +      STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
        else
 -      char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
 +      STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
      }
 -  else if (font_info->encoding[charset])
 +  else if (font_info->encoding_type)
      {
        /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
 -      int enc = font_info->encoding[charset];
 +      unsigned char enc = font_info->encoding_type;
  
        if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
@@@ -1129,20 -1123,15 +1129,20 @@@ x_set_mouse_face_gc (s
      face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
  
    if (s->first_glyph->type == CHAR_GLYPH)
 -    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
 +    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
    else
 -    face_id = FACE_FOR_CHAR (s->f, face, 0);
 +    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
    s->face = FACE_FROM_ID (s->f, face_id);
    PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
  
    /* If font in this face is same as S->font, use it.  */
    if (s->font == s->face->font)
      s->gc = s->face->gc;
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
 +    /* No need of setting a font for s->gc.  */
 +    s->gc = s->face->gc;
 +#endif        /* USE_FONT_BACKEND */
    else
      {
        /* Otherwise construct scratch_cursor_gc with values from FACE
@@@ -1236,61 -1225,16 +1236,61 @@@ x_set_glyph_string_gc (s
  static INLINE void
  x_set_glyph_string_clipping (s)
       struct glyph_string *s;
 +{
 +#ifdef USE_FONT_BACKEND
 +  XRectangle *r = s->clip;
 +#else
 +  XRectangle r[2];
 +#endif
 +  int n = get_glyph_string_clip_rects (s, r, 2);
 +
 +  if (n > 0)
 +    XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
 +#ifdef USE_FONT_BACKEND
 +  s->num_clips = n;
 +#endif
 +}
 +
 +
 +/* Set SRC's clipping for output of glyph string DST.  This is called
 +   when we are drawing DST's left_overhang or right_overhang only in
 +   the area of SRC.  */
 +
 +static void
 +x_set_glyph_string_clipping_exactly (src, dst)
 +     struct glyph_string *src, *dst;
  {
    XRectangle r;
 -  get_glyph_string_clip_rect (s, &r);
 -  XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
 +
 +#ifdef USE_FONT_BACKEND
 +  if (enable_font_backend)
 +    {
 +      r.x = src->x;
 +      r.width = src->width;
 +      r.y = src->y;
 +      r.height = src->height;
 +      dst->clip[0] = r;
 +      dst->num_clips = 1;
 +    }
 +  else
 +    {
 +#endif        /* USE_FONT_BACKEND */
 +  struct glyph_string *clip_head = src->clip_head;
 +  struct glyph_string *clip_tail = src->clip_tail;
 +
 +  /* This foces clipping just this glyph string.  */
 +  src->clip_head = src->clip_tail = src;
 +  get_glyph_string_clip_rect (src, &r);
 +  src->clip_head = clip_head, src->clip_tail = clip_tail;
 +#ifdef USE_FONT_BACKEND
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +  XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
  }
  
  
  /* RIF:
 -   Compute left and right overhang of glyph string S.  If S is a glyph
 -   string for a composition, assume overhangs don't exist.  */
 +   Compute left and right overhang of glyph string S.  */
  
  static void
  x_compute_glyph_string_overhangs (s)
      {
        XCharStruct cs;
        int direction, font_ascent, font_descent;
 +
 +#ifdef USE_FONT_BACKEND
 +      if (enable_font_backend)
 +      {
 +        unsigned *code = alloca (sizeof (unsigned) * s->nchars);
 +        struct font *font = (struct font *) s->font_info;
 +        struct font_metrics metrics;
 +        int i;
 +
 +        for (i = 0; i < s->nchars; i++)
 +          code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
 +        font->driver->text_extents (font, code, s->nchars, &metrics);
 +        cs.rbearing = metrics.rbearing;
 +        cs.lbearing = metrics.lbearing;
 +        cs.width = metrics.width;
 +      }
 +      else
 +#endif        /* USE_FONT_BACKEND */
        XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
                      &font_ascent, &font_descent, &cs);
        s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
        s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
      }
 +  else if (s->cmp)
 +    {
 +      s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
 +      s->left_overhang = - s->cmp->lbearing;
 +    }
  }
  
  
@@@ -1401,7 -1322,7 +1401,7 @@@ x_draw_glyph_string_foreground (s
       of S to the right of that box line.  */
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
          x += g->pixel_width;
        }
      }
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
 +    {
 +      int boff = s->font_info->baseline_offset;
 +      struct font *font = (struct font *) s->font_info;
 +      int y;
 +
 +      if (s->font_info->vertical_centering)
 +      boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
 +
 +      y = s->ybase - boff;
 +      if (s->for_overlaps
 +        || (s->background_filled_p && s->hl != DRAW_CURSOR))
 +      font->driver->draw (s, 0, s->nchars, x, y, 0);
 +      else
 +      font->driver->draw (s, 0, s->nchars, x, y, 1);
 +      if (s->face->overstrike)
 +      font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
 +    }
 +#endif        /* USE_FONT_BACKEND */
    else
      {
        char *char1b = (char *) s->char2b;
@@@ -1497,13 -1398,13 +1497,13 @@@ static voi
  x_draw_composite_glyph_string_foreground (s)
       struct glyph_string *s;
  {
 -  int i, x;
 +  int i, j, x;
  
    /* If first glyph of S has a left box line, start drawing the text
       of S to the right of that box line.  */
 -  if (s->face->box != FACE_NO_BOX
 +  if (s->face && s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p)
-     x = s->x + abs (s->face->box_line_width);
+     x = s->x + eabs (s->face->box_line_width);
    else
      x = s->x;
  
        XDrawRectangle (s->display, s->window, s->gc, x, s->y,
                        s->width - 1, s->height - 1);
      }
 -  else
 +#ifdef USE_FONT_BACKEND
 +  else if (enable_font_backend)
      {
 -      for (i = 0; i < s->nchars; i++, ++s->gidx)
 +      struct font *font = (struct font *) s->font_info;
 +      int y = s->ybase;
 +      int width = 0;
 +
 +      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
 -        XDrawString16 (s->display, s->window, s->gc,
 -                       x + s->cmp->offsets[s->gidx * 2],
 -                       s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
 -                       s->char2b + i, 1);
 -        if (s->face->overstrike)
 -          XDrawString16 (s->display, s->window, s->gc,
 -                         x + s->cmp->offsets[s->gidx * 2] + 1,
 -                         s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
 -                         s->char2b + i, 1);
 +        Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
 +                                    ->key_and_value,
 +                                    s->cmp->hash_index * 2);
 +        int from;
 +
 +        for (i = from = 0; i < s->nchars; i++)
 +          {
 +            Lisp_Object g = LGSTRING_GLYPH (gstring, i);
 +            Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
 +            int xoff, yoff, wadjust;
 +
 +            if (! VECTORP (adjustment))
 +              {
 +                width += XINT (LGLYPH_WIDTH (g));
 +                continue;
 +              }
 +            if (from < i)
 +              {
 +                font->driver->draw (s, from, i, x, y, 0);
 +                x += width;
 +              }
 +            xoff = XINT (AREF (adjustment, 0));
 +            yoff = XINT (AREF (adjustment, 1));
 +            wadjust = XINT (AREF (adjustment, 2));
 +
 +            font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
 +            x += XINT (LGLYPH_WIDTH (g)) + wadjust;
 +            from = i + 1;
 +            width = 0;
 +          }
 +        if (from < i)
 +          font->driver->draw (s, from, i, x, y, 0);
        }
 +      else
 +      {
 +        for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
 +          if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
 +            {
 +              int xx = x + s->cmp->offsets[j * 2];
 +              int yy = y - s->cmp->offsets[j * 2 + 1];
 +
 +              font->driver->draw (s, j, j + 1, xx, yy, 0);
 +              if (s->face->overstrike)
 +                font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
 +            }
 +      }
 +    }
 +#endif        /* USE_FONT_BACKEND */
 +  else
 +    {
 +      for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
 +      if (s->face)
 +        {
 +          XDrawString16 (s->display, s->window, s->gc,
 +                         x + s->cmp->offsets[j * 2],
 +                         s->ybase - s->cmp->offsets[j * 2 + 1],
 +                         s->char2b + j, 1);
 +          if (s->face->overstrike)
 +            XDrawString16 (s->display, s->window, s->gc,
 +                           x + s->cmp->offsets[j * 2] + 1,
 +                           s->ybase - s->cmp->offsets[j * 2 + 1],
 +                           s->char2b + j, 1);
 +        }
      }
  }
  
@@@ -1627,8 -1470,8 +1627,8 @@@ x_frame_of_widget (widget
  
    /* Look for a frame with that top-level widget.  Allocate the color
       on that frame to get the right gamma correction value.  */
 -  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
 -    if (GC_FRAMEP (XCAR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
 +    if (FRAMEP (XCAR (tail))
        && (f = XFRAME (XCAR (tail)),
            (FRAME_X_P (f)
               && f->output_data.nothing != 1
@@@ -2357,7 -2200,7 +2357,7 @@@ x_draw_glyph_string_box (s
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
  
-   width = abs (s->face->box_line_width);
+   width = eabs (s->face->box_line_width);
    raised_p = s->face->box == FACE_RAISED_BOX;
    left_x = s->x;
    right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@@@ -2403,7 -2246,7 +2403,7 @@@ x_draw_image_foreground (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
@@@ -2496,7 -2339,7 +2496,7 @@@ x_draw_image_relief (s
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
      }
    else
      {
-       thick = abs (s->img->relief);
+       thick = eabs (s->img->relief);
        raised_p = s->img->relief > 0;
      }
  
@@@ -2548,7 -2391,7 +2548,7 @@@ x_draw_image_foreground_1 (s, pixmap
    if (s->face->box != FACE_NO_BOX
        && s->first_glyph->left_box_line_p
        && s->slice.x == 0)
-     x += abs (s->face->box_line_width);
+     x += eabs (s->face->box_line_width);
  
    /* If there is a margin around the image, adjust x- and y-position
       by that margin.  */
@@@ -2648,7 -2491,7 +2648,7 @@@ static voi
  x_draw_image_glyph_string (s)
       struct glyph_string *s;
  {
-   int box_line_hwidth = abs (s->face->box_line_width);
+   int box_line_hwidth = eabs (s->face->box_line_width);
    int box_line_vwidth = max (s->face->box_line_width, 0);
    int height;
    Pixmap pixmap = None;
@@@ -2840,25 -2683,15 +2840,25 @@@ x_draw_glyph_string (s
  {
    int relief_drawn_p = 0;
  
 -  /* If S draws into the background of its successor, draw the
 -     background of the successor first so that S can draw into it.
 +  /* If S draws into the background of its successors, draw the
 +     background of the successors first so that S can draw into it.
       This makes S->next use XDrawString instead of XDrawImageString.  */
    if (s->next && s->right_overhang && !s->for_overlaps)
      {
 -      xassert (s->next->img == NULL);
 -      x_set_glyph_string_gc (s->next);
 -      x_set_glyph_string_clipping (s->next);
 -      x_draw_glyph_string_background (s->next, 1);
 +      int width;
 +      struct glyph_string *next;
 +
 +      for (width = 0, next = s->next; next;
 +         width += next->width, next = next->next)
 +      if (next->first_glyph->type != IMAGE_GLYPH)
 +        {
 +          x_set_glyph_string_gc (next);
 +          x_set_glyph_string_clipping (next);
 +          x_draw_glyph_string_background (next, 1);
 +#ifdef USE_FONT_BACKEND
 +          next->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
 +        }
      }
  
    /* Set up S->gc, set clipping and draw S.  */
        x_set_glyph_string_clipping (s);
        relief_drawn_p = 1;
      }
 +  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
 +         || (s->next && s->next->hl != s->hl && s->right_overhang))
 +    /* We must clip just this glyph.  left_overhang part has already
 +       drawn when s->prev was drawn, and right_overhang part will be
 +       drawn later when s->next is drawn. */
 +    x_set_glyph_string_clipping_exactly (s, s);
    else
      x_set_glyph_string_clipping (s);
  
          int y;
  
          /* Get the underline thickness.  Default is 1 pixel.  */
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend)
 +          /* In the future, we must use information of font.  */
 +          h = 1;
 +        else
 +#endif        /* USE_FONT_BACKEND */
          if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
            h = 1;
  
 -        y = s->y + s->height - h;
 -        if (!x_underline_at_descent_line)
 -            {
 -            /* Get the underline position.  This is the recommended
 -                 vertical offset in pixels from the baseline to the top of
 -                 the underline.  This is a signed value according to the
 -                 specs, and its default is
 -
 -               ROUND ((maximum descent) / 2), with
 -               ROUND(x) = floor (x + 0.5)  */
 -
 -              if (x_use_underline_position_properties
 -                  && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
 -                y = s->ybase + (long) tem;
 -              else if (s->face->font)
 -                y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
 -            }
 +#ifdef USE_FONT_BACKEND
 +        if (enable_font_backend)
 +          {
 +            if (s->face->font)
 +              /* In the future, we must use information of font.  */
 +              y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
 +            else
 +              y = s->y + s->height - h;
 +          }
 +        else
 +#endif
 +          {
 +            y = s->y + s->height - h;
 +            if (!x_underline_at_descent_line)
 +              {
 +                /* Get the underline position.  This is the recommended
 +                   vertical offset in pixels from the baseline to the top of
 +                   the underline.  This is a signed value according to the
 +                   specs, and its default is
 +
 +                   ROUND ((maximum descent) / 2), with
 +                   ROUND(x) = floor (x + 0.5)  */
 +
 +                if (x_use_underline_position_properties
 +                    && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
 +                  y = s->ybase + (long) tem;
 +                else if (s->face->font)
 +                  y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
 +              }
 +          }
  
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
        /* Draw relief if not yet drawn.  */
        if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
        x_draw_glyph_string_box (s);
 +
 +      if (s->prev)
 +      {
 +        struct glyph_string *prev;
 +
 +        for (prev = s->prev; prev; prev = prev->prev)
 +          if (prev->hl != s->hl
 +              && prev->x + prev->width + prev->right_overhang > s->x)
 +            {
 +              /* As prev was drawn while clipped to its own area, we
 +                 must draw the right_overhang part using s->hl now.  */
 +              enum draw_glyphs_face save = prev->hl;
 +
 +              prev->hl = s->hl;
 +              x_set_glyph_string_gc (prev);
 +              x_set_glyph_string_clipping_exactly (s, prev);
 +              if (prev->first_glyph->type == CHAR_GLYPH)
 +                x_draw_glyph_string_foreground (prev);
 +              else
 +                x_draw_composite_glyph_string_foreground (prev);
 +              XSetClipMask (prev->display, prev->gc, None);
 +              prev->hl = save;
 +#ifdef USE_FONT_BACKEND
 +              prev->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
 +            }
 +      }
 +
 +      if (s->next)
 +      {
 +        struct glyph_string *next;
 +
 +        for (next = s->next; next; next = next->next)
 +          if (next->hl != s->hl
 +              && next->x - next->left_overhang < s->x + s->width)
 +            {
 +              /* As next will be drawn while clipped to its own area,
 +                 we must draw the left_overhang part using s->hl now.  */
 +              enum draw_glyphs_face save = next->hl;
 +
 +              next->hl = s->hl;
 +              x_set_glyph_string_gc (next);
 +              x_set_glyph_string_clipping_exactly (s, next);
 +              if (next->first_glyph->type == CHAR_GLYPH)
 +                x_draw_glyph_string_foreground (next);
 +              else
 +                x_draw_composite_glyph_string_foreground (next);
 +              XSetClipMask (next->display, next->gc, None);
 +              next->hl = save;
 +#ifdef USE_FONT_BACKEND
 +              next->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
 +            }
 +      }
      }
  
    /* Reset clipping.  */
    XSetClipMask (s->display, s->gc, None);
 +#ifdef USE_FONT_BACKEND
 +  s->num_clips = 0;
 +#endif        /* USE_FONT_BACKEND */
  }
  
  /* Shift display to make room for inserted glyphs.   */
@@@ -3535,9 -3286,9 +3535,9 @@@ x_focus_changed (type, state, dpyinfo, 
  
            /* Don't stop displaying the initial startup message
               for a switch-frame event we don't need.  */
 -          if (GC_NILP (Vterminal_frame)
 -              && GC_CONSP (Vframe_list)
 -              && !GC_NILP (XCDR (Vframe_list)))
 +          if (NILP (Vterminal_frame)
 +              && CONSP (Vframe_list)
 +              && !NILP (XCDR (Vframe_list)))
              {
                bufp->kind = FOCUS_IN_EVENT;
                XSETFRAME (bufp->frame_or_window, frame);
@@@ -3647,7 -3398,7 +3647,7 @@@ x_frame_rehighlight (dpyinfo
    if (dpyinfo->x_focus_frame)
      {
        dpyinfo->x_highlight_frame
 -      = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
 +      = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
           : dpyinfo->x_focus_frame);
        if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@@ -4193,13 -3944,15 +4193,13 @@@ x_window_to_scroll_bar (display, window
    window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
  #endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
  
 -  for (tail = Vframe_list;
 -       XGCTYPE (tail) == Lisp_Cons;
 -       tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        Lisp_Object frame, bar, condemned;
  
        frame = XCAR (tail);
        /* All elements of Vframe_list should be frames.  */
 -      if (! GC_FRAMEP (frame))
 +      if (! FRAMEP (frame))
        abort ();
  
        if (! FRAME_X_P (XFRAME (frame)))
        for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
           /* This trick allows us to search both the ordinary and
                condemned scroll bar lists with one loop.  */
 -         ! GC_NILP (bar) || (bar = condemned,
 +         ! NILP (bar) || (bar = condemned,
                               condemned = Qnil,
 -                             ! GC_NILP (bar));
 +                             ! NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
              FRAME_X_DISPLAY (XFRAME (frame)) == display)
@@@ -4235,7 -3988,9 +4235,7 @@@ x_window_to_menu_bar (window
  {
    Lisp_Object tail;
  
 -  for (tail = Vframe_list;
 -       XGCTYPE (tail) == Lisp_Cons;
 -       tail = XCDR (tail))
 +  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
      {
        if (FRAME_X_P (XFRAME (XCAR (tail))))
          {
@@@ -4630,7 -4385,7 +4630,7 @@@ xaw_jump_callback (widget, client_data
    whole = 10000000;
    portion = shown < 1 ? top * whole : 0;
  
-   if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
+   if (shown < 1 && (eabs (top + shown - 1) < 1.0/height))
      /* Some derivatives of Xaw refuse to shrink the thumb when you reach
         the bottom, so we force the scrolling whenever we see that we're
         too close to the bottom (in x_set_toolkit_scroll_bar_thumb
@@@ -4671,12 -4426,12 +4671,12 @@@ xaw_scroll_callback (widget, client_dat
    XtVaGetValues (widget, XtNheight, &height, NULL);
    UNBLOCK_INPUT;
  
-   if (abs (position) >= height)
+   if (eabs (position) >= height)
      part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
  
    /* If Xaw3d was compiled with ARROW_SCROLLBAR,
       it maps line-movement to call_data = max(5, height/20).  */
-   else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
+   else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
      part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
    else
      part = scroll_bar_move_ratio;
@@@ -5651,7 -5406,7 +5651,7 @@@ x_scroll_bar_handle_click (bar, event, 
       XEvent *event;
       struct input_event *emacs_event;
  {
 -  if (! GC_WINDOWP (bar->window))
 +  if (! WINDOWP (bar->window))
      abort ();
  
    emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
@@@ -5746,7 -5501,7 +5746,7 @@@ x_scroll_bar_note_movement (bar, event
    XSETVECTOR (last_mouse_scroll_bar, bar);
  
    /* If we're dragging the bar, display it.  */
 -  if (! GC_NILP (bar->dragging))
 +  if (! NILP (bar->dragging))
      {
        /* Where should the handle be now?  */
        int new_start = event->xmotion.y - XINT (bar->dragging);
@@@ -6623,14 -6378,41 +6623,14 @@@ handle_one_xevent (dpyinfo, eventp, fin
              goto done_keysym;
            }
  
 -        /* Keysyms directly mapped to supported Unicode characters.  */
 -        if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
 -            || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
 +        /* Keysyms directly mapped to Unicode characters.  */
 +        if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
            {
 -            int code = keysym & 0xFFFF, charset_id, c1, c2;
 -
 -            if (code < 0x80)
 -              {
 -                inev.ie.kind = ASCII_KEYSTROKE_EVENT;
 -                inev.ie.code = code;
 -              }
 -            else if (code < 0x100)
 -              {
 -                if (code < 0xA0)
 -                  charset_id = CHARSET_8_BIT_CONTROL;
 -                else
 -                  charset_id = charset_latin_iso8859_1;
 -                inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
 -                inev.ie.code = MAKE_CHAR (charset_id, code, 0);
 -              }
 +            if (keysym < 0x01000080)
 +              inev.ie.kind = ASCII_KEYSTROKE_EVENT;
              else
 -              {
 -                if (code < 0x2500)
 -                  charset_id = charset_mule_unicode_0100_24ff,
 -                    code -= 0x100;
 -                else if (code < 0xE000)
 -                  charset_id = charset_mule_unicode_2500_33ff,
 -                    code -= 0x2500;
 -                else
 -                  charset_id = charset_mule_unicode_e000_ffff,
 -                    code -= 0xE000;
 -                c1 = (code / 96) + 32, c2 = (code % 96) + 32;
 -                inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
 -                inev.ie.code = MAKE_CHAR (charset_id, c1, c2);
 -              }
 +              inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
 +            inev.ie.code = keysym & 0xFFFFFF;
              goto done_keysym;
            }
  
            register int c;
            int nchars, len;
  
 -          /* The input should be decoded with `coding_system'
 -             which depends on which X*LookupString function
 -             we used just above and the locale.  */
 -          setup_coding_system (coding_system, &coding);
 -          coding.src_multibyte = 0;
 -          coding.dst_multibyte = 1;
 -          /* The input is converted to events, thus we can't
 -             handle composition.  Anyway, there's no XIM that
 -             gives us composition information.  */
 -          coding.composing = COMPOSITION_DISABLED;
 -
 -          if (nbytes > 0)
 +          for (i = 0, nchars = 0; i < nbytes; i++)
 +            {
 +              if (ASCII_BYTE_P (copy_bufptr[i]))
 +                nchars++;
 +              STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
 +            }
 +
 +          if (nchars < nbytes)
              {
                /* Decode the input data.  */
                int require;
                unsigned char *p;
  
 -              for (i = 0; i < nbytes; i++)
 -                {
 -                  STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
 -                }
 -
 -              require = decoding_buffer_size (&coding, nbytes);
 -              p = (unsigned char *) alloca (require);
 +              /* The input should be decoded with `coding_system'
 +                 which depends on which X*LookupString function
 +                 we used just above and the locale.  */
 +              setup_coding_system (coding_system, &coding);
 +              coding.src_multibyte = 0;
 +              coding.dst_multibyte = 1;
 +              /* The input is converted to events, thus we can't
 +                 handle composition.  Anyway, there's no XIM that
 +                 gives us composition information.  */
 +              coding.common_flags &= ~CODING_ANNOTATION_MASK;
 +
 +              require = MAX_MULTIBYTE_LENGTH * nbytes;
 +              coding.destination = alloca (require);
 +              coding.dst_bytes = require;
                coding.mode |= CODING_MODE_LAST_BLOCK;
 -              /* We explicitly disable composition handling because
 -                 key data should not contain any composition sequence.  */
 -              coding.composing = COMPOSITION_DISABLED;
 -              decode_coding (&coding, copy_bufptr, p, nbytes, require);
 +              decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
                nbytes = coding.produced;
                nchars = coding.produced_char;
 -              copy_bufptr = p;
 +              copy_bufptr = coding.destination;
 +            }
  
 -              /* Convert the input data to a sequence of
 -                 character events.  */
 -              for (i = 0; i < nbytes; i += len)
 -                {
 -                  if (nchars == nbytes)
 -                    c = copy_bufptr[i], len = 1;
 -                  else
 -                    c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
 -                                                nbytes - i, len);
 -                  inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
 -                                  ? ASCII_KEYSTROKE_EVENT
 -                                  : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
 -                  inev.ie.code = c;
 -                  kbd_buffer_store_event_hold (&inev.ie, hold_quit);
 -                }
 +          /* Convert the input data to a sequence of
 +             character events.  */
 +          for (i = 0; i < nbytes; i += len)
 +            {
 +              if (nchars == nbytes)
 +                c = copy_bufptr[i], len = 1;
 +              else
 +                c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
 +                                            nbytes - i, len);
 +              inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
 +                              ? ASCII_KEYSTROKE_EVENT
 +                              : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
 +              inev.ie.code = c;
 +              kbd_buffer_store_event_hold (&inev.ie, hold_quit);
              }
  
            /* Previous code updated count by nchars rather than nbytes,
@@@ -8235,16 -8017,11 +8235,16 @@@ x_new_font (f, fontname
       register char *fontname;
  {
    struct font_info *fontp
 -    = FS_LOAD_FONT (f, 0, fontname, -1);
 +    = FS_LOAD_FONT (f, fontname);
  
    if (!fontp)
      return Qnil;
  
 +  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
 +    /* This font is already set in frame F.  There's nothing more to
 +       do.  */
 +    return build_string (fontp->full_name);
 +
    FRAME_FONT (f) = (XFontStruct *) (fontp->font);
    FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
    FRAME_FONTSET (f) = -1;
    return build_string (fontp->full_name);
  }
  
 -/* Give frame F the fontset named FONTSETNAME as its default font, and
 -   return the full name of that fontset.  FONTSETNAME may be a wildcard
 -   pattern; in that case, we choose some fontset that fits the pattern.
 -   The return value shows which fontset we chose.  */
 +/* Give frame F the fontset named FONTSETNAME as its default fontset,
 +   and return the full name of that fontset.  FONTSETNAME may be a
 +   wildcard pattern; in that case, we choose some fontset that fits
 +   the pattern.  FONTSETNAME may be a font name for ASCII characters;
 +   in that case, we create a fontset from that font name.
 +
 +   The return value shows which fontset we chose.
 +   If FONTSETNAME specifies the default fontset, return Qt.
 +   If an ASCII font in the specified fontset can't be loaded, return
 +   Qnil.  */
  
  Lisp_Object
  x_new_fontset (f, fontsetname)
       struct frame *f;
 -     char *fontsetname;
 +     Lisp_Object fontsetname;
  {
 -  int fontset = fs_query_fontset (build_string (fontsetname), 0);
 +  int fontset = fs_query_fontset (fontsetname, 0);
    Lisp_Object result;
  
 -  if (fontset < 0)
 -    return Qnil;
 -
 -  if (FRAME_FONTSET (f) == fontset)
 +  if (fontset > 0 && f->output_data.x->fontset == fontset)
      /* This fontset is already set in frame F.  There's nothing more
         to do.  */
      return fontset_name (fontset);
 +  else if (fontset == 0)
 +    /* The default fontset can't be the default font.   */
 +    return Qt;
  
 -  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  if (fontset > 0)
 +    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 +  else
 +    result = x_new_font (f, SDATA (fontsetname));
  
    if (!STRINGP (result))
      /* Can't load ASCII font.  */
      return Qnil;
  
 +  if (fontset < 0)
 +    fontset = new_fontset_from_font_name (result);
 +
    /* Since x_new_font doesn't update any fontset information, do it now.  */
    FRAME_FONTSET (f) = fontset;
  
      xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
  #endif
  
 -  return build_string (fontsetname);
 +  return fontset_name (fontset);
  }
  
 +#ifdef USE_FONT_BACKEND
 +Lisp_Object
 +x_new_fontset2 (f, fontset, font_object)
 +     struct frame *f;
 +     int fontset;
 +     Lisp_Object font_object;
 +{
 +  struct font *font = XSAVE_VALUE (font_object)->pointer;
 +
 +  if (FRAME_FONT_OBJECT (f) == font)
 +    /* This font is already set in frame F.  There's nothing more to
 +       do.  */
 +    return fontset_name (fontset);
 +
 +  BLOCK_INPUT;
 +
 +  FRAME_FONT_OBJECT (f) = font;
 +  FRAME_FONT (f) = font->font.font;
 +  FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
 +  FRAME_FONTSET (f) = fontset;
 +
 +  FRAME_COLUMN_WIDTH (f) = font->font.average_width;
 +  FRAME_SPACE_WIDTH (f) = font->font.space_width;
 +  FRAME_LINE_HEIGHT (f) = font->font.height;
 +
 +  compute_fringe_widths (f, 1);
 +
 +  /* Compute the scroll bar width in character columns.  */
 +  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
 +    {
 +      int wid = FRAME_COLUMN_WIDTH (f);
 +      FRAME_CONFIG_SCROLL_BAR_COLS (f)
 +      = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
 +    }
 +  else
 +    {
 +      int wid = FRAME_COLUMN_WIDTH (f);
 +      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
 +    }
 +
 +  /* Now make the frame display the given font.  */
 +  if (FRAME_X_WINDOW (f) != 0)
 +    {
 +      /* Don't change the size of a tip frame; there's no point in
 +       doing it because it's done in Fx_show_tip, and it leads to
 +       problems because the tip frame has no widget.  */
 +      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
 +      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
 +    }
 +
 +#ifdef HAVE_X_I18N
 +  if (FRAME_XIC (f)
 +      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
 +    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 +#endif
 +
 +  UNBLOCK_INPUT;
 +
 +  return fontset_name (fontset);
 +}
 +#endif        /* USE_FONT_BACKEND */
 +
  \f
  /***********************************************************************
                           X Input Methods
@@@ -9044,7 -8747,8 +9044,8 @@@ x_sync_with_move (f, left, top, fuzzy
            /* The left fuzz-factor is 10 pixels.  The top fuzz-factor is 40
               pixels.  */
  
-           if (abs (current_left - left) <= 10 && abs (current_top - top) <= 40)
+           if (eabs (current_left - left) <= 10
+             && eabs (current_top - top) <= 40)
              return;
    }
        else if (current_left == left && current_top == top)
@@@ -9695,15 -9399,6 +9696,15 @@@ x_free_frame_resources (f
       commands to the X server.  */
    if (dpyinfo->display)
      {
 +#ifdef USE_FONT_BACKEND
 +      /* We must free faces before destroying windows because some
 +       font-driver (e.g. xft) access a window while finishing a
 +       face.  */
 +      if (enable_font_backend
 +        && FRAME_FACE_CACHE (f))
 +      free_frame_faces (f);
 +#endif        /* USE_FONT_BACKEND */
 +
        if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
  
@@@ -10098,7 -9793,7 +10099,7 @@@ x_get_font_info (f, font_idx
     If SIZE is > 0, it is the size (maximum bounds width) of fonts
     to be listed.
  
 -   SIZE < 0 means include scalable fonts.
 +   SIZE < 0 means include auto scaled fonts.
  
     Frame F null means we have not yet created any frame on X, and
     consult the first display in x_display_list.  MAXNAMES sets a limit
@@@ -10571,7 -10266,6 +10572,7 @@@ x_load_font (f, fontname, size
      bzero (fontp, sizeof (*fontp));
      fontp->font = font;
      fontp->font_idx = i;
 +    fontp->charset = -1;      /* fs_load_font sets it.  */
      fontp->name = (char *) xmalloc (strlen (fontname) + 1);
      bcopy (fontname, fontp->name, strlen (fontname) + 1);
  
         the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
         (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
         2:0xA020..0xFF7F).  For the moment, we don't know which charset
 -       uses this font.  So, we set information in fontp->encoding[1]
 +       uses this font.  So, we set information in fontp->encoding_type
         which is never used by any charset.  If mapping can't be
         decided, set FONT_ENCODING_NOT_DECIDED.  */
 -    fontp->encoding[1]
 +    fontp->encoding_type
        = (font->max_byte1 == 0
         /* 1-byte font */
         ? (font->min_char_or_byte2 < 0x80
@@@ -10786,160 -10480,6 +10787,160 @@@ x_find_ccl_program (fontp
  }
  
  
 +/* Return a char-table whose elements are t if the font FONT_INFO
 +   contains a glyph for the corresponding character, and nil if
 +   not.  */
 +
 +Lisp_Object
 +x_get_font_repertory (f, font_info)
 +     FRAME_PTR f;
 +     struct font_info *font_info;
 +{
 +  XFontStruct *font = (XFontStruct *) font_info->font;
 +  Lisp_Object table;
 +  int min_byte1, max_byte1, min_byte2, max_byte2;
 +  int c;
 +  struct charset *charset = CHARSET_FROM_ID (font_info->charset);
 +  int offset = CHARSET_OFFSET (charset);
 +
 +  table = Fmake_char_table (Qnil, Qnil);
 +
 +  min_byte1 = font->min_byte1;
 +  max_byte1 = font->max_byte1;
 +  min_byte2 = font->min_char_or_byte2;
 +  max_byte2 = font->max_char_or_byte2;
 +  if (min_byte1 == 0 && max_byte1 == 0)
 +    {
 +      if (! font->per_char || font->all_chars_exist == True)
 +      {
 +        if (offset >= 0)
 +          char_table_set_range (table, offset + min_byte2,
 +                                offset + max_byte2, Qt);
 +        else
 +          for (; min_byte2 <= max_byte2; min_byte2++)
 +            {
 +              c = DECODE_CHAR (charset, min_byte2);
 +              CHAR_TABLE_SET (table, c, Qt);
 +            }
 +      }
 +      else
 +      {
 +        XCharStruct *pcm = font->per_char;
 +        int from = -1;
 +        int i;
 +
 +        for (i = min_byte2; i <= max_byte2; i++, pcm++)
 +          {
 +            if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
 +              {
 +                if (from >= 0)
 +                  {
 +                    if (offset >= 0)
 +                      char_table_set_range (table, offset + from,
 +                                            offset + i - 1, Qt);
 +                    else
 +                      for (; from < i; from++)
 +                        {
 +                          c = DECODE_CHAR (charset, from);
 +                          CHAR_TABLE_SET (table, c, Qt);
 +                        }
 +                    from = -1;
 +                  }
 +              }
 +            else if (from < 0)
 +              from = i;
 +          }
 +        if (from >= 0)
 +          {
 +            if (offset >= 0)
 +              char_table_set_range (table, offset + from, offset + i - 1,
 +                                    Qt);
 +            else
 +              for (; from < i; from++)
 +                {
 +                  c = DECODE_CHAR (charset, from);
 +                  CHAR_TABLE_SET (table, c, Qt);
 +                }
 +          }
 +      }
 +    }
 +  else
 +    {
 +      if (! font->per_char || font->all_chars_exist == True)
 +      {
 +        int i, j;
 +
 +        if (offset >= 0)
 +          for (i = min_byte1; i <= max_byte1; i++)
 +            char_table_set_range
 +              (table, offset + ((i << 8) | min_byte2),
 +               offset + ((i << 8) | max_byte2), Qt);
 +        else
 +          for (i = min_byte1; i <= max_byte1; i++)        
 +            for (j = min_byte2; j <= max_byte2; j++)
 +              {
 +                unsigned code = (i << 8) | j;
 +                c = DECODE_CHAR (charset, code);
 +                CHAR_TABLE_SET (table, c, Qt);
 +              }
 +      }
 +      else
 +      {
 +        XCharStruct *pcm = font->per_char;
 +        int i;
 +
 +        for (i = min_byte1; i <= max_byte1; i++)
 +          {
 +            int from = -1;
 +            int j;
 +
 +            for (j = min_byte2; j <= max_byte2; j++, pcm++)
 +              {
 +                if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
 +                  {
 +                    if (from >= 0)
 +                      {
 +                        if (offset >= 0)
 +                          char_table_set_range
 +                            (table, offset + ((i << 8) | from),
 +                             offset + ((i << 8) | (j - 1)), Qt);
 +                        else
 +                          {
 +                            for (; from < j; from++)
 +                              {
 +                                unsigned code = (i << 8) | from;
 +                                c = ENCODE_CHAR (charset, code);
 +                                CHAR_TABLE_SET (table, c, Qt);
 +                              }
 +                          }
 +                        from = -1;
 +                      }
 +                  }
 +                else if (from < 0)
 +                  from = j;
 +              }
 +            if (from >= 0)
 +              {
 +                if (offset >= 0)
 +                  char_table_set_range
 +                    (table, offset + ((i << 8) | from),
 +                     offset + ((i << 8) | (j - 1)), Qt);
 +                else
 +                  {
 +                    for (; from < j; from++)
 +                      {
 +                        unsigned code = (i << 8) | from;
 +                        c = DECODE_CHAR (charset, code);
 +                        CHAR_TABLE_SET (table, c, Qt);
 +                      }
 +                  }
 +              }
 +          }
 +      }
 +    }
 +
 +  return table;
 +}
  \f
  /***********************************************************************
                            Initialization
@@@ -11928,6 -11468,8 +11929,6 @@@ syms_of_xterm (
    staticpro (&Qvendor_specific_keysyms);
    Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
  
 -  staticpro (&Qutf_8);
 -  Qutf_8 = intern ("utf-8");
    staticpro (&Qlatin_1);
    Qlatin_1 = intern ("latin-1");