changeset 25012:583c6bc7fe82

Complete rewrite.
author Gerd Moellmann <gerd@gnu.org>
date Wed, 21 Jul 1999 21:43:52 +0000
parents 12235d1f1871
children f75cb74a9e96
files lisp/faces.el src/dispextern.h src/dispnew.c src/xdisp.c
diffstat 4 files changed, 18218 insertions(+), 6764 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/faces.el	Wed Jul 21 21:43:52 1999 +0000
+++ b/lisp/faces.el	Wed Jul 21 21:43:52 1999 +0000
@@ -1,6 +1,7 @@
-;;; faces.el --- Lisp interface to the c "face" structure
+;;; faces.el --- Lisp faces
 
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998
+;;   Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -21,740 +22,1435 @@
 
 ;;; Commentary:
 
-;; Mostly derived from Lucid.
-
 ;;; Code:
 
 (eval-when-compile
- ;; These used to be defsubsts, now they're subrs.  Avoid losing if we're
- ;; being compiled with an old Emacs that still has defsubrs in it.
- (put 'face-name 'byte-optimizer nil)
- (put 'face-id 'byte-optimizer nil)
- (put 'face-font 'byte-optimizer nil)
- (put 'face-font-explicit 'byte-optimizer nil)
- (put 'face-foreground 'byte-optimizer nil)
- (put 'face-background 'byte-optimizer nil)
- (put 'face-stipple 'byte-optimizer nil)
- (put 'face-underline-p 'byte-optimizer nil)
- (put 'set-face-font 'byte-optimizer nil)
- (put 'set-face-font-auto 'byte-optimizer nil)
- (put 'set-face-foreground 'byte-optimizer nil)
- (put 'set-face-background 'byte-optimizer nil)
- (put 'set-face-stipple 'byte-optimizer nil)
- (put 'set-face-underline-p 'byte-optimizer nil))
-
-;;;; Functions for manipulating face vectors.
-
-;;; A face vector is a vector of the form:
-;;;    [face NAME ID FONT FOREGROUND BACKGROUND STIPPLE
-;;;          UNDERLINE-P INVERSE-VIDEO-P FONT-EXPLICIT-P BOLD-P ITALIC-P]
-
-;;; Type checkers.
-(defsubst internal-facep (x)
-  (and (vectorp x) (= (length x) 12) (eq (aref x 0) 'face)))
-
-(defun facep (x)
-  "Return t if X is a face name or an internal face vector."
-  (and (or (internal-facep x)
-	   (and (symbolp x) (assq x global-face-data)))
-       t))
-      
-(defmacro internal-check-face (face)
-  (` (or (internal-facep (, face))
-	 (signal 'wrong-type-argument (list 'internal-facep (, face))))))
-
-;;; Accessors.
-(defun face-name (face)
-  "Return the name of face FACE."
-  (aref (internal-get-face face) 1))
+  (require 'custom)
+  (require 'cl))
 
-(defun face-id (face)
-  "Return the internal ID number of face FACE."
-  (aref (internal-get-face face) 2))
-
-(defun face-font (face &optional frame)
-  "Return the font name of face FACE, or nil if it is unspecified.
-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."
-  (aref (internal-get-face face frame) 3))
-
-(defun face-foreground (face &optional frame)
-  "Return the foreground color name of face FACE, or nil if unspecified.
-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).
-If FRAME is omitted or nil, use the selected frame."
-  (aref (internal-get-face face frame) 4))
-
-(defun face-background (face &optional frame)
-  "Return the background color name of face FACE, or nil if unspecified.
-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).
-If FRAME is omitted or nil, use the selected frame."
-  (aref (internal-get-face face frame) 5))
-
-(defun face-stipple (face &optional frame)
- "Return the stipple pixmap name of face FACE, or nil if unspecified.
-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).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 6))
-
-(defalias 'face-background-pixmap 'face-stipple)
-
-(defun face-underline-p (face &optional frame)
- "Return t if face FACE is underlined.
-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).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 7))
+(require 'cus-face)
 
-(defun face-inverse-video-p (face &optional frame)
- "Return t if face FACE is in inverse video.
-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).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 8))
-
-(defun face-font-explicit (face &optional frame)
-  "Return non-nil if this face's font was explicitly specified."
-  (aref (internal-get-face face frame) 9))
-
-(defun face-bold-p (face &optional frame)
-  "Return non-nil if the font of FACE is bold.
-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).
-If FRAME is omitted or nil, use the selected frame."
-  (aref (internal-get-face face frame) 10))
-
-(defun face-italic-p (face &optional frame)
-  "Return non-nil if the font of FACE is italic.
-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).
-If FRAME is omitted or nil, use the selected frame."
-  (aref (internal-get-face face frame) 11))
-
-(defalias 'face-doc-string 'face-documentation)
-(defun face-documentation (face)
-  "Get the documentation string for FACE."
-  (get face 'face-documentation))
 
-;;; Mutators.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Font selection.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun set-face-font (face font &optional frame)
-  "Change the font of face FACE to FONT (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "font"))
-  (if (stringp font)
-      (setq font (or (resolve-fontset-name font)
-		     (x-resolve-font-name font 'default frame))))
-  (internal-set-face-1 face 'font font 3 frame)
-  ;; Record that this face's font was set explicitly, not automatically,
-  ;; unless we are setting it to nil.
-  (internal-set-face-1 face nil (not (null font)) 9 frame))
-
-(defun set-face-font-auto (face font &optional frame)
-  "Change the font of face FACE to FONT (a string), for an automatic change.
-An automatic change means that we don't change the \"explicit\" flag;
-if the font was derived from the frame font before, it is now.
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "font"))
-  (if (stringp font)
-      (setq font (or (resolve-fontset-name font)
-		     (x-resolve-font-name font 'default frame))))
-  (internal-set-face-1 face 'font font 3 frame))
+(defgroup font-selection nil
+  "Influencing face font selection."
+  :group 'faces)
 
-(defun set-face-font-explicit (face flag &optional frame)
-  "Set the explicit-font flag of face FACE to FLAG.
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (internal-set-face-1 face nil flag 9 frame))
-
-(defun set-face-foreground (face color &optional frame)
-  "Change the foreground color of face FACE to COLOR (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "foreground" 'color))
-  (internal-set-face-1 face 'foreground color 4 frame))
-
-(defvar face-default-stipple "gray3" 
-  "Default stipple pattern used on monochrome displays.
-This stipple pattern is used on monochrome displays
-instead of shades of gray for a face background color.
-See `set-face-stipple' for possible values for this variable.")
-
-(defun face-color-gray-p (color &optional frame)
-  "Return t if COLOR is a shade of gray (or white or black).
-FRAME specifies the frame and thus the display for interpreting COLOR."
-  (let* ((values (x-color-values color frame))
-	 (r (nth 0 values))
-	 (g (nth 1 values))
-	 (b (nth 2 values)))
-    (and values
-	 (< (abs (- r g)) (/ (max 1 (abs r) (abs g)) 20))
-	 (< (abs (- g b)) (/ (max 1 (abs g) (abs b)) 20))
-	 (< (abs (- b r)) (/ (max 1 (abs b) (abs r)) 20)))))
 
-(defun set-face-background (face color &optional frame)
-  "Change the background color of face FACE to COLOR (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "background" 'color))
-  ;; For a specific frame, use gray stipple instead of gray color
-  ;; if the display does not support a gray color.
-  (if (and frame (not (eq frame t)) color
-	   ;; Check for support for foreground, not for background!
-	   ;; face-color-supported-p is smart enough to know
-	   ;; that grays are "supported" as background
-	   ;; because we are supposed to use stipple for them!
-	   (not (face-color-supported-p frame color nil)))
-      (set-face-stipple face face-default-stipple frame)
-    (if (null frame)
-	(let ((frames (frame-list)))
-	  (while frames
-	    (set-face-background (face-name face) color (car frames))
-	    (setq frames (cdr frames)))
-	  (set-face-background face color t)
-	  color)
-      (internal-set-face-1 face 'background color 5 frame))))
-
-(defun set-face-stipple (face pixmap &optional frame)
-  "Change the stipple pixmap of face FACE to PIXMAP.
-PIXMAP should be a string, the name of a file of pixmap data.
-The directories listed in the `x-bitmap-file-path' variable are searched.
-
-Alternatively, PIXMAP may be a list of the form (WIDTH HEIGHT DATA)
-where WIDTH and HEIGHT are the size in pixels,
-and DATA is a string, containing the raw bits of the bitmap.  
-
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive-stipple "stipple"))
-  (internal-set-face-1 face 'background-pixmap pixmap 6 frame))
-
-(defalias 'set-face-background-pixmap 'set-face-stipple)
-
-(defun set-face-underline-p (face underline-p &optional frame)
-  "Specify whether face FACE is underlined.  (Yes if UNDERLINE-P is non-nil.)
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "underline-p" "underlined"))
-  (internal-set-face-1 face 'underline underline-p 7 frame))
+(defcustom face-font-selection-order
+  '(:width :height :weight :slant)
+  "*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
+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."
+  :tag "Font selection order."
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+	   (set-default symbol value)
+	   (internal-set-font-selection-order value)))
 
-(defun set-face-inverse-video-p (face inverse-video-p &optional frame)
-  "Specify whether face FACE is in inverse video.
-\(Yes if INVERSE-VIDEO-P is non-nil.)
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (interactive (internal-face-interactive "inverse-video-p" "inverse-video"))
-  (internal-set-face-1 face 'inverse-video inverse-video-p 8 frame))
-
-(defun set-face-bold-p (face bold-p &optional frame)
-  "Specify whether face FACE is bold.  (Yes if BOLD-P is non-nil.)
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (cond ((eq bold-p nil) (make-face-unbold face frame t))
-	(t (make-face-bold face frame t))))
-
-(defun set-face-italic-p (face italic-p &optional frame)
-  "Specify whether face FACE is italic.  (Yes if ITALIC-P is non-nil.)
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
-  (cond ((eq italic-p nil) (make-face-unitalic face frame t))
-	(t (make-face-italic face frame t))))
-
-(defalias 'set-face-doc-string 'set-face-documentation)
-(defun set-face-documentation (face string)
-  "Set the documentation string for FACE to STRING."
-  (put face 'face-documentation string))
-
-(defun modify-face-read-string (face default name alist)
-  (let ((value
-	 (completing-read
-	  (if default
-	      (format "Set face %s %s (default %s): "
-		      face name (downcase default))
-	    (format "Set face %s %s: " face name))
-	  alist)))
-    (cond ((equal value "none")
-	   '(nil))
-	  ((equal value "")
-	   default)
-	  (t value))))
-
-(defun modify-face (face foreground background stipple
-		    bold-p italic-p underline-p &optional inverse-p frame)
-  "Change the display attributes for face FACE.
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame.
-
-FOREGROUND and BACKGROUND should be a colour name string (or list of strings to
-try) or nil.  STIPPLE should be a stipple pattern name string or nil.
-If nil, means do not change the display attribute corresponding to that arg.
-If (nil), that means clear out the attribute.
 
-BOLD-P, ITALIC-P, UNDERLINE-P, and INVERSE-P specify whether
-the face should be set bold, italic, underlined or in inverse-video,
-respectively.  If one of these arguments is neither nil or t, it means do not
-change the display attribute corresponding to that argument.
+(defcustom face-font-family-alternatives
+  '(("courier" "fixed")
+    ("helv" "helvetica" "fixed"))
+  "*Alist of alternative font family names.
+Each element has the the form (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...).
+If fonts of family FAMILY can't be loaded, try ALTERNATIVE1, then
+ALTERNATIVE2 etc."
+  :tag "Alternative font families to try."
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+	   (set-default symbol value)
+	   (internal-set-alternative-font-family-alist value)))
 
-If called interactively, prompts for a face name and face attributes."
-  (interactive
-   (let* ((completion-ignore-case t)
-	  (face		(symbol-name (read-face-name "Modify face: ")))
-	  (colors	(mapcar 'list x-colors))
-	  (stipples	(mapcar 'list (apply 'nconc
-					    (mapcar 'directory-files
-						    x-bitmap-file-path))))
-	  (foreground	(modify-face-read-string
-			 face (face-foreground (intern face))
-			 "foreground" colors))
-	  (background	(modify-face-read-string
-			 face (face-background (intern face))
-			 "background" colors))
-	  ;; If the stipple value is a list (WIDTH HEIGHT DATA),
-	  ;; represent that as a string by printing it out.
-	  (old-stipple-string
-	   (if (stringp (face-stipple (intern face)))
-	       (face-stipple (intern face))
-	     (if (face-stipple (intern face))
-		 (prin1-to-string (face-stipple (intern face))))))
-	  (new-stipple-string
-	   (modify-face-read-string
-	    face old-stipple-string
-	    "stipple" stipples))
-	  ;; Convert the stipple value text we read
-	  ;; back to a list if it looks like one.
-	  ;; This makes the assumption that a pixmap file name
-	  ;; won't start with an open-paren.
-	  (stipple
-	   (and new-stipple-string
-		(if (string-match "^(" new-stipple-string)
-		    (read new-stipple-string)
-		  new-stipple-string)))
-	  (bold-p	(y-or-n-p (concat "Should face " face " be bold ")))
-	  (italic-p	(y-or-n-p (concat "Should face " face " be italic ")))
-	  (underline-p	(y-or-n-p (concat "Should face " face " be underlined ")))
-	  (inverse-p	(y-or-n-p (concat "Should face " face " be inverse-video ")))
-	  (all-frames-p	(y-or-n-p (concat "Modify face " face " in all frames "))))
-     (message "Face %s: %s" face
-      (mapconcat 'identity
-       (delq nil
-	(list (if (equal foreground '(nil))
-		  " no foreground"
-		(and foreground (concat (downcase foreground) " foreground")))
-	      (if (equal background '(nil))
-		  " no background"
-		(and background (concat (downcase background) " background")))
-	      (if (equal stipple '(nil))
-		  " no stipple"
-		(and stipple (concat (downcase new-stipple-string) " stipple")))
-	      (and bold-p "bold") (and italic-p "italic")
-	      (and inverse-p "inverse")
-	      (and underline-p "underline"))) ", "))
-     (list (intern face) foreground background stipple
-	   bold-p italic-p underline-p inverse-p
-	   (if all-frames-p nil (selected-frame)))))
-  ;; Clear this before we install the new foreground and background;
-  ;; otherwise, clearing it after would swap them!
-  (when (and (or foreground background) (face-inverse-video-p face))
-    (set-face-inverse-video-p face nil frame)
-    ;; Arrange to restore it after, if we are not setting it now.
-    (or (memq inverse-p '(t nil))
-	(setq inverse-p t)))
-  (condition-case nil
-      (face-try-color-list 'set-face-foreground face foreground frame)
-    (error nil))
-  (condition-case nil
-      (face-try-color-list 'set-face-background face background frame)
-    (error nil))
-  (condition-case nil
-      (set-face-stipple face stipple frame)
-    (error nil))
-  ;; Now that we have the new colors, 
-  (if (memq inverse-p '(nil t))
-      (set-face-inverse-video-p face inverse-p frame))
-  (cond ((eq bold-p nil)
-	 (if (face-font face frame)
-	     (make-face-unbold face frame t)))
-	((eq bold-p t)
-	 (make-face-bold face frame t)))
-  (cond ((eq italic-p nil)
-	 (if (face-font face frame)
-	     (make-face-unitalic face frame t)))
-	((eq italic-p t) (make-face-italic face frame t)))
-  (if (memq underline-p '(nil t))
-      (set-face-underline-p face underline-p frame))
-  (and (interactive-p) (redraw-display)))
+
 
-;;;; Associating face names (symbols) with their face vectors.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Creation, copying.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defvar global-face-data nil
-  "Internal data for face support functions.  Not for external use.
-This is an alist associating face names with the default values for
-their parameters.  Newly created frames get their data from here.")
 
 (defun face-list ()
-  "Returns a list of all defined face names."
-  (mapcar 'car global-face-data))
+  "Return a list of all defined face names."
+  (mapcar #'car face-new-frame-defaults))
+
+
+;;; ### If not frame-local initialize by what X resources?
+
+(defun make-face (face &optional no-init-from-resources)
+  "Define a new face with name FACE, a symbol.
+NO-INIT-FROM-RESOURCES non-nil means don't initialize frame-local
+variants of FACE from X resources.  (X resources recognized are found
+in the global variable `face-x-resources'.)  If FACE is already known
+as a face, leave it unmodified.  Value is FACE."
+  (interactive "SMake face: ")
+  (unless (facep face)
+    ;; Make frame-local faces (this also makes the global one).
+    (dolist (frame (frame-list))
+      (internal-make-lisp-face face frame))
+    ;; Add the face to the face menu.
+    (when (fboundp 'facemenu-add-new-face)
+      (facemenu-add-new-face face))
+    ;; Define frame-local faces for all frames from X resources.
+    (unless no-init-from-resources
+      (make-face-x-resource-internal face)))
+  face)
+
+
+(defun make-empty-face (face)
+  "Define a new, empty face with name FACE.
+If the face already exists, it is left unmodified.  Value is FACE."
+  (interactive "SMake empty face: ")
+  (make-face face 'no-init-from-resources))
+
+
+(defun copy-face (old-face new-face &optional frame new-frame)
+  "Define a face just like OLD-FACE, with name NEW-FACE.
+
+If NEW-FACE already exists as a face, it is modified to be like
+OLD-FACE.  If it doesn't already exist, it is created.
+
+If the optional argument FRAME is given as a frame,  NEW-FACE is
+changed on FRAME only.
+If FRAME is t, the frame-independent default specification for OLD-FACE
+is copied to NEW-FACE.
+If FRAME is nil, copying is done for the frame-independent defaults
+and for each existing frame.
+
+If the optional fourth argument NEW-FRAME is given,
+copy the information from face OLD-FACE on frame FRAME
+to NEW-FACE on frame NEW-FRAME."
+  (let ((inhibit-quit t))
+    (if (null frame)
+	(progn
+	  (dolist (frame (frame-list))
+	    (copy-face old-face new-face frame))
+	  (copy-face old-face new-face t))
+      (internal-copy-lisp-face old-face new-face frame new-frame))
+    new-face))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Obsolete functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The functions in this section are defined because Lisp packages use
+;; them, despite the prefix `internal-' suggesting that they are
+;; private to the face implementation.  
 
 (defun internal-find-face (name &optional frame)
-  "Retrieve the face named NAME.  Return nil if there is no such face.
+  "Retrieve the face named NAME.
+Return nil if there is no such face.
 If the optional argument FRAME is given, this gets the face NAME for
 that frame; otherwise, it uses the selected frame.
 If FRAME is the symbol t, then the global, non-frame face is returned.
-If NAME is already a face, it is simply returned."
-  (if (and (eq frame t) (not (symbolp name)))
-      (setq name (face-name name)))
-  (if (symbolp name)
-      (cdr (assq name
-		 (if (eq frame t)
-		     global-face-data
-		   (frame-face-alist (or frame (selected-frame))))))
-    (internal-check-face name)
-    name))
+If NAME is already a face, it is simply returned.
+
+This function is defined for compatibility with Emacs 20.2.  It
+should not be used anymore."
+  (facep name))
+
 
 (defun internal-get-face (name &optional frame)
   "Retrieve the face named NAME; error if there is none.
 If the optional argument FRAME is given, this gets the face NAME for
 that frame; otherwise, it uses the selected frame.
 If FRAME is the symbol t, then the global, non-frame face is returned.
-If NAME is already a face, it is simply returned."
+If NAME is already a face, it is simply returned.
+
+This function is defined for compatibility with Emacs 20.2.  It
+should not be used anymore."
   (or (internal-find-face name frame)
-      (internal-check-face name)))
+      (check-face name)))
 
 
-(defun internal-set-face-1 (face name value index frame)
-  (let ((inhibit-quit t))
-    (if (null frame)
-	(let ((frames (frame-list)))
-	  (while frames
-	    (internal-set-face-1 (face-name face) name value index (car frames))
-	    (setq frames (cdr frames)))
-	  (aset (internal-get-face (if (symbolp face) face (face-name face)) t)
-		index value)
-	  value)
-      (let ((internal-face (internal-get-face face frame)))
-	(or (eq frame t)
-	    (if (eq name 'inverse-video)
-		(or (eq value (aref internal-face index))
-		    (invert-face face frame))
-	      (and name (fboundp 'set-face-attribute-internal)
-		   (set-face-attribute-internal (face-id face)
-						name value frame))))
-	(aset internal-face index value)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Predicates, type checks.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun facep (face)
+  "Return non-nil if FACE is a face name."
+  (internal-lisp-face-p face))
+
+
+(defun check-face (face)
+  "Signal an error if FACE doesn't name a face.
+Value is FACE."
+  (unless (facep face)
+    (error "Not a face: %s" face))
+  face)
 
 
-(defun read-face-name (prompt)
-  (let (face)
-    (while (= (length face) 0)
-      (setq face (completing-read prompt
-				  (mapcar '(lambda (x) (list (symbol-name x)))
-					  (face-list))
-				  nil t)))
-    (intern face)))
-
-(defun internal-face-interactive (what &optional bool)
-  (let* ((fn (intern (concat "face-" what)))
-	 (prompt (concat "Set " what " of face"))
-	 (face (read-face-name (concat prompt ": ")))
-	 (default (if (fboundp fn)
-		      (or (funcall fn face (selected-frame))
-			  (funcall fn 'default (selected-frame)))))
-	 value)
-    (setq value
-	  (cond ((eq bool 'color)
-		 (completing-read (concat prompt " " (symbol-name face) " to: ")
-				  (mapcar (function (lambda (color)
-						      (cons color color)))
-					  x-colors)
-				  nil nil nil nil default))
-		(bool
-		 (y-or-n-p (concat "Should face " (symbol-name face)
-				   " be " bool "? ")))
-		(t
-		 (read-string (concat prompt " " (symbol-name face) " to: ")
-			      nil nil default))))
-    (list face (if (equal value "") nil value))))
-
-(defun internal-face-interactive-stipple (what)
-  (let* ((fn (intern (concat "face-" what)))
-	 (prompt (concat "Set " what " of face"))
-	 (face (read-face-name (concat prompt ": ")))
-	 (default (if (fboundp fn)
-		      (or (funcall fn face (selected-frame))
-			  (funcall fn 'default (selected-frame)))))
-	 ;; If the stipple value is a list (WIDTH HEIGHT DATA),
-	 ;; represent that as a string by printing it out.
-	 (old-stipple-string
-	  (if (stringp (face-stipple face))
-	      (face-stipple face)
-	    (if (null (face-stipple face))
-		nil
-	      (prin1-to-string (face-stipple face)))))
-	 (new-stipple-string
-	  (read-string
-	   (concat prompt " " (symbol-name face) " to: ")
-	   old-stipple-string))
-	 ;; Convert the stipple value text we read
-	 ;; back to a list if it looks like one.
-	 ;; This makes the assumption that a pixmap file name
-	 ;; won't start with an open-paren.
-	 (stipple
-	  (if (string-match "^(" new-stipple-string)
-	      (read new-stipple-string)
-	    new-stipple-string)))
-    (list face (if (equal stipple "") nil stipple))))
-
-(defun make-face (name &optional no-resources)
-  "Define a new FACE on all frames.  
-You can modify the font, color, etc of this face with the set-face- functions.
-If NO-RESOURCES is non-nil, then we ignore X resources
-and always make a face whose attributes are all nil.
-
-If the face already exists, it is unmodified."
-  (interactive "SMake face: ")
-  (or (internal-find-face name)
-      (let ((face (make-vector 12 nil)))
-	(aset face 0 'face)
-	(aset face 1 name)
-	(let* ((frames (frame-list))
-	       (inhibit-quit t)
-	       (id (internal-next-face-id)))
-	  (if (fboundp 'make-face-internal)
-	      (make-face-internal id))
-	  (aset face 2 id)
-	  (while frames
-	    (set-frame-face-alist (car frames)
-				  (cons (cons name (copy-sequence face))
-					(frame-face-alist (car frames))))
-	    (setq frames (cdr frames)))
-	  (setq global-face-data (cons (cons name face) global-face-data)))
-	;; When making a face after frames already exist
-	(or no-resources
-	    (if (memq window-system '(x w32))
-		(make-face-x-resource-internal face)))
-	;; Add to menu of faces.
-	(if (fboundp 'facemenu-add-new-face)
-	    (facemenu-add-new-face name))
-	face))
-  name)
-
-(defun make-empty-face (face)
-  "Define a new FACE on all frames, which initially reflects the defaults.
-You can modify the font, color, etc of this face with the set-face- functions.
-If the face already exists, it is unmodified."
-  (interactive "SMake empty face: ")
-  (make-face face t))
+;; The ID returned is not to be confused with the internally used IDs
+;; of realized faces.  The ID assigned to Lisp faces is used to
+;; support faces in display table entries.
 
-;; Fill in a face by default based on X resources, for all existing frames.
-;; This has to be done when a new face is made.
-(defun make-face-x-resource-internal (face &optional frame set-anyway)
-  (cond ((null frame)
-	 (let ((frames (frame-list)))
-	   (while frames
-	     (if (memq (framep (car frames)) '(x w32))
-		 (make-face-x-resource-internal (face-name face)
-						(car frames) set-anyway))
-	     (setq frames (cdr frames)))))
-	(t
-	 (setq face (internal-get-face (face-name face) frame))
-	 ;;
-	 ;; These are things like "attributeForeground" instead of simply
-	 ;; "foreground" because people tend to do things like "*foreground",
-	 ;; which would cause all faces to be fully qualified, making faces
-	 ;; inherit attributes in a non-useful way.  So we've made them slightly
-	 ;; less obvious to specify in order to make them work correctly in
-	 ;; more random environments.
-	 ;;
-	 ;; I think these should be called "face.faceForeground" instead of
-	 ;; "face.attributeForeground", but they're the way they are for
-	 ;; hysterical reasons.
-	 ;; 
-	 (let* ((name (symbol-name (face-name face)))
-		(fn  (or (x-get-resource (concat name ".attributeFont")
-					 "Face.AttributeFont")
-			 (and set-anyway (face-font face))))
-		(fg  (or (x-get-resource (concat name ".attributeForeground")
-					 "Face.AttributeForeground")
-			 (and set-anyway (face-foreground face))))
-		(bg  (or (x-get-resource (concat name ".attributeBackground")
-					 "Face.AttributeBackground")
-			 (and set-anyway (face-background face))))
-		(bgp (or (x-get-resource (concat name ".attributeStipple")
-					 "Face.AttributeStipple")
-			 (x-get-resource (concat name ".attributeBackgroundPixmap")
-					 "Face.AttributeBackgroundPixmap")
-			 (and set-anyway (face-stipple face))))
-		(ulp (let ((resource (x-get-resource
-				      (concat name ".attributeUnderline")
-				      "Face.AttributeUnderline")))
-		       (if resource
-			   (member (downcase resource) '("on" "true"))
-			 (and set-anyway (face-underline-p face)))))
-		)
-	   (if fn
-	       (condition-case ()
-		   (cond ((string= fn "italic")
-			  (make-face-italic face))
-			 ((string= fn "bold")
-			  (make-face-bold face))
-			 ((string= fn "bold-italic")
-			  (make-face-bold-italic face))
-			 (t
-			  (set-face-font face fn frame)))
-		 (error
-		  (if (member fn '("italic" "bold" "bold-italic"))
-		      (message "no %s version found for face `%s'" fn name)
-		    (message "font `%s' not found for face `%s'" fn name)))))
-	   (if fg
-	       (condition-case ()
-		   (set-face-foreground face fg frame)
-		 (error (message "color `%s' not allocated for face `%s'" fg name))))
-	   (if bg
-	       (condition-case ()
-		   (set-face-background face bg frame)
-		 (error (message "color `%s' not allocated for face `%s'" bg name))))
-	   (if bgp
-	       (condition-case ()
-		   (set-face-stipple face bgp frame)
-		 (error (message "pixmap `%s' not found for face `%s'" bgp name))))
-	   (if (or ulp set-anyway)
-	       (set-face-underline-p face ulp frame))
-	   )))
-  face)
+(defun face-id (face &optional frame)
+  "Return the interNal ID of face with name FACE.
+If optional argument FRAME is nil or omitted, use the selected frame."
+  (check-face face)
+  (get face 'face))
 
-(defun copy-face (old-face new-face &optional frame new-frame)
-  "Define a face just like OLD-FACE, with name NEW-FACE.
-If NEW-FACE already exists as a face, it is modified to be like OLD-FACE.
-If it doesn't already exist, it is created.
-
-If the optional argument FRAME is given as a frame,
-NEW-FACE is changed on FRAME only.
-If FRAME is t, the frame-independent default specification for OLD-FACE
-is copied to NEW-FACE.
-If FRAME is nil, copying is done for the frame-independent defaults
-and for each existing frame.
-If the optional fourth argument NEW-FRAME is given, 
-copy the information from face OLD-FACE on frame FRAME
-to NEW-FACE on frame NEW-FRAME."
-  (or new-frame (setq new-frame frame))
-  (let ((inhibit-quit t))
-    (if (null frame)
-	(let ((frames (frame-list)))
-	  (while frames
-	    (copy-face old-face new-face (car frames))
-	    (setq frames (cdr frames)))
-	  (copy-face old-face new-face t))
-      (setq old-face (internal-get-face old-face frame))
-      (setq new-face (or (internal-find-face new-face new-frame)
-			 (make-face new-face)))
-      (condition-case nil
-	  ;; A face that has a global symbolic font modifier such as `bold'
-	  ;; might legitimately get an error here.
-	  ;; Use the frame's default font in that case.
-	  (set-face-font new-face (face-font old-face frame) new-frame)
-	(error
-	 (set-face-font new-face nil new-frame)))
-      (set-face-font-explicit new-face (face-font-explicit old-face frame)
-			      new-frame)
-      (set-face-foreground new-face (face-foreground old-face frame) new-frame)
-      (set-face-background new-face (face-background old-face frame) new-frame)
-      (set-face-stipple new-face
-			(face-stipple old-face frame)
-			new-frame)
-      (set-face-underline-p new-face (face-underline-p old-face frame)
-			    new-frame))
-    new-face))
 
 (defun face-equal (face1 face2 &optional frame)
-  "True if the faces FACE1 and FACE2 display in the same way."
-  (setq face1 (internal-get-face face1 frame)
-	face2 (internal-get-face face2 frame))
-  (and (equal (face-foreground face1 frame) (face-foreground face2 frame))
-       (equal (face-background face1 frame) (face-background face2 frame))
-       (equal (face-font face1 frame) (face-font face2 frame))
-       (eq (face-underline-p face1 frame) (face-underline-p face2 frame))
-       (equal (face-stipple face1 frame)
-	      (face-stipple face2 frame))))
+  "Non-nil if faces FACE1 and FACE2 are equal.
+Faces are considered equal if all their attributes are equal.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-lisp-face-equal-p face1 face2 frame))
+
 
 (defun face-differs-from-default-p (face &optional frame)
-  "True if face FACE displays differently from the default face, on FRAME.
-A face is considered to be ``the same'' as the default face if it is 
-actually specified in the same way (equivalent fonts, etc) or if it is 
-fully unspecified, and thus inherits the attributes of any face it 
-is displayed on top of.
+  "Non-nil if FACE displays differently from the default face.
+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).
+If FRAME is omitted or nil, use the selected frame.
+A face is considered to be ``the same'' as the default face if it is
+actually specified in the same way (equal attributes) or if it is
+fully-unspecified, and thus inherits the attributes of any face it
+is displayed on top of."
+  (or (internal-lisp-face-empty-p face frame)
+      (not (internal-lisp-face-equal-p face 'default frame))))
 
-The optional argument FRAME specifies which frame to test;
-if FRAME is t, test the default for new frames.
-If FRAME is nil or omitted, test the selected frame."
-  (let ((default (internal-get-face 'default frame)))
-    (setq face (internal-get-face face frame))
-    (not (and (or (equal (face-foreground default frame)
-			 (face-foreground face frame))
-		  (null (face-foreground face frame)))
-	      (or (equal (face-background default frame)
-			 (face-background face frame))
-		  (null (face-background face frame)))
-	      (or (null (face-font face frame))
-		  (equal (face-font face frame)
-			 (or (face-font default frame)
-			     (downcase
-			      (cdr (assq 'font (frame-parameters frame)))))))
-	      (or (equal (face-stipple default frame)
-			 (face-stipple face frame))
-		  (null (face-stipple face frame)))
-	      (equal (face-underline-p default frame)
-		     (face-underline-p face frame))
-	      ))))
 
 (defun face-nontrivial-p (face &optional frame)
   "True if face FACE has some non-nil attribute.
-The optional argument FRAME specifies which frame to test;
-if FRAME is t, test the default for new frames.
-If FRAME is nil or omitted, test the selected frame."
-  (setq face (internal-get-face face frame))
-  (or (face-foreground face frame)
-      (face-background face frame)
-      (face-font face frame)
-      (face-stipple face frame)
-      (face-underline-p face frame)))
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (not (internal-lisp-face-empty-p face frame)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Setting face attributes from X resources.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defcustom face-x-resources
+  '((:family (".attributeFamily" . "Face.AttributeFamily"))
+    (:width (".attributeWidth" . "Face.AttributeWidth"))
+    (:height (".attributeHeight" . "Face.AttributeHeight"))
+    (:weight (".attributeWeight" . "Face.AttributeWeight"))
+    (:slant (".attributeSlant" . "Face.AttributeSlant"))
+    (:foreground (".attributeForeground" . "Face.AttributeForeground"))
+    (:background (".attributeBackground" . "Face.AttributeBackground"))
+    (:overline (".attributeOverline" . "Face.AttributeOverline"))
+    (:strike-through (".attributeStrikeThrough" . "Face.AttributeStrikeThrough"))
+    (:box (".attributeBox" . "Face.AttributeBox"))
+    (:underline (".attributeUnderline" . "Face.AttributeUnderline"))
+    (:inverse-video (".attributeInverse" . "Face.AttributeInverse"))
+    (:stipple
+     (".attributeStipple" . "Face.AttributeStipple")
+     (".attributeBackgroundPixmap" . "Face.AttributeBackgroundPixmap"))
+    (:font (".attributeFont" . "Face.AttributeFont"))
+    (:bold (".attributeBold" . "Face.AttributeBold"))
+    (:italic (".attributeItalic" . "Face.AttributeItalic"))
+    (:font (".attributeFont" . "Face.AttributeFont")))
+  "*List of X resources and classes for face attributes.
+Each element has the form (ATTRIBUTE ENTRY1 ENTRY2...) where ATTRIBUTE is
+the name of a face attribute, and each ENTRY is a cons of the form
+(RESOURCE . CLASS) with RESOURCE being the resource and CLASS being the
+X resource class for the attribute."
+  :type 'sexp
+  :group 'faces)
+
+
+(defun set-face-attribute-from-resource (face attribute resource class frame)
+  "Set FACE's ATTRIBUTE from X resource RESOURCE, class CLASS on FRAME.
+Value is the attribute value specified by the resource, or nil
+if not present.  This function displays a message if the resource
+specifies an invalid attribute."
+  (let* ((face-name (face-name face))
+	 (value (internal-face-x-get-resource (concat face-name resource)
+					      class frame)))
+    (when value
+      (condition-case ()
+	  (internal-set-lisp-face-attribute-from-resource
+	   face attribute (downcase value) frame)
+	(error
+	 (message "Face %s, frame %s: invalid attribute %s %s from X resource"
+		  face-name frame attribute value))))
+    value))
+
+
+(defun set-face-attributes-from-resources (face frame)
+  "Set attributes of FACE from X resources for FRAME."
+  (when (memq (framep frame) '(x w32))
+    (dolist (definition face-x-resources)
+      (let ((attribute (car definition)))
+	(dolist (entry (cdr definition))
+	  (set-face-attribute-from-resource face attribute (car entry)
+					    (cdr entry) frame))))))
+    
+  
+(defun make-face-x-resource-internal (face &optional frame)
+  "Fill frame-local FACE on FRAME from X resources.
+FRAME nil or not specified means do it for all frames."
+  (if (null frame)
+      (dolist (frame (frame-list))
+	(set-face-attributes-from-resources face frame))
+    (set-face-attributes-from-resources face frame)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Retrieving face attributes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun face-name (face)
+  "Return the name of face FACE."
+  (symbol-name (check-face face)))
+
+
+(defun face-attribute (face attribute &optional frame)
+  "Return the value of FACE's ATTRIBUTE on FRAME.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-get-lisp-face-attribute face attribute frame))
+
+
+(defun face-foreground (face &optional frame)
+  "Return the foreground color name of FACE, or nil if unspecified.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-get-lisp-face-attribute face :foreground frame))
+
+
+(defun face-background (face &optional frame)
+  "Return the background color name of FACE, or nil if unspecified.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-get-lisp-face-attribute face :background frame))
+
+
+(defun face-stipple (face &optional frame)
+ "Return the stipple pixmap name of FACE, or nil if unspecified.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-get-lisp-face-attribute face :stipple frame))
+
+
+(defalias 'face-background-pixmap 'face-stipple)
+
+
+(defun face-underline-p (face &optional frame)
+ "Return non-nil if FACE is underlined.
+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).
+If FRAME is omitted or nil, use the selected frame."
+ (eq (face-attribute face :underline frame) t))
+
+
+(defun face-inverse-video-p (face &optional frame)
+ "Return non-nil if FACE is in inverse video on FRAME.
+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).
+If FRAME is omitted or nil, use the selected frame."
+ (eq (face-attribute face :inverse-video frame) t))
+
+
+(defun face-bold-p (face &optional frame)
+  "Return non-nil if the font of FACE is bold on FRAME.
+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).
+If FRAME is omitted or nil, use the selected frame.
+Use `face-attribute' for finer control."
+  (let ((bold (face-attribute face :weight frame)))
+    (not (memq bold '(normal unspecified)))))
+
+
+(defun face-italic-p (face &optional frame)
+  "Return non-nil if the font of FACE is italic on FRAME.
+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).
+If FRAME is omitted or nil, use the selected frame.
+Use `face-attribute' for finer control."
+  (let ((italic (face-attribute face :slant frame)))
+    (not (memq italic '(normal unspecified)))))
+    
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Face documentation.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun face-documentation (face)
+  "Get the documentation string for FACE."
+  (get face 'face-documentation))
+
+
+(defun set-face-documentation (face string)
+  "Set the documentation string for FACE to STRING."
+  (put face 'face-documentation string))
+
+
+(defalias 'face-doc-string 'face-documentation)
+(defalias 'set-face-doc-string 'set-face-documentation)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Setting face attributes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun set-face-attribute (face frame &rest args)
+  "Set attributes of FACE on FRAME from ARGS.
+
+FRAME nil means change attributes on all frames.  FRAME t means change
+the default for new frames (this is done automatically each time an
+attribute is changed on all frames).
+
+ARGS must come in pairs ATTRIBUTE VALUE.  ATTRIBUTE must be a valid
+face attribute name.  All attributes can be set to `unspecified';
+this fact is not further mentioned below.
+
+The following attributes are recognized:
+
+`:family'
+
+VALUE must be a string specifying the font family, e.g. ``courier'',
+or a fontset alias name.  If a font family is specified, wild-cards `*'
+and `?' are allowed.
+
+`:width'
+
+VALUE specifies the relative proportionate width of the font to use.
+It must be one of the symbols `ultra-condensed', `extra-condensed',
+`condensed', `semi-condensed', `normal', `semi-expanded', `expanded',
+`extra-expanded', or `ultra-expanded'.
+
+`:height'
+
+VALUE must be an integer specifying the height of the font to use in
+1/10 pt.
+
+`:weight'
+
+VALUE specifies the weight of the font to use.  It must be one of the
+symbols `ultra-bold', `extra-bold', `bold', `semi-bold', `normal',
+`semi-light', `light', `extra-light', `ultra-light'.
+
+`:slant'
+
+VALUE specifies the slant of the font to use.  It must be one of the
+symbols `italic', `oblique', `normal', `reverse-italic', or
+`reverse-oblique'.
+
+`:foreground', `:background'
+
+VALUE must be a color name, a string.
+
+`:underline'
+
+VALUE specifies whether characters in FACE should be underlined.  If
+VALUE is t, underline with foreground color of the face.  If VALUE is
+a string, underline with that color.  If VALUE is nil, explicitly
+don't underline.
+
+`:overline'
+
+VALUE specifies whether characters in FACE should be overlined.  If
+VALUE is t, overline with foreground color of the face.  If VALUE is a
+string, overline with that color.  If VALUE is nil, explicitly don't
+overline.
+
+`:strike-through'
+
+VALUE specifies whether characters in FACE should be drawn with a line
+striking through them.  If VALUE is t, use the foreground color of the
+face.  If VALUE is a string, strike-through with that color.  If VALUE
+is nil, explicitly don't strike through.
+
+`:box'
+
+VALUE specifies whether characters in FACE should have a box drawn
+around them.  If VALUE is nil, explicitly don't draw boxes.  If
+VALUE is t, draw a box with lines of width 1 in the foreground color
+of the face.  If VALUE is a string, the string must be a color name,
+and the box is drawn in that color with a line width of 1.  Otherwise,
+VALUE must be a property list of the form `(:line-width WIDTH
+:color COLOR :style STYLE)'.  If a keyword/value pair is missing from
+the property list, a default value will be used for the value, as
+specified below.  WIDTH specifies the width of the lines to draw; it
+defaults to 1.  COLOR is the name of the color to draw in, default is
+the foreground color of the face for simple boxes, and the background
+color of the face for 3D boxes.  STYLE specifies whether a 3D box
+should be draw.  If STYLE is `released-button', draw a box looking
+like a released 3D button.  If STYLE is `pressed-button' draw a box
+that appears like a pressed button.  If STYLE is nil, the default if
+the property list doesn't contain a style specification, draw a 2D
+box.
+
+`:inverse-video'
+
+VALUE specifies whether characters in FACE should be displayed in
+inverse video. VALUE must be one of t or nil.
+
+`:stipple'
+
+If VALUE is a string, it must be the name of a file of pixmap data.
+The directories listed in the `x-bitmap-file-path' variable are
+searched.  Alternatively, VALUE may be a list of the form (WIDTH
+HEIGHT DATA) where WIDTH and HEIGHT are the size in pixels, and DATA
+is a string containing the raw bits of the bitmap.  VALUE nil means
+explicitly don't use a stipple pattern.
+
+For convenience, attributes `:family', `:width', `:height', `:weight',
+and `:slant' may also be set in one step from an X font name:
+
+`:font'
+
+Set font-related face attributes from VALUE.  VALUE must be a valid
+XLFD font name.  If it is a font name pattern, the first matching font
+will be used.
+
+For compatibility with Emacs 20, keywords `:bold' and `:italic' can
+be used to specify that a bold or italic font should be used.  VALUE
+must be t or nil in that case.  A value of `unspecified' is not allowed."
+  (cond ((null frame)
+	 ;; Change face on all frames.
+	 (dolist (frame (frame-list))
+	   (apply #'set-face-attribute face frame args))
+	 ;; Record that as a default for new frames.
+	 (apply #'set-face-attribute face t args))
+	(t
+	 (while args
+	   (internal-set-lisp-face-attribute face (car args)
+					     (car (cdr args)) frame)
+	   (setq args (cdr (cdr args)))))))
+
+
+(defun make-face-bold (face &optional frame)
+  "Make the font of FACE be bold, if possible.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' for finer control of the font weight."
+  (interactive (list (read-face-name "Make which face bold: ")))
+  (set-face-attribute face frame :weight 'bold))
+
+
+(defun make-face-unbold (face &optional frame)
+  "Make the font of FACE be non-bold, if possible.
+FRAME nil or not specified means change face on all frames."
+  (interactive (list (read-face-name "Make which face non-bold: ")))
+  (set-face-attribute face frame :weight 'normal))
+
+  
+(defun make-face-italic (face &optional frame)
+  "Make the font of FACE be italic, if possible.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' for finer control of the font slant."
+  (interactive (list (read-face-name "Make which face italic: ")))
+  (set-face-attribute face frame :slant 'italic))
+
+
+(defun make-face-unitalic (face &optional frame)
+  "Make the font of FACE be non-italic, if possible.
+FRAME nil or not specified means change face on all frames."
+  (interactive (list (read-face-name "Make which face non-italic: ")))
+  (set-face-attribute face frame :slant 'normal))
+
+  
+(defun make-face-bold-italic (face &optional frame)
+  "Make the font of FACE be bold and italic, if possible.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' for finer control of font weight and slant."
+  (interactive (list (read-face-name "Make which face bold-italic: ")))
+  (set-face-attribute face frame :weight 'bold :slant 'italic))
+
+
+(defun set-face-font (face font &optional frame)
+  "Change font-related attributes of FACE to those of FONT (a string).
+FRAME nil or not specified means change face on all frames.
+This sets the attributes `:family', `:width', `:height', `:weight',
+and `:slant'.  When called interactively, prompt for the face and font."
+  (interactive (read-face-and-attribute :font))
+  (set-face-attribute face frame :font font))
+
+
+;; Implementation note: Emulating gray background colors with a
+;; stipple pattern is now part of the face realization process, and is
+;; done in C depending on the frame on which the face is realized.
+
+(defun set-face-background (face color &optional frame)
+  "Change the background color of face FACE to COLOR (a string).
+FRAME nil or not specified means change face on all frames.
+When called interactively, prompt for the face and color."
+  (interactive (read-face-and-attribute :background))
+  (set-face-attribute face frame :background color))
+
+
+(defun set-face-foreground (face color &optional frame)
+  "Change the foreground color of face FACE to COLOR (a string).
+FRAME nil or not specified means change face on all frames.
+When called interactively, prompt for the face and color."
+  (interactive (read-face-and-attribute :foreground))
+  (set-face-attribute face frame :foreground color))
+
+
+(defun set-face-stipple (face stipple &optional frame)
+  "Change the stipple pixmap of face FACE to STIPPLE.
+FRAME nil or not specified means change face on all frames.
+STIPPLE. should be a string, the name of a file of pixmap data.
+The directories listed in the `x-bitmap-file-path' variable are searched.
+
+Alternatively, STIPPLE may be a list of the form (WIDTH HEIGHT DATA)
+where WIDTH and HEIGHT are the size in pixels,
+and DATA is a string, containing the raw bits of the bitmap."
+  (interactive (read-face-and-attribute :stipple))
+  (set-face-attribute face frame :stipple stipple))
+
+
+(defun set-face-underline (face underline &optional frame)
+  "Specify whether face FACE is underlined.
+UNDERLINE nil means FACE explicitly doesn't underline.
+UNDERLINE non-nil means FACE explicitly does underlining
+with the same of the foreground color.
+If UNDERLINE is a string, underline with the color named UNDERLINE.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to ``unspecify'' underlining."
+  (interactive
+   (let ((list (read-face-and-attribute :underline)))
+     (list (car list) (eq (car (cdr list)) t))))
+  (set-face-attribute face frame :underline underline))
+
+
+(defun set-face-underline-p (face underline-p &optional frame)
+  "Specify whether face FACE is underlined.
+UNDERLINE-P nil means FACE explicitly doesn't underline.
+UNDERLINE-P non-nil means FACE explicitly does underlining.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to ``unspecify'' underlining."
+  (interactive
+   (let ((list (read-face-and-attribute :underline)))
+     (list (car list) (eq (car (cdr list)) t))))
+  (set-face-attribute face frame :underline underline-p))
+
+
+(defun set-face-inverse-video-p (face inverse-video-p &optional frame)
+  "Specify whether face FACE is in inverse video.
+INVERSE-VIDEO-P non-nil means FACE displays explicitly in inverse video.
+INVERSE-VIDEO-P nil means FACE explicitly is not in inverse video.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to ``unspecify'' the inverse video attribute."
+  (interactive
+   (let ((list (read-face-and-attribute :inverse-video)))
+     (list (car list) (eq (car (cdr list)) t))))
+  (set-face-attribute face frame :inverse-video inverse-video-p))
+
+
+(defun set-face-bold-p (face bold-p &optional frame)
+  "Specify whether face FACE is bold.
+BOLD-P non-nil means FACE should explicitly display bold.
+BOLD-P nil means FACE should explicitly display non-bold.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' or `modify-face' for finer control."
+  (if (null bold-p)
+      (make-face-unbold face frame)
+    (make-face-bold face frame)))
+
+
+(defun set-face-italic-p (face italic-p &optional frame)
+  "Specify whether face FACE is italic.
+ITALIC-P non-nil means FACE should explicitly display italic.
+ITALIC-P nil means FACE should explicitly display non-italic.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' or `modify-face' for finer control."
+  (if (null italic-p)
+      (make-face-unitalic face frame)
+    (make-face-italic face frame)))
+
+
+(defalias 'set-face-background-pixmap 'set-face-stipple)
 
 
 (defun invert-face (face &optional frame)
-  "Swap the foreground and background colors of face FACE.
-If the face doesn't specify both foreground and background, then
-set its foreground and background to the default background and foreground."
+  "Swap the foreground and background colors of FACE.
+FRAME nil or not specified means change face on all frames.
+If FACE specifies neither foreground nor background color,
+set its foreground and background to the background and foreground
+of the default face.  Value is FACE."
   (interactive (list (read-face-name "Invert face: ")))
-  (setq face (internal-get-face face frame))
-  (let ((fg (face-foreground face frame))
-	(bg (face-background face frame)))
+  (let ((fg (face-attribute face :foreground frame))
+	(bg (face-attribute face :background frame)))
     (if (or fg bg)
-	(progn
-	  (set-face-foreground face bg frame)
-	  (set-face-background face fg frame))
-      (let* ((frame-bg (cdr (assq 'background-color (frame-parameters frame))))
-	     (default-bg (or (face-background 'default frame)
-			     frame-bg))
-	     (frame-fg (cdr (assq 'foreground-color (frame-parameters frame))))
-	     (default-fg (or (face-foreground 'default frame)
-			     frame-fg)))
-	(set-face-foreground face default-bg frame)
-	(set-face-background face default-fg frame))))
+	(set-face-attribute face frame :foreground bg :background fg)
+      (set-face-attribute face frame
+			  :foreground
+			  (face-attribute 'default :background frame)
+			  :background
+			  (face-attribute 'default :foreground frame))))
   face)
 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Interactively modifying faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun internal-try-face-font (face font &optional frame)
-  "Like set-face-font, but returns nil on failure instead of an error."
-  (condition-case ()
-      (set-face-font-auto face font frame)
-    (error nil)))
+(defun read-face-name (prompt)
+  "Read and return a face symbol, prompting with PROMPT.
+Value is a symbol naming a known face."
+  (let ((face-list (mapcar #'(lambda (x) (cons (symbol-name x) x))
+			   (face-list)))
+	face)
+    (while (equal "" (setq face (completing-read prompt face-list nil t))))
+    (intern face)))
+
+
+(defun face-valid-attribute-values (attribute &optional frame)
+  "Return valid values for face attribute ATTRIBUTE.
+The optional argument FRAME is used to determine available fonts
+and colors.  If it is nil or not specified, the selected frame is
+used.  Value is an alist of (NAME . VALUE) if ATTRIBUTE expects a value
+out of a set of discrete values.  Value is `integerp' if ATTRIBUTE expects
+an integer value."
+  (case attribute
+    (:family
+     (if window-system
+	 (mapcar #'(lambda (x) (cons (car x) (car x)))
+		 (x-font-family-list))
+       ;; Only one font on TTYs.
+       (cons "default" "default")))
+    ((:width :weight :slant :inverse-video)
+     (mapcar #'(lambda (x) (cons (symbol-name x) x))
+	     (internal-lisp-face-attribute-values attribute)))
+    ((:underline :overline :strike-through :box)
+     (if window-system
+	 (nconc (mapcar #'(lambda (x) (cons (symbol-name x) x))
+			(internal-lisp-face-attribute-values attribute))
+		(mapcar #'(lambda (c) (cons c c))
+			(x-defined-colors frame)))
+       (mapcar #'(lambda (x) (cons (symbol-name x) x))
+	       (internal-lisp-face-attribute-values attribute))))
+    ((:foreground :background)
+     (mapcar #'(lambda (c) (cons c c))
+	     (or (and window-system (x-defined-colors frame))
+		 (tty-defined-colors))))
+    ((:height)
+     'integerp)
+    (:stipple
+     (and window-system
+	  (mapcar #'list
+		  (apply #'nconc (mapcar #'directory-files
+					 x-bitmap-file-path)))))
+    (t
+     (error "Internal error"))))
+
+
+(defvar face-attribute-name-alist
+  '((:family . "font family")
+    (:width . "character set width")
+    (:height . "height in 1/10 pt")
+    (:weight . "weight")
+    (:slant . "slant")
+    (:underline . "underline")
+    (:overline . "overline")
+    (:strike-through . "strike-through")
+    (:box . "box")
+    (:inverse-video . "inverse-video display")
+    (:foreground . "foreground color")
+    (:background . "background color")
+    (:stipple . "background stipple"))
+  "An alist of descriptive names for face attributes.
+Each element has the form (ATTRIBUTE-NAME . DESCRIPTION) where
+ATTRIBUTE-NAME is a face attribute name (a keyword symbol), and
+DESCRIPTION is a descriptive name for ATTRIBUTE-NAME.")
+
+
+(defun face-descriptive-attribute-name (attribute)
+  "Return a descriptive name for ATTRIBUTE."
+  (cdr (assq attribute face-attribute-name-alist)))
+
+
+(defun face-read-string (face default name &optional completion-alist)
+  "Interactively read a face attribute string value.
+FACE is the face whose attribute is read.  DEFAULT is the default
+value to return if no new value is entered.  NAME is a descriptive
+name of the attribute for prompting.  COMPLETION-ALIST is an alist
+of valid values, if non-nil.
+
+Entering ``none'' as attribute value means an unspecified attribute
+value.  Entering nothing accepts the default value DEFAULT.
+
+Value is the new attribute value."
+  (let* ((completion-ignore-case t)
+	 (value (completing-read
+		 (if default
+		     (format "Set face %s %s (default %s): "
+			     face name (downcase (if (symbolp default)
+						     (symbol-name default)
+						   default)))
+		   (format "Set face %s %s: " face name))
+		 completion-alist)))
+    (if (equal value "none")
+	nil
+      (if (equal value "") default value))))
+
+
+(defun face-read-integer (face default name)
+  "Interactively read an integer face attribute value.
+FACE is the face whose attribute is read.  DEFAULT is the default
+value to return if no new value is entered.  NAME is a descriptive
+name of the attribute for prompting.  Value is the new attribute value."
+  (let ((new-value (face-read-string face
+				     (and default (int-to-string default))
+				     name)))
+    (and new-value
+	 (string-to-int new-value))))
+
+
+(defun read-face-attribute (face attribute &optional frame)
+  "Interactively read a new value for FACE's ATTRIBUTE.
+Optional argument FRAME nil or unspecified means read an attribute value
+of a global face.  Value is the new attribute value."
+  (let* ((old-value (face-attribute face attribute frame))
+	 (attribute-name (face-descriptive-attribute-name attribute))
+	 (valid (face-valid-attribute-values attribute frame))
+	 new-value)
+    ;; Represent complex attribute values as strings by printing them
+    ;; out.  Stipple can be a vector; (WIDTH HEIGHT DATA).  Box can be
+    ;; a list `(:width WIDTH :color COLOR)' or `(:width WIDTH :shadow
+    ;; SHADOW)'.
+    (when (and (or (eq attribute :stipple)
+		   (eq attribute :box))
+	       (or (consp old-value)
+		   (vectorp old-value)))
+      (setq old-value (prin1-to-string old-value)))
+    (cond ((listp valid)
+	   (setq new-value
+		 (cdr (assoc (face-read-string face old-value
+					       attribute-name valid)
+			     valid))))
+	  ((eq valid 'integerp)
+	   (setq new-value (face-read-integer face old-value attribute-name)))
+	  (t (error "Internal error")))
+    ;; Convert stipple and box value text we read back to a list or
+    ;; vector if it looks like one.  This makes the assumption that a
+    ;; pixmap file name won't start with an open-paren.
+    (when (and (or (eq attribute :stipple)
+		   (eq attribute :box))
+	       (stringp new-value)
+	       (string-match "^[[(]" new-value))
+      (setq new-value (read new-value)))
+    new-value))
+
+
+(defun read-face-font (face &optional frame)
+  "Read the name of a font for FACE on FRAME.
+If optional argument FRAME Is nil or omitted, use the selected frame."
+  (let ((completion-ignore-case t))
+    (completing-read "Set font attributes of face %s from font: "
+		     face (x-list-fonts "*" nil frame))))
+
+
+(defun read-all-face-attributes (face &optional frame)
+  "Interactively read all attributes for FACE.
+If optional argument FRAME Is nil or omitted, use the selected frame.
+Value is a property list of attribute names and new values."
+  (let (result)
+    (dolist (attribute face-attribute-name-alist result)
+      (setq result (cons (car attribute)
+			 (cons (read-face-attribute face (car attribute) frame)
+			       result))))))
+
+    
+(defun modify-face (&optional frame)
+  "Modify attributes of faces interactively.
+If optional argument FRAME is nil or omitted, modify the face used
+for newly created frame, i.e. the global face."
+  (interactive)
+  (let ((face (read-face-name "Modify face: ")))
+    (apply #'set-face-attribute face frame
+	   (read-all-face-attributes face frame))))
+
+
+(defun read-face-and-attribute (attribute &optional frame)
+  "Read face name and face attribute value.
+ATTRIBUTE is the attribute whose new value is read.
+FRAME nil or unspecified means read attribute value of global face.
+Value is a list (FACE NEW-VALUE) where FACE is the face read
+(a symbol), and NEW-VALUE is value read."
+  (cond ((eq attribute :font)
+	 (let* ((prompt (format "Set font-related attributes of face: "))
+		(face (read-face-name prompt))
+		(font (read-face-font face frame)))
+	   (list face font)))
+	(t
+	 (let* ((attribute-name (face-descriptive-attribute-name attribute))
+		(prompt (format "Set %s of face: " attribute-name))
+		(face (read-face-name prompt))
+		(new-value (read-face-attribute face attribute frame)))
+	   (list face new-value)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Listing faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar list-faces-sample-text
+  "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+  "*Text string to display as the sample text for `list-faces-display'.")
+
+
+;; The name list-faces would be more consistent, but let's avoid a
+;; conflict with Lucid, which uses that name differently.
+
+(defun list-faces-display ()
+  "List all faces, using the same sample text in each.
+The sample text is a string that comes from the variable
+`list-faces-sample-text'."
+  (interactive)
+  (let ((faces (sort (face-list) #'string-lessp))
+	(face nil)
+	(frame (selected-frame))
+	disp-frame window)
+    (with-output-to-temp-buffer "*Faces*"
+      (save-excursion
+	(set-buffer standard-output)
+	(setq truncate-lines t)
+	(while faces
+	  (setq face (car faces))
+	  (setq faces (cdr faces))
+	  (insert (format "%25s " (face-name face)))
+	  (let ((beg (point)))
+	    (insert list-faces-sample-text)
+	    (insert "\n")
+	    (put-text-property beg (1- (point)) 'face face)
+	    ;; If the sample text has multiple lines, line up all of them.
+	    (goto-char beg)
+	    (forward-line 1)
+	    (while (not (eobp))
+	      (insert "                          ")
+	      (forward-line 1))))
+	(goto-char (point-min)))
+      (print-help-return-message))
+    ;; If the *Faces* buffer appears in a different frame,
+    ;; copy all the face definitions from FRAME,
+    ;; so that the display will reflect the frame that was selected.
+    (setq window (get-buffer-window (get-buffer "*Faces*") t))
+    (setq disp-frame (if window (window-frame window)
+		       (car (frame-list))))
+    (or (eq frame disp-frame)
+	(let ((faces (face-list)))
+	  (while faces
+	    (copy-face (car faces) (car faces) frame disp-frame)
+	    (setq faces (cdr faces)))))))
+
+
+(defun describe-face (face &optional frame)
+  "Display the properties of face FACE on FRAME.
+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).
+If FRAME is omitted or nil, use the selected frame."
+  (interactive (list (read-face-name "Describe face: ")))
+  (let* ((attrs '((:family . "Family")
+		  (:width . "Width")
+		  (:height . "Height")
+		  (:weight . "Weight")
+		  (:slant . "Slant")
+		  (:foreground . "Foreground")
+		  (:background . "Background")
+		  (:underline . "Underline")
+		  (:overline . "Overline")
+		  (:strike-through . "Strike-through")
+		  (:box . "Box")
+		  (:inverse-video . "Inverse")
+		  (:stipple . "Stipple")))
+	(max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x)))
+					attrs))))
+    (with-output-to-temp-buffer "*Help*"
+      (save-excursion
+	(set-buffer standard-output)
+	(dolist (a attrs)
+	  (let ((attr (face-attribute face (car a) frame)))
+	    (insert (make-string (- max-width (length (cdr a))) ?\ )
+		    (cdr a) ": " (format "%s" attr) "\n")))
+	(insert "\nDocumentation:\n\n"
+		(or (face-documentation face)
+		    "not documented as a face.")))
+      (print-help-return-message))))
+  
+
+
 
-;; Manipulating font names.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Face specifications (defface).
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Parameter FRAME Is kept for call compatibility to with previous
+;; face implementation.
+
+(defun face-attr-construct (face &optional frame)
+  "Return a defface-style attribute list for FACE on FRAME.
+Value is a property list of pairs ATTRIBUTE VALUE for all specified
+face attributes of FACE where ATTRIBUTE is the attribute name and
+VALUE is the specified value of that attribute."
+  (let (result)
+    (dolist (entry face-attribute-name-alist result)
+      (let* ((attribute (car entry))
+	     (value (face-attribute face attribute)))
+	(unless (eq value 'unspecified)
+	  (setq result (nconc (list attribute value) result)))))))
+    
+
+(defun face-spec-set-match-display (display frame)
+  "Non-nil if DISPLAY matches FRAME.
+DISPLAY is part of a spec such as can be used in `defface'.
+If FRAME is nil, the current FRAME is used."
+  (let* ((conjuncts display)
+	 conjunct req options
+	 ;; t means we have succeeded against all the conjuncts in
+	 ;; DISPLAY that have been tested so far.
+	 (match t))
+    (if (eq conjuncts t)
+	(setq conjuncts nil))
+    (while (and conjuncts match)
+      (setq conjunct (car conjuncts)
+	    conjuncts (cdr conjuncts)
+	    req (car conjunct)
+	    options (cdr conjunct)
+	    match (cond ((eq req 'type)
+			 (or (memq window-system options)
+			     (and (null window-system)
+				  (memq 'tty options))))
+			((eq req 'class)
+			 (memq (frame-parameter frame 'display-type) options))
+			((eq req 'background)
+			 (memq (frame-parameter frame 'background-mode)
+			       options))
+			(t (error "Unknown req `%S' with options `%S'" 
+				  req options)))))
+    match))
+
+
+(defun face-spec-choose (spec &optional frame)
+  "Choose the proper attributes for FRAME, out of SPEC."
+  (unless frame
+    (setq frame (selected-frame)))
+  (let ((tail spec)
+	result)
+    (while tail
+      (let* ((entry (car tail))
+	     (display (nth 0 entry))
+	     (attrs (nth 1 entry)))
+	(setq tail (cdr tail))
+	(when (face-spec-set-match-display display frame)
+	  (setq result attrs tail nil))))
+    result))
+
+
+(defun face-spec-reset-face (face &optional frame)
+  "Reset all attributes of FACE on FRAME to unspecified."
+  (let ((attrs face-attribute-name-alist)
+	params)
+    (while attrs
+      (let ((attr-and-name (car attrs)))
+	(setq params (cons (car attr-and-name) (cons 'unspecified params))))
+      (setq attrs (cdr attrs)))
+    (apply #'set-face-attribute face frame params)))
+
+
+(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."
+  (let ((attrs (face-spec-choose spec frame))
+	params)
+    (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))))
+	(setq params (cons attribute (cons value params))))
+      (setq attrs (cdr (cdr attrs))))
+    (face-spec-reset-face face frame)
+    (apply #'set-face-attribute face frame params)))
+
+
+(defun face-attr-match-p (face attrs &optional frame)
+  "Value is non-nil if attributes of FACE match values in plist ATTRS.
+Optional parameter FRAME is the frame whose definition of FACE
+is used.  If nil or omitted, use the selected frame."
+  (unless frame
+    (setq frame (selected-frame)))
+  (let ((list face-attribute-name-alist)
+	(match t))
+    (while (and match (not (null list)))
+      (let* ((attr (car (car list)))
+	     (specified-value (plist-get attrs attr))
+	     (value-now (face-attribute face attr frame)))
+	(when specified-value
+	  (setq match (equal specified-value value-now)))
+	(setq list (cdr list))))
+    match))
+
+
+(defun face-spec-match-p (face spec &optional frame)
+  "Return t if FACE, on FRAME, matches what SPEC says it should look like."
+  (face-attr-match-p face (face-spec-choose spec frame) frame))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Background mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defcustom frame-background-mode nil
+  "*The brightness of the background.
+Set this to the symbol `dark' if your background color is dark, `light' if
+your background is light, or nil (default) if you want Emacs to
+examine the brightness for you."
+  :group 'faces
+  :set #'(lambda (var value)
+	   (set var value)
+	   (mapcar 'frame-set-background-mode (frame-list)))
+  :initialize 'custom-initialize-changed
+  :type '(choice (choice-item dark) 
+		 (choice-item light)
+		 (choice-item :tag "default" nil)))
+
+
+(defun frame-set-background-mode (frame)
+  "Set up the `background-mode' and `display-type' frame parameters for FRAME."
+  (let* ((bg-resource
+	  (and window-system
+	       (x-get-resource ".backgroundMode" "BackgroundMode")))
+	 (params (frame-parameters frame))
+	 (bg-mode (cond (frame-background-mode)
+			((null window-system)
+			 ;; No way to determine this automatically (?).
+			 'dark)
+			(bg-resource
+			 (intern (downcase bg-resource)))
+			((< (apply '+ (x-color-values
+				       (cdr (assq 'background-color
+						  params))
+				       frame))
+			    ;; Just looking at the screen, colors whose
+			    ;; values add up to .6 of the white total
+			    ;; still look dark to me.
+			    (* (apply '+ (x-color-values "white" frame)) .6))
+			 'dark)
+			(t 'light)))
+	 (display-type (cond ((null window-system)
+			      (if (tty-display-color-p) 'color 'mono))
+			     ((x-display-color-p frame)
+			      'color)
+			     ((x-display-grayscale-p frame)
+			      'grayscale)
+			     (t 'mono))))
+    (modify-frame-parameters frame
+			     (list (cons 'background-mode bg-mode)
+				   (cons 'display-type display-type))))
+  
+  ;; For all named faces, choose face specs matching the new frame
+  ;; parameters.
+  (let ((face-list (face-list)))
+    (while face-list
+      (let* ((face (car face-list))
+	     (spec (get face 'face-defface-spec)))
+	(when spec
+	  (face-spec-set face spec frame))
+      (setq face-list (cdr face-list))))))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Frame creation.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun x-handle-named-frame-geometry (parameters)
+  "Add geometry parameters for a named frame to parameter list PARAMETERS.
+Value is the new parameter list."
+  (let* ((name (or (cdr (assq 'name parameters))
+		   (cdr (assq 'name default-frame-alist))))
+	 (x-resource-name name)
+	 (res-geometry (if name (x-get-resource "geometry" "Geometry"))))
+    (when res-geometry
+      (let ((parsed (x-parse-geometry res-geometry)))
+	;; If the resource specifies a position, call the position
+	;; and size "user-specified".
+	(when (or (assq 'top parsed)
+		  (assq 'left parsed))
+	  (setq parsed (append '((user-position . t) (user-size . t)) parsed)))
+	;; Put the geometry parameters at the end.  Copy
+	;; default-frame-alist so that they go after it.
+	(setq parameters (append parameters default-frame-alist parsed))))
+    parameters))
+
+
+(defun x-handle-reverse-video (frame parameters)
+  "Handle the reverse-video frame parameter and X resource.
+`x-create-frame' does not handle this one."
+  (when (cdr (or (assq 'reverse parameters)
+		 (assq 'reverse default-frame-alist)
+		 (let ((resource (x-get-resource "reverseVideo"
+						 "ReverseVideo")))
+		   (if resource
+		       (cons nil (member (downcase resource)
+					 '("on" "true")))))))
+      (let* ((params (frame-parameters frame))
+	     (bg (cdr (assq 'foreground-color params)))
+	     (fg (cdr (assq 'background-color params))))
+	(modify-frame-parameters frame
+				 (list (cons 'foreground-color fg)
+				       (cons 'background-color bg)))
+	(if (equal bg (cdr (assq 'border-color params)))
+	    (modify-frame-parameters frame
+				     (list (cons 'border-color fg))))
+	(if (equal bg (cdr (assq 'mouse-color params)))
+	    (modify-frame-parameters frame
+				     (list (cons 'mouse-color fg))))
+	(if (equal bg (cdr (assq 'cursor-color params)))
+	    (modify-frame-parameters frame
+				     (list (cons 'cursor-color fg)))))))
+
+
+(defun x-create-frame-with-faces (&optional parameters)
+  "Create a frame from optional frame parameters PARAMETERS.
+Parameters not specified by PARAMETERS are taken from
+`default-frame-alist'.  If PARAMETERS specify a frame name,
+handle X geometry resources for that name.  If either PARAMETERS
+or `default-frame-alist' contains a `reverse' parameter, or
+the X resource ``reverseVideo'' is present, handle that.
+Value is the new frame created."
+  (setq parameters (x-handle-named-frame-geometry parameters))
+  (let ((visibility-spec (assq 'visibility parameters))
+	(frame-list (frame-list))
+	(frame (x-create-frame (cons '(visibility . nil) parameters)))
+	success)
+    (unwind-protect
+	(progn
+	  (x-handle-reverse-video frame parameters)
+	  (frame-set-background-mode frame)
+	  (face-set-after-frame-default frame)
+	  (if (or (null frame-list) (null visibility-spec))
+	      (make-frame-visible frame)
+	    (modify-frame-parameters frame (list visibility-spec)))
+	  (setq success t))
+      (unless success
+	(delete-frame frame)))
+    frame))
+
+
+(defun face-set-after-frame-default (frame)
+  "Set frame-local faces of FRAME from face specs and resources."
+  (dolist (face (face-list))
+    (let ((spec (or (get face 'saved-face)
+		    (get face 'face-defface-spec))))
+      (when spec
+	(face-spec-set face spec frame))
+      (internal-merge-in-global-face face frame)
+      (when window-system
+	(make-face-x-resource-internal face frame)))))
+
+
+(defun tty-create-frame-with-faces (&optional parameters)
+  "Create a frame from optional frame parameters PARAMETERS.
+Parameters not specified by PARAMETERS are taken from
+`default-frame-alist'.  If either PARAMETERS or `default-frame-alist'
+contains a `reverse' parameter, handle that.  Value is the new frame
+created."
+  (let ((frame (make-terminal-frame parameters))
+	success)
+    (unwind-protect
+	(progn
+	  (frame-set-background-mode frame)
+	  (face-set-after-frame-default frame)
+	  (setq success t))
+      (unless success
+	(delete-frame frame)))
+    frame))
+
+
+;; Called from C function init_display to initialize faces of the
+;; dumped terminal frame on startup.
+
+(defun tty-set-up-initial-frame-faces ()
+  (let ((frame (selected-frame)))
+    (frame-set-background-mode frame)
+    (face-set-after-frame-default frame)))
+  
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Compatiblity with 20.2
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Update a frame's faces when we change its default font.
+
+(defun frame-update-faces (frame)
+  nil)
+
+
+;; Update the colors of FACE, after FRAME's own colors have been
+;; changed.
+
+(defun frame-update-face-colors (frame)
+  (frame-set-background-mode frame))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Standard faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Make the standard faces.  The C code knows faces `default',
+;; `modeline', `toolbar' and `region', so they must be the first faces
+;; made.  Unspecified attributes of these three faces are filled-in
+;; from frame parameters in the C code.
+
+(defgroup basic-faces nil
+  "The standard faces of Emacs."
+  :group 'faces)
+
+
+(defface default
+  '((t nil))
+  "Basic default face."
+  :group 'basic-faces)
+
+
+(defface modeline
+  '((((type x) (class color))
+     (:box (:line-width 2 :style released-button) :background "grey75"))
+    (t
+     (:inverse-video t)))
+  "Basic mode line face."
+  :group 'basic-faces)
+
+
+(defface top-line
+  '((((type x) (class color))
+     (:box (:line-width 2 :style released-button) :background "grey75"))
+    (t
+     (:inverse-video t)))
+  "Basic top line face."
+  :group 'basic-faces)
+
+
+(defface toolbar
+  '((((type x) (class color))
+     (:box (:line-width 1 :style released-button) :background "grey75"))
+    (t
+     ()))
+  "Basic toolbar face."
+  :group 'basic-faces)
+
+
+(defface region
+  '((((type tty) (class color))
+     (:background "blue" :foreground "white"))
+    (((type tty) (class mono))
+     (:inverse-video t))
+    (((class color) (background dark))
+     (:background "blue"))
+    (((class color) (background light))
+     (:background "lightblue"))
+    (t (:background "gray")))
+  "Basic face for highlight the region."
+  :group 'basic-faces)
+
+
+(defface bitmap-area
+  '((((class color))
+     (:background "grey95"))
+    (t (:background "gray")))
+  "Basic face for bitmap areas under X."
+  :group 'basic-faces)
+
+
+(defface bold '((t (:weight bold)))
+  "Basic bold face."
+  :group 'basic-faces)
+
+
+(defface italic '((t (:slant italic)))
+  "Basic italic font."
+  :group 'basic-faces)
+
+
+(defface bold-italic '((t (:weight bold :slant italic)))
+  "Basic bold-italic face."
+  :group 'basic-faces)
+
+
+(defface underline '((t (:underline t)))
+  "Basic underlined face."
+  :group 'basic-faces)
+
+
+(defface highlight
+  '((((type tty) (class color))
+     (:background "green"))
+    (((class color) (background light))
+     (:background "darkseagreen2"))
+    (((class color) (background dark))
+     (:background "darkolivegreen"))
+    (t (:inverse-video t)))
+  "Basic face for highlighting.")
+
+
+(defface secondary-selection
+  '((((type tty) (class color))
+     (:background "cyan"))
+    (((class color) (background light))
+     (:background "paleturquoise"))
+    (((class color) (background dark))
+     (:background "darkslateblue"))
+    (t (:inverse-video t)))
+  "Basic face for displaying the secondary selection.")
+
+
+(defface fixed-pitch '((t (:family "courier*")))
+  "The basic fixed-pitch face."
+  :group 'basic-faces)
+
+
+(defface variable-pitch '((t (:family "helv*")))
+  "The basic variable-pitch face."
+  :group 'basic-faces)
+
+
+(defface trailing-whitespace
+  '((((class color) (background light))
+     (:background "red"))
+    (((class color) (background dark))
+     (:background "red"))
+    (t (:inverse-video t)))
+  "Basic face for highlighting trailing whitespace.")
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Manipulating font names.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; This is here for compatibilty with Emacs 20.2.  For example,
+;; international/fontset.el uses these functions to manipulate font
+;; names.  The following functions are not used in the face
+;; implementation itself.
 
 (defvar x-font-regexp nil)
 (defvar x-font-regexp-head nil)
@@ -803,6 +1499,7 @@
   (setq x-font-regexp-weight (concat - weight -))
   nil)	    
 
+
 (defun x-resolve-font-name (pattern &optional face frame)
   "Return a font name matching PATTERN.
 All wildcards in PATTERN become substantiated.
@@ -832,6 +1529,7 @@
 	(car fonts))
     (cdr (assq 'font (frame-parameters (selected-frame))))))
 
+
 (defun x-frob-font-weight (font which)
   (let ((case-fold-search t))
     (cond ((string-match x-font-regexp font)
@@ -852,6 +1550,7 @@
 	   (concat (substring font 0 (match-beginning 1)) which
 		   (substring font (match-end 1)))))))
 
+
 (defun x-frob-font-slant (font which)
   (let ((case-fold-search t))
     (cond ((string-match x-font-regexp font)
@@ -872,813 +1571,50 @@
 	   (concat (substring font 0 (match-beginning 1)) which
 		   (substring font (match-end 1)))))))
 
+
 (defun x-make-font-bold (font)
   "Given an X font specification, make a bold version of it.
 If that can't be done, return nil."
   (x-frob-font-weight font "bold"))
 
+
 (defun x-make-font-demibold (font)
   "Given an X font specification, make a demibold version of it.
 If that can't be done, return nil."
   (x-frob-font-weight font "demibold"))
 
+
 (defun x-make-font-unbold (font)
   "Given an X font specification, make a non-bold version of it.
 If that can't be done, return nil."
   (x-frob-font-weight font "medium"))
 
+
 (defun x-make-font-italic (font)
   "Given an X font specification, make an italic version of it.
 If that can't be done, return nil."
   (x-frob-font-slant font "i"))
 
+
 (defun x-make-font-oblique (font) ; you say tomayto...
   "Given an X font specification, make an oblique version of it.
 If that can't be done, return nil."
   (x-frob-font-slant font "o"))
 
+
 (defun x-make-font-unitalic (font)
   "Given an X font specification, make a non-italic version of it.
 If that can't be done, return nil."
   (x-frob-font-slant font "r"))
 
+
 (defun x-make-font-bold-italic (font)
   "Given an X font specification, make a bold and italic version of it.
 If that can't be done, return nil."
   (and (setq font (x-make-font-bold font))
        (x-make-font-italic font)))
-
-;;; non-X-specific interface
 
-(defun make-face-bold (face &optional frame noerror)
-  "Make the font of the given face be bold, if possible.  
-If NOERROR is non-nil, return nil on failure."
-  (interactive (list (read-face-name "Make which face bold: ")))
-  ;; Set the bold-p flag, first of all.
-  (internal-set-face-1 face nil t 10 frame)
-  (if (and (eq frame t) (listp (face-font face t)))
-      (set-face-font face (if (memq 'italic (face-font face t))
-			      '(bold italic) '(bold))
-		     t)
-    (let (font)
-      (if (null frame)
-	  (let ((frames (frame-list)))
-	    ;; Make this face bold in global-face-data.
-	    (make-face-bold face t noerror)
-	    ;; Make this face bold in each frame.
-	    (while frames
-	      (make-face-bold face (car frames) noerror)
-	      (setq frames (cdr frames))))
-	(setq face (internal-get-face face frame))
-	(setq font (or (face-font face frame)
-		       (face-font face t)))
-	(if (listp font)
-	    (setq font nil))
-	(setq font (or font
-		       (face-font 'default frame)
-		       (cdr (assq 'font (frame-parameters frame)))))
-	(or (and font (make-face-bold-internal face frame font))
-	    ;; We failed to find a bold version of the font.
-	    noerror
-	    (error "No bold version of %S" font))))))
-
-(defun make-face-bold-internal (face frame font)
-  (let (f2)
-    (or (and (setq f2 (x-make-font-bold font))
-	     (internal-try-face-font face f2 frame))
-	(and (setq f2 (x-make-font-demibold font))
-	     (internal-try-face-font face f2 frame)))))
-
-(defun make-face-italic (face &optional frame noerror)
-  "Make the font of the given face be italic, if possible.  
-If NOERROR is non-nil, return nil on failure."
-  (interactive (list (read-face-name "Make which face italic: ")))
-  ;; Set the italic-p flag, first of all.
-  (internal-set-face-1 face nil t 11 frame)
-  (if (and (eq frame t) (listp (face-font face t)))
-      (set-face-font face (if (memq 'bold (face-font face t))
-			      '(bold italic) '(italic))
-		     t)
-    (let (font)
-      (if (null frame)
-	  (let ((frames (frame-list)))
-	    ;; Make this face italic in global-face-data.
-	    (make-face-italic face t noerror)
-	    ;; Make this face italic in each frame.
-	    (while frames
-	      (make-face-italic face (car frames) noerror)
-	      (setq frames (cdr frames))))
-	(setq face (internal-get-face face frame))
-	(setq font (or (face-font face frame)
-		       (face-font face t)))
-	(if (listp font)
-	    (setq font nil))
-	(setq font (or font
-		       (face-font 'default frame)
-		       (cdr (assq 'font (frame-parameters frame)))))
-	(or (and font (make-face-italic-internal face frame font))
-	    ;; We failed to find an italic version of the font.
-	    noerror
-	    (error "No italic version of %S" font))))))
-
-(defun make-face-italic-internal (face frame font)
-  (let (f2)
-    (or (and (setq f2 (x-make-font-italic font))
-	     (internal-try-face-font face f2 frame))
-	(and (setq f2 (x-make-font-oblique font))
-	     (internal-try-face-font face f2 frame)))))
-
-(defun make-face-bold-italic (face &optional frame noerror)
-  "Make the font of the given face be bold and italic, if possible.  
-If NOERROR is non-nil, return nil on failure."
-  (interactive (list (read-face-name "Make which face bold-italic: ")))
-  ;; Set the bold-p and italic-p flags, first of all.
-  (internal-set-face-1 face nil t 10 frame)
-  (internal-set-face-1 face nil t 11 frame)
-  (if (and (eq frame t) (listp (face-font face t)))
-      (set-face-font face '(bold italic) t)
-    (let (font)
-      (if (null frame)
-	  (let ((frames (frame-list)))
-	    ;; Make this face bold-italic in global-face-data.
-	    (make-face-bold-italic face t noerror)
-	    ;; Make this face bold in each frame.
-	    (while frames
-	      (make-face-bold-italic face (car frames) noerror)
-	      (setq frames (cdr frames))))
-	(setq face (internal-get-face face frame))
-	(setq font (or (face-font face frame)
-		       (face-font face t)))
-	(if (listp font)
-	    (setq font nil))
-	(setq font (or font
-		       (face-font 'default frame)
-		       (cdr (assq 'font (frame-parameters frame)))))
-	(or (and font (make-face-bold-italic-internal face frame font))
-	    ;; We failed to find a bold italic version.
-	    noerror
-	    (error "No bold italic version of %S" font))))))
-
-(defun make-face-bold-italic-internal (face frame font)
-  (let (f2 f3)
-    (or (and (setq f2 (x-make-font-italic font))
-	     (not (equal font f2))
-	     (setq f3 (x-make-font-bold f2))
-	     (not (equal f2 f3))
-	     (internal-try-face-font face f3 frame))
-	(and (setq f2 (x-make-font-oblique font))
-	     (not (equal font f2))
-	     (setq f3 (x-make-font-bold f2))
-	     (not (equal f2 f3))
-	     (internal-try-face-font face f3 frame))
-	(and (setq f2 (x-make-font-italic font))
-	     (not (equal font f2))
-	     (setq f3 (x-make-font-demibold f2))
-	     (not (equal f2 f3))
-	     (internal-try-face-font face f3 frame))
-	(and (setq f2 (x-make-font-oblique font))
-	     (not (equal font f2))
-	     (setq f3 (x-make-font-demibold f2))
-	     (not (equal f2 f3))
-	     (internal-try-face-font face f3 frame)))))
-
-(defun make-face-unbold (face &optional frame noerror)
-  "Make the font of the given face be non-bold, if possible.  
-If NOERROR is non-nil, return nil on failure."
-  (interactive (list (read-face-name "Make which face non-bold: ")))
-  ;; Clear the bold-p flag, first of all.
-  (internal-set-face-1 face nil nil 10 frame)
-  (if (and (eq frame t) (listp (face-font face t)))
-      (set-face-font face (if (memq 'italic (face-font face t))
-			      '(italic) nil)
-		     t)
-    (let (font font1)
-      (if (null frame)
-	  (let ((frames (frame-list)))
-	    ;; Make this face unbold in global-face-data.
-	    (make-face-unbold face t noerror)
-	    ;; Make this face unbold in each frame.
-	    (while frames
-	      (make-face-unbold face (car frames) noerror)
-	      (setq frames (cdr frames))))
-	(setq face (internal-get-face face frame))
-	(setq font1 (or (face-font face frame)
-			(face-font face t)))
-	(if (listp font1)
-	    (setq font1 nil))
-	(setq font1 (or font1
-			(face-font 'default frame)
-			(cdr (assq 'font (frame-parameters frame)))))
-	(setq font (and font1 (x-make-font-unbold font1)))
-	(or (if font (internal-try-face-font face font frame))
-	    noerror
-	    (error "No unbold version of %S" font1))))))
-
-(defun make-face-unitalic (face &optional frame noerror)
-  "Make the font of the given face be non-italic, if possible.  
-If NOERROR is non-nil, return nil on failure."
-  (interactive (list (read-face-name "Make which face non-italic: ")))
-  ;; Clear the italic-p flag, first of all.
-  (internal-set-face-1 face nil nil 11 frame)
-  (if (and (eq frame t) (listp (face-font face t)))
-      (set-face-font face (if (memq 'bold (face-font face t))
-			      '(bold) nil)
-		     t)
-    (let (font font1)
-      (if (null frame)
-	  (let ((frames (frame-list)))
-	    ;; Make this face unitalic in global-face-data.
-	    (make-face-unitalic face t noerror)
-	    ;; Make this face unitalic in each frame.
-	    (while frames
-	      (make-face-unitalic face (car frames) noerror)
-	      (setq frames (cdr frames))))
-	(setq face (internal-get-face face frame))
-	(setq font1 (or (face-font face frame)
-			(face-font face t)))
-	(if (listp font1)
-	    (setq font1 nil))
-	(setq font1 (or font1
-			(face-font 'default frame)
-			(cdr (assq 'font (frame-parameters frame)))))
-	(setq font (and font1 (x-make-font-unitalic font1)))
-	(or (if font (internal-try-face-font face font frame))
-	    noerror
-	    (error "No unitalic version of %S" font1))))))
-
-(defvar list-faces-sample-text
-  "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-  "*Text string to display as the sample text for `list-faces-display'.")
-
-;; The name list-faces would be more consistent, but let's avoid a conflict
-;; with Lucid, which uses that name differently.
-(defun list-faces-display ()
-  "List all faces, using the same sample text in each.
-The sample text is a string that comes from the variable
-`list-faces-sample-text'.
-
-It is possible to give a particular face name different appearances in
-different frames.  This command shows the appearance in the
-selected frame."
-  (interactive)
-  (let ((faces (sort (face-list) (function string-lessp)))
-	(face nil)
-	(frame (selected-frame))
-	disp-frame window
-        (face-name-max-length
-         (car (sort (mapcar (function string-width)
-			    (mapcar (function symbol-name) (face-list)))
-                    (function >)))))
-    (with-output-to-temp-buffer "*Faces*"
-      (save-excursion
-	(set-buffer standard-output)
-	(setq truncate-lines t)
-	(while faces
-	  (setq face (car faces))
-	  (setq faces (cdr faces))
-	  (insert (format 
-                   (format "%%-%ds "
-                           face-name-max-length)
-                   (symbol-name face)))
-	  (let ((beg (point)))
-	    (insert list-faces-sample-text)
-	    (insert "\n")
-	    (put-text-property beg (1- (point)) 'face face)
-	    ;; If the sample text has multiple lines, line up all of them.
-	    (goto-char beg)
-	    (forward-line 1)
-	    (while (not (eobp))
-	      (insert-char ?  (1+ face-name-max-length))
-	      (forward-line 1))))
-	(goto-char (point-min)))
-      (print-help-return-message))
-    ;; If the *Faces* buffer appears in a different frame,
-    ;; copy all the face definitions from FRAME,
-    ;; so that the display will reflect the frame that was selected.
-    (setq window (get-buffer-window (get-buffer "*Faces*") t))
-    (setq disp-frame (if window (window-frame window)
-		       (car (frame-list))))
-    (or (eq frame disp-frame)
-	(let ((faces (face-list)))
-	  (while faces
-	    (copy-face (car faces) (car faces) frame disp-frame)
-	    (setq faces (cdr faces)))))))
-
-(defun describe-face (face)
-  "Display the properties of face FACE."
-  (interactive (list (read-face-name "Describe face: ")))
-  (with-output-to-temp-buffer "*Help*"
-    (princ "Properties of face `")
-    (princ (face-name face))
-    (princ "':") (terpri)
-    (princ "Foreground: ") (princ (face-foreground face)) (terpri)
-    (princ "Background: ") (princ (face-background face)) (terpri)
-    (princ "      Font: ") (princ (face-font face)) (terpri)
-    (princ "Underlined: ") (princ (if (face-underline-p face) "yes" "no")) (terpri)
-    (princ "   Stipple: ") (princ (or (face-stipple face) "none")) (terpri)
-    (terpri)
-    (princ "Documentation:") (terpri)
-    (let ((doc (face-documentation face)))
-      (if doc
-	  (princ doc)
-	(princ "not documented as a face.")))
-    (print-help-return-message)))
-
-;;; Setting a face based on a SPEC.
-
-(defun face-attr-match-p (face attrs &optional frame)
-  (or frame (setq frame (selected-frame)))
-  (and (face-attr-match-1 face frame attrs ':inverse-video
-			  'face-inverse-video-p)
-       (if (face-inverse-video-p face frame)
-	   (and
-	    (face-attr-match-1 face frame attrs
-			       ':foreground 'face-background
-			       (cdr (assq 'foreground-color
-					  (frame-parameters frame))))
-	    (face-attr-match-1 face frame attrs
-			       ':background 'face-foreground 
-			       (cdr (assq 'background-color
-					  (frame-parameters frame)))))
-	 (and
-	  (face-attr-match-1 face frame attrs ':foreground 'face-foreground)
-	  (face-attr-match-1 face frame attrs ':background 'face-background)))
-       (face-attr-match-1 face frame attrs ':stipple 'face-stipple)
-       (face-attr-match-1 face frame attrs ':bold 'face-bold-p)
-       (face-attr-match-1 face frame attrs ':italic 'face-italic-p)
-       (face-attr-match-1 face frame attrs ':underline 'face-underline-p)
-))
-
-(defun face-attr-match-1 (face frame plist property function
-			       &optional defaultval)
-  (while (and plist (not (eq (car plist) property)))
-    (setq plist (cdr (cdr plist))))
-  (eq (funcall function face frame)
-      (if plist
-	  (nth 1 plist)
-	(or defaultval
-	    (funcall function 'default frame)))))
-
-(defun face-spec-match-p (face spec &optional frame)
-  "Return t if FACE, on FRAME, matches what SPEC says it should look like."
-  (face-attr-match-p face (face-spec-choose spec frame) frame))
-
-(defun face-attr-construct (face &optional frame)
-  "Return a defface-style attribute list for FACE, as it exists on FRAME." 
-  (let (result)
-    (if (face-inverse-video-p face frame)
-	(progn
-	  (setq result (cons ':inverse-video (cons t result)))
-	  (or (face-attr-match-1 face frame nil
-				 ':foreground 'face-background
-				 (cdr (assq 'foreground-color
-					    (frame-parameters frame))))
-	      (setq result (cons ':foreground
-				 (cons (face-foreground face frame) result))))
-	  (or (face-attr-match-1 face frame nil
-				 ':background 'face-foreground 
-				 (cdr (assq 'background-color
-					    (frame-parameters frame))))
-	      (setq result (cons ':background
-				 (cons (face-background face frame) result)))))
-      (if (face-foreground face frame)
-	  (setq result (cons ':foreground
-			     (cons (face-foreground face frame) result))))
-      (if (face-background face frame)
-	  (setq result (cons ':background
-			     (cons (face-background face frame) result)))))
-    (if (face-stipple face frame)
-	(setq result (cons ':stipple
-			   (cons (face-stipple face frame) result))))
-    (if (face-bold-p face frame)
-	(setq result (cons ':bold
-			   (cons (face-bold-p face frame) result))))
-    (if (face-italic-p face frame)
-	(setq result (cons ':italic
-			   (cons (face-italic-p face frame) result))))
-    (if (face-underline-p face frame)
-	(setq result (cons ':underline
-			   (cons (face-underline-p face frame) result))))
-    result))
-    
-;; Choose the proper attributes for FRAME, out of SPEC.
-(defun face-spec-choose (spec &optional frame)
-  (or frame (setq frame (selected-frame)))
-  (let ((tail spec)
-	result)
-    (while tail
-      (let* ((entry (car tail))
-	     (display (nth 0 entry))
-	     (attrs (nth 1 entry)))
-	(setq tail (cdr tail))
-	(when (face-spec-set-match-display display frame)
-	  (setq result attrs tail nil))))
-    result))
-
-(defun face-spec-set (face spec &optional frame)
-  "Set FACE's face attributes according to the first matching entry in SPEC.
-If optional FRAME is non-nil, set it for that frame only.
-If it is nil, then apply SPEC to each frame individually.
-See `defface' for information about SPEC."
-  (if frame
-      (let ((attrs (face-spec-choose spec frame)))
-	(when attrs
-	  ;; If the font was set automatically, clear it out
-	  ;; to allow it to be set it again.
-	  (unless (face-font-explicit face frame)
-	    (set-face-font face nil frame))
-	  (modify-face face '(nil) '(nil) nil nil nil nil nil frame)
-	  (face-spec-set-1 face frame attrs ':foreground 'set-face-foreground)
-	  (face-spec-set-1 face frame attrs ':background 'set-face-background)
-	  (face-spec-set-1 face frame attrs ':stipple 'set-face-stipple)
-	  (face-spec-set-1 face frame attrs ':bold 'set-face-bold-p)
-	  (face-spec-set-1 face frame attrs ':italic 'set-face-italic-p)
-	  (face-spec-set-1 face frame attrs ':underline 'set-face-underline-p)
-	  (face-spec-set-1 face frame attrs ':inverse-video
-			   'set-face-inverse-video-p)))
-    (let ((frames (frame-list))
-	  frame)
-      (while frames
-	(setq frame (car frames)
-	      frames (cdr frames))
-	(face-spec-set face (or (get face 'saved-face)
-				(get face 'face-defface-spec))
-		       frame)
-	(face-spec-set face spec frame)))))
-
-(defun face-spec-set-1 (face frame plist property function)
-  (while (and plist (not (eq (car plist) property)))
-    (setq plist (cdr (cdr plist))))
-  (if plist
-      (funcall function face (nth 1 plist) frame)))
-
-(defun face-spec-set-match-display (display frame)
-  "Non-nil iff DISPLAY matches FRAME.
-DISPLAY is part of a spec such as can be used in `defface'.
-If FRAME is nil, the current FRAME is used."
-  (let* ((conjuncts display)
-	 conjunct req options
-	 ;; t means we have succeeded against all
-	 ;; the conjunts in DISPLAY that have been tested so far.
-	 (match t))
-    (if (eq conjuncts t)
-	(setq conjuncts nil))
-    (while (and conjuncts match)
-      (setq conjunct (car conjuncts)
-	    conjuncts (cdr conjuncts)
-	    req (car conjunct)
-	    options (cdr conjunct)
-	    match (cond ((eq req 'type)
-			 (memq window-system options))
-			((eq req 'class)
-			 (memq (frame-parameter frame 'display-type) options))
-			((eq req 'background)
-			 (memq (frame-parameter frame 'background-mode)
-			       options))
-			(t
-			 (error "Unknown req `%S' with options `%S'" 
-				req options)))))
-    match))
-
-;; Like x-create-frame but also set up the faces.
-
-(defun x-create-frame-with-faces (&optional parameters)
-  ;; Read this frame's geometry resource, if it has an explicit name,
-  ;; and put the specs into PARAMETERS.
-  (let* ((name (or (cdr (assq 'name parameters))
-		   (cdr (assq 'name default-frame-alist))))
-	 (x-resource-name name)
-	 (res-geometry (if name (x-get-resource "geometry" "Geometry"))))
-    (if res-geometry
-	(let ((parsed (x-parse-geometry res-geometry)))
-	  ;; If the resource specifies a position,
-	  ;; call the position and size "user-specified".
-	  (if (or (assq 'top parsed) (assq 'left parsed))
-	      (setq parsed (append '((user-position . t) (user-size . t))
-				   parsed)))
-	  ;; Put the geometry parameters at the end.
-	  ;; Copy default-frame-alist so that they go after it.
-	  (setq parameters (append parameters default-frame-alist parsed)))))
-
-  (if default-enable-multibyte-characters
-      ;; If an ASCII font is specified in PARAMETERS, we try to create
-      ;; a fontset from it, and use it for the new frame.
-      (condition-case nil
-	  (let ((font (cdr (assq 'font parameters))))
-	    (if (and font
-		     (not (query-fontset font)))
-		(setq parameters
-		      (cons (cons 'font (create-fontset-from-ascii-font font))
-			    parameters))))
-	(error nil)))
-
-  (let (frame)
-    (if (null global-face-data)
-	(progn
-	  (setq frame (x-create-frame parameters))
-	  (frame-set-background-mode frame))
-      (let* ((visibility-spec (assq 'visibility parameters))
-	     success faces rest)
-	(setq frame (x-create-frame (cons '(visibility . nil) parameters)))
-	(unwind-protect
-	    (progn
-	      ;; Copy the face alist, copying the face vectors
-	      ;; and emptying out their attributes.
-	      (setq faces
-		    (mapcar '(lambda (elt)
-			       (cons (car elt)
-				     (vector 'face
-					     (face-name (cdr elt))
-					     (face-id (cdr elt))
-					     nil
-					     nil nil nil nil
-					     nil nil nil nil)))
-			    global-face-data))
-	      (set-frame-face-alist frame faces)
-
-	      ;; Handle the reverse-video frame parameter
-	      ;; and X resource.  x-create-frame does not handle this one.
-	      (if (cdr (or (assq 'reverse parameters)
-			   (assq 'reverse default-frame-alist)
-			   (let ((resource (x-get-resource "reverseVideo"
-							   "ReverseVideo")))
-			     (if resource
-				 (cons nil (member (downcase resource)
-						   '("on" "true")))))))
-		  (let* ((params (frame-parameters frame))
-			 (bg (cdr (assq 'foreground-color params)))
-			 (fg (cdr (assq 'background-color params))))
-		    (modify-frame-parameters frame
-					     (list (cons 'foreground-color fg)
-						   (cons 'background-color bg)))
-		    (if (equal bg (cdr (assq 'border-color params)))
-			(modify-frame-parameters frame
-						 (list (cons 'border-color fg))))
-		    (if (equal bg (cdr (assq 'mouse-color params)))
-			(modify-frame-parameters frame
-						 (list (cons 'mouse-color fg))))
-		    (if (equal bg (cdr (assq 'cursor-color params)))
-			(modify-frame-parameters frame
-						 (list (cons 'cursor-color fg))))))
-
-	      (frame-set-background-mode frame)
-
-	      (face-set-after-frame-default frame)
-
-	      ;; Make the frame visible, if desired.
-	      (if (null visibility-spec)
-		  (make-frame-visible frame)
-		(modify-frame-parameters frame (list visibility-spec)))
-	      (setq success t))
-	  (or success
-	      (delete-frame frame)))))
-    frame))
-
-;; Update a frame's faces after the frame font changes.
-;; This is called from modify-frame-parameters
-;; as well as from elsewhere in this file.
-(defun face-set-after-frame-default (frame)
-  (let ((rest (frame-face-alist frame)))
-    (while rest
-      ;; Set up each face, first from the defface information,
-      ;; then the global face data, and then the X resources.
-      (let* ((face (car (car rest)))
-	     (spec (or (get face 'customized-face)
-		       (get face 'saved-face)
-		       (get face 'face-defface-spec)))
-	     (global (cdr (assq face global-face-data)))
-	     (local (cdr (car rest))))
-	(when spec
-	  (face-spec-set face spec frame))
-	(face-fill-in face global frame)
-	(make-face-x-resource-internal local frame))
-      (setq rest (cdr rest)))))
-
-(defcustom frame-background-mode nil
-  "*The brightness of the background.
-Set this to the symbol dark if your background color is dark, light if
-your background is light, or nil (default) if you want Emacs to
-examine the brightness for you."
-  :group 'faces
-  :set #'(lambda (var value)
-	   (set var value)
-	   (mapcar 'frame-set-background-mode (frame-list)))
-  :initialize 'custom-initialize-changed
-  :type '(choice (choice-item dark) 
-		 (choice-item light)
-		 (choice-item :tag "default" nil)))
-
-(defun frame-set-background-mode (frame)
-  "Set up the `background-mode' and `display-type' frame parameters for FRAME."
-  (unless (eq (framep frame) t)
-    (let ((bg-resource (x-get-resource ".backgroundMode"
-				       "BackgroundMode"))
-	  (params (frame-parameters frame))
-	  (bg-mode))
-      (setq bg-mode
-	    (cond (frame-background-mode)
-		  (bg-resource (intern (downcase bg-resource)))
-		  ((< (apply '+ (x-color-values
-				 (cdr (assq 'background-color params))
-				 frame))
-		      ;; Just looking at the screen,
-		      ;; colors whose values add up to .6 of the white total
-		      ;; still look dark to me.
-		      (* (apply '+ (x-color-values "white" frame)) .6))
-		   'dark)
-		  (t 'light)))
-      (modify-frame-parameters frame
-			       (list (cons 'background-mode bg-mode)
-				     (cons 'display-type
-					   (cond ((x-display-color-p frame)
-						  'color)
-						 ((x-display-grayscale-p frame)
-						  'grayscale)
-						 (t 'mono))))))))
-
-;; Update a frame's faces when we change its default font.
-(defun frame-update-faces (frame) nil)
-
-;; Update the colors of FACE, after FRAME's own colors have been changed.
-;; This applies only to faces with global color specifications
-;; that are not simple constants.
-(defun frame-update-face-colors (frame)
-  (frame-set-background-mode frame)
-  (let ((faces global-face-data))
-    (while faces
-      (condition-case nil
-	  (let* ((data (cdr (car faces)))
-		 (face (car (car faces)))
-		 (foreground (face-foreground data))
-		 (background (face-background data)))
-	    ;; If the global spec is a specific color,
-	    ;; which doesn't depend on the frame's attributes,
-	    ;; we don't need to recalculate it now.
-	    (or (listp foreground)
-		(setq foreground nil))
-	    (or (listp background)
-		(setq background nil))
-	    ;; If we are going to frob this face at all,
-	    ;; reinitialize it first.
-	    (if (or foreground background)
-		(progn (set-face-foreground face nil frame)
-		       (set-face-background face nil frame)))
-	    (if foreground
-		(face-try-color-list 'set-face-foreground
-				     face foreground frame))
-	    (if background
-		(face-try-color-list 'set-face-background
-				     face background frame)))
-	(error nil))
-      (setq faces (cdr faces)))))
-
-;; Fill in the face FACE from frame-independent face data DATA.
-;; DATA should be the non-frame-specific ("global") face vector
-;; for the face.  FACE should be a face name or face object.
-;; FRAME is the frame to act on; it must be an actual frame, not nil or t.
-(defun face-fill-in (face data frame)
-  (condition-case nil
-      (let ((foreground (face-foreground data))
-	    (background (face-background data))
-	    (font (face-font data))
-	    (stipple (face-stipple data)))
-	(if (face-underline-p data)
-	    (set-face-underline-p face (face-underline-p data) frame))
-	(if foreground
-	    (face-try-color-list 'set-face-foreground
-				 face foreground frame))
-	(if background
-	    (face-try-color-list 'set-face-background
-				 face background frame))
-	(if (listp font)
-	    (let ((bold (memq 'bold font))
-		  (italic (memq 'italic font)))
-	      (cond ((and bold italic)
-		     (make-face-bold-italic face frame))
-		    (bold
-		     (make-face-bold face frame))
-		    (italic
-		     (make-face-italic face frame))))
-	  (if font
-	      (set-face-font face font frame)))
-	(if stipple
-	    (set-face-stipple face stipple frame)))
-    (error nil)))
-
-;; Assuming COLOR is a valid color name,
-;; return t if it can be displayed on FRAME.
-(defun face-color-supported-p (frame color background-p)
-  (and window-system
-       (or (x-display-color-p frame)
-	   ;; A black-and-white display can implement these.
-	   (member color '("black" "white"))
-	   ;; A black-and-white display can fake gray for background.
-	   (and background-p
-		(face-color-gray-p color frame))
-	   ;; A grayscale display can implement colors that are gray (more or less).
-	   (and (x-display-grayscale-p frame)
-		(face-color-gray-p color frame)))))
-
-;; Use FUNCTION to store a color in FACE on FRAME.
-;; COLORS is either a single color or a list of colors.
-;; If it is a list, try the colors one by one until one of them
-;; succeeds.  We signal an error only if all the colors failed.
-;; t as COLORS or as an element of COLORS means to invert the face.
-;; That can't fail, so any subsequent elements after the t are ignored.
-(defun face-try-color-list (function face colors frame)
-  (if (stringp colors)
-      (if (face-color-supported-p frame colors
-				  (eq function 'set-face-background))
-	  (funcall function face colors frame))
-    (if (eq colors t)
-	(set-face-inverse-video-p face t frame)
-      (let (done)
-	(while (and colors (not done))
-	  (if (or (memq (car colors) '(t underline nil))
-		  (face-color-supported-p frame (car colors)
-					  (eq function 'set-face-background)))
-	      (if (cdr colors)
-		  ;; If there are more colors to try, catch errors
-		  ;; and set `done' if we succeed.
-		  (condition-case nil
-		      (progn
-			(cond ((eq (car colors) t)
-			       (set-face-inverse-video-p face t frame))
-			      ((eq (car colors) 'underline)
-			       (set-face-underline-p face t frame))
-			      (t
-			       (funcall function face (car colors) frame)))
-			(setq done t))
-		    (error nil))
-		;; If this is the last color, let the error get out if it fails.
-		;; If it succeeds, we will exit anyway after this iteration.
-		(cond ((eq (car colors) t)
-		       (set-face-inverse-video-p face t frame))
-		      ((eq (car colors) 'underline)
-		       (set-face-underline-p face t frame))
-		      (t
-		       (funcall function face (car colors) frame)))))
-	  (setq colors (cdr colors)))))))
-
-;;; Make the standard faces.
-;;; The C code knows the default and modeline faces as faces 0 and 1,
-;;; so they must be the first two faces made.
-(make-face 'default)
-(make-face 'modeline)
-(make-face 'highlight)
-
-;; These aren't really special in any way, but they're nice to have around.
-
-(make-face 'bold)
-(make-face 'italic)
-(make-face 'bold-italic)
-(make-face 'region)
-(make-face 'secondary-selection)
-(make-face 'underline)
-
-(setq region-face (face-id 'region))
-
-(defgroup basic-faces nil
-  "The standard faces of Emacs."
-  :prefix "huh"
-  :group 'faces)
-
-;; Specify how these faces look, and their documentation.
-(let ((all '((bold "Use bold font." ((t (:bold t))))
-	     (bold-italic "Use bold italic font." ((t (:bold t :italic t))))
-	     (italic "Use italic font." ((t (:italic t))))
-	     (underline "Underline text." ((t (:underline t))))
-	     (default "Used for text not covered by other faces." ((t nil)))
-	     (highlight "Highlight text in some way."
-			((((class color) (background light))
-			  (:background "darkseagreen2"))
-			 (((class color) (background dark))
-			  (:background "darkolivegreen"))
-			 (t (:inverse-video t))))
-	     (modeline "Used for displaying the modeline."
-		       ((t (:inverse-video t))))
-	     (region "Used for displaying the region."
-		     ((((class color) (background dark))
-		       (:background "blue"))
-		      (t (:background "gray"))))
-	     (secondary-selection
-	      "Used for displaying the secondary selection."
-	      ((((class color) (background light))
-		(:background "paleturquoise"))
-	       (((class color) (background dark))
-		(:background "darkslateblue"))
-	       (t (:inverse-video t))))))
-      entry symbol doc spec)
-  (while all
-    (setq entry (car all)
-	  all (cdr all)
-	  symbol (nth 0 entry)
-	  doc (nth 1 entry)
-	  spec (nth 2 entry))
-    (custom-add-to-group 'basic-faces symbol 'custom-face)
-    (put symbol 'face-documentation doc)
-    (put symbol 'face-defface-spec spec)))
 
 (provide 'faces)
 
-;;; faces.el ends here
+;;; end of faces.el
--- a/src/dispextern.h	Wed Jul 21 21:43:52 1999 +0000
+++ b/src/dispextern.h	Wed Jul 21 21:43:52 1999 +0000
@@ -1,5 +1,6 @@
 /* Interface definitions for display code.
-   Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1993, 1994, 1997, 1998, 1999
+     Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,12 +19,10 @@
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-#ifndef _DISPEXTERN_H_
-#define _DISPEXTERN_H_
-
-/* Nonzero means last display completed and cursor is really at
-   cursX, cursY.  Zero means it was preempted. */
-extern int display_completed;
+/* New redisplay written by Gerd Moellmann <gerd@acm.org>.  */
+
+#ifndef DISPEXTERN_H_INCLUDED
+#define DISPEXTERN_H_INCLUDED
 
 #ifdef HAVE_X_WINDOWS
 #include <X11/Xlib.h>
@@ -37,180 +36,2131 @@
 #include "w32gui.h"
 #endif
 
-#ifdef HAVE_FACES
-struct face
+
+/* Structure forward declarations.  Some are here because function
+   prototypes below reference structure types before their definition
+   in this file.  Some are here because not every file including
+   dispextern.h also includes frame.h and windows.h.  */
+
+struct glyph;
+struct glyph_row;
+struct glyph_matrix;
+struct glyph_pool;
+struct frame;
+struct window;
+
+
+
+/***********************************************************************
+			      Configuration
+ ***********************************************************************/
+
+/* If NO_PROMPT_IN_BUFFER is zero or undefined (default), prompts are
+   inserted into minibuffers as read-only text.  Otherwise, the
+   behavior of Emacs 20.2 is restored.  Define this as part of CFLAGS
+   because dispextern.h is not included in every C source file
+   containing conditional code for it.  */
+
+#if 0
+#define NO_PROMPT_IN_BUFFER 1
+#endif
+
+
+
+/***********************************************************************
+			      Debugging
+ ***********************************************************************/
+
+/* If GLYPH_DEBUG is non-zero, additional checks are activated.  Turn
+   it off by defining the macro GLYPH_DEBUG to zero.  */
+
+#ifndef GLYPH_DEBUG
+#define GLYPH_DEBUG 0
+#endif
+
+/* Macros to include code only if GLYPH_DEBUG != 0.  */
+
+#if GLYPH_DEBUG
+#define IF_DEBUG(X)	X
+#define xassert(X)	if (!(X)) abort (); else (void) 0
+#else
+#define IF_DEBUG(X)	(void) 0
+#define xassert(X)	(void) 0
+#endif
+
+/* Macro for displaying traces of redisplay.  If Emacs was compiled
+   with GLYPH_DEBUG != 0, the variable trace_redisplay_p can be set to
+   a non-zero value in debugging sessions to activate traces.  */
+
+#if GLYPH_DEBUG
+
+extern int trace_redisplay_p;
+#include <stdio.h>
+
+#define TRACE(X)				\
+     if (trace_redisplay_p)			\
+       fprintf X;				\
+     else					\
+       (void) 0
+
+#else /* GLYPH_DEBUG == 0 */
+
+#define TRACE(X)	(void) 0
+
+#endif /* GLYPH_DEBUG == 0 */
+
+     
+
+/***********************************************************************
+			    Text positions
+ ***********************************************************************/
+
+/* Starting with Emacs 20.3, characters from strings and buffers have
+   both a character and a byte position associated with them.  The
+   following structure holds such a pair of positions.  */
+     
+struct text_pos
+{
+  /* Character position.  */
+  int charpos;
+
+  /* Corresponding byte position.  */
+  int bytepos;
+};
+
+/* Access character and byte position of POS in a functional form.  */
+
+#define BYTEPOS(POS)	(POS).bytepos
+#define CHARPOS(POS)	(POS).charpos
+
+/* Set character position of POS to CHARPOS, byte position to BYTEPOS.  */
+
+#define SET_TEXT_POS(POS, CHARPOS, BYTEPOS) \
+     ((POS).charpos = (CHARPOS), (POS).bytepos = BYTEPOS)
+
+/* Increment text position POS.  */
+
+#define INC_TEXT_POS(POS)			\
+     do						\
+       {					\
+	 ++(POS).charpos;			\
+	 INC_POS ((POS).bytepos);		\
+       }					\
+     while (0)
+
+/* Decrement text position POS.  */
+
+#define DEC_TEXT_POS(POS)			\
+     do						\
+       {					\
+	 --(POS).charpos;			\
+	 DEC_POS ((POS).bytepos);		\
+       }					\
+     while (0)
+
+/* Set text position POS from marker MARKER.  */
+
+#define SET_TEXT_POS_FROM_MARKER(POS, MARKER)		\
+     (CHARPOS (POS) = marker_position ((MARKER)),	\
+      BYTEPOS (POS) = marker_byte_position ((MARKER)))
+
+/* Set marker MARKER from text position POS.  */
+
+#define SET_MARKER_FROM_TEXT_POS(MARKER, POS) \
+     set_marker_both ((MARKER), Qnil, CHARPOS ((POS)), BYTEPOS ((POS)))
+     
+/* Value is non-zero if character and byte positions of POS1 and POS2
+   are equal.  */
+
+#define TEXT_POS_EQUAL_P(POS1, POS2)		\
+     ((POS1).charpos == (POS2).charpos		\
+      && (POS1).bytepos == (POS2).bytepos)
+
+/* When rendering glyphs, redisplay scans string or buffer text,
+   overlay strings in that text, and does display table or control
+   character translations.  The following structure captures a
+   position taking all this into account.  */
+
+struct display_pos
+{
+  /* Buffer or string position.  */
+  struct text_pos pos;
+
+  /* If this is a position in an overlay string, overlay_string_index
+     is the index of that overlay string in the sequence of overlay
+     strings at `pos' in the order redisplay processes them.  A value
+     < 0 means that this is not a position in an overlay string.  */
+  int overlay_string_index;
+
+  /* If this is a position in an overlay string, string_pos is the
+     position within that string.  */
+  struct text_pos string_pos;
+
+  /* If the character at the position above is a control character or
+     has a display table entry, dpvec_index is an index in the display
+     table or control character translation of that character.  A
+     value < 0 means this is not a position in such a translation.  */
+  int dpvec_index;
+};
+
+
+
+/***********************************************************************
+				Glyphs
+ ***********************************************************************/
+
+/* Enumeration of glyph types.  Glyph structures contain a type field
+   containing one of the enumerators defined here.  */
+
+enum glyph_type
+{
+  /* Glyph describes a character.  */
+  CHAR_GLYPH, 	
+
+  /* Glyph describes an image.  */
+  IMAGE_GLYPH,
+
+  /* Glyph is a space of fractional width and/or height.  */
+  STRETCH_GLYPH
+};
+
+
+/* Glyphs.  */
+
+struct glyph
+{
+  /* Position from which this glyph was drawn.  If `object' below is a
+     Lisp string, this is a position in that string.  If it is a
+     buffer, this is a position in that buffer.  A value of -1
+     together with a null object means glyph is a truncation glyph at
+     the start of a row.  */
+  int charpos;
+
+  /* Lisp object source of this glyph.  Currently either a buffer or
+     a string, or 0.  */
+  Lisp_Object object;
+
+  /* Width in pixels.  */
+  short pixel_width;
+
+  /* Vertical offset.  If < 0, the glyph is displayed raised, if > 0
+     the glyph is displayed lowered.  */
+  short voffset;
+
+  /* Which kind of glyph this is---character, image etc.  Value
+     should be an enumerator of type enum glyph_type.  */
+  unsigned type : 2;
+
+  /* 1 means this glyph was produced from multibyte text.  Zero
+     means it was produced from unibyte text, i.e. charsets aren't
+     applicable, and encoding is not performed.  */
+  unsigned multibyte_p : 1;
+
+  /* Non-zero means draw a box line at the left or right side of this
+     glyph.  This is part of the implementation of the face attribute
+     `:box'.  */
+  unsigned left_box_line_p : 1;
+  unsigned right_box_line_p : 1;
+
+  /* A union of sub-structures for different glyph types.  */
+  union
   {
-    /* If this is non-zero, it is a GC we can use without modification
-       to represent this face.  Used only for ASCII characters.  */
-    GC gc;
-
-    /* GC used for non-ASCII characters.  */
-    GC non_ascii_gc;
-
-    /* Pixel value for foreground color.  */
-    EMACS_UINT foreground;
-  
-    /* Pixel value for background color.  */
-    EMACS_UINT background;
-  
-    /* Font used for this face.  If any fontset is set for this face,
-       this points to a `font' slot of the struct `font_info' for an
-       ASCII font of the fontset.  In that case, we should not call
-       XFreeFont on it because the font may still be used somewhere
-       else.  */
-    XFontStruct *font;
-
-    /* Fontset ID if any fontset is set for this face, else -1.  */
-    int fontset;
-  
-    /* Background stipple or bitmap used for this face.  */
-    Pixmap stipple;
-
-    /* Pixmap_depth.  */
-    unsigned int pixmap_w, pixmap_h;
+    /* Sub-structure for character glyphs (type == CHAR_GLYPH).  */
+    struct 
+    {
+      /* Character code.  */
+      unsigned code : 19;
+
+      /* Character's face.  */
+      unsigned face_id : 11;
+
+      /* 1 means glyph is a padding glyph.  Padding glyphs are used
+	 for characters whose visual shape consists of more than one
+	 glyph (e.g. Asian characters).  All but the first glyph of
+	 such a glyph sequence have the padding_p flag set.  Only used
+	 for terminal frames, and there only to minimize code changes.
+	 A better way would probably be to use the width field of
+	 glyphs to express padding.  */
+      unsigned padding_p : 1;
+    }
+    ch;
+
+    /* Sub-structure for image glyphs (type == IMAGE_GLYPH).  */
+    struct
+    {
+      /* Image id.  */
+      unsigned id : 20;
+
+      /* Face under the image.  */
+      unsigned face_id : 12;
+    }
+    img;
+
+    /* Sub-structure for type == STRETCH_GLYPH.  */
+    struct
+    {
+      /* The height of the glyph.  */
+      unsigned height  : 11;
+
+      /* The ascent of the glyph.  */
+      unsigned ascent  : 10;
+
+      /* The face of the stretch glyph.  */
+      unsigned face_id : 11;
+    }
+    stretch;
+    
+    /* Used to compare all bit-fields above in one step.  */
+    unsigned val;
+  } u;
+};
+
+
+/* Is GLYPH a space?  */
+
+#define CHAR_GLYPH_SPACE_P(GLYPH) \
+     (GLYPH_FROM_CHAR_GLYPH ((GLYPH)) == SPACEGLYPH)
+
+/* Are glyphs *X and *Y equal?  */
+     
+#define GLYPH_EQUAL_P(X, Y)					\
+     ((X)->type == (Y)->type					\
+      && (X)->u.val == (Y)->u.val				\
+      && (X)->left_box_line_p == (Y)->left_box_line_p		\
+      && (X)->right_box_line_p == (Y)->right_box_line_p		\
+      && (X)->voffset == (Y)->voffset)
+
+/* Fill a character glyph GLYPH.  CODE, FACE_ID, PADDING_P correspond
+   to the bits defined for the typedef `GLYPH' in lisp.h.  */
+     
+#define SET_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P)	\
+     do							\
+       {						\
+         (GLYPH).u.ch.code = (CODE);			\
+         (GLYPH).u.ch.face_id = (FACE_ID);		\
+         (GLYPH).u.ch.padding_p = (PADDING_P);		\
+       }						\
+     while (0)
+
+/* Fill a character type glyph GLYPH from a glyph typedef FROM as
+   defined in lisp.h.  */
+     
+#define SET_CHAR_GLYPH_FROM_GLYPH(GLYPH, FROM)			\
+     SET_CHAR_GLYPH ((GLYPH),					\
+	 	     FAST_GLYPH_CHAR ((FROM)),			\
+		     FAST_GLYPH_FACE ((FROM)),			\
+		     ((FROM) & GLYPH_MASK_PADDING) != 0)
+
+/* Construct a typedef'd GLYPH value from a character glyph GLYPH.  */
+     
+#define GLYPH_FROM_CHAR_GLYPH(GLYPH)				\
+     ((GLYPH).u.ch.code						\
+       | ((GLYPH).u.ch.face_id << CHARACTERBITS)		\
+       | ((GLYPH).u.ch.padding_p ? GLYPH_MASK_PADDING : 0))
+
+/* Is GLYPH a padding glyph?  */
+     
+#define CHAR_GLYPH_PADDING_P(GLYPH) (GLYPH).u.ch.padding_p
+
+
+
+
+/***********************************************************************
+			     Glyph Pools
+ ***********************************************************************/
+
+/* Glyph Pool.
+
+   Glyph memory for frame-based redisplay is allocated from the heap
+   in one vector kept in a glyph pool structure which is stored with
+   the frame.  The size of the vector is made large enough to cover
+   all windows on the frame.
+
+   Both frame and window glyph matrices reference memory from a glyph
+   pool in frame-based redisplay.
+
+   In window-based redisplay, no glyphs pools exist; windows allocate
+   and free their glyph memory themselves.  */
+
+struct glyph_pool
+{
+  /* Vector of glyphs allocated from the heap.  */
+  struct glyph *glyphs;
+
+  /* Allocated size of `glyphs'.  */
+  int nglyphs;
+
+  /* Number of rows and columns in a matrix.  */
+  int nrows, ncolumns;
+};
+
+
+
+/***********************************************************************
+			     Glyph Matrix
+ ***********************************************************************/
+
+/* Glyph Matrix.
+
+   Three kinds of glyph matrices exist:
+
+   1. Frame glyph matrices.  These are used for terminal frames whose
+   redisplay needs a view of the whole screen due to limited terminal
+   capabilities.  Frame matrices are used only in the update phase
+   of redisplay.  They are built in update_frame and not used after
+   the update has been performed.
+
+   2. Window glyph matrices on frames having frame glyph matrices.
+   Such matrices are sub-matrices of their corresponding frame matrix,
+   i.e. frame glyph matrices and window glyph matrices share the same
+   glyph memory which is allocated in form of a glyph_pool structure.
+   Glyph rows in such a window matrix are slices of frame matrix rows.
+
+   2. Free-standing window glyph matrices managing their own glyph
+   storage.  This form is used in window-based redisplay which
+   includes variable width and height fonts etc.
+
+   The size of a window's row vector depends on the height of fonts
+   defined on its frame.  It is chosen so that the vector is large
+   enough to describe all lines in a window when it is displayed in
+   the smallest possible character size.  When new fonts are loaded,
+   or window sizes change, the row vector is adjusted accordingly.  */
+
+struct glyph_matrix
+{
+  /* The pool from which glyph memory is allocated, if any.  This is
+     null for frame matrices and for window matrices managing their
+     own storage.  */
+  struct glyph_pool *pool;
+
+  /* Vector of glyph row structures.  The row at nrows - 1 is reserved
+     for the mode line.  */
+  struct glyph_row *rows;
+
+  /* Number of elements allocated for the vector rows above.  */
+  int rows_allocated;
+
+  /* The number of rows used by the window if all lines were displayed
+     with the smallest possible character height.  */
+  int nrows;
+
+  /* Origin within the frame matrix if this is a window matrix on a
+     frame having a frame matrix.  Both values are zero for
+     window-based redisplay.  */
+  int matrix_x, matrix_y;
+
+  /* Width and height of the matrix in columns and rows.  */
+  int matrix_w, matrix_h;
+
+  /* If this structure describes a window matrix, window_top_y is the
+     top-most y-position and window_height is the height of the
+     window, and window_vscroll is the vscroll at the time the matrix
+     was last adjusted.  Only set for window-based redisplay.  */
+  int window_top_y, window_height, window_width, window_vscroll;
+
+  /* Number of glyphs reserved for left and right marginal areas when
+     the matrix was last adjusted.  */
+  int left_margin_glyphs, right_margin_glyphs;
+
+  /* Flag indicating that scrolling should not be tried in
+     update_window.  This flag is set by functions like try_window_id
+     which do their own scrolling.  */
+  unsigned no_scrolling_p : 1;
+
+  /* Non-zero means window displayed in this matrix has a top mode
+     line.  */
+  unsigned top_line_p : 1;
+
+#ifdef GLYPH_DEBUG
+  /* A string identifying the method used to display the matrix.  */
+  char method[512];
+#endif
+};
+
+
+/* Check that glyph pointers stored in glyph rows of MATRIX are okay.
+   This aborts if any pointer is found twice.  */
+
+#if GLYPH_DEBUG
+void check_matrix_pointer_lossage P_ ((struct glyph_matrix *));
+#define CHECK_MATRIX(MATRIX) check_matrix_pointer_lossage ((MATRIX))
+#else
+#define CHECK_MATRIX(MATRIX) (void) 0
+#endif
+
+
+
+/***********************************************************************
+			     Glyph Rows
+ ***********************************************************************/
+
+/* Area in window glyph matrix.  If values are added or removed, the
+   function mark_object in alloc.c has to be changed.  */
+
+enum glyph_row_area
+{
+  LEFT_MARGIN_AREA,
+  TEXT_AREA,
+  RIGHT_MARGIN_AREA,
+  LAST_AREA
+};
+
+
+/* Rows of glyphs in a windows or frame glyph matrix.
+
+   Each row is partitioned into three areas.  The start and end of
+   each area is recorded in a pointer as shown below.
+   
+   +--------------------+-------------+---------------------+
+   |  left margin area  |  text area  |  right margin area  |
+   +--------------------+-------------+---------------------+
+   |                    |             |                     |
+   glyphs[LEFT_MARGIN_AREA]           glyphs[RIGHT_MARGIN_AREA]
+			|                                   |
+			glyphs[TEXT_AREA]                   |
+			                      glyphs[LAST_AREA]   
+
+   Rows in frame matrices reference glyph memory allocated in a frame
+   glyph pool (see the description of struct glyph_pool).  Rows in
+   window matrices on frames having frame matrices reference slices of
+   the glyphs of corresponding rows in the frame matrix.
+   
+   Rows in window matrices on frames having no frame matrices point to
+   glyphs allocated from the heap via xmalloc;
+   glyphs[LEFT_MARGIN_AREA] is the start address of the allocated
+   glyph structure array.  */
+
+struct glyph_row
+{
+  /* Pointers to beginnings of areas.  The end of an area A is found at
+     A + 1 in the vector.  The last element of the vector is the end
+     of the whole row.
+
+     Kludge alert: Even if used[TEXT_AREA] == 0, glyphs[TEXT_AREA][0]'s
+     position field is used.  It is -1 if this row does not correspond
+     to any text; it is some buffer position if the row corresponds to
+     an empty display line that displays a line end.  This is what old
+     redisplay used to do.  (Except in code for terminal frames, this
+     kludge is no longer use, I believe. --gerd).
+
+     See also start, end, displays_text_p and ends_at_zv_p for cleaner
+     ways to do it.  The special meaning of positions 0 and -1 will be
+     removed some day, so don't use it in new code.  */
+  struct glyph *glyphs[1 + LAST_AREA];
+
+  /* Number of glyphs actually filled in areas.  */
+  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
+     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
+     the text area of the row are invisible because the glyph is
+     partially visible.  */
+  int x, y;
+
+  /* Width of the row in pixels without taking face extension at the
+     end of the row into account.  */
+  int pixel_width;
+
+  /* Height information.  The value of ascent is zero and height is 1
+     on terminal frames.  */
+  int ascent, height;
+
+  /* Portion of row that is visible.  Partially visible rows may be
+     found at the top and bottom of a window.  This is 1 for tty
+     frames.  It may be < 0 in case of completely invisible rows.  */
+  int visible_height;
+
+  /* Hash code.  This hash code is available as soon as the row
+     is constructed, i.e. after a call to display_line.  */
+  unsigned hash;
+
+  /* First position in this row.  This is the text position, including
+     overlay position information etc, where the display of this row
+     started, and can thus be less the position of the first glyph
+     (e.g. due to invisible text or horizontal scrolling).  */
+  struct display_pos start;
+
+  /* Text position at the end of this row.  This is the position after
+     the last glyph on this row.  It can be greater than the last
+     glyph position + 1, due to truncation, invisible text etc.  In an
+     up-to-date display, this should always be equal to the start
+     position of the next row.  */
+  struct display_pos end;
+
+  /* In a desired matrix, 1 means that this row must be updated.  In a
+     current matrix, 0 means that the row has been invalidated, i.e.
+     the row's contents do not agree with what is visible on the
+     screen.  */
+  unsigned enabled_p : 1;
+
+  /* Display this line in inverse video?  Used for the mode line and
+     menu bar lines.  */
+  unsigned inverse_p : 1;
+
+  /* 1 means row displays a text line that is truncated on the left or
+     right side.  */
+  unsigned truncated_on_left_p : 1;
+  unsigned truncated_on_right_p : 1;
+
+  /* 1 means the overlay arrow is on this line.  */
+  unsigned overlay_arrow_p : 1;
   
-    /* Whether or not to underline text in this face.  */
-    char underline;
-  };
-
-/* Let's stop using this and get rid of it.  */
-typedef struct face *FACE;
-
-#define NORMAL_FACE ((struct face *) 0)
-
-#define FACE_HAS_GC(f) ((f)->gc)
-#define FACE_GC(f) ((f)->gc)
-#define FACE_NON_ASCII_GC(f) ((f)->non_ascii_gc)
-#define FACE_FOREGROUND(f) ((f)->foreground)
-#define FACE_BACKGROUND(f) ((f)->background)
-#define FACE_FONT(f) ((f)->font)
-#define FACE_FONTSET(f) ((f)->fontset)
-#define FACE_STIPPLE(f) ((f)->stipple)
-#define FACE_UNDERLINE_P(f) ((f)->underline)
-
-#else /* not HAVE_FACES */
-
-typedef int FACE;
-
-#define NORMAL_FACE 0x0
-#define HIGHLIGHT_FACE 0x1
-#define UNDERLINE_FACE 0x2
-#define HIGHLIGHT_UNDERLINE_FACE 0x3
-
-#define FACE_HIGHLIGHT(f) ((f) & 0x1)
-#define FACE_UNDERLINE(f) ((f) & 0x2)
-
-#endif /* not HAVE_FACES */
-
-
-/* This structure is used for the actual display of text on a frame.
-
-   There are two instantiations of it:  the glyphs currently displayed,
-   and the glyphs we desire to display.  The latter object is generated
-   from buffers being displayed.  */
-
-struct frame_glyphs
-  {
-    struct  frame *frame;	/* Frame these glyphs belong to.  */
-    int height;
-    int width;
-
-    /* Contents of the frame.
-       glyphs[V][H] is the glyph at position V, H.
-       Note that glyphs[V][-1],
-                 glyphs[V][used[V]],
-	     and glyphs[V][frame_width] are always '\0'.  */
-    GLYPH **glyphs;
-    /* long vector from which the strings in `glyphs' are taken.  */
-    GLYPH *total_contents;
-
-    /* When representing a desired frame,
-         enable[n] == 0 means that line n is same as current frame.
-	 Between updates, all lines should be disabled.
-       When representing current frame contents,
-         enable[n] == 0 means that line n is blank.  */
-    char *enable;
-
-    /* Everything on line n after column used[n] is considered blank.  */
-    int *used;
-
-    /* highlight[n] != 0 iff line n is highlighted.  */
-    char *highlight;
-
-    /* Buffer offset of this line's first char.
-       This is not really implemented, and cannot be,
-       and should be deleted.  */
-    int   *bufp;
+  /* 1 means that this row displays a continued line, i.e. it has a
+     continuation mark at the right side.  */
+  unsigned continued_p : 1;
+
+  /* 0 means that this row does not contain any text, i.e. it is
+     a blank line at the window and buffer end.  */
+  unsigned displays_text_p : 1;
+
+  /* 1 means that this line ends at ZV.  */
+  unsigned ends_at_zv_p : 1;
+
+  /* 1 means the face of the last glyph in the text area is drawn to
+     the right end of the window.  This flag is used in
+     update_text_area to optimize clearing to the end of the area.  */
+  unsigned fill_line_p : 1;
+
+  /* Non-zero means display a bitmap on X frames indicating that this
+     line contains no text and ends in ZV.  */
+  unsigned indicate_empty_line_p : 1;
+
+  /* 1 means this row contains glyphs that overlap each other because
+     of lbearing or rbearing.  */
+  unsigned contains_overlapping_glyphs_p : 1;
+
+  /* 1 means this row is a wide as the window it is displayed in, including
+     scroll bars, bitmap areas, and internal borders.  This also
+     implies that the row doesn't have marginal areas.  */
+  unsigned full_width_p : 1;
+
+  /* if non-zero, and full_width_p is also non-zero, don't let
+     the row draw over the frame's internal border.  */
+  unsigned internal_border_p : 1;
+
+  /* Non-zero means row is a mode or top-line.  */
+  unsigned mode_line_p : 1;
+
+  /* Continuation lines width at the start of the row.  */
+  int continuation_lines_width;
+};
+
+
+/* Get a pointer to row number ROW in matrix MATRIX.  If GLYPH_DEBUG
+   is defined to a non-zero value, the function matrix_row checks that
+   we don't try to access rows that are out of bounds.  */
+
+#if GLYPH_DEBUG
+struct glyph_row *matrix_row P_ ((struct glyph_matrix *, int));
+#define MATRIX_ROW(MATRIX, ROW)   matrix_row ((MATRIX), (ROW))
+#else
+#define MATRIX_ROW(MATRIX, ROW)	  ((MATRIX)->rows + (ROW))
+#endif
+
+/* Return a pointer to the row reserved for the mode line in MATRIX.  
+   Row MATRIX->nrows - 1 is always reserved for the mode line.  */
+
+#define MATRIX_MODE_LINE_ROW(MATRIX) \
+     ((MATRIX)->rows + (MATRIX)->nrows - 1)
+
+/* Return a pointer to the row reserved for the top line in MATRIX.
+   This is always the first row in MATRIX because that's the only
+   way that works in frame-based redisplay.  */
+
+#define MATRIX_TOP_LINE_ROW(MATRIX) (MATRIX)->rows
+
+/* Return a pointer to first row in MATRIX used for text display.  */
+
+#define MATRIX_FIRST_TEXT_ROW(MATRIX) \
+     ((MATRIX)->rows->mode_line_p ? (MATRIX)->rows + 1 : (MATRIX)->rows)
+
+/* Return a pointer to the first glyph in the text area of a row.
+   MATRIX is the glyph matrix accessed, and ROW is the row index in
+   MATRIX.  */
+
+#define MATRIX_ROW_GLYPH_START(MATRIX, ROW) \
+     (MATRIX_ROW ((MATRIX), (ROW))->glyphs[TEXT_AREA])
+
+/* Return the number of used glyphs in the text area of a row.  */
+     
+#define MATRIX_ROW_USED(MATRIX, ROW) \
+     (MATRIX_ROW ((MATRIX), (ROW))->used[TEXT_AREA])
+
+/* Return the character/ byte position at which the display of ROW
+   starts.  */
+     
+#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos)
+#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos)
+
+/* Return character/ byte position at which ROW ends.  */
+     
+#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos)
+#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos)
+
+/* Return the vertical position of ROW in MATRIX.  */
+     
+#define MATRIX_ROW_VPOS(ROW, MATRIX) ((ROW) - (MATRIX)->rows)
+
+/* Return the last glyph row + 1 in MATRIX on window W reserved for
+   text.  If W has a mode line, the last row in the matrix is reserved
+   for it.  */
+     
+#define MATRIX_BOTTOM_TEXT_ROW(MATRIX, W)		\
+     ((MATRIX)->rows					\
+      + (MATRIX)->nrows					\
+      - (WINDOW_WANTS_MODELINE_P ((W)) ? 1 : 0))
+
+/* Non-zero if the face of the last glyph in ROW's text area has
+   to be drawn to the end of the text area.  */
+     
+#define MATRIX_ROW_EXTENDS_FACE_P(ROW) ((ROW)->fill_line_p)
+
+/* Set and query the enabled_p flag of glyph row ROW in MATRIX.  */
+     
+#define SET_MATRIX_ROW_ENABLED_P(MATRIX, ROW, VALUE) \
+     (MATRIX_ROW ((MATRIX), (ROW))->enabled_p = (VALUE) != 0)
+     
+#define MATRIX_ROW_ENABLED_P(MATRIX, ROW) \
+     (MATRIX_ROW ((MATRIX), (ROW))->enabled_p)
+
+/* Non-zero if ROW displays text.  Value is non-zero if the row is
+   blank but displays a line end.  */
+     
+#define MATRIX_ROW_DISPLAYS_TEXT_P(ROW) ((ROW)->displays_text_p)
+
+/* Non-zero if ROW is not completely visible in window W.  */
+     
+#define MATRIX_ROW_PARTIALLY_VISIBLE_P(ROW)	\
+     ((ROW)->height != (ROW)->visible_height)
+
+/* Non-zero if ROW is partially visible at the top of window W.  */
+     
+#define MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P(W, ROW)		\
+     (MATRIX_ROW_PARTIALLY_VISIBLE_P ((ROW))			\
+      && (ROW)->y < WINDOW_DISPLAY_TOP_LINE_HEIGHT ((W)))
+
+/* Non-zero if ROW is partially visible at the bottom of window W.  */
+     
+#define MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P(W, ROW)		      \
+     (MATRIX_ROW_PARTIALLY_VISIBLE_P ((ROW))				      \
+      && (ROW)->y + (ROW)->height > WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE ((W)))
+
+/* Return the bottom Y + 1 of ROW.   */
+     
+#define MATRIX_ROW_BOTTOM_Y(ROW) ((ROW)->y + (ROW)->height)
+
+/* Is ROW the last visible one in the display described by the
+   iterator structure pointed to by IT?.  */
+     
+#define MATRIX_ROW_LAST_VISIBLE_P(ROW, IT) \
+     (MATRIX_ROW_BOTTOM_Y ((ROW)) >= (IT)->last_visible_y)
+
+/* Non-zero if ROW displays a continuation line.  */
+
+#define MATRIX_ROW_CONTINUATION_LINE_P(ROW) \
+     ((ROW)->continuation_lines_width > 0)
+
+/* Non-zero if ROW ends in the middle of a character.  This is the
+   case for continued lines showing only part of a display table entry
+   or a control char, or an overlay string.  */
+
+#define MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P(ROW)	\
+     ((ROW)->end.dpvec_index >= 0			\
+      || (ROW)->end.overlay_string_index >= 0)
+
+/* Non-zero if ROW ends in the middle of an overlay string.  */
+
+#define MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P(ROW) \
+     ((ROW)->end.overlay_string_index >= 0)
+
+/* Non-zero if ROW starts in the middle of a character.  See above.  */
+     
+#define MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P(ROW)	\
+     ((ROW)->start.dpvec_index >= 0			\
+      || ((ROW)->start.overlay_string_index >= 0	\
+	  && (ROW)->start.string_pos.charpos > 0))
+
+     
+/* Non-zero means that fonts have been loaded since the last glyph
+   matrix adjustments.  The function redisplay_internal adjusts glyph
+   matrices when this flag is non-zero.  */
+
+extern int fonts_changed_p;
+
+/* A glyph for a space.  */
+
+extern struct glyph space_glyph;
+
+/* Window being updated by update_window.  This is non-null as long as
+   update_window has not finished, and null otherwise.  It's role is
+   analogous to updating_frame.  */
+
+extern struct window *updated_window;
+
+/* Glyph row and area updated by update_window_line.  */
+
+extern struct glyph_row *updated_row;
+extern int updated_area;
+
+/* Non-zero means reading single-character input with prompt so put
+   cursor on mini-buffer after the prompt.  Positive means at end of
+   text in echo area; negative means at beginning of line.  */
+
+extern int cursor_in_echo_area;
+
+/* Non-zero means last display completed.  Zero means it was
+   preempted.  */
+
+extern int display_completed;
+
+/* Non-zero means redisplay has been performed directly (see also
+   direct_output_for_insert and direct_output_forward_char), so that
+   no further updating has to be performed.  The function
+   redisplay_internal checks this flag, and does nothing but reset it
+   to zero if it is non-zero.  */
+
+extern int redisplay_performed_directly_p;
+
+/* A temporary storage area, including a row of glyphs.  Initialized
+   in xdisp.c.  Used for various purposes, as an example see
+   direct_output_for_insert.  */
+
+extern struct glyph_row scratch_glyph_row;
+
+
+
+/************************************************************************
+			  Display Dimensions
+ ************************************************************************/
+
+/* Return the height of the mode line in glyph matrix MATRIX, or zero
+   if not known.  This macro is called under circumstances where
+   MATRIX might not have been allocated yet.  */
+
+#define MATRIX_MODE_LINE_HEIGHT(MATRIX)		\
+     ((MATRIX) && (MATRIX)->rows		\
+      ? MATRIX_MODE_LINE_ROW (MATRIX)->height	\
+      : 0)
+
+/* Return the height of the top line in glyph matrix MATRIX, or zero
+   if not known.  This macro is called under circumstances where
+   MATRIX might not have been allocated yet.  */
+
+#define MATRIX_TOP_LINE_HEIGHT(MATRIX)		\
+     ((MATRIX) && (MATRIX)->rows		\
+      ? MATRIX_TOP_LINE_ROW (MATRIX)->height	\
+      : 0)
+
+/* Return the current height of the mode line of window W.  If not
+   known from W's current glyph matrix, return a default based on the
+   height of the font of the face `modeline'.  */
+
+#define CURRENT_MODE_LINE_HEIGHT(W)			\
+     (MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix)	\
+      ? MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix)	\
+      : estimate_mode_line_height (XFRAME ((W)->frame), MODE_LINE_FACE_ID))
+
+/* Return the current height of the top line of window W.  If not
+   known from W's current glyph matrix, return an estimation based on
+   the height of the font of the face `top-line'.  */
+
+#define CURRENT_TOP_LINE_HEIGHT(W)					   \
+      (MATRIX_TOP_LINE_HEIGHT ((W)->current_matrix)			   \
+      ? MATRIX_TOP_LINE_HEIGHT ((W)->current_matrix)			   \
+      : estimate_mode_line_height (XFRAME ((W)->frame), TOP_LINE_FACE_ID))
+
+/* Return the height of the desired mode line of window W.  */
+
+#define DESIRED_MODE_LINE_HEIGHT(W) \
+     MATRIX_MODE_LINE_HEIGHT ((W)->desired_matrix)
+
+/* Return the height of the desired top line of window W.  */
+
+#define DESIRED_TOP_LINE_HEIGHT(W) \
+     MATRIX_TOP_LINE_HEIGHT ((W)->desired_matrix)
+
+/* Like FRAME_INTERNAL_BORDER_WIDTH but checks whether frame F is a
+   window-system frame.  */
+
+#define FRAME_INTERNAL_BORDER_WIDTH_SAFE(F) \
+     (FRAME_WINDOW_P (F) ? FRAME_INTERNAL_BORDER_WIDTH (F) : 0)
+
+/* Width of display region of window W.  For terminal frames, this
+   equals the width of W since there are no vertical scroll bars.  For
+   window system frames, the value has to be corrected by the pixel
+   width of vertical scroll bars, and bitmap areas.  */
+
+#define WINDOW_DISPLAY_PIXEL_WIDTH(W)					\
+     (((XFASTINT ((W)->width)						\
+        - FRAME_SCROLL_BAR_WIDTH (XFRAME (WINDOW_FRAME ((W))))		\
+	- 2 * FRAME_FLAGS_AREA_COLS (XFRAME (WINDOW_FRAME ((W)))))	\
+       * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W))))))
+
+/* Height of the display region of W, including a mode line, if any.  */
+     
+#define WINDOW_DISPLAY_PIXEL_HEIGHT(W)					\
+     (XFASTINT ((W)->height)						\
+      * CANON_Y_UNIT (XFRAME (WINDOW_FRAME ((W)))))
+
+/* Height in pixels of the mode line.  May be zero if W doesn't have a
+   mode line.  */
+     
+#define WINDOW_DISPLAY_MODE_LINE_HEIGHT(W)	\
+     (WINDOW_WANTS_MODELINE_P ((W))		\
+      ? CURRENT_MODE_LINE_HEIGHT (W)		\
+      : 0)
+
+/* Height in pixels of the top line.  Zero if W doesn't have a top
+   line.  */
+     
+#define WINDOW_DISPLAY_TOP_LINE_HEIGHT(W)	\
+     (WINDOW_WANTS_TOP_LINE_P ((W))		\
+      ? CURRENT_TOP_LINE_HEIGHT (W)		\
+      : 0)
+
+/* Pixel height of window W without mode line.  */
+     
+#define WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE(W)	\
+     (WINDOW_DISPLAY_PIXEL_HEIGHT ((W))		\
+      - WINDOW_DISPLAY_MODE_LINE_HEIGHT ((W)))
+
+/* Pixel height of window W without mode and top line.  */
+     
+#define WINDOW_DISPLAY_TEXT_HEIGHT(W)		\
+     (WINDOW_DISPLAY_PIXEL_HEIGHT ((W))		\
+      - WINDOW_DISPLAY_MODE_LINE_HEIGHT ((W))	\
+      - WINDOW_DISPLAY_TOP_LINE_HEIGHT ((W)))
+
+/* Left edge of W in pixels relative to its frame.  */
+     
+#define WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X(W)				\
+     (FRAME_INTERNAL_BORDER_WIDTH_SAFE (XFRAME (WINDOW_FRAME ((W))))	\
+      + (WINDOW_LEFT_MARGIN ((W))					\
+         * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W)))))			\
+      + FRAME_FLAGS_AREA_WIDTH (XFRAME (WINDOW_FRAME ((W)))))
+
+/* Right edge of window W in pixels, relative to its frame.  */
+     
+#define WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X(W)		\
+     (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W))		\
+      + WINDOW_DISPLAY_PIXEL_WIDTH ((W)))
+
+/* Top edge of W in pixels relative to its frame.  */
+     
+#define WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y(W)				\
+     (FRAME_INTERNAL_BORDER_WIDTH_SAFE (XFRAME (WINDOW_FRAME ((W))))	\
+      + (XFASTINT ((W)->top)						\
+         * CANON_Y_UNIT (XFRAME (WINDOW_FRAME ((W))))))
+
+/* Bottom edge of window W relative to its frame.  */
+     
+#define WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y(W)		\
+     (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W))		\
+      + WINDOW_DISPLAY_PIXEL_HEIGHT ((W)))
+     
+/* Convert window W relative pixel X to frame pixel coordinates.  */
+     
+#define WINDOW_TO_FRAME_PIXEL_X(W, X) \
+     ((X) + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W)))
+
+/* Convert window W relative pixel Y to frame pixel coordinates.  */
+     
+#define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \
+     ((Y) + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W)))
+
+/* Convert frame relative pixel X to window relative pixel X.  */
+     
+#define FRAME_TO_WINDOW_PIXEL_X(W, X) \
+     ((X) - WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W)))
+
+/* Convert frame relative pixel X to window relative pixel Y.  */
+     
+#define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \
+     ((Y) - WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W)))
+
+/* Width of left margin area in pixels.  */
+     
+#define WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH(W)		\
+     (NILP ((W)->left_margin_width)			\
+      ? 0						\
+      : (XINT ((W)->left_margin_width)			\
+	 * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W))))))
+	    
+/* Width of right marginal area in pixels.  */
+     
+#define WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH(W)	\
+     (NILP ((W)->right_margin_width)			\
+      ? 0						\
+      : (XINT ((W)->right_margin_width)			\
+	 * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W))))))
+
+/* Width of text area in pixels.  */
+     
+#define WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH(W)		\
+     (WINDOW_DISPLAY_PIXEL_WIDTH ((W))			\
+      - WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W))	\
+      - WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH ((W)))
+
+/* Convert a text area relative x-position in window W to frame X
+   pixel coordinates.  */
+
+#define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X)		\
+     (WINDOW_TO_FRAME_PIXEL_X ((W), (X))		\
+      + WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W)))
+
+/* Translate an x-position relative to AREA in window W to frame pixel
+   coordinates.  */
+
+#define WINDOW_AREA_TO_FRAME_PIXEL_X(W, AREA, X)	\
+     (WINDOW_TO_FRAME_PIXEL_X ((W), (X))		\
+      + (((AREA) > LEFT_MARGIN_AREA)			\
+	 ? WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W))	\
+	 : 0)						\
+      + (((AREA) > TEXT_AREA)				\
+	 ? WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH ((W))	\
+	 : 0))
+
+/* Return the pixel width of AREA in W.  */
+
+#define WINDOW_AREA_PIXEL_WIDTH(W, AREA)		\
+     (((AREA) == TEXT_AREA)				\
+      ? WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH ((W))	\
+      : (((AREA) == LEFT_MARGIN_AREA)			\
+	 ? WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W))	\
+	 : WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH ((W))))
+     
+/* Value is non-zero if window W has a mode line.  */
+
+#define WINDOW_WANTS_MODELINE_P(W)					\
+     (!MINI_WINDOW_P (W)						\
+      && !(W)->pseudo_window_p						\
+      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W)))		\
+      && !NILP (XBUFFER ((W)->buffer)->mode_line_format))
+
+/* Value is non-zero if window W wants a top line.  */
+
+#define WINDOW_WANTS_TOP_LINE_P(W)					\
+     (!MINI_WINDOW_P (W)						\
+      && !(W)->pseudo_window_p						\
+      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W)))		\
+      && !NILP (XBUFFER ((W)->buffer)->top_line_format))
+
+     
+/***********************************************************************
+				Faces
+ ***********************************************************************/
+     
+/* Indices of face attributes in Lisp face vectors.  Slot zero is the
+   symbol `face'.  */
+
+enum lface_attribute_index
+{
+  LFACE_FAMILY_INDEX = 1,
+  LFACE_SWIDTH_INDEX,
+  LFACE_HEIGHT_INDEX,
+  LFACE_WEIGHT_INDEX,
+  LFACE_SLANT_INDEX,
+  LFACE_UNDERLINE_INDEX,
+  LFACE_INVERSE_INDEX,
+  LFACE_FOREGROUND_INDEX,
+  LFACE_BACKGROUND_INDEX,
+  LFACE_STIPPLE_INDEX,
+  LFACE_OVERLINE_INDEX,
+  LFACE_STRIKE_THROUGH_INDEX,
+  LFACE_BOX_INDEX,
+  LFACE_VECTOR_SIZE
+};
+
+
+/* Box types of faces.  */
+
+enum face_box_type
+{
+  /* No box around text.  */
+  FACE_NO_BOX,
+
+  /* Simple box of specified width and color.  Default width is 1, and
+     default color is the foreground color of the face.  */
+  FACE_SIMPLE_BOX,
+
+  /* Boxes with 3D shadows.  Color equals the background color of the
+     face.  Width is specified.  */
+  FACE_RAISED_BOX,
+  FACE_SUNKEN_BOX
+};
+
+
+/* Structure describing a realized face.
+
+   For each Lisp face, 0..N realized faces can exist for different
+   frames and different charsets.  Realized faces are built from Lisp
+   faces and text properties/overlays by merging faces and adding
+   unspecified attributes from the `default' face.  */
+
+struct face
+{
+  /* The id of this face.  The id equals the index of this face in the
+     vector faces_by_id of its face cache.  */
+  int id;
 
 #ifdef HAVE_WINDOW_SYSTEM
-    /* Pixel position of top left corner of line.  */
-    short *top_left_x;
-    short *top_left_y;
-
-    /* Pixel width of line.  */
-    short *pix_width;
-
-    /* Pixel height of line.  */
-    short *pix_height;
-
-    /* Largest font ascent on this line.  */
-    short *max_ascent;
-#endif	/* HAVE_WINDOW_SYSTEM */
-
-    /* Mapping of coordinate pairs to buffer positions.
-       This field holds a vector indexed by row number.
-       Its elements are vectors indexed by column number.
-       Each element of these vectors is a buffer position, 0, or -1.
-
-       For a column where the image of a text character starts,
-       the element value is the buffer position of that character.
-       When a window's screen line starts in mid character,
-       the element for the line's first column (at the window's left margin)
-       is that character's position.
-       For successive columns within a multicolumn character,
-       the element is -1.
-       For the column just beyond the last glyph on a line,
-       the element is the buffer position of the end of the line.
-       For following columns within the same window, the element is 0.
-       For rows past the end of the accessible buffer text,
-       the window's first column has ZV and other columns have 0.
-
-       Mode lines and vertical separator lines have 0.
-
-       The column of a window's left margin
-       always has a positive value (a buffer position), not 0 or -1,
-       for each line in that window's interior.  */
-
-    int **charstarts;
-
-    /* This holds all the space in the subvectors of the charstarts field.  */
-    int *total_charstarts;
-  };
-
+  
+  /* If non-zero, a GC we can use without modification to draw 
+     characters in this face.  */
+  GC gc;
+  
+  /* Font used for this face, or null if the font could not be loaded
+     for some reason.  This points to a `font' slot of a struct
+     font_info, and we should not call XFreeFont on it because the
+     font may still be used somewhere else.  */
+  XFontStruct *font;
+
+  /* Background stipple or bitmap used for this face.  */
+  Pixmap stipple;
+
+#else /* not HAVE_WINDOW_SYSTEM */
+
+  /* Dummy.  */
+  int stipple;
+
+#endif /* not HAVE_WINDOW_SYSTEM */
+
+  /* Pixel value of foreground color for X frames.  Color index
+     for tty frames.  */
+  unsigned long foreground;
+  
+  /* Pixel value or color index of background color.  */
+  unsigned long background;
+
+  /* Pixel value or color index of underline color.  */
+  unsigned long underline_color;
+
+  /* Pixel value or color index of overlined, strike-through, or box
+     color.  */
+  unsigned long overline_color;
+  unsigned long strike_through_color;
+  unsigned long box_color;
+
+  /* The font's name.  This points to a `name' of a font_info, and it
+     must not be freed.  */
+  char *font_name;
+
+  /* The X font registry and encoding of font_name.  */
+  Lisp_Object registry;
+
+  /* Font info ID for this face's font.  An ID is stored here because
+     pointers to font_info structures may change.  The reason is that
+     they are pointers into a font table vector that is itself
+     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 CHARSET_COMPOSITION.  For all other
+     charsets, a specific font is loaded from the set of fonts
+     specified by the fontset given by the family attribute of the face.  */
+  int fontset;
+  
+  /* Pixmap width and height.  */
+  unsigned int pixmap_w, pixmap_h;
+  
+  /* Non-zero means characters in this face have a box that thickness
+     around them.  */
+  int box_line_width;
+
+  /* Type of box drawn.  A value of FACE_NO_BOX means no box is drawn
+     around text in this face.  A value of FACE_SIMPLE_BOX means a box
+     of width box_line_width is drawn in color box_color.  A value of
+     FACE_RAISED_BOX or FACE_SUNKEN_BOX means a 3D box is drawn with
+     shadow colors derived from the background color of the face.  */
+  enum face_box_type box;
+
+  /* If `box' above specifies a 3D type, 1 means use box_color for
+     drawing shadows.  */
+  unsigned use_box_color_for_shadows_p : 1;
+
+  /* The Lisp face attributes this face realizes.  All attributes
+     in this vector are non-nil.  */
+  Lisp_Object lface[LFACE_VECTOR_SIZE];
+
+  /* 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
+     CHARSET_COMPOSITION.  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;
+  unsigned overline_p : 1;
+  unsigned strike_through_p : 1;
+
+  /* 1 means that the colors specified for this face could not be
+     loaded, and were replaced by default colors, so they shouldn't be
+     freed.  */
+  unsigned foreground_defaulted_p : 1;
+  unsigned background_defaulted_p : 1;
+
+  /* 1 means that either no color is specified for underlining or that
+     the the specified color couldn't be loaded.  Use the foreground
+     color when drawing in that case. */
+  unsigned underline_defaulted_p : 1; 
+
+  /* 1 means that either no color is specified for the corresponding
+     attribute or that the the specified color couldn't be loaded.
+     Use the foreground color when drawing in that case. */
+  unsigned overline_color_defaulted_p : 1;
+  unsigned strike_through_color_defaulted_p : 1;
+  unsigned box_color_defaulted_p : 1;
+
+  /* TTY appearances.  Blinking is not yet implemented.  Colors are
+     found in `lface' with empty color string meaning the default
+     color of the TTY.  */
+  unsigned tty_bold_p : 1;
+  unsigned tty_dim_p : 1;
+  unsigned tty_underline_p : 1;
+  unsigned tty_alt_charset_p : 1;
+  unsigned tty_reverse_p : 1;
+  unsigned tty_blinking_p : 1;
+
+  /* Next and previous face in hash collision list of face cache.  */
+  struct face *next, *prev;
+};
+
+
+/* Color index indicating that face uses a terminal's default color.  */
+
+#define FACE_TTY_DEFAULT_COLOR ((unsigned long) -1)
+
+/* Non-zero if FACE was realized for unibyte use.  */
+
+#define FACE_UNIBYTE_P(FACE) ((FACE)->charset < 0)
+
+
+/* IDs of important faces known by the C face code.  These are the IDs
+   of the faces for CHARSET_ASCII.  */
+
+enum face_id
+{
+  DEFAULT_FACE_ID,
+  MODE_LINE_FACE_ID,
+  TOOLBAR_FACE_ID,
+  BITMAP_AREA_FACE_ID,
+  TOP_LINE_FACE_ID,
+  BASIC_FACE_ID_SENTINEL
+};
+
+
+/* A cache of realized faces.  Each frame has its own cache because
+   Emacs allows different frame-local face definitions.  */
+
+struct face_cache
+{
+  /* Hash table of cached realized faces.  */
+  struct face **buckets;
+  
+  /* Back-pointer to the frame this cache belongs to.  */
+  struct frame *f;
+
+  /* A vector of faces so that faces can be referenced by an ID.  */
+  struct face **faces_by_id;
+
+  /* The allocated size, and number of used slots of faces_by_id.  */
+  int size, used;
+};
+
+
+/* Prepare face FACE for use on frame F.  This must be called before
+   using X resources of FACE.  */
+
+#define PREPARE_FACE_FOR_DISPLAY(F, FACE)	\
+     if ((FACE)->gc == 0)			\
+       prepare_face_for_display ((F), (FACE));	\
+     else					\
+       (void) 0
+
+/* Return a pointer to the face with ID on frame F, or null if such a
+   face doesn't exist.  */
+
+#define FACE_FROM_ID(F, ID)				\
+     (((ID) >= 0 && (ID) < FRAME_FACE_CACHE (F)->used)	\
+      ? FRAME_FACE_CACHE (F)->faces_by_id[ID]		\
+      : NULL)
+
+/* Non-zero if FACE is suitable for displaying characters of CHARSET.
+   CHARSET < 0 means unibyte text.  */
+
+#define FACE_SUITABLE_FOR_CHARSET_P(FACE, CHARSET)			\
+     (((CHARSET) < 0							\
+       ? (EQ ((FACE)->registry, Vface_default_registry)			\
+	  || !NILP (Fequal ((FACE)->registry, Vface_default_registry)))	\
+       : ((FACE)->charset == (CHARSET)					\
+	  || ((FACE)->charset == CHARSET_ASCII				\
+	      && (CHARSET) == charset_latin_iso8859_1			\
+	      && face_suitable_for_iso8859_1_p ((FACE)))		\
+	  || ((FACE)->charset == charset_latin_iso8859_1		\
+	      && (CHARSET) == CHARSET_ASCII))))
+     
+/* Return the id of the realized face on frame F that is like the face
+   with id ID but is suitable for displaying characters of CHARSET.
+   This macro is only meaningful for CHARSET >= 0, i.e. multibyte
+   text.  */
+   
+#define FACE_FOR_CHARSET(F, ID, CHARSET)				\
+     (FACE_SUITABLE_FOR_CHARSET_P (FACE_FROM_ID ((F), (ID)), (CHARSET))	\
+      ? (ID)								\
+      : lookup_face ((F), FACE_FROM_ID ((F), (ID))->lface, (CHARSET)))
+
+/* The default registry and encoding to use.  */
+
+extern Lisp_Object Vface_default_registry;
+
+/* Non-zero means face attributes have been changed since the last
+   redisplay.  Used in redisplay_internal.  */
+
+extern int face_change_count;
+
+
+
+
+/***********************************************************************
+			    Display Iterator
+ ***********************************************************************/
+
+/* Iteration over things to display in current_buffer or in a string.
+
+   The iterator handles:
+
+   1. Overlay strings (after-string, before-string).
+   2. Face properties.
+   3. Invisible text properties.
+   4. Selective display.
+   5. Translation of characters via display tables.
+   6. Translation of control characters to the forms `\003' or `^C'.
+   7. `glyph' and `space-width' properties.
+
+   Iterators are initialized by calling init_iterator or one of the
+   equivalent functions below.  A call to get_next_display_element
+   loads the iterator structure with information about what next to
+   display.  A call to set_iterator_to_next increments the iterator's
+   position.
+
+   Characters from overlay strings, display table entries or control
+   character translations are returned one at a time.  For example, if
+   we have a text of `a\x01' where `a' has a display table definition
+   of `cd' and the control character is displayed with a leading
+   arrow, then the iterator will return:
+
+   Call		Return  Source		Call next
+   -----------------------------------------------------------------
+   next		c	display table	move
+   next		d	display table	move
+   next		^	control char	move
+   next		A	control char	move
+
+   The same mechanism is also used to return characters for ellipses
+   displayed at the end of invisible text.
+
+   CAVEAT: Under some circumstances, move_.* functions can be called
+   asynchronously, e.g. when computing a buffer position from an x and
+   y pixel position.  This means that these functions and functions
+   called from them SHOULD NOT USE xmalloc and alike.  See also the
+   comment at the start of xdisp.c.  */
+
+/* Enumeration describing what kind of display element an iterator is
+   loaded with after a call to get_next_display_element.  */
+
+enum display_element_type
+{
+  /* A normal character.  */
+  IT_CHARACTER,
+
+  /* An image.  */
+  IT_IMAGE,
+
+  /* A flexible width and height space.  */
+  IT_STRETCH,
+
+  /* End of buffer or string.  */
+  IT_EOB,
+
+  /* Truncation glyphs.  Never returned by get_next_display_element.
+     Used to get display information about truncation glyphs via
+     produce_glyphs.  */
+  IT_TRUNCATION,
+
+  /* Continuation glyphs.  See the comment for IT_TRUNCATION.  */
+  IT_CONTINUATION
+};
+
+
+/* An enumerator for each text property that has a meaning for display
+   purposes.  */
+
+enum prop_idx
+{
+  FONTIFIED_PROP_IDX,
+  FACE_PROP_IDX,
+  INVISIBLE_PROP_IDX,
+  DISPLAY_PROP_IDX,
+
+  /* Not a property.  Used to indicate changes in overlays.  */
+  OVERLAY_PROP_IDX,
+
+  /* Sentinel.  */
+  LAST_PROP_IDX
+};
+
+
+struct it
+{
+  /* The window in which we iterate over current_buffer (or a string).  */
+  Lisp_Object window;
+  struct window *w;
+
+  /* The window's frame.  */
+  struct frame *f;
+
+  /* Function to call to load this structure with the next display
+     element.  */
+  int (* method) P_ ((struct it *it));
+
+  /* The next position at which to check for face changes, invisible
+     text, overlay strings, end of text etc., which see.  */
+  int stop_charpos;
+
+  /* Maximum string or buffer position + 1.  ZV when iterating over
+     current_buffer.  */
+  int end_charpos;
+
+  /* C string to iterate over.  Non-null means get characters from
+     this string, otherwise characters are read from current_buffer
+     or it->string.  */
+  unsigned char *s;
+
+  /* Number of characters in the string (s, or it->string) we iterate
+     over.  */
+  int string_nchars;
+
+  /* Start and end of a visible region; -1 if the region is not
+     visible in the window.  */
+  int region_beg_charpos, region_end_charpos;
+
+  /* Position at which redisplay end trigger functions should be run.  */
+  int redisplay_end_trigger_charpos;
+
+  /* 1 means multibyte characters are enabled.  */
+  unsigned multibyte_p : 1;
+
+  /* 1 means highlight trailing whitespace.  */
+  unsigned show_trailing_whitespace_p : 1;
+
+  /* 1 means window has a mode line at its top.  */
+  unsigned top_line_p : 1;
+
+  /* 1 means `string' is the value of a `display' property.
+     Don't handle some `display' properties in these strings.  */
+  unsigned string_from_display_prop_p : 1;
+
+  /* Display table in effect or null for none.  */
+  struct Lisp_Char_Table *dp;
+
+  /* Current display table vector to return characters from and its
+     end.  dpvec null means we are not returning characters from a
+     display table entry; current.dpvec_index gives the current index
+     into dpvec.  This same mechanism is also used to return
+     characters from translated control characters, i.e. `\003' or
+     `^C'.  */
+  Lisp_Object *dpvec, *dpend;
+
+  /* Length in bytes of the char that filled dpvec.  A value of zero
+     means that no character such character is involved.  */
+  int dpvec_char_len;
+
+  /* Face id of the iterator saved in case a glyph from dpvec contains
+     a face.  The face is restored when all glyphs from dpvec have
+     been delivered.  */
+  int saved_face_id;
+
+  /* Vector of glyphs for control character translation.  The pointer
+     dpvec is set to ctl_chars when a control character is translated.  */
+  Lisp_Object ctl_chars[4];
+
+  /* Current buffer or string position of the iterator, including
+     position in overlay strings etc.  */
+  struct display_pos current;
+
+  /* Vector of overlays to process.  Overlay strings are processed
+     OVERLAY_STRING_CHUNK_SIZE at a time.  */
+#define OVERLAY_STRING_CHUNK_SIZE 3
+  Lisp_Object overlay_strings[OVERLAY_STRING_CHUNK_SIZE];
+
+  /* Total number of overlay strings to process.  This can be >
+     OVERLAY_STRING_CHUNK_SIZE.  */
+  int n_overlay_strings;
+
+  /* If non-nil, a Lisp string being processed.  If
+     current.overlay_string_index >= 0, this is an overlay string from
+     pos.  */
+  Lisp_Object string;
+
+  /* Stack of saved values.  New entries are pushed when we begin to
+     process an overlay string or a string from a `glyph' property.
+     Entries are popped when we return to deliver display elements
+     from what we previously had.  */
+  struct iterator_stack_entry
+  {
+    int stop_charpos;
+    int face_id;
+    Lisp_Object string;
+    struct display_pos pos;
+    int end_charpos;
+    int string_nchars;
+    enum glyph_row_area area;
+    unsigned multibyte_p : 1;
+    unsigned string_from_display_prop_p : 1;
+    Lisp_Object space_width;
+    short voffset;
+    Lisp_Object font_height;
+  }
+  stack[2];
+
+  /* Stack pointer.  */
+  int sp;
+  
+  /* Setting of buffer-local variable selective-display-ellipsis.  */
+  unsigned selective_display_ellipsis_p : 1;
+
+  /* 1 means control characters are translated into the form `^C'
+     where the `^' can be replaced by a display table entry.  */
+  unsigned ctl_arrow_p : 1;
+
+  /* -1 means selective display hides everything between a \r and the
+     next newline; > 0 means hide lines indented more than that value.  */
+  int selective;
+
+  /* An enumeration describing what the next display element is
+     after a call to get_next_display_element.  */
+  enum display_element_type what;
+
+  /* Face to use.  */
+  int face_id;
+
+  /* Non-zero means that the current face has a box.  */
+  unsigned face_box_p : 1;
+
+  /* Non-null means that the current character is the first in a run
+     of characters with box face.  */
+  unsigned start_of_box_run_p : 1;
+  
+  /* Non-zero means that the current character is the last in a run
+     of characters with box face.  */
+  unsigned end_of_box_run_p : 1;
+
+  /* 1 means overlay strings at end_charpos have been processed.  */
+  unsigned overlay_strings_at_end_processed_p : 1;
+
+  /* The ID of the default face to use.  One of DEFAULT_FACE_ID,
+     MODE_LINE_FACE_ID, or TOOLBAR_FACE_ID, depending on what we
+     are displaying.  */
+  int base_face_id;
+
+  /* If what == IT_CHARACTER, character and length in bytes.  This is
+     a character from a buffer or string.  It may be different from
+     the character displayed in case that
+     unibyte_display_via_language_environment is set.  */
+  int c, len;
+
+  /* The character to display, possibly translated to multibyte
+     if unibyte_display_via_language_environment is set.  This
+     is set after x_produce_glyphs has been called.  */
+  int char_to_display;
+
+  /* Charset for which face_id was computed.  This is the charset
+     of char_to_display after x_produce_glyphs has been called.  */
+  int charset;
+
+  /* If what == IT_IMAGE, the id of the image to display.  */
+  int image_id;
+
+  /* Value of the `space-width' property, if any; nil if none.  */
+  Lisp_Object space_width;
+
+  /* Computed from the value of the `raise' property.  */
+  short voffset;
+
+  /* Value of the `height' property, if any; nil if none.  */
+  Lisp_Object font_height;
+
+  /* Object and position where the current display element came from.
+     Object can be a Lisp string in case the current display element
+     comes from an overlay string, or it is buffer.  Position is
+     a position in object.  */
+  Lisp_Object object;
+  struct text_pos position;
+
+  /* 1 means lines are truncated.  */
+  unsigned truncate_lines_p : 1;
+
+  /* Number of columns per \t.  */
+  short tab_width;
+
+  /* Width in pixels of truncation and continuation glyphs.  */
+  short truncation_pixel_width, continuation_pixel_width;
+
+  /* First and last visible x-position in the display area.  If window
+     is hscrolled by n columns, first_visible_x == n * CANON_X_UNIT
+     (f), and last_visible_x == pixel width of W + first_visible_x.  */
+  int first_visible_x, last_visible_x;
+
+  /* Last visible y-position + 1 in the display area without a mode
+     line, if the window has one.  */
+  int last_visible_y;
+
+  /* Width of a prompt in front of the line.  Used to perform tab
+     calculations.  The x on which tab calculations are based is
+     current_x - prompt_width + continuation_lines_width.  */
+  int prompt_width;
+
+  /* If non-null, glyphs are produced in glyph_row with each call to
+     produce_glyphs.  */
+  struct glyph_row *glyph_row;
+
+  /* The area of glyph_row to which glyphs are added.  */
+  enum glyph_row_area area;
+
+  /* Number of glyphs needed for the last character requested via
+     produce_glyphs.  This is 1 except for tabs.  */
+  int nglyphs;
+  
+  /* Width of the display element in pixels.  Result of
+     produce_glyphs.  */
+  int pixel_width;
+
+  /* Current and maximum line height information.  Result of
+     produce_glyphs.  */
+  int ascent, descent, max_ascent, max_descent;
+
+  /* Current x pixel position within the display line.  This value
+     does not include the width of continuation lines in front of the
+     line.  The value of current_x is automatically incremented by
+     pixel_width with each call to produce_glyphs.  */
+  int current_x;
+
+  /* Accumulated width of continuation lines.  If > 0, this means we
+     are currently in a continuation line.  This is initially zero and
+     incremented/reset by display_line, move_it_to etc.  */
+  int continuation_lines_width;
+
+  /* Current y-position.  Automatically incremented by the height of
+     glyph_row in move_it_to and display_line.  */
+  int current_y;
+
+  /* Current vertical matrix position, or line number.  Automatically
+     incremented by move_it_to and display_line.  */
+  int vpos;
+
+  /* Horizontal matrix position reached in move_it_in_display_line.
+     Only set there, not in display_line.  */
+  int hpos;
+};
+
+
+/* Access to positions of iterator IT.  */
+
+#define IT_CHARPOS(IT)		CHARPOS ((IT).current.pos)
+#define IT_BYTEPOS(IT)		BYTEPOS ((IT).current.pos)
+#define IT_STRING_CHARPOS(IT)	CHARPOS ((IT).current.string_pos)
+#define IT_STRING_BYTEPOS(IT)	BYTEPOS ((IT).current.string_pos)
+
+/* Test if IT has reached the end of its buffer or string.  This will
+   only work after get_next_display_element has been called.  */
+
+#define ITERATOR_AT_END_P(IT) ((IT)->what == IT_EOB)
+
+/* Non-zero means IT is at the end of a line.  This is the case if it
+   is either on a newline or on a carriage return and selective
+   display hides the rest of the line.  */
+
+#define ITERATOR_AT_END_OF_LINE_P(IT)			\
+     ((IT)->what == IT_CHARACTER			\
+      && ((IT)->c == '\n'				\
+	  || ((IT)->c == '\r' && (IT)->selective)))
+
+/* Call produce_glyphs or produce_glyphs_hook, if set.  Shortcut to
+   avoid the function call overhead.  */
+
+#define PRODUCE_GLYPHS(IT)			\
+     (rif					\
+      ? rif->produce_glyphs ((IT))		\
+      : produce_glyphs ((IT)))
+
+/* Bit-flags indicating what operation move_it_to should perform.  */
+
+enum move_operation_enum
+{
+  /* Stop if specified x-position is reached.  */
+  MOVE_TO_X = 0x01,
+
+  /* Stop if specified y-position is reached.  */
+  MOVE_TO_Y = 0x02,
+
+  /* Stop if specified vpos is reached.  */
+  MOVE_TO_VPOS = 0x04,
+
+  /* Stop if specified buffer or string position is reached.  */
+  MOVE_TO_POS = 0x08
+};
+
+
+
+/***********************************************************************
+		   Window-based redisplay interface
+ ***********************************************************************/
+
+/* Structure used to describe runs of lines that must be scrolled.  */
+
+struct run
+{
+  /* Source and destination y pixel position.  */
+  int desired_y, current_y;
+
+  /* Source and destination vpos in matrix.  */
+  int desired_vpos, current_vpos;
+
+  /* Height in pixels, number of glyph rows.  */
+  int height, nrows;
+};
+
+
+/* Structure holding system-dependent interface functions needed
+   for window-based redisplay.  */
+
+struct redisplay_interface
+{
+  /* Produce glyphs/get display metrics for the display element IT is
+     loaded with.  */
+  void (*produce_glyphs) P_ ((struct it *it));
+  
+  /* Write or insert LEN glyphs from STRING at the nominal output
+     position.  */
+  void (*write_glyphs) P_ ((struct glyph *string, int len));
+  void (*insert_glyphs) P_ ((struct glyph *start, int len));
+
+  /* Clear from nominal output position to X.  X < 0 means clear
+     to right end of display.  */
+  void (*clear_end_of_line) P_ ((int x));
+  
+  /* Function to call to scroll the display as described by RUN on
+     window W.  */
+  void (*scroll_run_hook) P_ ((struct window *w, struct run *run));
+
+  /* Function to call after a line in a display has been completely
+     updated.  Used to draw truncation marks and alike.  DESIRED_ROW
+     is the desired row which has been updated.  */
+  void (*after_update_window_line_hook) P_ ((struct glyph_row *desired_row));
+
+  /* Function to call before beginning to update window W in
+     window-based redisplay.  */
+  void (*update_window_begin_hook) P_ ((struct window *w));
+
+  /* Function to call after window W has been updated in window-based
+     redisplay.  CURSOR_ON_P non-zero means switch cursor on.  */
+  void (*update_window_end_hook) P_ ((struct window *w, int cursor_on_p));
+  
+  /* Move cursor to row/column position VPOS/HPOS, pixel coordinates
+     Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y
+     are window-relative pixel positions.  */
+  void (*cursor_to) P_ ((int vpos, int hpos, int y, int x));
+
+  /* Flush the display of frame F.  For X, this is XFlush.  */
+  void (*flush_display) P_ ((struct frame *f));
+
+  /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
+     frame F.  */
+  void (*get_glyph_overhangs) P_ ((struct glyph *glyph, struct frame *f,
+				   int *left, int *right));
+};
+
+/* The current interface for window-based redisplay.  */
+
+extern struct redisplay_interface *rif;
+
+/* Hook to call in estimate_mode_line_height.  */
+
+extern int (* estimate_mode_line_height_hook) P_ ((struct frame *,
+                                                   enum face_id));
+
+
+/***********************************************************************
+				Images
+ ***********************************************************************/
+
+#ifdef HAVE_X_WINDOWS
+
+/* Structure forward declarations.  */
+
+struct image;
+
+
+/* Each image format (JPEG, IIFF, ...) supported is described by
+   a structure of the type below.  */
+
+struct image_type
+{
+  /* A symbol uniquely identifying the image type, .e.g `jpeg'.  */
+  Lisp_Object *type;
+
+  /* Check that SPEC is a valid image specification for the given
+     image type.  Value is non-zero if SPEC is valid.  */
+  int (* valid_p) P_ ((Lisp_Object spec));
+
+  /* Load IMG which is used on frame F from information contained in
+     IMG->spec.  Value is non-zero if successful.  */
+  int (* load) P_ ((struct frame *f, struct image *img));
+
+  /* Free resources of image IMG which is used on frame F.  */
+  void (* free) P_ ((struct frame *f, struct image *img));
+
+  /* Next in list of all supported image types.  */
+  struct image_type *next;
+};
+
+
+/* Structure describing an image.  Specific image formats like XBM are
+   converted into this form, so that display only has to deal with
+   this type of image.  */
+
+struct image
+{
+  /* The time in seconds at which the image was last displayed.  Set
+     in prepare_image_for_display.  */
+  unsigned long timestamp;
+
+  /* Pixmaps of the image.  */
+  Pixmap pixmap, mask;
+
+  /* Colors allocated for this image, if any.  Allocated via xmalloc.  */
+  unsigned long *colors;
+  int ncolors;
+
+  /* Width and height of the image.  */
+  int width, height;
+
+  /* These values are used for the rectangles displayed for images
+     that can't be loaded.  */
+#define DEFAULT_IMAGE_WIDTH 30
+#define DEFAULT_IMAGE_HEIGHT 30
+
+  /* Percent of image height used as ascent.  */
+  int ascent;
+#define DEFAULT_IMAGE_ASCENT 50
+
+  /* Lisp specification of this image.  */
+  Lisp_Object spec;
+
+  /* Relief to draw around the image.  */
+  int relief;
+
+  /* Optional margin around the image.  This includes the relief.  */
+  int margin;
+
+  /* Reference to the type of the image.  */
+  struct image_type *type;
+
+  /* A place for image types to store additional data.  The member
+     data.lisp_val is marked during GC, so it's safe to store Lisp data
+     there.  Image types should free this data when their `free'
+     function is called.  */
+  struct
+  {
+    int int_val;
+    void *ptr_val;
+    Lisp_Object lisp_val;
+  } data;
+
+  /* Hash value of image specification to speed up comparisons.  */
+  unsigned hash;
+
+  /* Image id of this image.  */
+  int id;
+
+  /* Hash collision chain.  */
+  struct image *next, *prev;
+};
+
+
+/* Cache of images.  Each frame has a cache.  X frames with the same
+   x_display_info share their caches.  */
+
+struct image_cache
+{
+  /* Hash table of images.  */
+  struct image **buckets;
+
+  /* Vector mapping image ids to images.  */
+  struct image **images;
+
+  /* Allocated size of `images'.  */
+  unsigned size;
+
+  /* Number of images in the cache.  */
+  unsigned used;
+
+  /* Reference count (number of frames sharing this cache).  */
+  int refcount;
+};
+
+
+/* Value is the ascent of image IMG.  */
+
+#define IMAGE_ASCENT(IMG) \
+     (((IMG)->height + (IMG)->margin) * (IMG)->ascent / 100.0)
+
+/* Value is a pointer to the image with id ID on frame F, or null if
+   no image with that id exists.  */
+
+#define IMAGE_FROM_ID(F, ID)					\
+     (((ID) >= 0 && (ID) < (FRAME_X_IMAGE_CACHE (F)->used))	\
+      ? FRAME_X_IMAGE_CACHE (F)->images[ID]			\
+      : NULL)
+
+/* Size of bucket vector of image caches.  Should be prime.  */
+
+#define IMAGE_CACHE_BUCKETS_SIZE 1001
+
+#endif /* HAVE_X_WINDOWS */
+
+
+
+/***********************************************************************
+			       Toolbars
+ ***********************************************************************/
+
+/* Enumeration defining where to find toolbar item information in
+   toolbar items vectors stored with frames.  Each toolbar item
+   occupies TOOLBAR_ITEM_NSLOTS elements in such a vector.  */
+
+enum toolbar_item_idx
+{
+  /* The key of the toolbar item.  Used to remove items when a binding
+     for `undefined' is found.  */
+  TOOLBAR_ITEM_KEY,
+
+  /* Non-nil if item is enabled.  */
+  TOOLBAR_ITEM_ENABLED_P,
+
+  /* Non-nil if item is selected (pressed).  */
+  TOOLBAR_ITEM_SELECTED_P,
+
+  /* Caption.  */
+  TOOLBAR_ITEM_CAPTION,
+
+  /* Image(s) to display.  This is either a single image specification
+     or a vector of specifications.  */
+  TOOLBAR_ITEM_IMAGES,
+
+  /* The binding.  */
+  TOOLBAR_ITEM_BINDING,
+
+  /* Button type.  One of nil, `:radio' or `:toggle'.  */
+  TOOLBAR_ITEM_TYPE,
+
+  /* Help string.  */
+  TOOLBAR_ITEM_HELP,
+
+  /* Sentinel = number of slots in toolbar_items occupied by one
+     toolbar item.  */
+  TOOLBAR_ITEM_NSLOTS
+};
+
+
+/* An enumeration for the different images that can be specified
+   for a toolbar item.  */
+
+enum toolbar_item_image
+{
+  TOOLBAR_IMAGE_ENABLED_SELECTED,
+  TOOLBAR_IMAGE_ENABLED_DESELECTED,
+  TOOLBAR_IMAGE_DISABLED_SELECTED,
+  TOOLBAR_IMAGE_DISABLED_DESELECTED
+};
+
+/* Non-zero means raise toolbar buttons when the mouse moves over them.  */
+
+extern int auto_raise_toolbar_buttons_p;
+
+/* Margin around toolbar buttons in pixels.  */
+
+extern int toolbar_button_margin;
+
+/* Thickness of relief to draw around toolbar buttons.  */
+
+extern int toolbar_button_relief;
+
+
+
+/***********************************************************************
+			 Function Prototypes
+ ***********************************************************************/
+
+/* Defined in xdisp.c */
+
+int try_window P_ ((Lisp_Object, struct text_pos));
+void window_box P_ ((struct window *, int, int *, int *, int *, int *));
+int window_box_height P_ ((struct window *));
+int window_text_bottom_y P_ ((struct window *));
+int window_box_width P_ ((struct window *, int));
+int window_box_left P_ ((struct window *, int));
+int window_box_right P_ ((struct window *, int));
+void window_box_edges P_ ((struct window *, int, int *, int *, int *, int *));
+void mark_window_display_accurate P_ ((Lisp_Object, int));
+void redisplay_preserve_echo_area P_ ((void));
+void set_cursor_from_row P_ ((struct window *, struct glyph_row *,
+			      struct glyph_matrix *, int, int, int, int));
+void init_iterator P_ ((struct it *, struct window *, int,
+			int, struct glyph_row *, enum face_id));
+void init_iterator_to_row_start P_ ((struct it *, struct window *,
+				     struct glyph_row *));
+int get_next_display_element P_ ((struct it *));
+void set_iterator_to_next P_ ((struct it *));
+void produce_glyphs P_ ((struct it *));
+void produce_special_glyphs P_ ((struct it *, enum display_element_type));
+void start_display P_ ((struct it *, struct window *, struct text_pos));
+void move_it_to P_ ((struct it *, int, int, int, int, int));
+void move_it_vertically P_ ((struct it *, int));
+void move_it_by_lines P_ ((struct it *, int, int));
+int frame_mode_line_height P_ ((struct frame *));
+void highlight_trailing_whitespace P_ ((struct frame *, struct glyph_row *));
+int toolbar_item_info P_ ((struct frame *, struct glyph *, int *));
+extern Lisp_Object Qtoolbar;
+extern int redisplaying_p;
+
+/* Defined in sysdep.c */
+
+void get_frame_size P_ ((int *, int *));
+void request_sigio P_ ((void));
+void unrequest_sigio P_ ((void));
+int tabs_safe_p P_ ((void));
+void init_baud_rate P_ ((void));
+void init_sigio P_ ((int));
+
+/* Defined in xface.c */
+
+char *x_charset_registry P_ ((int));
+void clear_face_cache P_ ((int));
+void unload_color P_ ((struct frame *, unsigned long));
+int frame_update_line_height P_ ((struct frame *));
+int ascii_face_of_lisp_face P_ ((struct frame *, int));
+void prepare_face_for_display P_ ((struct frame *, struct face *));
+int face_suitable_for_iso8859_1_p P_ ((struct face *));
+int xstricmp P_ ((unsigned char *, unsigned char *));
+int lookup_face P_ ((struct frame *, Lisp_Object *, int));
+int face_suitable_for_charset_p P_ ((struct face *, int));
+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));
+void init_frame_faces P_ ((struct frame *));
+void free_frame_faces P_ ((struct frame *));
+void recompute_basic_faces P_ ((struct frame *));
+int face_at_buffer_position P_ ((struct window *, int, int, int, int *,
+				 int, int));
+int face_at_string_position P_ ((struct window *, Lisp_Object,
+				 int, int, int, int, int *, enum face_id));
+int compute_char_face P_ ((struct frame *, int, Lisp_Object));
+void free_all_realized_faces P_ ((Lisp_Object));
+extern Lisp_Object Qforeground_color, Qbackground_color;
+
+/* Defined in xfns.c  */
+
+#ifdef HAVE_X_WINDOWS 
+
+int x_screen_planes P_ ((struct frame *));
+void x_implicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+struct image_cache *make_image_cache P_ ((void));
+void free_image_cache P_ ((struct frame *));
+void clear_image_cache P_ ((struct frame *, int));
+void forall_images_in_image_cache P_ ((struct frame *,
+				       void (*) P_ ((struct image *))));
+int valid_image_p P_ ((Lisp_Object));
+void prepare_image_for_display P_ ((struct frame *, struct image *));
+int lookup_image P_ ((struct frame *, Lisp_Object));
+extern struct frame *tip_frame;
+extern Window tip_window;
+EXFUN (Fx_show_tip, 4);
+EXFUN (Fx_hide_tip, 0);
+EXFUN (Fx_show_busy_cursor, 0);
+EXFUN (Fx_hide_busy_cursor, 1);
+extern int inhibit_busy_cursor;
+extern int display_busy_cursor_p;
+
+#endif /* HAVE_X_WINDOWS */
+
+
+/* Defined in xmenu.c  */
+
+int popup_activated P_ ((void));
+
+/* Defined in dispnw.c  */
+
+Lisp_Object mode_line_string P_ ((struct window *, int, int, int, int *));
 extern void redraw_frame P_ ((struct frame *));
 extern void redraw_garbaged_frames P_ ((void));
-extern void free_frame_glyphs P_ ((struct frame *, struct frame_glyphs *));
-extern void remake_frame_glyphs P_ ((struct frame *));
 extern void cancel_line P_ ((int, struct frame *));
-extern void clear_frame_records P_ ((struct frame *));
 extern void init_desired_glyphs P_ ((struct frame *));
-extern void get_display_line P_ ((struct frame *, int, int));
 extern int scroll_frame_lines P_ ((struct frame *, int, int, int, int));
-extern void preserve_other_columns P_ ((struct window *));
-extern void adjust_window_charstarts P_ ((struct window *, int, int));
-extern void verify_charstarts P_ ((struct window *));
-extern void cancel_my_columns P_ ((struct window *));
 extern int direct_output_for_insert P_ ((int));
 extern int direct_output_forward_char P_ ((int));
 extern int update_frame P_ ((struct frame *, int, int));
-extern void quit_error_check P_ ((void));
 extern int scrolling P_ ((struct frame *));
-extern int buffer_posn_from_coords P_ ((struct window *, int, int));
 extern void do_pending_window_change P_ ((void));
 extern void change_frame_size P_ ((struct frame *, int, int, int, int));
 extern void bitch_at_user P_ ((void));
+void adjust_glyphs P_ ((struct frame *));
+void free_glyphs P_ ((struct frame *));
+void free_window_matrices P_ ((struct window *));
+void check_glyph_memory P_ ((void));
+void mirrored_line_dance P_ ((struct glyph_matrix *, int, int, int *, char *));
+void clear_glyph_matrix P_ ((struct glyph_matrix *));
+void clear_current_matrices P_ ((struct frame *f));
+void clear_desired_matrices P_ ((struct frame *));
+void shift_glyph_matrix P_ ((struct window *, struct glyph_matrix *,
+			     int, int, int));
+void rotate_matrix P_ ((struct glyph_matrix *, int, int, int));
+void increment_glyph_matrix_buffer_positions P_ ((struct glyph_matrix *,
+						  int, int, int, int));
+void blank_row P_ ((struct window *, struct glyph_row *, int));
+void increment_glyph_row_buffer_positions P_ ((struct glyph_row *, int, int));
+void enable_glyph_matrix_rows P_ ((struct glyph_matrix *, int, int, int));
+void clear_glyph_row P_ ((struct glyph_row *));
+void prepare_desired_row P_ ((struct glyph_row *));
+int line_hash_code P_ ((struct glyph_row *));
+void set_window_update_flags P_ ((struct window *, int));
+void write_glyphs P_ ((struct glyph *, int));
+void insert_glyphs P_ ((struct glyph *, int));
+void redraw_frame P_ ((struct frame *));
+void redraw_garbaged_frames P_ ((void));
+int scroll_cost P_ ((struct frame *, int, int, int));
+int direct_output_for_insert P_ ((int));
+int direct_output_forward_char P_ ((int));
+int update_frame P_ ((struct frame *, int, int));
+void update_single_window P_ ((struct window *, int));
+int scrolling P_ ((struct frame *));
+int buffer_posn_from_coords P_ ((struct window *, int *, int *));
+void do_pending_window_change P_ ((void));
+void change_frame_size P_ ((struct frame *, int, int, int, int));
+void bitch_at_user P_ ((void));
+Lisp_Object sit_for P_ ((int, int, int, int, int));
+void init_display P_ ((void));
+void syms_of_display P_ ((void));
 
 /* Defined in term.c */
+
 extern void ring_bell P_ ((void));
 extern void set_terminal_modes P_ ((void));
 extern void reset_terminal_modes P_ ((void));
@@ -222,13 +2172,9 @@
 extern void turn_off_highlight P_ ((void));
 extern void background_highlight P_ ((void));
 extern void reassert_line_highlight P_ ((int, int));
-extern void change_line_highlight P_ ((int, int, int));
-extern void cursor_to P_ ((int, int));
 extern void clear_frame P_ ((void));
 extern void clear_end_of_line P_ ((int));
 extern void clear_end_of_line_raw P_ ((int));
-extern void write_glyphs P_ ((GLYPH *, int));
-extern void insert_glyphs P_ ((GLYPH *, int));
 extern void delete_glyphs P_ ((int));
 extern void ins_del_lines P_ ((int, int));
 extern int string_cost P_ ((char *));
@@ -236,12 +2182,17 @@
 extern void calculate_costs P_ ((struct frame *));
 extern void term_init P_ ((char *));
 extern void fatal P_ ((/* char *, ... */));
+void cursor_to P_ ((int, int));
+void change_line_highlight P_ ((int, int, int, int));
 
 /* Defined in scroll.c */
+
 extern int scrolling_max_lines_saved P_ ((int, int, int *, int *, int *));
 extern int scroll_cost P_ ((struct frame *, int, int, int));
 extern void do_line_insertion_deletion_costs P_ ((struct frame *, char *,
 						  char *, char *, char *,
 						  char *, char *, int));
-
-#endif /* not _DISPEXTERN_H_ */
+void scrolling_1 P_ ((struct frame *, int, int, int, int *, int *, int *,
+		      int *, int));
+
+#endif /* not DISPEXTERN_H_INCLUDED */
--- a/src/dispnew.c	Wed Jul 21 21:43:52 1999 +0000
+++ b/src/dispnew.c	Wed Jul 21 21:43:52 1999 +0000
@@ -19,11 +19,8 @@
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 #include <signal.h>
-
 #include <config.h>
-
 #include <stdio.h>
 #include <ctype.h>
 
@@ -57,29 +54,36 @@
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
-#endif	/* HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS */
 
 #ifdef HAVE_NTGUI
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
-/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
+/* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
+
 #include "systime.h"
-
 #include <errno.h>
 
+/* To get the prototype for `sleep'.  */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #define min(a, b) ((a) < (b) ? (a) : (b))
-#define minmax(floor, val, ceil) \
-	((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
 
 /* Get number of chars of output now in the buffer of a stdio stream.
-   This ought to be built in in stdio, but it isn't.
-   Some s- files override this because their stdio internals differ.  */
+   This ought to be built in in stdio, but it isn't.  Some s- files
+   override this because their stdio internals differ.  */
+
 #ifdef __GNU_LIBRARY__
-/* The s- file might have overridden the definition with one that works for
-   the system's C library.  But we are using the GNU C library, so this is
-   the right definition for every system.  */
+
+/* The s- file might have overridden the definition with one that
+   works for the system's C library.  But we are using the GNU C
+   library, so this is the right definition for every system.  */
+
 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
 #else
@@ -90,21 +94,98 @@
 #ifndef PENDING_OUTPUT_COUNT
 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
 #endif
-#endif
-
-static void change_frame_size_1 ();
+#endif /* not __GNU_LIBRARY__ */
+
+
+/* Structure to pass dimensions around.  Used for character bounding
+   boxes, glyph matrix dimensions and alike.  */
+
+struct dim
+{
+  int width;
+  int height;
+};
+
+
+/* Function prototypes.  */
+
+static int count_blanks P_ ((struct glyph *, int));
+static int count_match P_ ((struct glyph *, struct glyph *,
+			    struct glyph *, struct glyph *));
+static unsigned line_draw_cost P_ ((struct glyph_matrix *, int));
+static void update_frame_line P_ ((struct frame *, int));
+static struct dim allocate_matrices_for_frame_redisplay
+     P_ ((Lisp_Object, int, int, struct dim, int, int *));
+static void allocate_matrices_for_window_redisplay P_ ((struct window *,
+							struct dim));
+static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim));
+static void adjust_frame_glyphs P_ ((struct frame *));
+struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *));
+static void free_glyph_matrix P_ ((struct glyph_matrix *));
+static void adjust_glyph_matrix P_ ((struct window *, struct glyph_matrix *,
+				     int, int, struct dim));
+static void change_frame_size_1 P_ ((struct frame *, int, int, int, int));
+static void swap_glyphs_in_rows P_ ((struct glyph_row *, struct glyph_row *));
+static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *));
+static int glyph_row_slice_p P_ ((struct glyph_row *, struct glyph_row *));
+static void fill_up_frame_row_with_spaces P_ ((struct glyph_row *, int));
+static void build_frame_matrix_from_window_tree P_ ((struct glyph_matrix *,
+						     struct window *));
+static void build_frame_matrix_from_leaf_window P_ ((struct glyph_matrix *,
+						     struct window *));
+static struct glyph_pool *new_glyph_pool P_ ((void));
+static void free_glyph_pool P_ ((struct glyph_pool *));
+static void adjust_frame_glyphs_initially P_ ((void));
+static void adjust_frame_message_buffer P_ ((struct frame *));
+static void adjust_decode_mode_spec_buffer P_ ((struct frame *));
+static void fill_up_glyph_row_with_spaces P_ ((struct glyph_row *));
+static void build_frame_matrix P_ ((struct frame *));
+void clear_current_matrices P_ ((struct frame *));
+void scroll_glyph_matrix_range P_ ((struct glyph_matrix *, int, int,
+				    int, int));
+static void clear_window_matrices P_ ((struct window *, int));
+static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int));
+static int scrolling_window P_ ((struct window *, int));
+static void update_window_line P_ ((struct window *, int));
+static void update_marginal_area P_ ((struct window *, int, int));
+static void update_text_area P_ ((struct window *, int));
+static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *,
+			      int));
+static void mirror_make_current P_ ((struct window *, int));
+void check_window_matrix_pointers P_ ((struct window *));
+static void check_matrix_pointers P_ ((struct glyph_matrix *,
+				       struct glyph_matrix *));
+static void mirror_line_dance P_ ((struct window *, int, int, int *, char *));
+static int update_window_tree P_ ((struct window *, int));
+static int update_window P_ ((struct window *, int));
+static int update_frame_1 P_ ((struct frame *, int, int));
+static void set_window_cursor_after_update P_ ((struct window *));
+static int row_equal_p P_ ((struct window *, struct glyph_row *,
+			    struct glyph_row *));
+static void adjust_frame_glyphs_for_window_redisplay P_ ((struct frame *));
+static void adjust_frame_glyphs_for_frame_redisplay P_ ((struct frame *));
+static void reverse_rows P_ ((struct glyph_matrix *, int, int));
+static int margin_glyphs_to_reserve P_ ((struct window *, int, Lisp_Object));
+
+
+
+/* Non-zero means don't pause redisplay for pending input.  (This is
+   for debugging and for a future implementation of EDT-like
+   scrolling.  */
+
+int redisplay_dont_pause;
 
 /* Nonzero upon entry to redisplay means do not assume anything about
    current contents of actual terminal frame; clear and redraw it.  */
 
 int frame_garbaged;
 
-/* Nonzero means last display completed.  Zero means it was preempted. */
+/* Nonzero means last display completed.  Zero means it was preempted.  */
 
 int display_completed;
 
-/* Lisp variable visible-bell; enables use of screen-flash
-   instead of audible bell.  */
+/* Lisp variable visible-bell; enables use of screen-flash instead of
+   audible bell.  */
 
 int visible_bell;
 
@@ -116,19 +197,23 @@
 
 int baud_rate;
 
-/* nil or a symbol naming the window system under which emacs is
-   running ('x is the only current possibility).  */
+/* Either nil or a symbol naming the window system under which Emacs
+   is running.  */
 
 Lisp_Object Vwindow_system;
 
 /* Version number of X windows: 10, 11 or nil.  */
+
 Lisp_Object Vwindow_system_version;
 
-/* Vector of glyph definitions.  Indexed by glyph number,
-   the contents are a string which is how to output the glyph.
+/* Vector of glyph definitions.  Indexed by glyph number, the contents
+   are a string which is how to output the glyph.
 
    If Vglyph_table is nil, a glyph is output by using its low 8 bits
-   as a character code.  */
+   as a character code.
+
+   This is an obsolete feature that is no longer used.  The variable
+   is retained for compatibility.  */
 
 Lisp_Object Vglyph_table;
 
@@ -136,417 +221,107 @@
 
 Lisp_Object Vstandard_display_table;
 
-/* Nonzero means reading single-character input with prompt
-   so put cursor on minibuffer after the prompt.
-   positive means at end of text in echo area;
-   negative means at beginning of line.  */
+/* Nonzero means reading single-character input with prompt so put
+   cursor on mini-buffer after the prompt.  positive means at end of
+   text in echo area; negative means at beginning of line.  */
+
 int cursor_in_echo_area;
 
 Lisp_Object Qdisplay_table;
+
 
-/* The currently selected frame.
-   In a single-frame version, this variable always holds the address of
-   the_only_frame.  */
-
-FRAME_PTR selected_frame;
-
-/* A frame which is not just a minibuffer, or 0 if there are no such
+/* The currently selected frame.  In a single-frame version, this
+   variable always holds the address of the_only_frame.  */
+
+struct frame *selected_frame;
+
+/* A frame which is not just a mini-buffer, or 0 if there are no such
    frames.  This is usually the most recent such frame that was
    selected.  In a single-frame version, this variable always holds
    the address of the_only_frame.  */
-FRAME_PTR last_nonminibuf_frame;
-
-/* This is a vector, made larger whenever it isn't large enough,
-   which is used inside `update_frame' to hold the old contents
-   of the FRAME_PHYS_LINES of the frame being updated.  */
-struct frame_glyphs **ophys_lines;
-/* Length of vector currently allocated.  */
-int ophys_lines_length;
-
-FILE *termscript;	/* Stdio stream being used for copy of all output.  */
-
-struct cm Wcm;		/* Structure for info on cursor positioning */
-
-int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */
-
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
-  "Clear frame FRAME and output again what is supposed to appear on it.")
-  (frame)
-     Lisp_Object frame;
-{
-  FRAME_PTR f;
-
-  CHECK_LIVE_FRAME (frame, 0);
-  f = XFRAME (frame);
-
-  /* Erase the frame and its glyph records--if it has any records.
-     It may have none, in the case of the terminal frame
-     that initially exists but is never used
-     when Emacs is using a window system.  */
-  if (FRAME_CURRENT_GLYPHS (f) != 0)
-    {
-      update_begin (f);
-      if (FRAME_MSDOS_P (f))
-	set_terminal_modes ();
-      clear_frame ();
-      clear_frame_records (f);
-      update_end (f);
-      fflush (stdout);
-    }
-
-  windows_or_buffers_changed++;
-  /* Mark all windows as INaccurate,
-     so that every window will have its redisplay done.  */
-  mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
-  f->garbaged = 0;
-  return Qnil;
-}
-
-void
-redraw_frame (f)
-     FRAME_PTR f;
-{
-  Lisp_Object frame;
-  XSETFRAME (frame, f);
-  Fredraw_frame (frame);
-}
-
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear and redisplay all visible frames.")
-  ()
-{
-  Lisp_Object tail, frame;
-
-  FOR_EACH_FRAME (tail, frame)
-    if (FRAME_VISIBLE_P (XFRAME (frame)))
-      Fredraw_frame (frame);
-
-  return Qnil;
-}
-
-/* This is used when frame_garbaged is set.
-   Redraw the individual frames marked as garbaged.  */
-
-void
-redraw_garbaged_frames ()
-{
-  Lisp_Object tail, frame;
-
-  FOR_EACH_FRAME (tail, frame)
-    if (FRAME_VISIBLE_P (XFRAME (frame))
-	&& FRAME_GARBAGED_P (XFRAME (frame)))
-      Fredraw_frame (frame);
-}
-
-
-static struct frame_glyphs *
-make_frame_glyphs (frame, empty)
-     register FRAME_PTR frame;
-     int empty;
-{
-  register int i;
-  register int width = FRAME_WINDOW_WIDTH (frame);
-  register int height = FRAME_HEIGHT (frame);
-  register struct frame_glyphs *new
-    = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
-
-  SET_GLYPHS_FRAME (new, frame);
-  new->height = height;
-  new->width = width;
-  new->used = (int *) xmalloc (height * sizeof (int));
-  new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
-  new->charstarts = (int **) xmalloc (height * sizeof (int *));
-  new->highlight = (char *) xmalloc (height * sizeof (char));
-  new->enable = (char *) xmalloc (height * sizeof (char));
-  bzero (new->enable, height * sizeof (char));
-  new->bufp = (int *) xmalloc (height * sizeof (int));
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (frame))
-    {
-      new->top_left_x = (short *) xmalloc (height * sizeof (short));
-      new->top_left_y = (short *) xmalloc (height * sizeof (short));
-      new->pix_width = (short *) xmalloc (height * sizeof (short));
-      new->pix_height = (short *) xmalloc (height * sizeof (short));
-      new->max_ascent = (short *) xmalloc (height * sizeof (short));
-    }
-#endif /* HAVE_WINDOW_SYSTEM */
-
-  if (empty)
-    {
-      /* Make the buffer used by decode_mode_spec.  This buffer is also
-         used as temporary storage when updating the frame.  See scroll.c. */
-      unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
-      unsigned int total_charstarts = (width + 2) * sizeof (int);
-
-      new->total_contents = (GLYPH *) xmalloc (total_glyphs);
-      bzero (new->total_contents, total_glyphs);
-
-      new->total_charstarts = (int *) xmalloc (total_charstarts);
-      bzero (new->total_charstarts, total_charstarts);
-    }
-  else
-    {
-      unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
-
-      new->total_contents = (GLYPH *) xmalloc (total_glyphs);
-      bzero (new->total_contents, total_glyphs);
-      for (i = 0; i < height; i++)
-	new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
-
-      if (!FRAME_TERMCAP_P (frame))
-	{
-	  unsigned int total_charstarts = height * (width + 2) * sizeof (int);
-
-	  new->total_charstarts = (int *) xmalloc (total_charstarts);
-	  bzero (new->total_charstarts, total_charstarts);
-	  for (i = 0; i < height; i++)
-	    new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
-	}
-      else
-	{
-	  /* Without a window system, we don't really need charstarts.
-	     So use a small amount of space to make enough data structure
-	     to prevent crashes in display_text_line.  */
-	  new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
-	  for (i = 0; i < height; i++)
-	    new->charstarts[i] = new->total_charstarts;
-	}
-    }
-
-  return new;
-}
-
-void
-free_frame_glyphs (frame, glyphs)
-     FRAME_PTR frame;
-     struct frame_glyphs *glyphs;
-{
-  if (glyphs->total_contents)
-    xfree (glyphs->total_contents);
-  if (glyphs->total_charstarts)
-    xfree (glyphs->total_charstarts);
-
-  xfree (glyphs->used);
-  xfree (glyphs->glyphs);
-  xfree (glyphs->highlight);
-  xfree (glyphs->enable);
-  xfree (glyphs->bufp);
-  if (glyphs->charstarts)
-    xfree (glyphs->charstarts);
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (frame))
-    {
-      xfree (glyphs->top_left_x);
-      xfree (glyphs->top_left_y);
-      xfree (glyphs->pix_width);
-      xfree (glyphs->pix_height);
-      xfree (glyphs->max_ascent);
-    }
-#endif /* HAVE_WINDOW_SYSTEM */
-
-  xfree (glyphs);
-}
-
-void
-remake_frame_glyphs (frame)
-     FRAME_PTR frame;
-{
-  if (FRAME_CURRENT_GLYPHS (frame))
-    free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
-  if (FRAME_DESIRED_GLYPHS (frame))
-    free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
-  if (FRAME_TEMP_GLYPHS (frame))
-    free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
-
-  if (FRAME_MESSAGE_BUF (frame))
-    {
-      /* Reallocate the frame's message buffer; remember that
-	 echo_area_glyphs may be pointing here.  */
-      char *old_message_buf = FRAME_MESSAGE_BUF (frame);
-
-      FRAME_MESSAGE_BUF (frame)
-	= (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
-			     FRAME_MESSAGE_BUF_SIZE (frame) + 1);
-
-      if (echo_area_glyphs == old_message_buf)
-	echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
-      if (previous_echo_glyphs == old_message_buf)
-	previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
-    }
-  else
-    FRAME_MESSAGE_BUF (frame)
-      = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame) + 1);
-
-  FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
-  FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
-  FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
-  if (FRAME_WINDOW_P (frame) || frame == selected_frame)
-    SET_FRAME_GARBAGED (frame);
-}
-
-/* Return the hash code of contents of line VPOS in frame-matrix M.  */
-
-static int
-line_hash_code (m, vpos)
-     register struct frame_glyphs *m;
-     int vpos;
-{
-  register GLYPH *body, *end;
-  register int h = 0;
-
-  if (!m->enable[vpos])
-    return 0;
-
-  /* Give all highlighted lines the same hash code
-     so as to encourage scrolling to leave them in place.  */
-  if (m->highlight[vpos])
-    return -1;
-
-  body = m->glyphs[vpos];
-
-  if (must_write_spaces)
-    while (1)
-      {
-	GLYPH g = *body++;
-
-	if (g == 0)
-	  break;
-	h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
-      }
-  else
-    while (1)
-      {
-	GLYPH g = *body++;
-
-	if (g == 0)
-	  break;
-	h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
-      }
-
-  if (h)
-    return h;
-  return 1;
-}
-
-/* Return number of characters in line in M at vpos VPOS,
-   except don't count leading and trailing spaces
-   unless the terminal requires those to be explicitly output.  */
-
-static unsigned int
-line_draw_cost (m, vpos)
-     struct frame_glyphs *m;
-     int vpos;
-{
-  register GLYPH *beg = m->glyphs[vpos];
-  register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
-  register int i;
-  register int tlen = GLYPH_TABLE_LENGTH;
-  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-
-  /* Ignore trailing and leading spaces if we can.  */
-  if (!must_write_spaces)
-    {
-      while ((end != beg) && (*end == SPACEGLYPH))
-	--end;
-      if (end == beg)
-	return (0); /* All blank line. */
-
-      while (*beg == SPACEGLYPH)
-	++beg;
-    }
-
-  /* If we don't have a glyph-table, each glyph is one character,
-     so return the number of glyphs.  */
-  if (tbase == 0)
-    return end - beg;
-
-  /* Otherwise, scan the glyphs and accumulate their total size in I.  */
-  i = 0;
-  while ((beg <= end) && *beg)
-    {
-      register GLYPH g = *beg++;
-
-      if (GLYPH_SIMPLE_P (tbase, tlen, g))
-	i += 1;
-      else
-	i += GLYPH_LENGTH (tbase, g);
-    }
-  return i;
-}
-
-/* The functions on this page are the interface from xdisp.c to redisplay.
-
-   The only other interface into redisplay is through setting
-   FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
-   and SET_FRAME_GARBAGED (frame).  */
-
-/* cancel_line eliminates any request to display a line at position `vpos' */
-
-void
-cancel_line (vpos, frame)
-     int vpos;
-     register FRAME_PTR frame;
-{
-  FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
-}
-
-void
-clear_frame_records (frame)
-     register FRAME_PTR frame;
-{
-  bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
-}
-
-/* Clear out all display lines for a coming redisplay.  */
-
-void
-init_desired_glyphs (frame)
-     register FRAME_PTR frame;
-{
-  register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
-  int vpos;
-  int height = FRAME_HEIGHT (frame);
-
-  for (vpos = 0; vpos < height; vpos++)
-    desired_glyphs->enable[vpos] = 0;
-}
-
-/* Prepare to display on line VPOS starting at HPOS within it.  */
-
-void
-get_display_line (frame, vpos, hpos)
-     register FRAME_PTR frame;
-     int vpos;
-     register int hpos;
-{
-  register struct frame_glyphs *glyphs;
-  register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
-  register GLYPH *p;
-
-  if (vpos < 0)
-    abort ();
-
-  if (! desired_glyphs->enable[vpos])
-    {
-      desired_glyphs->used[vpos] = 0;
-      desired_glyphs->highlight[vpos] = 0;
-      desired_glyphs->enable[vpos] = 1;
-    }
-
-  if (hpos > desired_glyphs->used[vpos])
-    {
-      GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
-      GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
-
-      desired_glyphs->used[vpos] = hpos;
-      while (g != end)
-	*g++ = SPACEGLYPH;
-    }
-}
-
-/* Like bcopy except never gets confused by overlap.  */
+
+struct frame *last_nonminibuf_frame;
+
+/* Stdio stream being used for copy of all output.  */
+
+FILE *termscript;
+
+/* Structure for info on cursor positioning.  */
+
+struct cm Wcm;
+
+/* 1 means SIGWINCH happened when not safe.  */
+
+int delayed_size_change;
+
+/* 1 means glyph initialization has been completed at startup.  */
+
+static int glyphs_initialized_initially_p;
+
+/* Updated window if != 0.  Set by update_window.  */
+
+struct window *updated_window;
+
+/* Glyph row updated in update_window_line, and area that is updated.  */
+
+struct glyph_row *updated_row;
+int updated_area;
+
+/* A glyph for a space.  */
+
+struct glyph space_glyph;
+
+/* Non-zero means update has been performed directly, so that there's
+   no need for redisplay_internal to do much work.  Set by
+   direct_output_for_insert.  */
+
+int redisplay_performed_directly_p;
+
+/* Counts of allocated structures.  These counts serve to diagnose
+   memory leaks and double frees.  */
+
+int glyph_matrix_count;
+int glyph_pool_count;
+
+/* If non-null, the frame whose frame matrices are manipulated.  If
+   null, window matrices are worked on.  */
+
+static struct frame *frame_matrix_frame;
+
+/* Current interface for window-based redisplay.  Set from init_xterm.
+   A null value means we are not using window-based redisplay.  */
+
+struct redisplay_interface *rif;
+
+/* Non-zero means that fonts have been loaded since the last glyph
+   matrix adjustments.  Redisplay must stop, and glyph matrices must
+   be adjusted when this flag becomes non-zero during display.  The
+   reason fonts can be loaded so late is that fonts of fontsets are
+   loaded on demand.  */
+
+int fonts_changed_p;
+
+/* Convert vpos and hpos from frame to window and vice versa. 
+   This may only be used for terminal frames.  */
+
+#if GLYPH_DEBUG
+
+static int window_to_frame_vpos P_ ((struct window *, int));
+static int window_to_frame_hpos P_ ((struct window *, int));
+#define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
+#define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
+
+#else /* GLYPH_DEBUG == 0 */
+
+#define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top))
+#define WINDOW_TO_FRAME_HPOS(W, HPOS) ((HPOS) + XFASTINT ((W)->left))
+
+#endif /* GLYPH_DEBUG == 0 */
+
+
+/* Like bcopy except never gets confused by overlap.  Let this be the
+   first function defined in this file, or change emacs.c where the
+   address of this function is used.  */
 
 void
 safe_bcopy (from, to, size)
@@ -594,635 +369,3906 @@
 	    }
 
 	  /* If SIZE wasn't a multiple of TO - FROM, there will be a
-	     little left over.  The amount left over is
-	     (endt + (to - from)) - to, which is endt - from.  */
+	     little left over.  The amount left over is (endt + (to -
+	     from)) - to, which is endt - from.  */
 	  bcopy (from, to, endt - from);
 	}
     }
 }     
 
-/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
-   DISTANCE may be negative.  */
+
+
+/***********************************************************************
+			    Glyph Matrices
+ ***********************************************************************/
+
+/* Allocate and return a glyph_matrix structure.  POOL is the glyph
+   pool from which memory for the matrix should be allocated, or null
+   for window-based redisplay where no glyph pools are used.  The
+   member `pool' of the glyph matrix structure returned is set to
+   POOL, the structure is otherwise zeroed.  */
+
+struct glyph_matrix *
+new_glyph_matrix (pool)
+     struct glyph_pool *pool;
+{
+  struct glyph_matrix *result;
+
+  /* Allocate and clear.  */
+  result = (struct glyph_matrix *) xmalloc (sizeof *result);
+  bzero (result, sizeof *result);
+
+  /* Increment number of allocated matrices.  This count is used
+     to detect memory leaks.  */
+  ++glyph_matrix_count;
+
+  /* Set pool and return.  */
+  result->pool = pool;
+  return result;
+}
+
+
+/* Free glyph matrix MATRIX.  Passing in a null MATRIX is allowed.
+
+   The global counter glyph_matrix_count is decremented when a matrix
+   is freed.  If the count gets negative, more structures were freed
+   than allocated, i.e. one matrix was freed more than once or a bogus
+   pointer was passed to this function.
+ 
+   If MATRIX->pool is null, this means that the matrix manages its own
+   glyph memory---this is done for matrices on X frames.  Freeing the
+   matrix also frees the glyph memory in this case.  */
+
+static void
+free_glyph_matrix (matrix)
+     struct glyph_matrix *matrix;
+{
+  if (matrix)
+    {
+      int i;
+
+      /* Detect the case that more matrices are freed than were
+	 allocated.  */
+      if (--glyph_matrix_count < 0)
+	abort ();
+
+      /* Free glyph memory if MATRIX owns it.  */
+      if (matrix->pool == NULL)
+	for (i = 0; i < matrix->rows_allocated; ++i)
+	  xfree (matrix->rows[i].glyphs[LEFT_MARGIN_AREA]);
+      
+      /* Free row structures and the matrix itself.  */
+      xfree (matrix->rows);
+      xfree (matrix);
+    }
+}
+
+
+/* Return the number of glyphs to reserve for a marginal area of
+   window W.  TOTAL_GLYPHS is the number of glyphs in a complete
+   display line of window W.  MARGIN gives the width of the marginal
+   area in canonical character units.  MARGIN should be an integer
+   or a float.  */
+
+static int
+margin_glyphs_to_reserve (w, total_glyphs, margin)
+     struct window *w;
+     int total_glyphs;
+     Lisp_Object margin;
+{
+  int n;
+
+  if (NUMBERP (margin))
+    {
+      int width = XFASTINT (w->width);
+      double d = max (0, XFLOATINT (margin));
+      d = min (width / 2 - 1, d);
+      n = (int) ((double) total_glyphs / width * d);
+    }
+  else
+    n = 0;
+
+  return n;
+}
+
+
+/* Adjust glyph matrix MATRIX on window W or on a frame to changed
+   window sizes.
+
+   W is null if the function is called for a frame glyph matrix.
+   Otherwise it is the window MATRIX is a member of.  X and Y are the
+   indices of the first column and row of MATRIX within the frame
+   matrix, if such a matrix exists.  They are zero for purely
+   window-based redisplay.  DIM is the needed size of the matrix.
+
+   In window-based redisplay, where no frame matrices exist, glyph
+   matrices manage their own glyph storage.  Otherwise, they allocate
+   storage from a common frame glyph pool which can be found in
+   MATRIX->pool.
+
+   The reason for this memory management strategy is to avoid complete
+   frame redraws if possible.  When we allocate from a common pool, a
+   change of the location or size of a sub-matrix within the pool
+   requires a complete redisplay of the frame because we cannot easily
+   make sure that the current matrices of all windows still agree with
+   what is displayed on the screen.  While this is usually fast, it
+   leads to screen flickering.  */
+
+static void
+adjust_glyph_matrix (w, matrix, x, y, dim)
+     struct window *w;
+     struct glyph_matrix *matrix;
+     int x, y;
+     struct dim dim;
+{
+  int i;
+  int new_rows;
+  int marginal_areas_changed_p = 0;
+  int top_line_changed_p = 0;
+  int top_line_p = 0;
+  int left = -1, right = -1;
+  int window_x, window_y, window_width, window_height;
+
+  /* See if W had a top line that has disappeared now, or vice versa.  */
+  if (w)
+    {
+      top_line_p = WINDOW_WANTS_TOP_LINE_P (w);
+      top_line_changed_p = top_line_p != matrix->top_line_p;
+    }
+  matrix->top_line_p = top_line_p;
+
+  /* Do nothing if MATRIX' size, position, vscroll, and marginal areas
+     haven't changed.  This optimization is important because preserving
+     the matrix means preventing redisplay.  */
+  if (matrix->pool == NULL)
+    {
+      window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+      left = margin_glyphs_to_reserve (w, dim.width, w->left_margin_width);
+      right = margin_glyphs_to_reserve (w, dim.width, w->right_margin_width);
+      xassert (left >= 0 && right >= 0);
+      marginal_areas_changed_p = (left != matrix->left_margin_glyphs
+				  || right != matrix->right_margin_glyphs);
+
+      if (!marginal_areas_changed_p
+	  && !fonts_changed_p
+	  && !top_line_changed_p
+	  && matrix->window_top_y == XFASTINT (w->top)
+	  && matrix->window_height == window_height
+	  && matrix->window_vscroll == w->vscroll
+	  && matrix->window_width == window_width)
+	return;
+    }
+  
+  /* Enlarge MATRIX->rows if necessary.  New rows are cleared.  */
+  if (matrix->rows_allocated < dim.height)
+    {
+      int size = dim.height * sizeof (struct glyph_row);
+      new_rows = dim.height - matrix->rows_allocated;
+      matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size);
+      bzero (matrix->rows + matrix->rows_allocated,
+	     new_rows * sizeof *matrix->rows);
+      matrix->rows_allocated = dim.height;
+    }
+  else
+    new_rows = 0;
+
+  /* If POOL is not null, MATRIX is a frame matrix or a window matrix
+     on a frame not using window-based redisplay.  Set up pointers for
+     each row into the glyph pool.  */
+  if (matrix->pool)
+    {
+      xassert (matrix->pool->glyphs);
+      
+      if (w)
+	{
+	  left = margin_glyphs_to_reserve (w, dim.width,
+					   w->left_margin_width);
+	  right = margin_glyphs_to_reserve (w, dim.width,
+					    w->right_margin_width);
+	}
+      else
+	left = right = 0;
+      
+      for (i = 0; i < dim.height; ++i)
+	{
+	  struct glyph_row *row = &matrix->rows[i];
+	  
+	  row->glyphs[LEFT_MARGIN_AREA] 
+	    = (matrix->pool->glyphs
+	       + (y + i) * matrix->pool->ncolumns
+	       + x);
+	  
+	  if (w == NULL
+	      || row == matrix->rows + dim.height - 1
+	      || (row == matrix->rows && matrix->top_line_p))
+	    {
+	      row->glyphs[TEXT_AREA]
+		= row->glyphs[LEFT_MARGIN_AREA];
+	      row->glyphs[RIGHT_MARGIN_AREA]
+		= row->glyphs[TEXT_AREA] + dim.width;
+	      row->glyphs[LAST_AREA]
+		= row->glyphs[RIGHT_MARGIN_AREA];
+	    }
+	  else
+	    {
+	      row->glyphs[TEXT_AREA]
+		= row->glyphs[LEFT_MARGIN_AREA] + left;
+	      row->glyphs[RIGHT_MARGIN_AREA]
+		= row->glyphs[TEXT_AREA] + dim.width - left - right;
+	      row->glyphs[LAST_AREA]
+		= row->glyphs[LEFT_MARGIN_AREA] + dim.width;
+	    }
+	}
+      
+      matrix->left_margin_glyphs = left;
+      matrix->right_margin_glyphs = right;
+    }
+  else
+    {
+      /* If MATRIX->pool is null, MATRIX is responsible for managing
+	 its own memory.  Allocate glyph memory from the heap.  */
+      if (dim.width > matrix->matrix_w
+	  || new_rows
+	  || top_line_changed_p
+	  || marginal_areas_changed_p)
+	{
+	  struct glyph_row *row = matrix->rows;
+	  struct glyph_row *end = row + matrix->rows_allocated;
+	  
+	  while (row < end)
+	    {
+	      row->glyphs[LEFT_MARGIN_AREA]
+		= (struct glyph *) xrealloc (row->glyphs[LEFT_MARGIN_AREA],
+					     (dim.width
+					      * sizeof (struct glyph)));
+	      
+	      /* The mode line never has marginal areas.  */
+	      if (row == matrix->rows + dim.height - 1
+		  || (row == matrix->rows && matrix->top_line_p))
+		{
+		  row->glyphs[TEXT_AREA]
+		    = row->glyphs[LEFT_MARGIN_AREA];
+		  row->glyphs[RIGHT_MARGIN_AREA]
+		    = row->glyphs[TEXT_AREA] + dim.width;
+		  row->glyphs[LAST_AREA]
+		    = row->glyphs[RIGHT_MARGIN_AREA];
+		}
+	      else
+		{
+		  row->glyphs[TEXT_AREA]
+		    = row->glyphs[LEFT_MARGIN_AREA] + left;
+		  row->glyphs[RIGHT_MARGIN_AREA]
+		    = row->glyphs[TEXT_AREA] + dim.width - left - right;
+		  row->glyphs[LAST_AREA]
+		    = row->glyphs[LEFT_MARGIN_AREA] + dim.width;
+		}
+	      ++row;
+	    }
+	}
+
+      xassert (left >= 0 && right >= 0);
+      matrix->left_margin_glyphs = left;
+      matrix->right_margin_glyphs = right;
+    }
+  
+  /* Number of rows to be used by MATRIX.  */
+  matrix->nrows = dim.height;
+
+  /* Mark rows in a current matrix of a window as not having valid
+     contents.  It's important to not do this for desired matrices.
+     When Emacs starts, it may already be building desired matrices
+     when this function runs.  */
+  if (w && matrix == w->current_matrix)
+    {
+      /* Optimize the case that only the height has changed (C-x 2,
+         upper window).  Invalidate all rows that are no longer part
+         of the window.  */
+      if (!marginal_areas_changed_p
+	  && matrix->window_top_y == XFASTINT (w->top)
+	  && matrix->window_width == window_width)
+	{
+	  i = 0;
+	  while (matrix->rows[i].enabled_p
+		 && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i)
+		     < matrix->window_height))
+	    ++i;
+
+	  /* Window end is invalid, if inside of the rows that
+	     are invalidated.  */
+	  if (INTEGERP (w->window_end_vpos)
+	      && XFASTINT (w->window_end_vpos) >= i)
+	    w->window_end_valid = Qnil;
+	  
+	  while (i < matrix->nrows)
+	    matrix->rows[i++].enabled_p = 0;
+	}
+      else
+	{
+	  for (i = 0; i < matrix->nrows; ++i)
+	    matrix->rows[i].enabled_p = 0;
+	}
+    }
+  
+  /* Remember last values to be able to optimize frame redraws.  */
+  matrix->matrix_x = x;
+  matrix->matrix_y = y;
+  matrix->matrix_w = dim.width;
+  matrix->matrix_h = dim.height;
+
+  /* Record the top y location and height of W at the time the matrix
+     was last adjusted.  This is used to optimize redisplay above.  */
+  if (w)
+    {
+      matrix->window_top_y = XFASTINT (w->top);
+      matrix->window_height = window_height;
+      matrix->window_width = window_width;
+      matrix->window_vscroll = w->vscroll;
+    }
+}
+
+
+/* Reverse the contents of rows in MATRIX between START and END.  The
+   contents of the row at END - 1 end up at START, END - 2 at START +
+   1 etc.  This is part of the implementation of rotate_matrix (see
+   below).  */
 
 static void
-rotate_vector (vector, size, distance)
-     char *vector;
-     int size;
-     int distance;
+reverse_rows (matrix, start, end)
+     struct glyph_matrix *matrix;
+     int start, end;
 {
-  char *temp = (char *) alloca (size);
-
-  if (distance < 0)
-    distance += size;
-
-  bcopy (vector, temp + distance, size - distance);
-  bcopy (vector + size - distance, temp, distance);
-  bcopy (temp, vector, size);
+  int i, j;
+
+  for (i = start, j = end - 1; i < j; ++i, --j)
+    {
+      /* Non-ISO HP/UX compiler doesn't like auto struct
+	 initialization.  */
+      struct glyph_row temp;
+      temp = matrix->rows[i];
+      matrix->rows[i] = matrix->rows[j];
+      matrix->rows[j] = temp;
+    }
 }
 
-/* Scroll lines from vpos FROM up to but not including vpos END
-   down by AMOUNT lines (AMOUNT may be negative).
-   Returns nonzero if done, zero if terminal cannot scroll them.  */
-
-int
-scroll_frame_lines (frame, from, end, amount, newpos)
-     register FRAME_PTR frame;
-     int from, end, amount, newpos;
+
+/* Rotate the contents of rows in MATRIX in the range FIRST .. LAST -
+   1 by BY positions.  BY < 0 means rotate left, i.e. towards lower
+   indices.  (Note: this does not copy glyphs, only glyph pointers in
+   row structures are moved around).
+
+   The algorithm used for rotating the vector was, I believe, first
+   described by Kernighan.  See the vector R as consisting of two
+   sub-vectors AB, where A has length BY for BY >= 0.  The result
+   after rotating is then BA.  Reverse both sub-vectors to get ArBr
+   and reverse the result to get (ArBr)r which is BA.  Similar for
+   rotating right.  */
+
+void
+rotate_matrix (matrix, first, last, by)
+     struct glyph_matrix *matrix;
+     int first, last, by;
 {
-  register int i;
-  register struct frame_glyphs *current_frame
-    = FRAME_CURRENT_GLYPHS (frame);
-  int pos_adjust;
-  int width = FRAME_WINDOW_WIDTH (frame);
-
-  if (!line_ins_del_ok)
-    return 0;
-
-  if (amount == 0)
-    return 1;
-
-  if (amount > 0)
+  if (by < 0)
+    {
+      /* Up (rotate left, i.e. towards lower indices).  */
+      by = -by;
+      reverse_rows (matrix, first, first + by);
+      reverse_rows (matrix, first + by, last);
+      reverse_rows (matrix, first, last);
+    }
+  else if (by > 0)
     {
-      update_begin (frame);
-      set_terminal_window (end + amount);
-      if (!scroll_region_ok)
-	ins_del_lines (end, -amount);
-      ins_del_lines (from, amount);
-      set_terminal_window (0);
-
-      rotate_vector (current_frame->glyphs + from,
-		     sizeof (GLYPH *) * (end + amount - from),
-		     amount * sizeof (GLYPH *));
-
-      rotate_vector (current_frame->charstarts + from,
-		     sizeof (int *) * (end + amount - from),
-		     amount * sizeof (int *));
-
-      safe_bcopy (current_frame->used + from,
-		  current_frame->used + from + amount,
-		  (end - from) * sizeof current_frame->used[0]);
-
-      safe_bcopy (current_frame->highlight + from,
-		  current_frame->highlight + from + amount,
-		  (end - from) * sizeof current_frame->highlight[0]);
-
-      safe_bcopy (current_frame->enable + from,
-		  current_frame->enable + from + amount,
-		  (end - from) * sizeof current_frame->enable[0]);
-
-      /* Adjust the lines by an amount
-	 that puts the first of them at NEWPOS.  */
-      pos_adjust = newpos - current_frame->charstarts[from + amount][0];
-
-      /* Offset each char position in the charstarts lines we moved
-	 by pos_adjust.  */
-      for (i = from + amount; i < end + amount; i++)
-	{
-	  int *line = current_frame->charstarts[i];
-	  int col;
-	  for (col = 0; col < width; col++)
-	    if (line[col] > 0)
-	      line[col] += pos_adjust;
-	}
-      for (i = from; i < from + amount; i++)
-	{
-	  int *line = current_frame->charstarts[i];
-	  int col;
-	  line[0] = -1;
-	  for (col = 0; col < width; col++)
-	    line[col] = 0;
-	}
-
-      /* Mark the lines made empty by scrolling as enabled, empty and
-	 normal video.  */
-      bzero (current_frame->used + from,
-	     amount * sizeof current_frame->used[0]);
-      bzero (current_frame->highlight + from,
-	     amount * sizeof current_frame->highlight[0]);
-      for (i = from; i < from + amount; i++)
-	{
-	  current_frame->glyphs[i][0] = '\0';
-	  current_frame->charstarts[i][0] = -1;
-	  current_frame->enable[i] = 1;
-	}
-
-      safe_bcopy (current_frame->bufp + from,
-		  current_frame->bufp + from + amount,
-		  (end - from) * sizeof current_frame->bufp[0]);
-
-#ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_WINDOW_P (frame))
-	{
-	  safe_bcopy (current_frame->top_left_x + from,
-		      current_frame->top_left_x + from + amount,
-		      (end - from) * sizeof current_frame->top_left_x[0]);
-
-	  safe_bcopy (current_frame->top_left_y + from,
-		      current_frame->top_left_y + from + amount,
-		      (end - from) * sizeof current_frame->top_left_y[0]);
-
-	  safe_bcopy (current_frame->pix_width + from,
-		      current_frame->pix_width + from + amount,
-		      (end - from) * sizeof current_frame->pix_width[0]);
-
-	  safe_bcopy (current_frame->pix_height + from,
-		      current_frame->pix_height + from + amount,
-		      (end - from) * sizeof current_frame->pix_height[0]);
-
-	  safe_bcopy (current_frame->max_ascent + from,
-		      current_frame->max_ascent + from + amount,
-		      (end - from) * sizeof current_frame->max_ascent[0]);
-	}
-#endif /* HAVE_WINDOW_SYSTEM */
-
-      update_end (frame);
+      /* Down (rotate right, i.e. towards higher indices).  */
+      reverse_rows (matrix, last - by, last);
+      reverse_rows (matrix, first, last - by);
+      reverse_rows (matrix, first, last);
     }
-  if (amount < 0)
+}
+
+
+/* Increment buffer positions in glyph rows of MATRIX.  Do it for rows
+   with indices START <= index < END.  Increment positions by DELTA/
+   DELTA_BYTES.  */
+
+void
+increment_glyph_matrix_buffer_positions (matrix, start, end, delta,
+					 delta_bytes)
+     struct glyph_matrix *matrix;
+     int start, end, delta, delta_bytes;
+{
+  /* Check that START and END are reasonable values.  */
+  xassert (start >= 0 && start <= matrix->nrows);
+  xassert (end >= 0 && end <= matrix->nrows);
+  xassert (start <= end);
+
+  for (; start < end; ++start)
+    increment_glyph_row_buffer_positions (matrix->rows + start,
+					  delta, delta_bytes);
+}
+
+
+/* Enable a range of rows in glyph matrix MATRIX.  START and END are
+   the row indices of the first and last + 1 row to enable.  If
+   ENABLED_P is non-zero, enabled_p flags in rows will be set to 1.  */
+
+void
+enable_glyph_matrix_rows (matrix, start, end, enabled_p)
+     struct glyph_matrix *matrix;
+     int start, end;
+     int enabled_p;
+{
+  xassert (start <= end);
+  xassert (start >= 0 && start < matrix->nrows);
+  xassert (end >= 0 && end <= matrix->nrows);
+  
+  for (; start < end; ++start)
+    matrix->rows[start].enabled_p = enabled_p != 0;
+}
+
+
+/* Clear MATRIX.
+
+   This empties all rows in MATRIX by setting the enabled_p flag for
+   all rows of the matrix to zero.  The function prepare_desired_row
+   will eventually really clear a row when it sees one with a zero
+   enabled_p flag.
+
+   Resets update hints to defaults value.  The only update hint
+   currently present is the flag MATRIX->no_scrolling_p.  */
+
+void
+clear_glyph_matrix (matrix)
+     struct glyph_matrix *matrix;
+{
+  if (matrix)
     {
-      update_begin (frame);
-      set_terminal_window (end);
-      ins_del_lines (from + amount, amount);
-      if (!scroll_region_ok)
-	ins_del_lines (end + amount, -amount);
-      set_terminal_window (0);
-
-      rotate_vector (current_frame->glyphs + from + amount,
-		     sizeof (GLYPH *) * (end - from - amount),
-		     amount * sizeof (GLYPH *));
-
-      rotate_vector (current_frame->charstarts + from + amount,
-		     sizeof (int *) * (end - from - amount),
-		     amount * sizeof (int *));
-
-      safe_bcopy (current_frame->used + from,
-		  current_frame->used + from + amount,
-		  (end - from) * sizeof current_frame->used[0]);
-
-      safe_bcopy (current_frame->highlight + from,
-		  current_frame->highlight + from + amount,
-		  (end - from) * sizeof current_frame->highlight[0]);
-
-      safe_bcopy (current_frame->enable + from,
-		  current_frame->enable + from + amount,
-		  (end - from) * sizeof current_frame->enable[0]);
-
-      /* Adjust the lines by an amount
-	 that puts the first of them at NEWPOS.  */
-      pos_adjust = newpos - current_frame->charstarts[from + amount][0];
-
-      /* Offset each char position in the charstarts lines we moved
-	 by pos_adjust.  */
-      for (i = from + amount; i < end + amount; i++)
-	{
-	  int *line = current_frame->charstarts[i];
-	  int col;
-	  for (col = 0; col < width; col++)
-	    if (line[col] > 0)
-	      line[col] += pos_adjust;
-	}
-      for (i = end + amount; i < end; i++)
-	{
-	  int *line = current_frame->charstarts[i];
-	  int col;
-	  line[0] = -1;
-	  for (col = 0; col < width; col++)
-	    line[col] = 0;
-	}
-
-      /* Mark the lines made empty by scrolling as enabled, empty and
-	 normal video.  */
-      bzero (current_frame->used + end + amount,
-	     - amount * sizeof current_frame->used[0]);
-      bzero (current_frame->highlight + end + amount,
-	     - amount * sizeof current_frame->highlight[0]);
-      for (i = end + amount; i < end; i++)
-	{
-	  current_frame->glyphs[i][0] = '\0';
-	  current_frame->charstarts[i][0] = 0;
-	  current_frame->enable[i] = 1;
-	}
-
-      safe_bcopy (current_frame->bufp + from,
-		  current_frame->bufp + from + amount,
-		  (end - from) * sizeof current_frame->bufp[0]);
-
-#ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_WINDOW_P (frame))
-	{
-	  safe_bcopy (current_frame->top_left_x + from,
-		      current_frame->top_left_x + from + amount,
-		      (end - from) * sizeof current_frame->top_left_x[0]);
-
-	  safe_bcopy (current_frame->top_left_y + from,
-		      current_frame->top_left_y + from + amount,
-		      (end - from) * sizeof current_frame->top_left_y[0]);
-
-	  safe_bcopy (current_frame->pix_width + from,
-		      current_frame->pix_width + from + amount,
-		      (end - from) * sizeof current_frame->pix_width[0]);
-
-	  safe_bcopy (current_frame->pix_height + from,
-		      current_frame->pix_height + from + amount,
-		      (end - from) * sizeof current_frame->pix_height[0]);
-
-	  safe_bcopy (current_frame->max_ascent + from,
-		      current_frame->max_ascent + from + amount,
-		      (end - from) * sizeof current_frame->max_ascent[0]);
-	}
-#endif /* HAVE_WINDOW_SYSTEM */
-
-      update_end (frame);
+      enable_glyph_matrix_rows (matrix, 0, matrix->nrows, 0);
+      matrix->no_scrolling_p = 0;
     }
-  return 1;
 }
-
-/* After updating a window W that isn't the full frame wide,
-   copy all the columns that W does not occupy
-   into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
-   so that update_frame will not change those columns.  */
+  
+
+/* Shift part of the glyph matrix MATRIX of window W up or down.
+   Increment y-positions in glyph rows between START and END by DY,
+   and recompute their visible height.  */
+
+void
+shift_glyph_matrix (w, matrix, start, end, dy)
+     struct window *w;
+     struct glyph_matrix *matrix;
+     int start, end, dy;
+{
+  int min_y, max_y;
+  
+  xassert (start <= end);
+  xassert (start >= 0 && start < matrix->nrows);
+  xassert (end >= 0 && end <= matrix->nrows);
+  
+  min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+  max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
+  
+  for (; start < end; ++start)
+    {
+      struct glyph_row *row = &matrix->rows[start];
+      
+      row->y += dy;
+      
+      if (row->y < min_y)
+	row->visible_height = row->height - (min_y - row->y);
+      else if (row->y + row->height > max_y)
+	row->visible_height = row->height - (row->y + row->height - max_y);
+      else
+	row->visible_height = row->height;
+    }
+}
+
+
+/* Mark all rows in current matrices of frame F as invalid.  Marking
+   invalid is done by setting enabled_p to zero for all rows in a
+   current matrix.  */
+
+void
+clear_current_matrices (f)
+     register struct frame *f;
+{
+  /* Clear frame current matrix, if we have one.  */
+  if (f->current_matrix)
+    clear_glyph_matrix (f->current_matrix);
+
+  /* Clear the matrix of the menu bar window, if such a window exists.
+     The menu bar window is currently used to display menus on X when
+     no toolkit support is compiled in.  */
+  if (WINDOWP (f->menu_bar_window))
+    clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
+
+  /* Clear the matrix of the toolbar window, if any.  */
+  if (WINDOWP (f->toolbar_window))
+    clear_glyph_matrix (XWINDOW (f->toolbar_window)->current_matrix);
+
+  /* Clear current window matrices.  */
+  xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
+  clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 0);
+}
+
+
+/* Clear out all display lines of F for a coming redisplay.  */
 
 void
-preserve_other_columns (w)
-     struct window *w;
+clear_desired_matrices (f)
+     register struct frame *f;
 {
-  register int vpos;
-  register struct frame_glyphs *current_frame, *desired_frame;
-  register FRAME_PTR frame = XFRAME (w->frame);
-  int start = WINDOW_LEFT_MARGIN (w);
-  int end = WINDOW_RIGHT_EDGE (w);
-  int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
-  current_frame = FRAME_CURRENT_GLYPHS (frame);
-  desired_frame = FRAME_DESIRED_GLYPHS (frame);
-
-  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
+  if (f->desired_matrix)
+    clear_glyph_matrix (f->desired_matrix);
+  
+  if (WINDOWP (f->menu_bar_window))
+    clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
+
+  if (WINDOWP (f->toolbar_window))
+    clear_glyph_matrix (XWINDOW (f->toolbar_window)->desired_matrix);
+
+  /* Do it for window matrices.  */
+  xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
+  clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
+}
+
+
+/* Clear matrices in window tree rooted in W.  If DESIRED_P is
+   non-zero clear desired matrices, otherwise clear current matrices.  */
+
+static void
+clear_window_matrices (w, desired_p)
+     struct window *w;
+     int desired_p;
+{
+  while (w)
     {
-      if (current_frame->enable[vpos] && desired_frame->enable[vpos])
+      if (!NILP (w->hchild))
+	{
+	  xassert (WINDOWP (w->hchild));
+	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
+	}
+      else if (!NILP (w->vchild))
 	{
-	  if (start > 0)
+	  xassert (WINDOWP (w->vchild));
+	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
+	}
+      else
+	{
+	  if (desired_p)
+	    clear_glyph_matrix (w->desired_matrix);
+	  else
 	    {
-	      int len;
-
-	      bcopy (current_frame->glyphs[vpos],
-		     desired_frame->glyphs[vpos],
-		     start * sizeof (current_frame->glyphs[vpos][0]));
-	      bcopy (current_frame->charstarts[vpos],
-		     desired_frame->charstarts[vpos],
-		     start * sizeof (current_frame->charstarts[vpos][0]));
-	      len = min (start, current_frame->used[vpos]);
-	      if (desired_frame->used[vpos] < len)
-		desired_frame->used[vpos] = len;
+	      clear_glyph_matrix (w->current_matrix);
+	      w->window_end_valid = Qnil;
 	    }
-	  if (current_frame->used[vpos] > end
-	      && desired_frame->used[vpos] < current_frame->used[vpos])
-	    {
-	      while (desired_frame->used[vpos] < end)
-		{
-		  int used = desired_frame->used[vpos]++;
-		  desired_frame->glyphs[vpos][used] = SPACEGLYPH;
-		  desired_frame->glyphs[vpos][used] = 0;
-		}
-	      bcopy (current_frame->glyphs[vpos] + end,
-		     desired_frame->glyphs[vpos] + end,
-		     ((current_frame->used[vpos] - end)
-		      * sizeof (current_frame->glyphs[vpos][0])));
-	      bcopy (current_frame->charstarts[vpos] + end,
-		     desired_frame->charstarts[vpos] + end,
-		     ((current_frame->used[vpos] - end)
-		      * sizeof (current_frame->charstarts[vpos][0])));
-	      desired_frame->used[vpos] = current_frame->used[vpos];
-	    }
+	}
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}
+
+
+
+/***********************************************************************
+			      Glyph Rows
+
+      See dispextern.h for an overall explanation of glyph rows.
+ ***********************************************************************/
+
+/* Clear glyph row ROW.  Do it in a way that makes it robust against
+   changes in the glyph_row structure, i.e. addition or removal of
+   structure members.  */
+
+void
+clear_glyph_row (row)
+     struct glyph_row *row;
+{
+  struct glyph *p[1 + LAST_AREA];
+  static struct glyph_row null_row;
+
+  /* Save pointers.  */
+  p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
+  p[TEXT_AREA] = row->glyphs[TEXT_AREA];
+  p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA];
+  p[LAST_AREA] = row->glyphs[LAST_AREA];
+
+  /* Clear.  */
+  *row = null_row;
+
+  /* Restore pointers.  */
+  row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA];
+  row->glyphs[TEXT_AREA] = p[TEXT_AREA];
+  row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
+  row->glyphs[LAST_AREA] = p[LAST_AREA];
+}
+
+
+/* Make ROW an empty, enabled row of canonical character height,
+   in window W starting at y-position Y.  */
+
+void
+blank_row (w, row, y)
+     struct window *w;
+     struct glyph_row *row;
+     int y;
+{
+  int min_y, max_y;
+  
+  min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+  max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
+  
+  clear_glyph_row (row);
+  row->y = y;
+  row->ascent = 0;
+  row->height = CANON_Y_UNIT (XFRAME (WINDOW_FRAME (w)));
+  
+  if (row->y < min_y)
+    row->visible_height = row->height - (min_y - row->y);
+  else if (row->y + row->height > max_y)
+    row->visible_height = row->height - (row->y + row->height - max_y);
+  else
+    row->visible_height = row->height;
+
+  row->enabled_p = 1;
+}
+
+
+/* Increment buffer positions in glyph row ROW.  DELTA and DELTA_BYTES
+   are the amounts by which to change positions.  Note that the first
+   glyph of the text area of a row can have a buffer position even if
+   the used count of the text area is zero.  Such rows display line
+   ends.  */
+
+void
+increment_glyph_row_buffer_positions (row, delta, delta_bytes)
+     struct glyph_row *row;
+     int delta, delta_bytes;
+{
+  int area, i;
+
+  /* Increment start and end positions.  */
+  MATRIX_ROW_START_CHARPOS (row) += delta;
+  MATRIX_ROW_START_BYTEPOS (row) += delta_bytes;
+  MATRIX_ROW_END_CHARPOS (row) += delta;
+  MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
+
+  /* Increment positions in glyphs.  */
+  for (area = 0; area < LAST_AREA; ++area)
+    for (i = 0; i < row->used[area]; ++i)
+      if (BUFFERP (row->glyphs[area][i].object)
+	  && row->glyphs[area][i].charpos > 0)
+	row->glyphs[area][i].charpos += delta;
+
+  /* Capture the case of rows displaying a line end.  */
+  if (row->used[TEXT_AREA] == 0
+      && MATRIX_ROW_DISPLAYS_TEXT_P (row))
+    row->glyphs[TEXT_AREA]->charpos += delta;
+}
+
+
+/* Swap glyphs between two glyph rows A and B.  This exchanges glyph
+   contents, i.e. glyph structure contents are exchanged between A and
+   B without changing glyph pointers in A and B.  */
+
+static void
+swap_glyphs_in_rows (a, b)
+     struct glyph_row *a, *b;
+{
+  int area;
+
+  for (area = 0; area < LAST_AREA; ++area)
+    {
+      /* Number of glyphs to swap.  */
+      int max_used = max (a->used[area], b->used[area]);
+
+      /* Start of glyphs in area of row A.  */
+      struct glyph *glyph_a = a->glyphs[area];
+
+      /* End + 1 of glyphs in area of row A.  */
+      struct glyph *glyph_a_end = a->glyphs[max_used];
+
+      /* Start of glyphs in area of row B.  */
+      struct glyph *glyph_b = b->glyphs[area];
+
+      while (glyph_a < glyph_a_end)
+	{
+	  /* Non-ISO HP/UX compiler doesn't like auto struct
+             initialization.  */
+	  struct glyph temp;
+	  temp = *glyph_a;
+	  *glyph_a = *glyph_b;
+	  *glyph_b = temp;
+	  ++glyph_a;
+	  ++glyph_b;
 	}
     }
 }
+
+
+/* Exchange pointers to glyph memory between glyph rows A and B.  */
+
+static INLINE void
+swap_glyph_pointers (a, b)
+     struct glyph_row *a, *b;
+{
+  int i;
+  for (i = 0; i < LAST_AREA + 1; ++i)
+    {
+      struct glyph *temp = a->glyphs[i];
+      a->glyphs[i] = b->glyphs[i];
+      b->glyphs[i] = temp;
+    }
+}
+
+
+/* Copy glyph row structure FROM to glyph row structure TO, except
+   that glyph pointers in the structures are left unchanged.  */
+
+INLINE void
+copy_row_except_pointers (to, from)
+     struct glyph_row *to, *from;
+{
+  struct glyph *pointers[1 + LAST_AREA];
+
+  /* Save glyph pointers of TO.  */
+  bcopy (to->glyphs, pointers, sizeof to->glyphs);
+
+  /* Do a structure assignment.  */
+  *to = *from;
+
+  /* Restore original pointers of TO.  */
+  bcopy (pointers, to->glyphs, sizeof to->glyphs);
+}
+
+
+/* Copy contents of glyph row FROM to glyph row TO.  Glyph pointers in
+   TO and FROM are left unchanged.  Glyph contents are copied from the
+   glyph memory of FROM to the glyph memory of TO.  Increment buffer
+   positions in row TO by DELTA/ DELTA_BYTES.  */
+
+void
+copy_glyph_row_contents (to, from, delta, delta_bytes)
+     struct glyph_row *to, *from;
+     int delta, delta_bytes;
+{
+  int area;
+
+  /* This is like a structure assignment TO = FROM, except that
+     glyph pointers in the rows are left unchanged.  */
+  copy_row_except_pointers (to, from);
+
+  /* Copy glyphs from FROM to TO.  */
+  for (area = 0; area < LAST_AREA; ++area)
+    if (from->used[area])
+      bcopy (from->glyphs[area], to->glyphs[area], 
+	     from->used[area] * sizeof (struct glyph));
+
+  /* Increment buffer positions in TO by DELTA.  */
+  increment_glyph_row_buffer_positions (to, delta, delta_bytes);
+}
+
+
+/* Assign glyph row FROM to glyph row TO.  This works like a structure
+   assignment TO = FROM, except that glyph pointers are not copied but
+   exchanged between TO and FROM.  Pointers must be exchanged to avoid
+   a memory leak.  */
+
+static INLINE void
+assign_row (to, from)
+     struct glyph_row *to, *from;
+{
+  swap_glyph_pointers (to, from);
+  copy_row_except_pointers (to, from);
+}
+
+
+/* Test whether the glyph memory of the glyph row WINDOW_ROW, which is
+   a row in a window matrix, is a slice of the glyph memory of the
+   glyph row FRAME_ROW which is a row in a frame glyph matrix.  Value
+   is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
+   memory of FRAME_ROW.  */
+
+static int
+glyph_row_slice_p (window_row, frame_row)
+     struct glyph_row *window_row, *frame_row;
+{
+  struct glyph *window_glyph_start = window_row->glyphs[0];
+  struct glyph *frame_glyph_start = frame_row->glyphs[0];
+  struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA];
+
+  return (frame_glyph_start <= window_glyph_start
+	  && window_glyph_start < frame_glyph_end);
+}
+
+
+/* Find the row in the window glyph matrix WINDOW_MATRIX being a slice
+   of ROW in the frame matrix FRAME_MATRIX.  Value is null if no row
+   in WINDOW_MATRIX is found satisfying the condition.  */
+
+static struct glyph_row *
+find_glyph_row_slice (window_matrix, frame_matrix, row)
+     struct glyph_matrix *window_matrix, *frame_matrix;
+     int row;
+{
+  int i;
+
+  xassert (row >= 0 && row < frame_matrix->nrows);
+
+  for (i = 0; i < window_matrix->nrows; ++i)
+    if (glyph_row_slice_p (window_matrix->rows + i,
+			   frame_matrix->rows + row))
+      break;
+
+  return i < window_matrix->nrows ? window_matrix->rows + i : 0;
+}
+
+
+/* Prepare ROW for display.  Desired rows are cleared lazily,
+   i.e. they are only marked as to be cleared by setting their
+   enabled_p flag to zero.  When a row is to be displayed, a prior
+   call to this function really clears it.  */
+
+void
+prepare_desired_row (row)
+     struct glyph_row *row;
+{
+  if (!row->enabled_p)
+    {
+      clear_glyph_row (row);
+      row->enabled_p = 1;
+    }
+}
+
+
+/* Return a hash code for glyph row ROW.  */
+
+int
+line_hash_code (row)
+     struct glyph_row *row;
+{
+  int hash = 0;
+  
+  if (row->enabled_p)
+    {
+      if (row->inverse_p)
+        {
+          /* Give all highlighted lines the same hash code
+	     so as to encourage scrolling to leave them in place.  */
+          hash = -1;
+        }
+      else
+        {
+          struct glyph *glyph = row->glyphs[TEXT_AREA];
+	  struct glyph *end = glyph + row->used[TEXT_AREA];
+
+          while (glyph < end)
+            {
+	      GLYPH g = GLYPH_FROM_CHAR_GLYPH (*glyph);
+	      if (must_write_spaces)
+	        g -= SPACEGLYPH;
+	      hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + g;
+	      ++glyph;
+	    }
+
+          if (hash == 0)
+	    hash = 1;
+        }
+    }
+
+  return hash;
+}
+
+
+/* Return the cost of drawing line VPOS In MATRIX.  The cost equals
+   the number of characters in the line.  If must_write_spaces is
+   zero, leading and trailing spaces are ignored.  */
+
+static unsigned int
+line_draw_cost (matrix, vpos)
+     struct glyph_matrix *matrix;
+     int vpos;
+{
+  struct glyph_row *row = matrix->rows + vpos;
+  struct glyph *beg = row->glyphs[TEXT_AREA];
+  struct glyph *end = beg + row->used[TEXT_AREA];
+  int len;
+  Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE;
+  int glyph_table_len = GLYPH_TABLE_LENGTH;
+
+  /* Ignore trailing and leading spaces if we can.  */
+  if (!must_write_spaces)
+    {
+      /* Skip from the end over trailing spaces.  */
+      while (end != beg && CHAR_GLYPH_SPACE_P (*end))
+	--end;
+
+      /* All blank line.  */      
+      if (end == beg)
+	return 0;
+
+      /* Skip over leading spaces.  */
+      while (CHAR_GLYPH_SPACE_P (*beg))
+	++beg;
+    }
+
+  /* If we don't have a glyph-table, each glyph is one character,
+     so return the number of glyphs.  */
+  if (glyph_table_base == 0)
+    len = end - beg;
+  else
+    {
+      /* Otherwise, scan the glyphs and accumulate their total length
+	 in LEN.  */
+      len = 0;
+      while (beg < end)
+	{
+	  GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg);
+	  
+	  if (GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
+	    len += 1;
+	  else
+	    len += GLYPH_LENGTH (glyph_table_base, g);
+	  
+	  ++beg;
+	}
+    }
+  
+  return len;
+}
+
+
+/* Test two glyph rows A and B for equality.  Value is non-zero if A
+   and B have equal contents.  W is the window to which the glyphs
+   rows A and B belong.  It is needed here to test for partial row
+   visibility.  */
+
+static INLINE int 
+row_equal_p (w, a, b)
+     struct window *w;
+     struct glyph_row *a, *b;
+{
+  if (a == b)
+    return 1;
+  else if (a->hash != b->hash)
+    return 0;
+  else
+    {
+      struct glyph *a_glyph, *b_glyph, *a_end;
+      int area;
+
+      /* Compare glyphs.  */
+      for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+	{
+	  if (a->used[area] != b->used[area])
+	    return 0;
+	  
+	  a_glyph = a->glyphs[area];
+	  a_end = a_glyph + a->used[area];
+	  b_glyph = b->glyphs[area];
+	  
+	  while (a_glyph < a_end
+		 && GLYPH_EQUAL_P (a_glyph, b_glyph))
+	    ++a_glyph, ++b_glyph;
+	  
+	  if (a_glyph != a_end)
+	    return 0;
+	}
+
+      if (a->truncated_on_left_p != b->truncated_on_left_p
+	  || a->inverse_p != b->inverse_p
+	  || a->fill_line_p != b->fill_line_p
+	  || a->truncated_on_right_p != b->truncated_on_right_p
+	  || a->overlay_arrow_p != b->overlay_arrow_p
+	  || a->continued_p != b->continued_p
+	  || a->indicate_empty_line_p != b->indicate_empty_line_p
+	  || (MATRIX_ROW_CONTINUATION_LINE_P (a)
+	      != MATRIX_ROW_CONTINUATION_LINE_P (b))
+	  /* Different partially visible characters on left margin.  */
+	  || a->x != b->x
+	  /* Different height.  */
+	  || a->ascent != b->ascent
+	  || a->visible_height != b->visible_height)
+	return 0;
+    }
+
+  return 1;
+}
+
+
 
+/***********************************************************************
+			      Glyph Pool
+
+     See dispextern.h for an overall explanation of glyph pools.
+ ***********************************************************************/
+
+/* Allocate a glyph_pool structure.  The structure returned is
+   initialized with zeros.  The global variable glyph_pool_count is
+   incremented for each pool allocated.  */
+
+static struct glyph_pool *
+new_glyph_pool ()
+{
+  struct glyph_pool *result;
+
+  /* Allocate a new glyph_pool and clear it.  */
+  result = (struct glyph_pool *) xmalloc (sizeof *result);
+  bzero (result, sizeof *result);
+  
+  /* For memory leak and double deletion checking.  */
+  ++glyph_pool_count;
+  
+  return result;
+}
+
+
+/* Free a glyph_pool structure POOL.  The function may be called with
+   a null POOL pointer.  The global variable glyph_pool_count is
+   decremented with every pool structure freed.  If this count gets
+   negative, more structures were freed than allocated, i.e. one
+   structure must have been freed more than once or a bogus pointer
+   was passed to free_glyph_pool.  */
+
+static void
+free_glyph_pool (pool)
+     struct glyph_pool *pool;
+{
+  if (pool)
+    {
+      /* More freed than allocated? */
+      --glyph_pool_count;
+      xassert (glyph_pool_count >= 0);
+
+      xfree (pool->glyphs);
+      xfree (pool);
+    }
+}
+
+
+/* Enlarge a glyph pool POOL.  MATRIX_DIM gives the number of rows and
+   columns we need.  This function never shrinks a pool.  The only
+   case in which this would make sense, would be when a frame's size
+   is changed from a large value to a smaller one.  But, if someone
+   does it once, we can expect that he will do it again.
+
+   Value is non-zero if the pool changed in a way which makes
+   re-adjusting window glyph matrices necessary.  */
+
+static int
+realloc_glyph_pool (pool, matrix_dim)
+     struct glyph_pool *pool;
+     struct dim matrix_dim;
+{
+  int needed;
+  int changed_p;
+
+  changed_p = (pool->glyphs == 0
+	       || matrix_dim.height != pool->nrows
+	       || matrix_dim.width != pool->ncolumns);
+
+  /* Enlarge the glyph pool.  */
+  needed = matrix_dim.width * matrix_dim.height;
+  if (needed > pool->nglyphs)
+    {
+      int size = needed * sizeof (struct glyph);
+
+      if (pool->glyphs)
+	pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size);
+      else
+	{
+	  pool->glyphs = (struct glyph *) xmalloc (size);
+	  bzero (pool->glyphs, size);
+	}
+
+      pool->nglyphs = needed;
+    }
+
+  /* Remember the number of rows and columns because (a) we use then
+     to do sanity checks, and (b) the number of columns determines
+     where rows in the frame matrix start---this must be available to
+     determine pointers to rows of window sub-matrices.  */
+  pool->nrows = matrix_dim.height;
+  pool->ncolumns = matrix_dim.width;
+  
+  return changed_p;
+}
+
+
+
+/***********************************************************************
+			      Debug Code
+ ***********************************************************************/
+
+#if GLYPH_DEBUG
+
+/* Check that no glyph pointers have been lost in MATRIX.  If a
+   pointer has been lost, e.g. by using a structure assignment between
+   rows, at least one pointer must occur more than once in the rows of
+   MATRIX.  */
+
+void
+check_matrix_pointer_lossage (matrix)
+     struct glyph_matrix *matrix;
+{
+  int i, j;
+  
+  for (i = 0; i < matrix->nrows; ++i)
+    for (j = 0; j < matrix->nrows; ++j)
+      xassert (i == j
+	       || (matrix->rows[i].glyphs[TEXT_AREA]
+		   != matrix->rows[j].glyphs[TEXT_AREA]));
+}
+
+
+/* Get a pointer to glyph row ROW in MATRIX, with bounds checks.  */
+
+struct glyph_row *
+matrix_row (matrix, row)
+     struct glyph_matrix *matrix;
+     int row;
+{
+  xassert (matrix && matrix->rows);
+  xassert (row >= 0 && row < matrix->nrows);
+
+  /* That's really too slow for normal testing because this function
+     is called almost everywhere.  Although---it's still astonishingly
+     fast, so it is valuable to have for debugging purposes.  */
 #if 0
-
-/* If window w does not need to be updated and isn't the full frame wide,
- copy all the columns that w does occupy
- into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
- so that update_frame will not change those columns.
-
- Have not been able to figure out how to use this correctly.  */
-
-preserve_my_columns (w)
+  check_matrix_pointer_lossage (matrix);
+#endif
+  
+  return matrix->rows + row;
+}
+
+
+#if 0 /* This function makes invalid assumptions when text is
+	 partially invisible.  But it might come handy for debugging
+	 nevertheless.  */
+
+/* Check invariants that must hold for an up to date current matrix of
+   window W.  */
+
+static void
+check_matrix_invariants (w)
      struct window *w;
 {
-  register int vpos, fin;
-  register struct frame_glyphs *l1, *l2;
-  register FRAME_PTR frame = XFRAME (w->frame);
-  int start = WINDOW_LEFT_MARGIN (w);
-  int end = WINDOW_RIGHT_EDGE (w);
-  int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
-  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
+  struct glyph_matrix *matrix = w->current_matrix;
+  int yb = window_text_bottom_y (w);
+  struct glyph_row *row = matrix->rows;
+  struct glyph_row *last_text_row = NULL;
+  struct buffer *saved = current_buffer;
+  struct buffer *buffer = XBUFFER (w->buffer);
+  int c;
+  
+  /* This can sometimes happen for a fresh window.  */
+  if (matrix->nrows < 2)
+    return;
+
+  set_buffer_temp (buffer);
+
+  /* Note: last row is always reserved for the mode line.  */
+  while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
+	 && MATRIX_ROW_BOTTOM_Y (row) < yb)
+    {
+      struct glyph_row *next = row + 1;
+
+      if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+	last_text_row = row;
+
+      /* Check that character and byte positions are in sync.  */
+      xassert (MATRIX_ROW_START_BYTEPOS (row)
+	       == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row)));
+
+      /* CHAR_TO_BYTE aborts when invoked for a position > Z.  We can
+	 have such a position temporarily in case of a minibuffer
+	 displaying something like `[Sole completion]' at its end.  */
+      if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer))
+	xassert (MATRIX_ROW_END_BYTEPOS (row)
+		 == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row)));
+
+      /* Check that end position of `row' is equal to start position
+	 of next row.  */
+      if (next->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (next))
+	{
+	  xassert (MATRIX_ROW_END_CHARPOS (row)
+		   == MATRIX_ROW_START_CHARPOS (next));
+	  xassert (MATRIX_ROW_END_BYTEPOS (row)
+		   == MATRIX_ROW_START_BYTEPOS (next));
+	}
+      row = next;
+    }
+
+  xassert (w->current_matrix->nrows == w->desired_matrix->nrows);
+  xassert (w->desired_matrix->rows != NULL);
+  set_buffer_temp (saved);
+}
+
+#endif /* 0  */
+
+#endif /* GLYPH_DEBUG != 0 */
+
+
+
+/**********************************************************************
+		 Allocating/ Adjusting Glyph Matrices
+ **********************************************************************/
+
+/* Allocate glyph matrices over a window tree for a frame-based
+   redisplay
+
+   X and Y are column/row within the frame glyph matrix where
+   sub-matrices for the window tree rooted at WINDOW must be
+   allocated.  CH_DIM contains the dimensions of the smallest
+   character that could be used during display.  DIM_ONLY_P non-zero
+   means that the caller of this function is only interested in the
+   result matrix dimension, and matrix adjustments should not be
+   performed.
+
+   The function returns the total width/height of the sub-matrices of
+   the window tree.  If called on a frame root window, the computation
+   will take the mini-buffer window into account.
+
+   *WINDOW_CHANGE_FLAGS is set to a bit mask with bits
+
+   NEW_LEAF_MATRIX set if any window in the tree did not have a
+   glyph matrices yet, and
+
+   CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
+   any window in the tree will be changed or have been changed (see
+   DIM_ONLY_P).
+
+   *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
+   function.
+
+   Windows are arranged into chains of windows on the same level
+   through the next fields of window structures.  Such a level can be
+   either a sequence of horizontally adjacent windows from left to
+   right, or a sequence of vertically adjacent windows from top to
+   bottom.  Each window in a horizontal sequence can be either a leaf
+   window or a vertical sequence; a window in a vertical sequence can
+   be either a leaf or a horizontal sequence.  All windows in a
+   horizontal sequence have the same height, and all windows in a
+   vertical sequence have the same width.
+
+   This function uses, for historical reasons, a more general
+   algorithm to determine glyph matrix dimensions that would be
+   necessary.
+
+   The matrix height of a horizontal sequence is determined by the
+   maximum height of any matrix in the sequence.  The matrix width of
+   a horizontal sequence is computed by adding up matrix widths of
+   windows in the sequence.
+
+   |<------- result width ------->|
+   +---------+----------+---------+ ---
+   |         |		|	  |  |
+   |         |		|	  |
+   +---------+		|	  |  result height
+	     |		+---------+
+	     |		|            |
+	     +----------+	    ---
+
+   The matrix width of a vertical sequence is the maximum matrix width
+   of any window in the sequence.  Its height is computed by adding up
+   matrix heights of windows in the sequence.
+
+   |<---- result width -->|
+   +---------+		    ---
+   |         |               |
+   |         |               |
+   +---------+--+            |
+   |		|            |
+   |		|	     result height
+   |		|
+   +------------+---------+  |
+   |			  |  |
+   |			  |  |
+   +------------+---------+ ---  */
+
+/* Bit indicating that a new matrix will be allocated or has been
+   allocated.  */
+
+#define NEW_LEAF_MATRIX		(1 << 0)
+
+/* Bit indicating that a matrix will or has changed its location or
+   size.  */
+
+#define CHANGED_LEAF_MATRIX	(1 << 1)
+
+static struct dim
+allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
+				       dim_only_p, window_change_flags)
+     Lisp_Object window;
+     int x, y;
+     struct dim ch_dim;
+     int dim_only_p;
+     int *window_change_flags;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+  int x0 = x, y0 = y;
+  int wmax = 0, hmax = 0;
+  struct dim total;
+  struct dim dim;
+  struct window *w;
+  int in_horz_combination_p;
+
+  /* What combination is WINDOW part of?  Compute this once since the
+     result is the same for all windows in the `next' chain.  The
+     special case of a root window (parent equal to nil) is treated
+     like a vertical combination because a root window's `next'
+     points to the mini-buffer window, if any, which is arranged
+     vertically below other windows.  */
+  in_horz_combination_p
+    = (!NILP (XWINDOW (window)->parent)
+       && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+
+  /* For WINDOW and all windows on the same level.  */
+  do 
+    {
+      w = XWINDOW (window);
+
+      /* Get the dimension of the window sub-matrix for W, depending
+	 on whether this a combination or a leaf window.  */
+      if (!NILP (w->hchild))
+	dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim,
+						     dim_only_p,
+						     window_change_flags);
+      else if (!NILP (w->vchild))
+	dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim,
+						     dim_only_p,
+						     window_change_flags);
+      else
+	{
+	  /* If not already done, allocate sub-matrix structures.  */
+	  if (w->desired_matrix == NULL)
+	    {
+	      w->desired_matrix = new_glyph_matrix (f->desired_pool);
+	      w->current_matrix = new_glyph_matrix (f->current_pool);
+	      *window_change_flags |= NEW_LEAF_MATRIX;
+	    }
+  
+	  /* Width and height MUST be chosen so that there are no
+	     holes in the frame matrix.  */
+	  dim.width = w->width;
+	  dim.height = w->height;
+
+	  /* Will matrix be re-allocated?  */
+	  if (x != w->desired_matrix->matrix_x
+	      || y != w->desired_matrix->matrix_y
+	      || dim.width != w->desired_matrix->matrix_w
+	      || dim.height != w->desired_matrix->matrix_h
+	      || (margin_glyphs_to_reserve (w, dim.width,
+					    w->right_margin_width)
+		  != w->desired_matrix->left_margin_glyphs)
+	      || (margin_glyphs_to_reserve (w, dim.width,
+					    w->left_margin_width)
+		  != w->desired_matrix->right_margin_glyphs))
+	    *window_change_flags |= CHANGED_LEAF_MATRIX;
+
+	  /* Actually change matrices, if allowed.  Do not consider
+	     CHANGED_LEAF_MATRIX computed above here because the pool
+	     may have been changed which we don't now here.  We trust
+	     that we only will be called with DIM_ONLY_P != 0 when
+	     necessary.  */
+	  if (!dim_only_p)
+	    {
+	      adjust_glyph_matrix (w, w->desired_matrix, x, y, dim);
+	      adjust_glyph_matrix (w, w->current_matrix, x, y, dim);
+	    }
+	}
+
+      /* If we are part of a horizontal combination, advance x for
+	 windows to the right of W; otherwise advance y for windows
+	 below W.  */
+      if (in_horz_combination_p)
+	x += dim.width;
+      else 
+        y += dim.height;
+
+      /* Remember maximum glyph matrix dimensions.  */
+      wmax = max (wmax, dim.width);
+      hmax = max (hmax, dim.height);
+
+      /* Next window on same level.  */
+      window = w->next;
+    }
+  while (!NILP (window));
+
+  /* Set `total' to the total glyph matrix dimension of this window
+     level.  In a vertical combination, the width is the width of the
+     widest window; the height is the y we finally reached, corrected
+     by the y we started with.  In a horizontal combination, the total
+     height is the height of the tallest window, and the width is the
+     x we finally reached, corrected by the x we started with.  */
+  if (in_horz_combination_p)
+    {
+      total.width = x - x0;
+      total.height = hmax;
+    }
+  else 
+    {
+      total.width = wmax;
+      total.height = y - y0;
+    }
+
+  return total;
+}
+
+
+/* Allocate window matrices for window-based redisplay.  W is the
+   window whose matrices must be allocated/reallocated.  CH_DIM is the
+   size of the smallest character that could potentially be used on W.  */
+   
+static void
+allocate_matrices_for_window_redisplay (w, ch_dim)
+     struct window *w;
+     struct dim ch_dim;
+{
+  struct frame *f = XFRAME (w->frame);
+  
+  while (w)
     {
-      if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
-	  && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
+      if (!NILP (w->vchild))
+	allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim);
+      else if (!NILP (w->hchild))
+	allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim);
+      else
 	{
-	  if (l2->length > start && l1->length < l2->length)
+	  /* W is a leaf window.  */
+	  int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
+	  int window_pixel_height = window_box_height (w) + abs (w->vscroll);
+	  struct dim dim;
+
+	  /* If matrices are not yet allocated, allocate them now.  */
+	  if (w->desired_matrix == NULL)
 	    {
-	      fin = l2->length;
-	      if (fin > end) fin = end;
-	      while (l1->length < start)
-		l1->body[l1->length++] = ' ';
-	      bcopy (l2->body + start, l1->body + start, fin - start);
-	      l1->length = fin;
+	      w->desired_matrix = new_glyph_matrix (NULL);
+	      w->current_matrix = new_glyph_matrix (NULL);
 	    }
+
+	  /* Compute number of glyphs needed in a glyph row.  */
+	  dim.width = (((window_pixel_width + ch_dim.width - 1)
+			/ ch_dim.width)
+		       /* 2 partially visible columns in the text area.  */
+		       + 2
+		       /* One partially visible column at the right
+			  edge of each marginal area.  */
+		       + 1 + 1);
+
+	  /* Compute number of glyph rows needed.  */
+	  dim.height = (((window_pixel_height + ch_dim.height - 1)
+			 / ch_dim.height)
+			/* One partially visible line at the top and
+			   bottom of the window.  */
+			+ 2
+			/* 2 for top and mode line.  */
+			+ 2);
+
+	  /* Change matrices.  */
+	  adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
+	  adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
+	}
+      
+      w = NILP (w->next) ? NULL : XWINDOW (w->next);
+    }
+}
+
+
+/* Re-allocate/ re-compute glyph matrices on frame F.  If F is null,
+   do it for all frames; otherwise do it just for the given frame.
+   This function must be called when a new frame is created, its size
+   changes, or its window configuration changes.  */
+
+void
+adjust_glyphs (f)
+     struct frame *f;
+{
+  if (f)
+    adjust_frame_glyphs (f);
+  else
+    {
+      Lisp_Object tail, lisp_frame;
+      
+      FOR_EACH_FRAME (tail, lisp_frame)
+	adjust_frame_glyphs (XFRAME (lisp_frame));
+    }
+}
+
+
+/* Adjust frame glyphs when Emacs is initialized.
+   
+   To be called from init_display. 
+   
+   We need a glyph matrix because redraw will happen soon.
+   Unfortunately, window sizes on selected_frame are not yet set to
+   meaningful values.  I believe we can assume that there are only two
+   windows on the frame---the mini-buffer and the root window.  Frame
+   height and width seem to be correct so far.  So, set the sizes of
+   windows to estimated values.  */
+
+static void
+adjust_frame_glyphs_initially ()
+{
+  struct window *root = XWINDOW (selected_frame->root_window);
+  struct window *mini = XWINDOW (root->next);
+  int frame_height = FRAME_HEIGHT (selected_frame);
+  int frame_width = FRAME_WIDTH (selected_frame);
+  int top_margin = FRAME_TOP_MARGIN (selected_frame);
+
+  /* Do it for the root window.  */
+  XSETFASTINT (root->top, top_margin);
+  XSETFASTINT (root->width, frame_width);
+  set_window_height (selected_frame->root_window,
+		     frame_height - 1 - top_margin, 0);
+
+  /* Do it for the mini-buffer window.  */
+  XSETFASTINT (mini->top, frame_height - 1);
+  XSETFASTINT (mini->width, frame_width);
+  set_window_height (root->next, 1, 0);
+
+  adjust_frame_glyphs (selected_frame);
+  glyphs_initialized_initially_p = 1;
+}
+  
+
+/* Allocate/reallocate glyph matrices of a single frame F.  */
+
+static void
+adjust_frame_glyphs (f)
+     struct frame *f;
+{
+  if (FRAME_WINDOW_P (f))
+    adjust_frame_glyphs_for_window_redisplay (f);
+  else
+    adjust_frame_glyphs_for_frame_redisplay (f);
+  
+  /* Don't forget the message buffer and the buffer for
+     decode_mode_spec.  */
+  adjust_frame_message_buffer (f);
+  adjust_decode_mode_spec_buffer (f);
+
+  f->glyphs_initialized_p = 1;
+}
+
+
+/* Allocate/reallocate glyph matrices of a single frame F for
+   frame-based redisplay.  */
+
+static void
+adjust_frame_glyphs_for_frame_redisplay (f)
+     struct frame *f;
+{
+  struct dim ch_dim;
+  struct dim matrix_dim;
+  int pool_changed_p;
+  int window_change_flags;
+  int top_window_y;
+
+  if (!FRAME_LIVE_P (f))
+    return;
+
+  /* Determine the smallest character in any font for F.  On
+     console windows, all characters have dimension (1, 1).  */
+  ch_dim.width = ch_dim.height = 1;
+  
+  top_window_y = FRAME_TOP_MARGIN (f);
+
+  /* Allocate glyph pool structures if not already done.  */
+  if (f->desired_pool == NULL)
+    {
+      f->desired_pool = new_glyph_pool ();
+      f->current_pool = new_glyph_pool ();
+    }
+
+  /* Allocate frames matrix structures if needed.  */
+  if (f->desired_matrix == NULL)
+    {
+      f->desired_matrix = new_glyph_matrix (f->desired_pool);
+      f->current_matrix = new_glyph_matrix (f->current_pool);
+    }
+      
+  /* Compute window glyph matrices.  (This takes the mini-buffer
+     window into account).  The result is the size of the frame glyph
+     matrix needed.  The variable window_change_flags is set to a bit
+     mask indicating whether new matrices will be allocated or
+     existing matrices change their size or location within the frame
+     matrix.  */
+  window_change_flags = 0;
+  matrix_dim
+    = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
+					     0, top_window_y,
+					     ch_dim, 1,
+					     &window_change_flags);
+
+  /* Add in menu bar lines, if any.  */
+  matrix_dim.height += top_window_y;
+
+  /* Enlarge pools as necessary.  */
+  pool_changed_p = realloc_glyph_pool (f->desired_pool, matrix_dim);
+  realloc_glyph_pool (f->current_pool, matrix_dim);
+
+  /* Set up glyph pointers within window matrices.  Do this only if 
+     absolutely necessary since it requires a frame redraw.  */
+  if (pool_changed_p || window_change_flags)
+    {
+      /* Do it for window matrices.  */
+      allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
+					     0, top_window_y, ch_dim, 0,
+					     &window_change_flags);
+
+      /* Size of frame matrices must equal size of frame.  Note
+	 that we are called for X frames with window widths NOT equal
+	 to the frame width (from CHANGE_FRAME_SIZE_1).  */
+      xassert (matrix_dim.width == FRAME_WIDTH (f)
+	       && matrix_dim.height == FRAME_HEIGHT (f));
+  
+      /* Resize frame matrices.  */
+      adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+      adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+
+      /* Since location and size of sub-matrices within the pool may
+	 have changed, and current matrices don't have meaningful
+	 contents anymore, mark the frame garbaged.  */
+      SET_FRAME_GARBAGED (f);
+    }
+}
+
+
+/* Allocate/reallocate glyph matrices of a single frame F for
+   window-based redisplay.  */
+
+static void
+adjust_frame_glyphs_for_window_redisplay (f)
+     struct frame *f;
+{
+  struct dim ch_dim;
+  struct window *w;
+
+  xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f));
+  
+  /* Get minimum sizes.  */
+#ifdef HAVE_WINDOW_SYSTEM
+  ch_dim.width = FRAME_SMALLEST_CHAR_WIDTH (f);
+  ch_dim.height = FRAME_SMALLEST_FONT_HEIGHT (f);
+#else
+  ch_dim.width = ch_dim.height = 1;
+#endif
+    
+  /* Allocate/reallocate window matrices.  */
+  allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)),
+					  ch_dim);
+
+  /* Allocate/ reallocate matrices of the dummy window used to display
+     the menu bar under X when no X toolkit support is available.  */
+#ifndef USE_X_TOOLKIT
+  {
+    /* Allocate a dummy window if not already done.  */
+    if (NILP (f->menu_bar_window))
+      {
+	f->menu_bar_window = make_window ();
+	w = XWINDOW (f->menu_bar_window);
+	XSETFRAME (w->frame, f);
+	w->pseudo_window_p = 1;
+      }
+    else
+      w = XWINDOW (f->menu_bar_window);
+
+    /* Set window dimensions to frame dimensions and allocate or
+       adjust glyph matrices of W.  */
+    XSETFASTINT (w->top, 0);
+    XSETFASTINT (w->left, 0);
+    XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
+    XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
+    allocate_matrices_for_window_redisplay (w, ch_dim);
+  }
+#endif /* not USE_X_TOOLKIT */
+
+  /* Allocate/ reallocate matrices of the toolbar window.  If we don't
+     have a toolbar window yet, make one.  */
+  if (NILP (f->toolbar_window))
+    {
+      f->toolbar_window = make_window ();
+      w = XWINDOW (f->toolbar_window);
+      XSETFRAME (w->frame, f);
+      w->pseudo_window_p = 1;
+    }
+  else
+    w = XWINDOW (f->toolbar_window);
+
+  XSETFASTINT (w->top, FRAME_MENU_BAR_LINES (f));
+  XSETFASTINT (w->left, 0);
+  XSETFASTINT (w->height, FRAME_TOOLBAR_LINES (f));
+  XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
+  allocate_matrices_for_window_redisplay (w, ch_dim);
+}
+
+
+/* Adjust/ allocate message buffer of frame F. 
+
+   The global variables echo_area_glyphs and previous_echo_area_glyphs
+   may be pointing to the frames message buffer and must be relocated
+   if the buffer is reallocated.
+
+   Note that the message buffer is never freed.  Since I could not
+   find a free in 19.34, I assume that freeing it would be
+   problematic in some way and don't do it either.
+
+   (Implementation note: It should be checked if we can free it
+   eventually without causing trouble).  */
+
+static void
+adjust_frame_message_buffer (f)
+     struct frame *f;
+{
+  int size = FRAME_MESSAGE_BUF_SIZE (f) + 1;
+
+  if (FRAME_MESSAGE_BUF (f))
+    {
+      char *buffer = FRAME_MESSAGE_BUF (f);
+      char *new_buffer = (char *) xrealloc (buffer, size);
+ 
+      if (buffer == echo_area_glyphs)
+        echo_area_glyphs = new_buffer;
+      if (buffer == previous_echo_glyphs)
+        previous_echo_glyphs = new_buffer;
+
+      FRAME_MESSAGE_BUF (f) = new_buffer;
+    }
+  else
+    FRAME_MESSAGE_BUF (f) = (char *) xmalloc (size);
+}
+
+
+/* Re-allocate buffer for decode_mode_spec on frame F.  */
+
+static void
+adjust_decode_mode_spec_buffer (f)
+     struct frame *f;
+{
+  f->decode_mode_spec_buffer
+    = (char *) xrealloc (f->decode_mode_spec_buffer,
+			 FRAME_MESSAGE_BUF_SIZE (f) + 1);
+}
+
+
+
+/**********************************************************************
+			Freeing Glyph Matrices
+ **********************************************************************/
+
+/* Free glyph memory for a frame F.  F may be null.  This function can
+   be called for the same frame more than once.  The root window of
+   F may be nil when this function is called.  This is the case when
+   the function is called when F is destroyed.  */
+
+void
+free_glyphs (f)
+     struct frame *f;
+{
+  if (f && f->glyphs_initialized_p)
+    {
+      f->glyphs_initialized_p = 0;
+      
+      /* Release window sub-matrices.  */
+      if (!NILP (f->root_window))
+        free_window_matrices (XWINDOW (f->root_window));
+
+      /* Free the dummy window for menu bars without X toolkit and its
+	 glyph matrices.  */
+      if (!NILP (f->menu_bar_window))
+	{
+	  struct window *w = XWINDOW (f->menu_bar_window);
+	  free_glyph_matrix (w->desired_matrix);
+	  free_glyph_matrix (w->current_matrix);
+	  w->desired_matrix = w->current_matrix = NULL;
+	  f->menu_bar_window = Qnil;
+	}
+
+      /* Free the toolbar window and its glyph matrices.  */
+      if (!NILP (f->toolbar_window))
+	{
+	  struct window *w = XWINDOW (f->toolbar_window);
+	  free_glyph_matrix (w->desired_matrix);
+	  free_glyph_matrix (w->current_matrix);
+	  w->desired_matrix = w->current_matrix = NULL;
+	  f->toolbar_window = Qnil;
+	}
+
+      /* Release frame glyph matrices.  Reset fields to zero in
+	 case we are called a second time.  */
+      if (f->desired_matrix)
+	{
+	  free_glyph_matrix (f->desired_matrix);
+	  free_glyph_matrix (f->current_matrix);
+	  f->desired_matrix = f->current_matrix = NULL;
+	}
+
+      /* Release glyph pools.  */
+      if (f->desired_pool)
+	{
+	  free_glyph_pool (f->desired_pool);
+	  free_glyph_pool (f->current_pool);
+	  f->desired_pool = f->current_pool = NULL;
 	}
     }
 }
 
-#endif
-
-/* Adjust by ADJUST the charstart values in window W
-   after vpos VPOS, which counts relative to the frame
-   (not relative to W itself).  */
+
+/* Free glyph sub-matrices in the window tree rooted at W.  This
+   function may be called with a null pointer, and it may be called on
+   the same tree more than once.  */
+
+void
+free_window_matrices (w)
+     struct window *w;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+	free_window_matrices (XWINDOW (w->hchild));
+      else if (!NILP (w->vchild))
+	free_window_matrices (XWINDOW (w->vchild));
+      else 
+	{
+	  /* This is a leaf window.  Free its memory and reset fields
+	     to zero in case this function is called a second time for
+	     W.  */
+	  free_glyph_matrix (w->current_matrix);
+	  free_glyph_matrix (w->desired_matrix);
+	  w->current_matrix = w->desired_matrix = NULL;
+	}
+
+      /* Next window on same level.  */
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}
+
+
+/* Check glyph memory leaks.  This function is called from
+   shut_down_emacs.  Note that frames are not destroyed when Emacs
+   exits.  We therefore free all glyph memory for all active frames
+   explicitly and check that nothing is left allocated.  */
 
 void
-adjust_window_charstarts (w, vpos, adjust)
-     struct window *w;
-     int vpos;
-     int adjust;
+check_glyph_memory ()
 {
-  int left = WINDOW_LEFT_MARGIN (w);
-  int top = XFASTINT (w->top);
-  int right = left + window_internal_width (w);
-  int bottom = top + window_internal_height (w);
+  Lisp_Object tail, frame;
+
+  /* Free glyph memory for all frames.  */
+  FOR_EACH_FRAME (tail, frame)
+    free_glyphs (XFRAME (frame));
+
+  /* Check that nothing is left allocated.  */
+  if (glyph_matrix_count)
+    abort ();
+  if (glyph_pool_count)
+    abort ();
+}
+
+
+
+/**********************************************************************
+		       Building a Frame Matrix
+ **********************************************************************/
+
+/* Most of the redisplay code works on glyph matrices attached to
+   windows.  This is a good solution most of the time, but it is not
+   suitable for terminal code.  Terminal output functions cannot rely
+   on being able to set an arbitrary terminal window.  Instead they
+   must be provided with a view of the whole frame, i.e. the whole
+   screen.  We build such a view by constructing a frame matrix from
+   window matrices in this section.
+
+   Windows that must be updated have their must_be_update_p flag set.
+   For all such windows, their desired matrix is made part of the
+   desired frame matrix.  For other windows, their current matrix is
+   made part of the desired frame matrix.
+
+   +-----------------+----------------+
+   |     desired     |   desired      |
+   |                 |                |
+   +-----------------+----------------+
+   |               current            |
+   |                                  |
+   +----------------------------------+
+
+   Desired window matrices can be made part of the frame matrix in a
+   cheap way: We exploit the fact that the desired frame matrix and
+   desired window matrices share their glyph memory.  This is not
+   possible for current window matrices.  Their glyphs are copied to
+   the desired frame matrix.  The latter is equivalent to
+   preserve_other_columns in the old redisplay.
+
+   Used glyphs counters for frame matrix rows are the result of adding
+   up glyph lengths of the window matrices.  A line in the frame
+   matrix is enabled, if a corresponding line in a window matrix is
+   enabled.
+   
+   After building the desired frame matrix, it will be passed to
+   terminal code, which will manipulate both the desired and current
+   frame matrix.  Changes applied to the frame's current matrix have
+   to be visible in current window matrices afterwards, of course.
+
+   This problem is solved like this:
+
+   1. Window and frame matrices share glyphs.  Window matrices are
+   constructed in a way that their glyph contents ARE the glyph
+   contents needed in a frame matrix.  Thus, any modification of
+   glyphs done in terminal code will be reflected in window matrices
+   automatically.
+   
+   2. Exchanges of rows in a frame matrix done by terminal code are
+   intercepted by hook functions so that corresponding row operations
+   on window matrices can be performed.  This is necessary because we
+   use pointers to glyphs in glyph row structures.  To satisfy the
+   assumption of point 1 above that glyphs are updated implicitly in
+   window matrices when they are manipulated via the frame matrix,
+   window and frame matrix must of course agree where to find the
+   glyphs for their rows.  Possible manipulations that must be
+   mirrored are assignments of rows of the desired frame matrix to the
+   current frame matrix and scrolling the current frame matrix.  */
+
+/* Build frame F's desired matrix from window matrices.  Only windows
+   which have the flag must_be_updated_p set have to be updated.  Menu
+   bar lines of a frame are not covered by window matrices, so make
+   sure not to touch them in this function.  */
+
+static void
+build_frame_matrix (f)
+     struct frame *f;
+{
   int i;
 
-  for (i = vpos + 1; i < bottom; i++)
+  /* F must have a frame matrix when this function is called.  */
+  xassert (!FRAME_WINDOW_P (f));
+  
+  /* Clear all rows in the frame matrix covered by window matrices.
+     Menu bar lines are not covered by windows.  */
+  for (i = FRAME_TOP_MARGIN (f); i < f->desired_matrix->nrows; ++i)
+    clear_glyph_row (MATRIX_ROW (f->desired_matrix, i));
+
+  /* Build the matrix by walking the window tree.  */
+  build_frame_matrix_from_window_tree (f->desired_matrix,
+				       XWINDOW (FRAME_ROOT_WINDOW (f)));
+}
+
+
+/* Walk a window tree, building a frame matrix MATRIX from window
+   matrices.  W is the root of a window tree.  */
+
+static void
+build_frame_matrix_from_window_tree (matrix, w)
+     struct glyph_matrix *matrix;
+     struct window *w;
+{
+  while (w)
     {
-      int *charstart
-	= FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
-      int j;
-      for (j = left; j < right; j++)
-	if (charstart[j] > 0)
-	  charstart[j] += adjust;
+      if (!NILP (w->hchild))
+	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
+      else if (!NILP (w->vchild))
+	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
+      else
+	build_frame_matrix_from_leaf_window (matrix, w);
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
 }
 
-/* Check the charstarts values in the area of window W
-   for internal consistency.  We cannot check that they are "right";
-   we can only look for something nonsensical.  */
-
-void
-verify_charstarts (w)
+
+/* Add a window's matrix to a frame matrix.  FRAME_MATRIX is the
+   desired frame matrix built.  W is a leaf window whose desired or
+   current matrix is to be added to FRAME_MATRIX.  W's flag
+   must_be_updated_p determines which matrix it contributes to
+   FRAME_MATRIX.  If must_be_updated_p is non-zero, W's desired matrix
+   is added to FRAME_MATRIX, otherwise W's current matrix is added.
+   Adding a desired matrix means setting up used counters and such in
+   frame rows, while adding a current window matrix to FRAME_MATRIX
+   means copying glyphs.  The latter case corresponds to
+   preserve_other_columns in the old redisplay.  */
+
+static void
+build_frame_matrix_from_leaf_window (frame_matrix, w)
+     struct glyph_matrix *frame_matrix;
      struct window *w;
 {
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-  int i;
-  int top = XFASTINT (w->top);
-  int bottom = top + window_internal_height (w);
-  int left = WINDOW_LEFT_MARGIN (w);
-  int right = left + window_internal_width (w);
-  int next_line;
-  int truncate = (XINT (w->hscroll)
-		  || (truncate_partial_width_windows
-		      && !WINDOW_FULL_WIDTH_P (w))
-		  || !NILP (XBUFFER (w->buffer)->truncate_lines));
-
-  for (i = top; i < bottom; i++)
+  struct glyph_matrix *window_matrix;
+  int window_y, frame_y;
+  /* If non-zero, a glyph to insert at the right border of W.  */
+  GLYPH right_border_glyph = 0;
+
+  /* Set window_matrix to the matrix we have to add to FRAME_MATRIX.  */
+  if (w->must_be_updated_p)
+    {
+      window_matrix = w->desired_matrix;
+
+      /* Decide whether we want to add a vertical border glyph.  */
+      if (!WINDOW_RIGHTMOST_P (w))
+	{
+	  struct Lisp_Char_Table *dp = window_display_table (w);
+	  right_border_glyph = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
+				? XINT (DISP_BORDER_GLYPH (dp))
+				: '|');
+	}
+    }
+  else
+    window_matrix = w->current_matrix;
+
+  /* For all rows in the window matrix and corresponding rows in the
+     frame matrix.  */
+  window_y = 0;
+  frame_y = window_matrix->matrix_y;
+  while (window_y < window_matrix->nrows)
     {
-      int j;
-      int last;
-      int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
-
-      if (i != top)
+      struct glyph_row *frame_row = frame_matrix->rows + frame_y;
+      struct glyph_row *window_row = window_matrix->rows + window_y;
+
+      /* Fill up the frame row with spaces up to the left margin of the
+	 window row.  */
+      fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x);
+
+      /* Fill up areas in the window matrix row with spaces.  */
+      fill_up_glyph_row_with_spaces (window_row);
+      
+      if (window_matrix == w->current_matrix)
 	{
-	  if (truncate)
+	  /* We have to copy W's current matrix.  Copy window
+	     row to frame row.  */
+	  bcopy (window_row->glyphs[0],
+		 frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x,
+		 window_matrix->matrix_w * sizeof (struct glyph));
+	}
+      else
+	{
+	  /* Copy W's desired matrix.  */
+
+          /* Maybe insert a vertical border between horizontally adjacent
+	     windows.  */
+          if (right_border_glyph)
+	    {
+              struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
+	      SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
+	    }
+
+	  /* Due to hooks installed, it normally doesn't happen that
+	     window rows and frame rows of the same matrix are out of
+	     sync, i.e. have a different understanding of where to
+	     find glyphs for the row.  The following is a safety-belt
+	     that doesn't cost much and makes absolutely sure that
+	     window and frame matrices are in sync.  */
+	  if (!glyph_row_slice_p (window_row, frame_row))
 	    {
-	      /* If we are truncating lines, allow a jump
-		 in charstarts from one line to the next.  */
-	      if (charstart[left] < next_line)
-		abort ();
+	      /* Find the row in the window being a slice.  There
+		 should exist one from program logic.  */
+	      struct glyph_row *slice_row
+		= find_glyph_row_slice (window_matrix, frame_matrix, frame_y);
+	      xassert (slice_row != 0);
+	      
+	      /* Exchange glyphs between both window rows.  */
+	      swap_glyphs_in_rows (window_row, slice_row);
+	      
+	      /* Exchange pointers between both rows.  */
+	      swap_glyph_pointers (window_row, slice_row);
 	    }
-	  else
+
+	  /* Now, we are sure that window row window_y is a slice of
+	     the frame row frame_y.  But, lets check that assumption.  */
+	  xassert (glyph_row_slice_p (window_row, frame_row));
+
+	  /* If rows are in sync, we don't have to copy glyphs because
+	     frame and window share glyphs.  */
+	}
+
+      /* Set number of used glyphs in the frame matrix.  Since we fill
+         up with spaces, and visit leaf windows from left to right it
+         can be done simply.  */
+      frame_row->used[TEXT_AREA] 
+	= window_matrix->matrix_x + window_matrix->matrix_w;
+
+      /* Or in flags.  */
+      frame_row->enabled_p |= window_row->enabled_p;
+      frame_row->inverse_p |= window_row->inverse_p;
+
+      /* Next row.  */
+      ++window_y;
+      ++frame_y;
+    }
+}
+
+
+/* Add spaces to a glyph row ROW in a window matrix.
+
+   Each row has the form:
+
+   +---------+-----------------------------+------------+
+   | left    |	text			   | right	|
+   +---------+-----------------------------+------------+
+
+   Left and right marginal areas are optional.  This function adds
+   spaces to areas so that there are no empty holes between areas.
+   In other words:  If the right area is not empty, the text area
+   is filled up with spaces up to the right area.   If the text area
+   is not empty, the left area is filled up.
+
+   To be called for frame-based redisplay, only.  */
+
+static void
+fill_up_glyph_row_with_spaces (row)
+     struct glyph_row *row;
+{
+  fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA);
+  fill_up_glyph_row_area_with_spaces (row, TEXT_AREA);
+  fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA);
+}
+
+
+/* Fill area AREA of glyph row ROW with spaces.  To be called for
+   frame-based redisplay only.  */
+
+static void
+fill_up_glyph_row_area_with_spaces (row, area)
+     struct glyph_row *row;
+     int area;
+{
+  if (row->glyphs[area] < row->glyphs[area + 1])
+    {
+      struct glyph *end = row->glyphs[area + 1];
+      struct glyph *text = row->glyphs[area] + row->used[area];
+
+      while (text < end)
+	*text++ = space_glyph;
+      row->used[area] = text - row->glyphs[area];
+    }
+}
+
+
+/* Add spaces to the end of ROW in a frame matrix until index UPTO is
+   reached.  In frame matrices only one area, TEXT_AREA, is used.  */
+
+static void
+fill_up_frame_row_with_spaces (row, upto)
+     struct glyph_row *row;
+     int upto;
+{
+  int i = row->used[TEXT_AREA];
+  struct glyph *glyph = row->glyphs[TEXT_AREA];
+  
+  while (i < upto)
+    glyph[i++] = space_glyph;
+
+  row->used[TEXT_AREA] = i;
+}
+
+
+
+/**********************************************************************
+      Mirroring operations on frame matrices in window matrices
+ **********************************************************************/
+
+/* Set frame being updated via frame-based redisplay to F.  This
+   function must be called before updates to make explicit that we are
+   working on frame matrices or not.  */
+
+static INLINE void
+set_frame_matrix_frame (f)
+     struct frame *f;
+{
+  frame_matrix_frame = f;
+}
+
+
+/* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
+   DESIRED_MATRIX is the desired matrix corresponding to
+   CURRENT_MATRIX.  The update is done by exchanging glyph pointers
+   between rows in CURRENT_MATRIX and DESIRED_MATRIX.  If
+   frame_matrix_frame is non-null, this indicates that the exchange is
+   done in frame matrices, and that we have to perform analogous
+   operations in window matrices of frame_matrix_frame.  */
+
+static INLINE void
+make_current (desired_matrix, current_matrix, row)
+     struct glyph_matrix *desired_matrix, *current_matrix;
+     int row;
+{
+  struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
+  struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
+
+  /* Do current_row = desired_row.  This exchanges glyph pointers
+     between both rows, and does a structure assignment otherwise.  */
+  assign_row (current_row, desired_row);
+
+  /* Enable current_row to mark it as valid.  */
+  current_row->enabled_p = 1;
+
+  /* If we are called on frame matrices, perform analogous operations
+     for window matrices.  */
+  if (frame_matrix_frame)
+    mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row);
+}
+
+
+/* W is the root of a window tree.  FRAME_ROW is the index of a row in
+   W's frame which has been made current (by swapping pointers between
+   current and desired matrix).  Perform analogous operations in the
+   matrices of leaf windows in the window tree rooted at W.  */
+
+static void
+mirror_make_current (w, frame_row)
+     struct window *w;
+     int frame_row;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+ 	mirror_make_current (XWINDOW (w->hchild), frame_row);
+      else if (!NILP (w->vchild))
+	mirror_make_current (XWINDOW (w->vchild), frame_row);
+      else
+	{
+	  /* Row relative to window W.  Don't use FRAME_TO_WINDOW_VPOS
+	     here because the checks performed in debug mode there
+	     will not allow the conversion.  */
+	  int row = frame_row - w->desired_matrix->matrix_y;
+
+	  /* If FRAME_ROW is within W, assign the desired row to the
+	     current row (exchanging glyph pointers).  */
+	  if (row >= 0 && row < w->desired_matrix->matrix_h)
 	    {
-	      if (charstart[left] != next_line)
-		abort ();
+	      struct glyph_row *current_row
+		= MATRIX_ROW (w->current_matrix, row);
+	      struct glyph_row *desired_row
+		= MATRIX_ROW (w->desired_matrix, row);
+	      
+	      assign_row (current_row, desired_row);
+	      current_row->enabled_p = 1;
 	    }
 	}
-
-      for (j = left; j < right; j++)
-	if (charstart[j] > 0)
-	  last = charstart[j];
-      /* Record where the next line should start.  */
-      next_line = last;
-      if (BUF_ZV (XBUFFER (w->buffer)) != last)
-	{
-	  /* If there's a newline between the two lines, count that.  */
-	  int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
-	  if (endchar == '\n')
-	    next_line++;
-	}
+      
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
 }
-
-/* On discovering that the redisplay for a window was no good,
-   cancel the columns of that window, so that when the window is
-   displayed over again get_display_line will not complain.  */
+
+
+/* Perform row dance after scrolling.  We are working on the range of
+   lines UNCHANGED_AT_TOP + 1 to UNCHANGED_AT_TOP + NLINES (not
+   including) in MATRIX.  COPY_FROM is a vector containing, for each
+   row I in the range 0 <= I < NLINES, the index of the original line
+   to move to I.  This index is relative to the row range, i.e. 0 <=
+   index < NLINES.  RETAINED_P is a vector containing zero for each
+   row 0 <= I < NLINES which is empty.
+
+   This function is called from do_scrolling and do_direct_scrolling.  */
+   
+void
+mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
+		     retained_p)
+     struct glyph_matrix *matrix;
+     int unchanged_at_top, nlines;
+     int *copy_from;
+     char *retained_p;
+{
+  /* A copy of original rows.  */
+  struct glyph_row *old_rows;
+
+  /* Rows to assign to.  */
+  struct glyph_row *new_rows = MATRIX_ROW (matrix, unchanged_at_top);
+  
+  int i;
+
+  /* Make a copy of the original rows.  */
+  old_rows = (struct glyph_row *) alloca (nlines * sizeof *old_rows);
+  bcopy (new_rows, old_rows, nlines * sizeof *old_rows);
+
+  /* Assign new rows, maybe clear lines.  */
+  for (i = 0; i < nlines; ++i)
+    {
+      int enabled_before_p = new_rows[i].enabled_p;
+
+      xassert (i + unchanged_at_top < matrix->nrows);
+      xassert (unchanged_at_top + copy_from[i] < matrix->nrows);
+      new_rows[i] = old_rows[copy_from[i]];
+      new_rows[i].enabled_p = enabled_before_p;
+
+      /* RETAINED_P is zero for empty lines.  */
+      if (!retained_p[copy_from[i]])
+	new_rows[i].enabled_p = 0;
+    }
+
+  /* Do the same for window matrices, if MATRIX Is a frame matrix.  */
+  if (frame_matrix_frame)
+    mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
+		       unchanged_at_top, nlines, copy_from, retained_p);
+}
+
+
+/* Perform a line dance in the window tree rooted at W, after
+   scrolling a frame matrix in mirrored_line_dance.
+
+   We are working on the range of lines UNCHANGED_AT_TOP + 1 to
+   UNCHANGED_AT_TOP + NLINES (not including) in W's frame matrix.
+   COPY_FROM is a vector containing, for each row I in the range 0 <=
+   I < NLINES, the index of the original line to move to I.  This
+   index is relative to the row range, i.e. 0 <= index < NLINES.
+   RETAINED_P is a vector containing zero for each row 0 <= I < NLINES
+   which is empty.  */
+
+static void
+mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
+     struct window *w;
+     int unchanged_at_top, nlines;
+     int *copy_from;
+     char *retained_p;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+	mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
+			   nlines, copy_from, retained_p);
+      else if (!NILP (w->vchild))
+	mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
+			   nlines, copy_from, retained_p);
+      else
+	{
+	  /* W is a leaf window, and we are working on its current
+	     matrix m.  */
+	  struct glyph_matrix *m = w->current_matrix;
+	  
+	  int i;
+	  
+	  struct glyph_row *old_rows;
+
+	  /* Make a copy of the original rows of matrix m.  */
+	  old_rows = (struct glyph_row *) alloca (m->nrows * sizeof *old_rows);
+	  bcopy (m->rows, old_rows, m->nrows * sizeof *old_rows);
+
+	  for (i = 0; i < nlines; ++i)
+	    {
+	      /* Frame relative line assigned to.  */
+	      int frame_to = i + unchanged_at_top;
+	      
+	      /* Frame relative line assigned.  */
+	      int frame_from = copy_from[i] + unchanged_at_top;
+	      
+	      /* Window relative line assigned to.  */
+	      int window_to = frame_to - m->matrix_y;
+	      
+	      /* Window relative line assigned.  */
+	      int window_from = frame_from - m->matrix_y;
+	      
+	      /* Is assigned line inside window?  */
+	      int from_inside_window_p
+		= window_from >= 0 && window_from < m->matrix_h;
+	      
+	      if (from_inside_window_p)
+		{
+#if GLYPH_DEBUG
+		  /* Is assigned to line inside window?  */
+		  int to_inside_window_p
+		    = window_to >= 0 && window_to < m->matrix_h;
+#endif
+		  
+		  /* Enabled setting before assignment.  */
+		  int enabled_before_p;
+		  
+		  /* If not both lines inside the window, we have a
+		     serious problem.  */
+		  xassert (to_inside_window_p);
+		  
+		  /* Do the assignment.  The enabled_p flag is saved
+		     over the assignment because the old redisplay did
+		     that.  */
+		  enabled_before_p = m->rows[window_to].enabled_p;
+		  m->rows[window_to] = old_rows[window_from];
+		  m->rows[window_to].enabled_p = enabled_before_p;
+		  
+		  /* If frame line is empty, window line is empty, too.  */
+		  if (!retained_p[copy_from[i]])
+		    m->rows[window_to].enabled_p = 0;
+		}
+	    }
+	  
+	  /* Check that no pointers are lost.  */
+	  CHECK_MATRIX (m);
+	}
+
+      /* Next window on same level.  */
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}
+
+
+#if GLYPH_DEBUG
+
+/* Check that window and frame matrices agree about their
+   understanding where glyphs of the rows are to find.  For each
+   window in the window tree rooted at W, check that rows in the
+   matrices of leaf window agree with their frame matrices about
+   glyph pointers.  */
 
 void
-cancel_my_columns (w)
+check_window_matrix_pointers (w)
      struct window *w;
 {
-  register int vpos;
-  register struct frame_glyphs *desired_glyphs
-    = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
-  register int start = WINDOW_LEFT_MARGIN (w);
-  register int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
-  for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
-    if (desired_glyphs->enable[vpos]
-	&& desired_glyphs->used[vpos] >= start)
-      desired_glyphs->used[vpos] = start;
+  while (w)
+    {
+      if (!NILP (w->hchild))
+	check_window_matrix_pointers (XWINDOW (w->hchild));
+      else if (!NILP (w->vchild))
+	check_window_matrix_pointers (XWINDOW (w->vchild));
+      else
+	{
+	  struct frame *f = XFRAME (w->frame);
+	  check_matrix_pointers (w->desired_matrix, f->desired_matrix);
+	  check_matrix_pointers (w->current_matrix, f->current_matrix);
+	}
+      
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}
+
+
+/* Check that window rows are slices of frame rows.  WINDOW_MATRIX is
+   a window and FRAME_MATRIX is the corresponding frame matrix.  For
+   each row in WINDOW_MATRIX check that it's a slice of the
+   corresponding frame row.  If it isn't, abort.  */
+
+static void
+check_matrix_pointers (window_matrix, frame_matrix)
+     struct glyph_matrix *window_matrix, *frame_matrix;
+{
+  /* Row number in WINDOW_MATRIX.  */
+  int i = 0;
+
+  /* Row number corresponding to I in FRAME_MATRIX.  */
+  int j = window_matrix->matrix_y;
+
+  /* For all rows check that the row in the window matrix is a 
+     slice of the row in the frame matrix.  If it isn't we didn't
+     mirror an operation on the frame matrix correctly.  */
+  while (i < window_matrix->nrows)
+    {
+      if (!glyph_row_slice_p (window_matrix->rows + i,
+			      frame_matrix->rows + j))
+        abort ();
+      ++i, ++j;
+    }
+}
+
+#endif /* GLYPH_DEBUG != 0 */
+
+
+
+/**********************************************************************
+		      VPOS and HPOS translations
+ **********************************************************************/
+
+#if GLYPH_DEBUG
+
+/* Translate vertical position VPOS which is relative to window W to a
+   vertical position relative to W's frame.  */
+
+static int
+window_to_frame_vpos (w, vpos)
+     struct window *w;
+     int vpos;
+{
+  struct frame *f = XFRAME (w->frame);
+  
+  xassert (!FRAME_WINDOW_P (f));
+  xassert (vpos >= 0 && vpos <= w->desired_matrix->nrows);
+  vpos += XFASTINT (w->top);
+  xassert (vpos >= 0 && vpos <= FRAME_HEIGHT (f));
+  return vpos;
+}
+
+
+/* Translate horizontal position HPOS which is relative to window W to
+   a vertical position relative to W's frame.  */
+
+static int
+window_to_frame_hpos (w, hpos)
+     struct window *w;
+     int hpos;
+{
+  struct frame *f = XFRAME (w->frame);
+  
+  xassert (!FRAME_WINDOW_P (f));
+  hpos += XFASTINT (w->left);
+  return hpos;
 }
+  
+#endif /* GLYPH_DEBUG */
+
+
 
-/* These functions try to perform directly and immediately on the frame
-   the necessary output for one change in the buffer.
-   They may return 0 meaning nothing was done if anything is difficult,
-   or 1 meaning the output was performed properly.
-   They assume that the frame was up to date before the buffer
-   change being displayed.  They make various other assumptions too;
-   see command_loop_1 where these are called.  */
+/**********************************************************************
+			    Redrawing Frames
+ **********************************************************************/
+
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
+  "Clear frame FRAME and output again what is supposed to appear on it.")
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+
+  CHECK_LIVE_FRAME (frame, 0);
+  f = XFRAME (frame);
+
+  /* Ignore redraw requests, if frame has no glyphs yet.
+     (Implementation note: It still has to be checked why we are
+     called so early here).  */
+  if (!glyphs_initialized_initially_p)
+    return Qnil;
+
+  update_begin (f);
+  if (FRAME_MSDOS_P (f))
+    set_terminal_modes ();
+  clear_frame ();
+  clear_current_matrices (f);
+  update_end (f);
+  fflush (stdout);
+  windows_or_buffers_changed++;
+  /* Mark all windows as inaccurate, so that every window will have
+     its redisplay done.  */
+  mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
+  set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
+  f->garbaged = 0;
+  return Qnil;
+}
+
+
+/* Redraw frame F.  This is nothing more than a call to the Lisp
+   function redraw-frame.  */
+
+void
+redraw_frame (f)
+     struct frame *f;
+{
+  Lisp_Object frame;
+  XSETFRAME (frame, f);
+  Fredraw_frame (frame);
+}
+
+
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+  "Clear and redisplay all visible frames.")
+  ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+
+  return Qnil;
+}
+
+
+/* This is used when frame_garbaged is set.  Call Fredraw_frame on all
+   visible frames marked as garbaged.  */
+
+void
+redraw_garbaged_frames ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame))
+	&& FRAME_GARBAGED_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+}
+
+
+
+/***********************************************************************
+			  Direct Operations
+ ***********************************************************************/
+
+/* Try to update display and current glyph matrix directly.
+
+   This function is called after a character G has been inserted into
+   current_buffer.  It tries to update the current glyph matrix and
+   perform appropriate screen output to reflect the insertion.  If it
+   succeeds, the global flag redisplay_performed_directly_p will be
+   set to 1, and thereby prevent the more costly general redisplay
+   from running (see redisplay_internal).
+
+   This function is not called for `hairy' character insertions.
+   In particular, it is not called when after or before change
+   functions exist, like they are used by font-lock.  See keyboard.c
+   for details where this function is called.  */
 
 int
 direct_output_for_insert (g)
      int g;
 {
-  register FRAME_PTR frame = selected_frame;
-  register struct frame_glyphs *current_frame
-    = FRAME_CURRENT_GLYPHS (frame);
-
-#ifndef COMPILER_REGISTER_BUG
-  register
-#endif /* COMPILER_REGISTER_BUG */
-    struct window *w = XWINDOW (selected_window);
-#ifndef COMPILER_REGISTER_BUG
-  register
-#endif /* COMPILER_REGISTER_BUG */
-    int hpos = FRAME_CURSOR_X (frame);
-#ifndef COMPILER_REGISTER_BUG
-  register
-#endif /* COMPILER_REGISTER_BUG */
-    int vpos = FRAME_CURSOR_Y (frame);
-
-  /* Give up if about to continue line.  */
-  if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
-    
-  /* Avoid losing if cursor is in invisible text off left margin */
-      || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
-    
-  /* Give up if cursor outside window (in minibuf, probably) */
-      || cursor_in_echo_area
-      || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
-      || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
-
-  /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
+  register struct frame *f = selected_frame;
+  struct window *w = XWINDOW (selected_window);
+  struct it it, it2;
+  struct glyph_row *glyph_row;
+  struct glyph *glyphs, *glyph, *end;
+  int n;
+  /* Non-null means that Redisplay of W is based on window matrices.  */
+  int window_redisplay_p = FRAME_WINDOW_P (f);
+  /* Non-null means we are in overwrite mode.  */
+  int overwrite_p = !NILP (current_buffer->overwrite_mode);
+  int added_width;
+  struct text_pos pos;
+  int delta, delta_bytes;
+
+  /* Not done directly.  */
+  redisplay_performed_directly_p = 0;
+
+  /* Quickly give up for some common cases.  */
+  if (cursor_in_echo_area
+      /* Give up if fonts have changed.  */
+      || fonts_changed_p
+      /* Give up if face attributes have been changed.  */
+      || face_change_count
+      /* Give up if cursor position not really known.  */
       || !display_completed
-
-  /* Give up if buffer appears in two places.  */
+      /* Give up if buffer appears in two places.  */
       || buffer_shared > 1
-
-#ifdef USE_TEXT_PROPERTIES
-  /* Intervals have already been adjusted, point is after the
-     character that was just inserted. */
-  /* Give up if character is invisible. */
-  /* Give up if character has a face property.
-     At the moment we only lose at end of line or end of buffer
-     and only with faces that have some background */
-  /* Instead of wasting time, give up if character has any text properties */
-      || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
-#endif
-
-  /* Give up if w is minibuffer and a message is being displayed there */
-      || (MINI_WINDOW_P (w) && echo_area_glyphs))
+      /* Give up if w is mini-buffer and a message is being displayed there */
+      || (MINI_WINDOW_P (w)
+	  && (echo_area_glyphs || STRINGP (echo_area_message)))
+      /* Give up for hscrolled mini-buffer because display of the prompt
+	 is handled specially there (see display_line).  */
+      || (MINI_WINDOW_P (w) && XFASTINT (w->hscroll))
+      /* Give up if overwriting in the middle of a line.  */
+      || (overwrite_p 
+	  && PT != ZV 
+	  && FETCH_BYTE (PT) != '\n')
+      /* Give up for tabs and line ends.  */
+      || g == '\t'
+      || g == '\n'
+      || g == '\r'
+      /* Give up if unable to display the cursor in the window.  */
+      || w->cursor.vpos < 0
+      /* Can't do it in a continued line because continuation lines
+	 will change.  */
+      || MATRIX_ROW (w->current_matrix, w->cursor.vpos)->continued_p
+      /* Can't do it for partial width windows on terminal frames
+	 because we can't clear to eol in such a window.  */
+      || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
+    return 0;
+
+  /* Set up a display iterator structure for W.  Glyphs will be
+     produced in scratch_glyph_row.  Current position is W's cursor
+     position.  */
+  clear_glyph_row (&scratch_glyph_row);
+  SET_TEXT_POS (pos, PT, PT_BYTE);
+  DEC_TEXT_POS (pos);
+  init_iterator (&it, w, CHARPOS (pos), BYTEPOS (pos), &scratch_glyph_row,
+		 DEFAULT_FACE_ID);
+
+  glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+  
+  /* Give up if highlighting trailing whitespace and we have trailing
+     whitespace in glyph_row.  We would have to remove the trailing
+     whitespace face in that case.  */
+  if (it.show_trailing_whitespace_p
+      && glyph_row->used[TEXT_AREA])
+    {
+      struct glyph *last;
+
+      last = glyph_row->glyphs[TEXT_AREA] + glyph_row->used[TEXT_AREA] - 1;
+      if (last->type == STRETCH_GLYPH
+	  || (last->type == CHAR_GLYPH
+	      && last->u.ch.code == ' '))
+	return 0;
+    }
+
+  /* Give up if there are overlay strings at pos.  This would fail
+     if the overlay string has newlines in it.  */
+  if (STRINGP (it.string))
+    return 0;
+  
+  it.hpos = w->cursor.hpos;
+  it.vpos = w->cursor.vpos;
+  it.current_x = w->cursor.x + it.first_visible_x;
+  it.current_y = w->cursor.y;
+  it.end_charpos = PT;
+  it.stop_charpos = min (PT, it.stop_charpos);
+
+  /* More than one display element may be returned for PT - 1 if
+     (i) it's a control character which is translated into `\003' or
+     `^C', or (ii) it has a display table entry, or (iii) it's a 
+     combination of both.  */
+  delta = delta_bytes = 0;
+  while (get_next_display_element (&it))
+    {
+      PRODUCE_GLYPHS (&it);
+
+      /* Give up if glyph doesn't fit completely on the line.  */
+      if (it.current_x >= it.last_visible_x)
+	return 0;
+
+      /* Give up if new glyph has different ascent or descent than
+	 the original row, or if it is not a character glyph.  */
+      if (glyph_row->ascent != it.ascent
+	  || glyph_row->height != it.ascent + it.descent
+	  || it.what != IT_CHARACTER)
+	return 0;
+
+      delta += 1;
+      delta_bytes += it.len;
+      set_iterator_to_next (&it);
+    }
+
+  /* Give up if we hit the right edge of the window.  We would have
+     to insert truncation or continuation glyphs.  */
+  added_width = it.current_x - (w->cursor.x + it.first_visible_x);
+  if (glyph_row->pixel_width + added_width >= it.last_visible_x)
     return 0;
 
-  {
-    int face = 0;
-#ifdef HAVE_FACES
-    int dummy;
-
-    if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
-      face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
-#endif
-    current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
-    current_frame->charstarts[vpos][hpos] = PT - 1;
-    /* Record the entry for after the newly inserted character.  */
-    current_frame->charstarts[vpos][hpos + 1] = PT;
-    adjust_window_charstarts (w, vpos, 1);
-  }
+  /* Give up if there is a \t following in the line.  */
+  it2 = it;
+  it2.end_charpos = ZV;
+  it2.stop_charpos = min (it2.stop_charpos, ZV);
+  while (get_next_display_element (&it2)
+	 && !ITERATOR_AT_END_OF_LINE_P (&it2))
+    {
+      if (it2.c == '\t')
+	return 0;
+      set_iterator_to_next (&it2);
+    }
+
+  /* Number of new glyphs produced.  */
+  n = it.glyph_row->used[TEXT_AREA];
+
+  /* Start and end of glyphs in original row.  */
+  glyphs = glyph_row->glyphs[TEXT_AREA] + w->cursor.hpos;
+  end = glyph_row->glyphs[1 + TEXT_AREA];
+
+  /* Make room for new glyphs, then insert them.  */
+  xassert (end - glyphs - n >= 0);
+  safe_bcopy (glyphs, glyphs + n, (end - glyphs - n) * sizeof (*end));
+  bcopy (it.glyph_row->glyphs[TEXT_AREA], glyphs, n * sizeof *glyphs);
+  glyph_row->used[TEXT_AREA] = min (glyph_row->used[TEXT_AREA] + n,
+				    end - glyph_row->glyphs[TEXT_AREA]);
+  
+  /* Compute new line width.  */
+  glyph = glyph_row->glyphs[TEXT_AREA];
+  end = glyph + glyph_row->used[TEXT_AREA];
+  glyph_row->pixel_width = glyph_row->x;
+  while (glyph < end)
+    {
+      glyph_row->pixel_width += glyph->pixel_width;
+      ++glyph;
+    }
+
+  /* Increment buffer positions for glyphs following the newly 
+     inserted ones.  */
+  for (glyph = glyphs + n; glyph < end; ++glyph)
+    if (glyph->charpos > 0)
+      glyph->charpos += delta;
+  
+  if (MATRIX_ROW_END_CHARPOS (glyph_row) > 0)
+    {
+      MATRIX_ROW_END_CHARPOS (glyph_row) += delta;
+      MATRIX_ROW_END_BYTEPOS (glyph_row) += delta_bytes;
+    }
+      
+  /* Adjust positions in lines following the one we are in.  */
+  increment_glyph_matrix_buffer_positions (w->current_matrix,
+					   w->cursor.vpos + 1,
+					   w->current_matrix->nrows,
+					   delta, delta_bytes);
+
+  glyph_row->contains_overlapping_glyphs_p
+    |= it.glyph_row->contains_overlapping_glyphs_p;
+
+  if (it.show_trailing_whitespace_p)
+    highlight_trailing_whitespace (it.f, glyph_row);
+
+  /* Write glyphs.  If at end of row, we can simply call write_glyphs.
+     In the middle, we have to insert glyphs.  Note that this is now
+     implemented for X frames.  The implementation uses updated_window
+     and updated_row.  */
+  updated_row = glyph_row;
+  update_begin (f);
+  if (rif)
+    {
+      rif->update_window_begin_hook (w);
+      
+      if (glyphs == end - n)
+	rif->write_glyphs (glyphs, n);
+      else
+	rif->insert_glyphs (glyphs, n);
+    }
+  else
+    {
+      if (glyphs == end - n)
+	write_glyphs (glyphs, n);
+      else
+	insert_glyphs (glyphs, n);
+    }
+
+  w->cursor.hpos += n;
+  w->cursor.x = it.current_x - it.first_visible_x;
+  xassert (w->cursor.hpos >= 0
+	   && w->cursor.hpos < w->desired_matrix->matrix_w);
+
+  /* How to set the cursor differs depending on whether we are
+     using a frame matrix or a window matrix.   Note that when
+     a frame matrix is used, cursor_to expects frame coordinates,
+     and the X and Y parameters are not used.  */
+  if (window_redisplay_p)
+    rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
+		    w->cursor.y, w->cursor.x);
+  else
+    {
+      int x, y;
+      x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
+	   + (INTEGERP (w->left_margin_width)
+	      ? XFASTINT (w->left_margin_width)
+	      : 0));
+      y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
+      cursor_to (y, x);
+    }
+
+  if (rif)
+    rif->update_window_end_hook (w, 1);
+  update_end (f);
+  updated_row = NULL;
+  fflush (stdout);
+
+  TRACE ((stderr, "direct output for insert\n"));
+
   unchanged_modified = MODIFF;
   beg_unchanged = GPT - BEG;
   XSETFASTINT (w->last_point, PT);
-  XSETFASTINT (w->last_point_x, hpos + 1);
+  w->last_cursor = w->cursor;
   XSETFASTINT (w->last_modified, MODIFF);
   XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
 
-  reassert_line_highlight (0, vpos);
-  write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
-  fflush (stdout);
-  ++FRAME_CURSOR_X (frame);
-  if (hpos == current_frame->used[vpos])
-    {
-      current_frame->used[vpos] = hpos + 1;
-      current_frame->glyphs[vpos][hpos + 1] = 0;
-    }
-
+  redisplay_performed_directly_p = 1;
   return 1;
 }
 
+
+/* Perform a direct display update for moving PT by N positions
+   left or right.  N < 0 means a movement backwards.  This function
+   is currently only called for N == 1 or N == -1.  */
+
 int
 direct_output_forward_char (n)
      int n;
 {
-  register FRAME_PTR frame = selected_frame;
-  register struct window *w = XWINDOW (selected_window);
-  Lisp_Object position;
-  int hpos = FRAME_CURSOR_X (frame);
-
-  /* Give up if in truncated text at end of line.  */
-  /* This check is not redundant.  */
-  if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
-    return 0;
-
-  /* Give up if the buffer's direction is reversed (i.e. right-to-left).  */
-  if (!NILP (XBUFFER(w->buffer)->direction_reversed))
+  struct frame *f = selected_frame;
+  struct window *w = XWINDOW (selected_window);
+  struct glyph_row *row;
+
+  /* Give up if face attributes have been changed.  */
+  if (face_change_count)
     return 0;
-
-  /* Avoid losing if cursor is in invisible text off left margin
-     or about to go off either side of window.  */
-  if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
-       && (XINT (w->hscroll) || n < 0))
-      || (n > 0
-	  && (FRAME_CURSOR_X (frame) + 1 
-	      >= XFASTINT (w->left) + window_internal_width (w) - 1))
-      /* BUG FIX: Added "XFASTINT (w->left)".  Without this,
-	 direct_output_forward_char() always fails on "the right"
-	 window.  */
-      || cursor_in_echo_area)
+  
+  /* Give up if current matrix is not up to date or we are 
+     displaying a message.  */
+  if (!display_completed || cursor_in_echo_area)
+    return 0;
+
+  /* Give up if the buffer's direction is reversed.  */
+  if (!NILP (XBUFFER (w->buffer)->direction_reversed))
     return 0;
 
   /* Can't use direct output if highlighting a region.  */
   if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
     return 0;
 
-  /* Can't use direct output at an overlay boundary; it might have
-     before-string or after-string properties.  */
-  if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
-    return 0;
-
-#ifdef USE_TEXT_PROPERTIES
-  /* Don't use direct output next to an invisible character
-     since we might need to do something special.  */
-
-  XSETFASTINT (position, PT);
-  if (XFASTINT (position) < ZV
-      && ! NILP (Fget_char_property (position,
-				     Qinvisible,
-				     selected_window)))
+  row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+
+  if (PT <= MATRIX_ROW_START_BYTEPOS (row)
+      || PT >= MATRIX_ROW_END_BYTEPOS (row))
     return 0;
 
-  XSETFASTINT (position, PT - 1);
-  if (XFASTINT (position) >= BEGV
-      && ! NILP (Fget_char_property (position,
-				     Qinvisible,
-				     selected_window)))
-    return 0;
-#endif
-
-  FRAME_CURSOR_X (frame) += n;
-  XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
+  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+  w->last_cursor = w->cursor;
   XSETFASTINT (w->last_point, PT);
-  cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
+
+  xassert (w->cursor.hpos >= 0
+	   && w->cursor.hpos < w->desired_matrix->matrix_w);
+  
+  if (FRAME_WINDOW_P (f))
+    rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
+		    w->cursor.y, w->cursor.x);
+  else
+    {
+      int x, y;
+      x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
+	   + (INTEGERP (w->left_margin_width)
+	      ? XFASTINT (w->left_margin_width)
+	      : 0));
+      y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
+      cursor_to (y, x);
+    }
+  
   fflush (stdout);
-
+  redisplay_performed_directly_p = 1;
   return 1;
 }
+
+
 
-static void update_line ();
-
-/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
-   Value is nonzero if redisplay stopped due to pending input.
-   FORCE nonzero means do not stop for pending input.  */
+/***********************************************************************
+			     Frame Update
+ ***********************************************************************/
+
+/* Update frame F based on the data in desired matrices.
+
+   If FORCE_P is non-zero, don't let redisplay be stopped by detecting
+   pending input.  If INHIBIT_HAIRY_ID_P is non-zero, don't try
+   scrolling.
+   
+   Value is non-zero if redisplay was stopped due to pending input.  */
 
 int
-update_frame (f, force, inhibit_hairy_id)
-     FRAME_PTR f;
-     int force;
-     int inhibit_hairy_id;
+update_frame (f, force_p, inhibit_hairy_id_p)
+     struct frame *f;
+     int force_p;
+     int inhibit_hairy_id_p;
+{
+  /* 1 means display has been paused because of pending input.  */
+  int paused_p;
+  struct window *root_window = XWINDOW (f->root_window);
+
+  if (FRAME_WINDOW_P (f))
+    {
+      /* We are working on window matrix basis.  All windows whose
+	 flag must_be_updated_p is set have to be updated.  */
+
+      /* Record that we are not working on frame matrices.  */
+      set_frame_matrix_frame (NULL);
+
+      /* Update all windows in the window tree of F, maybe stopping
+	 when pending input is detected.  */
+      update_begin (f);
+
+      /* Update the menu bar on X frames that don't have toolkit
+	 support.  */
+      if (WINDOWP (f->menu_bar_window))
+	update_window (XWINDOW (f->menu_bar_window), 1);
+
+      /* Update the tool-bar window, if present.  */
+      if (WINDOWP (f->toolbar_window))
+	{
+	  Lisp_Object tem;
+	  struct window *w = XWINDOW (f->toolbar_window);
+
+	  /* Update tool-bar window.  */
+	  if (w->must_be_updated_p)
+	    {
+	      update_window (w, 1);
+	      w->must_be_updated_p = 0;
+
+	      /* Swap tool-bar strings.  We swap because we want to
+		 reuse strings.  */
+	      tem = f->current_toolbar_string;
+	      f->current_toolbar_string = f->desired_toolbar_string;
+	      f->desired_toolbar_string = tem;
+	      f->n_current_toolbar_items = f->n_desired_toolbar_items;
+	      
+	      /* Swap tool-bar items.  We swap because we want to
+		 reuse vectors.  */
+	      tem = f->current_toolbar_items;
+	      f->current_toolbar_items = f->desired_toolbar_items;
+	      f->desired_toolbar_items = tem;
+	    }
+	}
+  
+
+      /* Update windows.  */
+      paused_p = update_window_tree (root_window, force_p);
+      update_end (f);
+      display_completed = !paused_p;
+
+      /* The flush is a performance bottleneck under X.  */
+#if 0
+      rif->flush_display (f);
+#endif
+    }
+  else
+    {
+      /* We are working on frame matrix basis.  Set the frame on whose
+	 frame matrix we operate.  */
+      set_frame_matrix_frame (f);
+
+      /* Build F's desired matrix from window matrices.  For windows
+	 whose must_be_updated_p flag is set, desired matrices are
+	 made part of the desired frame matrix.  For other windows,
+	 the current matrix is copied.  */
+      build_frame_matrix (f);
+      
+      /* Do the update on the frame desired matrix.  */
+      paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
+      
+      /* Check window matrices for lost pointers.  */
+      IF_DEBUG (check_window_matrix_pointers (root_window));
+    }
+
+  /* Reset flags indicating that a window should be updated.  */
+  set_window_update_flags (root_window, 0);
+  return paused_p;
+}
+
+
+
+/************************************************************************
+			 Window-based updates
+ ************************************************************************/
+
+/* Perform updates in window tree rooted at W.  FORCE_P non-zero means
+   don't stop updating when input is pending.  */
+
+static int
+update_window_tree (w, force_p)
+     struct window *w;
+     int force_p;
+{
+  int paused_p = 0;
+  
+  while (w && !paused_p)
+    {
+      if (!NILP (w->hchild))
+	paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
+      else if (!NILP (w->vchild))
+	paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
+      else if (w->must_be_updated_p)
+	paused_p |= update_window (w, force_p);
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+
+  return paused_p;
+}
+
+
+/* Update window W if its flag must_be_updated_p is non-zero.  If
+   FORCE_P is non-zero, don't stop updating if input is pending.  */
+
+void
+update_single_window (w, force_p)
+     struct window *w;
+     int force_p;
+{
+  if (w->must_be_updated_p)
+    {
+      struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+      /* Record that this is not a frame-based redisplay.  */
+      set_frame_matrix_frame (NULL);
+
+      /* Update W.  */
+      update_begin (f);
+      update_window (w, force_p);
+      update_end (f);
+
+      /* Reset flag in W.  */
+      w->must_be_updated_p = 0;
+    }
+}
+
+
+/* Update display of window W.  FORCE_P non-zero means that we should
+   not stop when detecting pending input.  */
+
+static int
+update_window (w, force_p)
+     struct window *w;
+     int force_p;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct glyph_matrix *desired_matrix = w->desired_matrix;
+  int paused_p;
+  int preempt_count = baud_rate / 2400 + 1;
+  extern int input_pending;
+  extern struct frame *updating_frame;
+
+  /* Check that W's frame doesn't have glyph matrices.  */
+  xassert (FRAME_WINDOW_P (f));
+  xassert (updating_frame != NULL);
+
+  /* Check pending input the first time so that we can quickly return.  */
+  if (redisplay_dont_pause)
+    force_p = 1;
+  else
+    detect_input_pending ();
+
+  /* If forced to complete the update, or if no input is pending, do
+     the update.  */
+  if (force_p || !input_pending)
+    {
+      struct glyph_row *row, *end;
+      struct glyph_row *mode_line_row;
+      struct glyph_row *top_line_row = NULL;
+      int yb;
+
+      rif->update_window_begin_hook (w);
+      yb = window_text_bottom_y (w);
+
+      /* If window has a top line, update it before everything else.
+	 Adjust y-positions of other rows by the top line height.  */
+      row = desired_matrix->rows;
+      end = row + desired_matrix->nrows - 1;
+      if (row->mode_line_p)
+	top_line_row = row++;
+
+      /* Update the mode line, if necessary.  */
+      mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
+      if (mode_line_row->mode_line_p && mode_line_row->enabled_p)
+	{
+	  mode_line_row->y = yb;
+	  update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
+						  desired_matrix));
+	}
+
+      /* Find first enabled row.  Optimizations in redisplay_internal
+	 may lead to an update with only one row enabled.  There may
+	 be also completely empty matrices.  */
+      while (row < end && !row->enabled_p)
+	++row;
+      
+      /* Try reusing part of the display by inserting/deleting lines.  */
+      if (row < end && !desired_matrix->no_scrolling_p)
+	{
+	  int rc = scrolling_window (w, top_line_row != NULL);
+	  if (rc < 0)
+	    {
+	      /* All rows were found to be equal.  */
+	      paused_p = 0;
+	      goto set_cursor;
+	    }
+	  else if (rc > 0)
+	    force_p = 1;
+	}
+
+      /* Update the top mode line after scrolling because a new top
+	 line would otherwise overwrite lines at the top of the window
+	 that can be scrolled.  */
+      if (top_line_row && top_line_row->enabled_p)
+	{
+	  top_line_row->y = 0;
+	  update_window_line (w, 0);
+	}
+
+      /* Update the rest of the lines.  */
+      for (; row < end && (force_p || !input_pending); ++row)
+	if (row->enabled_p
+	    /* A row can be completely invisible in case a desired
+	       matrix was built with a vscroll and then
+	       make_cursor_line_fully_visible shifts the matrix.  */
+	    && row->visible_height > 0)
+	  {
+	    int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
+	    int i;
+	    
+	    /* We'll Have to play a little bit with when to
+	       detect_input_pending.  If it's done too often,
+	       scrolling large windows with repeated scroll-up
+	       commands will too quickly pause redisplay.  */
+	    if (!force_p && vpos % preempt_count == 0)
+	      detect_input_pending ();
+
+	    update_window_line (w, vpos);
+
+	    /* Mark all rows below the last visible one in the current
+	       matrix as invalid.  This is necessary because of
+	       variable line heights.  Consider the case of three
+	       successive redisplays, where the first displays 5
+	       lines, the second 3 lines, and the third 5 lines again.
+	       If the second redisplay wouldn't mark rows in the
+	       current matrix invalid, the third redisplay might be
+	       tempted to optimize redisplay based on lines displayed
+	       in the first redisplay.  */
+	    if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
+	      for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
+		MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
+	  }
+
+      /* Was display preempted?  */
+      paused_p = row < end;
+      
+    set_cursor:
+      
+      if (!paused_p && !w->pseudo_window_p)
+	{
+	  /* Make cursor visible at cursor position of W.  */
+	  set_window_cursor_after_update (w);
+
+#if 0
+	  /* Check that current matrix invariants are satisfied.  This
+	     is for debugging only.  See the comment around
+	     check_matrix_invariants.  */
+	  IF_DEBUG (check_matrix_invariants (w));
+#endif
+	}
+
+#if GLYPH_DEBUG
+      /* Remember the redisplay method used to display the matrix.  */
+      strcpy (w->current_matrix->method, w->desired_matrix->method);
+#endif
+      
+      /* End of update of window W.  */
+      rif->update_window_end_hook (w, 1);
+    }
+  else
+    paused_p = 1;
+
+  clear_glyph_matrix (desired_matrix);
+  return paused_p;
+}
+
+
+/* Update the display of area AREA in window W, row number VPOS.
+   AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA.  */
+
+static void
+update_marginal_area (w, area, vpos)
+     struct window *w;
+     int area, vpos;
+{
+  struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+
+  /* Let functions in xterm.c know what area subsequent X positions
+     will be relative to.  */
+  updated_area = area;
+
+  /* Set cursor to start of glyphs, write them, and clear to the end
+     of the area.  I don't think that something more sophisticated is
+     necessary here, since marginal areas will not be the default.  */
+  rif->cursor_to (vpos, 0, desired_row->y, 0);
+  if (desired_row->used[area])
+    rif->write_glyphs (desired_row->glyphs[area], desired_row->used[area]);
+  rif->clear_end_of_line (-1);
+}
+
+
+/* Update the display of the text area of row VPOS in window W.  */
+
+static void
+update_text_area (w, vpos)
+     struct window *w;
+     int vpos;
 {
-  register struct frame_glyphs *current_frame;
-  register struct frame_glyphs *desired_frame = 0;
-  register int i;
+  struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
+  struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+
+  /* Let functions in xterm.c know what area subsequent X positions
+     will be relative to.  */
+  updated_area = TEXT_AREA;
+  
+  /* If rows are at different X or Y, or rows have different height,
+     or the current row is marked invalid, write the entire line.  */
+  if (!current_row->enabled_p
+      || desired_row->y != current_row->y
+      || desired_row->ascent != current_row->ascent
+      || desired_row->visible_height != current_row->visible_height
+      || current_row->x != desired_row->x)
+    {
+      rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
+      
+      if (desired_row->used[TEXT_AREA])
+	rif->write_glyphs (desired_row->glyphs[TEXT_AREA],
+			   desired_row->used[TEXT_AREA]);
+      
+      /* Clear to end of window.  */
+      rif->clear_end_of_line (-1);
+    }
+  else
+    {
+      int stop, i, x;
+      struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
+      struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
+
+      /* If the desired row extends its face to the text area end,
+	 make sure we write at least one glyph, so that the face
+	 extension actually takes place.  */
+      int desired_stop_pos = (desired_row->used[TEXT_AREA]
+			      - (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
+				 ? 1 : 0));
+      
+      stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
+      i = 0;
+      x = desired_row->x;
+      
+      while (i < stop)
+	{
+	  /* Skip over glyphs that both rows have in common.  These
+	     don't have to be written.  */
+	  while (i < stop
+		 && GLYPH_EQUAL_P (desired_glyph, current_glyph))
+	    {
+	      x += desired_glyph->pixel_width;
+	      ++desired_glyph, ++current_glyph, ++i;
+	    }
+
+	  /* Consider the case that the current row contains "xxx ppp
+	     ggg" in italic Courier font, and the desired row is "xxx
+	     ggg".  The character `p' has lbearing, `g' has not.  The
+	     loop above will stop in front of the first `p' in the
+	     current row.  If we would start writing glyphs there, we
+	     wouldn't erase the lbearing of the `p'.  The rest of the
+	     lbearing problem is then taken care of by x_draw_glyphs.  */
+	  if (current_row->contains_overlapping_glyphs_p
+	      && i > 0
+	      && i < current_row->used[TEXT_AREA]
+	      && current_row->used[TEXT_AREA] != desired_row->used[TEXT_AREA])
+	    {
+	      int left, right;
+	      rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+					&left, &right);
+	      while (left > 0 && i > 0)
+		{
+		  --i, --desired_glyph, --current_glyph;
+		  x -= desired_glyph->pixel_width;
+		  left -= desired_glyph->pixel_width;
+		}
+	    }
+	  
+	  /* Try to avoid writing the entire rest of the desired row
+	     by looking for a resync point.  This mainly prevents
+	     mode line flickering in the case the mode line is in
+	     fixed-pitch font, which it usually will be.  */
+	  if (i < desired_row->used[TEXT_AREA])
+	    {
+	      int start_x = x, start_hpos = i;
+	      struct glyph *start = desired_glyph;
+	      int current_x = x;
+	      
+	      /* Find the next glyph that's equal again.  */
+	      while (i < stop
+		     && !GLYPH_EQUAL_P (desired_glyph, current_glyph)
+		     && x == current_x)
+		{
+		  x += desired_glyph->pixel_width;
+		  current_x += current_glyph->pixel_width;
+		  ++desired_glyph, ++current_glyph, ++i;
+		}
+
+	      if (i == start_hpos || x != current_x)
+		{
+		  i = start_hpos;
+		  x = start_x;
+		  desired_glyph = start;
+		  break;
+		}
+	      
+	      rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
+	      rif->write_glyphs (start, i - start_hpos);
+	    }
+	}
+      
+      /* Write the rest.  */
+      if (i < desired_row->used[TEXT_AREA])
+	{
+	  rif->cursor_to (vpos, i, desired_row->y, x);
+	  rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i);
+	}
+      
+      /* Maybe clear to end of line.  */
+      if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
+	{
+	  /* If new row extends to the end of the text area, nothing
+	     has to be cleared, if and only if we did a write_glyphs
+	     above.  This is made sure by setting desired_stop_pos
+	     appropriately above.  */
+	  xassert (i < desired_row->used[TEXT_AREA]);
+	}
+      else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
+	{
+	  /* If old row extends to the end of the text area, clear.  */
+	  if (i >= desired_row->used[TEXT_AREA])
+	    rif->cursor_to (vpos, i, desired_row->y,
+			    desired_row->x + desired_row->pixel_width);
+	  rif->clear_end_of_line (-1);
+	}
+      else if (desired_row->pixel_width < current_row->pixel_width)
+	{
+	  /* Otherwise clear to the end of the old row.  Everything
+	     after that position should be clear already.  */
+	  int x;
+	  
+	  if (i >= desired_row->used[TEXT_AREA])
+	    rif->cursor_to (vpos, i, desired_row->y,
+			    desired_row->x + desired_row->pixel_width);
+
+	  /* If cursor is displayed at the end of the line, make sure
+	     it's cleared.  Nowadays we don't have a phys_cursor_glyph
+	     with which to erase the cursor (because this method
+	     doesn't work with lbearing/rbearing), so we must do it
+	     this way.  */
+	  if (vpos == w->phys_cursor.vpos
+	      && w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])
+	    {
+	      w->phys_cursor_on_p = 0;
+	      x = -1;
+	    }
+	  else
+	    x = current_row->x + current_row->pixel_width;
+	  rif->clear_end_of_line (x);
+	}
+    }
+}
+
+
+/* Update row VPOS in window W.  */
+
+static void
+update_window_line (w, vpos)
+     struct window *w;
+     int vpos;
+{
+  struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
+  struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+
+  xassert (desired_row->enabled_p);
+
+  /* Set the row being updated.  This is important to let xterm.c
+     know what line height values are in effect.  */
+  updated_row = desired_row;
+
+  /* Update display of the left margin area, if there is one.  */
+  if (!desired_row->full_width_p
+      && !NILP (w->left_margin_width))
+    update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+  
+  /* Update the display of the text area.  */
+  update_text_area (w, vpos);
+  
+  /* Update display of the right margin area, if there is one.  */
+  if (!desired_row->full_width_p
+      && !NILP (w->right_margin_width))
+    update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+  
+  /* Draw truncation marks etc.  */
+  if (!current_row->enabled_p
+      || desired_row->y != current_row->y
+      || desired_row->visible_height != current_row->visible_height
+      || desired_row->overlay_arrow_p != current_row->overlay_arrow_p
+      || desired_row->truncated_on_left_p != current_row->truncated_on_left_p
+      || desired_row->truncated_on_right_p != current_row->truncated_on_right_p
+      || desired_row->continued_p != current_row->continued_p
+      || desired_row->mode_line_p != current_row->mode_line_p
+      || (desired_row->indicate_empty_line_p
+	  != current_row->indicate_empty_line_p)
+      || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
+	  != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
+    rif->after_update_window_line_hook (desired_row);
+  
+  /* Update current_row from desired_row.  */
+  make_current (w->desired_matrix, w->current_matrix, vpos);
+  updated_row = NULL;
+}
+
+
+/* Set the cursor after an update of window W.  This function may only
+   be called from update_window.  */
+
+static void
+set_window_cursor_after_update (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  int cx, cy, vpos, hpos;
+
+  /* Not intended for frame matrix updates.  */
+  xassert (FRAME_WINDOW_P (f));
+  
+  if ((cursor_in_echo_area
+       /* If we are showing a message instead of the mini-buffer,
+	  show the cursor for the message instead of for the
+	  (now hidden) mini-buffer contents.  */
+       || (XWINDOW (minibuf_window) == w
+	   && EQ (minibuf_window, echo_area_window)
+	   && (echo_area_glyphs || STRINGP (echo_area_message))))
+      /* These cases apply only to the frame that contains
+	 the active mini-buffer window.  */
+      && FRAME_HAS_MINIBUF_P (f)
+      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+    {
+      cx = cy = vpos = hpos = 0;
+
+      if (cursor_in_echo_area >= 0)
+	{
+	  /* If the mini-buffer is several lines high, find the last
+	     line that has any text on it.  Note: either all lines
+	     are enabled or none.  Otherwise we wouldn't be able to
+	     determine Y.  */
+	  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
+	  int vpos, last_row_vpos;
+	  struct glyph_row *last_row = NULL;
+
+	  vpos = 0;
+	  while (vpos < w->current_matrix->nrows)
+	    {
+	      if (row->enabled_p && row->used[TEXT_AREA])
+		{
+		  last_row = row;
+		  last_row_vpos = vpos;
+		}
+	      ++row;
+	      ++vpos;
+	    }
+
+	  if (last_row)
+	    {
+	      cx = last_row->pixel_width;
+	      hpos = last_row->used[TEXT_AREA];
+	      cy = last_row->y;
+	      vpos = last_row_vpos;
+	    }
+	}
+    }
+  else
+    {
+      cx = w->cursor.x;
+      cy = w->cursor.y;
+      hpos = w->cursor.hpos;
+      vpos = w->cursor.vpos;
+    }
+
+  /* Window cursor can be out of sync for horizontally split windows.  */
+  hpos = max (0, hpos);
+  hpos = min (w->current_matrix->matrix_w - 1, hpos);
+  vpos = max (0, vpos);
+  vpos = min (w->current_matrix->nrows - 1, vpos);
+  rif->cursor_to (vpos, hpos, cy, cx);
+}
+
+
+/* Try to reuse part of the current display of W by scrolling lines.
+   TOP_LINE_P non-zero means W has a top mode line.
+
+   The algorithm is taken from Communications of the ACM, Apr78 "A
+   Technique for Isolating Differences Between Files."  It should take
+   O(N) time.
+
+   A short outline of the steps of the algorithm
+
+   1. Skip lines equal at the start and end of both matrices.
+
+   2. Enter rows in the current and desired matrix into a symbol
+   table, counting how often they appear in both matrices.
+
+   3. Rows that appear exactly once in both matrices serve as anchors,
+   i.e. we assume that such lines are likely to have been moved.
+
+   4. Starting from anchor lines, extend regions to be scrolled both
+   forward and backward.
+
+   Value is
+
+   -1	if all rows were found to be equal.
+   0	to indicate that we did not scroll the display, or
+   1	if we did scroll.  */
+
+static int
+scrolling_window (w, top_line_p)
+     struct window *w;
+     int top_line_p;
+{
+  struct symbol 
+  {
+    /* Number of occurrences of this line in old and new matrix.  */
+    short old_uses, new_uses;
+    
+    /* Vpos of line in new matrix.  */
+    short new_line_number;
+    
+    /* The line itself.  */
+    struct glyph_row *row;
+    
+    /* Hash collision chain.  */
+    struct symbol *next;
+  };
+
+  int SYMBOL_TABLE_SIZE = 101;
+  struct symbol **table;
+  struct symbol **old_line_syms, **new_line_syms;
+  int i, j, first_old, first_new, last_old, last_new;
+  struct symbol *sym;
+  struct run **runs;
+  int nruns;
+  struct glyph_matrix *desired_matrix = w->desired_matrix;
+  struct glyph_matrix *current_matrix = w->current_matrix;
+  int yb = window_text_bottom_y (w);
+
+  /* Skip over rows equal at the start.  */
+  i = top_line_p ? 1 : 0;
+  while (i < current_matrix->nrows - 1
+         && MATRIX_ROW_ENABLED_P (current_matrix, i)
+	 && MATRIX_ROW_ENABLED_P (desired_matrix, i)
+	 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb
+	 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb
+         && row_equal_p (w,
+			 MATRIX_ROW (desired_matrix, i),
+                         MATRIX_ROW (current_matrix, i)))
+    {
+      assign_row (MATRIX_ROW (current_matrix, i),
+		  MATRIX_ROW (desired_matrix, i));
+      MATRIX_ROW (desired_matrix, i)->enabled_p = 0;
+      ++i;
+    }
+
+  /* Give up if some rows in the desired matrix are not enabled.  */
+  if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
+    return -1;
+  
+  first_old = first_new = i;
+
+  /* Set last_new to the index + 1 of the last enabled row in the
+     desired matrix.  */
+  i = first_new + 1;
+  while (i < desired_matrix->nrows - 1
+	 && MATRIX_ROW (desired_matrix, i)->enabled_p
+	 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb)
+    ++i;
+
+  if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
+    return 0;
+
+  last_new = i;
+
+  /* Set last_old to the index + 1 of the last enabled row in the
+     current matrix.  We don't look at the enabled flag here because
+     we plan to reuse part of the display even if other parts are
+     disabled.  */
+  i = first_old + 1;
+  while (i < current_matrix->nrows - 1
+	 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb)
+    ++i;
+  last_old = i;
+
+  /* Skip over rows equal at the bottom.  */
+  i = last_new;
+  j = last_old;
+  while (i - 1 > first_new
+         && j - 1 > first_old
+         && MATRIX_ROW (current_matrix, i - 1)->enabled_p
+	 && (MATRIX_ROW (current_matrix, i - 1)->y
+	     == MATRIX_ROW (desired_matrix, j - 1)->y)
+         && row_equal_p (w,
+			 MATRIX_ROW (desired_matrix, i - 1),
+                         MATRIX_ROW (current_matrix, j - 1)))
+    --i, --j;
+  last_new = i;
+  last_old = j;
+
+  /* Nothing to do if all rows are equal.  */
+  if (last_new == first_new)
+    return 0;
+
+  /* Allocate a hash table in which all rows will be inserted.  */
+  table = (struct symbol **) alloca (SYMBOL_TABLE_SIZE * sizeof *table);
+  bzero (table, SYMBOL_TABLE_SIZE * sizeof *table);
+
+  /* For each row in the current matrix, record the symbol belonging
+     to the row in OLD_LINE_SYMS.  */
+  old_line_syms = (struct symbol **) alloca (current_matrix->nrows
+					     * sizeof *old_line_syms);
+  new_line_syms = (struct symbol **) alloca (desired_matrix->nrows
+					     * sizeof *new_line_syms);
+
+#define ADDSYM(ROW) 						\
+  do								\
+    {								\
+      struct glyph_row *row_ = (ROW);				\
+      int i_ = row_->hash % SYMBOL_TABLE_SIZE;			\
+      sym = table[i_];						\
+      while (sym && !row_equal_p (w, sym->row, row_))		\
+        sym = sym->next;					\
+      if (sym == NULL)						\
+	{							\
+	  sym = (struct symbol *) alloca (sizeof *sym);		\
+	  sym->row = row_;					\
+	  sym->old_uses = sym->new_uses = 0;			\
+	  sym->next = table[i_];				\
+	  table[i_] = sym;					\
+	}							\
+    }								\
+  while (0)
+
+  /* Add current rows to the symbol table.  */
+  for (i = first_old; i < last_old; ++i)
+    {
+      if (MATRIX_ROW (current_matrix, i)->enabled_p)
+	{
+	  ADDSYM (MATRIX_ROW (current_matrix, i));
+	  old_line_syms[i] = sym;
+	  ++sym->old_uses;
+	}
+      else
+	old_line_syms[i] = NULL;
+    }
+
+  /* Add desired rows to the symbol table.  */
+  for (i = first_new; i < last_new; ++i)
+    {
+      xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i));
+      ADDSYM (MATRIX_ROW (desired_matrix, i));
+      ++sym->new_uses;
+      new_line_syms[i] = sym;
+      sym->new_line_number = i;
+    }
+
+#undef ADDSYM
+
+  /* Record in runs which moves were found, ordered by pixel
+     height of copied areas.  */
+  nruns = 0;
+  runs = (struct run **) alloca (desired_matrix->nrows * sizeof *runs);
+
+  /* Identify moves based on lines that are unique and equal
+     in both matrices.  */
+  for (i = first_old; i < last_old;)
+    if (old_line_syms[i]
+	&& old_line_syms[i]->old_uses == 1
+        && old_line_syms[i]->new_uses == 1)
+      {
+	int j, k;
+	int new_line = old_line_syms[i]->new_line_number;
+	struct run *run = (struct run *) alloca (sizeof *run);
+
+	/* Record move.  */
+	run->current_vpos = i;
+	run->current_y = MATRIX_ROW (current_matrix, i)->y;
+	run->desired_vpos = new_line;
+	run->desired_y = MATRIX_ROW (desired_matrix, new_line)->y;
+	run->nrows = 1;
+	run->height = MATRIX_ROW (current_matrix, i)->height;
+
+	/* Extend backward.  */
+	j = i - 1;
+	k = new_line - 1;
+	while (j > first_old
+	       && k > first_new
+	       && old_line_syms[j] == new_line_syms[k])
+	  {
+	    int h = MATRIX_ROW (current_matrix, j)->height;
+	    --run->current_vpos; 
+	    --run->desired_vpos; 
+	    ++run->nrows;
+	    run->height += h;
+	    run->desired_y -= h;
+	    run->current_y -= h;
+	    --j, --k;
+	  }
+
+	/* Extend forward.  */
+	j = i + 1;
+	k = new_line + 1;
+	while (j < last_old
+	       && k < last_new
+	       && old_line_syms[j] == new_line_syms[k])
+	  {
+	    int h = MATRIX_ROW (current_matrix, j)->height;
+	    ++run->nrows; 
+	    run->height += h;
+	    ++j, ++k;
+	  }
+
+	/* Insert run into list of all runs.  Order runs by copied
+	   pixel lines.  Note that we record runs that don't have to
+	   be copied because they are already in place.  This is done
+	   because we can avoid calling update_window_line in this
+	   case.  */
+	for (j = 0; j < nruns && runs[j]->height > run->height; ++j)
+	  ;
+	for (k = nruns; k >= j; --k)
+	  runs[k] = runs[k - 1];
+	runs[j] = run;
+	++nruns;
+
+	i += run->nrows;
+      }
+    else
+      ++i;
+
+  /* Do the moves.  Do it in a way that we don't overwrite something
+     we want to copy later on.  This is not solvable in general
+     because there is only one display and we don't have a way to
+     exchange areas on this display.  Example:
+
+          +-----------+       +-----------+
+          |     A     |       |     B     |
+          +-----------+  -->  +-----------+
+          |     B     |       |     A     |
+          +-----------+       +-----------+
+
+     Instead, prefer bigger moves, and invalidate moves that would
+     copy from where we copied to.  */
+
+  for (i = 0; i < nruns; ++i)
+    if (runs[i]->nrows > 0)
+      {
+	struct run *r = runs[i];
+
+	/* Copy on the display.  */
+	if (r->current_y != r->desired_y)
+	  {
+	    rif->scroll_run_hook (w, r);
+
+	    /* Invalidate runs that copy from where we copied to.  */
+	    for (j = i + 1; j < nruns; ++j)
+	      {
+		struct run *p = runs[j];
+		
+		if ((p->current_y >= r->desired_y
+		     && p->current_y < r->desired_y + r->height)
+		    || (p->current_y + p->height >= r->desired_y
+			&& (p->current_y + p->height
+			    < r->desired_y + r->height)))
+		  p->nrows = 0;
+	      }
+	  }
+
+	/* Assign matrix rows.  */
+	for (j = 0; j < r->nrows; ++j)
+	  {
+	    struct glyph_row *from, *to;
+	    to = MATRIX_ROW (current_matrix, r->desired_vpos + j);
+	    from = MATRIX_ROW (desired_matrix, r->desired_vpos + j);
+	    assign_row (to, from);
+	    to->enabled_p = 1, from->enabled_p = 0;
+	  }
+      }
+
+  /* Value is non-zero to indicate that we scrolled the display.  */
+  return 1;
+}
+
+
+/* Set WINDOW->must_be_updated_p TO ON_P for all windows WINDOW in the
+   window tree rooted at W.  */
+
+void
+set_window_update_flags (w, on_p)
+     struct window *w;
+     int on_p;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+	set_window_update_flags (XWINDOW (w->hchild), on_p);
+      else if (!NILP (w->vchild))
+	set_window_update_flags (XWINDOW (w->vchild), on_p);
+      else
+	w->must_be_updated_p = on_p;
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}    
+
+
+
+/************************************************************************
+			 Frame-Based Updates
+ ************************************************************************/
+
+/* Update the desired frame matrix of frame F.
+
+   FORCE_P non-zero means that the update should not be stopped by
+   pending input.  INHIBIT_HAIRY_ID_P non-zero means that scrolling
+   should not be tried.
+
+   Value is non-zero if update was stopped due to pending input.  */
+
+static int
+update_frame_1 (f, force_p, inhibit_id_p)
+     struct frame *f;
+     int force_p;
+     int inhibit_id_p;
+{
+  /* Frame matrices to work on.  */
+  struct glyph_matrix *current_matrix = f->current_matrix;
+  struct glyph_matrix *desired_matrix = f->desired_matrix;
+  int i;
   int pause;
   int preempt_count = baud_rate / 2400 + 1;
   extern int input_pending;
-#ifdef HAVE_WINDOW_SYSTEM
-  register int downto, leftmost;
-#endif
+
+  xassert (current_matrix && desired_matrix);
 
   if (baud_rate != FRAME_COST_BAUD_RATE (f))
     calculate_costs (f);
@@ -1230,10 +4276,8 @@
   if (preempt_count <= 0)
     preempt_count = 1;
 
-  if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
-
   detect_input_pending ();
-  if (input_pending && !force)
+  if (input_pending && !force_p)
     {
       pause = 1;
       goto do_pause;
@@ -1241,48 +4285,28 @@
 
   update_begin (f);
 
+  /* If we cannot insert/delete lines, it's no use trying it.  */
   if (!line_ins_del_ok)
-    inhibit_hairy_id = 1;
-
-  /* These are separate to avoid a possible bug in the AIX C compiler.  */
-  current_frame = FRAME_CURRENT_GLYPHS (f);
-  desired_frame = FRAME_DESIRED_GLYPHS (f);
+    inhibit_id_p = 1;
 
   /* See if any of the desired lines are enabled; don't compute for
-     i/d line if just want cursor motion. */
-  for (i = 0; i < FRAME_HEIGHT (f); i++)
-    if (desired_frame->enable[i])
+     i/d line if just want cursor motion.  */
+  for (i = 0; i < desired_matrix->nrows; i++)
+    if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
       break;
 
   /* Try doing i/d line, if not yet inhibited.  */
-  if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
-    force |= scrolling (f);
+  if (!inhibit_id_p && i < desired_matrix->nrows)
+    force_p |= scrolling (f);
 
   /* Update the individual lines as needed.  Do bottom line first.  */
-
-  if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
-    update_line (f, FRAME_HEIGHT (f) - 1);
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (f))
+  if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1))
+    update_frame_line (f, desired_matrix->nrows - 1);
+
+  /* Now update the rest of the lines.  */
+  for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++)
     {
-      leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
-      if (desired_frame->enable[0])
-	{
-	  current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
-	  current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
-	    = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
-	      - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
-	  current_frame->top_left_x[0] = leftmost;
-	  current_frame->top_left_y[0] = downto;
-	}
-    }
-#endif /* HAVE_WINDOW_SYSTEM */
-
-  /* Now update the rest of the lines. */
-  for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
-    {
-      if (desired_frame->enable[i])
+      if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
 	{
 	  if (FRAME_TERMCAP_P (f))
 	    {
@@ -1300,7 +4324,7 @@
 #ifdef EMACS_OUTQSIZE
 		      if (EMACS_OUTQSIZE (0, &outq) < 0)
 			/* Probably not a tty.  Ignore the error and reset
-			 * the outq count. */
+			 * the outq count.  */
 			outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
 		      outq *= 10;
@@ -1313,35 +4337,24 @@
 	  if ((i - 1) % preempt_count == 0)
 	    detect_input_pending ();
 
-	  update_line (f, i);
-#ifdef HAVE_WINDOW_SYSTEM
-	  if (FRAME_WINDOW_P (f))
-	    {
-	      current_frame->top_left_y[i] = downto;
-	      current_frame->top_left_x[i] = leftmost;
-	    }
-#endif /* HAVE_WINDOW_SYSTEM */
+	  update_frame_line (f, i);
 	}
-
-#ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_WINDOW_P (f))
-	downto += current_frame->pix_height[i];
-#endif /* HAVE_WINDOW_SYSTEM */
     }
+  
   pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
 
   /* Now just clean up termcap drivers and set cursor, etc.  */
   if (!pause)
     {
       if ((cursor_in_echo_area
-	   /* If we are showing a message instead of the minibuffer,
+	   /* If we are showing a message instead of the mini-buffer,
 	      show the cursor for the message instead of for the
-	      (now hidden) minibuffer contents.  */
+	      (now hidden) mini-buffer contents.  */
 	   || (EQ (minibuf_window, selected_window)
 	       && EQ (minibuf_window, echo_area_window)
-	       && echo_area_glyphs != 0))
+	       && (echo_area_glyphs || STRINGP (echo_area_message))))
 	  /* These cases apply only to the frame that contains
-	     the active minibuffer window.  */
+	     the active mini-buffer window.  */
 	  && FRAME_HAS_MINIBUF_P (f)
 	  && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
 	{
@@ -1350,21 +4363,39 @@
 
 	  if (cursor_in_echo_area < 0)
 	    {
+	      /* Negative value of cursor_in_echo_area means put
+                 cursor at beginning of line.  */
 	      row = top;
 	      col = 0;
 	    }
 	  else
 	    {
-	      /* If the minibuffer is several lines high, find the last
-		 line that has any text on it.  */
+	      /* Positive value of cursor_in_echo_area means put
+		 cursor at the end of the prompt.  If the mini-buffer
+		 is several lines high, find the last line that has
+		 any text on it.  */
 	      row = FRAME_HEIGHT (f);
 	      do 
 		{
-		  row--;
-		  if (current_frame->enable[row])
-		    col = current_frame->used[row];
-		  else
-		    col = 0;
+		  --row;
+		  col = 0;
+		  
+		  if (MATRIX_ROW_ENABLED_P (current_matrix, row))
+		    {
+		      /* Frame rows are filled up with spaces that
+			 must be ignored here.  */
+		      int i;
+		      struct glyph_row *r = MATRIX_ROW (current_matrix,
+							row);
+		      struct glyph *start = r->glyphs[TEXT_AREA];
+		      struct glyph *last = start + r->used[TEXT_AREA];
+
+		      while (last > start
+			     && (last - 1)->charpos < 0)
+			--last;
+		      
+		      col = last - start;
+		    }
 		}
 	      while (row > top && col == 0);
 
@@ -1386,9 +4417,22 @@
 	  cursor_to (row, col);
 	}
       else
-	cursor_to (FRAME_CURSOR_Y (f), 
-		   minmax (0, FRAME_CURSOR_X (f),
-			   FRAME_CURSOR_X_LIMIT (f) - 1));
+	{
+	  /* We have only one cursor on terminal frames.  Use it to
+	     display the cursor of the selected window.  */
+	  struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+	  if (w->cursor.vpos >= 0)
+	    {
+	      int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
+	      int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
+
+	      if (INTEGERP (w->left_margin_width))
+		x += XFASTINT (w->left_margin_width);
+	      
+	      /* x = max (min (x, FRAME_WINDOW_WIDTH (f) - 1), 0); */
+	      cursor_to (y, x);
+	    }
+	}
     }
 
   update_end (f);
@@ -1397,39 +4441,19 @@
     fflush (termscript);
   fflush (stdout);
 
-  /* Here if output is preempted because input is detected.  */
  do_pause:
 
-  if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
   display_completed = !pause;
-
-  bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
+  clear_desired_matrices (f);
   return pause;
 }
 
-/* Called when about to quit, to check for doing so
-   at an improper time.  */
-
-void
-quit_error_check ()
-{
-#if 0
-  if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
-    return;
-  if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
-    abort ();
-  if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
-    abort ();
-#endif
-}
-
-/* Decide what insert/delete line to do, and do it */
-
-extern void scrolling_1 ();
+
+/* Do line insertions/deletions on frame F for frame-based redisplay.  */
 
 int
 scrolling (frame)
-     FRAME_PTR frame;
+     struct frame *frame;
 {
   int unchanged_at_top, unchanged_at_bottom;
   int window_size;
@@ -1440,24 +4464,25 @@
   int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
   register int i;
   int free_at_end_vpos = FRAME_HEIGHT (frame);
-  register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
-  register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
-
-  /* Compute hash codes of all the lines.
-     Also calculate number of changed lines,
-     number of unchanged lines at the beginning,
-     and number of unchanged lines at the end.  */
-
+  struct glyph_matrix *current_matrix = frame->current_matrix;
+  struct glyph_matrix *desired_matrix = frame->desired_matrix;
+
+  if (!current_matrix)
+    abort ();
+
+  /* Compute hash codes of all the lines.  Also calculate number of
+     changed lines, number of unchanged lines at the beginning, and
+     number of unchanged lines at the end.  */
   changed_lines = 0;
   unchanged_at_top = 0;
   unchanged_at_bottom = FRAME_HEIGHT (frame);
   for (i = 0; i < FRAME_HEIGHT (frame); i++)
     {
       /* Give up on this scrolling if some old lines are not enabled.  */
-      if (!current_frame->enable[i])
+      if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
 	return 0;
-      old_hash[i] = line_hash_code (current_frame, i);
-      if (! desired_frame->enable[i])
+      old_hash[i] = line_hash_code (MATRIX_ROW (current_matrix, i));
+      if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
 	{
 	  /* This line cannot be redrawn, so don't let scrolling mess it.  */
 	  new_hash[i] = old_hash[i];
@@ -1466,8 +4491,8 @@
 	}
       else
 	{
-	  new_hash[i] = line_hash_code (desired_frame, i);
-	  draw_cost[i] = line_draw_cost (desired_frame, i);
+	  new_hash[i] = line_hash_code (MATRIX_ROW (desired_matrix, i));
+	  draw_cost[i] = line_draw_cost (desired_matrix, i);
 	}
 
       if (old_hash[i] != new_hash[i])
@@ -1477,11 +4502,11 @@
 	}
       else if (i == unchanged_at_top)
 	unchanged_at_top++;
-      old_draw_cost[i] = line_draw_cost (current_frame, i);
+      old_draw_cost[i] = line_draw_cost (current_matrix, i);
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
-  if (!scroll_region_ok && changed_lines < baud_rate / 2400
+  if ((!scroll_region_ok && changed_lines < baud_rate / 2400)
       || unchanged_at_bottom == FRAME_HEIGHT (frame))
     return 1;
 
@@ -1494,7 +4519,7 @@
     free_at_end_vpos = -1;
 
   /* If large window, fast terminal and few lines in common between
-     current frame and desired frame, don't bother with i/d calc. */
+     current frame and desired frame, don't bother with i/d calc.  */
   if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
       && (window_size >=
 	  10 * scrolling_max_lines_saved (unchanged_at_top,
@@ -1502,6 +4527,9 @@
 					  old_hash, new_hash, draw_cost)))
     return 0;
 
+  if (window_size < 2)
+    return 0;
+
   scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
 	       draw_cost + unchanged_at_top - 1,
 	       old_draw_cost + unchanged_at_top - 1,
@@ -1511,218 +4539,174 @@
 
   return 0;
 }
-
-/* Return the offset in its buffer of the character at location col, line
-   in the given window.  */
-int
-buffer_posn_from_coords (window, col, line)
-     struct window *window;
-     int col, line;
+
+
+/* Count the number of blanks at the start of the vector of glyphs R
+   which is LEN glyphs long.  */
+
+static int
+count_blanks (r, len)
+     struct glyph *r;
+     int len;
 {
-  int hscroll = XINT (window->hscroll);
-  int window_left = WINDOW_LEFT_MARGIN (window);
-
-  /* The actual width of the window is window->width less one for the
-     DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
-     window.  */
-  int window_width = window_internal_width (window) - 1;
-
-  int startp = marker_position (window->start);
-
-  /* Since compute_motion will only operate on the current buffer,
-     we need to save the old one and restore it when we're done.  */
-  struct buffer *old_current_buffer = current_buffer;
-  struct position *posn;
-
-  current_buffer = XBUFFER (window->buffer);
-
-  /* We can't get a correct result in this case,
-     but at least prevent compute_motion from crashing.  */
-  if (startp < BEGV)
-    startp = BEGV;
-
-  /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
-     (window->frame))->bufp to avoid scanning from the very top of
-     the window, but it isn't maintained correctly, and I'm not even
-     sure I will keep it.  */
-  posn = compute_motion (startp, 0,
-			 ((window == XWINDOW (minibuf_window) && startp == BEG
-			   ? minibuf_prompt_width : 0)
-			  + (hscroll ? 1 - hscroll : 0)),
-			 0,
-			 ZV, line, col,
-			 window_width, hscroll, 0, window);
-
-  current_buffer = old_current_buffer;
-
-  /* compute_motion considers frame points past the end of a line
-     to be *after* the newline, i.e. at the start of the next line.
-     This is reasonable, but not really what we want.  So if the
-     result is on a line below LINE, back it up one character.  */
-  if (posn->vpos > line)
-    return posn->bufpos - 1;
-  else
-    return posn->bufpos;
+  int i;
+
+  for (i = 0; i < len; ++i)
+    if (!CHAR_GLYPH_SPACE_P (r[i]))
+      break;
+
+  return i;
 }
-
-static int
-count_blanks (r)
-     register GLYPH *r;
-{
-  register GLYPH *p = r;
-  while (*p++ == SPACEGLYPH);
-  return p - r - 1;
-}
+
+
+/* Count the number of glyphs in common at the start of the glyph
+   vectors STR1 and STR2.  END1 is the end of STR1 and END2 is the end
+   of STR2.  Value is the number of equal glyphs equal at the start.  */
 
 static int
-count_match (str1, str2)
-     GLYPH *str1, *str2;
+count_match (str1, end1, str2, end2)
+     struct glyph *str1, *end1, *str2, *end2;
 {
-  register GLYPH *p1 = str1;
-  register GLYPH *p2 = str2;
-  while (*p1++ == *p2++);
-  return p1 - str1 - 1;
+  struct glyph *p1 = str1;
+  struct glyph *p2 = str2;
+  
+  while (p1 < end1
+	 && p2 < end2
+	 && GLYPH_FROM_CHAR_GLYPH (*p1) == GLYPH_FROM_CHAR_GLYPH (*p2))
+    ++p1, ++p2;
+  
+  return p1 - str1;
 }
 
+
 /* Char insertion/deletion cost vector, from term.c */
+
 extern int *char_ins_del_vector;
-
 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
 
+
+/* Perform a frame-based update on line VPOS in frame FRAME.  */
+
 static void
-update_line (frame, vpos)
-     register FRAME_PTR frame;
+update_frame_line (frame, vpos)
+     register struct frame *frame;
      int vpos;
 {
-  register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
-  int *temp1;
+  struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
   int tem;
   int osp, nsp, begmatch, endmatch, olen, nlen;
-  GLYPH save;
-  register struct frame_glyphs *current_frame
-    = FRAME_CURRENT_GLYPHS (frame);
-  register struct frame_glyphs *desired_frame
-    = FRAME_DESIRED_GLYPHS (frame);
-
-  if (desired_frame->highlight[vpos]
-      != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
+  struct glyph_matrix *current_matrix = frame->current_matrix;
+  struct glyph_matrix *desired_matrix = frame->desired_matrix;
+  struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
+  struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
+  int must_write_whole_line_p;
+
+  if (desired_row->inverse_p
+      != (current_row->enabled_p && current_row->inverse_p))
     {
-      change_line_highlight (desired_frame->highlight[vpos], vpos,
-			     (current_frame->enable[vpos] ?
-			      current_frame->used[vpos] : 0));
-      current_frame->enable[vpos] = 0;
+      int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0;
+      change_line_highlight (desired_row->inverse_p, vpos, vpos, n);
+      current_row->enabled_p = 0;
     }
   else
-    reassert_line_highlight (desired_frame->highlight[vpos], vpos);
-
-  if (! current_frame->enable[vpos])
+    reassert_line_highlight (desired_row->inverse_p, vpos);
+
+  must_write_whole_line_p = !current_row->enabled_p;
+  if (must_write_whole_line_p)
     {
+      /* A line that is not enabled is empty.  */
+      obody = 0;
       olen = 0;
     }
   else
     {
-      obody = current_frame->glyphs[vpos];
-      olen = current_frame->used[vpos];
-      if (! current_frame->highlight[vpos])
+      /* A line not empty in the current matrix.  */
+      obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
+      olen = current_row->used[TEXT_AREA];
+      
+      if (! current_row->inverse_p)
 	{
+	  /* Ignore trailing spaces.  */
 	  if (!must_write_spaces)
-	    while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
+	    while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
 	      olen--;
 	}
       else
 	{
-	  /* For an inverse-video line, remember we gave it
-	     spaces all the way to the frame edge
-	     so that the reverse video extends all the way across.  */
-
-	  while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
-	    obody[olen++] = SPACEGLYPH;
+	  /* For an inverse-video line, remember we gave it spaces all
+	     the way to the frame edge so that the reverse video
+	     extends all the way across.  */
+	  while (olen < FRAME_WIDTH (frame) - 1)
+	    obody[olen++] = space_glyph;
 	}
     }
 
-  /* One way or another, this will enable the line being updated.  */
-  current_frame->enable[vpos] = 1;
-  current_frame->used[vpos] = desired_frame->used[vpos];
-  current_frame->highlight[vpos] = desired_frame->highlight[vpos];
-  current_frame->bufp[vpos] = desired_frame->bufp[vpos];
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (frame))
-    {
-      current_frame->pix_width[vpos]
-	= current_frame->used[vpos]
-	  * FONT_WIDTH (FRAME_FONT (frame));
-      current_frame->pix_height[vpos]
-	= FRAME_LINE_HEIGHT (frame);
-    }
-#endif /* HAVE_WINDOW_SYSTEM */
-
-  if (!desired_frame->enable[vpos])
+  current_row->enabled_p = 1;
+  current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
+  current_row->inverse_p = desired_row->inverse_p;
+
+  /* If desired line is empty, just clear the line.  */
+  if (!desired_row->enabled_p)
     {
       nlen = 0;
       goto just_erase;
     }
 
-  nbody = desired_frame->glyphs[vpos];
-  nlen = desired_frame->used[vpos];
+  nbody = desired_row->glyphs[TEXT_AREA];
+  nlen = desired_row->used[TEXT_AREA];
+  nend = nbody + nlen;
+
+  /* If display line has unknown contents, write the whole line.  */
+  if (must_write_whole_line_p)
+    {
+      cursor_to (vpos, 0);
+      write_glyphs (nbody, nlen);
+      cursor_to (vpos, nlen);
+      clear_end_of_line (-1);
+      make_current (desired_matrix, current_matrix, vpos);
+      return;
+    }
 
   /* Pretend trailing spaces are not there at all,
      unless for one reason or another we must write all spaces.  */
-  if (! desired_frame->highlight[vpos])
+  if (!desired_row->inverse_p)
     {
       if (!must_write_spaces)
-	/* We know that the previous character byte contains 0.  */
-	while (nbody[nlen - 1] == SPACEGLYPH)
+	while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
 	  nlen--;
     }
   else
     {
-      /* For an inverse-video line, give it extra trailing spaces
-	 all the way to the frame edge
-	 so that the reverse video extends all the way across.  */
-
-      while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
-	nbody[nlen++] = SPACEGLYPH;
+      /* For an inverse-video line, give it extra trailing spaces all
+	 the way to the frame edge so that the reverse video extends
+	 all the way across.  */
+      while (nlen < FRAME_WIDTH (frame) - 1)
+	nbody[nlen++] = space_glyph;
     }
 
   /* If there's no i/d char, quickly do the best we can without it.  */
   if (!char_ins_del_ok)
     {
-      int i,j;
-
-#if 0
-      if (FRAME_X_P (frame))
-	{
-	  /* Under X, erase everything we are going to rewrite,
-	     and rewrite everything from the first char that's changed.
-	     This is part of supporting fonts like Courier
-	     whose chars can overlap outside the char width.  */
-	  for (i = 0; i < nlen; i++)
-	    if (i >= olen || nbody[i] != obody[i])
-	      break;
-
-	  cursor_to (vpos, i);
-	  if (i != olen)
-	    clear_end_of_line (olen);
-	  write_glyphs (nbody + i, nlen - i);
-	}
-      else
-	{}
-#endif /* 0 */
+      int i, j;
+
+      /* Find the first glyph in desired row that doesn't agree with
+	 a glyph in the current row, and write the rest from there on.  */
       for (i = 0; i < nlen; i++)
 	{
-	  if (i >= olen || nbody[i] != obody[i])    /* A non-matching char. */
+	  if (i >= olen || !GLYPH_EQUAL_P (nbody + i, obody + i))
 	    {
+	      /* Find the end of the run of different glyphs.  */
+	      j = i + 1;
+	      while (j < nlen
+		     && (j >= olen
+			 || !GLYPH_EQUAL_P (nbody + j, obody + j)
+			 || CHAR_GLYPH_PADDING_P (nbody[j])))
+		++j;
+		     
+	      /* Output this run of non-matching chars.  */ 
 	      cursor_to (vpos, i);
-	      for (j = 1;
-		   (i + j < nlen
-		    && (i + j >= olen || nbody[i + j] != obody[i + j]
-			|| (nbody[i + j] & GLYPH_MASK_PADDING)));
-		   j++);
-
-	      /* Output this run of non-matching chars.  */ 
-	      write_glyphs (nbody + i, j);
-	      i += j - 1;
+	      write_glyphs (nbody + i, j - i);
+	      i = j - 1;
 
 	      /* Now find the next non-match.  */
 	    }
@@ -1735,23 +4719,23 @@
 	  clear_end_of_line (olen);
 	}
 
-      /* Exchange contents between current_frame and new_frame.  */
-      temp = desired_frame->glyphs[vpos];
-      desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
-      current_frame->glyphs[vpos] = temp;
-
-      /* Exchange charstarts between current_frame and new_frame.  */
-      temp1 = desired_frame->charstarts[vpos];
-      desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
-      current_frame->charstarts[vpos] = temp1;
-
+      /* Make current row = desired row.  */
+      make_current (desired_matrix, current_matrix, vpos);
       return;
     }
 
+  /* Here when CHAR_INS_DEL_OK != 0, i.e. we can insert or delete
+     characters in a row.  */
+
   if (!olen)
     {
-      nsp = (must_write_spaces || desired_frame->highlight[vpos])
-	      ? 0 : count_blanks (nbody);
+      /* If current line is blank, skip over initial spaces, if
+	 possible, and write the rest.  */
+      if (must_write_spaces || desired_row->inverse_p)
+	nsp = 0;
+      else
+	nsp = count_blanks (nbody, nlen);
+
       if (nlen > nsp)
 	{
 	  cursor_to (vpos, nsp);
@@ -1759,44 +4743,30 @@
 	}
 
       /* Exchange contents between current_frame and new_frame.  */
-      temp = desired_frame->glyphs[vpos];
-      desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
-      current_frame->glyphs[vpos] = temp;
-
-      /* Exchange charstarts between current_frame and new_frame.  */
-      temp1 = desired_frame->charstarts[vpos];
-      desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
-      current_frame->charstarts[vpos] = temp1;
-
+      make_current (desired_matrix, current_matrix, vpos);
       return;
     }
 
-  obody[olen] = 1;
-  save = nbody[nlen];
-  nbody[nlen] = 0;
-
   /* Compute number of leading blanks in old and new contents.  */
-  osp = count_blanks (obody);
-  if (!desired_frame->highlight[vpos])
-    nsp = count_blanks (nbody);
-  else
-    nsp = 0;
-
-  /* Compute number of matching chars starting with first nonblank.  */
-  begmatch = count_match (obody + osp, nbody + nsp);
+  osp = count_blanks (obody, olen);
+  nsp = desired_row->inverse_p ? 0 : count_blanks (nbody, nlen);
+
+  /* Compute number of matching chars starting with first non-blank.  */
+  begmatch = count_match (obody + osp, obody + olen,
+			  nbody + nsp, nbody + nlen);
 
   /* Spaces in new match implicit space past the end of old.  */
   /* A bug causing this to be a no-op was fixed in 18.29.  */
   if (!must_write_spaces && osp + begmatch == olen)
     {
       np1 = nbody + nsp;
-      while (np1[begmatch] == SPACEGLYPH)
-	begmatch++;
+      while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
+	++begmatch;
     }
 
   /* Avoid doing insert/delete char
      just cause number of leading spaces differs
-     when the following text does not match. */
+     when the following text does not match.  */
   if (begmatch == 0 && osp != nsp)
     osp = nsp = min (osp, nsp);
 
@@ -1804,20 +4774,14 @@
   op1 = obody + olen;
   np1 = nbody + nlen;
   op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
-  while (op1 > op2 && op1[-1] == np1[-1])
+  while (op1 > op2
+	 && GLYPH_EQUAL_P (op1 - 1, np1 - 1))
     {
       op1--;
       np1--;
     }
   endmatch = obody + olen - op1;
 
-  /* Put correct value back in nbody[nlen].
-     This is important because direct_output_for_insert
-     can write into the line at a later point.
-     If this screws up the zero at the end of the line, re-establish it.  */
-  nbody[nlen] = save;
-  obody[olen] = 0;
-
   /* tem gets the distance to insert or delete.
      endmatch is how many characters we save by doing so.
      Is it worth it?  */
@@ -1861,7 +4825,7 @@
 	  olen = nlen - (nsp - osp);
 	}
       cursor_to (vpos, osp);
-      insert_glyphs ((GLYPH *) 0, nsp - osp);
+      insert_glyphs (0, nsp - osp);
     }
   olen += nsp - osp;
 
@@ -1878,29 +4842,6 @@
 	  if (nlen == FRAME_WINDOW_WIDTH (frame))
 	    olen = 0;
 	  write_glyphs (nbody + nsp + begmatch, nlen - tem);
-
-#ifdef obsolete
-
-/* the following code loses disastrously if tem == nlen.
-   Rather than trying to fix that case, I am trying the simpler
-   solution found above.  */
-
-	  /* If the text reaches to the right margin,
-	     it will lose one way or another (depending on AutoWrap)
-	     to clear to end of line after outputting all the text.
-	     So pause with one character to go and clear the line then.  */
-	  if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
-	    {
-	      /* endmatch must be zero, and tem must equal nsp + begmatch */
-	      write_glyphs (nbody + tem, nlen - tem - 1);
-	      clear_end_of_line (olen);
-	      olen = 0;		/* Don't let it be cleared again later */
-	      write_glyphs (nbody + nlen - 1, 1);
-	    }
-	  else
-	    write_glyphs (nbody + nsp + begmatch, nlen - tem);
-#endif	/* OBSOLETE */
-
 	}
       else if (nlen > olen)
 	{
@@ -1915,9 +4856,9 @@
 	  int del;
 
 	  /* Calculate columns we can actually overwrite.  */
-	  while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--;
+	  while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--;
 	  write_glyphs (nbody + nsp + begmatch, out);
-	  /* If we left columns to be overwritten. we must delete them.  */
+	  /* If we left columns to be overwritten, we must delete them.  */
 	  del = olen - tem - out;
 	  if (del > 0) delete_glyphs (del);
 	  /* At last, we insert columns not yet written out.  */
@@ -1941,130 +4882,107 @@
     }
 
   /* Exchange contents between current_frame and new_frame.  */
-  temp = desired_frame->glyphs[vpos];
-  desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
-  current_frame->glyphs[vpos] = temp;
-
-  /* Exchange charstarts between current_frame and new_frame.  */
-  temp1 = desired_frame->charstarts[vpos];
-  desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
-  current_frame->charstarts[vpos] = temp1;
+  make_current (desired_matrix, current_matrix, vpos);
 }
+
+
 
-/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
-   session's frames, frame names, buffers, buffer-read-only flags, and
-   buffer-modified-flags, and a trailing sentinel (so we don't need to
-   add length checks).  */
-static Lisp_Object frame_and_buffer_state;
-
-DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
-  Sframe_or_buffer_changed_p, 0, 0, 0,
-  "Return non-nil if the frame and buffer state appears to have changed.\n\
-The state variable is an internal vector containing all frames and buffers,\n\
-aside from buffers whose names start with space,\n\
-along with the buffers' read-only and modified flags, which allows a fast\n\
-check to see whether the menu bars might need to be recomputed.\n\
-If this function returns non-nil, it updates the internal vector to reflect\n\
-the current state.\n")
-  ()
+/***********************************************************************
+		   X/Y Position -> Buffer Position
+ ***********************************************************************/
+
+/* Return the character position of the character at window relative
+   pixel position (*X, *Y).  *X and *Y are adjusted to character
+   boundaries.  */
+
+int
+buffer_posn_from_coords (w, x, y)
+     struct window *w;
+     int *x, *y;
 {
-  Lisp_Object tail, frame, buf;
-  Lisp_Object *vecp;
-  int n;
-
-  vecp = XVECTOR (frame_and_buffer_state)->contents;
-  FOR_EACH_FRAME (tail, frame)
-    {
-      if (!EQ (*vecp++, frame))
-	goto changed;
-      if (!EQ (*vecp++, XFRAME (frame)->name))
-	goto changed;
-    }
-  /* Check that the buffer info matches.
-     No need to test for the end of the vector
-     because the last element of the vector is lambda
-     and that will always cause a mismatch.  */
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      buf = XCONS (XCONS (tail)->car)->cdr;
-      /* Ignore buffers that aren't included in buffer lists.  */
-      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
-	continue;
-      if (!EQ (*vecp++, buf))
-	goto changed;
-      if (!EQ (*vecp++, XBUFFER (buf)->read_only))
-	goto changed;
-      if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
-	goto changed;
-    }
-  /* Detect deletion of a buffer at the end of the list.  */
-  if (EQ (*vecp, Qlambda))
+  struct it it;
+  struct buffer *old_current_buffer = current_buffer;
+  struct text_pos startp;
+  int left_area_width;
+
+  current_buffer = XBUFFER (w->buffer);
+  SET_TEXT_POS_FROM_MARKER (startp, w->start);
+  CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
+  BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
+  start_display (&it, w, startp);
+  
+  left_area_width = WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH (w);
+  move_it_to (&it, -1, *x + it.first_visible_x - left_area_width, *y, -1,
+	      MOVE_TO_X | MOVE_TO_Y);
+  
+  *x = it.current_x - it.first_visible_x + left_area_width;
+  *y = it.current_y;
+  current_buffer = old_current_buffer;
+  return IT_CHARPOS (it);
+}
+
+
+/* Value is the string under window-relative coordinates X/Y in the
+   mode or top line of window W, or nil if none.  MODE_LINE_P non-zero
+   means look at the mode line.  *CHARPOS is set to the position in
+   the string returned.  */
+
+Lisp_Object
+mode_line_string (w, x, y, mode_line_p, charpos)
+     struct window *w;
+     int x, y;
+     int *charpos;
+{
+  struct glyph_row *row;
+  struct glyph *glyph, *end;
+  struct frame *f = XFRAME (w->frame);
+  int x0;
+  Lisp_Object string = Qnil;
+
+  /* Only do this for frames under a window system.  */
+  if (!FRAME_WINDOW_P (f))
     return Qnil;
- changed:
-  /* Start with 1 so there is room for at least one lambda at the end.  */
-  n = 1;
-  FOR_EACH_FRAME (tail, frame)
-    n += 2;
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
-    n += 3;
-  /* Reallocate the vector if it's grown, or if it's shrunk a lot.  */
-  if (n > XVECTOR (frame_and_buffer_state)->size
-      || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
-    /* Add 20 extra so we grow it less often.  */
-    frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
-  vecp = XVECTOR (frame_and_buffer_state)->contents;
-  FOR_EACH_FRAME (tail, frame)
+
+  if (mode_line_p)
+    row = MATRIX_MODE_LINE_ROW (w->current_matrix);
+  else
+    row = MATRIX_TOP_LINE_ROW (w->current_matrix);
+
+  if (row->mode_line_p && row->enabled_p)
     {
-      *vecp++ = frame;
-      *vecp++ = XFRAME (frame)->name;
-    }
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      buf = XCONS (XCONS (tail)->car)->cdr;
-      /* Ignore buffers that aren't included in buffer lists.  */
-      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
-	continue;
-      *vecp++ = buf;
-      *vecp++ = XBUFFER (buf)->read_only;
-      *vecp++ = Fbuffer_modified_p (buf);
+      /* The mode lines are displayed over scroll bars and bitmap
+	 areas, and X is window-relative.  Correct X by the scroll bar
+	 and bitmap area width.  */
+      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+	x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+      x += FRAME_FLAGS_AREA_WIDTH (f);
+
+      /* Find the glyph under X.  If we find one with a string object,
+         it's the one we were looking for.  */
+      glyph = row->glyphs[TEXT_AREA];
+      end = glyph + row->used[TEXT_AREA];
+      for (x0 = 0; glyph < end; x0 += glyph->pixel_width, ++glyph)
+	if (x >= x0 && x < x0 + glyph->pixel_width)
+	  {
+	    string = glyph->object;
+	    *charpos = glyph->charpos;
+	    break;
+	  }
     }
-  /* Fill up the vector with lambdas (always at least one).  */
-  *vecp++ = Qlambda;
-  while  (vecp - XVECTOR (frame_and_buffer_state)->contents
-	  < XVECTOR (frame_and_buffer_state)->size)
-    *vecp++ = Qlambda;
-  /* Make sure we didn't overflow the vector.  */
-  if (vecp - XVECTOR (frame_and_buffer_state)->contents
-      > XVECTOR (frame_and_buffer_state)->size)
-    abort ();
-  return Qt;
+
+  return string;
 }
-
-DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
-  1, 1, "FOpen termscript file: ",
-  "Start writing all terminal output to FILE as well as the terminal.\n\
-FILE = nil means just close any termscript file currently open.")
-  (file)
-     Lisp_Object file;
-{
-  if (termscript != 0) fclose (termscript);
-  termscript = 0;
-
-  if (! NILP (file))
-    {
-      file = Fexpand_file_name (file, Qnil);
-      termscript = fopen (XSTRING (file)->data, "w");
-      if (termscript == 0)
-	report_file_error ("Opening termscript", Fcons (file, Qnil));
-    }
-  return Qnil;
-}
-
+
+
+/***********************************************************************
+			 Changing Frame Sizes
+ ***********************************************************************/
 
 #ifdef SIGWINCH
+
 SIGTYPE
 window_change_signal (signalnum) /* If we don't have an argument, */
-     int signalnum;		/* some compilers complain in signal calls. */
+     int signalnum;		/* some compilers complain in signal calls.  */
 {
   int width, height;
   extern int errno;
@@ -2112,7 +5030,7 @@
 
       FOR_EACH_FRAME (tail, frame)
 	{
-	  FRAME_PTR f = XFRAME (frame);
+	  struct frame *f = XFRAME (frame);
 
 	  int height = FRAME_NEW_HEIGHT (f);
 	  int width = FRAME_NEW_WIDTH (f);
@@ -2134,7 +5052,7 @@
 
 void
 change_frame_size (f, newheight, newwidth, pretend, delay)
-     register FRAME_PTR f;
+     register struct frame *f;
      int newheight, newwidth, pretend, delay;
 {
   Lisp_Object tail, frame;
@@ -2153,8 +5071,8 @@
 }
 
 static void
-change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
-     register FRAME_PTR frame;
+change_frame_size_1 (f, newheight, newwidth, pretend, delay)
+     register struct frame *f;
      int newheight, newwidth, pretend, delay;
 {
   int new_frame_window_width;
@@ -2164,36 +5082,32 @@
   /* If we can't deal with the change now, queue it for later.  */
   if (delay)
     {
-      FRAME_NEW_HEIGHT (frame) = newheight;
-      FRAME_NEW_WIDTH (frame) = newwidth;
+      FRAME_NEW_HEIGHT (f) = newheight;
+      FRAME_NEW_WIDTH (f) = newwidth;
       delayed_size_change = 1;
       return;
     }
 
   /* This size-change overrides any pending one for this frame.  */
-  FRAME_NEW_HEIGHT (frame) = 0;
-  FRAME_NEW_WIDTH  (frame) = 0;
+  FRAME_NEW_HEIGHT (f) = 0;
+  FRAME_NEW_WIDTH  (f) = 0;
 
   /* If an argument is zero, set it to the current value.  */
   if (newheight == 0)
-    newheight = FRAME_HEIGHT (frame);
+    newheight = FRAME_HEIGHT (f);
   if (newwidth == 0)
-    newwidth  = FRAME_WIDTH  (frame);
-  new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
-
-  total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH);
-
-  /* If these sizes are so big they cause overflow,
-     just ignore the change.  It's not clear what better we could do.  */
-  if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2)
-    return;
+    newwidth  = FRAME_WIDTH  (f);
+
+  /* Compute width of windows in F.
+     This is the width of the frame without vertical scroll bars.  */
+  new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (f, newwidth);
 
   /* Round up to the smallest acceptable size.  */
-  check_frame_size (frame, &newheight, &newwidth);
+  check_frame_size (f, &newheight, &newwidth);
 
   /* If we're not changing the frame size, quit now.  */
-  if (newheight == FRAME_HEIGHT (frame)
-      && new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
+  if (newheight == FRAME_HEIGHT (f)
+      && new_frame_window_width == FRAME_WINDOW_WIDTH (f))
     return;
 
   BLOCK_INPUT;
@@ -2205,76 +5119,101 @@
   dos_set_window_size (&newheight, &newwidth);
 #endif
 
-  if (newheight != FRAME_HEIGHT (frame))
+  if (newheight != FRAME_HEIGHT (f))
     {
-      if (FRAME_HAS_MINIBUF_P (frame)
-	  && ! FRAME_MINIBUF_ONLY_P (frame))
+      if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
 	{
-	  /* Frame has both root and minibuffer.  */
-	  set_window_height (FRAME_ROOT_WINDOW (frame),
-			     newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
-	  XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
+	  /* Frame has both root and mini-buffer.  */
+	  XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (f))->top,
+		       FRAME_TOP_MARGIN (f));
+	  set_window_height (FRAME_ROOT_WINDOW (f),
+			     (newheight
+			      - 1
+			      - FRAME_TOP_MARGIN (f)),
+			      0);
+	  XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top,
 		       newheight - 1);
-	  set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
+	  set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0);
 	}
       else
 	/* Frame has just one top-level window.  */
-	set_window_height (FRAME_ROOT_WINDOW (frame),
-			   newheight - FRAME_MENU_BAR_LINES (frame), 0);
-
-      if (FRAME_TERMCAP_P (frame) && !pretend)
+	set_window_height (FRAME_ROOT_WINDOW (f),
+			   newheight - FRAME_TOP_MARGIN (f), 0);
+
+      if (FRAME_TERMCAP_P (f) && !pretend)
 	FrameRows = newheight;
-
-#if 0
-      if (frame->output_method == output_termcap)
-	{
-	  frame_height = newheight;
-	  if (!pretend)
-	    FrameRows = newheight;
-	}
-#endif
     }
 
-  if (new_frame_window_width  != FRAME_WINDOW_WIDTH (frame))
+  if (new_frame_window_width  != FRAME_WINDOW_WIDTH (f))
     {
-      set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
-      if (FRAME_HAS_MINIBUF_P (frame))
-	set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
-
-      if (FRAME_TERMCAP_P (frame) && !pretend)
+      set_window_width (FRAME_ROOT_WINDOW (f), new_frame_window_width, 0);
+      if (FRAME_HAS_MINIBUF_P (f))
+	set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_window_width, 0);
+
+      if (FRAME_TERMCAP_P (f) && !pretend)
 	FrameCols = newwidth;
-#if 0
-      if (frame->output_method == output_termcap)
-	{
-	  frame_width = newwidth;
-	  if (!pretend)
-	    FrameCols = newwidth;
-	}
-#endif
+
+      if (WINDOWP (f->toolbar_window))
+	XSETFASTINT (XWINDOW (f->toolbar_window)->width, newwidth);
     }
 
-  FRAME_HEIGHT (frame) = newheight;
-  SET_FRAME_WIDTH (frame, newwidth);
-
-  if (FRAME_CURSOR_X (frame) >= FRAME_CURSOR_X_LIMIT (frame))
-    FRAME_CURSOR_X (frame) = FRAME_CURSOR_X_LIMIT (frame) - 1;
-  if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
-    FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
-
-  remake_frame_glyphs (frame);
-  calculate_costs (frame);
+  FRAME_HEIGHT (f) = newheight;
+  SET_FRAME_WIDTH (f, newwidth);
+
+  {
+    struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+    int text_area_x, text_area_y, text_area_width, text_area_height;
+    
+    window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
+		&text_area_height);
+    if (w->cursor.x >= text_area_x + text_area_width)
+      w->cursor.hpos = w->cursor.x = 0;
+    if (w->cursor.y >= text_area_y + text_area_height)
+      w->cursor.vpos = w->cursor.y = 0;
+  }
+
+  adjust_glyphs (f);
+  SET_FRAME_GARBAGED (f);
+  calculate_costs (f);
 
   UNBLOCK_INPUT;
 
   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
 
   /* This isn't quite a no-op: it runs window-configuration-change-hook.  */
-  Fset_window_buffer (FRAME_SELECTED_WINDOW (frame),
-		      XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer);
+  Fset_window_buffer (FRAME_SELECTED_WINDOW (f),
+		      XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
 
   unbind_to (count, Qnil);
 }
+
+
 
+/***********************************************************************
+		   Terminal Related Lisp Functions
+ ***********************************************************************/
+
+DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
+  1, 1, "FOpen termscript file: ",
+  "Start writing all terminal output to FILE as well as the terminal.\n\
+FILE = nil means just close any termscript file currently open.")
+  (file)
+     Lisp_Object file;
+{
+  if (termscript != 0) fclose (termscript);
+  termscript = 0;
+
+  if (! NILP (file))
+    {
+      file = Fexpand_file_name (file, Qnil);
+      termscript = fopen (XSTRING (file)->data, "w");
+      if (termscript == 0)
+	report_file_error ("Opening termscript", Fcons (file, Qnil));
+    }
+  return Qnil;
+}
+
+
 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
   Ssend_string_to_terminal, 1, 1, 0,
   "Send STRING to the terminal without alteration.\n\
@@ -2295,6 +5234,7 @@
   return Qnil;
 }
 
+
 DEFUN ("ding", Fding, Sding, 0, 1, 0,
   "Beep, or flash the screen.\n\
 Also, unless an argument is given,\n\
@@ -2321,13 +5261,19 @@
 {
   if (noninteractive)
     putchar (07);
-  else if (!INTERACTIVE)  /* Stop executing a keyboard macro. */
+  else if (!INTERACTIVE)  /* Stop executing a keyboard macro.  */
     error ("Keyboard macro terminated by a command ringing the bell");
   else
     ring_bell ();
   fflush (stdout);
 }
 
+
+
+/***********************************************************************
+			  Sleeping, Waiting
+ ***********************************************************************/
+
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
   "Pause, without updating display, for SECONDS seconds.\n\
 SECONDS may be a floating-point value, meaning that you can wait for a\n\
@@ -2421,6 +5367,7 @@
   return Qnil;
 }
 
+
 /* This is just like wait_reading_process_input, except that
    it does the redisplay.
 
@@ -2454,6 +5401,7 @@
   return detect_input_pending () ? Qnil : Qt;
 }
 
+
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
   "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
 SECONDS may be a floating-point value, meaning that you can wait for a\n\
@@ -2494,13 +5442,115 @@
 
   return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
 }
+
+
 
+/***********************************************************************
+			 Other Lisp Functions
+ ***********************************************************************/
+
+/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
+   session's frames, frame names, buffers, buffer-read-only flags, and
+   buffer-modified-flags, and a trailing sentinel (so we don't need to
+   add length checks).  */
+
+static Lisp_Object frame_and_buffer_state;
+
+
+DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
+  Sframe_or_buffer_changed_p, 0, 0, 0,
+  "Return non-nil if the frame and buffer state appears to have changed.\n\
+The state variable is an internal vector containing all frames and buffers,\n\
+aside from buffers whose names start with space,\n\
+along with the buffers' read-only and modified flags, which allows a fast\n\
+check to see whether the menu bars might need to be recomputed.\n\
+If this function returns non-nil, it updates the internal vector to reflect\n\
+the current state.\n")
+  ()
+{
+  Lisp_Object tail, frame, buf;
+  Lisp_Object *vecp;
+  int n;
+
+  vecp = XVECTOR (frame_and_buffer_state)->contents;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      if (!EQ (*vecp++, frame))
+	goto changed;
+      if (!EQ (*vecp++, XFRAME (frame)->name))
+	goto changed;
+    }
+  /* Check that the buffer info matches.
+     No need to test for the end of the vector
+     because the last element of the vector is lambda
+     and that will always cause a mismatch.  */
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      /* Ignore buffers that aren't included in buffer lists.  */
+      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+	continue;
+      if (!EQ (*vecp++, buf))
+	goto changed;
+      if (!EQ (*vecp++, XBUFFER (buf)->read_only))
+	goto changed;
+      if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
+	goto changed;
+    }
+  /* Detect deletion of a buffer at the end of the list.  */
+  if (EQ (*vecp, Qlambda))
+    return Qnil;
+ changed:
+  /* Start with 1 so there is room for at least one lambda at the end.  */
+  n = 1;
+  FOR_EACH_FRAME (tail, frame)
+    n += 2;
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    n += 3;
+  /* Reallocate the vector if it's grown, or if it's shrunk a lot.  */
+  if (n > XVECTOR (frame_and_buffer_state)->size
+      || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
+    /* Add 20 extra so we grow it less often.  */
+    frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
+  vecp = XVECTOR (frame_and_buffer_state)->contents;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      *vecp++ = frame;
+      *vecp++ = XFRAME (frame)->name;
+    }
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      /* Ignore buffers that aren't included in buffer lists.  */
+      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+	continue;
+      *vecp++ = buf;
+      *vecp++ = XBUFFER (buf)->read_only;
+      *vecp++ = Fbuffer_modified_p (buf);
+    }
+  /* Fill up the vector with lambdas (always at least one).  */
+  *vecp++ = Qlambda;
+  while  (vecp - XVECTOR (frame_and_buffer_state)->contents
+	  < XVECTOR (frame_and_buffer_state)->size)
+    *vecp++ = Qlambda;
+  /* Make sure we didn't overflow the vector.  */
+  if (vecp - XVECTOR (frame_and_buffer_state)->contents
+      > XVECTOR (frame_and_buffer_state)->size)
+    abort ();
+  return Qt;
+}
+
+
+
+/***********************************************************************
+			    Initialization
+***********************************************************************/
+
 char *terminal_type;
 
-/* Initialization done when Emacs fork is started, before doing stty. */
-/* Determine terminal type and set terminal_driver */
-/* Then invoke its decoding routine to set up variables
-  in the terminal package */
+/* Initialization done when Emacs fork is started, before doing stty.
+   Determine terminal type and set terminal_driver.  Then invoke its
+   decoding routine to set up variables in the terminal package.  */
 
 void
 init_display ()
@@ -2509,6 +5559,11 @@
   extern int display_arg;
 #endif
 
+  /* Construct the space glyph.  */
+  space_glyph.type = CHAR_GLYPH;
+  SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' ');
+  space_glyph.charpos = -1;
+
   meta_key = 0;
   inverse_video = 0;
   cursor_in_echo_area = 0;
@@ -2557,6 +5612,7 @@
 	 So call tgetent.  */
       { char b[2044]; tgetent (b, "xterm");}
 #endif
+      adjust_frame_glyphs_initially ();
       return;
     }
 #endif /* HAVE_X_WINDOWS */
@@ -2566,6 +5622,7 @@
     {
       Vwindow_system = intern ("w32");
       Vwindow_system_version = make_number (1);
+      adjust_frame_glyphs_initially ();
       return;
     }
 #endif /* HAVE_NTGUI */
@@ -2593,7 +5650,7 @@
     }
 
 #ifdef VMS
-  /* VMS DCL tends to upcase things, so downcase term type.
+  /* VMS DCL tends to up-case things, so down-case term type.
      Hardly any uppercase letters in terminal types; should be none.  */
   {
     char *new = (char *) xmalloc (strlen (terminal_type) + 1);
@@ -2607,37 +5664,84 @@
 
     terminal_type = new;
   }	
-#endif
+#endif /* VMS */
 
   term_init (terminal_type);
-
+  
   {
     int width = FRAME_WINDOW_WIDTH (selected_frame);
     int height = FRAME_HEIGHT (selected_frame);
 
-    unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
-
-    /* If these sizes are so big they cause overflow,
-       just ignore the change.  It's not clear what better we could do.  */
-    if (total_glyphs / sizeof (GLYPH) / height != width + 2)
+    unsigned int total_glyphs = height * (width + 2) * sizeof (struct glyph);
+
+    /* If these sizes are so big they cause overflow, just ignore the
+       change.  It's not clear what better we could do.  */
+    if (total_glyphs / sizeof (struct glyph) / height != width + 2)
       fatal ("screen size %dx%d too big", width, height);
   }
 
-  remake_frame_glyphs (selected_frame);
+  adjust_frame_glyphs_initially ();
   calculate_costs (selected_frame);
 
-  /* X and Y coordinates of the cursor between updates. */
-  FRAME_CURSOR_X (selected_frame) = 0;
-  FRAME_CURSOR_Y (selected_frame) = 0;
-
 #ifdef SIGWINCH
 #ifndef CANNOT_DUMP
   if (initialized)
 #endif /* CANNOT_DUMP */
     signal (SIGWINCH, window_change_signal);
 #endif /* SIGWINCH */
+
+  /* Set up faces of the initial terminal frame of a dumped Emacs.  */
+  if (initialized
+      && !noninteractive
+      && NILP (Vwindow_system))
+    call0 (intern ("tty-set-up-initial-frame-faces"));
 }
+
+
 
+/***********************************************************************
+			   Blinking cursor
+ ***********************************************************************/
+
+DEFUN ("show-cursor", Fshow_cursor, Sshow_cursor, 0, 2, 0,
+  "Change visibility flag of the text cursor of WINDOW.\n\
+ON_P nil means toggle the flag.  Otherwise, ON_P must be an integer,\n\
+and the flag is set according to the value of ON_P.  WINDOW nil or\n\
+omitted means use the selected window.  The new cursor state takes effect\n\
+with the next redisplay.")
+  (on_p, window)
+     Lisp_Object on_p, window;
+{
+  struct window *w;
+
+  /* Don't change cursor state while redisplaying.  This could confuse
+     output routines.  */
+  if (!redisplaying_p)
+    {
+      if (NILP (window))
+	window = selected_window;
+      else
+	CHECK_WINDOW (window, 2);
+      w = XWINDOW (window);
+      
+      if (NILP (on_p))
+	w->cursor_off_p = !w->cursor_off_p;
+      else
+	{
+	  CHECK_NUMBER (on_p, 1);
+	  w->cursor_off_p = XINT (on_p) != 0;
+	}
+    }
+
+  return Qnil;
+}
+
+
+
+/***********************************************************************
+			    Initialization
+ ***********************************************************************/
+
 void
 syms_of_display ()
 {
@@ -2649,6 +5753,7 @@
   defsubr (&Ssit_for);
   defsubr (&Ssleep_for);
   defsubr (&Ssend_string_to_terminal);
+  defsubr (&Sshow_cursor);
 
   frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
   staticpro (&frame_and_buffer_state);
@@ -2660,24 +5765,31 @@
     "*The output baud rate of the terminal.\n\
 On most systems, changing this value will affect the amount of padding\n\
 and the other strategic decisions made during redisplay.");
+  
   DEFVAR_BOOL ("inverse-video", &inverse_video,
     "*Non-nil means invert the entire frame display.\n\
 This means everything is in inverse video which otherwise would not be.");
+  
   DEFVAR_BOOL ("visible-bell", &visible_bell,
     "*Non-nil means try to flash the frame to represent a bell.");
+  
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
     "*Non-nil means no need to redraw entire frame after suspending.\n\
 A non-nil value is useful if the terminal can automatically preserve\n\
 Emacs's frame display when you reenter Emacs.\n\
 It is up to you to set this variable if your terminal can do that.");
+  
   DEFVAR_LISP ("window-system", &Vwindow_system,
     "A symbol naming the window-system under which Emacs is running\n\
 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
+  
   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
     "The version number of the window system in use.\n\
 For X windows, this is 10 or 11.");
+  
   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
     "Non-nil means put cursor in minibuffer, at end of any message there.");
+  
   DEFVAR_LISP ("glyph-table", &Vglyph_table,
     "Table defining how to output a glyph code to the frame.\n\
 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
@@ -2693,6 +5805,10 @@
 See `buffer-display-table' for more information.");
   Vstandard_display_table = Qnil;
 
+  DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
+    "*Non-nil means update isn't paused when input is detected.");
+  redisplay_dont_pause = 0;
+
   /* Initialize `window-system', unless init_display already decided it.  */
 #ifdef CANNOT_DUMP
   if (noninteractive)
--- a/src/xdisp.c	Wed Jul 21 21:43:52 1999 +0000
+++ b/src/xdisp.c	Wed Jul 21 21:43:52 1999 +0000
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 1998
-     Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99
+   Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -19,11 +19,159 @@
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
+/* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
+
+   Redisplay.
+
+   Emacs separates the task of updating the display from code
+   modifying global state, e.g. buffer text.  This way functions
+   operating on buffers don't also have to be concerned with updating
+   the display.
+
+   Updating the display is triggered by the Lisp interpreter when it
+   decides it's time to do it.  This is done either automatically for
+   you as part of the interpreter's command loop or as the result of
+   calling Lisp functions like `sit-for'.  The C function `redisplay'
+   in xdisp.c is the only entry into the inner redisplay code.  (Or,
+   let's say almost---see the the description of direct update
+   operations, below.).
+
+   The following diagram shows how redisplay code is invoked.  As you
+   can see, Lisp calls redisplay and vice versa.  Under window systems
+   like X, some portions of the redisplay code are also called
+   asynchronously during mouse movement or expose events.  It is very
+   important that these code parts do NOT use the C library (malloc,
+   free) because many C libraries under Unix are not reentrant.  They
+   may also NOT call functions of the Lisp interpreter which could
+   change the interpreter's state.  If you don't follow these rules,
+   you will encounter bugs which are very hard to explain.
+
+	     (Direct functions, see below)
+             direct_output_for_insert, 
+             direct_forward_char (dispnew.c)
+   	  +---------------------------------+
+          |                                 |
+	  |                                 V
+   +--------------+   redisplay()   +----------------+
+   | Lisp machine |---------------->| Redisplay code |<--+
+   +--------------+   (xdisp.c)     +----------------+   |
+	  ^				     |		 |
+	  +----------------------------------+           |
+	    Don't use this path when called		 |
+	    asynchronously!				 |
+                                                         |
+                           expose_window (asynchronous)  |
+                                                         |
+			           X expose events  -----+
+
+   What does redisplay?  Obviously, it has to figure out somehow what
+   has been changed since the last time the display has been updated,
+   and to make these changes visible.  Preferably it would do that in
+   a moderately intelligent way, i.e. fast.
+
+   Changes in buffer text can be deduced from window and buffer
+   structures, and from some global variables like `beg_unchanged' and
+   `end_unchanged'.  The contents of the display are additionally
+   recorded in a `glyph matrix', a two-dimensional matrix of glyph
+   structures.  Each row in such a matrix corresponds to a line on the
+   display, and each glyph in a row corresponds to a column displaying
+   a character, an image, or what else.  This matrix is called the
+   `current glyph matrix' or `current matrix' in redisplay
+   terminology.
+
+   For buffer parts that have been changed since the last update, a
+   second glyph matrix is constructed, the so called `desired glyph
+   matrix' or short `desired matrix'.  Current and desired matrix are
+   then compared to find a cheap way to update the display, e.g. by
+   reusing part of the display by scrolling lines.
+
+
+   Direct operations.
+
+   You will find a lot of of redisplay optimizations when you start
+   looking at the innards of redisplay.  The overall goal of all these
+   optimizations is to make redisplay fast because it is done
+   frequently.
+
+   Two optimizations are not found in xdisp.c.  These are the direct
+   operations mentioned above.  As the name suggests they follow a
+   different principle than the rest of redisplay.  Instead of
+   building a desired matrix and then comparing it with the current
+   display, they perform their actions directly on the display and on
+   the current matrix.
+
+   One direct operation updates the display after one character has
+   been entered.  The other one moves the cursor by one position
+   forward or backward.  You find these functions under the names
+   `direct_output_for_insert' and `direct_output_forward_char' in
+   dispnew.c.
+
+   
+   Desired matrices.
+
+   Desired matrices are always built per Emacs window.  The function
+   `display_line' is the central function to look at if you are
+   interested.  It constructs one row in a desired matrix given an
+   iterator structure containing both a buffer position and a
+   description of the environment in which the text is to be
+   displayed.  But this is too early, read on.
+
+   Characters and pixmaps displayed for a range of buffer text depend
+   on various settings of buffers and windows, on overlays and text
+   properties, on display tables, on selective display.  The good news
+   is that all this hairy stuff is hidden behind a small set of
+   interface functions taking a iterator structure (struct it)
+   argument.
+
+   Iteration over things to be be displayed is then simple.  It is
+   started by initializing an iterator with a call to init_iterator
+   (or init_string_iterator for that matter).  Calls to
+   get_next_display_element fill the iterator structure with relevant
+   information about the next thing to display.  Calls to
+   set_iterator_to_next move the iterator to the next thing.
+
+   Besides this, an iterator also contains information about the
+   display environment in which glyphs for display elements are to be
+   produced.  It has fields for the width and height of the display,
+   the information whether long lines are truncated or continued, a
+   current X and Y position, and lots of other stuff you can better
+   see in dispextern.h.
+
+   Glyphs in a desired matrix are normally constructed in a loop
+   calling get_next_display_element and then produce_glyphs.  The call
+   to produce_glyphs will fill the iterator structure with pixel
+   information about the element being displayed and at the same time
+   produce glyphs for it.  If the display element fits on the line
+   being displayed, set_iterator_to_next is called next, otherwise the
+   glyphs produced are discarded.
+
+
+   Frame matrices.
+
+   That just couldn't be all, could it?  What about terminal types not
+   supporting operations on sub-windows of the screen?  To update the
+   display on such a terminal, window-based glyph matrices are not
+   well suited.  To be able to reuse part of the display (scrolling
+   lines up and down), we must instead have a view of the whole
+   screen.  This is what `frame matrices' are for.  They are a trick.
+
+   Frames on terminals like above have a glyph pool.  Windows on such
+   a frame sub-allocate their glyph memory from their frame's glyph
+   pool.  The frame itself is given its own glyph matrices.  By
+   coincidence---or maybe something else---rows in window glyph
+   matrices are slices of corresponding rows in frame matrices.  Thus
+   writing to window matrices implicitly updates a frame matrix which
+   provides us with the view of the whole screen that we originally
+   wanted to have without having to move many bytes around.  To be
+   honest, there is a little bit more done, but not much more.  If you
+   plan to extend that code, take a look at dispnew.c.  The function
+   build_frame_matrix is a good starting point.  */
 
 #include <config.h>
 #include <stdio.h>
-/*#include <ctype.h>*/
-#undef NULL
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif
 #include "lisp.h"
 #include "frame.h"
 #include "window.h"
@@ -46,6 +194,11 @@
 #include "xterm.h"
 #endif
 
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#define INFINITY 10000000
+
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
 extern void set_frame_menubar ();
 extern int pending_menu_activation;
@@ -60,222 +213,4333 @@
 
 extern Lisp_Object Voverriding_local_map;
 extern Lisp_Object Voverriding_local_map_menu_flag;
+extern Lisp_Object Qmenu_item;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
+Lisp_Object QCeval, QCwhen;
+Lisp_Object Qfontified;
+
+/* Functions called to fontify regions of text.  */
+
+Lisp_Object Vfontification_functions;
+Lisp_Object Qfontification_functions;
+
+/* Non-zero means draw toolbar buttons raised when the mouse moves
+   over them.  */
+
+int auto_raise_toolbar_buttons_p;
+
+/* Margin around toolbar buttons in pixels.  */
+
+int toolbar_button_margin;
+
+/* Thickness of shadow to draw around toolbar buttons.  */
+
+int toolbar_button_relief;
+
+/* Non-zero means automatically resize toolbars so that all toolbar
+   items are visible, and no blank lines remain.  */
+
+int auto_resize_toolbars_p;
 
 /* Non-nil means don't actually do any redisplay.  */
 
 Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
 
-/* Nonzero means print newline to stdout before next minibuffer message.  */
+/* Names of text properties relevant for redisplay.  */
+
+Lisp_Object Qdisplay, Qrelative_width, Qwidth, Qalign_to;
+extern Lisp_Object Qface, Qinvisible, Qimage;
+
+/* Symbols used in text property values.  */
+
+Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
+Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qheight, Qraise;
+
+/* Name of the variable controlling the highlighting of trailing
+   whitespace.  The implementation uses find_symbol_value to get its
+   value.  */
+
+Lisp_Object Qshow_trailing_whitespace;
+
+/* Name of the face used to highlight trailing whitespace.  */
+
+Lisp_Object Qtrailing_whitespace;
+
+/* The symbol `image' which is the car of the lists used to represent
+   images in Lisp.  */
+
+Lisp_Object Qimage;
+
+/* Non-zero means print newline to stdout before next mini-buffer
+   message.  */
 
 int noninteractive_need_newline;
 
-/* Nonzero means print newline to message log before next message.  */
+/* Non-zero means print newline to message log before next message.  */
 
 static int message_log_need_newline;
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define minmax(floor, val, ceil) \
-	((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
-
-/* The buffer position of the first character appearing
- entirely or partially on the current frame line.
- Or zero, which disables the optimization for the current frame line. */
-static int this_line_bufpos;
-
-/* Number of characters past the end of this line,
-   including the terminating newline */
-static int this_line_endpos;
-
-/* The vertical position of this frame line. */
+
+/* The buffer position of the first character appearing entirely or
+   partially on the line of the selected window which contains the
+   cursor; <= 0 if not known.  Set by set_cursor_from_row, used for
+   redisplay optimization in redisplay_internal.  */
+
+static struct text_pos this_line_start_pos;
+
+/* Number of characters past the end of the line above, including the
+   terminating newline.  */
+
+static struct text_pos this_line_end_pos;
+
+/* The vertical positions and the height of this line.  */
+
 static int this_line_vpos;
-
-/* Hpos value for start of display on this frame line.
-   Usually zero, but negative if first character really began
-   on previous line */
-static int this_line_start_hpos;
-
-/* Buffer that this_line variables are describing. */
+static int this_line_y;
+static int this_line_pixel_height;
+
+/* X position at which this display line starts.  Usually zero;
+   negative if first character is partially visible.  */
+
+static int this_line_start_x;
+
+/* Buffer that this_line_.* variables are referring to.  */
+
 static struct buffer *this_line_buffer;
 
-/* Value of echo_area_glyphs when it was last acted on.
-  If this is nonzero, there is a message on the frame
-  in the minibuffer and it should be erased as soon
-  as it is no longer requested to appear. */
-char *previous_echo_glyphs;
-
-/* Nonzero means truncate lines in all windows less wide than the frame */
+/* Nonzero means truncate lines in all windows less wide than the
+   frame.  */
+
 int truncate_partial_width_windows;
 
 /* A flag to control how to display unibyte 8-bit character.  */
+
 int unibyte_display_via_language_environment;
-
-/* Nonzero means we have more than one non-minibuffer-only frame.
-   Not guaranteed to be accurate except while parsing frame-title-format.  */
+ 
+/* Nonzero means we have more than one non-mini-buffer-only frame.
+   Not guaranteed to be accurate except while parsing
+   frame-title-format.  */
+
 int multiple_frames;
 
 Lisp_Object Vglobal_mode_string;
 
 /* Marker for where to display an arrow on top of the buffer text.  */
+
 Lisp_Object Voverlay_arrow_position;
 
-/* String to display for the arrow.  */
+/* String to display for the arrow.  Only used on terminal frames.  */
+
 Lisp_Object Voverlay_arrow_string;
 
-/* Values of those variables at last redisplay.
-   However, if Voverlay_arrow_position is a marker,
-   last_arrow_position is its numerical position.  */
+/* Values of those variables at last redisplay.  However, if
+   Voverlay_arrow_position is a marker, last_arrow_position is its
+   numerical position.  */
+
 static Lisp_Object last_arrow_position, last_arrow_string;
 
-/* Like mode-line-format, but for the titlebar on a visible frame.  */
+/* Like mode-line-format, but for the title bar on a visible frame.  */
+
 Lisp_Object Vframe_title_format;
 
-/* Like mode-line-format, but for the titlebar on an iconified frame.  */
+/* Like mode-line-format, but for the title bar on an iconified frame.  */
+
 Lisp_Object Vicon_title_format;
 
 /* List of functions to call when a window's size changes.  These
    functions get one arg, a frame on which one or more windows' sizes
    have changed.  */
+
 static Lisp_Object Vwindow_size_change_functions;
 
 Lisp_Object Qmenu_bar_update_hook;
 
 /* Nonzero if overlay arrow has been displayed once in this window.  */
+
 static int overlay_arrow_seen;
 
-/* Nonzero if visible end of buffer has already been displayed once
-   in this window.  (We need this variable in case there are overlay
-   strings that get displayed there.)  */
-static int zv_strings_seen;
-
 /* Nonzero means highlight the region even in nonselected windows.  */
-static int highlight_nonselected_windows;
-
-/* If cursor motion alone moves point off frame,
-   Try scrolling this many lines up or down if that will bring it back.  */
+
+int highlight_nonselected_windows;
+
+/* If cursor motion alone moves point off frame, try scrolling this
+   many lines up or down if that will bring it back.  */
+
 static int scroll_step;
 
-/* Non-0 means scroll just far enough to bring point back on the screen,
-   when appropriate.  */
+/* Non-0 means scroll just far enough to bring point back on the
+   screen, when appropriate.  */
+
 static int scroll_conservatively;
 
-/* Recenter the window whenever point gets within this many lines
-   of the top or bottom of the window.  */
+/* Recenter the window whenever point gets within this many lines of
+   the top or bottom of the window.  This value is translated into a
+   pixel value by multiplying it with CANON_Y_UNIT, which means that
+   there is really a fixed pixel height scroll margin.  */
+
 int scroll_margin;
 
-/* Number of characters of overlap to show,
-   when scrolling a one-line window such as a minibuffer.  */
+/* Number of characters of overlap to show, when scrolling a one-line
+   window such as a minibuffer.  */
+
 static int minibuffer_scroll_overlap;
 
-/* Nonzero if try_window_id has made blank lines at window bottom
- since the last redisplay that paused */
-static int blank_end_of_window;
-
-/* Number of windows showing the buffer of the selected window
-   (or another buffer with the same base buffer).
-   keyboard.c refers to this.  */
+/* Number of windows showing the buffer of the selected window (or
+   another buffer with the same base buffer).  keyboard.c refers to
+   this.  */
+
 int buffer_shared;
 
-/* display_text_line sets these to the frame position (origin 0) of point,
-   whether the window is selected or not.
-   Set one to -1 first to determine whether point was found afterwards.  */
-
-static int cursor_vpos;
-static int cursor_hpos;
-
-static int debug_end_pos;
-
-/* Nonzero means display mode line highlighted */
+/* Vector containing glyphs for an ellipsis `...'.  */
+
+static Lisp_Object default_invis_vector[3];
+
+/* Nonzero means display mode line highlighted.  */
+
 int mode_line_inverse_video;
 
-static void redisplay_internal ();
-static int message_log_check_duplicate ();
-static void echo_area_display ();
-void mark_window_display_accurate ();
-static void redisplay_windows ();
-static void redisplay_window ();
-static void update_menu_bar ();
-static void try_window ();
-static int try_window_id ();
-static struct position *display_text_line ();
-static void display_mode_line ();
-static int display_mode_element ();
-static char *decode_mode_spec ();
-static int display_string ();
-static void display_menu_bar ();
-static int display_count_lines ();
-
-/* Prompt to display in front of the minibuffer contents */
+/* Prompt to display in front of the mini-buffer contents.  */
+
 Lisp_Object minibuf_prompt;
 
-/* Width in columns of current minibuffer prompt.  */
+/* Width of current mini-buffer prompt.  Only set after display_line
+   of the line that contains the prompt.  */
+
 int minibuf_prompt_width;
-
-/* Message to display instead of minibuffer contents
-   This is what the functions error and message make,
-   and command echoing uses it as well.
-   It overrides the minibuf_prompt as well as the buffer.  */
+int minibuf_prompt_pixel_width;
+
+/* Message to display instead of mini-buffer contents.  This is what
+   the functions error and message make, and command echoing uses it
+   as well.  It overrides the minibuf_prompt as well as the buffer.  */
+
 char *echo_area_glyphs;
 
-/* This is the length of the message in echo_area_glyphs.  */
+/* A Lisp string to display instead of mini-buffer contents, analogous
+   to echo_area_glyphs.  If this is a string, display that string.
+   Otherwise, if echo_area_glyphs is non-null, display that.  */
+
+Lisp_Object echo_area_message;
+
+/* This is the length of the message in echo_area_glyphs or
+   echo_area_message.  */
+
 int echo_area_glyphs_length;
 
-/* This is the window where the echo area message was displayed.
-   It is always a minibuffer window, but it may not be the
-   same window currently active as a minibuffer.  */
+/* Value of echo_area_glyphs when it was last acted on.  If this is
+   nonzero, there is a message on the frame in the mini-buffer and it
+   should be erased as soon as it is no longer requested to appear.  */
+
+char *previous_echo_glyphs;
+Lisp_Object previous_echo_area_message;
+static int previous_echo_glyphs_length;
+
+/* This is the window where the echo area message was displayed.  It
+   is always a mini-buffer window, but it may not be the same window
+   currently active as a mini-buffer.  */
+
 Lisp_Object echo_area_window;
 
 /* Nonzero means multibyte characters were enabled when the echo area
    message was specified.  */
+
 int message_enable_multibyte;
 
-/* true iff we should redraw the mode lines on the next redisplay */
+/* True if we should redraw the mode lines on the next redisplay.  */
+
 int update_mode_lines;
 
-/* Smallest number of characters before the gap
-   at any time since last redisplay that finished.
-   Valid for current buffer when try_window_id can be called.  */
+/* Smallest number of characters before the gap at any time since last
+   redisplay that finished.  Valid for current buffer when
+   try_window_id can be called.  */
+
 int beg_unchanged;
 
-/* Smallest number of characters after the gap
-   at any time since last redisplay that finished.
-   Valid for current buffer when try_window_id can be called.  */
+/* Smallest number of characters after the gap at any time since last
+   redisplay that finished.  Valid for current buffer when
+   try_window_id can be called.  */
+
 int end_unchanged;
 
-/* MODIFF as of last redisplay that finished;
-   if it matches MODIFF, and overlay_unchanged_modified
-   matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
-   contain no useful information */
+/* MODIFF as of last redisplay that finished; if it matches MODIFF,
+   and overlay_unchanged_modified matches OVERLAY_MODIFF, that means
+   beg_unchanged and end_unchanged contain no useful information.  */
+
 int unchanged_modified;
 
 /* OVERLAY_MODIFF as of last redisplay that finished.  */
+
 int overlay_unchanged_modified;
 
-/* Nonzero if window sizes or contents have changed
-   since last redisplay that finished */
+/* Nonzero if window sizes or contents have changed since last
+   redisplay that finished */
+
 int windows_or_buffers_changed;
 
-/* Nonzero after display_mode_line if %l was used
-   and it displayed a line number.  */
+/* Nonzero after display_mode_line if %l was used and it displayed a
+   line number.  */
+
 int line_number_displayed;
 
 /* Maximum buffer size for which to display line numbers.  */
+
 static int line_number_display_limit;
 
-/* Number of lines to keep in the message log buffer.
-   t means infinite.  nil means don't log at all.  */
+/* Number of lines to keep in the message log buffer.  t means
+   infinite.  nil means don't log at all.  */
+
 Lisp_Object Vmessage_log_max;
 
-#define COERCE_MARKER(X)	\
-  (MARKERP ((X)) ? Fmarker_position (X) : (X))
-
-static int pos_tab_offset P_ ((struct window *, int, int));
+/* A scratch glyph row with contents used for generating truncation
+   glyphs.  Also used in direct_output_for_insert.  */
+
+#define MAX_SCRATCH_GLYPHS 100
+struct glyph_row scratch_glyph_row;
+static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
+
+/* Ascent and height of the last line processed by move_it_to.  */
+
+static int last_max_ascent, last_height;
+
+/* The maximum distance to look ahead for text properties.  Values
+   that are too small let us call compute_char_face and similar 
+   functions too often which is expensive.  Values that are too large
+   let us call compute_char_face and alike too often because we
+   might not be interested in text properties that far away.  */
+
+#define TEXT_PROP_DISTANCE_LIMIT 100
+
+/* Non-zero means print traces of redisplay if compiled with
+   GLYPH_DEBUG != 0.  */
+
+#if GLYPH_DEBUG
+int trace_redisplay_p;
+#endif
+
+/* Value returned from text property handlers (see below).  */
+
+enum prop_handled
+{
+  HANDLED_NORMALLY,
+  HANDLED_RECOMPUTE_PROPS,
+  HANDLED_OVERLAY_STRING_CONSUMED,
+  HANDLED_RETURN
+};
+
+/* A description of text properties that redisplay is interested
+   in.  */
+
+struct props
+{
+  /* The name of the property.  */
+  Lisp_Object *name;
+
+  /* A unique index for the property.  */
+  enum prop_idx idx;
+
+  /* A handler function called to set up iterator IT from the property
+     at IT's current position.  Value is used to steer handle_stop.  */
+  enum prop_handled (*handler) P_ ((struct it *it));
+};
+
+static enum prop_handled handle_face_prop P_ ((struct it *));
+static enum prop_handled handle_invisible_prop P_ ((struct it *));
+static enum prop_handled handle_display_prop P_ ((struct it *));
+static enum prop_handled handle_overlay_change P_ ((struct it *));
+static enum prop_handled handle_fontified_prop P_ ((struct it *));
+
+/* Properties handled by iterators.  */
+
+static struct props it_props[] =
+{
+  {&Qfontified,		FONTIFIED_PROP_IDX,	handle_fontified_prop},
+  /* Handle `face' before `display' because some sub-properties of
+     `display' need to know the face.  */
+  {&Qface,		FACE_PROP_IDX,		handle_face_prop},
+  {&Qdisplay,		DISPLAY_PROP_IDX,	handle_display_prop},
+  {&Qinvisible,		INVISIBLE_PROP_IDX,	handle_invisible_prop},
+  {NULL,		0,			NULL}
+};
+
+/* Value is the position described by X.  If X is a marker, value is
+   the marker_position of X.  Otherwise, value is X.  */
+
+#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
+
+/* Enumeration returned by some move_it_.* functions internally.  */
+
+enum move_it_result
+{
+  /* Not used.  Undefined value.  */
+  MOVE_UNDEFINED,
+
+  /* Move ended at the requested buffer position or ZV.  */
+  MOVE_POS_MATCH_OR_ZV,
+
+  /* Move ended at the requested X pixel position.  */
+  MOVE_X_REACHED,
+
+  /* Move within a line ended at the end of a line that must be
+     continued.  */
+  MOVE_LINE_CONTINUED,
+  
+  /* Move within a line ended at the end of a line that would
+     be displayed truncated.  */
+  MOVE_LINE_TRUNCATED,
+
+  /* Move within a line ended at a line end.  */
+  MOVE_NEWLINE_OR_CR
+};
+
+
+
+/* Function prototypes.  */
+
+static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
+					     struct text_pos));
+static int compute_window_start_on_continuation_line P_ ((struct window *));
+static Lisp_Object eval_handler P_ ((Lisp_Object));
+static Lisp_Object eval_form P_ ((Lisp_Object));
+static void insert_left_trunc_glyphs P_ ((struct it *));
+static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
+static void extend_face_to_end_of_line P_ ((struct it *));
+static void append_space P_ ((struct it *, int));
+static void make_cursor_line_fully_visible P_ ((struct window *));
+static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
+static int trailing_whitespace_p P_ ((int));
+static int message_log_check_duplicate P_ ((int, int, int, int));
+int invisible_p P_ ((Lisp_Object, Lisp_Object));
+int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
+static void push_it P_ ((struct it *));
+static void pop_it P_ ((struct it *));
+static void sync_frame_with_window_matrix_rows P_ ((struct window *));
+static void redisplay_internal P_ ((int));
+static void echo_area_display P_ ((int));
+static void redisplay_windows P_ ((Lisp_Object));
+static void redisplay_window P_ ((Lisp_Object, int));
+static void update_menu_bar P_ ((struct frame *, int));
+static int try_window_reusing_current_matrix P_ ((struct window *));
+static int try_window_id P_ ((struct window *));
+static int display_line P_ ((struct it *));
+static void display_mode_lines P_ ((struct window *));
+static void display_mode_line P_ ((struct window *, enum face_id,
+				   Lisp_Object));
+static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
+static char *decode_mode_spec P_ ((struct window *, char, int, int));
+static void display_menu_bar P_ ((struct window *));
+static int display_count_lines P_ ((int, int, int, int, int *));
+static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
+			       int, int, struct it *, int, int, int, int));
+static void compute_line_metrics P_ ((struct it *));
+static void run_redisplay_end_trigger_hook P_ ((struct it *));
+static int get_overlay_strings P_ ((struct it *));
+static void next_overlay_string P_ ((struct it *));
+void set_iterator_to_next P_ ((struct it *));
+static void reseat P_ ((struct it *, struct text_pos, int));
+static void reseat_1 P_ ((struct it *, struct text_pos, int));
+static void back_to_previous_visible_line_start P_ ((struct it *));
+static void reseat_at_previous_visible_line_start P_ ((struct it *));
+static int next_element_from_display_vector P_ ((struct it *));
+static int next_element_from_string P_ ((struct it *));
+static int next_element_from_c_string P_ ((struct it *));
+static int next_element_from_buffer P_ ((struct it *));
+static int next_element_from_image P_ ((struct it *));
+static int next_element_from_stretch P_ ((struct it *));
+static void load_overlay_strings P_ ((struct it *));
+static void init_from_display_pos P_ ((struct it *, struct window *,
+				       struct display_pos *));
+static void reseat_to_string P_ ((struct it *, unsigned char *,
+				  Lisp_Object, int, int, int, int));
+static int charset_at_position P_ ((struct text_pos));
+static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
+							   int, int, int));
+void move_it_vertically_backward P_ ((struct it *, int));
+static void init_to_row_start P_ ((struct it *, struct window *,
+				   struct glyph_row *));
+static void init_to_row_end P_ ((struct it *, struct window *,
+				 struct glyph_row *));
+static void back_to_previous_line_start P_ ((struct it *));
+static void forward_to_next_line_start P_ ((struct it *));
+static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
+						    Lisp_Object, int));
+static struct text_pos string_pos P_ ((int, Lisp_Object));
+static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
+static int number_of_chars P_ ((unsigned char *, int));
+static void compute_stop_pos P_ ((struct it *));
+static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
+				    Lisp_Object));
+static int face_before_or_after_it_pos P_ ((struct it *, int));
+static int next_overlay_change P_ ((int));
+static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
+					   Lisp_Object, struct text_pos *));
+
+#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
+#define face_after_it_pos(IT)  face_before_or_after_it_pos ((IT), 0)
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+static void update_toolbar P_ ((struct frame *, int));
+static void build_desired_toolbar_string P_ ((struct frame *f));
+static int redisplay_toolbar P_ ((struct frame *));
+static void display_toolbar_line P_ ((struct it *));
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+
+/***********************************************************************
+		      Window display dimensions
+ ***********************************************************************/
+
+/* Return the window-relative maximum y + 1 for glyph rows displaying
+   text in window W.  This is the height of W minus the height of a
+   mode line, if any.  */
+
+INLINE int
+window_text_bottom_y (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  
+  if (WINDOW_WANTS_MODELINE_P (w))
+    height -= CURRENT_MODE_LINE_HEIGHT (w);
+  return height;
+}
+
+
+/* Return the pixel width of display area AREA of window W.  AREA < 0
+   means return the total width of W, not including bitmap areas to
+   the left and right of the window.  */
+
+INLINE int
+window_box_width (w, area)
+     struct window *w;
+     int area;
+{
+  struct frame *f = XFRAME (w->frame);
+  int width = XFASTINT (w->width);
+  
+  if (!w->pseudo_window_p)
+    {
+      width -= FRAME_SCROLL_BAR_WIDTH (f) + 2 * FRAME_FLAGS_AREA_COLS (f);
+      
+      if (area == TEXT_AREA)
+	{
+	  if (INTEGERP (w->left_margin_width))
+	    width -= XFASTINT (w->left_margin_width);
+	  if (INTEGERP (w->right_margin_width))
+	    width -= XFASTINT (w->right_margin_width);
+	}
+      else if (area == LEFT_MARGIN_AREA)
+	width = (INTEGERP (w->left_margin_width)
+		 ? XFASTINT (w->left_margin_width) : 0);
+      else if (area == RIGHT_MARGIN_AREA)
+	width = (INTEGERP (w->right_margin_width)
+		 ? XFASTINT (w->right_margin_width) : 0);
+    }
+
+  return width * CANON_X_UNIT (f);
+}
+
+
+/* Return the pixel height of the display area of window W, not
+   including mode lines of W, if any..  */
+
+INLINE int
+window_box_height (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  
+  if (WINDOW_WANTS_MODELINE_P (w))
+    height -= CURRENT_MODE_LINE_HEIGHT (w);
+
+  if (WINDOW_WANTS_TOP_LINE_P (w))
+    height -= CURRENT_TOP_LINE_HEIGHT (w);
+
+  return height;
+}
+
+
+/* Return the frame-relative coordinate of the left edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the right of any bitmap area at the left side of
+   W.  */
+
+INLINE int
+window_box_left (w, area)
+     struct window *w;
+     int area;
+{
+  struct frame *f = XFRAME (w->frame);
+  int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
+
+  if (!w->pseudo_window_p)
+    {
+      x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
+	    + FRAME_FLAGS_AREA_WIDTH (f));
+      
+      if (area == TEXT_AREA)
+	x += window_box_width (w, LEFT_MARGIN_AREA);
+      else if (area == RIGHT_MARGIN_AREA)
+	x += (window_box_width (w, LEFT_MARGIN_AREA)
+	      + window_box_width (w, TEXT_AREA));
+    }
+
+  return x;
+}     
+
+
+/* Return the frame-relative coordinate of the right edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the left of any bitmap area at the right side of
+   W.  */
+
+INLINE int
+window_box_right (w, area)
+     struct window *w;
+     int area;
+{
+  return window_box_left (w, area) + window_box_width (w, area);
+}     
+     
+
+/* Get the bounding box of the display area AREA of window W, without
+   mode lines, in frame-relative coordinates.  AREA < 0 means the
+   whole window, not including bitmap areas to the left and right of
+   the window.  Return in *BOX_X and *BOX_Y the frame-relative pixel
+   coordinates of the upper-left corner of the box.  Return in
+   *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box.  */
+
+INLINE void
+window_box (w, area, box_x, box_y, box_width, box_height)
+     struct window *w;
+     int area;
+     int *box_x, *box_y, *box_width, *box_height;
+{
+  struct frame *f = XFRAME (w->frame);
+  
+  *box_width = window_box_width (w, area);
+  *box_height = window_box_height (w);
+  *box_x = window_box_left (w, area);
+  *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
+	    + XFASTINT (w->top) * CANON_Y_UNIT (f));
+  if (WINDOW_WANTS_TOP_LINE_P (w))
+    *box_y += CURRENT_TOP_LINE_HEIGHT (w);
+}
+
+
+/* Get the bounding box of the display area AREA of window W, without
+   mode lines.  AREA < 0 means the whole window, not including bitmap
+   areas to the left and right of the window.  Return in *TOP_LEFT_X
+   and TOP_LEFT_Y the frame-relative pixel coordinates of the
+   upper-left corner of the box.  Return in *BOTTOM_RIGHT_X, and
+   *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
+   box.  */
+
+INLINE void
+window_box_edges (w, area, top_left_x, top_left_y,
+		  bottom_right_x, bottom_right_y)
+     struct window *w;
+     int area;
+     int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
+{
+  window_box (w, area, top_left_x, top_left_y, bottom_right_x,
+	      bottom_right_y);
+  *bottom_right_x += *top_left_x;
+  *bottom_right_y += *top_left_y;
+}
+
+
+
+/***********************************************************************
+			      Utilities
+ ***********************************************************************/
+
+/* Given a position POS containing a valid character and byte position
+   in STRING, return the position NCHARS ahead (NCHARS >= 0).  */
+
+static struct text_pos
+string_pos_nchars_ahead (pos, string, nchars)
+     struct text_pos pos;
+     Lisp_Object string;
+     int nchars;
+{
+  xassert (STRINGP (string) && nchars >= 0);
+
+  if (STRING_MULTIBYTE (string))
+    {
+      int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
+      unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
+      int len;
+
+      while (nchars--)
+	{
+	  STRING_CHAR_AND_LENGTH (p, rest, len);
+	  p += len, rest -= len;
+	  xassert (rest >= 0);
+	  CHARPOS (pos) += 1;
+	  BYTEPOS (pos) += len;
+	}
+    }
+  else
+    SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
+
+  return pos;
+}
+
+
+/* Value is the text position, i.e. character and byte position,
+   for character position CHARPOS in STRING.  */
+
+static INLINE struct text_pos
+string_pos (charpos, string)
+     int charpos;
+     Lisp_Object string;
+{
+  struct text_pos pos;
+  xassert (STRINGP (string));
+  xassert (charpos >= 0);
+  SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
+  return pos;
+}
+
+
+/* Value is a text position, i.e. character and byte position, for
+   character position CHARPOS in C string S.  MULTIBYTE_P non-zero
+   means recognize multibyte characters.  */
+
+static struct text_pos
+c_string_pos (charpos, s, multibyte_p)
+     int charpos;
+     unsigned char *s;
+     int multibyte_p;
+{
+  struct text_pos pos;
+
+  xassert (s != NULL);
+  xassert (charpos >= 0);
+
+  if (multibyte_p)
+    {
+      int rest = strlen (s), len;
+
+      SET_TEXT_POS (pos, 0, 0);
+      while (charpos--)
+	{
+	  STRING_CHAR_AND_LENGTH (s, rest, len);
+	  s += len, rest -= len;
+	  xassert (rest >= 0);
+	  CHARPOS (pos) += 1;
+	  BYTEPOS (pos) += len;
+	}
+    }
+  else
+    SET_TEXT_POS (pos, charpos, charpos);
+
+  return pos;
+}
+
+
+/* Value is the number of characters in C string S.  MULTIBYTE_P
+   non-zero means recognize multibyte characters.  */
+
+static int
+number_of_chars (s, multibyte_p)
+     unsigned char *s;
+     int multibyte_p;
+{
+  int nchars;
+  
+  if (multibyte_p)
+    {
+      int rest = strlen (s), len;
+      unsigned char *p = (unsigned char *) s;
+
+      for (nchars = 0; rest > 0; ++nchars)
+	{
+	  STRING_CHAR_AND_LENGTH (p, rest, len);
+	  rest -= len, p += len;
+	}
+    }
+  else
+    nchars = strlen (s);
+
+  return nchars;
+}
+
+     
+/* Compute byte position NEWPOS->bytepos corresponding to
+   NEWPOS->charpos.  POS is a known position in string STRING.
+   NEWPOS->charpos must be >= POS.charpos.  */
+
+static void
+compute_string_pos (newpos, pos, string)
+     struct text_pos *newpos, pos;
+     Lisp_Object string;
+{
+  xassert (STRINGP (string));
+  xassert (CHARPOS (*newpos) >= CHARPOS (pos));
+  
+  if (STRING_MULTIBYTE (string))
+    *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
+				       string);
+  else
+    BYTEPOS (*newpos) = CHARPOS (*newpos);
+}
+
+
+/* Return the charset of the character at position POS in
+   current_buffer.  */
+
+static int
+charset_at_position (pos)
+     struct text_pos pos;
+{
+  int c, multibyte_p;
+  unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
+
+  multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+  if (multibyte_p)
+    {
+      int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
+		    - BYTEPOS (pos));
+      int len;
+      c = STRING_CHAR_AND_LENGTH (p, maxlen, len);
+    }
+  else
+    c = *p;
+
+  return CHAR_CHARSET (c);
+}
+
+
+
+/***********************************************************************
+			Lisp form evaluation
+ ***********************************************************************/
+
+/* Error handler for eval_form.  */
+
+static Lisp_Object
+eval_handler (arg)
+     Lisp_Object arg;
+{
+  return Qnil;
+}
+
+
+/* Evaluate SEXPR and return the result, or nil if something went
+   wrong.  */
+
+static Lisp_Object
+eval_form (sexpr)
+     Lisp_Object sexpr;
+{
+  int count = specpdl_ptr - specpdl;
+  Lisp_Object val;
+  specbind (Qinhibit_redisplay, Qt);
+  val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler);
+  return unbind_to (count, val);
+}
+
+
+
+/***********************************************************************
+			      Debugging
+ ***********************************************************************/
+
+#if 0
+
+/* Define CHECK_IT to perform sanity checks on iterators.
+   This is for debugging.  It is too slow to do unconditionally.  */
+
+static void
+check_it (it)
+     struct it *it;
+{
+  if (it->method == next_element_from_string)
+    {
+      xassert (STRINGP (it->string));
+      xassert (IT_STRING_CHARPOS (*it) >= 0);
+    }
+  else if (it->method == next_element_from_buffer)
+    {
+      /* Check that character and byte positions agree.  */
+      xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
+    }
+
+  if (it->dpvec)
+    xassert (it->current.dpvec_index >= 0);
+  else
+    xassert (it->current.dpvec_index < 0);
+}
+
+#define CHECK_IT(IT)	check_it ((IT))
+
+#else /* not 0 */
+
+#define CHECK_IT(IT)	(void) 0
+
+#endif /* not 0 */
+
+
+#if GLYPH_DEBUG
+
+/* Check that the window end of window W is what we expect it
+   to be---the last row in the current matrix displaying text.  */
+
+static void
+check_window_end (w)
+     struct window *w;
+{
+  if (!MINI_WINDOW_P (w)
+      && !NILP (w->window_end_valid))
+    {
+      struct glyph_row *row;
+      xassert ((row = MATRIX_ROW (w->current_matrix,
+				  XFASTINT (w->window_end_vpos)),
+		!row->enabled_p
+		|| MATRIX_ROW_DISPLAYS_TEXT_P (row)
+		|| MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
+    }
+}
+
+#define CHECK_WINDOW_END(W)	check_window_end ((W))
+
+#else /* not GLYPH_DEBUG */
+
+#define CHECK_WINDOW_END(W)	(void) 0
+
+#endif /* not GLYPH_DEBUG */
+
+
+
+/***********************************************************************
+		       Iterator initialization
+ ***********************************************************************/
+
+/* Initialize IT for displaying current_buffer in window W, starting
+   at character position CHARPOS.  CHARPOS < 0 means that no buffer
+   position is specified which is useful when the iterator is assigned
+   a position later.  BYTEPOS is the byte position corresponding to
+   CHARPOS.  BYTEPOS <= 0 means compute it from CHARPOS.
+
+   If ROW is not null, calls to produce_glyphs with IT as parameter
+   will produce glyphs in that row.
+
+   BASE_FACE_ID is the id of a base face to use.  It must be one of
+   DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
+   TOP_LINE_FACE_ID for displaying mode lines, or TOOLBAR_FACE_ID for
+   displaying the toolbar.
+   
+   If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
+   TOP_LINE_FACE_ID, the iterator will be initialized to use the
+   corresponding mode line glyph row of the desired matrix of W.  */
+
+void
+init_iterator (it, w, charpos, bytepos, row, base_face_id)
+     struct it *it;
+     struct window *w;
+     int charpos, bytepos;
+     struct glyph_row *row;
+     enum face_id base_face_id;
+{
+  int highlight_region_p;
+  Lisp_Object value;
+
+  /* Some precondition checks.  */
+  xassert (w != NULL && it != NULL);
+  xassert (charpos < 0 || current_buffer == XBUFFER (w->buffer));
+  xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
+
+  /* If face attributes have been changed since the last redisplay,
+     free realized faces now because they depend on face definitions
+     that might have changed.  */
+  if (face_change_count)
+    {
+      face_change_count = 0;
+      free_all_realized_faces (Qnil);
+    }
+
+  /* Use one of the mode line rows of W's desired matrix if
+     appropriate.  */
+  if (row == NULL)
+    {
+      if (base_face_id == MODE_LINE_FACE_ID)
+	row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
+      else if (base_face_id == TOP_LINE_FACE_ID)
+	row = MATRIX_TOP_LINE_ROW (w->desired_matrix);
+    }
+  
+  /* Clear IT.  */
+  bzero (it, sizeof *it);
+  it->current.overlay_string_index = -1;
+  it->current.dpvec_index = -1;
+  it->charset = CHARSET_ASCII;
+  it->base_face_id = base_face_id;
+
+  /* The window in which we iterate over current_buffer:  */
+  XSETWINDOW (it->window, w);
+  it->w = w;
+  it->f = XFRAME (w->frame);
+
+  /* If realized faces have been removed, e.g. because of face
+     attribute changes of named faces, recompute them.  */
+  if (FRAME_FACE_CACHE (it->f)->used == 0)
+    recompute_basic_faces (it->f);
+
+  /* Should we highlight trailing whitespace?  */
+  value = find_symbol_value (Qshow_trailing_whitespace);
+  it->show_trailing_whitespace_p 
+    = EQ (value, Qunbound) ? 0 : !NILP (value);
+
+  /* Current value of the `space-width', and 'height' properties.  */
+  it->space_width = Qnil;
+  it->font_height = Qnil;
+  
+  /* Are control characters displayed as `^C'?  */
+  it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
+
+  /* -1 means everything between a CR and the following line end
+     is invisible.  >0 means lines indented more than this value are
+     invisible.  */
+  it->selective = (INTEGERP (current_buffer->selective_display)
+		   ? XFASTINT (current_buffer->selective_display)
+		   : (!NILP (current_buffer->selective_display) 
+		      ? -1 : 0));
+  it->selective_display_ellipsis_p
+    = !NILP (current_buffer->selective_display_ellipses);
+
+  /* Display table to use.  */
+  it->dp = window_display_table (w);
+
+  /* Are multibyte characters enabled in current_buffer?  */
+  it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+
+  /* Non-zero if we should highlight the region.  */
+  highlight_region_p
+    = (!NILP (Vtransient_mark_mode) 
+       && !NILP (current_buffer->mark_active)
+       && XMARKER (current_buffer->mark)->buffer != 0);
+
+  /* Set IT->region_beg_charpos and IT->region_end_charpos to the
+     start and end of a visible region in window IT->w.  Set both to
+     -1 to indicate no region.  */
+  if (highlight_region_p
+      /* Maybe highlight only in selected window.  */
+      && (/* Either show region everywhere.  */ 
+	  highlight_nonselected_windows
+	  /* Or show region in the selected window.  */
+	  || w == XWINDOW (selected_window)
+	  /* Or show the region if we are in the mini-buffer and W is
+	     the window the mini-buffer refers to.  */
+	  || (MINI_WINDOW_P (XWINDOW (selected_window))
+	      && w == XWINDOW (Vminibuf_scroll_window))))
+    {
+      int charpos = marker_position (current_buffer->mark);
+      it->region_beg_charpos = min (PT, charpos);
+      it->region_end_charpos = max (PT, charpos);
+    }
+  else
+    it->region_beg_charpos = it->region_end_charpos = -1;
+
+  /* Get the position at which the redisplay_end_trigger hook should
+     be run, if it is to be run at all.  */
+  if (MARKERP (w->redisplay_end_trigger)
+      && XMARKER (w->redisplay_end_trigger)->buffer != 0)
+    it->redisplay_end_trigger_charpos
+      = marker_position (w->redisplay_end_trigger);
+  else if (INTEGERP (w->redisplay_end_trigger))
+    it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
+
+  /* Correct bogus values of tab_width.  */
+  it->tab_width = XINT (current_buffer->tab_width);
+  if (it->tab_width <= 0 || it->tab_width > 1000)
+    it->tab_width = 8;
+
+  /* Are lines in the display truncated?  */
+  it->truncate_lines_p
+    = (base_face_id != DEFAULT_FACE_ID
+       || XINT (it->w->hscroll)
+       || (truncate_partial_width_windows
+	   && !WINDOW_FULL_WIDTH_P (it->w))
+       || !NILP (current_buffer->truncate_lines));
+
+  /* Get dimensions of truncation and continuation glyphs.  These are
+     displayed as bitmaps under X, so we don't need them for such
+     frames.  */
+  if (!FRAME_WINDOW_P (it->f))
+    {
+      if (it->truncate_lines_p)
+	{
+	  /* We will need the truncation glyph.  */
+	  xassert (it->glyph_row == NULL);
+	  produce_special_glyphs (it, IT_TRUNCATION);
+	  it->truncation_pixel_width = it->pixel_width;
+	}
+      else
+	{
+	  /* We will need the continuation glyph.  */
+	  xassert (it->glyph_row == NULL);
+	  produce_special_glyphs (it, IT_CONTINUATION);
+	  it->continuation_pixel_width = it->pixel_width;
+	}
+
+      /* Reset these values to zero becaue the produce_special_glyphs
+	 above has changed them.  */
+      it->pixel_width = it->ascent = it->descent = 0;
+    }
+
+  /* Set this after getting the dimensions of truncation and
+     continuation glyphs, so that we don't produce glyphs when calling
+     produce_special_glyphs, above.  */
+  it->glyph_row = row;
+  it->area = TEXT_AREA;
+
+  /* Get the dimensions of the display area.  The display area
+     consists of the visible window area plus a horizontally scrolled
+     part to the left of the window.  All x-values are relative to the
+     start of this total display area.  */
+  if (base_face_id != DEFAULT_FACE_ID)
+    {
+      /* Mode lines, menu bar in terminal frames.  */
+      it->first_visible_x = 0;
+      it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
+    }
+  else
+    {
+      it->first_visible_x
+	= XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
+      it->last_visible_x = (it->first_visible_x
+			    + window_box_width (w, TEXT_AREA));
+
+      /* If we truncate lines, leave room for the truncator glyph(s) at
+	 the right margin.  Otherwise, leave room for the continuation
+	 glyph(s).  Truncation and continuation glyphs are not inserted
+	 for window-based redisplay.  */
+      if (!FRAME_WINDOW_P (it->f))
+	{
+	  if (it->truncate_lines_p)
+	    it->last_visible_x -= it->truncation_pixel_width;
+	  else
+	    it->last_visible_x -= it->continuation_pixel_width;
+	}
+
+      it->top_line_p = WINDOW_WANTS_TOP_LINE_P (w);
+      it->current_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w) + w->vscroll;
+    }
+
+  /* Leave room for a border glyph.  */
+  if (!FRAME_WINDOW_P (it->f)
+      && !WINDOW_RIGHTMOST_P (it->w))
+    it->last_visible_x -= 1;
+
+  it->last_visible_y = window_text_bottom_y (w);
+
+  /* For mode lines and alike, arrange for the first glyph having a
+     left box line if the face specifies a box.  */
+  if (base_face_id != DEFAULT_FACE_ID)
+    {
+      struct face *face;
+      
+      it->face_id = base_face_id;
+
+      /* If we have a boxed mode line, make the first character appear
+	 with a left box line.  */
+      face = FACE_FROM_ID (it->f, base_face_id);
+      if (face->box != FACE_NO_BOX)
+	it->start_of_box_run_p = 1;
+    }
+
+  /* If a buffer position was specified, set the iterator there,
+     getting overlays and face properties from that position.  */
+  if (charpos > 0)
+    {
+      it->end_charpos = ZV;
+      it->face_id = -1;
+      IT_CHARPOS (*it) = charpos;
+      
+      /* Compute byte position if not specified.  */
+      if (bytepos <= 0)
+	IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
+      else
+	IT_BYTEPOS (*it) = bytepos;
+
+      /* Compute faces etc.  */
+      reseat (it, it->current.pos, 1);
+    }
+  
+  CHECK_IT (it);
+}
+
+
+/* Initialize IT for the display of window W with window start POS.  */
+
+void
+start_display (it, w, pos)
+     struct it *it;
+     struct window *w;
+     struct text_pos pos;
+{
+  int start_at_line_beg_p;
+  struct glyph_row *row;
+  int first_vpos = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0;
+  int first_y;
+
+  row = w->desired_matrix->rows + first_vpos;
+  init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
+  first_y = it->current_y;
+  
+  /* If window start is not at a line start, move back to the line
+     start.  This makes sure that we take continuation lines into
+     account.  */
+  start_at_line_beg_p = (CHARPOS (pos) == BEGV
+			 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
+  if (!start_at_line_beg_p)
+    reseat_at_previous_visible_line_start (it);
+
+#if NO_PROMPT_IN_BUFFER
+  /* Take the mini-buffer prompt width into account for tab
+     calculations.  */
+  if (MINI_WINDOW_P (w) && IT_CHARPOS (*it) == BEGV)
+    {
+      /* Why is mini-buffer_prompt_width guaranteed to be set here?  */
+      it->prompt_width = minibuf_prompt_pixel_width;
+    }
+#endif /* NO_PROMPT_IN_BUFFER */
+
+  /* If window start is not at a line start, skip forward to POS to
+     get the correct continuation_lines_width and current_x.  */
+  if (!start_at_line_beg_p)
+    {
+      move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
+
+      /* If lines are continued, this line may end in the middle of a
+	 multi-glyph character (e.g. a control character displayed as
+	 \003, or in the middle of an overlay string).  In this case
+	 move_it_to above will not have taken us to the start of
+	 the continuation line but to the end of the continued line.  */
+      if (!it->truncate_lines_p && it->current_x > 0)
+	{
+	  if (it->current.dpvec_index >= 0
+	      || it->current.overlay_string_index >= 0)
+	    {
+	      set_iterator_to_next (it);
+	      move_it_in_display_line_to (it, -1, -1, 0);
+	    }
+	  it->continuation_lines_width += it->current_x;
+	}
+      
+      it->current_y = first_y;
+      it->vpos = 0;
+      it->current_x = it->hpos = 0;
+    }
+
+#if 0 /* Don't assert the following because start_display is sometimes
+         called intentionally with a window start that is not at a
+	 line start.  Please leave this code in as a comment.  */
+  
+  /* Window start should be on a line start, now.  */
+  xassert (it->continuation_lines_width
+	   || IT_CHARPOS (it) == BEGV
+	   || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
+#endif /* 0 */
+}
+
+
+/* Initialize IT for stepping through current_buffer in window W,
+   starting at position POS that includes overlay string and display
+   vector/ control character translation position information.  */
+
+static void
+init_from_display_pos (it, w, pos)
+     struct it *it;
+     struct window *w;
+     struct display_pos *pos;
+{
+  /* Keep in mind: the call to reseat in init_iterator skips invisible
+     text, so we might end up at a position different from POS.  This
+     is only a problem when POS is a row start after a newline and an
+     overlay starts there with an after-string, and the overlay has an
+     invisible property.  Since we don't skip invisible text in
+     display_line and elsewhere immediately after consuming the
+     newline before the row start, such a POS will not be in a string,
+     but the call to init_iterator below will move us to the
+     after-string.  */
+  init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
+		 NULL, DEFAULT_FACE_ID);
+
+  /* If position is within an overlay string, set up IT to
+     the right overlay string.  */
+  if (pos->overlay_string_index >= 0)
+    {
+      int relative_index;
+      
+      /* We already have the first chunk of overlay strings in
+	 IT->overlay_strings.  Load more until the one for
+	 pos->overlay_string_index is in IT->overlay_strings.  */
+      if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
+	{
+	  int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
+	  it->current.overlay_string_index = 0;
+	  while (n--)
+	    {
+	      load_overlay_strings (it);
+	      it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
+	    }
+	}
+      
+      it->current.overlay_string_index = pos->overlay_string_index;
+      relative_index = (it->current.overlay_string_index
+			% OVERLAY_STRING_CHUNK_SIZE);
+      it->string = it->overlay_strings[relative_index];
+      it->current.string_pos = pos->string_pos;
+      it->method = next_element_from_string;
+    }
+  else if (CHARPOS (pos->string_pos) >= 0)
+    {
+      /* Recorded position is not in an overlay string, but in another
+	 string.  This can only be a string from a `display' property.
+	 IT should already be filled with that string.  */
+      it->current.string_pos = pos->string_pos;
+      xassert (STRINGP (it->string));
+    }
+
+  /* Restore position in display vector translations or control
+     character translations.  */
+  if (pos->dpvec_index >= 0)
+    {
+      /* This fills IT->dpvec.  */
+      get_next_display_element (it);
+      xassert (it->dpvec && it->current.dpvec_index == 0);
+      it->current.dpvec_index = pos->dpvec_index;
+    }
+  
+  CHECK_IT (it);
+}
+
+
+/* Initialize IT for stepping through current_buffer in window W
+   starting at ROW->start.  */
+
+static void
+init_to_row_start (it, w, row)
+     struct it *it;
+     struct window *w;
+     struct glyph_row *row;
+{
+  init_from_display_pos (it, w, &row->start);
+  it->continuation_lines_width = row->continuation_lines_width;
+  CHECK_IT (it);
+}
+
+     
+/* Initialize IT for stepping through current_buffer in window W
+   starting in the line following ROW, i.e. starting at ROW->end.  */
+
+static void
+init_to_row_end (it, w, row)
+     struct it *it;
+     struct window *w;
+     struct glyph_row *row;
+{
+  init_from_display_pos (it, w, &row->end);
+
+  if (row->continued_p)
+    it->continuation_lines_width = (row->continuation_lines_width
+				    + row->pixel_width);
+  CHECK_IT (it);
+}
+
+
+
+
+/***********************************************************************
+			   Text properties
+ ***********************************************************************/
+
+/* Called when IT reaches IT->stop_charpos.  Handle text property and
+   overlay changes.  Set IT->stop_charpos to the next position where
+   to stop.  */
+
+static void
+handle_stop (it)
+     struct it *it;
+{
+  enum prop_handled handled;
+  int handle_overlay_change_p = 1;
+  struct props *p;
+
+  it->dpvec = NULL;
+  it->current.dpvec_index = -1;
+
+  do
+    {
+      handled = HANDLED_NORMALLY;
+      
+      /* Call text property handlers.  */
+      for (p = it_props; p->handler; ++p)
+	{
+	  handled = p->handler (it);
+	  
+	  if (handled == HANDLED_RECOMPUTE_PROPS)
+	    break;
+	  else if (handled == HANDLED_RETURN)
+	    return;
+	  else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
+	    handle_overlay_change_p = 0;
+	}
+
+      if (handled != HANDLED_RECOMPUTE_PROPS)
+	{
+	  /* Don't check for overlay strings below when set to deliver
+	     characters from a display vector.  */
+	  if (it->method == next_element_from_display_vector)
+	    handle_overlay_change_p = 0;
+
+	  /* Handle overlay changes.  */
+	  if (handle_overlay_change_p)
+	    handled = handle_overlay_change (it);
+      
+	  /* Determine where to stop next.  */
+	  if (handled == HANDLED_NORMALLY)
+	    compute_stop_pos (it);
+	}
+    }
+  while (handled == HANDLED_RECOMPUTE_PROPS);
+}
+
+
+/* Compute IT->stop_charpos from text property and overlay change
+   information for IT's current position.  */
+
+static void
+compute_stop_pos (it)
+     struct it *it;
+{
+  register INTERVAL iv, next_iv;
+  Lisp_Object object, limit, position;
+
+  /* If nowhere else, stop at the end.  */
+  it->stop_charpos = it->end_charpos;
+  
+  if (STRINGP (it->string))
+    {
+      /* Strings are usually short, so don't limit the search for
+	 properties.  */
+      object = it->string;
+      limit = Qnil;
+      XSETFASTINT (position, IT_STRING_CHARPOS (*it));
+    }
+  else
+    {
+      int charpos;
+
+      /* If next overlay change is in front of the current stop pos
+	 (which is IT->end_charpos), stop there.  Note: value of
+	 next_overlay_change is point-max if no overlay change
+	 follows.  */
+      charpos = next_overlay_change (IT_CHARPOS (*it));
+      if (charpos < it->stop_charpos)
+	it->stop_charpos = charpos;
+
+      /* If showing the region, we have to stop at the region
+	 start or end because the face might change there.  */
+      if (it->region_beg_charpos > 0)
+	{
+	  if (IT_CHARPOS (*it) < it->region_beg_charpos)
+	    it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
+	  else if (IT_CHARPOS (*it) < it->region_end_charpos)
+	    it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
+	}
+      
+      /* Set up variables for computing the stop position from text
+         property changes.  */
+      XSETBUFFER (object, current_buffer);
+      XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
+      XSETFASTINT (position, IT_CHARPOS (*it));
+
+    }
+
+  /* Get the interval containing IT's position.  Value is a null
+     interval if there isn't such an interval.  */
+  iv = validate_interval_range (object, &position, &position, 0);
+  if (!NULL_INTERVAL_P (iv))
+    {
+      Lisp_Object values_here[LAST_PROP_IDX];
+      struct props *p;
+
+      /* Get properties here.  */
+      for (p = it_props; p->handler; ++p)
+	values_here[p->idx] = textget (iv->plist, *p->name);
+
+      /* Look for an interval following iv that has different
+	 properties.  */
+      for (next_iv = next_interval (iv);
+	   (!NULL_INTERVAL_P (next_iv)
+	    && (NILP (limit)
+		|| XFASTINT (limit) > next_iv->position));
+	   next_iv = next_interval (next_iv))
+	{
+	  for (p = it_props; p->handler; ++p)
+	    {
+	      Lisp_Object new_value;
+
+	      new_value = textget (next_iv->plist, *p->name);
+	      if (!EQ (values_here[p->idx], new_value))
+		break;
+	    }
+	  
+	  if (p->handler)
+	    break;
+	}
+
+      if (!NULL_INTERVAL_P (next_iv))
+	{
+	  if (INTEGERP (limit)
+	      && next_iv->position >= XFASTINT (limit))
+	    /* No text property change up to limit.  */
+	    it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
+	  else
+	    /* Text properties change in next_iv.  */
+	    it->stop_charpos = min (it->stop_charpos, next_iv->position);
+	}
+    }
+
+  xassert (STRINGP (it->string)
+	   || (it->stop_charpos >= BEGV
+	       && it->stop_charpos >= IT_CHARPOS (*it)));
+}
+
+
+/* Return the position of the next overlay change after POS in
+   current_buffer.  Value is point-max if no overlay change
+   follows.  This is like `next-overlay-change' but doesn't use
+   xmalloc.  */
+
+static int
+next_overlay_change (pos)
+     int pos;
+{
+  int noverlays;
+  int endpos;
+  Lisp_Object *overlays;
+  int len;
+  int i;
+
+  /* Get all overlays at the given position.  */
+  len = 10;
+  overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
+  noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
+  if (noverlays > len)
+    {
+      len = noverlays;
+      overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
+      noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
+    }
+
+  /* If any of these overlays ends before endpos,
+     use its ending point instead.  */
+  for (i = 0; i < noverlays; ++i)
+    {
+      Lisp_Object oend;
+      int oendpos;
+
+      oend = OVERLAY_END (overlays[i]);
+      oendpos = OVERLAY_POSITION (oend);
+      endpos = min (endpos, oendpos);
+    }
+
+  return endpos;
+}
+
+
+
+/***********************************************************************
+			    Fontification
+ ***********************************************************************/
+
+/* Handle changes in the `fontified' property of the current buffer by
+   calling hook functions from Qfontification_functions to fontify
+   regions of text.  */
+
+static enum prop_handled
+handle_fontified_prop (it)
+     struct it *it;
+{
+  Lisp_Object prop, pos;
+  enum prop_handled handled = HANDLED_NORMALLY;
+
+  /* Get the value of the `fontified' property at IT's current buffer
+     position.  (The `fontified' property doesn't have a special
+     meaning in strings.)  If the value is nil, call functions from
+     Qfontification_functions.  */
+  if (!STRINGP (it->string)
+      && it->s == NULL
+      && !NILP (Vfontification_functions)
+      && (pos = make_number (IT_CHARPOS (*it)),
+	  prop = Fget_char_property (pos, Qfontified, Qnil),
+	  NILP (prop)))
+    {
+      Lisp_Object args[2];
+
+      /* Run the hook functions.  */
+      args[0] = Qfontification_functions;
+      args[1] = pos;
+      Frun_hook_with_args (make_number (2), args);
+
+      /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
+	 something.  This avoids an endless loop if they failed to
+	 fontify the text for which reason ever.  */
+      if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
+	handled = HANDLED_RECOMPUTE_PROPS;
+    }
+
+  return handled;
+}
+
+
+
+/***********************************************************************
+				Faces
+ ***********************************************************************/
+
+/* Set up iterator IT from face properties at its current position.
+   Called from handle_stop.  */
+
+static enum prop_handled
+handle_face_prop (it)
+     struct it *it;
+{
+  int new_face_id, next_stop;
+  
+  if (!STRINGP (it->string))
+    {
+      new_face_id
+	= face_at_buffer_position (it->w,
+				   IT_CHARPOS (*it),
+				   it->region_beg_charpos,
+				   it->region_end_charpos,
+				   &next_stop,
+				   (IT_CHARPOS (*it)
+				    + TEXT_PROP_DISTANCE_LIMIT),
+				   0);
+      
+      /* Is this a start of a run of characters with box face?
+	 Caveat: this can be called for a freshly initialized
+	 iterator; face_id is -1 is this case.  We know that the new
+	 face will not change until limit, i.e. if the new face has a
+	 box, all characters up to limit will have one.  But, as
+	 usual, we don't know whether limit is really the end.  */
+      if (new_face_id != it->face_id)
+	{
+	  struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+	  
+	  /* If new face has a box but old face has not, this is
+	     the start of a run of characters with box, i.e. it has
+	     a shadow on the left side.  The value of face_id of the
+	     iterator will be -1 if this is the initial call that gets
+	     the face.  In this case, we have to look in front of IT's
+	     position and see whether there is a face != new_face_id.  */
+	  it->start_of_box_run_p
+	    = (new_face->box != FACE_NO_BOX
+	       && (it->face_id >= 0
+		   || IT_CHARPOS (*it) == BEG
+		   || new_face_id != face_before_it_pos (it)));
+	  it->face_box_p = new_face->box != FACE_NO_BOX;
+	}
+    }
+  else
+    {
+      new_face_id
+	= face_at_string_position (it->w,
+				   it->string,
+				   IT_STRING_CHARPOS (*it),
+				   (it->current.overlay_string_index >= 0
+				    ? IT_CHARPOS (*it)
+				    : 0),
+				   it->region_beg_charpos,
+				   it->region_end_charpos,
+				   &next_stop,
+				   it->base_face_id);
+      
+#if 0 /* This shouldn't be neccessary.  Let's check it.  */
+      /* If IT is used to display a mode line we would really like to
+	 use the mode line face instead of the frame's default face.  */
+      if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
+	  && new_face_id == DEFAULT_FACE_ID)
+	new_face_id = MODE_LINE_FACE_ID;
+#endif
+      
+      /* Is this a start of a run of characters with box?  Caveat:
+	 this can be called for a freshly allocated iterator; face_id
+	 is -1 is this case.  We know that the new face will not
+	 change until the next check pos, i.e. if the new face has a
+	 box, all characters up to that position will have a
+	 box.  But, as usual, we don't know whether that position
+	 is really the end.  */
+      if (new_face_id != it->face_id)
+	{
+	  struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+	  struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
+	  
+	  /* If new face has a box but old face hasn't, this is the
+	     start of a run of characters with box, i.e. it has a
+	     shadow on the left side.  */
+	  it->start_of_box_run_p
+	    = new_face->box && (old_face == NULL || !old_face->box);
+	  it->face_box_p = new_face->box != FACE_NO_BOX;
+	}
+    }
+  
+  it->face_id = new_face_id;
+  it->charset = CHARSET_ASCII;
+  return HANDLED_NORMALLY;
+}
+
+
+/* Compute the face one character before or after the current position
+   of IT.  BEFORE_P non-zero means get the face in front of IT's
+   position.  Value is the id of the face.  */
+
+static int
+face_before_or_after_it_pos (it, before_p)
+     struct it *it;
+     int before_p;
+{
+  int face_id, limit;
+  int next_check_charpos;
+  struct text_pos pos;
+
+  xassert (it->s == NULL);
+    
+  if (STRINGP (it->string))
+    {
+      /* No face change past the end of the string (for the case
+	 we are padding with spaces).  No face change before the
+	 string start.  */
+      if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
+	  || (IT_STRING_CHARPOS (*it) == 0 && before_p))
+	return it->face_id;
+
+      /* Set pos to the position before or after IT's current position.  */
+      if (before_p)
+	pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
+      else
+	pos = string_pos (IT_STRING_CHARPOS (*it) + 1, it->string);
+
+      /* Get the face for ASCII, or unibyte.  */
+      face_id
+	= face_at_string_position (it->w,
+				   it->string,
+				   CHARPOS (pos),
+				   (it->current.overlay_string_index >= 0
+				    ? IT_CHARPOS (*it)
+				    : 0),
+				   it->region_beg_charpos,
+				   it->region_end_charpos,
+				   &next_check_charpos,
+				   it->base_face_id);
+
+      /* Correct the face for charsets different from ASCII.  Do it
+	 for the multibyte case only.  The face returned above is
+	 suitable for unibyte text if IT->string is unibyte.  */
+      if (STRING_MULTIBYTE (it->string))
+	{
+	  unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
+	  int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
+	  int c, len, charset;
+      
+	  c = STRING_CHAR_AND_LENGTH (p, rest, len);
+	  charset = CHAR_CHARSET (c);
+	  if (charset != CHARSET_ASCII)
+	    face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+	}
+    }
+  else
+    {
+      limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
+      pos = it->current.pos;
+      
+      if (before_p)
+	DEC_TEXT_POS (pos);
+      else
+	INC_TEXT_POS (pos);
+      
+      /* Determine face for CHARSET_ASCII, or unibyte.  */
+      face_id = face_at_buffer_position (it->w,
+					 CHARPOS (pos),
+					 it->region_beg_charpos,
+					 it->region_end_charpos,
+					 &next_check_charpos,
+					 limit, 0);
+
+      /* Correct the face for charsets different from ASCII.  Do it
+	 for the multibyte case only.  The face returned above is
+	 suitable for unibyte text if current_buffer is unibyte.  */
+      if (it->multibyte_p)
+	{
+	  int charset = charset_at_position (pos);
+	  if (charset != CHARSET_ASCII)
+	    face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+	}
+    }
+  
+  return face_id;
+}
+
+
+
+/***********************************************************************
+			    Invisible text
+ ***********************************************************************/
+
+/* Set up iterator IT from invisible properties at its current
+   position.  Called from handle_stop.  */
+
+static enum prop_handled
+handle_invisible_prop (it)
+     struct it *it;
+{
+  enum prop_handled handled = HANDLED_NORMALLY;
+
+  if (STRINGP (it->string))
+    {
+      extern Lisp_Object Qinvisible;
+      Lisp_Object prop, end_charpos, limit, charpos;
+
+      /* Get the value of the invisible text property at the
+	 current position.  Value will be nil if there is no such
+	 property.  */
+      XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
+      prop = Fget_text_property (charpos, Qinvisible, it->string);
+
+      if (!NILP (prop))
+	{
+	  handled = HANDLED_RECOMPUTE_PROPS;
+	  
+	  /* Get the position at which the next change of the
+	     invisible text property can be found in IT->string.
+	     Value will be nil if the property value is the same for
+	     all the rest of IT->string.  */
+	  XSETINT (limit, XSTRING (it->string)->size);
+	  end_charpos = Fnext_single_property_change (charpos, Qinvisible,
+						  it->string, limit);
+	  
+	  /* Text at current position is invisible.  The next
+	     change in the property is at position end_charpos.
+	     Move IT's current position to that position.  */
+	  if (INTEGERP (end_charpos)
+	      && XFASTINT (end_charpos) < XFASTINT (limit))
+	    {
+	      struct text_pos old;
+	      old = it->current.string_pos;
+	      IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
+	      compute_string_pos (&it->current.string_pos, old, it->string);
+	    }
+	  else
+	    {
+	      /* The rest of the string is invisible.  If this is an
+		 overlay string, proceed with the next overlay string
+		 or whatever comes and return a character from there.  */
+	      if (it->current.overlay_string_index >= 0)
+		{
+		  next_overlay_string (it);
+		  /* Don't check for overlay strings when we just
+		     finished processing them.  */
+		  handled = HANDLED_OVERLAY_STRING_CONSUMED;
+		}
+	      else
+		{
+		  struct Lisp_String *s = XSTRING (it->string);
+		  IT_STRING_CHARPOS (*it) = s->size;
+		  IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
+		}
+	    }
+	}
+    }
+  else
+    {
+      int visible_p, newpos, next_stop;
+      Lisp_Object pos, prop;
+
+      /* First of all, is there invisible text at this position?  */
+      XSETFASTINT (pos, IT_CHARPOS (*it));
+      prop = Fget_char_property (pos, Qinvisible, it->window);
+      
+      /* If we are on invisible text, skip over it.  */
+      if (TEXT_PROP_MEANS_INVISIBLE (prop))
+	{
+	  /* Record whether we have to display an ellipsis for the
+	     invisible text.  */
+	  int display_ellipsis_p
+	    = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
+
+	  handled = HANDLED_RECOMPUTE_PROPS;
+	  
+	  /* Loop skipping over invisible text.  The loop is left at
+	     ZV or with IT on the first char being visible again.  */
+	  do
+	    {
+	      /* Try to skip some invisible text.  Return value is the
+		 position reached which can be equal to IT's position
+		 if there is nothing invisible here.  This skips both
+		 over invisible text properties and overlays with
+		 invisible property.  */
+	      newpos = skip_invisible (IT_CHARPOS (*it),
+				       &next_stop, ZV, it->window);
+
+	      /* If we skipped nothing at all we weren't at invisible
+		 text in the first place.  If everything to the end of
+		 the buffer was skipped, end the loop.  */
+	      if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
+		visible_p = 1;
+	      else
+		{
+		  /* We skipped some characters but not necessarily
+		     all there are.  Check if we ended up on visible
+		     text.  Fget_char_property returns the property of
+		     the char before the given position, i.e. if we
+		     get visible_p = 1, this means that the char at
+		     newpos is visible.  */
+		  XSETFASTINT (pos, newpos);
+		  prop = Fget_char_property (pos, Qinvisible, it->window);
+		  visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
+		}
+	      
+	      /* If we ended up on invisible text, proceed to
+		 skip starting with next_stop.  */
+	      if (!visible_p)
+		IT_CHARPOS (*it) = next_stop;
+	    }
+	  while (!visible_p);
+	  
+	  /* The position newpos is now either ZV or on visible text.  */
+	  IT_CHARPOS (*it) = newpos;
+	  IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
+	  
+	  /* Maybe return `...' next for the end of the invisible text.  */
+	  if (display_ellipsis_p)
+	    {
+	      if (it->dp 
+		  && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+		{
+		  struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
+		  it->dpvec = v->contents;
+		  it->dpend = v->contents + v->size;
+		}
+	      else 
+		{
+		  /* Default `...'.  */
+		  it->dpvec = default_invis_vector;
+		  it->dpend = default_invis_vector + 3;
+		}
+
+	      /* The ellipsis display does not replace the display of
+	         the character at the new position.  Indicate this by
+	         setting IT->dpvec_char_len to zero.  */
+	      it->dpvec_char_len = 0;
+	      
+	      it->current.dpvec_index = 0;
+	      it->method = next_element_from_display_vector;
+	    }
+	}
+    }
+
+  return handled;
+}
+
+
 
+/***********************************************************************
+			    'display' property
+ ***********************************************************************/
+
+/* Set up iterator IT from `display' property at its current position.
+   Called from handle_stop.  */
+
+static enum prop_handled
+handle_display_prop (it)
+     struct it *it;
+{
+  Lisp_Object prop, object;
+  struct text_pos *position;
+  int space_or_image_found_p;
+
+  if (STRINGP (it->string))
+    {
+      object = it->string;
+      position = &it->current.string_pos;
+    }
+  else
+    {
+      object = Qnil;
+      position = &it->current.pos;
+    }
+
+  /* Reset those iterator values set from display property values.  */
+  it->font_height = Qnil;
+  it->space_width = Qnil;
+  it->voffset = 0;
+
+  /* We don't support recursive `display' properties, i.e. string
+     values that have a string `display' property, that have a string
+     `display' property etc.  */
+  if (!it->string_from_display_prop_p)
+    it->area = TEXT_AREA;
+
+  prop = Fget_char_property (make_number (position->charpos),
+			     Qdisplay, object);
+  if (NILP (prop))
+    return HANDLED_NORMALLY;
+
+  space_or_image_found_p = 0;
+  if (CONSP (prop) && CONSP (XCAR (prop)))
+    {
+      while (CONSP (prop))
+	{
+	  if (handle_single_display_prop (it, XCAR (prop), object, position))
+	    space_or_image_found_p = 1;
+	  prop = XCDR (prop);
+	}
+    }
+  else if (VECTORP (prop))
+    {
+      int i;
+      for (i = 0; i < XVECTOR (prop)->size; ++i)
+	if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
+					object, position))
+	  space_or_image_found_p = 1;
+    }
+  else
+    {
+      if (handle_single_display_prop (it, prop, object, position))
+	space_or_image_found_p = 1;
+    }
+
+  return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
+}
+
+
+/* Value is the position of the end of the `display' property stating
+   at START_POS in OBJECT.  */
+
+static struct text_pos
+display_prop_end (it, object, start_pos)
+     struct it *it;
+     Lisp_Object object;
+     struct text_pos start_pos;
+{
+  Lisp_Object end;
+  struct text_pos end_pos;
+  
+  /* Characters having this form of property are not displayed, so
+     we have to find the end of the property.  */
+  end = Fnext_single_property_change (make_number (start_pos.charpos),
+				      Qdisplay, object, Qnil);
+  if (NILP (end))
+    {
+      /* A nil value of `end' means there are no changes of the
+	 property to the end of the buffer or string.  */
+      if (it->current.overlay_string_index >= 0)
+	end_pos.charpos = XSTRING (it->string)->size;
+      else
+	end_pos.charpos = it->end_charpos;
+    }
+  else
+    end_pos.charpos = XFASTINT (end);
+
+  if (STRINGP (it->string))
+    compute_string_pos (&end_pos, start_pos, it->string);
+  else
+    end_pos.bytepos = CHAR_TO_BYTE (end_pos.charpos);
+
+  return end_pos;
+}
+
+
+/* Set up IT from a single `display' sub-property value PROP.  OBJECT
+   is the object in which the `display' property was found.  *POSITION
+   is the position at which it was found.
+
+   If PROP is a `space' or `image' sub-property, set *POSITION to the
+   end position of the `display' property.
+
+   Value is non-zero if a `space' or `image' property value was found.  */
+
+static int
+handle_single_display_prop (it, prop, object, position)
+     struct it *it;
+     Lisp_Object prop;
+     Lisp_Object object;
+     struct text_pos *position;
+{
+  Lisp_Object value;
+  int space_or_image_found_p = 0;
+
+  Lisp_Object form;
+
+  /* If PROP is a list of the form `(:when FORM VALUE)', FORM is
+     evaluated.  If the result is nil, VALUE is ignored.  */
+  form = Qt;
+  if (CONSP (prop) && EQ (XCAR (prop), QCwhen))
+    {
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+	return 0;
+      form = XCAR (prop);
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+	return 0;
+      prop = XCAR (prop);
+    }
+
+  if (!NILP (form) && !EQ (form, Qt))
+    {
+      struct gcpro gcpro1;
+      struct text_pos end_pos, pt;
+      
+      end_pos = display_prop_end (it, object, *position);
+      GCPRO1 (form);
+
+      /* Temporarily set point to the end position, and then evaluate
+	 the form.  This makes `(eolp)' work as FORM.  */
+      CHARPOS (pt) = PT;
+      BYTEPOS (pt) = PT_BYTE;
+      TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
+      form = eval_form (form);
+      TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
+      UNGCPRO;  
+    }
+  
+  if (NILP (form))
+    return 0;
+
+  if (CONSP (prop)
+      && EQ (XCAR (prop), Qheight)
+      && CONSP (XCDR (prop)))
+    {
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+	return 0;
+      
+      /* `(height HEIGHT)'.  */
+      it->font_height = XCAR (XCDR (prop));
+      if (!NILP (it->font_height))
+	{
+	  struct face *face = FACE_FROM_ID (it->f, it->face_id);
+	  int new_height = -1;
+
+	  if (CONSP (it->font_height)
+	      && (EQ (XCAR (it->font_height), Qplus)
+		  || EQ (XCAR (it->font_height), Qminus))
+	      && CONSP (XCDR (it->font_height))
+	      && INTEGERP (XCAR (XCDR (it->font_height))))
+	    {
+	      /* `(+ N)' or `(- N)' where N is an integer.  */
+	      int steps = XINT (XCAR (XCDR (it->font_height)));
+	      if (EQ (XCAR (it->font_height), Qplus))
+		steps = - steps;
+	      it->face_id = smaller_face (it->f, it->face_id, steps);
+	    }
+	  else if (SYMBOLP (it->font_height))
+	    {
+	      /* Call function with current height as argument.
+		 Value is the new height.  */
+	      Lisp_Object form, height;
+	      struct gcpro gcpro1;
+	      
+	      height = face->lface[LFACE_HEIGHT_INDEX];
+	      form = Fcons (it->font_height, Fcons (height, Qnil));
+	      GCPRO1 (form);
+	      height = eval_form (form);
+	      if (NUMBERP (height))
+		new_height = XFLOATINT (height);
+	      UNGCPRO;
+	    }
+	  else if (NUMBERP (it->font_height))
+	    {
+	      /* Value is a multiple of the canonical char height.  */
+	      struct face *face;
+	      
+	      face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
+	      new_height = (XFLOATINT (it->font_height)
+			    * XINT (face->lface[LFACE_HEIGHT_INDEX]));
+	    }
+	  else
+	    {
+	      /* Evaluate IT->font_height with `height' bound to the
+		 current specified height to get the new height.  */
+	      Lisp_Object value;
+	      int count = specpdl_ptr - specpdl;
+	      
+	      specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
+	      value = eval_form (it->font_height);
+	      unbind_to (count, Qnil);
+	      
+	      if (NUMBERP (value))
+		new_height = XFLOATINT (value);
+	    }
+	  
+	  if (new_height > 0)
+	    it->face_id = face_with_height (it->f, it->face_id, new_height);
+	}
+    }
+  else if (CONSP (prop)
+	   && EQ (XCAR (prop), Qspace_width)
+	   && CONSP (XCDR (prop)))
+    {
+      /* `(space_width WIDTH)'.  */
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+	return 0;
+      
+      value = XCAR (XCDR (prop));
+      if (NUMBERP (value) && XFLOATINT (value) > 0)
+	it->space_width = value;
+    }
+  else if (CONSP (prop)
+	   && EQ (XCAR (prop), Qraise)
+	   && CONSP (XCDR (prop)))
+    {
+#ifdef HAVE_WINDOW_SYSTEM
+      /* `(raise FACTOR)'.  */
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+	return 0;
+      
+      value = XCAR (XCDR (prop));
+      if (NUMBERP (value))
+	{
+	  struct face *face = FACE_FROM_ID (it->f, it->face_id);
+	  it->voffset = - (XFLOATINT (value)
+			   * (face->font->ascent + face->font->descent));
+	}
+#endif /* HAVE_WINDOW_SYSTEM */
+    }
+  else if (!it->string_from_display_prop_p)
+    {
+      /* `(left-margin VALUE)' or `(right-margin VALUE)
+	 or `(nil VALUE)' or VALUE.  */
+      Lisp_Object location, value;
+      struct text_pos start_pos;
+      int valid_p;
+
+      /* Characters having this form of property are not displayed, so
+         we have to find the end of the property.  */
+      space_or_image_found_p = 1;
+      start_pos = *position;
+      *position = display_prop_end (it, object, start_pos);
+
+      /* Let's stop at the new position and assume that all
+	 text properties change there.  */
+      it->stop_charpos = position->charpos;
+
+      if (CONSP (prop)
+	  && !EQ (XCAR (prop), Qspace)
+	  && !EQ (XCAR (prop), Qimage))
+	{
+	  location = XCAR (prop);
+	  value = XCDR (prop);
+	}
+      else
+	{
+	  location = Qnil;
+	  value = prop;
+	}
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+	valid_p = STRINGP (value);
+      else
+	valid_p = (STRINGP (value)
+		   || (CONSP (value) && EQ (XCAR (value), Qspace))
+		   || valid_image_p (value));
+#else /* not HAVE_WINDOW_SYSTEM */
+      valid_p = STRINGP (value);
+#endif /* not HAVE_WINDOW_SYSTEM */
+      
+      if ((EQ (location, Qleft_margin)
+	   || EQ (location, Qright_margin)
+	   || NILP (location))
+	  && valid_p)
+	{
+	  /* Save current settings of IT so that we can restore them
+	     when we are finished with the glyph property value.  */
+	  push_it (it);
+	  
+	  if (NILP (location))
+	    it->area = TEXT_AREA;
+	  else if (EQ (location, Qleft_margin))
+	    it->area = LEFT_MARGIN_AREA;
+	  else
+	    it->area = RIGHT_MARGIN_AREA;
+	  
+	  if (STRINGP (value))
+	    {
+	      it->string = value;
+	      it->multibyte_p = STRING_MULTIBYTE (it->string);
+	      it->current.overlay_string_index = -1;
+	      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+	      it->end_charpos = it->string_nchars
+		= XSTRING (it->string)->size;
+	      it->method = next_element_from_string;
+	      it->stop_charpos = 0;
+	      it->string_from_display_prop_p = 1;
+	    }
+	  else if (CONSP (value) && EQ (XCAR (value), Qspace))
+	    {
+	      it->method = next_element_from_stretch;
+	      it->object = value;
+	      it->current.pos = it->position = start_pos;
+	    }
+#ifdef HAVE_WINDOW_SYSTEM
+	  else
+	    {
+	      it->what = IT_IMAGE;
+	      it->image_id = lookup_image (it->f, value);
+	      it->position = start_pos;
+	      it->object = NILP (object) ? it->w->buffer : object;
+	      it->method = next_element_from_image;
+	      
+	      /* Say that we don't have consumed the characters with
+		 `display' property yet.  The call to pop_it in
+		 set_iterator_to_next will clean this up.  */
+	      *position = start_pos;
+	    }
+#endif /* HAVE_WINDOW_SYSTEM */
+	}
+    }
+
+  return space_or_image_found_p;
+}
+
+
+
+/***********************************************************************
+			   Overlay strings
+ ***********************************************************************/
+
+/* The following structure is used to record overlay strings for
+   later sorting in load_overlay_strings.  */
+
+struct overlay_entry
+{
+  Lisp_Object string;
+  int priority;
+  int after_string_p;
+};
+
+
+/* Set up iterator IT from overlay strings at its current position.
+   Called from handle_stop.  */
+
+static enum prop_handled
+handle_overlay_change (it)
+     struct it *it;
+{
+  /* Overlays are handled in current_buffer only.  */
+  if (STRINGP (it->string))
+    return HANDLED_NORMALLY;
+  else
+    return (get_overlay_strings (it)
+	    ? HANDLED_RECOMPUTE_PROPS
+	    : HANDLED_NORMALLY);
+}
+
+
+/* Set up the next overlay string for delivery by IT, if there is an
+   overlay string to deliver.  Called by set_iterator_to_next when the
+   end of the current overlay string is reached.  If there are more
+   overlay strings to display, IT->string and
+   IT->current.overlay_string_index are set appropriately here.
+   Otherwise IT->string is set to nil.  */
+   
+static void
+next_overlay_string (it)
+     struct it *it;
+{
+  ++it->current.overlay_string_index;
+  if (it->current.overlay_string_index == it->n_overlay_strings)
+    {
+      /* No more overlay strings.  Restore IT's settings to what
+	 they were before overlay strings were processed, and
+	 continue to deliver from current_buffer.  */
+      pop_it (it);
+      xassert (it->stop_charpos >= BEGV
+	       && it->stop_charpos <= it->end_charpos);
+      it->string = Qnil;
+      it->current.overlay_string_index = -1;
+      SET_TEXT_POS (it->current.string_pos, -1, -1);
+      it->n_overlay_strings = 0;
+      it->method = next_element_from_buffer;
+    }
+  else
+    {
+      /* There are more overlay strings to process.  If
+	 IT->current.overlay_string_index has advanced to a position
+	 where we must load IT->overlay_strings with more strings, do
+	 it.  */
+      int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
+  
+      if (it->current.overlay_string_index && i == 0)
+	load_overlay_strings (it);
+
+      /* Initialize IT to deliver display elements from the overlay
+         string.  */
+      it->string = it->overlay_strings[i];
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
+      SET_TEXT_POS (it->current.string_pos, 0, 0);
+      it->method = next_element_from_string;
+      it->stop_charpos = 0;
+    }
+  
+  CHECK_IT (it);
+}
+
+
+/* Compare two overlay_entry structures E1 and E2.  Used as a
+   comparison function for qsort in load_overlay_strings.  Overlay
+   strings for the same position are sorted so that
+
+   1. All after-strings come in front of before-strings.
+   
+   2. Within after-strings, strings are sorted so that overlay strings
+   from overlays with higher priorities come first.
+
+   2. Within before-strings, strings are sorted so that overlay
+   strings from overlays with higher priorities come last.
+
+   Value is analogous to strcmp.  */
+
+  
+static int
+compare_overlay_entries (e1, e2)
+     void *e1, *e2;
+{
+  struct overlay_entry *entry1 = (struct overlay_entry *) e1;
+  struct overlay_entry *entry2 = (struct overlay_entry *) e2;
+  int result;
+
+  if (entry1->after_string_p != entry2->after_string_p)
+    /* Let after-strings appear in front of before-strings.  */
+    result = entry1->after_string_p ? -1 : 1;
+  else if (entry1->after_string_p)
+    /* After-strings sorted in order of decreasing priority.  */
+    result = entry2->priority - entry1->priority;
+  else
+    /* Before-strings sorted in order of increasing priority.  */
+    result = entry1->priority - entry2->priority;
+
+  return result;
+}
+
+
+/* Load the vector IT->overlay_strings with overlay strings from IT's
+   current buffer position.  Set IT->n_overlays to the total number of
+   overlay strings found.  
+
+   Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
+   a time.  On entry into load_overlay_strings,
+   IT->current.overlay_string_index gives the number of overlay
+   strings that have already been loaded by previous calls to this
+   function.
+
+   Overlay strings are sorted so that after-string strings come in
+   front of before-string strings.  Within before and after-strings,
+   strings are sorted by overlay priority.  See also function
+   compare_overlay_entries.  */
+   
+static void
+load_overlay_strings (it)
+     struct it *it;
+{
+  extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
+  Lisp_Object ov, overlay, window, str;
+  int start, end;
+  int size = 20;
+  int n = 0, i, j;
+  struct overlay_entry *entries
+    = (struct overlay_entry *) alloca (size * sizeof *entries);
+
+  /* Append the overlay string STRING of overlay OVERLAY to vector
+     `entries' which has size `size' and currently contains `n'
+     elements.  AFTER_P non-zero means STRING is an after-string of
+     OVERLAY.  */
+#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P)			\
+  do									\
+    {									\
+      Lisp_Object priority;						\
+									\
+      if (n == size)							\
+	{								\
+	  int new_size = 2 * size;					\
+	  struct overlay_entry *old = entries;				\
+	  entries =							\
+            (struct overlay_entry *) alloca (new_size			\
+					     * sizeof *entries);	\
+	  bcopy (old, entries, size * sizeof *entries);			\
+	  size = new_size;						\
+	}								\
+									\
+      entries[n].string = (STRING);					\
+      priority = Foverlay_get ((OVERLAY), Qpriority);			\
+      entries[n].priority 						\
+	= INTEGERP (priority) ? XFASTINT (priority) : 0;		\
+      entries[n].after_string_p = (AFTER_P);				\
+      ++n;								\
+    }									\
+  while (0)
+
+  /* Process overlay before the overlay center.  */
+  for (ov = current_buffer->overlays_before;
+       CONSP (ov);
+       ov = XCONS (ov)->cdr)
+    {
+      overlay = XCONS (ov)->car;
+      xassert (OVERLAYP (overlay));
+      start = OVERLAY_POSITION (OVERLAY_START (overlay));
+      end = OVERLAY_POSITION (OVERLAY_END (overlay));
+      
+      if (end < IT_CHARPOS (*it))
+	break;
+
+      /* Skip this overlay if it doesn't start or end at IT's current
+	 position.  */
+      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+	continue;
+      
+      /* Skip this overlay if it doesn't apply to IT->w.  */
+      window = Foverlay_get (overlay, Qwindow);
+      if (WINDOWP (window) && XWINDOW (window) != it->w)
+	continue;
+
+      /* If overlay has a non-empty before-string, record it.  */
+      if (start == IT_CHARPOS (*it)
+	  && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
+	  && XSTRING (str)->size)
+	RECORD_OVERLAY_STRING (overlay, str, 0);
+      
+      /* If overlay has a non-empty after-string, record it.  */
+      if (end == IT_CHARPOS (*it)
+	  && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
+	  && XSTRING (str)->size)
+	RECORD_OVERLAY_STRING (overlay, str, 1);
+    }
+      
+  /* Process overlays after the overlay center.  */
+  for (ov = current_buffer->overlays_after;
+	CONSP (ov);
+	ov = XCONS (ov)->cdr)
+    {
+      overlay = XCONS (ov)->car;
+      xassert (OVERLAYP (overlay));
+      start = OVERLAY_POSITION (OVERLAY_START (overlay));
+      end = OVERLAY_POSITION (OVERLAY_END (overlay));
+
+      if (start > IT_CHARPOS (*it))
+	break;
+      
+      /* Skip this overlay if it doesn't start or end at IT's current
+	 position.  */
+      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+	continue;
+
+      /* Skip this overlay if it doesn't apply to IT->w.  */
+      window = Foverlay_get (overlay, Qwindow);
+      if (WINDOWP (window) && XWINDOW (window) != it->w)
+	continue;
+      
+      /* If overlay has a non-empty before-string, record it.  */
+      if (start == IT_CHARPOS (*it)
+	  && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
+	  && XSTRING (str)->size)
+	RECORD_OVERLAY_STRING (overlay, str, 0);
+			       
+      /* If overlay has a non-empty after-string, record it.  */
+      if (end == IT_CHARPOS (*it)
+	  && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
+	  && XSTRING (str)->size)
+	RECORD_OVERLAY_STRING (overlay, str, 1);
+    }
+
+#undef RECORD_OVERLAY_STRING
+   
+  /* Sort entries.  */
+  qsort (entries, n, sizeof *entries, compare_overlay_entries);
+
+  /* Record the total number of strings to process.  */
+  it->n_overlay_strings = n;
+
+  /* IT->current.overlay_string_index is the number of overlay strings
+     that have already been consumed by IT.  Copy some of the
+     remaining overlay strings to IT->overlay_strings.  */
+  i = 0;
+  j = it->current.overlay_string_index;
+  while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
+    it->overlay_strings[i++] = entries[j++].string;
+  
+  CHECK_IT (it);
+}
+
+
+/* Get the first chunk of overlay strings at IT's current buffer
+   position.  Value is non-zero if at least one overlay string was
+   found.   */
+
+static int
+get_overlay_strings (it)
+     struct it *it;
+{
+  /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
+     process.  This fills IT->overlay_strings with strings, and sets
+     IT->n_overlay_strings to the total number of strings to process.
+     IT->pos.overlay_string_index has to be set temporarily to zero
+     because load_overlay_strings needs this; it must be set to -1
+     when no overlay strings are found because a zero value would
+     indicate a position in the first overlay string.  */
+  it->current.overlay_string_index = 0;
+  load_overlay_strings (it);
+
+  /* If we found overlay strings, set up IT to deliver display
+     elements from the first one.  Otherwise set up IT to deliver
+     from current_buffer.  */
+  if (it->n_overlay_strings)
+    {
+      /* Make sure we know settings in current_buffer, so that we can
+	 restore meaningful values when we're done with the overlay
+	 strings.  */
+      compute_stop_pos (it);
+      xassert (it->face_id >= 0);
+      
+      /* Save IT's settings.  They are restored after all overlay
+	 strings have been processed.  */
+      xassert (it->sp == 0);
+      push_it (it);
+
+      /* Set up IT to deliver display elements from the first overlay
+	 string.  */
+      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+      it->stop_charpos = 0;
+      it->string = it->overlay_strings[0];
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
+      xassert (STRINGP (it->string));
+      it->method = next_element_from_string;
+    }
+  else
+    {
+      it->string = Qnil;
+      it->current.overlay_string_index = -1;
+      it->method = next_element_from_buffer;
+    }
+
+  CHECK_IT (it);
+
+  /* Value is non-zero if we found at least one overlay string.  */
+  return STRINGP (it->string);
+}
+
+
+
+/***********************************************************************
+		      Saving and restoring state
+ ***********************************************************************/
+
+/* Save current settings of IT on IT->stack.  Called, for example,
+   before setting up IT for an overlay string, to be able to restore
+   IT's settings to what they were after the overlay string has been
+   processed.  */
+
+static void
+push_it (it)
+     struct it *it;
+{
+  struct iterator_stack_entry *p;
+  
+  xassert (it->sp < 2);
+  p = it->stack + it->sp;
+
+  p->stop_charpos = it->stop_charpos;
+  xassert (it->face_id >= 0);
+  p->face_id = it->face_id;
+  p->string = it->string;
+  p->pos = it->current;
+  p->end_charpos = it->end_charpos;
+  p->string_nchars = it->string_nchars;
+  p->area = it->area;
+  p->multibyte_p = it->multibyte_p;
+  p->space_width = it->space_width;
+  p->font_height = it->font_height;
+  p->voffset = it->voffset;
+  p->string_from_display_prop_p = it->string_from_display_prop_p;
+  ++it->sp;
+}
+
+
+/* Restore IT's settings from IT->stack.  Called, for example, when no
+   more overlay strings must be processed, and we return to delivering
+   display elements from a buffer, or when the end of a string from a
+   `display' property is reached and we return to delivering display
+   elements from an overlay string, or from a buffer.  */
+
+static void
+pop_it (it)
+     struct it *it;
+{
+  struct iterator_stack_entry *p;
+  
+  xassert (it->sp > 0);
+  --it->sp;
+  p = it->stack + it->sp;
+  it->stop_charpos = p->stop_charpos;
+  it->face_id = p->face_id;
+  it->string = p->string;
+  it->current = p->pos;
+  it->end_charpos = p->end_charpos;
+  it->string_nchars = p->string_nchars;
+  it->area = p->area;
+  it->multibyte_p = p->multibyte_p;
+  it->space_width = p->space_width;
+  it->font_height = p->font_height;
+  it->voffset = p->voffset;
+  it->string_from_display_prop_p = p->string_from_display_prop_p;
+}
+
+
+
+/***********************************************************************
+			  Moving over lines
+ ***********************************************************************/
+
+/* Set IT's current position to the previous line start.  */
+
+static void
+back_to_previous_line_start (it)
+     struct it *it;
+{
+  IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
+  IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
+}
+
+
+/* Set IT's current position to the next line start.  */
+
+static void
+forward_to_next_line_start (it)
+     struct it *it;
+{
+  IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1);
+  IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
+}
+
+
+/* Set IT's current position to the previous visible line start.  Skip
+   invisible text that is so either due to text properties or due to
+   selective display.  Caution: this does not change IT->current_x and
+   IT->hpos.  */
+
+static void
+back_to_previous_visible_line_start (it)
+     struct it *it;
+{
+  int visible_p = 0;
+
+  /* Go back one newline if not on BEGV already.  */
+  if (IT_CHARPOS (*it) > BEGV)
+    back_to_previous_line_start (it);
+
+  /* Move over lines that are invisible because of selective display
+     or text properties.  */
+  while (IT_CHARPOS (*it) > BEGV
+	 && !visible_p)
+    {
+      visible_p = 1;
+
+      /* If selective > 0, then lines indented more than that values
+	 are invisible.  */
+      if (it->selective > 0
+	  && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
+				it->selective))
+	visible_p = 0;
+#ifdef USE_TEXT_PROPERTIES
+      else 
+	{
+	  Lisp_Object prop;
+
+	  prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
+	  if (TEXT_PROP_MEANS_INVISIBLE (prop))
+	    visible_p = 0;
+	}
+#endif /* USE_TEXT_PROPERTIES  */
+
+      /* Back one more newline if the current one is invisible.  */
+      if (!visible_p)
+	back_to_previous_line_start (it);
+    }
+
+  xassert (IT_CHARPOS (*it) >= BEGV);
+  xassert (IT_CHARPOS (*it) == BEGV
+	   || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
+  CHECK_IT (it);
+}
+
+
+/* Reseat iterator IT at the previous visible line start.  Skip
+   invisible text that is so either due to text properties or due to
+   selective display.  At the end, update IT's overlay information,
+   face information etc.  */
+
+static void
+reseat_at_previous_visible_line_start (it)
+     struct it *it;
+{
+  back_to_previous_visible_line_start (it);
+  reseat (it, it->current.pos, 1);
+  CHECK_IT (it);
+}
+
+
+/* Reseat iterator IT on the next visible line start in the current
+   buffer.  Skip over invisible text that is so because of selective
+   display.  Compute faces, overlays etc at the new position.  Note
+   that this function does not skip over text that is invisible
+   because of text properties.  */
+
+static void
+reseat_at_next_visible_line_start (it)
+     struct it *it;
+{
+  /* Restore the buffer position when currently not delivering display
+     elements from the current buffer.  This is the case, for example,
+     when called at the end of a truncated overlay string.  */
+  while (it->sp)
+    pop_it (it);
+  it->method = next_element_from_buffer;
+  
+  /* Otherwise, scan_buffer would not work.  */
+  if (IT_CHARPOS (*it) < ZV)
+    {
+      /* If on a newline, advance past it.  Otherwise, find the next
+	 newline which automatically gives us the position following
+	 the newline.  */
+      if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n')
+	{
+	  ++IT_CHARPOS (*it);
+	  ++IT_BYTEPOS (*it);
+	}
+      else
+	forward_to_next_line_start (it);
+
+      /* We must either have reached the end of the buffer or end up
+	 after a newline.  */
+      xassert (IT_CHARPOS (*it) == ZV
+	       || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
+
+      /* Skip over lines that are invisible because they are indented
+	 more than the value of IT->selective.  */
+      if (it->selective > 0)
+	while (IT_CHARPOS (*it) < ZV
+	       && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
+				     it->selective))
+	  forward_to_next_line_start (it);
+      
+      /* Set the iterator there.  The 0 as the last parameter of
+	 reseat means don't force a text property lookup.  The lookup
+	 is then only done if we've skipped past the iterator's
+	 check_charpos'es.  This optimization is important because
+	 text property lookups tend to be expensive.  */
+      reseat (it, it->current.pos, 0);
+    }
+  
+  CHECK_IT (it);
+}
+
+
+
+/***********************************************************************
+		   Changing an iterator's position
+***********************************************************************/
+
+/* Change IT's current position to POS in current_buffer.  If FORCE_P
+   is non-zero, always check for text properties at the new position.
+   Otherwise, text properties are only looked up if POS >=
+   IT->check_charpos of a property.  */
+
+static void
+reseat (it, pos, force_p)
+     struct it *it;
+     struct text_pos pos;
+     int force_p;
+{
+  int original_pos = IT_CHARPOS (*it);
+
+  reseat_1 (it, pos, 0);
+
+  /* Determine where to check text properties.  Avoid doing it
+     where possible because text property lookup is very expensive.  */
+  if (force_p
+      || CHARPOS (pos) > it->stop_charpos
+      || CHARPOS (pos) < original_pos)
+    handle_stop (it);
+
+  CHECK_IT (it);
+}
+
+
+/* Change IT's buffer position to POS.  SET_STOP_P non-zero means set
+   IT->stop_pos to POS, also.  */
+
+static void
+reseat_1 (it, pos, set_stop_p)
+     struct it *it;
+     struct text_pos pos;
+     int set_stop_p;
+{
+  /* Don't call this function when scanning a C string.  */
+  xassert (it->s == NULL);
+
+  /* POS must be a reasonable value.  */
+  xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
+
+  it->current.pos = it->position = pos;
+  XSETBUFFER (it->object, current_buffer);
+  it->dpvec = NULL;
+  it->current.dpvec_index = -1;
+  it->current.overlay_string_index = -1;
+  IT_STRING_CHARPOS (*it) = -1;
+  IT_STRING_BYTEPOS (*it) = -1;
+  it->string = Qnil;
+  it->method = next_element_from_buffer;
+  it->sp = 0;
+
+  if (set_stop_p)
+    it->stop_charpos = CHARPOS (pos);
+}
+
+
+/* Set up IT for displaying a string, starting at CHARPOS in window W.
+   If S is non-null, it is a C string to iterate over.  Otherwise,
+   STRING gives a Lisp string to iterate over.
+   
+   If PRECISION > 0, don't return more then PRECISION number of
+   characters from the string.
+
+   If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
+   characters have been returned.  FIELD_WIDTH < 0 means an infinite
+   field width.
+
+   MULTIBYTE = 0 means disable processing of multibyte characters,
+   MULTIBYTE > 0 means enable it,
+   MULTIBYTE < 0 means use IT->multibyte_p.
+
+   IT must be initialized via a prior call to init_iterator before
+   calling this function.  */
+
+static void
+reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
+     struct it *it;
+     unsigned char *s;
+     Lisp_Object string;
+     int charpos;
+     int precision, field_width, multibyte;
+{
+  /* No region in strings.  */
+  it->region_beg_charpos = it->region_end_charpos = -1;
+
+  /* No text property checks performed by default, but see below.  */
+  it->stop_charpos = -1;
+
+  /* Set iterator position and end position.  */
+  bzero (&it->current, sizeof it->current);
+  it->current.overlay_string_index = -1;
+  it->current.dpvec_index = -1;
+  it->charset = CHARSET_ASCII;
+  xassert (charpos >= 0);
+  
+  /* Use the setting of MULTIBYTE if specified.  */
+  if (multibyte >= 0)
+    it->multibyte_p = multibyte > 0;
+  
+  if (s == NULL)
+    {
+      xassert (STRINGP (string));
+      it->string = string;
+      it->s = NULL;
+      it->end_charpos = it->string_nchars = XSTRING (string)->size;
+      it->method = next_element_from_string;
+      it->current.string_pos = string_pos (charpos, string);
+    }
+  else
+    {
+      it->s = s;
+      it->string = Qnil;
+
+      /* Note that we use IT->current.pos, not it->current.string_pos,
+	 for displaying C strings.  */
+      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
+      if (it->multibyte_p)
+	{
+	  it->current.pos = c_string_pos (charpos, s, 1);
+	  it->end_charpos = it->string_nchars = number_of_chars (s, 1);
+	}
+      else
+	{
+	  IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
+	  it->end_charpos = it->string_nchars = strlen (s);
+	}
+      
+      it->method = next_element_from_c_string;
+    }
+
+  /* PRECISION > 0 means don't return more than PRECISION characters
+     from the string.  */
+  if (precision > 0 && it->end_charpos - charpos > precision)
+    it->end_charpos = it->string_nchars = charpos + precision;
+
+  /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
+     characters have been returned.  FIELD_WIDTH == 0 means don't pad,
+     FIELD_WIDTH < 0 means infinite field width.  This is useful for
+     padding with `-' at the end of a mode line.  */
+  if (field_width < 0)
+    field_width = INFINITY;
+  if (field_width > it->end_charpos - charpos)
+    it->end_charpos = charpos + field_width;
+
+  /* Use the standard display table for displaying strings.  */
+  if (DISP_TABLE_P (Vstandard_display_table))
+    it->dp = XCHAR_TABLE (Vstandard_display_table);
+
+  it->stop_charpos = charpos;
+  CHECK_IT (it);
+}
+
+
+
+/***********************************************************************
+			      Iteration
+ ***********************************************************************/
+
+/* Load IT's display element fields with information about the next
+   display element from the current position of IT.  Value is zero if
+   end of buffer (or C string) is reached.  */
+
+int
+get_next_display_element (it)
+     struct it *it;
+{
+  /* Non-zero means that we found an display element.  Zero means that
+     we hit the end of what we iterate over.  Performance note: the
+     function pointer `method' used here turns out to be faster than
+     using a sequence of if-statements.  */
+  int success_p = (*it->method) (it);
+  int charset;
+
+  if (it->what == IT_CHARACTER)
+    {
+      /* Map via display table or translate control characters.
+	 IT->c, IT->len etc. have been set to the next character by
+	 the function call above.  If we have a display table, and it
+	 contains an entry for IT->c, translate it.  Don't do this if
+	 IT->c itself comes from a display table, otherwise we could
+	 end up in an infinite recursion.  (An alternative could be to
+	 count the recursion depth of this function and signal an
+	 error when a certain maximum depth is reached.)  Is it worth
+	 it?  */
+      if (success_p && it->dpvec == NULL)
+	{
+	  Lisp_Object dv;
+
+	  if (it->dp
+	      && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
+		  VECTORP (dv)))
+	    {
+	      struct Lisp_Vector *v = XVECTOR (dv);
+
+	      /* Return the first character from the display table
+		 entry, if not empty.  If empty, don't display the
+		 current character.  */
+	      if (v->size)
+		{
+		  it->dpvec_char_len = it->len;
+		  it->dpvec = v->contents;
+		  it->dpend = v->contents + v->size;
+		  it->current.dpvec_index = 0;
+		  it->method = next_element_from_display_vector;
+		}
+
+	      success_p = get_next_display_element (it);
+	    }
+
+	  /* Translate control characters into `\003' or `^C' form.
+	     Control characters coming from a display table entry are
+	     currently not translated because we use IT->dpvec to hold
+	     the translation.  This could easily be changed but I
+	     don't believe that it is worth doing.  */
+	  else if ((it->c < ' '
+		    && (it->area != TEXT_AREA
+			|| (it->c != '\n'
+			    && it->c != '\t'
+			    && it->c != '\r')))
+		   || (it->c >= 128
+		       && it->len == 1))
+	    {
+	      /* IT->c is a control character which must be displayed
+		 either as '\003' or as `^C' where the '\\' and '^'
+		 can be defined in the display table.  Fill
+		 IT->ctl_chars with glyphs for what we have to
+		 display.  Then, set IT->dpvec to these glyphs.  */
+	      GLYPH g;
+
+	      if (it->c < ' ' && it->ctl_arrow_p)
+		{
+		  /* Set IT->ctl_chars[0] to the glyph for `^'.  */
+		  if (it->dp
+		      && INTEGERP (DISP_CTRL_GLYPH (it->dp))
+		      && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
+		    g = XINT (DISP_CTRL_GLYPH (it->dp));
+		  else
+		    g = FAST_MAKE_GLYPH ('^', 0);
+		  XSETINT (it->ctl_chars[0], g);
+
+		  g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
+		  XSETINT (it->ctl_chars[1], g);
+
+		  /* Set up IT->dpvec and return first character from it.  */
+		  it->dpvec_char_len = it->len;
+		  it->dpvec = it->ctl_chars;
+		  it->dpend = it->dpvec + 2;
+		  it->current.dpvec_index = 0;
+		  it->method = next_element_from_display_vector;
+		  get_next_display_element (it);
+		}
+	      else
+		{
+		  /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
+		  if (it->dp
+		      && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+		      && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
+		    g = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
+		  else
+		    g = FAST_MAKE_GLYPH ('\\', 0);
+		  XSETINT (it->ctl_chars[0], g);
+
+		  /* Insert three more glyphs into IT->ctl_chars for
+		     the octal display of the character.  */
+		  g = FAST_MAKE_GLYPH (((it->c >> 6) & 7) + '0', 0); 
+		  XSETINT (it->ctl_chars[1], g);
+		  g = FAST_MAKE_GLYPH (((it->c >> 3) & 7) + '0', 0); 
+		  XSETINT (it->ctl_chars[2], g);
+		  g = FAST_MAKE_GLYPH ((it->c & 7) + '0', 0); 
+		  XSETINT (it->ctl_chars[3], g);
+
+		  /* Set up IT->dpvec and return the first character
+                     from it.  */
+		  it->dpvec_char_len = it->len;
+		  it->dpvec = it->ctl_chars;
+		  it->dpend = it->dpvec + 4;
+		  it->current.dpvec_index = 0;
+		  it->method = next_element_from_display_vector;
+		  get_next_display_element (it);
+		}
+	    }
+	}
+
+      /* Adjust face id if charset changes.  There are no charset
+         changes in unibyte text because Emacs' charsets are not
+	 applicable there.  */
+      if (it->multibyte_p
+	  && success_p
+	  && (charset = CHAR_CHARSET (it->c),
+	      charset != it->charset))
+	{
+	  it->charset = charset;
+	  it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
+	}
+    }
+
+  /* Is this character the last one of a run of characters with
+     box?  If yes, set IT->end_of_box_run_p to 1.  */
+  if (it->face_box_p
+      && it->s == NULL)
+    {
+      int face_id;
+      struct face *face;
+
+      it->end_of_box_run_p
+	= ((face_id = face_after_it_pos (it),
+	    face_id != it->face_id)
+	   && (face = FACE_FROM_ID (it->f, face_id),
+	       face->box == FACE_NO_BOX));
+    }
+
+  /* Value is 0 if end of buffer or string reached.  */
+  return success_p;
+}
+
+
+/* Move IT to the next display element.
+
+   Functions get_next_display_element and set_iterator_to_next are
+   separate because I find this arrangement easier to handle than a
+   get_next_display_element function that also increments IT's
+   position.  The way it is we can first look at an iterator's current
+   display element, decide whether it fits on a line, and if it does,
+   increment the iterator position.  The other way around we probably
+   would either need a flag indicating whether the iterator has to be
+   incremented the next time, or we would have to implement a
+   decrement position function which would not be easy to write.  */
+
+void
+set_iterator_to_next (it)
+     struct it *it;
+{
+  if (it->method == next_element_from_buffer)
+    {
+      /* The current display element of IT is a character from
+	 current_buffer.  Advance in the buffer, and maybe skip over
+	 invisible lines that are so because of selective display.  */
+      if (ITERATOR_AT_END_OF_LINE_P (it))
+	reseat_at_next_visible_line_start (it);
+      else
+	{
+	  xassert (it->len != 0);
+	  IT_BYTEPOS (*it) += it->len;
+	  IT_CHARPOS (*it) += 1;
+	  xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
+	}
+    }
+  else if (it->method == next_element_from_c_string)
+    {
+      /* Current display element of IT is from a C string.  */
+      IT_BYTEPOS (*it) += it->len;
+      IT_CHARPOS (*it) += 1;
+    }
+  else if (it->method == next_element_from_display_vector)
+    {
+      /* Current display element of IT is from a display table entry.
+	 Advance in the display table definition.  Reset it to null if
+	 end reached, and continue with characters from buffers/
+	 strings.  */
+      ++it->current.dpvec_index;
+      it->face_id = it->saved_face_id;
+      if (it->dpvec + it->current.dpvec_index == it->dpend)
+	{
+	  if (it->s)
+	    it->method = next_element_from_c_string;
+	  else if (STRINGP (it->string))
+	    it->method = next_element_from_string;
+	  else
+	    it->method = next_element_from_buffer;
+
+	  it->dpvec = NULL;
+	  it->current.dpvec_index = -1;
+
+	  /* Consume the character which was displayed via IT->dpvec.  */
+	  if (it->dpvec_char_len)
+	    {
+	      it->len = it->dpvec_char_len;
+	      set_iterator_to_next (it);
+	    }
+	}
+    }
+  else if (it->method == next_element_from_string)
+    {
+      /* Current display element is a character from a Lisp string.  */
+      xassert (it->s == NULL && STRINGP (it->string));
+      IT_STRING_BYTEPOS (*it) += it->len;
+      IT_STRING_CHARPOS (*it) += 1;
+      
+    consider_string_end:
+
+      if (it->current.overlay_string_index >= 0)
+	{
+	  /* IT->string is an overlay string.  Advance to the
+	     next, if there is one.  */
+	  if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
+	    next_overlay_string (it);
+	}
+      else
+	{
+	  /* IT->string is not an overlay string.  If we reached
+	     its end, and there is something on IT->stack, proceed
+	     with what is on the stack.  This can be either another
+	     string, this time an overlay string, or a buffer.  */
+	  if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
+	      && it->sp > 0)
+	    {
+	      pop_it (it);
+	      if (!STRINGP (it->string))
+		it->method = next_element_from_buffer;
+	    }
+	}
+    }
+  else if (it->method == next_element_from_image
+	   || it->method == next_element_from_stretch)
+    {
+      /* The position etc with which we have to proceed are on
+	 the stack.  The position may be at the end of a string,
+         if the `display' property takes up the whole string.  */
+      pop_it (it);
+      it->image_id = 0;
+      if (STRINGP (it->string))
+	{
+	  it->method = next_element_from_string;
+	  goto consider_string_end;
+	}
+      else
+	it->method = next_element_from_buffer;
+    }
+  else
+    /* There are no other methods defined, so this should be a bug.  */
+    abort ();
+
+  /* Reset flags indicating start and end of a sequence of
+     characters with box.  */
+  it->start_of_box_run_p = it->end_of_box_run_p = 0;
+  
+  xassert (it->method != next_element_from_string
+	   || (STRINGP (it->string)
+	       && IT_STRING_CHARPOS (*it) >= 0));
+}
+
+
+/* Load IT's display element fields with information about the next
+   display element which comes from a display table entry or from the
+   result of translating a control character to one of the forms `^C'
+   or `\003'.  IT->dpvec holds the glyphs to return as characters.  */
+
+static int
+next_element_from_display_vector (it)
+     struct it *it;
+{
+  /* Precondition.  */
+  xassert (it->dpvec && it->current.dpvec_index >= 0);
+
+  /* Remember the current face id in case glyphs specify faces.
+     IT's face is restored in set_iterator_to_next.  */
+  it->saved_face_id = it->face_id;
+  
+  if (INTEGERP (*it->dpvec)
+      && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
+    {
+      int lface_id;
+      GLYPH g;
+
+      g = XFASTINT (it->dpvec[it->current.dpvec_index]);
+      it->c = FAST_GLYPH_CHAR (g);
+      it->len = CHAR_LEN (it->c);
+
+      /* The entry may contain a face id to use.  Such a face id is
+	 the id of a Lisp face, not a realized face.  A face id of
+	 zero means no face.  */
+      lface_id = FAST_GLYPH_FACE (g);
+      if (lface_id)
+	{
+	  int face_id = ascii_face_of_lisp_face (it->f, lface_id);
+	  if (face_id >= 0)
+	    {
+	      it->face_id = face_id;
+	      it->charset = CHARSET_ASCII;
+	    }
+	}
+    }
+  else
+    /* Display table entry is invalid.  Return a space.  */
+    it->c = ' ', it->len = 1;
+
+  /* Don't change position and object of the iterator here.  They are
+     still the values of the character that had this display table
+     entry or was translated, and that's what we want.  */
+  it->what = IT_CHARACTER;
+  return 1;
+}
+
+
+/* Load IT with the next display element from Lisp string IT->string.
+   IT->current.string_pos is the current position within the string.
+   If IT->current.overlay_string_index >= 0, the Lisp string is an
+   overlay string.  */
+
+static int
+next_element_from_string (it)
+     struct it *it;
+{
+  struct text_pos position;
+
+  xassert (STRINGP (it->string));
+  xassert (IT_STRING_CHARPOS (*it) >= 0);
+  position = it->current.string_pos;
+
+  /* Time to check for invisible text?  */
+  if (IT_STRING_CHARPOS (*it) < it->end_charpos
+      && IT_STRING_CHARPOS (*it) == it->stop_charpos)
+    {
+      handle_stop (it);
+
+      /* Since a handler may have changed IT->method, we must
+	 recurse here.  */
+      return get_next_display_element (it);
+    }
+
+  if (it->current.overlay_string_index >= 0)
+    {
+      /* Get the next character from an overlay string.  In overlay
+	 strings, There is no field width or padding with spaces to
+	 do.  */
+      if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
+	{
+	  it->what = IT_EOB;
+	  return 0;
+	}
+      else if (STRING_MULTIBYTE (it->string))
+	{
+	  int remaining = (STRING_BYTES (XSTRING (it->string))
+			   - IT_STRING_BYTEPOS (*it));
+	  unsigned char *s = (XSTRING (it->string)->data
+			      + IT_STRING_BYTEPOS (*it));
+	  it->c = STRING_CHAR_AND_LENGTH (s, remaining, it->len);
+	}
+      else
+	{
+	  it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
+	  it->len = 1;
+	}
+    }
+  else
+    {
+      /* Get the next character from a Lisp string that is not an
+	 overlay string.  Such strings come from the mode line, for
+	 example.  We may have to pad with spaces, or truncate the
+	 string.  See also next_element_from_c_string.  */
+      if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
+	{
+	  it->what = IT_EOB;
+	  return 0;
+	}
+      else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
+	{
+	  /* Pad with spaces.  */
+	  it->c = ' ', it->len = 1;
+	  CHARPOS (position) = BYTEPOS (position) = -1;
+	}
+      else if (STRING_MULTIBYTE (it->string))
+	{
+	  int maxlen = (STRING_BYTES (XSTRING (it->string))
+			- IT_STRING_BYTEPOS (*it));
+	  unsigned char *s = (XSTRING (it->string)->data
+			      + IT_STRING_BYTEPOS (*it));
+	  it->c = STRING_CHAR_AND_LENGTH (s, maxlen, it->len);
+	}
+      else
+	{
+	  it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
+	  it->len = 1;
+	}
+    }
+
+  /* Record what we have and where it came from.  Note that we store a
+     buffer position in IT->position although it could arguably be a
+     string position.  */
+  it->what = IT_CHARACTER;
+  it->object = it->string;
+  it->position = position;
+  return 1;
+}
+
+
+/* Load IT with next display element from C string IT->s.
+   IT->string_nchars is the maximum number of characters to return
+   from the string.  IT->end_charpos may be greater than
+   IT->string_nchars when this function is called, in which case we
+   may have to return padding spaces.  Value is zero if end of string
+   reached, including padding spaces.  */
+
+static int
+next_element_from_c_string (it)
+     struct it *it;
+{
+  int success_p = 1;
+  
+  xassert (it->s);
+  it->what = IT_CHARACTER;
+  BYTEPOS (it->position) = CHARPOS (it->position) = 0;
+  it->object = Qnil;
+  
+  /* IT's position can be greater IT->string_nchars in case a field
+     width or precision has been specified when the iterator was
+     initialized.  */
+  if (IT_CHARPOS (*it) >= it->end_charpos)
+    {
+      /* End of the game.  */
+      it->what = IT_EOB;
+      success_p = 0;
+    }
+  else if (IT_CHARPOS (*it) >= it->string_nchars)
+    {
+      /* Pad with spaces.  */
+      it->c = ' ', it->len = 1;
+      BYTEPOS (it->position) = CHARPOS (it->position) = -1;
+    }
+  else if (it->multibyte_p)
+    {
+      /* Implementation note: The calls to strlen apparently aren't a
+	 performance problem because there is no noticeable performance
+	 difference between Emacs running in unibyte or multibyte mode.  */
+      int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
+      it->c = STRING_CHAR_AND_LENGTH (it->s + IT_BYTEPOS (*it),
+				      maxlen, it->len);
+    }
+  else
+    it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
+  
+  return success_p;
+}
+
+
+/* Set up IT to return characters from an ellipsis, if appropriate.
+   The definition of the ellipsis glyphs may come from a display table
+   entry.  This function Fills IT with the first glyph from the
+   ellipsis if an ellipsis is to be displayed.  */
+
+static void
+next_element_from_ellipsis (it)
+     struct it *it;
+{
+  if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+    {
+      /* Use the display table definition for `...'.  Invalid glyphs
+	 will be handled by the method returning elements from dpvec.  */
+      struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
+      it->dpvec_char_len = it->len;
+      it->dpvec = v->contents;
+      it->dpend = v->contents + v->size;
+      it->current.dpvec_index = 0;
+      it->method = next_element_from_display_vector;
+      get_next_display_element (it);
+    }
+  else if (it->selective_display_ellipsis_p)
+    {
+      /* Use default `...' which is stored in default_invis_vector.  */
+      it->dpvec_char_len = it->len;
+      it->dpvec = default_invis_vector;
+      it->dpend = default_invis_vector + 3;
+      it->current.dpvec_index = 0;
+      it->method = next_element_from_display_vector;
+      get_next_display_element (it);
+    }
+}
+
+
+/* Deliver an image display element.  The iterator IT is already
+   filled with image information (done in handle_display_prop).  Value
+   is always 1.  */
+  
+
+static int
+next_element_from_image (it)
+     struct it *it;
+{
+  it->what = IT_IMAGE;
+  return 1;
+}
+
+
+/* Fill iterator IT with next display element from a stretch glyph
+   property.  IT->object is the value of the text property.  Value is
+   always 1.  */
+
+static int
+next_element_from_stretch (it)
+     struct it *it;
+{
+  it->what = IT_STRETCH;
+  return 1;
+}
+
+
+/* Load IT with the next display element from current_buffer.  Value
+   is zero if end of buffer reached.  IT->stop_charpos is the next
+   position at which to stop and check for text properties or buffer
+   end.  */
+
+static int
+next_element_from_buffer (it)
+     struct it *it;
+{
+  int success_p = 1;
+
+  /* Check this assumption, otherwise, we would never enter the
+     if-statement, below.  */
+  xassert (IT_CHARPOS (*it) >= BEGV
+	   && IT_CHARPOS (*it) <= it->stop_charpos);
+
+  if (IT_CHARPOS (*it) >= it->stop_charpos)
+    {
+      if (IT_CHARPOS (*it) >= it->end_charpos)
+	{
+	  int overlay_strings_follow_p;
+	  
+	  /* End of the game, except when overlay strings follow that
+	     haven't been returned yet.  */
+	  if (it->overlay_strings_at_end_processed_p)
+	    overlay_strings_follow_p = 0;
+	  else
+	    {
+	      it->overlay_strings_at_end_processed_p = 1;
+	      overlay_strings_follow_p
+		= get_overlay_strings (it);
+	    }
+
+	  if (overlay_strings_follow_p)
+	    success_p = get_next_display_element (it);
+	  else
+	    {
+	      it->what = IT_EOB;
+	      it->position = it->current.pos;
+	      success_p = 0;
+	    }
+	}
+      else
+	{
+	  handle_stop (it);
+	  return get_next_display_element (it);
+	}
+    }
+  else
+    {
+      /* No face changes, overlays etc. in sight, so just return a
+	 character from current_buffer.  */
+      unsigned char *p;
+
+      /* Maybe run the redisplay end trigger hook.  Performance note:
+	 This doesn't seem to cost measurable time.  */
+      if (it->redisplay_end_trigger_charpos
+	  && it->glyph_row
+	  && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
+	run_redisplay_end_trigger_hook (it);
+
+      /* Get the next character, maybe multibyte.  */
+      p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
+      if (it->multibyte_p)
+	{
+	  int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
+			- IT_BYTEPOS (*it));
+	  it->c = STRING_CHAR_AND_LENGTH (p, maxlen, it->len);
+	}
+      else
+	it->c = *p, it->len = 1;
+
+      /* Record what we have and where it came from.  */
+      it->what = IT_CHARACTER;;
+      it->object = it->w->buffer;
+      it->position = it->current.pos;
+
+      /* Normally we return the character found above, except when we
+	 really want to return an ellipsis for selective display.  */
+      if (it->selective)
+	{
+	  if (it->c == '\n')
+	    {
+	      /* A value of selective > 0 means hide lines indented more
+		 than that number of columns.  */
+	      if (it->selective > 0
+		  && IT_CHARPOS (*it) + 1 < ZV
+		  && indented_beyond_p (IT_CHARPOS (*it) + 1,
+					IT_BYTEPOS (*it) + 1,
+					it->selective))
+		next_element_from_ellipsis (it);
+	    }
+	  else if (it->c == '\r' && it->selective == -1)
+	    {
+	      /* A value of selective == -1 means that everything from the
+		 CR to the end of the line is invisible, with maybe an
+		 ellipsis displayed for it.  */
+	      next_element_from_ellipsis (it);
+	    }
+	}
+    }
+
+  /* Value is zero if end of buffer reached.  */
+  xassert (!success_p || it->len > 0);
+  return success_p;
+}
+
+     
+/* Run the redisplay end trigger hook for IT.  */
+
+static void
+run_redisplay_end_trigger_hook (it)
+     struct it *it;
+{
+  Lisp_Object args[3];
+
+  /* IT->glyph_row should be non-null, i.e. we should be actually
+     displaying something, or otherwise we should not run the hook.  */
+  xassert (it->glyph_row);
+
+  /* Set up hook arguments.  */
+  args[0] = Qredisplay_end_trigger_functions;
+  args[1] = it->window;
+  XSETINT (args[2], it->redisplay_end_trigger_charpos);
+  it->redisplay_end_trigger_charpos = 0;
+
+  /* Since we are *trying* to run these functions, don't try to run
+     them again, even if they get an error.  */
+  it->w->redisplay_end_trigger = Qnil;
+  Frun_hook_with_args (3, args);
+  
+  /* Notice if it changed the face of the character we are on.  */
+  handle_face_prop (it);
+}
+
+
+
+/***********************************************************************
+	     Moving an iterator without producing glyphs
+ ***********************************************************************/
+
+/* Move iterator IT to a specified buffer or X position within one
+   line on the display without producing glyphs.
+
+   Begin to skip at IT's current position.  Skip to TO_CHARPOS or TO_X
+   whichever is reached first.
+
+   TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
+
+   TO_X < 0 means that no TO_X is specified.  TO_X is normally a value
+   0 <= TO_X <= IT->last_visible_x.  This means in particular, that
+   TO_X includes the amount by which a window is horizontally
+   scrolled.
+
+   Value is
+
+   MOVE_POS_MATCH_OR_ZV
+     - when TO_POS or ZV was reached.
+	
+   MOVE_X_REACHED
+     -when TO_X was reached before TO_POS or ZV were reached.
+	
+   MOVE_LINE_CONTINUED
+     - when we reached the end of the display area and the line must
+     be continued.
+			   
+   MOVE_LINE_TRUNCATED
+     - when we reached the end of the display area and the line is
+     truncated.
+
+   MOVE_NEWLINE_OR_CR
+     - when we stopped at a line end, i.e. a newline or a CR and selective
+     display is on.  */
+
+enum move_it_result
+move_it_in_display_line_to (it, to_charpos, to_x, op)
+     struct it *it;
+     int to_charpos, to_x, op;
+{
+  enum move_it_result result = MOVE_UNDEFINED;
+  struct glyph_row *saved_glyph_row;
+
+  /* Don't produce glyphs in produce_glyphs.  */
+  saved_glyph_row = it->glyph_row;
+  it->glyph_row = NULL;
+
+#if NO_PROMPT_IN_BUFFER
+  /* Take a mini-buffer prompt into account.  */
+  if (MINI_WINDOW_P (it->w)
+      && IT_CHARPOS (*it) == BEGV)
+    {
+      it->current_x = minibuf_prompt_pixel_width;
+      it->hpos = minibuf_prompt_width;
+    }
+#endif
+
+  while (1)
+    {
+      int x, i;
+      
+      /* Stop when ZV or TO_CHARPOS reached.  */
+      if (!get_next_display_element (it)
+	  || ((op & MOVE_TO_POS) != 0
+	      && BUFFERP (it->object)
+	      && IT_CHARPOS (*it) >= to_charpos))
+	{
+	  result = MOVE_POS_MATCH_OR_ZV;
+	  break;
+	}
+	  
+      /* The call to produce_glyphs will get the metrics of the
+	 display element IT is loaded with.  We record in x the
+	 x-position before this display element in case it does not
+	 fit on the line.  */
+      x = it->current_x;
+      PRODUCE_GLYPHS (it);
+
+      if (it->area != TEXT_AREA)
+	{
+	  set_iterator_to_next (it);
+	  continue;
+	}
+
+      /* The number of glyphs we get back in IT->nglyphs will normally
+	 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
+	 character on a terminal frame, or (iii) a line end.  For the
+	 second case, IT->nglyphs - 1 padding glyphs will be present
+	 (on X frames, there is only one glyph produced for a
+	 composite character.
+
+	 The behavior implemented below means, for continuation lines,
+	 that as many spaces of a TAB as fit on the current line are
+	 displayed there.  For terminal frames, as many glyphs of a
+	 multi-glyph character are displayed in the current line, too.
+	 This is what the old redisplay code did, and we keep it that
+	 way.  Under X, the whole shape of a complex character must
+	 fit on the line or it will be completely displayed in the
+	 next line.
+
+	 Note that both for tabs and padding glyphs, all glyphs have
+	 the same width.   */
+      if (it->nglyphs)
+	{
+	  /* More than one glyph or glyph doesn't fit on line.  All
+	     glyphs have the same width.  */
+	  int single_glyph_width = it->pixel_width / it->nglyphs;
+	  int new_x;
+	  
+	  for (i = 0; i < it->nglyphs; ++i, x = new_x)
+	    {
+	      new_x = x + single_glyph_width;
+
+	      /* We want to leave anything reaching TO_X to the caller.  */
+	      if ((op & MOVE_TO_X) && new_x > to_x)
+		{
+		  it->current_x = x;
+		  result = MOVE_X_REACHED;
+		  break;
+		}
+	      else if (/* Lines are continued.  */
+		       !it->truncate_lines_p
+		       && (/* And glyph doesn't fit on the line.  */
+			   new_x > it->last_visible_x
+			   /* Or it fits exactly and we're on a window
+			      system frame.  */
+			   || (new_x == it->last_visible_x
+			       && FRAME_WINDOW_P (it->f))))
+		{
+		  if (/* IT->hpos == 0 means the very first glyph
+			 doesn't fit on the line, e.g. a wide image.  */
+		      it->hpos == 0
+		      || (new_x == it->last_visible_x
+			  && FRAME_WINDOW_P (it->f)))
+		    {
+		      ++it->hpos;
+		      it->current_x = new_x;
+		      if (i == it->nglyphs - 1)
+			set_iterator_to_next (it);
+		    }
+		  else
+		    it->current_x = x;
+
+		  result = MOVE_LINE_CONTINUED;
+		  break;
+		}
+	      else if (new_x > it->first_visible_x)
+		{
+		  /* Glyph is visible.  Increment number of glyphs that
+		     would be displayed.  */
+		  ++it->hpos;
+		}
+	      else
+		{
+		  /* Glyph is completely off the left margin of the display 
+		     area.  Nothing to do.  */
+		}
+	    }
+
+	  if (result != MOVE_UNDEFINED)
+	    break;
+	}
+      else if ((op & MOVE_TO_X) && it->current_x >= to_x)
+	{
+	  /* Stop when TO_X specified and reached.  This check is
+	     necessary here because of lines consisting of a line end,
+	     only.  The line end will not produce any glyphs and we
+	     would never get MOVE_X_REACHED.  */
+	  xassert (it->nglyphs == 0);
+	  result = MOVE_X_REACHED;
+	  break;
+	}
+  
+      /* Is this a line end?  If yes, we're done.  */
+      if (ITERATOR_AT_END_OF_LINE_P (it))
+	{
+	  result = MOVE_NEWLINE_OR_CR;
+	  break;
+	}
+      
+      /* The current display element has been consumed.  Advance
+	 to the next.  */
+      set_iterator_to_next (it);
+      
+      /* Stop if lines are truncated and IT's current x-position is
+	 past the right edge of the window now.  */
+      if (it->truncate_lines_p
+	  && it->current_x >= it->last_visible_x)
+	{
+	  result = MOVE_LINE_TRUNCATED;
+	  break;
+	}
+    }
+
+  /* Restore the iterator settings altered at the beginning of this
+     function.  */
+  it->glyph_row = saved_glyph_row;
+  return result;
+}
+
+
+/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
+   TO_Y, TO_VPOS.  OP is a bit-mask that specifies where to stop.  See
+   the description of enum move_operation_enum.
+   
+   If TO_CHARPOS is in invisible text, e.g. a truncated part of a
+   screen line, this function will set IT to the next position >
+   TO_CHARPOS.  */
+
+void
+move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
+     struct it *it;
+     int to_charpos, to_x, to_y, to_vpos;
+     int op;
+{
+  enum move_it_result skip, skip2 = MOVE_X_REACHED;
+  int line_height;
+
+  xassert (XBUFFER (it->w->buffer) == current_buffer);
+
+  while (1)
+    {
+      if (op & MOVE_TO_VPOS)
+	{
+	  /* If no TO_CHARPOS and no TO_X specified, stop at the
+	     start of the line TO_VPOS.  */
+	  if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
+	    {
+	      if (it->vpos == to_vpos)
+		break;
+	      skip = move_it_in_display_line_to (it, -1, -1, 0);
+	    }
+	  else
+	    {
+	      /* TO_VPOS >= 0 means stop at TO_X in the line at
+		 TO_VPOS, or at TO_POS, whichever comes first.  */
+	      skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
+
+	      if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
+		break;
+	      else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
+		{
+		  /* We have reached TO_X but not in the line we want.  */
+		  skip = move_it_in_display_line_to (it, to_charpos,
+						     -1, MOVE_TO_POS);
+		  if (skip == MOVE_POS_MATCH_OR_ZV)
+		    break;
+		}
+	    }
+	}
+      else if (op & MOVE_TO_Y)
+	{
+	  struct it it_backup;
+	  int done_p;
+	  
+	  /* TO_Y specified means stop at TO_X in the line containing
+	     TO_Y---or at TO_CHARPOS if this is reached first.  The
+	     problem is that we can't really tell whether the line
+	     contains TO_Y before we have completely scanned it, and
+	     this may skip past TO_X.  What we do is to first scan to
+	     TO_X.
+
+	     If TO_X is not specified, use a TO_X of zero.  The reason
+	     is to make the outcome of this function more predictable.
+	     If we didn't use TO_X == 0, we would stop at the end of
+	     the line which is probably not what a caller would expect
+	     to happen.  */
+	  skip = move_it_in_display_line_to (it, to_charpos,
+					     ((op & MOVE_TO_X)
+					      ? to_x : 0),
+					     (MOVE_TO_X
+					      | (op & MOVE_TO_POS)));
+
+	  /* If TO_CHARPOS is reached or ZV, we don't have to do more.  */
+	  if (skip == MOVE_POS_MATCH_OR_ZV)
+	    break;
+	  
+	  /* If TO_X was reached, we would like to know whether TO_Y
+	     is in the line.  This can only be said if we know the
+	     total line height which requires us to scan the rest of
+	     the line.  */
+	  done_p = 0;
+	  if (skip == MOVE_X_REACHED)
+	    {
+	      it_backup = *it;
+	      skip2 = move_it_in_display_line_to (it, to_charpos, -1,
+						  op & MOVE_TO_POS);
+	    }
+
+	  /* Now, decide whether TO_Y is in this line.  */
+	  line_height = it->max_ascent + it->max_descent;
+	  
+	  if (to_y >= it->current_y
+	      && to_y < it->current_y + line_height)
+	    {
+	      if (skip == MOVE_X_REACHED)
+		/* If TO_Y is in this line and TO_X was reached above,
+		   we scanned too far.  We have to restore IT's settings
+		   to the ones before skipping.  */
+		*it = it_backup;
+	      done_p = 1;
+	    }
+	  else if (skip == MOVE_X_REACHED)
+	    {
+	      skip = skip2;
+	      if (skip == MOVE_POS_MATCH_OR_ZV)
+		done_p = 1;
+	    }
+
+	  if (done_p)
+	    break;
+	}
+      else
+	skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
+
+      switch (skip)
+	{
+	case MOVE_POS_MATCH_OR_ZV:
+	  return;
+
+	case MOVE_NEWLINE_OR_CR:
+	  set_iterator_to_next (it);
+	  it->continuation_lines_width = 0;
+	  break;
+
+	case MOVE_LINE_TRUNCATED:
+	  it->continuation_lines_width = 0;
+	  reseat_at_next_visible_line_start (it);
+	  if ((op & MOVE_TO_POS) != 0
+	      && IT_CHARPOS (*it) > to_charpos)
+	    goto out;
+	  break;
+
+	case MOVE_LINE_CONTINUED:
+	  it->continuation_lines_width += it->current_x;
+	  break;
+
+	default:
+	  abort ();
+	}
+
+      /* Reset/increment for the next run.  */
+      recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
+      it->current_x = it->hpos = 0;
+      it->current_y += it->max_ascent + it->max_descent;
+      ++it->vpos;
+      last_height = it->max_ascent + it->max_descent;
+      last_max_ascent = it->max_ascent;
+      it->max_ascent = it->max_descent = 0;
+    }
+ out:;
+}
+
+
+/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
+
+   If DY > 0, move IT backward at least that many pixels.  DY = 0
+   means move IT backward to the preceding line start or BEGV.  This
+   function may move over more than DY pixels if IT->current_y - DY
+   ends up in the middle of a line; in this case IT->current_y will be
+   set to the top of the line moved to.  */
+
+void
+move_it_vertically_backward (it, dy)
+     struct it *it;
+     int dy;
+{
+  int nlines, h, line_height;
+  struct it it2;
+  int start_pos = IT_CHARPOS (*it);
+  
+  xassert (dy >= 0);
+
+  /* Estimate how many newlines we must move back.  */
+  nlines = max (1, dy / CANON_Y_UNIT (it->f));
+
+  /* Set the iterator's position that many lines back.  */
+  while (nlines-- && IT_CHARPOS (*it) > BEGV)
+    back_to_previous_visible_line_start (it);
+
+  /* Reseat the iterator here.  When moving backward, we don't want
+     reseat to skip forward over invisible text, set up the iterator
+     to deliver from overlay strings at the new position etc.  So,
+     use reseat_1 here.  */
+  reseat_1 (it, it->current.pos, 1);
+
+  /* We are now surely at a line start.  */
+  it->current_x = it->hpos = 0;
+
+  /* Move forward and see what y-distance we moved.  First move to the
+     start of the next line so that we get its height.  We need this
+     height to be able to tell whether we reached the specified
+     y-distance.  */
+  it2 = *it;
+  it2.max_ascent = it2.max_descent = 0;
+  move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
+	      MOVE_TO_POS | MOVE_TO_VPOS);
+  xassert (IT_CHARPOS (*it) >= BEGV);
+  line_height = it2.max_ascent + it2.max_descent;
+  move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
+  xassert (IT_CHARPOS (*it) >= BEGV);
+  h = it2.current_y - it->current_y;
+  nlines = it2.vpos - it->vpos;
+
+  /* Correct IT's y and vpos position.  */
+  it->vpos -= nlines;
+  it->current_y -= h;
+  
+  if (dy == 0)
+    {
+      /* DY == 0 means move to the start of the screen line.  The
+	 value of nlines is > 0 if continuation lines were involved.  */
+      if (nlines > 0)
+	move_it_by_lines (it, nlines, 1);
+      xassert (IT_CHARPOS (*it) <= start_pos);
+    }
+  else if (nlines)
+    {
+      /* The y-position we try to reach.  Note that h has been
+         subtracted in front of the if-statement.  */
+      int target_y = it->current_y + h - dy;
+
+      /* If we did not reach target_y, try to move further backward if
+	 we can.  If we moved too far backward, try to move forward.  */
+      if (target_y < it->current_y
+	  && IT_CHARPOS (*it) > BEGV)
+	{
+	  move_it_vertically (it, target_y - it->current_y);
+	  xassert (IT_CHARPOS (*it) >= BEGV);
+	}
+      else if (target_y >= it->current_y + line_height
+	       && IT_CHARPOS (*it) < ZV)
+	{
+	  move_it_vertically (it, target_y - (it->current_y + line_height));
+	  xassert (IT_CHARPOS (*it) >= BEGV);
+	}
+    }
+}
+
+
+/* Move IT by a specified amount of pixel lines DY.  DY negative means
+   move backwards.  DY = 0 means move to start of screen line.  At the
+   end, IT will be on the start of a screen line.  */
+
+void 
+move_it_vertically (it, dy)
+    struct it *it;
+    int dy;
+{
+  if (dy <= 0)
+    move_it_vertically_backward (it, -dy);
+  else if (dy > 0)
+    {
+      move_it_to (it, ZV, -1, it->current_y + dy, -1,
+		  MOVE_TO_POS | MOVE_TO_Y);
+
+      /* If buffer ends in ZV without a newline, move to the start of
+	 the line to satisfy the post-condition.  */
+      if (IT_CHARPOS (*it) == ZV
+	  && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
+	move_it_by_lines (it, 0, 0);
+    }
+}
+
+
+/* Return non-zero if some text between buffer positions START_CHARPOS
+   and END_CHARPOS is invisible.  IT->window is the window for text
+   property lookup.  */
+
+static int
+invisible_text_between_p (it, start_charpos, end_charpos)
+     struct it *it;
+     int start_charpos, end_charpos;
+{
+#ifdef USE_TEXT_PROPERTIES
+  Lisp_Object prop, limit;
+  int invisible_found_p;
+  
+  xassert (it != NULL && start_charpos <= end_charpos);
+
+  /* Is text at START invisible?  */
+  prop = Fget_char_property (make_number (start_charpos), Qinvisible,
+			     it->window);
+  if (TEXT_PROP_MEANS_INVISIBLE (prop))
+    invisible_found_p = 1;
+  else
+    {
+      limit = Fnext_single_property_change (make_number (start_charpos),
+					    Qinvisible,
+					    Fcurrent_buffer (),
+					    make_number (end_charpos));
+      invisible_found_p = XFASTINT (limit) < end_charpos;
+    }
+
+  return invisible_found_p;
+  
+#else /* not USE_TEXT_PROPERTIES */
+  return 0;
+#endif /* not USE_TEXT_PROPERTIES */
+}
+
+
+/* Move IT by a specified number DVPOS of screen lines down.  DVPOS
+   negative means move up.  DVPOS == 0 means move to the start of the
+   screen line.  NEED_Y_P non-zero means calculate IT->current_y.  If
+   NEED_Y_P is zero, IT->current_y will be left unchanged.
+
+   Further optimization ideas: If we would know that IT->f doesn't use
+   a face with proportional font, we could be faster for
+   truncate-lines nil.  */
+
+void
+move_it_by_lines (it, dvpos, need_y_p)
+     struct it *it;
+     int dvpos, need_y_p;
+{
+  struct position pos;
+  
+  if (!FRAME_WINDOW_P (it->f))
+    {
+      struct text_pos textpos;
+      
+      /* We can use vmotion on frames without proportional fonts.  */
+      pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
+      SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
+      reseat (it, textpos, 1);
+      it->vpos += pos.vpos;
+      it->current_y += pos.vpos;
+    }
+  else if (dvpos == 0)
+    {
+      /* DVPOS == 0 means move to the start of the screen line.  */
+      move_it_vertically_backward (it, 0);
+      xassert (it->current_x == 0 && it->hpos == 0);
+    }
+  else if (dvpos > 0)
+    {
+      /* If there are no continuation lines, and if there is no
+	 selective display, try the simple method of moving forward
+	 DVPOS newlines, then see where we are.  */
+      if (!need_y_p && it->truncate_lines_p && it->selective == 0)
+	{
+	  int shortage = 0, charpos;
+
+	  if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
+	    charpos = IT_CHARPOS (*it) + 1;
+	  else
+	    charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
+				   &shortage, 0);
+	  
+	  if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
+	    {
+	      struct text_pos pos;
+	      CHARPOS (pos) = charpos;
+	      BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
+	      reseat (it, pos, 1);
+	      it->vpos += dvpos - shortage;
+	      it->hpos = it->current_x = 0;
+	      return;
+	    }
+	}
+
+      move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
+    }
+  else
+    {
+      struct it it2;
+      int start_charpos, i;
+
+      /* If there are no continuation lines, and if there is no
+	 selective display, try the simple method of moving backward
+	 -DVPOS newlines.  */
+      if (!need_y_p && it->truncate_lines_p && it->selective == 0)
+	{
+	  int shortage;
+	  int charpos = IT_CHARPOS (*it);
+	  int bytepos = IT_BYTEPOS (*it);
+
+	  /* If in the middle of a line, go to its start.  */
+	  if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
+	    {
+	      charpos = find_next_newline_no_quit (charpos, -1);
+	      bytepos = CHAR_TO_BYTE (charpos);
+	    }
+
+	  if (charpos == BEGV)
+	    {
+	      struct text_pos pos;
+	      CHARPOS (pos) = charpos;
+	      BYTEPOS (pos) = bytepos;
+	      reseat (it, pos, 1);
+	      it->hpos = it->current_x = 0;
+	      return;
+	    }
+	  else
+	    {
+	      charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
+	      if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
+		{
+		  struct text_pos pos;
+		  CHARPOS (pos) = charpos;
+		  BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
+		  reseat (it, pos, 1);
+		  it->vpos += dvpos + (shortage ? shortage - 1 : 0);
+		  it->hpos = it->current_x = 0;
+		  return;
+		}
+	    }
+	}
+
+      /* Go back -DVPOS visible lines and reseat the iterator there.  */
+      start_charpos = IT_CHARPOS (*it);
+      for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
+	back_to_previous_visible_line_start (it);
+      reseat (it, it->current.pos, 1);
+      it->current_x = it->hpos = 0;
+
+      /* Above call may have moved too far if continuation lines
+	 are involved.  Scan forward and see if it did.  */
+      it2 = *it;
+      it2.vpos = it2.current_y = 0;
+      move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
+      it->vpos -= it2.vpos;
+      it->current_y -= it2.current_y;
+      it->current_x = it->hpos = 0;
+
+      /* If we moved too far, move IT some lines forward.  */
+      if (it2.vpos > -dvpos)
+	{
+	  int delta = it2.vpos + dvpos;
+	  move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
+	}
+    }
+}
+
+
+
+/***********************************************************************
+			       Messages
+ ***********************************************************************/
+
+
 /* Output a newline in the *Messages* buffer if "needs" one.  */
 
 void
@@ -286,10 +4550,11 @@
 }
 
 
-/* Add a string to the message log, optionally terminated with a newline.
-   This function calls low-level routines in order to bypass text property
-   hooks, etc. which might not be safe to run.
-   MULTIBYTE, if nonzero, means interpret the contents of M as multibyte.  */
+/* Add a string M of length LEN to the message log, optionally
+   terminated with a newline when NLFLAG is non-zero.  MULTIBYTE, if
+   nonzero, means interpret the contents of M as multibyte.  This
+   function calls low-level routines in order to bypass text property
+   hooks, etc. which might not be safe to run.  */
 
 void
 message_dolog (m, len, nlflag, multibyte)
@@ -334,6 +4599,7 @@
 	{
 	  int i, c, nbytes;
 	  unsigned char work[1];
+	  
 	  /* Convert a multibyte string to single-byte
 	     for the *Message* buffer.  */
 	  for (i = 0; i < len; i += nbytes)
@@ -442,6 +4708,7 @@
     }
 }
 
+
 /* We are at the end of the buffer after just having inserted a newline.
    (Note: We depend on the fact we won't be crossing the gap.)
    Check to see if the most recent message looks a lot like the previous one.
@@ -480,16 +4747,16 @@
     }
   return 0;
 }
-
-/* Display an echo area message M with a specified length of LEN chars.
-   The string may include null characters.  If M is 0, clear out any
-   existing message, and let the minibuffer text show through.
-
-   The buffer M must continue to exist until after the echo area
-   gets cleared or some other message gets displayed there.
-
-   Do not pass text that is stored in a Lisp string.
-   Do not pass text in a buffer that was alloca'd.  */
+
+
+/* Display an echo area message M with a specified length of LEN
+   chars.  The string may include null characters.  If M is 0, clear
+   out any existing message, and let the mini-buffer text show through.
+
+   The buffer M must continue to exist until after the echo area gets
+   cleared or some other message gets displayed there.  This means do
+   not pass text that is stored in a Lisp string; do not pass text in
+   a buffer that was alloca'd.  */
 
 void
 message2 (m, len, multibyte)
@@ -528,12 +4795,14 @@
   /* A null message buffer means that the frame hasn't really been
      initialized yet.  Error messages get reported properly by
      cmd_error, so this must be just an informative message; toss it.  */
-  else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
+  else if (INTERACTIVE 
+	   && selected_frame->glyphs_initialized_p
+	   && FRAME_MESSAGE_BUF (selected_frame))
     {
       Lisp_Object mini_window;
-      FRAME_PTR f;
-
-      /* Get the frame containing the minibuffer
+      struct frame *f;
+
+      /* Get the frame containing the mini-buffer
 	 that the selected frame is using.  */
       mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
       f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
@@ -547,31 +4816,122 @@
 	{
 	  echo_area_glyphs = m;
 	  echo_area_glyphs_length = len;
+	  echo_area_message = Qnil;
 
 	  if (minibuffer_auto_raise)
 	    Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
 	}
       else
-	echo_area_glyphs = previous_echo_glyphs = 0;
+	{
+	  echo_area_glyphs = previous_echo_glyphs = NULL;
+	  echo_area_message = previous_echo_area_message = Qnil;
+	}
 
       do_pending_window_change ();
-      echo_area_display ();
-      update_frame (f, 1, 1);
+      echo_area_display (1);
       do_pending_window_change ();
       if (frame_up_to_date_hook != 0 && ! gc_in_progress)
 	(*frame_up_to_date_hook) (f);
     }
 }
-
-/* Display in echo area the null-terminated ASCII-only string M.
-   If M is 0, clear out any existing message,
-   and let the minibuffer text show through.
-
-   The string M must continue to exist until after the echo area
-   gets cleared or some other message gets displayed there.
-
-   Do not pass text that is stored in a Lisp string.
-   Do not pass text in a buffer that was alloca'd.  */
+
+
+/* Display an echo area message M with a specified length of LEN
+   chars.  The string may include null characters.  If M is not a
+   string, clear out any existing message, and let the mini-buffer
+   text show through.  */
+
+void
+message3 (m, len, multibyte)
+     Lisp_Object m;
+     int len;
+     int multibyte;
+{
+  struct gcpro gcpro1;
+
+  GCPRO1 (m);
+  
+  /* First flush out any partial line written with print.  */
+  message_log_maybe_newline ();
+  if (STRINGP (m))
+    message_dolog (XSTRING (m)->data, len, 1, multibyte);
+  message3_nolog (m, len, multibyte);
+
+  UNGCPRO;
+}
+
+
+/* The non-logging version of message3.  */
+
+void
+message3_nolog (m, len, multibyte)
+     Lisp_Object m;
+     int len, multibyte;
+{
+  message_enable_multibyte = multibyte;
+
+  if (noninteractive)
+    {
+      if (noninteractive_need_newline)
+	putc ('\n', stderr);
+      noninteractive_need_newline = 0;
+      if (STRINGP (m))
+	fwrite (XSTRING (m)->data, len, 1, stderr);
+      if (cursor_in_echo_area == 0)
+	fprintf (stderr, "\n");
+      fflush (stderr);
+    }
+  /* A null message buffer means that the frame hasn't really been
+     initialized yet.  Error messages get reported properly by
+     cmd_error, so this must be just an informative message; toss it.  */
+  else if (INTERACTIVE 
+	   && selected_frame->glyphs_initialized_p
+	   && FRAME_MESSAGE_BUF (selected_frame))
+    {
+      Lisp_Object mini_window;
+      struct frame *f;
+
+      /* Get the frame containing the mini-buffer
+	 that the selected frame is using.  */
+      mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+      f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
+
+      FRAME_SAMPLE_VISIBILITY (f);
+      if (FRAME_VISIBLE_P (selected_frame)
+	  && ! FRAME_VISIBLE_P (f))
+	Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
+
+      if (STRINGP (m))
+	{
+	  echo_area_glyphs = NULL;
+	  echo_area_message = m;
+	  echo_area_glyphs_length = len;
+
+	  if (minibuffer_auto_raise)
+	    Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
+	}
+      else
+	{
+	  echo_area_glyphs = previous_echo_glyphs = NULL;
+	  echo_area_message = previous_echo_area_message = Qnil;
+	}
+
+      do_pending_window_change ();
+      echo_area_display (1);
+      do_pending_window_change ();
+      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
+	(*frame_up_to_date_hook) (f);
+    }
+}
+
+
+/* Display a null-terminated echo area message M.  If M is 0, clear
+   out any existing message, and let the mini-buffer text show through.
+
+   The buffer M must continue to exist until after the echo area gets
+   cleared or some other message gets displayed there.  Do not pass
+   text that is stored in a Lisp string.  Do not pass text in a buffer
+   that was alloca'd.  */
 
 void
 message1 (m)
@@ -580,6 +4940,9 @@
   message2 (m, (m ? strlen (m) : 0), 0);
 }
 
+
+/* The non-logging counterpart of message1.  */
+
 void
 message1_nolog (m)
      char *m;
@@ -648,6 +5011,7 @@
     }
 }
 
+
 /* Truncate what will be displayed in the echo area
    the next time we display it--but don't redisplay it now.  */
 
@@ -662,12 +5026,15 @@
     echo_area_glyphs_length = len;
 }
 
-/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
-   zero if being used by message.  */
+
+/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by
+   print; zero if being used by message.  */
+
 int message_buf_print;
 
+
 /* Dump an informative message to the minibuf.  If M is 0, clear out
-   any existing message, and let the minibuffer text show through.  */
+   any existing message, and let the mini-buffer text show through.  */
 
 /* VARARGS 1 */
 void
@@ -690,20 +5057,21 @@
     }
   else if (INTERACTIVE)
     {
-      /* The frame whose minibuffer we're going to display the message on.
-	 It may be larger than the selected frame, so we need
-	 to use its buffer, not the selected frame's buffer.  */
+      /* The frame whose mini-buffer we're going to display the message
+	 on.  It may be larger than the selected frame, so we need to
+	 use its buffer, not the selected frame's buffer.  */
       Lisp_Object mini_window;
-      FRAME_PTR f;
-
-      /* Get the frame containing the minibuffer
+      struct frame *f;
+
+      /* Get the frame containing the mini-buffer
 	 that the selected frame is using.  */
       mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
       f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
 
       /* A null message buffer means that the frame hasn't really been
 	 initialized yet.  Error messages get reported properly by
-	 cmd_error, so this must be just an informative message; toss it.  */
+	 cmd_error, so this must be just an informative message; toss
+	 it.  */
       if (FRAME_MESSAGE_BUF (f))
 	{
 	  if (m)
@@ -735,7 +5103,9 @@
     }
 }
 
+
 /* The non-logging version of message.  */
+
 void
 message_nolog (m, a1, a2, a3)
      char *m;
@@ -748,204 +5118,341 @@
   Vmessage_log_max = old_log_max;
 }
 
+
+/* Display echo_area_message or echo_area_glyphs in the current
+   mini-buffer.  */
+
 void
 update_echo_area ()
 {
-  message2 (echo_area_glyphs, echo_area_glyphs_length,
-	    ! NILP (current_buffer->enable_multibyte_characters));
-}
-
+  if (STRINGP (echo_area_message))
+    message3 (echo_area_message, echo_area_glyphs_length,
+	      !NILP (current_buffer->enable_multibyte_characters));
+  else
+    message2 (echo_area_glyphs, echo_area_glyphs_length,
+	      !NILP (current_buffer->enable_multibyte_characters));
+}
+
+
+/* Redisplay the echo area of selected_frame.  If UPDATE_FRAME_P is
+   non-zero update selected_frame.  */
+
 static void
-echo_area_display ()
-{
-  register int vpos;
-  FRAME_PTR f;
+echo_area_display (update_frame_p)
+     int update_frame_p;
+{
   Lisp_Object mini_window;
-
-  /* Choose the minibuffer window for this display.
-     It is the minibuffer window used by the selected frame.  */
+  struct window *w;
+  struct frame *f;
+
   mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
-  /* This is the frame that window is in.  */
-  f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
-  if (! FRAME_VISIBLE_P (f))
+  w = XWINDOW (mini_window);
+  f = XFRAME (WINDOW_FRAME (w));
+
+  /* Don't display if frame is invisible or not yet initialized.  */
+  if (!FRAME_VISIBLE_P (f) 
+      || !f->glyphs_initialized_p)
     return;
 
+  /* When Emacs starts, selected_frame may be a visible terminal
+     frame, even if we run under a window system.  If we let this
+     through, a message would be displayed on the terminal.  */
+#ifdef HAVE_WINDOW_SYSTEM
+  if (!inhibit_window_system && !FRAME_WINDOW_P (selected_frame))
+    return;
+#endif /* HAVE_WINDOW_SYSTEM */
+
+  /* Redraw garbaged frames.  */
   if (frame_garbaged)
     {
-      redraw_garbaged_frames ();
+      /* Old redisplay called redraw_garbaged_frames here which in
+	 turn called redraw_frame which in turn called clear_frame.
+	 The call to clear_frame is a source of flickering.  After
+	 checking the places where SET_FRAME_GARBAGED is called, I
+	 believe a clear_frame is not necessary.  It should suffice in
+	 the new redisplay to invalidate all current matrices, and
+	 ensure a complete redisplay of all windows.  */
+      Lisp_Object tail, frame;
+      
+      FOR_EACH_FRAME (tail, frame)
+	{
+	  struct frame *f = XFRAME (frame);
+	  
+	  if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
+	    {
+	      clear_current_matrices (f);
+	      f->garbaged = 0;
+	    }
+	}
+
       frame_garbaged = 0;
-    }
-
-  if (echo_area_glyphs || minibuf_level == 0)
-    {
-      int i;
+      ++windows_or_buffers_changed;
+    }
+
+  if (echo_area_glyphs
+      || STRINGP (echo_area_message)
+      || minibuf_level == 0)
+    {
+      struct it it;
 
       echo_area_window = mini_window;
-
-      vpos = XFASTINT (XWINDOW (mini_window)->top);
-      get_display_line (f, vpos, 0);
-
-      /* Make sure the columns that overlap a left-hand scroll bar
-	 are always clear.  */
-      for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++)
-	f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH;
-
-      display_string (XWINDOW (mini_window), vpos,
-		      echo_area_glyphs ? echo_area_glyphs : "",
-		      echo_area_glyphs ? echo_area_glyphs_length : -1,
-		      FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-		      0, 0, 0,
-		      FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-		      message_enable_multibyte);
-
-#if 0 /* This just gets in the way.  update_frame does the job.  */
-      /* If desired cursor location is on this line, put it at end of text */
-      if (cursor_in_echo_area)
-	FRAME_CURSOR_Y (f) = vpos;
-      if (FRAME_CURSOR_Y (f) == vpos)
-	FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
-#endif
-
-      /* Fill the rest of the minibuffer window with blank lines.  */
-      {
-	int i;
-
-	for (i = vpos + 1;
-	     i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
-	  {
-	    get_display_line (f, i, 0);
-	    /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting
-	       hpos, because it is good to clear whatever is behind the
-	       scroll bar.  This does not affect the scroll bar itself.  */
-	    display_string (XWINDOW (mini_window), i,
-			    "", 0, 
-                            0, 0, 0,
-                            0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f),
-			    0);
-	  }
-      }
+      clear_glyph_matrix (w->desired_matrix);
+      init_iterator (&it, w, -1, -1, w->desired_matrix->rows, DEFAULT_FACE_ID);
+      
+      if (STRINGP (echo_area_message)
+	  && echo_area_glyphs_length)
+	{
+	  prepare_desired_row (it.glyph_row);
+	  display_string (NULL, echo_area_message, Qnil, 0, 0,
+			  &it, -1, echo_area_glyphs_length, 0,
+			  message_enable_multibyte);
+	  it.glyph_row->truncated_on_right_p = 0;
+	  compute_line_metrics (&it);
+	}
+      else if (echo_area_glyphs
+	       && echo_area_glyphs_length)
+	{
+	  prepare_desired_row (it.glyph_row);
+	  display_string (echo_area_glyphs, Qnil, Qnil, 0, 0, &it,
+			  -1, echo_area_glyphs_length, 0,
+			  message_enable_multibyte);
+	  it.glyph_row->truncated_on_right_p = 0;
+	  compute_line_metrics (&it);
+	}
+      else
+	blank_row (w, it.glyph_row, 0);
+      
+      it.glyph_row->y = it.current_y;
+      it.current_y += it.glyph_row->height;
+
+      /* Clear the rest of the lines.  */
+      while (it.current_y < it.last_visible_y)
+	{
+	  ++it.glyph_row;
+	  blank_row (w, it.glyph_row, it.current_y);
+	  it.current_y += it.glyph_row->height;
+	}
+
+      w->must_be_updated_p = 1;
+      if (update_frame_p)
+	{
+	  /* Calling update_single_window is faster when we can use
+	     window-based redisplay.  */
+	  if (FRAME_WINDOW_P (f))
+	    {
+	      update_single_window (w, 1);
+	      rif->flush_display (f);
+	    }
+	  else
+	    update_frame (f, 1, 1);
+	}
     }
   else if (!EQ (mini_window, selected_window))
     windows_or_buffers_changed++;
 
+  /* Prevent redisplay optimization in redisplay_internal by resetting
+     this_line_start_pos.  This is done because the mini-buffer now
+     displays the message instead of its buffer text.  */
   if (EQ (mini_window, selected_window))
-    this_line_bufpos = 0;
-
+    CHARPOS (this_line_start_pos) = 0;
+  
   previous_echo_glyphs = echo_area_glyphs;
-}
+  previous_echo_area_message = echo_area_message;
+  previous_echo_glyphs_length = echo_area_glyphs_length;
+}
+
+
 
-/* Update frame titles.  */
+/***********************************************************************
+			     Frame Titles
+ ***********************************************************************/
+
 
 #ifdef HAVE_WINDOW_SYSTEM
-static char frame_title_buf[512];
+
+/* A buffer for constructing frame titles in it; allocated from the
+   heap in init_xdisp and resized as needed in store_frame_title_char.  */
+
+static char *frame_title_buf;
+
+/* The buffer's end, and a current output position in it.  */
+
+static char *frame_title_buf_end;
 static char *frame_title_ptr;
 
+
+/* Store a single character C for the frame title in frame_title_buf.
+   Re-allocate frame_title_buf if necessary.  */
+
+static void
+store_frame_title_char (c)
+    char c;
+{
+  /* If output position has reached the end of the allocated buffer,
+     double the buffer's size.  */
+  if (frame_title_ptr == frame_title_buf_end)
+    {
+      int len = frame_title_ptr - frame_title_buf;
+      int new_size = 2 * len * sizeof *frame_title_buf;
+      frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
+      frame_title_buf_end = frame_title_buf + new_size;
+      frame_title_ptr = frame_title_buf + len;
+    }
+
+  *frame_title_ptr++ = c;
+}
+
+
+/* Store part of a frame title in frame_title_buf, beginning at
+   frame_title_ptr.  STR is the string to store.  Do not copy more
+   than PRECISION number of bytes from STR; PRECISION <= 0 means copy
+   the whole string.  Pad with spaces until FIELD_WIDTH number of
+   characters have been copied; FIELD_WIDTH <= 0 means don't pad.
+   Called from display_mode_element when it is used to build a frame
+   title.  */
+
 static int
-store_frame_title (str, mincol, maxcol)
-     char *str;
-     int mincol, maxcol;
-{
-  char *limit;
-  if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
-    maxcol = sizeof (frame_title_buf);
-  limit = &frame_title_buf[maxcol];
-  while (*str != '\0' && frame_title_ptr < limit)
-    *frame_title_ptr++ = *str++;
-  while (frame_title_ptr < &frame_title_buf[mincol])
-    *frame_title_ptr++ = ' ';
-  return frame_title_ptr - frame_title_buf;
-}
+store_frame_title (str, field_width, precision)
+     unsigned char *str;
+     int field_width, precision;
+{
+  int n = 0;
+
+  /* Copy at most PRECISION chars from STR.  */
+  while ((precision <= 0 || n < precision)
+	 && *str)
+    {
+      store_frame_title_char (*str++);
+      ++n;
+    }
+
+  /* Fill up with spaces until FIELD_WIDTH reached.  */
+  while (field_width > 0
+	 && n < field_width)
+    {
+      store_frame_title_char (' ');
+      ++n;
+    }
+
+  return n;
+}
+
+
+/* Set the title of FRAME, if it has changed.  The title format is
+   Vicon_title_format if FRAME is iconified, otherwise it is
+   frame_title_format.  */
 
 static void
 x_consider_frame_title (frame)
      Lisp_Object frame;
 {
-  Lisp_Object fmt;
-  struct buffer *obuf;
-  int len;
-  FRAME_PTR f = XFRAME (frame);
-
-  if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
-    return;
-
-  /* Do we have more than one visible frame on this X display?  */
-  {
-    Lisp_Object tail;
-
-    for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-      {
-	FRAME_PTR tf = XFRAME (XCONS (tail)->car);
-
-	if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
-	    && !FRAME_MINIBUF_ONLY_P (tf)
-	    && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
-	  break;
-      }
-
-    multiple_frames = CONSP (tail);
-  }
-
-  obuf = current_buffer;
-  Fset_buffer (XWINDOW (f->selected_window)->buffer);
-  fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
-  frame_title_ptr = frame_title_buf;
-  len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
-			      0, sizeof (frame_title_buf), fmt);
-  frame_title_ptr = 0;
-  set_buffer_internal (obuf);
-  /* Set the name only if it's changed.  This avoids consing
-     in the common case where it hasn't.  (If it turns out that we've
-     already wasted too much time by walking through the list with
-     display_mode_element, then we might need to optimize at a higher
-     level than this.)  */
-  if (! STRINGP (f->name) || STRING_BYTES (XSTRING (f->name)) != len
-      || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
-    x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
-}
-#else
+  struct frame *f = XFRAME (frame);
+
+  if (FRAME_WINDOW_P (f)
+      || FRAME_MINIBUF_ONLY_P (f)
+      || f->explicit_name)
+    {
+      /* Do we have more than one visible frame on this X display?  */
+      Lisp_Object tail;
+      Lisp_Object fmt;
+      struct buffer *obuf;
+      int len;
+      struct it it;
+
+      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+	{
+	  struct frame *tf = XFRAME (XCONS (tail)->car);
+
+	  if (tf != f 
+	      && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
+	      && !FRAME_MINIBUF_ONLY_P (tf)
+	      && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
+	    break;
+	}
+
+      /* Set global variable indicating that multiple frames exist.  */
+      multiple_frames = CONSP (tail);
+
+      /* Switch to the buffer of selected window of the frame.  Set up
+	 frame_title_ptr so that display_mode_element will output into it;
+	 then display the title.  */
+      obuf = current_buffer;
+      Fset_buffer (XWINDOW (f->selected_window)->buffer);
+      fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
+      frame_title_ptr = frame_title_buf;
+      init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
+		     NULL, DEFAULT_FACE_ID);
+      len = display_mode_element (&it, 0, -1, -1, fmt);
+      frame_title_ptr = NULL;
+      set_buffer_internal (obuf);
+
+      /* Set the title only if it's changed.  This avoids consing in
+	 the common case where it hasn't.  (If it turns out that we've
+	 already wasted too much time by walking through the list with
+	 display_mode_element, then we might need to optimize at a
+	 higher level than this.)  */
+      if (! STRINGP (f->name) 
+	  || STRING_BYTES (XSTRING (f->name)) != len
+	  || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
+	x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
+    }
+}
+
+#else /* not HAVE_WINDOW_SYSTEM */
+
 #define frame_title_ptr ((char *)0)
 #define store_frame_title(str, mincol, maxcol) 0
-#endif
+
+#endif /* not HAVE_WINDOW_SYSTEM */
+
+
+
 
-/* Prepare for redisplay by updating menu-bar item lists when appropriate.
-   This can call eval.  */
+/***********************************************************************
+			      Menu Bars
+ ***********************************************************************/
+
+
+/* Prepare for redisplay by updating menu-bar item lists when
+   appropriate.  This can call eval.  */
 
 void
 prepare_menu_bars ()
 {
-  register struct window *w = XWINDOW (selected_window);
   int all_windows;
   struct gcpro gcpro1, gcpro2;
-
-  all_windows = (update_mode_lines || buffer_shared > 1
-		 || windows_or_buffers_changed);
-
-  /* Update all frame titles based on their buffer names, etc.
-     We do this before the menu bars so that the buffer-menu
-     will show the up-to-date frame titles.
-
-     This used to be done after the menu bars, for a reason that
-     was stated as follows but which I do not understand:
-     "We do this after the menu bars so that the frame will first
-     create its menu bar using the name `emacs' if no other name
-     has yet been specified."
-     I think that is no longer a concern.  */
+  struct frame *f;
+  struct frame *tooltip_frame;
+
+#ifdef HAVE_X_WINDOWS
+  tooltip_frame = tip_frame;
+#else
+  tooltip_frame = NULL;
+#endif
+
+  /* Update all frame titles based on their buffer names, etc.  We do
+     this before the menu bars so that the buffer-menu will show the
+     up-to-date frame titles.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (windows_or_buffers_changed || update_mode_lines)
     {
       Lisp_Object tail, frame;
 
       FOR_EACH_FRAME (tail, frame)
-	if (FRAME_VISIBLE_P (XFRAME (frame))
-	    || FRAME_ICONIFIED_P (XFRAME (frame)))
-	  x_consider_frame_title (frame);
-    }
-#endif
-
-  /* Update the menu bar item lists, if appropriate.
-     This has to be done before any actual redisplay
-     or generation of display lines.  */
+	{
+	  f = XFRAME (frame);
+	  if (f != tooltip_frame
+	      && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
+	    x_consider_frame_title (frame);
+	}
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+  /* Update the menu bar item lists, if appropriate.  This has to be
+     done before any actual redisplay or generation of display lines.  */
+  all_windows = (update_mode_lines 
+		 || buffer_shared > 1
+		 || windows_or_buffers_changed);
   if (all_windows)
     {
       Lisp_Object tail, frame;
@@ -955,680 +5462,68 @@
 
       FOR_EACH_FRAME (tail, frame)
 	{
-	  /* If a window on this frame changed size,
-	     report that to the user and clear the size-change flag.  */
-	  if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
+	  f = XFRAME (frame);
+
+	  /* Ignore tooltip frame.  */
+	  if (f == tooltip_frame)
+	    continue;
+	  
+	  /* If a window on this frame changed size, report that to
+	     the user and clear the size-change flag.  */
+	  if (FRAME_WINDOW_SIZES_CHANGED (f))
 	    {
 	      Lisp_Object functions;
-	      /* Clear flag first in case we get error below.  */
-	      FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
+	      
+	      /* Clear flag first in case we get an error below.  */
+	      FRAME_WINDOW_SIZES_CHANGED (f) = 0;
 	      functions = Vwindow_size_change_functions;
 	      GCPRO2 (tail, functions);
+	      
 	      while (CONSP (functions))
 		{
-		  call1 (XCONS (functions)->car, frame);
-		  functions = XCONS (functions)->cdr;
+		  call1 (XCAR (functions), frame);
+		  functions = XCDR (functions);
 		}
 	      UNGCPRO;
 	    }
+	  
 	  GCPRO1 (tail);
-	  update_menu_bar (XFRAME (frame), 0);
+	  update_menu_bar (f, 0);
+#ifdef HAVE_WINDOW_SYSTEM
+	  update_toolbar (f, 0);
+#endif
 	  UNGCPRO;
 	}
 
       unbind_to (count, Qnil);
     }
   else
-    update_menu_bar (selected_frame, 1);
-
-  /* Motif needs this.  See comment in xmenu.c.
-     Turn it off when pending_menu_activation is not defined.  */
+    {
+      update_menu_bar (selected_frame, 1);
+#ifdef HAVE_WINDOW_SYSTEM
+      update_toolbar (selected_frame, 1);
+#endif
+    }
+
+  /* Motif needs this.  See comment in xmenu.c.  Turn it off when
+     pending_menu_activation is not defined.  */
 #ifdef USE_X_TOOLKIT
   pending_menu_activation = 0;
 #endif
 }
-
-/* Do a frame update, taking possible shortcuts into account.
-   This is the main external entry point for redisplay.
-
-   If the last redisplay displayed an echo area message and that
-   message is no longer requested, we clear the echo area
-   or bring back the minibuffer if that is in use.
-
-   Do not call eval from within this function.
-   Calls to eval after the call to echo_area_display would confuse
-   the display_line mechanism and would cause a crash.
-   Calls to eval before that point will work most of the time,
-   but can still lose, because  this function
-   can be called from signal handlers; with alarms set up;
-   or with synchronous processes running.
-
-   See Fcall_process; if you called it from here, it could be
-   entered recursively.  */
-
-static int do_verify_charstarts;
-
-/* Counter is used to clear the face cache
-   no more than once ever 1000 redisplays.  */
-static int clear_face_cache_count;
-
-/* Record the previous terminal frame we displayed.  */
-static FRAME_PTR previous_terminal_frame;
-
-void
-redisplay ()
-{
-  redisplay_internal (0);
-}
-
-/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
-   is not in response to any user action; therefore, we should
-   preserve the echo area.  (Actually, our caller does that job.)
-   Perhaps in the future avoid recentering windows
-   if it is not necessary; currently that causes some problems.  */
-
-static void
-redisplay_internal (preserve_echo_area)
-     int preserve_echo_area;
-{
-  register struct window *w = XWINDOW (selected_window);
-  register int pause;
-  int must_finish = 0;
-  int all_windows;
-  register int tlbufpos, tlendpos;
-  struct position pos;
-  int number_of_visible_frames;
-
-  if (noninteractive)
-    return;
-
-#ifdef USE_X_TOOLKIT
-  if (popup_activated ())
-    return;
-#endif
-
-  if (! NILP (Vinhibit_redisplay))
-    return;
-
- retry:
-
-  if (! FRAME_WINDOW_P (selected_frame)
-      && previous_terminal_frame != selected_frame)
-    {
-      /* Since frames on an ASCII terminal share the same display area,
-	 displaying a different frame means redisplay the whole thing.  */
-      windows_or_buffers_changed++;
-      SET_FRAME_GARBAGED (selected_frame);
-      XSETFRAME (Vterminal_frame, selected_frame);
-    }
-  previous_terminal_frame = selected_frame;
-
-  /* Set the visible flags for all frames.
-     Do this before checking for resized or garbaged frames; they want
-     to know if their frames are visible.
-     See the comment in frame.h for FRAME_SAMPLE_VISIBILITY.  */
-  {
-    Lisp_Object tail, frame;
-
-    number_of_visible_frames = 0;
-
-    FOR_EACH_FRAME (tail, frame)
-      {
-	FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-
-	if (FRAME_VISIBLE_P (XFRAME (frame)))
-	  number_of_visible_frames++;
-
-	/* Clear out all the display lines in which we will generate the
-	   glyphs to display.  */
-	init_desired_glyphs (XFRAME (frame));
-      }
-  }
-
-  /* Notice any pending interrupt request to change frame size.  */
-  do_pending_window_change ();
-
-  if (frame_garbaged)
-    {
-      redraw_garbaged_frames ();
-      frame_garbaged = 0;
-    }
-
-  prepare_menu_bars ();
-
-  if (windows_or_buffers_changed)
-    update_mode_lines++;
-
-  /* Detect case that we need to write or remove a star in the mode line.  */
-  if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
-    {
-      w->update_mode_line = Qt;
-      if (buffer_shared > 1)
-	update_mode_lines++;
-    }
-
-  /* If %c is in use, update it if needed.  */
-  if (!NILP (w->column_number_displayed)
-      /* This alternative quickly identifies a common case
-	 where no change is needed.  */
-      && !(PT == XFASTINT (w->last_point)
-	   && XFASTINT (w->last_modified) >= MODIFF
-	   && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
-      && XFASTINT (w->column_number_displayed) != current_column ())
-    w->update_mode_line = Qt; 
-
-  FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
-
-  all_windows = update_mode_lines || buffer_shared > 1;
-
-  /* If specs for an arrow have changed, do thorough redisplay
-     to ensure we remove any arrow that should no longer exist.  */
-  if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
-      || ! EQ (Voverlay_arrow_string, last_arrow_string))
-    all_windows = 1;
-
-  /* Normally the message* functions will have already displayed and
-     updated the echo area, but the frame may have been trashed, or
-     the update may have been preempted, so display the echo area
-     again here.  */
-  if (echo_area_glyphs || previous_echo_glyphs)
-    {
-      echo_area_display ();
-      must_finish = 1;
-    }
-
-  /* If showing region, and mark has changed, must redisplay whole window.  */
-  if (((!NILP (Vtransient_mark_mode)
-	&& !NILP (XBUFFER (w->buffer)->mark_active))
-       != !NILP (w->region_showing))
-      || (!NILP (w->region_showing)
-	  && !EQ (w->region_showing,
-		  Fmarker_position (XBUFFER (w->buffer)->mark))))
-    this_line_bufpos = -1;
-
-  tlbufpos = this_line_bufpos;
-  tlendpos = this_line_endpos;
-  if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
-      && !current_buffer->clip_changed
-      && FRAME_VISIBLE_P (XFRAME (w->frame))
-      && !FRAME_OBSCURED_P (XFRAME (w->frame))
-      /* Make sure recorded data applies to current buffer, etc */
-      && this_line_buffer == current_buffer
-      && current_buffer == XBUFFER (w->buffer)
-      && NILP (w->force_start)
-      /* Point must be on the line that we have info recorded about */
-      && PT >= tlbufpos
-      && PT <= Z - tlendpos
-      /* All text outside that line, including its final newline,
-	 must be unchanged */
-      && ((XFASTINT (w->last_modified) >= MODIFF
-	   && (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))
-	  || (beg_unchanged >= tlbufpos - 1
-	      && GPT >= tlbufpos
-	      /* If selective display, can't optimize
-		 if the changes start at the beginning of the line.  */
-	      && ((INTEGERP (current_buffer->selective_display)
-		   && XINT (current_buffer->selective_display) > 0
-		   ? (beg_unchanged >= tlbufpos
-		      && GPT > tlbufpos)
-		   : 1))
-	      && end_unchanged >= tlendpos
-	      && Z - GPT >= tlendpos)))
-    {
-      int tlbufpos_byte = CHAR_TO_BYTE (tlbufpos);
-      if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos_byte - 1) != '\n'
-	  && (tlbufpos == ZV
-	      || FETCH_BYTE (tlbufpos_byte) == '\n'))
-	/* Former continuation line has disappeared by becoming empty */
-	goto cancel;
-      else if (XFASTINT (w->last_modified) < MODIFF
-	       || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
-	       || MINI_WINDOW_P (w))
-	{
-	  /* We have to handle the case of continuation around a
-	     wide-column character (See the comment in indent.c around
-	     line 885).
-
-	     For instance, in the following case:
-
-	     --------  Insert  --------
-	     K_A_N_\\   `a'    K_A_N_a\		`X_' are wide-column chars.
-	     J_I_       ==>    J_I_		`^^' are cursors.
-	     ^^                ^^
-	     --------          --------
-
-	     As we have to redraw the line above, we should goto cancel.  */
-
-	  struct position val;
-	  int prevline;
-	  int opoint = PT, opoint_byte = PT_BYTE;
-
-	  scan_newline (tlbufpos, tlbufpos_byte, BEGV, BEGV_BYTE, -1, 1);
-
-	  val = *compute_motion (PT, 0,
-				 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
-				 0,
-				 tlbufpos,
-				 1 << (BITS_PER_SHORT - 1),
-				 1 << (BITS_PER_SHORT - 1),
-				 window_internal_width (w) - 1,
-				 XINT (w->hscroll), 0, w);
-	  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-	  if (val.hpos != this_line_start_hpos)
-	    goto cancel;
-
-	  cursor_vpos = -1;
-	  overlay_arrow_seen = 0;
-	  zv_strings_seen = 0;
-	  display_text_line (w, tlbufpos, tlbufpos_byte,
-			     this_line_vpos, this_line_start_hpos,
-			     pos_tab_offset (w, tlbufpos, tlbufpos_byte), 0);
-	  /* If line contains point, is not continued,
-		 and ends at same distance from eob as before, we win */
-	  if (cursor_vpos >= 0 && this_line_bufpos
-	      && this_line_endpos == tlendpos)
-	    {
-	      /* If this is not the window's last line,
-		 we must adjust the charstarts of the lines below.  */
-	      if (this_line_vpos + 1
-		  < XFASTINT (w->top) + window_internal_height (w))
-		{
-		  int left = WINDOW_LEFT_MARGIN (w);
-		  int *charstart_next_line
-		    = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
-		  int adjust;
-
-		  if (Z - tlendpos == ZV)
-		    /* This line ends at end of (accessible part of) buffer.
-		       There is no newline to count.  */
-		    adjust = Z - tlendpos - charstart_next_line[left];
-		  else
-		    /* This line ends in a newline.
-		       Must take account of the newline and the rest of the
-		       text that follows.  */
-		    adjust = Z - tlendpos + 1 - charstart_next_line[left];
-
-		  adjust_window_charstarts (w, this_line_vpos, adjust);
-		}
-
-	      if (!WINDOW_FULL_WIDTH_P (w))
-		preserve_other_columns (w);
-	      goto update;
-	    }
-	  else
-	    goto cancel;
-	}
-      else if (PT == XFASTINT (w->last_point)
-	       /* Make sure the cursor was last displayed
-		  in this window.  Otherwise we have to reposition it.  */
-	       && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
-	       && (XINT (w->top) + XINT (w->height)
-		   > FRAME_CURSOR_Y (selected_frame)))
-	{
-	  if (!must_finish)
-	    {
-	      do_pending_window_change ();
-	      return;
-	    }
-	  goto update;
-	}
-      /* If highlighting the region, or if the cursor is in the echo area,
-	 then we can't just move the cursor.  */
-      else if (! (!NILP (Vtransient_mark_mode)
-		  && !NILP (current_buffer->mark_active))
-	       && (w == XWINDOW (current_buffer->last_selected_window)
-		   || highlight_nonselected_windows)
-	       && NILP (w->region_showing)
-	       && !cursor_in_echo_area)
-	{
-	  pos = *compute_motion (tlbufpos, 0,
-				 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
-				 0,
-				 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
-				 window_internal_width (w) - 1,
-				 XINT (w->hscroll),
-				 pos_tab_offset (w, tlbufpos, tlbufpos_byte),
-				 w);
-	  if (pos.vpos < 1)
-	    {
-	      int width = window_internal_width (w) - 1;
-	      FRAME_CURSOR_X (selected_frame)
-		= WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width);
-	      FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
-	      goto update;
-	    }
-	  else
-	    goto cancel;
-	}
-    cancel:
-      /* Text changed drastically or point moved off of line */
-      cancel_line (this_line_vpos, selected_frame);
-    }
-
-  this_line_bufpos = 0;
-  all_windows |= buffer_shared > 1;
-
-  clear_face_cache_count++;
-
-  if (all_windows)
-    {
-      Lisp_Object tail, frame;
-
-#ifdef HAVE_FACES
-      /* Clear the face cache, only when we do a full redisplay
-	 and not too often either.  */
-      if (clear_face_cache_count > 1000)
-	{
-	  clear_face_cache ();
-	  clear_face_cache_count = 0;
-	}
-#endif
-
-      /* Recompute # windows showing selected buffer.
-	 This will be incremented each time such a window is displayed.  */
-      buffer_shared = 0;
-
-      FOR_EACH_FRAME (tail, frame)
-	{
-	  FRAME_PTR f = XFRAME (frame);
-	  if (FRAME_WINDOW_P (f) || f == selected_frame)
-	    {
-
-	      /* Mark all the scroll bars to be removed; we'll redeem the ones
-		 we want when we redisplay their windows.  */
-	      if (condemn_scroll_bars_hook)
-		(*condemn_scroll_bars_hook) (f);
-
-	      if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
-		redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
-
-	      /* Any scroll bars which redisplay_windows should have nuked
-		 should now go away.  */
-	      if (judge_scroll_bars_hook)
-		(*judge_scroll_bars_hook) (f);
-	    }
-	}
-    }
-  else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
-    {
-      redisplay_window (selected_window, 1, preserve_echo_area);
-      if (!WINDOW_FULL_WIDTH_P (w))
-	preserve_other_columns (w);
-    }
-
-update: 
-  /* Prevent various kinds of signals during display update.
-     stdio is not robust about handling signals,
-     which can cause an apparent I/O error.  */
-  if (interrupt_input)
-    unrequest_sigio ();
-  stop_polling ();
-
-  if (all_windows)
-    {
-      Lisp_Object tail;
-
-      pause = 0;
-
-      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-	{
-	  FRAME_PTR f;
-
-	  if (!FRAMEP (XCONS (tail)->car))
-	    continue;
-
-	  f = XFRAME (XCONS (tail)->car);
-
-	  if ((FRAME_WINDOW_P (f) || f == selected_frame)
-	      && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
-	    {
-	      pause |= update_frame (f, 0, 0);
-	      if (!pause)
-		{
-		  mark_window_display_accurate (f->root_window, 1);
-		  if (frame_up_to_date_hook != 0)
-		    (*frame_up_to_date_hook) (f);
-		}
-	    }
-	}
-    }
-  else
-    {
-      if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
-	pause = update_frame (selected_frame, 0, 0);
-      else
-	pause = 0;
-
-      /* We may have called echo_area_display at the top of this
-	 function.  If the echo area is on another frame, that may
-	 have put text on a frame other than the selected one, so the
-	 above call to update_frame would not have caught it.  Catch
-	 it here.  */
-      {
-	Lisp_Object mini_window;
-	FRAME_PTR mini_frame;
-
-	mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
-	mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-	
-	if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
-	  pause |= update_frame (mini_frame, 0, 0);
-      }
-    }
-
-  /* If frame does not match, prevent doing single-line-update next time.
-     Also, don't forget to check every line to update the arrow.  */
-  if (pause)
-    {
-      this_line_bufpos = 0;
-      if (!NILP (last_arrow_position))
-	{
-	  last_arrow_position = Qt;
-	  last_arrow_string = Qt;
-	}
-      /* If we pause after scrolling, some lines in current_frame
-	 may be null, so preserve_other_columns won't be able to
-	 preserve all the vertical-bar separators.  So, avoid using it
-	 in that case.  */
-      if (!WINDOW_FULL_WIDTH_P (w))
-	update_mode_lines = 1;
-    }
-
-  /* Now text on frame agrees with windows, so
-     put info into the windows for partial redisplay to follow */
-
-  if (!pause)
-    {
-      register struct buffer *b = XBUFFER (w->buffer);
-
-      blank_end_of_window = 0;
-      unchanged_modified = BUF_MODIFF (b);
-      overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
-      beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
-      end_unchanged = BUF_Z (b) - BUF_GPT (b);
-
-      /* Record the last place cursor was displayed in this window.
-	 But not if cursor is in the echo area, because in that case
-	 FRAME_CURSOR_X and FRAME_CURSOR_Y are in the echo area.  */
-      if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (selected_frame)
-	    && EQ (FRAME_MINIBUF_WINDOW (selected_frame), minibuf_window)))
-	{
-	  XSETFASTINT (w->last_point, BUF_PT (b));
-	  XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
-	  XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
-	}
-      else
-	/* Make last_point invalid, since we don't really know
-	   where the cursor would be if it were not in the echo area.  */
-	XSETINT (w->last_point, -1);
-
-      if (all_windows)
-	mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
-      else
-	{
-	  b->clip_changed = 0;
-	  w->update_mode_line = Qnil;
-	  XSETFASTINT (w->last_modified, BUF_MODIFF (b));
-	  XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
-	  w->last_had_star
-	    = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-	       ? Qt : Qnil);
-
-	  /* Record if we are showing a region, so can make sure to
-	     update it fully at next redisplay.  */
-	  w->region_showing = (!NILP (Vtransient_mark_mode)
-			       && (w == XWINDOW (current_buffer->last_selected_window)
-				   || highlight_nonselected_windows)
-			       && !NILP (XBUFFER (w->buffer)->mark_active)
-			       ? Fmarker_position (XBUFFER (w->buffer)->mark)
-			       : Qnil);
-
-	  w->window_end_valid = w->buffer;
-	  last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
-	  last_arrow_string = Voverlay_arrow_string;
-	  if (do_verify_charstarts)
-	    verify_charstarts (w);
-	  if (frame_up_to_date_hook != 0)
-	    (*frame_up_to_date_hook) (selected_frame);
-	}
-      update_mode_lines = 0;
-      windows_or_buffers_changed = 0;
-    }
-
-  /* Start SIGIO interrupts coming again.
-     Having them off during the code above
-     makes it less likely one will discard output,
-     but not impossible, since there might be stuff
-     in the system buffer here.
-     But it is much hairier to try to do anything about that.  */
-
-  if (interrupt_input)
-    request_sigio ();
-  start_polling ();
-
-  /* If something has become visible now which was not before,
-     redisplay again, so that we get them.  */
-  if (!pause)
-    {
-      Lisp_Object tail, frame;
-      int new_count = 0;
-
-      FOR_EACH_FRAME (tail, frame)
-	{
-	  int this_is_visible = 0;
-
-	  if (XFRAME (frame)->visible)
-	    this_is_visible = 1;
-	  FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-	  if (XFRAME (frame)->visible)
-	    this_is_visible = 1;
-
-	  if (this_is_visible)
-	    new_count++;
-	}
-
-      if (new_count != number_of_visible_frames)
-	windows_or_buffers_changed++;
-    }
-
-  /* Change frame size now if a change is pending.  */
-  do_pending_window_change ();
-
-  /* If we just did a pending size change, or have additional
-     visible frames, redisplay again.  */
-  if (windows_or_buffers_changed && !pause)
-    goto retry;
-}
-
-/* Redisplay, but leave alone any recent echo area message
-   unless another message has been requested in its place.
-
-   This is useful in situations where you need to redisplay but no
-   user action has occurred, making it inappropriate for the message
-   area to be cleared.  See tracking_off and
-   wait_reading_process_input for examples of these situations.  */
-
-void
-redisplay_preserve_echo_area ()
-{
-  if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
-    {
-      echo_area_glyphs = previous_echo_glyphs;
-      redisplay_internal (1);
-      echo_area_glyphs = 0;
-    }
-  else
-    redisplay_internal (1);
-}
-
-void
-mark_window_display_accurate (window, flag)
-     Lisp_Object window;
-     int flag;
-{
-  register struct window *w;
-
-  for (;!NILP (window); window = w->next)
-    {
-      if (!WINDOWP (window)) abort ();
-      w = XWINDOW (window);
-
-      if (!NILP (w->buffer))
-	{
-	  XSETFASTINT (w->last_modified,
-		       !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
-	  XSETFASTINT (w->last_overlay_modified,
-		       !flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)));
-	  w->last_had_star
-	    = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-	       ? Qt : Qnil);
-
-	  /* Record if we are showing a region, so can make sure to
-	     update it fully at next redisplay.  */
-	  w->region_showing = (!NILP (Vtransient_mark_mode)
-			       && (w == XWINDOW (current_buffer->last_selected_window)
-				   || highlight_nonselected_windows)
-			       && !NILP (XBUFFER (w->buffer)->mark_active)
-			       ? Fmarker_position (XBUFFER (w->buffer)->mark)
-			       : Qnil);
-	}
-
-      w->window_end_valid = w->buffer;
-      w->update_mode_line = Qnil;
-      if (!NILP (w->buffer) && flag)
-	XBUFFER (w->buffer)->clip_changed = 0;
-
-      if (!NILP (w->vchild))
-	mark_window_display_accurate (w->vchild, flag);
-      if (!NILP (w->hchild))
-	mark_window_display_accurate (w->hchild, flag);
-    }
-
-  if (flag)
-    {
-      last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
-      last_arrow_string = Voverlay_arrow_string;
-    }
-  else
-    {
-      /* t is unequal to any useful value of Voverlay_arrow_... */
-      last_arrow_position = Qt;
-      last_arrow_string = Qt;
-    }
-}
-
-/* Update the menu bar item list for frame F.
-   This has to be done before we start to fill in any display lines,
-   because it can call eval.
-
-   If SAVE_MATCH_DATA is 1, we must save and restore it here.  */
+
+
+/* Update the menu bar item list for frame F.  This has to be done
+   before we start to fill in any display lines, because it can call
+   eval.
+
+   If SAVE_MATCH_DATA is non-zero, we must save and restore it here.  */
 
 static void
 update_menu_bar (f, save_match_data)
-     FRAME_PTR f;
+     struct frame *f;
      int save_match_data;
 {
-  struct buffer *old = current_buffer;
   Lisp_Object window;
   register struct window *w;
 
@@ -1677,19 +5572,22 @@
 
 	  /* Run the Lucid hook.  */
 	  call1 (Vrun_hooks, Qactivate_menubar_hook);
+	  
 	  /* If it has changed current-menubar from previous value,
-	     really recompute the menubar from the value.  */
+	     really recompute the menu-bar from the value.  */
 	  if (! NILP (Vlucid_menu_bar_dirty_flag))
 	    call0 (Qrecompute_lucid_menubar);
+	  
 	  safe_run_hooks (Qmenu_bar_update_hook);
 	  FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+	  
 	  /* Redisplay the menu bar in case we changed it.  */
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
 	  if (FRAME_WINDOW_P (f))
 	    set_frame_menubar (f, 0, 0);
 	  else
 	    /* On a terminal screen, the menu bar is an ordinary screen
-	     line, and this makes it get updated.  */
+	       line, and this makes it get updated.  */
 	    w->update_mode_line = Qt;
 #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
 	  /* In the non-toolkit version, the menu bar is an ordinary screen
@@ -1702,24 +5600,1444 @@
 	}
     }
 }
+
+
 
-int do_id = 1;
-
-/* Redisplay WINDOW and its subwindows and siblings.  */
+/***********************************************************************
+			       Toolbars
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Update the toolbar item list for frame F.  This has to be done
+   before we start to fill in any display lines.  Called from
+   prepare_menu_bars.  If SAVE_MATCH_DATA is non-zero, we must save
+   and restore it here.  */
+
+static void
+update_toolbar (f, save_match_data)
+     struct frame *f;
+     int save_match_data;
+{
+  if (WINDOWP (f->toolbar_window)
+      && XFASTINT (XWINDOW (f->toolbar_window)->height) > 0)
+    {
+      Lisp_Object window;
+      struct window *w;
+
+      window = FRAME_SELECTED_WINDOW (f);
+      w = XWINDOW (window);
+  
+      /* If the user has switched buffers or windows, we need to
+	 recompute to reflect the new bindings.  But we'll
+	 recompute when update_mode_lines is set too; that means
+	 that people can use force-mode-line-update to request
+	 that the menu bar be recomputed.  The adverse effect on
+	 the rest of the redisplay algorithm is about the same as
+	 windows_or_buffers_changed anyway.  */
+      if (windows_or_buffers_changed
+	  || !NILP (w->update_mode_line)
+	  || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
+	       < BUF_MODIFF (XBUFFER (w->buffer)))
+	      != !NILP (w->last_had_star))
+	  || ((!NILP (Vtransient_mark_mode)
+	       && !NILP (XBUFFER (w->buffer)->mark_active))
+	      != !NILP (w->region_showing)))
+	{
+	  struct buffer *prev = current_buffer;
+	  int count = specpdl_ptr - specpdl;
+
+	  /* Set current_buffer to the buffer of the selected
+	     window of the frame, so that we get the right local
+	     keymaps.  */
+	  set_buffer_internal_1 (XBUFFER (w->buffer));
+
+	  /* Save match data, if we must.  */
+	  if (save_match_data)
+	    record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+
+	  /* Make sure that we don't accidentally use bogus keymaps.  */
+	  if (NILP (Voverriding_local_map_menu_flag))
+	    {
+	      specbind (Qoverriding_terminal_local_map, Qnil);
+	      specbind (Qoverriding_local_map, Qnil);
+	    }
+
+	  /* Build desired toolbar items from keymaps.  */
+	  f->desired_toolbar_items
+	    = toolbar_items (f->desired_toolbar_items,
+			     &f->n_desired_toolbar_items);
+	  
+	  /* Redisplay the toolbar in case we changed it.  */
+	  w->update_mode_line = Qt;
+
+	  unbind_to (count, Qnil);
+	  set_buffer_internal_1 (prev);
+	}
+    }
+}
+
+
+/* Set F->desired_toolbar_string to a Lisp string representing frame
+   F's desired toolbar contents.  F->desired_toolbar_items must have
+   been set up previously by calling prepare_menu_bars.  */
+
+static void
+build_desired_toolbar_string (f)
+     struct frame *f;
+{
+  int i, size, size_needed, string_idx;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+  Lisp_Object image, plist, props;
+
+  image = plist = props = Qnil;
+  GCPRO3 (image, plist, props);
+
+  /* Prepare F->desired_toolbar_string.  If we can reuse it, do so.
+     Otherwise, make a new string.  */
+  
+  /* The size of the string we might be able to reuse.  */
+  size = (STRINGP (f->desired_toolbar_string)
+	  ? XSTRING (f->desired_toolbar_string)->size
+	  : 0);
+
+  /* Each image in the string we build is preceded by a space,
+     and there is a space at the end.  */
+  size_needed = f->n_desired_toolbar_items + 1;
+
+  /* Reuse f->desired_toolbar_string, if possible.  */
+  if (size < size_needed)
+    f->desired_toolbar_string = Fmake_string (make_number (size_needed), ' ');
+  else
+    {
+      props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
+      Fremove_text_properties (make_number (0), make_number (size),
+			       props, f->desired_toolbar_string);
+    }
+
+  /* Put a `display' property on the string for the images to display,
+     put a `menu_item' property on toolbar items with a value that
+     is the index of the item in F's toolbar item vector.  */
+  for (i = 0, string_idx = 0;
+       i < f->n_desired_toolbar_items;
+       ++i, string_idx += 1)
+    {
+#define PROP(IDX)					\
+      (XVECTOR (f->desired_toolbar_items)		\
+       ->contents[i * TOOLBAR_ITEM_NSLOTS + (IDX)])
+
+      int enabled_p = !NILP (PROP (TOOLBAR_ITEM_ENABLED_P));
+      int selected_p = !NILP (PROP (TOOLBAR_ITEM_SELECTED_P));
+      int margin, relief;
+      extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
+      extern Lisp_Object Qlaplace;
+
+      /* If image is a vector, choose the image according to the
+	 button state.  */
+      image = PROP (TOOLBAR_ITEM_IMAGES);
+      if (VECTORP (image))
+	{
+	  enum toolbar_item_image idx;
+	  
+	  if (enabled_p)
+	    idx = (selected_p
+		   ? TOOLBAR_IMAGE_ENABLED_SELECTED
+		   : TOOLBAR_IMAGE_ENABLED_DESELECTED);
+	  else
+	    idx = (selected_p
+		   ? TOOLBAR_IMAGE_DISABLED_SELECTED
+		   : TOOLBAR_IMAGE_DISABLED_DESELECTED);
+	  
+	  xassert (XVECTOR (image)->size >= idx);
+	  image = XVECTOR (image)->contents[idx];
+	}
+
+      /* Ignore invalid image specifications.  */
+      if (!valid_image_p (image))
+	continue;
+
+      /* Display the toolbar button pressed, or depressed.  */
+      plist = Fcopy_sequence (XCDR (image));
+
+      /* Compute margin and relief to draw.  */
+      relief = toolbar_button_relief > 0 ? toolbar_button_relief : 3;
+      margin = relief + max (0, toolbar_button_margin);
+      
+      if (auto_raise_toolbar_buttons_p)
+	{
+	  /* Add a `:relief' property to the image spec if the item is
+	     selected.  */
+	  if (selected_p)
+	    {
+	      plist = Fplist_put (plist, QCrelief, make_number (-relief));
+	      margin -= relief;
+	    }
+	}
+      else
+	{
+	  /* If image is selected, display it pressed, i.e. with a
+	     negative relief.  If it's not selected, display it with a
+	     raised relief.  */
+	  plist = Fplist_put (plist, QCrelief,
+			      (selected_p
+			       ? make_number (-relief)
+			       : make_number (relief)));
+	  margin -= relief;
+	}
+
+      /* Put a margin around the image.  */
+      if (margin)
+	plist = Fplist_put (plist, QCmargin, make_number (margin));
+	  
+      /* If button is not enabled, make the image appear disabled by
+	 applying an appropriate algorithm to it.  */
+      if (!enabled_p)
+	plist = Fplist_put (plist, QCalgorithm, Qlaplace);
+      
+      /* Put a `display' text property on the string for the image to
+	 display.  Put a `menu-item' property on the string that gives
+	 the start of this item's properties in the toolbar items
+	 vector.  */
+      image = Fcons (Qimage, plist);
+      props = list4 (Qdisplay, image,
+		     Qmenu_item, make_number (i * TOOLBAR_ITEM_NSLOTS)),
+      Fadd_text_properties (make_number (string_idx),
+			    make_number (string_idx + 1),
+			    props, f->desired_toolbar_string);
+#undef PROP
+    }
+
+  UNGCPRO;
+}
+
+
+/* Display one line of the toolbar of frame IT->f.  */
+
+static void
+display_toolbar_line (it)
+     struct it *it;
+{
+  struct glyph_row *row = it->glyph_row;
+  int max_x = it->last_visible_x;
+  struct glyph *last;
+  
+  prepare_desired_row (row);
+  row->y = it->current_y;
+  
+  while (it->current_x < max_x)
+    {
+      int x_before, x, n_glyphs_before, i, nglyphs;
+
+      /* Get the next display element.  */
+      if (!get_next_display_element (it))
+	break;
+
+      /* Produce glyphs.  */
+      x_before = it->current_x;
+      n_glyphs_before = it->glyph_row->used[TEXT_AREA];
+      PRODUCE_GLYPHS (it);
+
+      nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
+      i = 0;
+      x = x_before;
+      while (i < nglyphs)
+	{
+	  struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
+	  
+	  if (x + glyph->pixel_width > max_x)
+	    {
+	      /* Glyph doesn't fit on line.  */
+	      it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
+	      it->current_x = x;
+	      goto out;
+	    }
+
+	  ++it->hpos;
+	  x += glyph->pixel_width;
+	  ++i;
+	}
+
+      /* Stop at line ends.  */
+      if (ITERATOR_AT_END_OF_LINE_P (it))
+	break;
+
+      set_iterator_to_next (it);
+    }
+
+ out:;
+
+  row->displays_text_p = row->used[TEXT_AREA] != 0;
+  extend_face_to_end_of_line (it);
+  last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
+  last->right_box_line_p = 1;
+  compute_line_metrics (it);
+  
+  /* If line is empty, make it occupy the rest of the toolbar.  */
+  if (!row->displays_text_p)
+    {
+      row->height = it->last_visible_y - row->y;
+      row->ascent = 0;
+    }
+  
+  row->full_width_p = 1;
+  row->continued_p = 0;
+  row->truncated_on_left_p = 0;
+  row->truncated_on_right_p = 0;
+
+  it->current_x = it->hpos = 0;
+  it->current_y += row->height;
+  ++it->vpos;
+  ++it->glyph_row;
+}
+
+
+/* Value is the number of screen lines needed to make all toolbar
+   items of frame F visible.  */
+
+static int
+toolbar_lines_needed (f)
+     struct frame *f;
+{
+  struct window *w = XWINDOW (f->toolbar_window);
+  struct it it;
+  
+  /* Initialize an iterator for iteration over F->desired_toolbar_string
+     in the toolbar window of frame F.  */
+  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID);
+  it.first_visible_x = 0;
+  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1);
+
+  while (!ITERATOR_AT_END_P (&it))
+    {
+      it.glyph_row = w->desired_matrix->rows;
+      clear_glyph_row (it.glyph_row);
+      display_toolbar_line (&it);
+    }
+
+  return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+}
+
+
+/* Display the toolbar of frame F.  Value is non-zero if toolbar's
+   height should be changed.  */
+
+static int
+redisplay_toolbar (f)
+     struct frame *f;
+{
+  struct window *w;
+  struct it it;
+  struct glyph_row *row;
+  int change_height_p = 0;
+  
+  /* If frame hasn't a toolbar window or if it is zero-height, don't
+     do anything.  This means you must start with toolbar-lines
+     non-zero to get the auto-sizing effect.  Or in other words, you
+     can turn off toolbars by specifying toolbar-lines zero.  */
+  if (!WINDOWP (f->toolbar_window)
+      || (w = XWINDOW (f->toolbar_window),
+	  XFASTINT (w->height) == 0))
+    return 0;
+
+  /* Set up an iterator for the toolbar window.  */
+  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID);
+  it.first_visible_x = 0;
+  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  row = it.glyph_row;
+
+  /* Build a string that represents the contents of the toolbar.  */
+  build_desired_toolbar_string (f);
+  reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1);
+
+  /* Display as many lines as needed to display all toolbar items.  */
+  while (it.current_y < it.last_visible_y)
+    display_toolbar_line (&it);
+
+  /* It doesn't make much sense to try scrolling in the toolbar
+     window, so don't do it.  */
+  w->desired_matrix->no_scrolling_p = 1;
+  w->must_be_updated_p = 1;
+
+  if (auto_resize_toolbars_p)
+    {
+      int nlines;
+      
+      /* If there are blank lines at the end, except for a partially
+	 visible blank line at the end that is smaller than
+	 CANON_Y_UNIT, change the toolbar's height.  */
+      row = it.glyph_row - 1;
+      if (!row->displays_text_p
+	  && row->height >= CANON_Y_UNIT (f))
+	change_height_p = 1;
+
+      /* If row displays toolbar items, but is partially visible,
+	 change the toolbar's height.  */
+      if (row->displays_text_p
+	  && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
+	change_height_p = 1;
+
+      /* Resize windows as needed by changing the `toolbar-lines'
+	 frame parameter.  */
+      if (change_height_p
+	  && (nlines = toolbar_lines_needed (f),
+	      nlines != XFASTINT (w->height)))
+	{
+	  extern Lisp_Object Qtoolbar_lines;
+	  Lisp_Object frame;
+	  
+	  XSETFRAME (frame, f);
+	  clear_glyph_matrix (w->desired_matrix);
+	  Fmodify_frame_parameters (frame,
+				    Fcons (Fcons (Qtoolbar_lines,
+						  make_number (nlines)),
+					   Qnil));
+	  fonts_changed_p = 1;
+	}
+    }
+
+  return change_height_p;
+}
+
+
+/* Get information about the toolbar item which is displayed in GLYPH
+   on frame F.  Return in *PROP_IDX the index where toolbar item
+   properties start in F->current_toolbar_items.  Value is zero if
+   GLYPH doesn't display a toolbar item.  */
+
+int
+toolbar_item_info (f, glyph, prop_idx)
+     struct frame *f;
+     struct glyph *glyph;
+     int *prop_idx;
+{
+  Lisp_Object prop;
+  int success_p;
+  
+  /* Get the text property `menu-item' at pos. The value of that
+     property is the start index of this item's properties in
+     F->current_toolbar_items.  */
+  prop = Fget_text_property (make_number (glyph->charpos),
+			     Qmenu_item, f->current_toolbar_string);
+  if (INTEGERP (prop))
+    {
+      *prop_idx = XINT (prop);
+      success_p = 1;
+    }
+  else
+    success_p = 0;
+
+  return success_p;
+}
+  
+#endif /* HAVE_WINDOW_SYSTEM */
+
+
+
+/************************************************************************
+			 Horizontal scrolling
+ ************************************************************************/
+
+static int hscroll_window_tree P_ ((Lisp_Object));
+static int hscroll_windows P_ ((Lisp_Object));
+
+/* For all leaf windows in the window tree rooted at WINDOW, set their
+   hscroll value so that PT is (i) visible in the window, and (ii) so
+   that it is not within a certain margin at the window's left and
+   right border.  Value is non-zero if any window's hscroll has been
+   changed.  */
+
+static int
+hscroll_window_tree (window)
+     Lisp_Object window;
+{
+  int hscrolled_p = 0;
+  
+  while (WINDOWP (window))
+    {
+      struct window *w = XWINDOW (window);
+      
+      if (WINDOWP (w->hchild))
+	hscrolled_p |= hscroll_window_tree (w->hchild);
+      else if (WINDOWP (w->vchild))
+	hscrolled_p |= hscroll_window_tree (w->vchild);
+      else if (w->cursor.vpos >= 0)
+	{
+	  int hscroll_margin, text_area_x, text_area_y;
+	  int text_area_width, text_area_height;
+	  struct glyph_row *cursor_row = MATRIX_ROW (w->current_matrix,
+						     w->cursor.vpos);
+
+	  window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
+		      &text_area_width, &text_area_height);
+
+	  /* Scroll when cursor is inside this scroll margin.  */
+	  hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
+	  
+	  if ((XFASTINT (w->hscroll)
+	       && w->cursor.x < hscroll_margin)
+	      || (cursor_row->truncated_on_right_p
+		  && (w->cursor.x > text_area_width - hscroll_margin)))
+	    {
+	      struct it it;
+	      int hscroll;
+	      struct buffer *saved_current_buffer;
+	      int pt;
+
+	      /* Find point in a display of infinite width.  */
+	      saved_current_buffer = current_buffer;
+	      current_buffer = XBUFFER (w->buffer);
+	      
+	      if (w == XWINDOW (selected_window))
+		pt = BUF_PT (current_buffer);
+	      else
+		{
+		  pt = marker_position (w->pointm);
+		  pt = max (BEGV, pt);
+		  pt = min (ZV, pt);
+		}
+
+	      /* Move iterator to pt starting at cursor_row->start in
+		 a line with infinite width.  */
+	      init_to_row_start (&it, w, cursor_row);
+	      it.last_visible_x = INFINITY;
+	      move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
+	      current_buffer = saved_current_buffer;
+
+	      /* Center cursor in window.  */
+	      hscroll = (max (0, it.current_x - text_area_width / 2)
+			 / CANON_X_UNIT (it.f));
+
+	      /* Don't call Fset_window_hscroll if value hasn't
+		 changed because it will prevent redisplay
+		 optimizations.  */
+	      if (XFASTINT (w->hscroll) != hscroll)
+		{
+		  Fset_window_hscroll (window, make_number (hscroll));
+		  hscrolled_p = 1;
+		}
+	    }
+	}
+
+      window = w->next;
+    }
+
+  /* Value is non-zero if hscroll of any leaf window has been changed.  */
+  return hscrolled_p;
+}
+
+
+/* Set hscroll so that cursor is visible and not inside horizontal
+   scroll margins for all windows in the tree rooted at WINDOW.  See
+   also hscroll_window_tree above.  Value is non-zero if any window's
+   hscroll has been changed.  If it has, desired matrices on the frame
+   of WINDOW are cleared.  */
+
+static int
+hscroll_windows (window)
+     Lisp_Object window;
+{
+  int hscrolled_p = hscroll_window_tree (window);
+  if (hscrolled_p)
+    clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+  return hscrolled_p;
+}
+
+
+
+/************************************************************************
+				Redisplay
+ ************************************************************************/
+
+/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
+   to a non-zero value.  This is sometimes handy to have in a debugger
+   session.  */
+
+#if GLYPH_DEBUG
+
+/* Values of beg_unchanged and end_unchanged as of last call to
+   try_window_id.  */
+
+int debug_beg_unchanged, debug_end_unchanged;
+
+/* First and last unchanged row for try_window_id.  */
+
+int debug_first_unchanged_at_end_vpos;
+int debug_last_unchanged_at_beg_vpos;
+
+/* Delta vpos and y.  */
+
+int debug_dvpos, debug_dy;
+
+/* Delta in characters and bytes for try_window_id.  */
+
+int debug_delta, debug_delta_bytes;
+
+/* Values of window_end_pos and window_end_vpos at the end of
+   try_window_id.  */
+
+int debug_end_pos, debug_end_vpos;
+
+/* Append a string to W->desired_matrix->method.  FMT is a printf
+   format string.  A1...A9 are a supplement for a variable-length
+   argument list.  If trace_redisplay_p is non-zero also printf the
+   resulting string to stderr.  */
+
+static void
+debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+     struct window *w;
+     char *fmt;
+     int a1, a2, a3, a4, a5, a6, a7, a8, a9;
+{
+  char buffer[512];
+  char *method = w->desired_matrix->method;
+  int len = strlen (method);
+  int size = sizeof w->desired_matrix->method;
+  int remaining = size - len - 1;
+
+  sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  if (len && remaining)
+    {
+      method[len] = '|';
+      --remaining, ++len;
+    }
+  
+  strncpy (method + len, buffer, remaining);
+
+  if (trace_redisplay_p)
+    fprintf (stderr, "%p (%s): %s\n",
+	     w,
+	     ((BUFFERP (w->buffer)
+	       && STRINGP (XBUFFER (w->buffer)->name))
+	      ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
+	      : "no buffer"),
+	     buffer);
+}
+
+#endif /* GLYPH_DEBUG */
+
+
+/* This counter is used to clear the face cache every once in a while
+   in redisplay_internal.  It is incremented for each redisplay.
+   Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
+   cleared.  */
+
+#define CLEAR_FACE_CACHE_COUNT	10000
+static int clear_face_cache_count;
+
+/* Record the previous terminal frame we displayed.  */
+
+static struct frame *previous_terminal_frame;
+
+/* Non-zero while redisplay_internal is in progress.  */
+
+int redisplaying_p;
+
+
+/* Value is non-zero if all changes in window W, which displays
+   current_buffer, are in the text between START and END.  START is a
+   buffer position, END is given as a distance from Z.  Used in
+   redisplay_internal for display optimization.  */
+
+static INLINE int
+text_outside_line_unchanged_p (w, start, end)
+     struct window *w;
+     int start, end;
+{
+  int unchanged_p = 1;
+  
+  /* If text or overlays have changed, see where.  */
+  if (XFASTINT (w->last_modified) < MODIFF
+      || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+    {
+      /* Gap in the line?  */
+      if (GPT < start || Z - GPT < end)
+	unchanged_p = 0;
+
+      /* Changes start in front of the line, or end after it?  */
+      if (unchanged_p
+	  && (beg_unchanged < start - 1
+	      || end_unchanged < end))
+	unchanged_p = 0;
+      
+      /* If selective display, can't optimize if changes start at the
+	 beginning of the line.  */
+      if (unchanged_p
+	  && INTEGERP (current_buffer->selective_display)
+	  && XINT (current_buffer->selective_display) > 0
+	  && (beg_unchanged < start || GPT <= start))
+	unchanged_p = 0;
+    }
+
+  return unchanged_p;
+}
+
+
+/* Do a frame update, taking possible shortcuts into account.  This is
+   the main external entry point for redisplay.
+
+   If the last redisplay displayed an echo area message and that message
+   is no longer requested, we clear the echo area or bring back the
+   mini-buffer if that is in use.  */
+
+void
+redisplay ()
+{
+  redisplay_internal (0);
+}
+
+
+/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
+   response to any user action; therefore, we should preserve the echo
+   area.  (Actually, our caller does that job.)  Perhaps in the future
+   avoid recentering windows if it is not necessary; currently that
+   causes some problems.  */
 
 static void
-redisplay_windows (window, preserve_echo_area)
-     Lisp_Object window;
+redisplay_internal (preserve_echo_area)
      int preserve_echo_area;
 {
-  for (; !NILP (window); window = XWINDOW (window)->next)
-    redisplay_window (window, 0, preserve_echo_area);
-}
+  struct window *w = XWINDOW (selected_window);
+  struct frame *f = XFRAME (w->frame);
+  int pause;
+  int must_finish = 0;
+  struct text_pos tlbufpos, tlendpos;
+  int number_of_visible_frames;
+
+  /* Non-zero means redisplay has to consider all windows on all
+     frames.  Zero means, only selected_window is considered.  */
+  int consider_all_windows_p;
+  
+  TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
+
+  /* No redisplay if running in batch mode or frame is not yet fully
+     initialized, or redisplay is explicitly turned off by setting
+     Vinhibit_redisplay.  */
+  if (noninteractive
+      || !NILP (Vinhibit_redisplay)
+      || !f->glyphs_initialized_p)
+    return;
+
+  /* The flag redisplay_performed_directly_p is set by
+     direct_output_for_insert when it already did the whole screen
+     update necessary.  */
+  if (redisplay_performed_directly_p)
+    {
+      redisplay_performed_directly_p = 0;
+      if (!hscroll_windows (selected_window))
+	return;
+    }
+
+#ifdef USE_X_TOOLKIT
+  if (popup_activated ())
+    return;
+#endif
+
+  if (redisplaying_p)
+    return;
+  ++redisplaying_p;
+
+ retry:
+
+  /* If new fonts have been loaded that make a glyph matrix adjustment
+     necessary, do it.  */
+  if (fonts_changed_p)
+    {
+      adjust_glyphs (NULL);
+      ++windows_or_buffers_changed;
+      fonts_changed_p = 0;
+    }
+
+  if (! FRAME_WINDOW_P (selected_frame)
+      && previous_terminal_frame != selected_frame)
+    {
+      /* Since frames on an ASCII terminal share the same display
+	 area, displaying a different frame means redisplay the whole
+	 thing.  */
+      windows_or_buffers_changed++;
+      SET_FRAME_GARBAGED (selected_frame);
+      XSETFRAME (Vterminal_frame, selected_frame);
+    }
+  previous_terminal_frame = selected_frame;
+
+  /* Set the visible flags for all frames.  Do this before checking
+     for resized or garbaged frames; they want to know if their frames
+     are visible.  See the comment in frame.h for
+     FRAME_SAMPLE_VISIBILITY.  */
+  {
+    Lisp_Object tail, frame;
+
+    number_of_visible_frames = 0;
+
+    FOR_EACH_FRAME (tail, frame)
+      {
+	struct frame *f = XFRAME (frame);
+	
+	FRAME_SAMPLE_VISIBILITY (f);
+	if (FRAME_VISIBLE_P (f))
+	  ++number_of_visible_frames;
+	clear_desired_matrices (f);
+      }
+  }
+
+  /* Notice any pending interrupt request to change frame size.  */
+  do_pending_window_change ();
+
+  /* Clear frames marked as garbaged.  */
+  if (frame_garbaged)
+    {
+      /* Old redisplay called redraw_garbaged_frames here which in
+	 turn called redraw_frame which in turn called clear_frame.
+	 The call to clear_frame is a source of flickering.  After
+	 checking the places where SET_FRAME_GARBAGED is called, I
+	 believe a clear_frame is not necessary.  It should suffice in
+	 the new redisplay to invalidate all current matrices, and
+	 ensure a complete redisplay of all windows.  */
+      Lisp_Object tail, frame;
+      
+      FOR_EACH_FRAME (tail, frame)
+	{
+	  struct frame *f = XFRAME (frame);
+	  
+	  if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
+	    {
+	      clear_current_matrices (f);
+	      f->garbaged = 0;
+	    }
+	}
+
+      frame_garbaged = 0;
+      ++windows_or_buffers_changed;
+    }
+
+  /* Build menubar and toolbar items.  */
+  prepare_menu_bars ();
+
+  if (windows_or_buffers_changed)
+    update_mode_lines++;
+
+  /* Detect case that we need to write or remove a star in the mode line.  */
+  if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
+    {
+      w->update_mode_line = Qt;
+      if (buffer_shared > 1)
+	update_mode_lines++;
+    }
+
+  /* If %c is in the mode line, update it if needed.  */
+  if (!NILP (w->column_number_displayed)
+      /* This alternative quickly identifies a common case
+	 where no change is needed.  */
+      && !(PT == XFASTINT (w->last_point)
+	   && XFASTINT (w->last_modified) >= MODIFF
+	   && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
+      && XFASTINT (w->column_number_displayed) != current_column ())
+    w->update_mode_line = Qt; 
+
+  FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
+
+  /* The variable buffer_shared is set in redisplay_window and
+     indicates that we redisplay a buffer in different windows.  See
+     there.  */
+  consider_all_windows_p = update_mode_lines || buffer_shared > 1;
+
+  /* If specs for an arrow have changed, do thorough redisplay
+     to ensure we remove any arrow that should no longer exist.  */
+  if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
+      || ! EQ (Voverlay_arrow_string, last_arrow_string))
+    consider_all_windows_p = windows_or_buffers_changed = 1;
+
+  /* Normally the message* functions will have already displayed and
+     updated the echo area, but the frame may have been trashed, or
+     the update may have been preempted, so display the echo area
+     again here.  */
+  if (echo_area_glyphs
+      || STRINGP (echo_area_message)
+      || previous_echo_glyphs
+      || STRINGP (previous_echo_area_message))
+    {
+      echo_area_display (0);
+      must_finish = 1;
+    }
+
+  /* If showing the region, and mark has changed, we must redisplay
+     the whole window.  The assignment to this_line_start_pos prevents
+     the optimization directly below this if-statement.  */
+  if (((!NILP (Vtransient_mark_mode)
+	&& !NILP (XBUFFER (w->buffer)->mark_active))
+       != !NILP (w->region_showing))
+      || (!NILP (w->region_showing)
+	  && !EQ (w->region_showing,
+		  Fmarker_position (XBUFFER (w->buffer)->mark))))
+    CHARPOS (this_line_start_pos) = 0;
+
+  /* Optimize the case that only the line containing the cursor in the
+     selected window has changed.  Variables starting with this_ are
+     set in display_line and record information about the line
+     containing the cursor.  */
+  tlbufpos = this_line_start_pos;
+  tlendpos = this_line_end_pos;
+  if (!consider_all_windows_p
+      && CHARPOS (tlbufpos) > 0
+      && NILP (w->update_mode_line)
+      && !current_buffer->clip_changed
+      && FRAME_VISIBLE_P (XFRAME (w->frame))
+      && !FRAME_OBSCURED_P (XFRAME (w->frame))
+      /* Make sure recorded data applies to current buffer, etc.  */
+      && this_line_buffer == current_buffer
+      && current_buffer == XBUFFER (w->buffer)
+      && NILP (w->force_start)
+      /* Point must be on the line that we have info recorded about.  */
+      && PT >= CHARPOS (tlbufpos)
+      && PT <= Z - CHARPOS (tlendpos)
+      /* All text outside that line, including its final newline,
+	 must be unchanged */
+      && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
+					CHARPOS (tlendpos)))
+    {
+      if (CHARPOS (tlbufpos) > BEGV
+	  && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
+	  && (CHARPOS (tlbufpos) == ZV
+	      || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
+	/* Former continuation line has disappeared by becoming empty */
+	goto cancel;
+      else if (XFASTINT (w->last_modified) < MODIFF
+	       || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
+	       || MINI_WINDOW_P (w))
+	{
+	  /* We have to handle the case of continuation around a
+	     wide-column character (See the comment in indent.c around
+	     line 885).
+
+	     For instance, in the following case:
+
+	     --------  Insert  --------
+	     K_A_N_\\   `a'    K_A_N_a\		`X_' are wide-column chars.
+	     J_I_       ==>    J_I_		`^^' are cursors.
+	     ^^                ^^
+	     --------          --------
+
+	     As we have to redraw the line above, we should goto cancel.  */
+
+	  struct it it;
+	  int line_height_before = this_line_pixel_height;
+
+	  /* Note that start_display will handle the case that the
+	     line starting at tlbufpos is a continuation lines.  */
+	  start_display (&it, w, tlbufpos);
+
+	  /* Implementation note: It this still necessary?  */
+	  if (it.current_x != this_line_start_x)
+	    goto cancel;
+
+	  TRACE ((stderr, "trying display optimization 1\n"));
+	  w->cursor.vpos = -1;
+	  overlay_arrow_seen = 0;
+	  it.vpos = this_line_vpos;
+	  it.current_y = this_line_y;
+	  it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
+	  display_line (&it);
+
+	  /* If line contains point, is not continued,
+             and ends at same distance from eob as before, we win */
+	  if (w->cursor.vpos >= 0 
+              /* Line is not continued, otherwise this_line_start_pos
+                 would have been set to 0 in display_line.  */
+	      && CHARPOS (this_line_start_pos)
+	      /* Line ends as before.  */
+	      && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
+              /* Line has same height as before.  Otherwise other lines
+                 would have to be shifted up or down.  */
+	      && this_line_pixel_height == line_height_before)
+	    {
+ 	      /* If this is not the window's last line, we must adjust
+ 		 the charstarts of the lines below.  */
+ 	      if (it.current_y < it.last_visible_y)
+  		{
+ 		  struct glyph_row *row
+ 		    = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
+  		  int delta, delta_bytes;
+  
+  		  if (Z - CHARPOS (tlendpos) == ZV)
+		    {
+		      /* This line ends at end of (accessible part of)
+			 buffer.  There is no newline to count.  */
+		      delta = (Z
+			       - CHARPOS (tlendpos)
+			       - MATRIX_ROW_START_CHARPOS (row));
+		      delta_bytes = (Z_BYTE
+				     - BYTEPOS (tlendpos)
+				     - MATRIX_ROW_START_BYTEPOS (row));
+		    }
+  		  else
+		    {
+		      /* This line ends in a newline.  Must take
+			 account of the newline and the rest of the
+			 text that follows.  */
+		      delta = (Z
+			       - CHARPOS (tlendpos)
+			       - MATRIX_ROW_START_CHARPOS (row));
+		      delta_bytes = (Z_BYTE
+				     - BYTEPOS (tlendpos)
+				     - MATRIX_ROW_START_BYTEPOS (row));
+		    }
+  
+  		  increment_glyph_matrix_buffer_positions (w->current_matrix,
+							   this_line_vpos + 1,
+							   w->current_matrix->nrows,
+							   delta, delta_bytes);
+		}
+
+	      /* If this row displays text now but previously didn't,
+		 or vice versa, w->window_end_vpos may have to be
+		 adjusted.  */
+	      if ((it.glyph_row - 1)->displays_text_p)
+		{
+		  if (XFASTINT (w->window_end_vpos) < this_line_vpos)
+		    XSETINT (w->window_end_vpos, this_line_vpos);
+		}
+	      else if (XFASTINT (w->window_end_vpos) == this_line_vpos
+		       && this_line_vpos > 0)
+		XSETINT (w->window_end_vpos, this_line_vpos - 1);
+	      w->window_end_valid = Qnil;
+	      
+	      /* Update hint: No need to try to scroll in update_window.  */
+	      w->desired_matrix->no_scrolling_p = 1;
+
+#if GLYPH_DEBUG
+	      *w->desired_matrix->method = 0;
+	      debug_method_add (w, "optimization 1");
+#endif
+	      goto update;
+	    }
+	  else
+	    goto cancel;
+	}
+      else if (/* Cursor position hasn't changed.  */
+	       PT == XFASTINT (w->last_point)
+	       /* Make sure the cursor was last displayed
+		  in this window.  Otherwise we have to reposition it.  */
+	       && 0 <= w->cursor.vpos
+	       && XINT (w->height) > w->cursor.vpos)
+	{
+	  if (!must_finish)
+	    {
+	      do_pending_window_change ();
+
+	      /* We used to always goto end_of_redisplay here, but this 
+		 isn't enough if we have a blinking cursor.  */
+	      if (w->cursor_off_p == w->last_cursor_off_p)
+		goto end_of_redisplay;
+	    }
+	  goto update;
+	}
+      /* If highlighting the region, or if the cursor is in the echo area,
+	 then we can't just move the cursor.  */
+      else if (! (!NILP (Vtransient_mark_mode)
+		  && !NILP (current_buffer->mark_active))
+	       && (w == XWINDOW (current_buffer->last_selected_window)
+		   || highlight_nonselected_windows)
+	       && NILP (w->region_showing)
+	       && !cursor_in_echo_area)
+	{
+	  struct it it;
+	  struct glyph_row *row;
+
+	  /* Skip from tlbufpos to PT and see where it is.  Note that
+	     PT may be in invisible text.  If so, we will end at the
+	     next visible position.  */
+	  init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
+			 NULL, DEFAULT_FACE_ID);
+	  it.current_x = this_line_start_x;
+	  it.current_y = this_line_y;
+	  it.vpos = this_line_vpos;
+	  
+	  /* The call to move_it_to stops in front of PT, but
+	     moves over before-strings.  */
+	  move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+
+	  if (it.vpos == this_line_vpos
+	      && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
+		  row->enabled_p))
+	    {
+	      xassert (this_line_vpos == it.vpos);
+	      xassert (this_line_y == it.current_y);
+	      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+	      goto update;
+	    }
+	  else
+	    goto cancel;
+	}
+
+    cancel:
+      /* Text changed drastically or point moved off of line.  */
+      SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
+    }
+
+  CHARPOS (this_line_start_pos) = 0;
+  consider_all_windows_p |= buffer_shared > 1;
+  ++clear_face_cache_count;
+
+  
+  /* Build desired matrices.  If consider_all_windows_p is non-zero,
+     do it for all windows on all frames.  Otherwise do it for
+     selected_window, only.  */
+
+  if (consider_all_windows_p)
+    {
+      Lisp_Object tail, frame;
+
+      /* Clear the face cache eventually.  */
+      if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
+	{
+	  clear_face_cache (0);
+	  clear_face_cache_count = 0;
+	}
+
+      /* Recompute # windows showing selected buffer.  This will be
+	 incremented each time such a window is displayed.  */
+      buffer_shared = 0;
+
+      FOR_EACH_FRAME (tail, frame)
+	{
+	  struct frame *f = XFRAME (frame);
+	  if (FRAME_WINDOW_P (f) || f == selected_frame)
+	    {
+	      /* Mark all the scroll bars to be removed; we'll redeem
+		 the ones we want when we redisplay their windows.  */
+	      if (condemn_scroll_bars_hook)
+		(*condemn_scroll_bars_hook) (f);
+
+	      if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+		redisplay_windows (FRAME_ROOT_WINDOW (f));
+
+	      /* Any scroll bars which redisplay_windows should have
+		 nuked should now go away.  */
+	      if (judge_scroll_bars_hook)
+		(*judge_scroll_bars_hook) (f);
+	    }
+	}
+    }
+  else if (FRAME_VISIBLE_P (selected_frame)
+	   && !FRAME_OBSCURED_P (selected_frame))
+    redisplay_window (selected_window, 1);
+
+  
+  /* Compare desired and current matrices, perform output.  */
+  
+update:
+  
+  /* If fonts changed, display again.  */
+  if (fonts_changed_p)
+    goto retry;
+
+  /* Prevent various kinds of signals during display update.
+     stdio is not robust about handling signals,
+     which can cause an apparent I/O error.  */
+  if (interrupt_input)
+    unrequest_sigio ();
+  stop_polling ();
+
+  if (consider_all_windows_p)
+    {
+      Lisp_Object tail;
+
+      pause = 0;
+
+      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+	{
+	  struct frame *f;
+
+	  if (!FRAMEP (XCONS (tail)->car))
+	    continue;
+
+	  f = XFRAME (XCONS (tail)->car);
+
+	  if ((FRAME_WINDOW_P (f) || f == selected_frame)
+	      && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+	    {
+	      /* Mark all windows as to be updated.  */
+	      set_window_update_flags (XWINDOW (f->root_window), 1);
+	      pause |= update_frame (f, 0, 0);
+	      if (!pause)
+		{
+		  if (hscroll_windows (f->root_window))
+		    goto retry;
+
+		  mark_window_display_accurate (f->root_window, 1);
+		  if (frame_up_to_date_hook != 0)
+		    (*frame_up_to_date_hook) (f);
+		}
+	    }
+	}
+    }
+  else
+    {
+      if (FRAME_VISIBLE_P (selected_frame)
+	  && !FRAME_OBSCURED_P (selected_frame))
+	{
+	  XWINDOW (selected_window)->must_be_updated_p = 1;
+	  pause = update_frame (selected_frame, 0, 0);
+	  if (!pause && hscroll_windows (selected_window))
+	    goto retry;
+	}
+      else
+	pause = 0;
+
+      /* We may have called echo_area_display at the top of this
+	 function.  If the echo area is on another frame, that may
+	 have put text on a frame other than the selected one, so the
+	 above call to update_frame would not have caught it.  Catch
+	 it here.  */
+      {
+	Lisp_Object mini_window;
+	struct frame *mini_frame;
+
+	mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+	mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
+	
+	if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
+	  {
+	    XWINDOW (mini_window)->must_be_updated_p = 1;
+	    pause |= update_frame (mini_frame, 0, 0);
+	    if (!pause && hscroll_windows (mini_window))
+	      goto retry;
+	  }
+      }
+    }
+
+  /* If display was paused because of pending input, make sure we do a
+     thorough update the next time.  */
+  if (pause)
+    {
+      /* Prevent the optimization at the beginning of
+	 redisplay_internal that tries a single-line update of the
+	 line containing the cursor in the selected window.  */
+      CHARPOS (this_line_start_pos) = 0;
+
+      /* Let the overlay arrow be updated the next time.  */
+      if (!NILP (last_arrow_position))
+	{
+	  last_arrow_position = Qt;
+	  last_arrow_string = Qt;
+	}
+      
+      /* If we pause after scrolling, some rows in the current
+	 matrices of some windows are not valid.  */
+      if (!WINDOW_FULL_WIDTH_P (w)
+	  && !FRAME_WINDOW_P (XFRAME (w->frame)))
+	update_mode_lines = 1;
+    }
+
+  /* Now text on frame agrees with windows, so put info into the
+     windows for partial redisplay to follow.  */
+  if (!pause)
+    {
+      register struct buffer *b = XBUFFER (w->buffer);
+
+      unchanged_modified = BUF_MODIFF (b);
+      overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
+      beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
+      end_unchanged = BUF_Z (b) - BUF_GPT (b);
+
+      if (consider_all_windows_p)
+	mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
+      else
+	{
+	  XSETFASTINT (w->last_point, BUF_PT (b));
+	  w->last_cursor = w->cursor;
+	  w->last_cursor_off_p = w->cursor_off_p;
+
+	  b->clip_changed = 0;
+	  w->update_mode_line = Qnil;
+	  XSETFASTINT (w->last_modified, BUF_MODIFF (b));
+	  XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
+	  w->last_had_star
+	    = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
+	       ? Qt : Qnil);
+
+	  /* Record if we are showing a region, so can make sure to
+	     update it fully at next redisplay.  */
+	  w->region_showing = (!NILP (Vtransient_mark_mode)
+			       && (w == XWINDOW (current_buffer->last_selected_window)
+				   || highlight_nonselected_windows)
+			       && !NILP (XBUFFER (w->buffer)->mark_active)
+			       ? Fmarker_position (XBUFFER (w->buffer)->mark)
+			       : Qnil);
+
+	  w->window_end_valid = w->buffer;
+	  last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
+	  last_arrow_string = Voverlay_arrow_string;
+	  if (frame_up_to_date_hook != 0)
+	    (*frame_up_to_date_hook) (selected_frame);
+	}
+      
+      update_mode_lines = 0;
+      windows_or_buffers_changed = 0;
+    }
+
+  /* Start SIGIO interrupts coming again.  Having them off during the
+     code above makes it less likely one will discard output, but not
+     impossible, since there might be stuff in the system buffer here.
+     But it is much hairier to try to do anything about that.  */
+  if (interrupt_input)
+    request_sigio ();
+  start_polling ();
+
+  /* If a frame has become visible which was not before, redisplay
+     again, so that we display it.  Expose events for such a frame
+     (which it gets when becoming visible) don't call the parts of
+     redisplay constructing glyphs, so simply exposing a frame won't
+     display anything in this case.  So, we have to display these
+     frames here explicitly.  */
+  if (!pause)
+    {
+      Lisp_Object tail, frame;
+      int new_count = 0;
+
+      FOR_EACH_FRAME (tail, frame)
+	{
+	  int this_is_visible = 0;
+
+	  if (XFRAME (frame)->visible)
+	    this_is_visible = 1;
+	  FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+	  if (XFRAME (frame)->visible)
+	    this_is_visible = 1;
+
+	  if (this_is_visible)
+	    new_count++;
+	}
+
+      if (new_count != number_of_visible_frames)
+	windows_or_buffers_changed++;
+    }
+
+  /* Change frame size now if a change is pending.  */
+  do_pending_window_change ();
+
+  /* If we just did a pending size change, or have additional
+     visible frames, redisplay again.  */
+  if (windows_or_buffers_changed && !pause)
+    goto retry;
+
+ end_of_redisplay:;
+  
+  if (--redisplaying_p < 0)
+    redisplaying_p = 0;
+}
+
+
+/* Redisplay, but leave alone any recent echo area message unless
+   another message has been requested in its place.
+
+   This is useful in situations where you need to redisplay but no
+   user action has occurred, making it inappropriate for the message
+   area to be cleared.  See tracking_off and
+   wait_reading_process_input for examples of these situations.  */
+
+void
+redisplay_preserve_echo_area ()
+{
+  if (!echo_area_glyphs
+      && !STRINGP (echo_area_message)
+      && (previous_echo_glyphs
+	  || STRINGP (previous_echo_area_message)))
+    {
+      echo_area_glyphs = previous_echo_glyphs;
+      echo_area_message = previous_echo_area_message;
+      echo_area_glyphs_length = previous_echo_glyphs_length;
+      redisplay_internal (1);
+      echo_area_glyphs = NULL;
+      echo_area_message = Qnil;
+    }
+  else
+    redisplay_internal (1);
+}
+
+
+/* Mark the display of windows in the window tree rooted at WINDOW as
+   accurate or inaccurate.  If FLAG is non-zero mark display of WINDOW
+   as accurate.  If FLAG is zero arrange for WINDOW to be redisplayed
+   the next time redisplay_internal is called.  */
+
+void
+mark_window_display_accurate (window, accurate_p)
+     Lisp_Object window;
+     int accurate_p;
+{
+  struct window *w;
+  
+  for (; !NILP (window); window = w->next)
+    {
+      w = XWINDOW (window);
+
+      if (BUFFERP (w->buffer))
+	{
+	  struct buffer *b = XBUFFER (w->buffer);
+	  
+	  XSETFASTINT (w->last_modified,
+		       accurate_p ? BUF_MODIFF (b) : 0);
+	  XSETFASTINT (w->last_overlay_modified,
+		       accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
+	  w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
+			      ? Qt : Qnil);
+
+#if 0 /* I don't think this is necessary because display_line does it.
+	 Let's check it.  */
+	  /* Record if we are showing a region, so can make sure to
+	     update it fully at next redisplay.  */
+	  w->region_showing
+	    = (!NILP (Vtransient_mark_mode)
+	       && (w == XWINDOW (current_buffer->last_selected_window)
+		   || highlight_nonselected_windows)
+	       && (!NILP (b->mark_active)
+		   ? Fmarker_position (b->mark)
+		   : Qnil));
+#endif
+	  
+	  if (accurate_p)
+	    {
+	      b->clip_changed = 0;
+	      w->last_cursor = w->cursor;
+	      w->last_cursor_off_p = w->cursor_off_p;
+	      if (w == XWINDOW (selected_window))
+		w->last_point = BUF_PT (b);
+	      else
+		w->last_point = XMARKER (w->pointm)->charpos;
+	    }
+	}
+
+      w->window_end_valid = w->buffer;
+      w->update_mode_line = Qnil;
+
+      if (!NILP (w->vchild))
+	mark_window_display_accurate (w->vchild, accurate_p);
+      if (!NILP (w->hchild))
+	mark_window_display_accurate (w->hchild, accurate_p);
+    }
+
+  if (accurate_p)
+    {
+      last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
+      last_arrow_string = Voverlay_arrow_string;
+    }
+  else
+    {
+      /* Force a thorough redisplay the next time by setting
+	 last_arrow_position and last_arrow_string to t, which is
+	 unequal to any useful value of Voverlay_arrow_... */
+      last_arrow_position = Qt;
+      last_arrow_string = Qt;
+    }
+}
+
 
 /* Return value in display table DP (Lisp_Char_Table *) for character
    C.  Since a display table doesn't have any parent, we don't have to
    follow parent.  Do not call this function directly but use the
    macro DISP_CHAR_VECTOR.  */
+
 Lisp_Object
 disp_char_vector (dp, c)
      struct Lisp_Char_Table *dp;
@@ -1728,18 +7046,22 @@
   int code[4], i;
   Lisp_Object val;
 
-  if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]);
+  if (SINGLE_BYTE_CHAR_P (c))
+    return (dp->contents[c]);
   
   SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
   if (code[0] != CHARSET_COMPOSITION)
     {
-      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
+      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] by 128 to get a correct index.  */
   code[0] += 128;
   code[3] = -1;		/* anchor */
 
@@ -1749,105 +7071,567 @@
       if (!SUB_CHAR_TABLE_P (val))
 	return (NILP (val) ? dp->defalt : val);
     }
-  /* Here, VAL is a sub char table.  We return the default value of it.  */
+  
+  /* Here, val is a sub char table.  We return the default value of
+     it.  */
   return (dp->defalt);
 }
 
-/* Redisplay window WINDOW and its subwindows.  */
+
+
+/***********************************************************************
+			   Window Redisplay
+ ***********************************************************************/
+
+/* Redisplay all leaf windows in the window tree rooted at WINDOW.  */
+
+static void
+redisplay_windows (window)
+     Lisp_Object window;
+{
+  while (!NILP (window))
+    {
+      struct window *w = XWINDOW (window);
+      
+      if (!NILP (w->hchild))
+	redisplay_windows (w->hchild);
+      else if (!NILP (w->vchild))
+	redisplay_windows (w->vchild);
+      else
+	redisplay_window (window, 0);
+
+      window = w->next;
+    }
+}
+
+
+/* Set cursor position of W.  PT is assumed to be displayed in ROW.
+   DELTA is the number of bytes by which positions recorded in ROW
+   differ from current buffer positions.  */
+
+void
+set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
+     struct window *w;
+     struct glyph_row *row;
+     struct glyph_matrix *matrix;
+     int delta, delta_bytes, dy, dvpos;
+{
+  struct glyph *glyph = row->glyphs[TEXT_AREA];
+  struct glyph *end = glyph + row->used[TEXT_AREA];
+  int x = row->x;
+  int pt_old = PT - delta;
+
+  /* Skip over glyphs not having an object at the start of the row.
+     These are special glyphs like truncation marks on terminal
+     frames.  */
+  if (row->displays_text_p)
+    while (glyph < end
+	   && !glyph->object
+	   && glyph->charpos < 0)
+      {
+	x += glyph->pixel_width;
+	++glyph;
+      }
+
+  while (glyph < end
+	 && glyph->object
+	 && (!BUFFERP (glyph->object)
+	     || glyph->charpos < pt_old))
+    {
+      x += glyph->pixel_width;
+      ++glyph;
+    }
+
+  w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
+  w->cursor.x = x;
+  w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
+  w->cursor.y = row->y + dy;
+
+  if (w == XWINDOW (selected_window))
+    {
+      if (!row->continued_p
+	  && !MATRIX_ROW_CONTINUATION_LINE_P (row)
+	  && row->x == 0)
+	{
+	  this_line_buffer = XBUFFER (w->buffer);
+	  
+	  CHARPOS (this_line_start_pos)
+	    = MATRIX_ROW_START_CHARPOS (row) + delta;
+	  BYTEPOS (this_line_start_pos)
+	    = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
+	  
+	  CHARPOS (this_line_end_pos)
+	    = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
+	  BYTEPOS (this_line_end_pos)
+	    = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
+	  
+	  this_line_y = w->cursor.y;
+	  this_line_pixel_height = row->height;
+	  this_line_vpos = w->cursor.vpos;
+	  this_line_start_x = row->x;
+	}
+      else
+	CHARPOS (this_line_start_pos) = 0;
+    }
+}
+
+
+/* Run window scroll functions, if any, for WINDOW with new window
+   start STARTP.  Sets the window start of WINDOW to that position.  */
+
+static INLINE struct text_pos
+run_window_scroll_functions (window, startp)
+     Lisp_Object window;
+     struct text_pos startp;
+{
+  struct window *w = XWINDOW (window);
+  SET_MARKER_FROM_TEXT_POS (w->start, startp);
+  
+  if (!NILP (Vwindow_scroll_functions))
+    {
+      run_hook_with_args_2 (Qwindow_scroll_functions, window, 
+			    make_number (CHARPOS (startp)));
+      SET_TEXT_POS_FROM_MARKER (startp, w->start);
+    }
+
+  return startp;
+}
+
+
+/* Modify the desired matrix of window W and W->vscroll so that the
+   line containing the cursor is fully visible.  */
 
 static void
-redisplay_window (window, just_this_one, preserve_echo_area)
+make_cursor_line_fully_visible (w)
+     struct window *w;
+{
+  struct glyph_matrix *matrix;
+  struct glyph_row *row;
+  int top_line_height;
+  
+  /* It's not always possible to find the cursor, e.g, when a window
+     is full of overlay strings.  Don't do anything in that case.  */
+  if (w->cursor.vpos < 0)
+    return;
+  
+  matrix = w->desired_matrix;
+  row = MATRIX_ROW (matrix, w->cursor.vpos);
+
+  /* If row->y == top y of window display area, the window isn't tall
+     enough to display a single line.  There is nothing we can do
+     about it.  */
+  top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+  if (row->y == top_line_height)
+    return;
+
+  if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
+    {
+      int dy = row->height - row->visible_height;
+      w->vscroll = 0;
+      w->cursor.y += dy;
+      shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
+    }
+  else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
+    {
+      int dy = - (row->height - row->visible_height);
+      w->vscroll = dy;
+      w->cursor.y += dy;
+      shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
+    }
+
+  /* When we change the cursor y-position of the selected window,
+     change this_line_y as well so that the display optimization for
+     the cursor line of the selected window in redisplay_internal uses
+     the correct y-position.  */
+  if (w == XWINDOW (selected_window))
+    this_line_y = w->cursor.y;
+}
+
+
+/* Try scrolling PT into view in window WINDOW.  JUST_THIS_ONE_P
+   non-zero means only WINDOW is redisplayed in redisplay_internal.
+   TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
+   in redisplay_window to bring a partially visible line into view in
+   the case that only the cursor has moved.
+
+   Value is
+
+   1	if scrolling succeeded
+    
+   0	if scrolling didn't find point.
+   
+   -1	if new fonts have been loaded so that we must interrupt
+   redisplay, adjust glyph matrices, and try again.  */
+
+static int
+try_scrolling (window, just_this_one_p, scroll_conservatively,
+	       scroll_step, temp_scroll_step)
      Lisp_Object window;
-     int just_this_one, preserve_echo_area;
-{
-  register struct window *w = XWINDOW (window);
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
+     int just_this_one_p;
+     int scroll_conservatively, scroll_step;
+     int temp_scroll_step;
+{
+  struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (w->frame);
+  struct text_pos scroll_margin_pos;
+  struct text_pos pos;
+  struct text_pos startp;
+  struct it it;
+  Lisp_Object window_end;
+  int this_scroll_margin;
+  int dy = 0;
+  int scroll_max;
+  int line_height, rc;
+  int amount_to_scroll = 0;
+  Lisp_Object aggressive;
   int height;
-  int lpoint = PT;
-  int lpoint_byte = PT_BYTE;
+
+#if GLYPH_DEBUG
+  debug_method_add (w, "try_scrolling");
+#endif
+
+  SET_TEXT_POS_FROM_MARKER (startp, w->start);
+  
+  /* Compute scroll margin height in pixels.  We scroll when point is
+     within this distance from the top or bottom of the window.  */
+  if (scroll_margin > 0)
+    {
+      this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
+      this_scroll_margin *= CANON_Y_UNIT (f);
+    }
+  else
+    this_scroll_margin = 0;
+
+  /* Compute how much we should try to scroll maximally to bring point
+     into view.  */
+  if (scroll_step)
+    scroll_max = scroll_step;
+  else if (scroll_conservatively)
+    scroll_max = scroll_conservatively;
+  else if (temp_scroll_step)
+    scroll_max = temp_scroll_step;
+  else if (NUMBERP (current_buffer->scroll_down_aggressively)
+	   || NUMBERP (current_buffer->scroll_up_aggressively))
+    /* We're trying to scroll because of aggressive scrolling
+       but no scroll_step is set.  Choose an arbitrary one.  Maybe
+       there should be a variable for this.  */
+    scroll_max = 10;
+  else
+    scroll_max = 0;
+  scroll_max *= CANON_Y_UNIT (f);
+
+  /* Decide whether we have to scroll down.  Start at the window end
+     and move this_scroll_margin up to find the position of the scroll
+     margin.  */
+  window_end = Fwindow_end (window, Qt);
+  CHARPOS (scroll_margin_pos) = XINT (window_end);
+  BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
+  if (this_scroll_margin)
+    {
+      start_display (&it, w, scroll_margin_pos);
+      move_it_vertically (&it, - this_scroll_margin);
+      scroll_margin_pos = it.current.pos;
+    }
+
+  if (PT >= CHARPOS (scroll_margin_pos))
+    {
+      int y0;
+      
+      /* Point is in the scroll margin at the bottom of the window, or
+	 below.  Compute a new window start that makes point visible.  */
+      
+      /* Compute the distance from the scroll margin to PT.
+	 Give up if the distance is greater than scroll_max.  */
+      start_display (&it, w, scroll_margin_pos);
+      y0 = it.current_y;
+      move_it_to (&it, PT, 0, it.last_visible_y, -1,
+		  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+      line_height = (it.max_ascent + it.max_descent
+		     ? it.max_ascent + it.max_descent
+		     : last_height);
+      dy = it.current_y + line_height - y0;
+      if (dy > scroll_max)
+	return 0;
+      
+      /* Move the window start down.  If scrolling conservatively,
+	 move it just enough down to make point visible.  If
+	 scroll_step is set, move it down by scroll_step.  */
+      start_display (&it, w, startp);
+
+      if (scroll_conservatively)
+	amount_to_scroll = dy;
+      else if (scroll_step || temp_scroll_step)
+	amount_to_scroll = scroll_max;
+      else
+	{
+	  aggressive = current_buffer->scroll_down_aggressively;
+	  height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
+		    - WINDOW_DISPLAY_TOP_LINE_HEIGHT (w));
+	  if (NUMBERP (aggressive))
+	    amount_to_scroll = XFLOATINT (aggressive) * height;
+	}
+
+      if (amount_to_scroll <= 0)
+	return 0;
+
+      move_it_vertically (&it, amount_to_scroll);
+      startp = it.current.pos;
+    }
+  else
+    {
+      /* See if point is inside the scroll margin at the top of the
+         window.  */
+      scroll_margin_pos = startp;
+      if (this_scroll_margin)
+	{
+	  start_display (&it, w, startp);
+	  move_it_vertically (&it, this_scroll_margin);
+	  scroll_margin_pos = it.current.pos;
+	}
+
+      if (PT < CHARPOS (scroll_margin_pos))
+	{
+	  /* Point is in the scroll margin at the top of the window or
+	     above what is displayed in the window.  */
+	  int y0;
+	  
+	  /* Compute the vertical distance from PT to the scroll
+	     margin position.  Give up if distance is greater than
+	     scroll_max.  */
+	  SET_TEXT_POS (pos, PT, PT_BYTE);
+	  start_display (&it, w, pos);
+	  y0 = it.current_y;
+	  move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
+		      it.last_visible_y, -1,
+		      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+	  dy = it.current_y - y0;
+	  if (dy > scroll_max)
+	    return 0;
+	  
+	  /* Compute new window start.  */
+	  start_display (&it, w, startp);
+	  
+	  if (scroll_conservatively)
+	    amount_to_scroll = dy;
+	  else if (scroll_step || temp_scroll_step)
+	    amount_to_scroll = scroll_max;
+	  else
+	    {
+	      aggressive = current_buffer->scroll_up_aggressively;
+	      height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
+			- WINDOW_DISPLAY_TOP_LINE_HEIGHT (w));
+	      if (NUMBERP (aggressive))
+		amount_to_scroll = XFLOATINT (aggressive) * height;
+	    }
+
+	  if (amount_to_scroll <= 0)
+	    return 0;
+	  
+	  move_it_vertically (&it, - amount_to_scroll);
+	  startp = it.current.pos;
+	}
+    }
+
+  /* Run window scroll functions.  */
+  startp = run_window_scroll_functions (window, startp);
+
+  /* Display the window.  Give up if new fonts are loaded, or if point
+     doesn't appear.  */
+  if (!try_window (window, startp))
+    rc = -1;
+  else if (w->cursor.vpos < 0)
+    {
+      clear_glyph_matrix (w->desired_matrix);
+      rc = 0;
+    }
+  else
+    {
+      /* Maybe forget recorded base line for line number display.  */
+      if (!just_this_one_p 
+	  || current_buffer->clip_changed
+	  || beg_unchanged < CHARPOS (startp))
+	w->base_line_number = Qnil;
+      
+      /* If cursor ends up on a partially visible line, shift display
+	 lines up or down.  */
+      make_cursor_line_fully_visible (w);
+      rc = 1;
+    }
+
+  return rc;
+}
+
+
+/* Compute a suitable window start for window W if display of W starts
+   on a continuation line.  Value is non-zero if a new window start
+   was computed.
+
+   The new window start will be computed, based on W's width, starting
+   from the start of the continued line.  It is the start of the
+   screen line with the minimum distance from the old start W->start.  */
+
+static int
+compute_window_start_on_continuation_line (w)
+     struct window *w;
+{
+  struct text_pos pos, start_pos;
+  int window_start_changed_p = 0;
+
+  SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
+
+  /* If window start is on a continuation line...  Window start may be
+     < BEGV in case there's invisible text at the start of the 
+     buffer (M-x rmail, for example).  */
+  if (CHARPOS (start_pos) > BEGV
+      && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
+    {
+      struct it it;
+      struct glyph_row *row;
+      
+      /* Find the start of the continued line.  This should be fast
+	 because scan_buffer is fast (newline cache).  */
+      row = w->desired_matrix->rows + (WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0);
+      init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
+		     row, DEFAULT_FACE_ID);
+      reseat_at_previous_visible_line_start (&it);
+
+      /* If the line start is "too far" away from the window start,
+         say it takes too much time to compute a new window start.  */
+      if (CHARPOS (start_pos) - IT_CHARPOS (it)
+	  < XFASTINT (w->height) * XFASTINT (w->width))
+	{
+	  int min_distance, distance;
+	  
+	  /* Move forward by display lines to find the new window
+	     start.  If window width was enlarged, the new start can
+	     be expected to be > the old start.  If window width was
+	     decreased, the new window start will be < the old start.
+	     So, we're looking for the display line start with the
+	     minimum distance from the old window start.  */
+	  pos = it.current.pos;
+	  min_distance = INFINITY;
+	  while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
+		 distance < min_distance)
+	    {
+	      min_distance = distance;
+	      pos = it.current.pos;
+	      move_it_by_lines (&it, 1, 0);
+	    }
+	  
+	  /* Set the window start there.  */
+	  SET_MARKER_FROM_TEXT_POS (w->start, pos);
+	  window_start_changed_p = 1;
+	}
+    }
+  
+  return window_start_changed_p;
+}
+
+
+/* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
+   selected_window is redisplayed.  */
+
+static void
+redisplay_window (window, just_this_one_p)
+     Lisp_Object window;
+     int just_this_one_p;
+{
+  struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (w->frame);
+  struct buffer *buffer = XBUFFER (w->buffer);
   struct buffer *old = current_buffer;
-  register int width = window_internal_width (w) - 1;
-  register int startp, startp_byte;
-  register int hscroll = XINT (w->hscroll);
-  struct position pos;
-  int opoint = PT;
-  int opoint_byte = PT_BYTE;
+  struct text_pos lpoint, opoint, startp;
+  int update_mode_line;
   int tem;
-  int update_mode_line;
-  struct Lisp_Char_Table *dp = window_display_table (w);
+  struct it it;
+  /* Record it now because it's overwritten.  */
+  int current_matrix_up_to_date_p = 0;
   int really_switched_buffer = 0;
+  int temp_scroll_step = 0;
   int count = specpdl_ptr - specpdl;
 
-  if (Z == Z_BYTE && lpoint != lpoint_byte)
-    abort ();
-  if (lpoint_byte < lpoint)
-    abort ();
-
-  if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
-
-  /* If this is a combination window, do its children; that's all.  */
-
-  if (!NILP (w->vchild))
-    {
-      redisplay_windows (w->vchild, preserve_echo_area);
-      return;
-    }
-  if (!NILP (w->hchild))
-    {
-      redisplay_windows (w->hchild, preserve_echo_area);
-      return;
-    }
-  if (NILP (w->buffer))
-    abort ();
+  SET_TEXT_POS (lpoint, PT, PT_BYTE);
+  opoint = lpoint;
+
+  /* W must be a leaf window here.  */
+  xassert (!NILP (w->buffer));
+#if GLYPH_DEBUG
+  *w->desired_matrix->method = 0;
+#endif
 
   specbind (Qinhibit_point_motion_hooks, Qt);
-
-  height = window_internal_height (w);
-  update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
-  if (XBUFFER (w->buffer)->clip_changed)
-    update_mode_line = 1;
+  
+  /* Has the mode line to be updated?  */ 
+  update_mode_line = (!NILP (w->update_mode_line)
+		      || update_mode_lines
+		      || buffer->clip_changed);
 
   if (MINI_WINDOW_P (w))
     {
-      if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
-	/* We've already displayed the echo area glyphs in this window.  */
-	goto finish_scroll_bars;
+      if (w == XWINDOW (echo_area_window)
+	  && (echo_area_glyphs
+	      || STRINGP (echo_area_message)))
+	{
+	  if (update_mode_line)
+	    /* We may have to update a tty frame's menu bar or a
+	       toolbar.  Example `M-x C-h C-h C-g'.  */
+	    goto finish_menu_bars;
+	  else
+	    /* We've already displayed the echo area glyphs in this window.  */
+	    goto finish_scroll_bars;
+	}
       else if (w != XWINDOW (minibuf_window))
 	{
-	  /* This is a minibuffer, but it's not the currently active one,
-	     so clear it.  */
-	  int vpos = XFASTINT (w->top);
-	  int i;
-
-	  for (i = 0; i < height; i++)
-	    {
-	      get_display_line (f, vpos + i, 0);
-	      display_string (w, vpos + i, "", 0, 
-			      FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-			      0, 1, 0, width, 0);
-	    }
-	  
+	  /* W is a mini-buffer window, but it's not the currently
+	     active one, so clear it.  */
+	  int yb = window_text_bottom_y (w);
+	  struct glyph_row *row;
+	  int y;
+
+	  for (y = 0, row = w->desired_matrix->rows;
+	       y < yb;
+	       y += row->height, ++row)
+	    blank_row (w, row, y);
 	  goto finish_scroll_bars;
 	}
     }
 
-  /* Otherwise set up data on this window; select its buffer and point value */
-
+  /* Otherwise set up data on this window; select its buffer and point
+     value.  */
   if (update_mode_line)
-    /* Really select the buffer, for the sake of buffer-local variables.  */
-    {
+    {
+      /* Really select the buffer, for the sake of buffer-local
+         variables.  */
       set_buffer_internal_1 (XBUFFER (w->buffer));
       really_switched_buffer = 1;
     }
   else
     set_buffer_temp (XBUFFER (w->buffer));
-
-  opoint = PT;
-  opoint_byte = PT_BYTE;
-
-  if (Z == Z_BYTE && opoint != opoint_byte)
+  SET_TEXT_POS (opoint, PT, PT_BYTE);
+
+  current_matrix_up_to_date_p
+    = (!NILP (w->window_end_valid)
+       && !current_buffer->clip_changed
+       && XFASTINT (w->last_modified) >= MODIFF
+       && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+
+  /* When windows_or_buffers_changed is non-zero, we can't rely on
+     the window end being valid, so set it to nil there.  */
+  if (windows_or_buffers_changed)
+    {
+      /* If window starts on a continuation line, maybe adjust the
+	 window start in case the window's width changed.  */
+      if (XMARKER (w->start)->buffer == current_buffer)
+	compute_window_start_on_continuation_line (w);
+      
+      w->window_end_valid = Qnil;
+    }
+
+  /* Some sanity checks.  */
+  CHECK_WINDOW_END (w);
+  if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
     abort ();
-  if (opoint_byte < opoint)
+  if (BYTEPOS (opoint) < CHARPOS (opoint))
     abort ();
 
   /* If %c is in mode line, update it if needed.  */
@@ -1860,10 +7644,9 @@
       && XFASTINT (w->column_number_displayed) != current_column ())
     update_mode_line = 1; 
 
-  /* Count number of windows showing the selected buffer.
-     An indirect buffer counts as its base buffer.  */
-
-  if (!just_this_one)
+  /* Count number of windows showing the selected buffer.  An indirect
+     buffer counts as its base buffer.  */
+  if (!just_this_one_p)
     {
       struct buffer *current_base, *window_base;
       current_base = current_buffer;
@@ -1876,9 +7659,8 @@
 	buffer_shared++;
     }
 
-  /* POINT refers normally to the selected window.
-     For any other window, set up appropriate value.  */
-
+  /* Point refers normally to the selected window.  For any other
+     window, set up appropriate value.  */
   if (!EQ (window, selected_window))
     {
       int new_pt = XMARKER (w->pointm)->charpos;
@@ -1895,13 +7677,14 @@
 	  new_pt_byte = ZV_BYTE;
 	  set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
 	}
+      
       /* We don't use SET_PT so that the point-motion hooks don't run.  */
       TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
     }
 
   /* If any of the character widths specified in the display table
-     have changed, invalidate the width run cache.  It's true that this
-     may be a bit late to catch such changes, but the rest of
+     have changed, invalidate the width run cache.  It's true that
+     this may be a bit late to catch such changes, but the rest of
      redisplay goes (non-fatally) haywire when the display table is
      changed, so why should we worry about doing any better?  */
   if (current_buffer->width_run_cache)
@@ -1922,32 +7705,18 @@
   if (XMARKER (w->start)->buffer != current_buffer)
     goto recenter;
 
-  startp = marker_position (w->start);
-  startp_byte = marker_byte_position (w->start);
+  SET_TEXT_POS_FROM_MARKER (startp, w->start);
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
-  if (!NILP (w->optional_new_start)
-      && startp >= BEGV && startp <= ZV)
+  if (!NILP (w->optional_new_start))
     {
       w->optional_new_start = Qnil;
-      /* Check whether this start pos is usable given where point is.  */
-
-      pos = *compute_motion (startp, 0,
-			     (((EQ (window, minibuf_window)
-				&& startp == BEG)
-			       ? minibuf_prompt_width : 0)
-			      + (hscroll ? 1 - hscroll : 0)),
-			     0,
-			     PT, height, 
-			     /* BUG FIX: See the comment of
-                                Fpos_visible_in_window_p (window.c).  */
-			     - (1 << (BITS_PER_SHORT - 1)),
-			     width, hscroll,
-			     pos_tab_offset (w, startp, startp_byte), w);
-      /* If PT does fit on the screen, we will use this start pos,
-	 so do so by setting force_start.  */
-      if (pos.bufpos == PT)
+      /* This takes a mini-buffer prompt into account.  */
+      start_display (&it, w, startp);
+      move_it_to (&it, PT, 0, it.last_visible_y, -1,
+		  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+      if (IT_CHARPOS (it) == PT)
 	w->force_start = Qt;
     }
 
@@ -1956,10 +7725,14 @@
   if (!NILP (w->force_start))
     {
       w->force_start = Qnil;
+      w->vscroll = 0;
+      w->window_end_valid = Qnil;
+
       /* Forget any recorded base line for line number display.  */
-      w->base_line_number = Qnil;
-      /* The old bottom-of-screen position is no longer valid.  */
-      w->window_end_valid = Qnil;
+      if (!current_matrix_up_to_date_p
+	  || current_buffer->clip_changed)
+	w->base_line_number = Qnil;
+
       /* Redisplay the mode line.  Select the buffer properly for that.
 	 Also, run the hook window-scroll-functions
 	 because we have scrolled.  */
@@ -1970,259 +7743,335 @@
       if (!update_mode_line
 	  || ! NILP (Vwindow_scroll_functions))
 	{
-	  Lisp_Object temp[3];
-
 	  if (!really_switched_buffer)
 	    {
 	      set_buffer_temp (old);
 	      set_buffer_internal_1 (XBUFFER (w->buffer));
+	      really_switched_buffer = 1;
 	    }
-	  really_switched_buffer = 1;
+	  
 	  update_mode_line = 1;
 	  w->update_mode_line = Qt;
-	  if (! NILP (Vwindow_scroll_functions))
-	    {
-	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				    make_number (startp));
-	      startp = marker_position (w->start);
-	      startp_byte = marker_byte_position (w->start);
-	    }
-	}
+	  startp = run_window_scroll_functions (window, startp);
+	}
+      
       XSETFASTINT (w->last_modified, 0);
       XSETFASTINT (w->last_overlay_modified, 0);
-      if (startp < BEGV) startp = BEGV, startp_byte = BEGV_BYTE;
-      if (startp > ZV)   startp = ZV, startp = ZV_BYTE;
-      try_window (window, startp);
-      if (cursor_vpos < 0)
-	{
-	  /* If point does not appear, move point so it does appear */
-	  pos = *compute_motion (startp, 0,
-				 (((EQ (window, minibuf_window)
-				    && startp == BEG)
-				   ? minibuf_prompt_width : 0)
-				  + (hscroll ? 1 - hscroll : 0)),
-				 0,
-				 ZV, height / 2,
-				 - (1 << (BITS_PER_SHORT - 1)),
-				 width, hscroll,
-				 pos_tab_offset (w, startp, startp_byte),
-				 w);
-	  TEMP_SET_PT_BOTH (pos.bufpos, pos.bytepos);
+      if (CHARPOS (startp) < BEGV)
+	SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
+      else if (CHARPOS (startp) > ZV)
+	SET_TEXT_POS (startp, ZV, ZV_BYTE);
+      
+      /* Redisplay, then check if cursor has been set during the 
+	 redisplay.  Give up if new fonts were loaded.  */
+      if (!try_window (window, startp))
+	{
+	  w->force_start = Qt;
+	  clear_glyph_matrix (w->desired_matrix);
+	  goto restore_buffers;
+	}
+
+      if (w->cursor.vpos < 0)
+	{
+	  /* If point does not appear, or on a line that is not fully
+	     visible, move point so it does appear.  The desired
+	     matrix has been built above, so we can use it.  */
+	  int height = window_box_height (w) / 2;
+	  struct glyph_row *row = MATRIX_ROW (w->desired_matrix, 0);
+	  
+	  while (row->y < height)
+	    ++row;
+
+	  TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
+			    MATRIX_ROW_START_BYTEPOS (row));
+
 	  if (w != XWINDOW (selected_window))
 	    set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
-	  else
-	    {
-	      if (current_buffer == old)
-		{
-		  lpoint = PT;
-		  lpoint_byte = PT_BYTE;
-		}
-	      FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
-				    + minmax (0, pos.hpos, width));
-	      FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
-	    }
-	  /* If we are highlighting the region,
-	     then we just changed the region, so redisplay to show it.  */
+	  else if (current_buffer == old)
+	    SET_TEXT_POS (lpoint, PT, PT_BYTE);
+
+	  set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
+	  
+	  /* If we are highlighting the region, then we just changed
+	     the region, so redisplay to show it.  */
 	  if (!NILP (Vtransient_mark_mode)
 	      && !NILP (current_buffer->mark_active))
 	    {
-	      cancel_my_columns (XWINDOW (window));
-	      try_window (window, startp);
+	      clear_glyph_matrix (w->desired_matrix);
+	      if (!try_window (window, startp))
+		goto restore_buffers;
 	    }
 	}
+
+      make_cursor_line_fully_visible (w);
+#if GLYPH_DEBUG
+      debug_method_add (w, "forced window start");
+#endif
       goto done;
     }
 
-  /* Handle case where text has not changed, only point,
-     and it has not moved off the frame.  */
-
-  /* This code is not used for minibuffer for the sake of
-     the case of redisplaying to replace an echo area message;
-     since in that case the minibuffer contents per se are usually unchanged.
-     This code is of no real use in the minibuffer since
-     the handling of this_line_bufpos, etc.,
-     in redisplay handles the same cases.  */
-
-  if (XFASTINT (w->last_modified) >= MODIFF
-      && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF
-      && PT >= startp && !current_buffer->clip_changed
-      && (just_this_one || WINDOW_FULL_WIDTH_P (w))
+  /* Handle case where text has not changed, only point, and it has
+     not moved off the frame.  */
+  if (current_matrix_up_to_date_p
+      /* Point may be in this window.  */
+      && PT >= CHARPOS (startp)
+      /* If we don't check this, we are called to move the cursor in a
+	 horizontally split window with a current matrix that doesn't
+	 fit the display.  */
+      && !windows_or_buffers_changed
+      /* Selective display hasn't changed.  */
+      && !current_buffer->clip_changed
       /* If force-mode-line-update was called, really redisplay;
 	 that's how redisplay is forced after e.g. changing
 	 buffer-invisibility-spec.  */
       && NILP (w->update_mode_line)
-      /* Can't use this case if highlighting a region.  */
-      && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
+      /* Can't use this case if highlighting a region.  When a 
+         region exists, cursor movement has to do more than just
+         set the cursor.  */
+      && !(!NILP (Vtransient_mark_mode)
+	   && !NILP (current_buffer->mark_active))
       && NILP (w->region_showing)
-      /* If end pos is out of date, scroll bar and percentage will be wrong */
+      /* Right after splitting windows, last_point may be nil.  */
+      && INTEGERP (w->last_point)
+      /* This code is not used for mini-buffer for the sake of the case
+	 of redisplaying to replace an echo area message; since in
+	 that case the mini-buffer contents per se are usually
+	 unchanged.  This code is of no real use in the mini-buffer
+	 since the handling of this_line_start_pos, etc., in redisplay
+	 handles the same cases.  */
+      && !EQ (window, minibuf_window)
+      /* When splitting windows or for new windows, it happens that
+	 redisplay is called with a nil window_end_vpos or one being
+	 larger than the window.  This should really be fixed in
+	 window.c.  I don't have this on my list, now, so we do
+	 approximately the same as the old redisplay code.  --gerd.  */
       && INTEGERP (w->window_end_vpos)
-      && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
-      && !EQ (window, minibuf_window)
-      && (!MARKERP (Voverlay_arrow_position)
+      && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
+      && (FRAME_WINDOW_P (f)
+	  || !MARKERP (Voverlay_arrow_position)
 	  || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
     {
-      /* All positions in this clause are relative to the window edge.  */
-
-      int this_scroll_margin = scroll_margin;
-      int last_point_y = XFASTINT (w->last_point_y) - XINT (w->top);
-      int last_point_x = (XFASTINT (w->last_point_x) - WINDOW_LEFT_MARGIN (w));
-
-      /* Find where PT is located now on the frame.  */
-      /* Check just_this_one as a way of verifying that the 
-	 window edges have not changed.  */
-      if (PT == XFASTINT (w->last_point) && just_this_one
-	  /* If CURSOR_IN_ECHO_AREA, last_point_x and last_point_y
-	     refer to the echo area and are not related to this window.  */
-	  && ! cursor_in_echo_area)
-	{
-	  pos.hpos = last_point_x;
-	  pos.vpos = last_point_y;
-	  pos.bufpos = PT;
-	}
-      else if (PT > XFASTINT (w->last_point)
-	       && ! cursor_in_echo_area
-	       && XFASTINT (w->last_point) > startp && just_this_one
-	       /* We can't use this if point is in the left margin of a
-		  hscrolled window, because w->last_point_x has been
-		  clipped to the window edges.  */
-	       && !(last_point_x <= 0 && hscroll))
-	{
-	  int last_point = XFASTINT (w->last_point);
-	  int last_point_byte = CHAR_TO_BYTE (last_point);
-	  int tab_offset = (pos_tab_offset (w, last_point, last_point_byte)
-			    - (last_point_x + hscroll - !! hscroll));
-
-	  pos = *compute_motion (last_point, last_point_y, last_point_x, 1,
-				 PT, height,
-				 /* BUG FIX: See the comment of	
-				    Fpos_visible_in_window_p (window.c).  */
-				 - (1 << (BITS_PER_SHORT - 1)),
-				 width, hscroll,
-				 tab_offset,
-				 w);
-	}
-      else
-	{
-	  pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
-				 PT, height,
-				 /* BUG FIX: See the comment of
-				    Fpos_visible_in_window_p (window.c).  */
-				 - (1 << (BITS_PER_SHORT - 1)),
-				 width, hscroll,
-				 pos_tab_offset (w, startp, startp_byte),
-				 w);
-	}
-
-      /* Don't use a scroll margin that is negative or too large.  */
-      if (this_scroll_margin < 0)
-	this_scroll_margin = 0;
-
-      if (XINT (w->height) < 4 * scroll_margin)
-	this_scroll_margin = XINT (w->height) / 4;
-
-      /* If point fits on the screen, and not within the scroll margin,
-	 we are ok.  */
-      if (pos.vpos < height - this_scroll_margin
-	  && (pos.vpos >= this_scroll_margin || startp == BEGV))
-	{
-	  /* Ok, point is still on frame */
-	  if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
+      int this_scroll_margin;
+      struct glyph_row *row;
+      int scroll_p;
+
+#if GLYPH_DEBUG
+      debug_method_add (w, "cursor movement");
+#endif
+
+      /* Scroll if point within this distance from the top or bottom
+	 of the window.  This is a pixel value.  */
+      this_scroll_margin = max (0, scroll_margin);
+      this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
+      this_scroll_margin *= CANON_Y_UNIT (f);
+
+      /* Start with the row the cursor was displayed during the last
+	 not paused redisplay.  Give up if that row is not valid.  */
+      if (w->last_cursor.vpos >= w->current_matrix->nrows)
+	goto try_to_scroll;
+      row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
+      if (row->mode_line_p)
+	++row;
+      if (!row->enabled_p)
+	goto try_to_scroll;
+
+      scroll_p = 0;
+      if (PT > XFASTINT (w->last_point))
+	{
+	  /* Point has moved forward.  */
+	  int last_y = window_text_bottom_y (w) - this_scroll_margin;
+	  
+	  while ((MATRIX_ROW_END_CHARPOS (row) < PT
+		  /* The end position of a row equals the start
+		     position of the next row.  If PT is there, we
+		     would rather display it in the next line, except
+		     when this line ends in ZV.  */
+		  || (MATRIX_ROW_END_CHARPOS (row) == PT
+		      && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+			  || !row->ends_at_zv_p)))
+		 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
 	    {
-	      /* These variables are supposed to be origin 1 */
-	      FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
-				    + minmax (0, pos.hpos, width));
-	      FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
+	      xassert (row->enabled_p);
+	      ++row;
+	    }
+
+	  /* If within the scroll margin, scroll.  Note that
+	     MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
+	     next line would be drawn, and that this_scroll_margin can
+	     be zero.  */
+	  if (MATRIX_ROW_BOTTOM_Y (row) > last_y
+	      || PT > MATRIX_ROW_END_CHARPOS (row)
+	      /* Line is completely visible last line in window and PT
+		 is to be set in the next line.  */
+	      || (MATRIX_ROW_BOTTOM_Y (row) == last_y
+		  && PT == MATRIX_ROW_END_CHARPOS (row)
+		  && !row->ends_at_zv_p
+		  && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
+	    scroll_p = 1;
+	}
+      else if (PT < XFASTINT (w->last_point))
+	{
+	  /* Cursor has to be moved backward.  Note that PT >=
+	     CHARPOS (startp) because of the outer if-statement.  */
+	  while (!row->mode_line_p
+		 && (MATRIX_ROW_START_CHARPOS (row) > PT
+		     || (MATRIX_ROW_START_CHARPOS (row) == PT
+			 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
+		 && (row->y > this_scroll_margin
+		     || CHARPOS (startp) == BEGV))
+	    {
+	      xassert (row->enabled_p);
+	      --row;
 	    }
-	  /* This doesn't do the trick, because if a window to the right of
-	     this one must be redisplayed, this does nothing because there
-	     is nothing in DesiredFrame yet, and then the other window is
-	     redisplayed, making likes that are empty in this window's columns.
-	     if (WINDOW_FULL_WIDTH_P (w))
-	     preserve_my_columns (w);
-	     */
-	  if (current_buffer->clip_changed
-	      && ! NILP (Vwindow_scroll_functions))
-	    run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				  make_number (marker_position (w->start)));
-
-	  goto done;
-	}
-      /* Don't bother trying redisplay with same start;
-	 we already know it will lose.  */
-    }
+
+	  /* Consider the following case: Window starts at BEGV, there
+	     is invisible, intangible text at BEGV, so that display
+	     starts at some point START > BEGV.  It can happen that
+	     we are called with PT somewhere between BEGV and START.
+	     Try to handle that case.  */
+	  if (row < w->current_matrix->rows
+	      || row->mode_line_p)
+	    {
+	      row = w->current_matrix->rows;
+	      if (row->mode_line_p)
+		++row;
+	    }
+
+	  /* Due to newlines in overlay strings, we may have to skip
+	     forward over overlay strings.  */
+	  while (MATRIX_ROW_END_CHARPOS (row) == PT
+		 && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row)
+		 && !row->ends_at_zv_p)
+	    ++row;
+	  
+	  /* If within the scroll margin, scroll.  */
+	  if (row->y < this_scroll_margin
+	      && CHARPOS (startp) != BEGV)
+	    scroll_p = 1;
+	}
+
+      /* if PT is not in the glyph row, give up.  */
+      if (PT < MATRIX_ROW_START_CHARPOS (row)
+	  || PT > MATRIX_ROW_END_CHARPOS (row))
+	goto try_to_scroll;
+
+      /* If we end up in a partially visible line, let's make it fully
+	 visible.  This can be done most easily by using the existing
+	 scrolling code.  */
+      if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+	{
+	  temp_scroll_step = 1;
+	  goto try_to_scroll;
+	}
+      else if (scroll_p)
+	goto try_to_scroll;
+      
+      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+      goto done;
+    }
+  
   /* If current starting point was originally the beginning of a line
      but no longer is, find a new starting point.  */
   else if (!NILP (w->start_at_line_beg)
-	   && !(startp <= BEGV
-		|| FETCH_BYTE (startp_byte - 1) == '\n'))
-    {
+	   && !(CHARPOS (startp) <= BEGV
+		|| FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
+    {
+#if GLYPH_DEBUG
+      debug_method_add (w, "recenter 1");
+#endif
       goto recenter;
     }
-  else if (just_this_one && !MINI_WINDOW_P (w)
-	   && PT >= startp
+  
+  /* Try scrolling with try_window_id.  */
+  else if (!windows_or_buffers_changed
+	   /* Window must be either use window-based redisplay or
+	      be full width.  */
+	   && (FRAME_WINDOW_P (f)
+	       || ((line_ins_del_ok && WINDOW_FULL_WIDTH_P (w))
+		   && just_this_one_p))
+	   && !MINI_WINDOW_P (w)
+	   /* Point is not known NOT to appear in window.  */
+	   && PT >= CHARPOS (startp)
 	   && XFASTINT (w->last_modified)
-	   /* or else vmotion on first line won't work.  */
-	   && ! NILP (w->start_at_line_beg)
-	   && ! EQ (w->window_end_valid, Qnil)
-	   && do_id && !current_buffer->clip_changed
-	   && !blank_end_of_window
-	   && WINDOW_FULL_WIDTH_P (w)
-	   /* Can't use this case if highlighting a region.  */
+	   /* Window is not hscrolled.  */
+	   && XFASTINT (w->hscroll) == 0
+	   /* Selective display has not changed.  */
+	   && !current_buffer->clip_changed
+	   /* Current matrix is up to date.  */
+	   && !NILP (w->window_end_valid)
+	   /* Can't use this case if highlighting a region because
+	      a cursor movement will do more than just set the cursor.  */
 	   && !(!NILP (Vtransient_mark_mode)
 		&& !NILP (current_buffer->mark_active))
-	   /* Don't use try_window_id if newline
-	      doesn't display as the end of a line.  */
-	   && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
 	   && NILP (w->region_showing)
+	   /* Overlay arrow position and string not changed.  */
 	   && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
 	   && EQ (last_arrow_string, Voverlay_arrow_string)
-	   && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
-	   && tem != -2)
-    {
-      /* tem > 0 means success.  tem == -1 means choose new start.
-	 tem == -2 means try again with same start,
-	  and nothing but whitespace follows the changed stuff.
-	 tem == 0 means try again with same start.  */
+	   /* Value is > 0 if update has been done, it is -1 if we
+	      know that the same window start will not work.  It is 0
+	      if unsuccessful for some other reason.  */
+	   && (tem = try_window_id (w)) != 0)
+    {
+#if GLYPH_DEBUG
+      debug_method_add (w, "try_window_id");
+#endif
+
+      if (fonts_changed_p)
+	goto restore_buffers;
       if (tem > 0)
 	goto done;
-    }
-  else if (startp >= BEGV && startp <= ZV
-	   && (startp < ZV
+      /* Otherwise try_window_id has returned -1 which means that we
+	 don't want the alternative below this comment to execute.  */
+    }
+  else if (CHARPOS (startp) >= BEGV
+	   && CHARPOS (startp) <= ZV
+	   && PT >= CHARPOS (startp)
+	   && (CHARPOS (startp) < ZV
 	       /* Avoid starting at end of buffer.  */
-#if 0 /* This change causes trouble for M-! finger & RET.
-	 It will have to be considered later.  */
-	       || ! EQ (window, selected_window)
-	       /* Don't do the recentering if redisplay
-		  is not for no user action.  */
-	       || preserve_echo_area
-#endif
-	       || startp == BEGV
+	       || CHARPOS (startp) == BEGV
 	       || (XFASTINT (w->last_modified) >= MODIFF
 		   && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
     {
-      /* Try to redisplay starting at same place as before */
-      /* If point has not moved off frame, accept the results */
-      try_window (window, startp);
-      if (cursor_vpos >= 0)
-	{
-	  if (!just_this_one || current_buffer->clip_changed
-	      || beg_unchanged < startp)
+#if GLYPH_DEBUG
+      debug_method_add (w, "same window start");
+#endif
+      
+      /* Try to redisplay starting at same place as before.
+         If point has not moved off frame, accept the results.  */
+      if (!current_matrix_up_to_date_p
+	  /* Don't use try_window_reusing_current_matrix in this case
+	     because it can have changed the buffer.  */
+	  || !NILP (Vwindow_scroll_functions)
+	  || MINI_WINDOW_P (w)
+	  || !try_window_reusing_current_matrix (w))
+	{
+	  IF_DEBUG (debug_method_add (w, "1"));
+	  try_window (window, startp);
+	}
+
+      if (fonts_changed_p)
+	goto restore_buffers;
+      
+      if (w->cursor.vpos >= 0)
+	{
+	  if (!just_this_one_p 
+	      || current_buffer->clip_changed
+	      || beg_unchanged < CHARPOS (startp))
 	    /* Forget any recorded base line for line number display.  */
 	    w->base_line_number = Qnil;
-
-	  if (current_buffer->clip_changed
-	      && ! NILP (Vwindow_scroll_functions))
-	    run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				  make_number (marker_position (w->start)));
-
+	  
+	  make_cursor_line_fully_visible (w);
 	  goto done;
 	}
       else
-	cancel_my_columns (w);
-    }
+	clear_glyph_matrix (w->desired_matrix);
+    }
+
+ try_to_scroll:
 
   XSETFASTINT (w->last_modified, 0);
   XSETFASTINT (w->last_overlay_modified, 0);
+
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
@@ -2230,257 +8079,224 @@
 	{
 	  set_buffer_temp (old);
 	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  really_switched_buffer = 1;
 	}
       update_mode_line = 1;
       w->update_mode_line = Qt;
     }
 
-  /* Try to scroll by specified few lines */
-
-  if ((scroll_conservatively || scroll_step)
+  /* Try to scroll by specified few lines.  */
+  if ((scroll_conservatively
+       || scroll_step
+       || temp_scroll_step
+       || NUMBERP (current_buffer->scroll_up_aggressively)
+       || NUMBERP (current_buffer->scroll_down_aggressively))
       && !current_buffer->clip_changed
-      && startp >= BEGV && startp <= ZV)
-    {
-      int this_scroll_margin = scroll_margin;
-      int scroll_margin_pos, scroll_margin_bytepos;
-      int scroll_max = scroll_step;
-      Lisp_Object ltemp;
-
-      if (scroll_conservatively)
-	scroll_max = scroll_conservatively;
-
-      /* Don't use a scroll margin that is negative or too large.  */
-      if (this_scroll_margin < 0)
-	this_scroll_margin = 0;
-
-      if (XINT (w->height) < 4 * this_scroll_margin)
-	this_scroll_margin = XINT (w->height) / 4;
-
-      ltemp = Fwindow_end (window, Qt);
-      scroll_margin_pos = XINT (ltemp);
-
-      if (this_scroll_margin)
-	{
-	  pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w);
-	  scroll_margin_pos = pos.bufpos;
-	  scroll_margin_bytepos = pos.bytepos;
+      && CHARPOS (startp) >= BEGV 
+      && CHARPOS (startp) <= ZV)
+    {
+      /* The function returns -1 if new fonts were loaded, 1 if
+	 successful, 0 if not successful.  */
+      int rc = try_scrolling (window, just_this_one_p,
+			      scroll_conservatively,
+			      scroll_step,
+			      temp_scroll_step);
+      if (rc > 0)
+	goto done;
+      else if (rc < 0)
+	goto restore_buffers;
+    }
+
+  /* Finally, just choose place to start which centers point */
+
+ recenter:
+
+#if GLYPH_DEBUG
+  debug_method_add (w, "recenter");
+#endif
+
+  /* w->vscroll = 0; */
+
+  /* Forget any previously recorded base line for line number display.  */
+  if (!current_matrix_up_to_date_p
+      || current_buffer->clip_changed)
+    w->base_line_number = Qnil;
+
+  /* Move backward half the height of the window.  */
+  init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
+  it.current_y = it.last_visible_y;
+  move_it_vertically_backward (&it, it.last_visible_y / 2);
+  xassert (IT_CHARPOS (it) >= BEGV);
+
+  /* The function move_it_vertically_backward may move over more
+     than the specified y-distance.  If it->w is small, e.g. a
+     mini-buffer window, we may end up in front of the window's
+     display area.  Start displaying at the start of the line
+     containing PT in this case.  */
+  if (it.current_y <= 0)
+    {
+      init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
+      move_it_vertically (&it, 0);
+      xassert (IT_CHARPOS (it) <= PT);
+      it.current_y = 0;
+    }
+
+  it.current_x = it.hpos = 0;
+  
+  /* Set startp here explicitly in case that helps avoid an infinite loop
+     in case the window-scroll-functions functions get errors.  */
+  set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
+
+  /* Run scroll hooks.  */
+  startp = run_window_scroll_functions (window, it.current.pos);
+
+  /* Redisplay the window.  */
+  if (!current_matrix_up_to_date_p
+      || windows_or_buffers_changed
+      /* Don't use try_window_reusing_current_matrix in this case
+	 because it can have changed the buffer.  */
+      || !NILP (Vwindow_scroll_functions)
+      || !just_this_one_p
+      || MINI_WINDOW_P (w)
+      || !try_window_reusing_current_matrix (w))
+    try_window (window, startp);
+
+  /* If new fonts have been loaded (due to fontsets), give up.  We
+     have to start a new redisplay since we need to re-adjust glyph
+     matrices.  */
+  if (fonts_changed_p)
+    goto restore_buffers;
+
+  /* If cursor did not appear assume that the middle of the window is
+     in the first line of the window.  Do it again with the next line.
+     (Imagine a window of height 100, displaying two lines of height
+     60.  Moving back 50 from it->last_visible_y will end in the first
+     line.)  */
+  if (w->cursor.vpos < 0)
+    {
+      if (!NILP (w->window_end_valid)
+	  && PT >= Z - XFASTINT (w->window_end_pos))
+	{
+	  clear_glyph_matrix (w->desired_matrix);
+	  move_it_by_lines (&it, 1, 0);
+	  try_window (window, it.current.pos);
+	}
+      else if (PT < IT_CHARPOS (it))
+	{
+	  clear_glyph_matrix (w->desired_matrix);
+	  move_it_by_lines (&it, -1, 0);
+	  try_window (window, it.current.pos);
 	}
       else
-	scroll_margin_bytepos = CHAR_TO_BYTE (scroll_margin_pos);
-
-      if (PT >= scroll_margin_pos)
-	{
-	  struct position pos;
-	  pos = *compute_motion (scroll_margin_pos, 0, 0, 0,
-				 PT, XFASTINT (w->height), 0,
-				 XFASTINT (w->width), XFASTINT (w->hscroll),
-				 pos_tab_offset (w, scroll_margin_pos,
-						 scroll_margin_bytepos),
-				 w);
-	  if (pos.vpos >= scroll_max)
-	    goto scroll_fail_1;
-
-	  pos = *vmotion (startp,
-			  scroll_conservatively ? pos.vpos + 1 : scroll_step,
-			  w);
-
-	  /* The old bottom-of-screen position is no longer valid.  */
-	  w->window_end_valid = Qnil;
-	  if (! NILP (Vwindow_scroll_functions))
-	    {
-	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
-	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				    make_number (pos.bufpos));
-	      pos.bufpos = marker_position (w->start);
-	    }
-	  try_window (window, pos.bufpos);
-	  if (cursor_vpos >= 0)
-	    {
-	      if (!just_this_one || current_buffer->clip_changed
-		  || beg_unchanged < startp)
-		/* Forget any recorded base line for line number display.  */
-		w->base_line_number = Qnil;
-	      goto done;
-	    }
-	  else
-	    cancel_my_columns (w);
-	}
-
-      scroll_margin_pos = startp;
-      if (this_scroll_margin)
-	{
-	  pos = *vmotion (scroll_margin_pos, this_scroll_margin, w);
-	  scroll_margin_pos = pos.bufpos;
-	}
-      if (PT < scroll_margin_pos)
-	{
-	  struct position pos;
-	  pos = *compute_motion (PT, 0, 0, 0,
-				 scroll_margin_pos, XFASTINT (w->height), 0,
-				 XFASTINT (w->width), XFASTINT (w->hscroll),
-				 pos_tab_offset (w, PT, PT_BYTE),
-				 w);
-	  if (pos.vpos > scroll_max)
-	    goto scroll_fail_1;
-
-	  pos = *vmotion (startp,
-			  scroll_conservatively ? -pos.vpos : - scroll_step,
-			  w);
-
-	  /* The old bottom-of-screen position is no longer valid.  */
-	  w->window_end_valid = Qnil;
-	  if (! NILP (Vwindow_scroll_functions))
-	    {
-	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
-	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				    make_number (pos.bufpos));
-	      pos.bufpos = marker_position (w->start);
-	    }
-	  try_window (window, pos.bufpos);
-	  if (cursor_vpos >= 0)
-	    {
-	      if (!just_this_one || current_buffer->clip_changed
-		  || beg_unchanged < startp)
-		/* Forget any recorded base line for line number display.  */
-		w->base_line_number = Qnil;
-	      goto done;
-	    }
-	  else
-	    cancel_my_columns (w);
-	}
-    scroll_fail_1: ;
-    }
-
-#if 0
-  if (scroll_step && ! scroll_margin && !current_buffer->clip_changed
-      && startp >= BEGV && startp <= ZV)
-    {
-      if (margin_call == 0)
-	margin_call = (PT > startp ? 1 : -1);
-      if (margin_call > 0)
-	{
-	  pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
-	  if (pos.vpos >= height)
-	    goto scroll_fail;
-	}
-
-      pos = *vmotion (startp, (margin_call < 0 ? - scroll_step : scroll_step),
-		      w);
-
-      if (PT >= pos.bufpos)
-	{
-	  /* The old bottom-of-screen position is no longer valid.  */
-	  w->window_end_valid = Qnil;
-
-	  if (! NILP (Vwindow_scroll_functions))
-	    {
-	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
-	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
-				    make_number (pos.bufpos));
-	      pos.bufpos = marker_position (w->start);
-	    }
-	  try_window (window, pos.bufpos);
-	  if (cursor_vpos >= 0)
-	    {
-	      if (!just_this_one || current_buffer->clip_changed
-		  || beg_unchanged < startp)
-		/* Forget any recorded base line for line number display.  */
-		w->base_line_number = Qnil;
-	      goto done;
-	    }
-	  else
-	    cancel_my_columns (w);
-	}
-    scroll_fail: ;
-    }
-#endif
-
-  /* Finally, just choose place to start which centers point */
-
-recenter:
-  /* Forget any previously recorded base line for line number display.  */
-  w->base_line_number = Qnil;
-
-  pos = *vmotion (PT, - (height / 2), w);
-
-  /* The minibuffer is often just one line.  Ordinary scrolling
-     gives little overlap and looks bad.  So show 20 chars before point.  */
-  if (height == 1
-      && (pos.bufpos >= PT - minibuffer_scroll_overlap
-	  /* If we scrolled less than 1/2 line forward, we will
-	     get too much overlap, so change to the usual amount.  */
-	  || pos.bufpos < startp + width / 2)
-      && PT > BEGV + minibuffer_scroll_overlap
-      /* If we scrolled to an actual line boundary,
-	 that's different; don't ignore line boundaries.  */
-      && FETCH_BYTE (pos.bytepos - 1) != '\n')
-    {
-      pos.bufpos = PT - minibuffer_scroll_overlap;
-      pos.bytepos = CHAR_TO_BYTE (pos.bufpos);
-    }
-    
-  /* Set startp here explicitly in case that helps avoid an infinite loop
-     in case the window-scroll-functions functions get errors.  */
-  set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
-
-  /* The old bottom-of-screen position is no longer valid.  */
-  w->window_end_valid = Qnil;
-  if (! NILP (Vwindow_scroll_functions))
-    {
-      run_hook_with_args_2 (Qwindow_scroll_functions, window,
-			    make_number (pos.bufpos));
-      pos.bufpos = marker_position (w->start);
-      pos.bytepos = marker_byte_position (w->start);
-    }
-  try_window (window, pos.bufpos);
-
-  startp = marker_position (w->start);
-  startp_byte = marker_byte_position (w->start);
-  w->start_at_line_beg
-    = (startp == BEGV || FETCH_BYTE (startp_byte - 1) == '\n') ? Qt : Qnil;
-
-done:
+	{
+	  /* Not much we can do about it.  */
+	}
+    }
+
+  /* Consider the following case: Window starts at BEGV, there is
+     invisible, intangible text at BEGV, so that display starts at
+     some point START > BEGV.  It can happen that we are called with
+     PT somewhere between BEGV and START.  Try to handle that case.  */
+  if (w->cursor.vpos < 0)
+    {
+      struct glyph_row *row = w->current_matrix->rows;
+      if (row->mode_line_p)
+	++row;
+      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+    }
+  
+  make_cursor_line_fully_visible (w);
+
+  SET_TEXT_POS_FROM_MARKER (startp, w->start);
+  w->start_at_line_beg = ((CHARPOS (startp) == BEGV
+			   || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
+			  ? Qt : Qnil);
+
+ done:
+
+  /* Display the mode line, if we must.  */
   if ((update_mode_line
        /* If window not full width, must redo its mode line
-	  if the window to its side is being redone */
-       || (!just_this_one && !WINDOW_FULL_WIDTH_P (w))
+	  if (a) the window to its side is being redone and 
+	  (b) we do a frame-based redisplay.  This is a consequence
+	  of how inverted lines are drawn in frame-based redisplay.  */
+       || (!just_this_one_p 
+	   && !FRAME_WINDOW_P (f)
+	   && !WINDOW_FULL_WIDTH_P (w))
+       /* Line number to display.  */
        || INTEGERP (w->base_line_pos)
+       /* Column number is displayed and different from the one displayed.  */
        || (!NILP (w->column_number_displayed)
 	   && XFASTINT (w->column_number_displayed) != current_column ()))
-      && height != XFASTINT (w->height))
-    {
-      FRAME_PTR oframe = selected_frame;
-      if (!really_switched_buffer)
-	{
-	  set_buffer_temp (old);
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
-	  really_switched_buffer = 1;
-	}
-      selected_frame = f;
-      display_mode_line (w);
-      selected_frame = oframe;
-    }
-  if (! line_number_displayed
-      && ! BUFFERP (w->base_line_pos))
+       /* This means that the window has a mode line.  */
+       && (WINDOW_WANTS_MODELINE_P (w)
+	   || WINDOW_WANTS_TOP_LINE_P (w)))
+    {
+      display_mode_lines (w);
+
+      /* If mode line height has changed, arrange for a thorough
+	 immediate redisplay using the correct mode line height.  */
+      if (WINDOW_WANTS_MODELINE_P (w)
+	  && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
+	{
+	  fonts_changed_p = 1;
+	  MATRIX_MODE_LINE_ROW (w->current_matrix)->height
+	    = DESIRED_MODE_LINE_HEIGHT (w);
+	}
+      
+      /* If top line height has changed, arrange for a thorough
+	 immediate redisplay using the correct mode line height.  */
+      if (WINDOW_WANTS_TOP_LINE_P (w)
+	  && CURRENT_TOP_LINE_HEIGHT (w) != DESIRED_TOP_LINE_HEIGHT (w))
+	{
+	  fonts_changed_p = 1;
+	  MATRIX_TOP_LINE_ROW (w->current_matrix)->height
+	    = DESIRED_TOP_LINE_HEIGHT (w);
+	}
+
+      if (fonts_changed_p)
+	goto restore_buffers;
+    }
+
+  if (!line_number_displayed
+      && !BUFFERP (w->base_line_pos))
     {
       w->base_line_pos = Qnil;
       w->base_line_number = Qnil;
     }
 
+ finish_menu_bars:
+  
   /* When we reach a frame's selected window, redo the frame's menu bar.  */
   if (update_mode_line
-      && (FRAME_WINDOW_P (f)
-	  ?
+      && EQ (FRAME_SELECTED_WINDOW (f), window))
+    {
+      int redisplay_menu_p = 0;
+
+      if (FRAME_WINDOW_P (f))
+	{
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
-	  FRAME_EXTERNAL_MENU_BAR (f) 
+	  redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
-	  FRAME_MENU_BAR_LINES (f) > 0
+	  redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
 #endif
-	  : FRAME_MENU_BAR_LINES (f) > 0)
-      && EQ (FRAME_SELECTED_WINDOW (f), window))
-    display_menu_bar (w);
+	}
+      else
+        redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
+
+      if (redisplay_menu_p)
+        display_menu_bar (w);
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (WINDOWP (f->toolbar_window)
+	  && (FRAME_TOOLBAR_LINES (f) > 0
+	      || auto_resize_toolbars_p))
+	redisplay_toolbar (f);
+#endif
+    }
 
  finish_scroll_bars:
+
   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
     {
       int start, end, whole;
@@ -2491,18 +8307,22 @@
 	 indicating narrowing, and scrollbars which reflect only the
 	 visible region.
 
-	 Note that minibuffers sometimes aren't displaying any text.  */
+	 Note that mini-buffers sometimes aren't displaying any text.  */
       if (! MINI_WINDOW_P (w)
-	  || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
+	  || (w == XWINDOW (minibuf_window)
+	      && !echo_area_glyphs
+	      && !STRINGP (echo_area_message)))
 	{
 	  whole = ZV - BEGV;
 	  start = marker_position (w->start) - BEGV;
 	  /* I don't think this is guaranteed to be right.  For the
 	     moment, we'll pretend it is.  */
-	  end = (Z - XINT (w->window_end_pos)) - BEGV;
-
-	  if (end < start) end = start;
-	  if (whole < (end - start)) whole = end - start;
+	  end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
+
+	  if (end < start) 
+	    end = start;
+	  if (whole < (end - start)) 
+	    whole = end - start;
 	}
       else
 	start = end = whole = 0;
@@ -2510,1829 +8330,2387 @@
       /* Indicate what this scroll bar ought to be displaying now.  */
       (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
 
-      /* Note that we actually used the scroll bar attached to this window,
-	 so it shouldn't be deleted at the end of redisplay.  */
+      /* Note that we actually used the scroll bar attached to this
+	 window, so it shouldn't be deleted at the end of redisplay.  */
       (*redeem_scroll_bar_hook) (w);
     }
 
-  TEMP_SET_PT_BOTH (opoint, opoint_byte);
+ restore_buffers:
+
+  /* Restore current_buffer and value of point in it.  */
+  TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
   if (really_switched_buffer)
     set_buffer_internal_1 (old);
   else
     set_buffer_temp (old);
-  TEMP_SET_PT_BOTH (lpoint, lpoint_byte);
+  TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
 
   unbind_to (count, Qnil);
 }
-
-/* Do full redisplay on one window, starting at position `pos'. */
-
-static void
+
+
+/* Build the complete desired matrix of WINDOW with a window start
+   buffer position POS.  Value is non-zero if successful.  It is zero
+   if fonts were loaded during redisplay which makes re-adjusting
+   glyph matrices necessary.  */
+
+int
 try_window (window, pos)
      Lisp_Object window;
-     register int pos;
-{
-  register struct window *w = XWINDOW (window);
-  register int height = window_internal_height (w);
-  register int vpos = XFASTINT (w->top);
-  register int last_text_vpos = vpos;
-  FRAME_PTR f = XFRAME (w->frame);
-  int width = window_internal_width (w) - 1;
-  struct position val;
-
-  /* POS should never be out of range!  */
-  if (pos < XBUFFER (w->buffer)->begv
-      || pos > XBUFFER (w->buffer)->zv)
-    abort ();
-
-  if (XMARKER (w->start)->charpos != pos)
-    Fset_marker (w->start, make_number (pos), Qnil);
-
-  cursor_vpos = -1;
+     struct text_pos pos;
+{
+  struct window *w = XWINDOW (window);
+  struct it it;
+  struct glyph_row *last_text_row = NULL;
+
+  /* Make POS the new window start.  */
+  set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
+
+  /* Mark cursor position as unknown.  No overlay arrow seen.  */
+  w->cursor.vpos = -1;
   overlay_arrow_seen = 0;
-  zv_strings_seen = 0;
-  val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
-  val.ovstring_chars_done = 0;
-  val.bytepos = marker_byte_position (w->start);
-  val.tab_offset = pos_tab_offset (w, pos, val.bytepos);
-
-  while (--height >= 0)
-    {
-      val = *display_text_line (w, pos, val.bytepos, vpos,
-				val.hpos, val.tab_offset,
-				val.ovstring_chars_done);
-      /* The following code is omitted because we maintain tab_offset
-         in VAL.  */
-#if 0
-      tab_offset += width;
-      if (val.vpos) tab_offset = 0;
-#endif  /* 0 */
-      vpos++;
-      if (pos != val.bufpos)
-	{
-	  int invis = 0;
-#ifdef USE_TEXT_PROPERTIES
-	  Lisp_Object invis_prop;
-	  invis_prop = Fget_char_property (make_number (val.bufpos - 1),
-					   Qinvisible, window);
-	  invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
-#endif
-
-	  last_text_vpos
-	    /* Next line, unless prev line ended in end of buffer with no cr */
-	    = vpos - (val.vpos
-		      && (FETCH_BYTE (val.bytepos - 1) != '\n' || invis));
-	}
-      pos = val.bufpos;
-    }
-
-  /* If last line is continued in middle of character,
-     include the split character in the text considered on the frame */
-  if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
-    pos++;
-
-  /* If bottom just moved off end of frame, change mode line percentage.  */
-  if (XFASTINT (w->window_end_pos) == 0
-      && Z != pos)
+
+  /* Initialize iterator and info to start at POS.  */
+  start_display (&it, w, pos);
+
+  /* Display all lines of W.  */
+  while (it.current_y < it.last_visible_y)
+    {
+      if (display_line (&it))
+	last_text_row = it.glyph_row - 1;
+      if (fonts_changed_p)
+	return 0;
+    }
+
+  /* If bottom moved off end of frame, change mode line percentage.  */
+  if (XFASTINT (w->window_end_pos) <= 0
+      && Z != IT_CHARPOS (it))
     w->update_mode_line = Qt;
 
-  /* Say where last char on frame will be, once redisplay is finished.  */
-  XSETFASTINT (w->window_end_pos, Z - pos);
-  XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
+  /* Set window_end_pos to the offset of the last character displayed
+     on the window from the end of current_buffer.  Set
+     window_end_vpos to its row number.  */
+  if (last_text_row)
+    {
+      xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
+      w->window_end_bytepos
+	= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
+      XSETFASTINT (w->window_end_pos,
+		   Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      XSETFASTINT (w->window_end_vpos,
+		   MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+      xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
+	       ->displays_text_p);
+    }
+  else
+    {
+      w->window_end_bytepos = 0;
+      XSETFASTINT (w->window_end_pos, 0);
+      XSETFASTINT (w->window_end_vpos, 0);
+    }
+  
   /* But that is not valid info until redisplay finishes.  */
   w->window_end_valid = Qnil;
-}
+  return 1;
+}
+
+
 
-/* Try to redisplay when buffer is modified locally,
- computing insert/delete line to preserve text outside
- the bounds of the changes.
- Return 1 if successful, 0 if if cannot tell what to do,
- or -1 to tell caller to find a new window start,
- or -2 to tell caller to do normal redisplay with same window start.  */
+/************************************************************************
+    Window redisplay reusing current matrix when buffer has not changed
+ ************************************************************************/
+
+/* Try redisplay of window W showing an unchanged buffer with a
+   different window start than the last time it was displayed by
+   reusing its current matrix.  Value is non-zero if successful.
+   W->start is the new window start.  */
+
+static int
+try_window_reusing_current_matrix (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph_row *row, *bottom_row;
+  struct it it;
+  struct run run;
+  struct text_pos start, new_start;
+  int nrows_scrolled, i;
+  struct glyph_row *last_text_row;
+  struct glyph_row *last_reused_text_row;
+  struct glyph_row *start_row;
+  int start_vpos, min_y, max_y;
+
+  /* Right now this function doesn't handle terminal frames.  */
+  if (!FRAME_WINDOW_P (f))
+    return 0;
+
+  /* Can't do this if region may have changed.  */
+  if ((!NILP (Vtransient_mark_mode)
+       && !NILP (current_buffer->mark_active))
+      || !NILP (w->region_showing))
+    return 0;
+
+  /* If top-line visibility has changed, give up.  */
+  if (WINDOW_WANTS_TOP_LINE_P (w)
+      != MATRIX_TOP_LINE_ROW (w->current_matrix)->mode_line_p)
+    return 0;
+
+  /* Give up if old or new display is scrolled vertically.  We could
+     make this function handle this, but right now it doesn't.  */
+  start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
+    return 0;
+
+  /* The variable new_start now holds the new window start.  The old
+     start `start' can be determined from the current matrix.  */
+  SET_TEXT_POS_FROM_MARKER (new_start, w->start);
+  start = start_row->start.pos;
+  start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
+
+  /* Clear the desired matrix for the display below.  */
+  clear_glyph_matrix (w->desired_matrix);
+  
+  if (CHARPOS (new_start) <= CHARPOS (start))
+    {
+      int first_row_y;
+      
+      IF_DEBUG (debug_method_add (w, "twu1"));
+      
+      /* Display up to a row that can be reused.  The variable
+	 last_text_row is set to the last row displayed that displays
+	 text.  */
+      start_display (&it, w, new_start);
+      first_row_y = it.current_y;
+      w->cursor.vpos = -1;
+      last_text_row = last_reused_text_row = NULL;
+      while (it.current_y < it.last_visible_y
+	     && IT_CHARPOS (it) < CHARPOS (start)
+	     && !fonts_changed_p)
+	if (display_line (&it))
+	  last_text_row = it.glyph_row - 1;
+
+      /* A value of current_y < last_visible_y means that we stopped
+	 at the previous window start, which in turn means that we
+	 have at least one reusable row.  */
+      if (it.current_y < it.last_visible_y)
+	{
+	  nrows_scrolled = it.vpos;
+	  
+	  /* Find PT if not already found in the lines displayed.  */
+	  if (w->cursor.vpos < 0)
+	    {
+	      int dy = it.current_y - first_row_y;
+	      
+	      row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+	      while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+		{
+		  if (PT >= MATRIX_ROW_START_CHARPOS (row)
+		      && PT < MATRIX_ROW_END_CHARPOS (row))
+		    {
+		      set_cursor_from_row (w, row, w->current_matrix, 0, 0,
+					   dy, nrows_scrolled);
+		      break;
+		    }
+		  
+		  if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
+		    break;
+		  
+		  ++row;
+		}
+	      
+	      /* Give up if point was not found.  This shouldn't
+		 happen often; not more often than with try_window
+		 itself.  */
+	      if (w->cursor.vpos < 0)
+		{
+		  clear_glyph_matrix (w->desired_matrix);
+		  return 0;
+		}
+	    }
+
+	  /* Scroll the display.  Do it before the current matrix is
+	     changed.  The problem here is that update has not yet
+	     run, i.e. part of the current matrix is not up to date.
+	     scroll_run_hook will clear the cursor, and use the
+	     current matrix to get the height of the row the cursor is
+	     in.  */
+	  run.current_y = first_row_y;
+	  run.desired_y = it.current_y;
+	  run.height = it.last_visible_y - it.current_y;
+	  if (run.height > 0)
+	    {
+	      update_begin (f);
+	      rif->update_window_begin_hook (w);
+	      rif->scroll_run_hook (w, &run);
+	      rif->update_window_end_hook (w, 0);
+	      update_end (f);
+	    }
+
+	  /* Shift current matrix down by nrows_scrolled lines.  */
+	  bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+	  rotate_matrix (w->current_matrix,
+			 start_vpos,
+			 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
+			 nrows_scrolled);
+	  
+	  /* Disable lines not reused.  */
+	  for (i = 0; i < it.vpos; ++i)
+	    MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
+	  
+	  /* Re-compute Y positions.  */
+	  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
+	  min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+	  max_y = it.last_visible_y;
+	  while (row < bottom_row)
+	    {
+	      row->y = it.current_y;
+
+	      if (row->y < min_y)
+		row->visible_height = row->height - (min_y - row->y);
+	      else if (row->y + row->height > max_y)
+		row->visible_height
+		  = row->height - (row->y + row->height - max_y);
+	      else
+		row->visible_height = row->height;
+	      
+	      it.current_y += row->height;
+	      ++it.vpos;
+
+	      if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+		last_reused_text_row = row;
+	      if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
+		break;
+	      ++row;
+	    }
+	}
+
+      /* Update window_end_pos etc.; last_reused_text_row is the last
+	 reused row from the current matrix containing text, if any.
+	 The value of last_text_row is the last displayed line
+	 containing text.  */
+      if (last_reused_text_row)
+	{
+	  w->window_end_bytepos
+	    = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
+	  XSETFASTINT (w->window_end_pos,
+		       Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
+	  XSETFASTINT (w->window_end_vpos,
+		       MATRIX_ROW_VPOS (last_reused_text_row,
+					w->current_matrix));
+	}
+      else if (last_text_row)
+	{
+	  w->window_end_bytepos
+	    = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
+	  XSETFASTINT (w->window_end_pos,
+		       Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+	  XSETFASTINT (w->window_end_vpos,
+		       MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+	}
+      else
+	{
+	  /* This window must be completely empty.  */
+	  w->window_end_bytepos = 0;
+	  XSETFASTINT (w->window_end_pos, 0);
+	  XSETFASTINT (w->window_end_vpos, 0);
+	}
+      w->window_end_valid = Qnil;
+
+      /* Update hint: don't try scrolling again in update_window.  */
+      w->desired_matrix->no_scrolling_p = 1;
+      
+#if GLYPH_DEBUG
+      debug_method_add (w, "try_window_reusing_current_matrix 1");
+#endif
+      return 1;
+    }
+  else if (CHARPOS (new_start) > CHARPOS (start))
+    {
+      struct glyph_row *pt_row, *row;
+      struct glyph_row *first_reusable_row;
+      struct glyph_row *first_row_to_display;
+      int dy;
+      int yb = window_text_bottom_y (w);
+
+      IF_DEBUG (debug_method_add (w, "twu2"));
+      
+      /* Find the row starting at new_start, if there is one.  Don't
+	 reuse a partially visible line at the end.  */
+      first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+      while (first_reusable_row->enabled_p
+	     && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
+	     && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
+		 < CHARPOS (new_start)))
+	++first_reusable_row;
+
+      /* Give up if there is no row to reuse.  */
+      if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
+	  || !first_reusable_row->enabled_p)
+	return 0;
+
+      /* The row we found must start at new_start, or else something
+	 is broken.  */
+      xassert (MATRIX_ROW_START_CHARPOS (first_reusable_row)
+	       == CHARPOS (new_start));
+      
+      /* We can reuse fully visible rows beginning with
+         first_reusable_row to the end of the window.  Set
+         first_row_to_display to the first row that cannot be reused.
+         Set pt_row to the row containing point, if there is any.  */
+      first_row_to_display = first_reusable_row;
+      pt_row = NULL;
+      while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
+	{
+	  if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
+	      && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
+	    pt_row = first_row_to_display;
+
+	  ++first_row_to_display;
+	}
+
+      /* Start displaying at the start of first_row_to_display.  */
+      xassert (first_row_to_display->y < yb);
+      init_to_row_start (&it, w, first_row_to_display);
+      nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix);
+      it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
+		 - nrows_scrolled);
+      it.current_y = first_row_to_display->y - first_reusable_row->y;
+
+      /* Display lines beginning with first_row_to_display in the
+         desired matrix.  Set last_text_row to the last row displayed
+         that displays text.  */
+      it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
+      if (pt_row == NULL)
+	w->cursor.vpos = -1;
+      last_text_row = NULL;
+      while (it.current_y < it.last_visible_y && !fonts_changed_p)
+	if (display_line (&it))
+	  last_text_row = it.glyph_row - 1;
+
+      /* Give up If point isn't in a row displayed or reused.  */
+      if (w->cursor.vpos < 0)
+	{
+	  clear_glyph_matrix (w->desired_matrix);
+	  return 0;
+	}
+
+      /* If point is in a reused row, adjust y and vpos of the cursor
+	 position.  */
+      if (pt_row)
+	{
+	  w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
+					     w->current_matrix);
+	  w->cursor.y -= first_reusable_row->y;
+	}
+
+      /* Scroll the display.  */
+      run.current_y = first_reusable_row->y;
+      run.desired_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      run.height = it.last_visible_y - run.current_y;
+      if (run.height)
+	{
+	  struct frame *f = XFRAME (WINDOW_FRAME (w));
+	  update_begin (f);
+	  rif->update_window_begin_hook (w);
+	  rif->scroll_run_hook (w, &run);
+	  rif->update_window_end_hook (w, 0);
+	  update_end (f);
+	}
+
+      /* Adjust Y positions of reused rows.  */
+      bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+      row = first_reusable_row;
+      dy = first_reusable_row->y;
+      min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      max_y = it.last_visible_y;
+      while (row < first_row_to_display)
+	{
+	  row->y -= dy;
+	  if (row->y < min_y)
+	    row->visible_height = row->height - (min_y - row->y);
+	  else if (row->y + row->height > max_y)
+	    row->visible_height
+	      = row->height - (row->y + row->height - max_y);
+	  else
+	    row->visible_height = row->height;
+	  ++row;
+	}
+
+      /* Disable rows not reused.  */
+      while (row < bottom_row)
+	{
+	  row->enabled_p = 0;
+	  ++row;
+	}
+
+      /* Scroll the current matrix.  */
+      xassert (nrows_scrolled > 0);
+      rotate_matrix (w->current_matrix,
+		     start_vpos,
+		     MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
+		     -nrows_scrolled);
+
+      /* Adjust window end.  A null value of last_text_row means that
+	 the window end is in reused rows which in turn means that
+	 only its vpos can have changed.  */
+      if (last_text_row)
+	{
+	  w->window_end_bytepos
+	    = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
+	  XSETFASTINT (w->window_end_pos,
+		       Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+	  XSETFASTINT (w->window_end_vpos,
+		       MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+	}
+      else
+	{
+	  XSETFASTINT (w->window_end_vpos,
+		       XFASTINT (w->window_end_vpos) - nrows_scrolled);
+	}
+      
+      w->window_end_valid = Qnil;
+      w->desired_matrix->no_scrolling_p = 1;
+
+#if GLYPH_DEBUG
+      debug_method_add (w, "try_window_reusing_current_matrix 2");
+#endif
+      return 1;
+    }
+  
+  return 0;
+}
+
+
+
+/************************************************************************
+   Window redisplay reusing current matrix when buffer has changed
+ ************************************************************************/
+
+static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *));
+static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *,
+							     int *, int *));
+static struct glyph_row *
+find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
+				   struct glyph_row *));
+
+
+/* Return the last row in MATRIX displaying text.  If row START is
+   non-null, start searching with that row.  IT gives the dimensions
+   of the display.  Value is null if matrix is empty; otherwise it is
+   a pointer to the row found.  */
+
+static struct glyph_row *
+find_last_row_displaying_text (matrix, it, start)
+     struct glyph_matrix *matrix;
+     struct it *it;
+     struct glyph_row *start;
+{
+  struct glyph_row *row, *row_found;
+
+  /* Set row_found to the last row in IT->w's current matrix
+     displaying text.  The loop looks funny but think of partially
+     visible lines.  */
+  row_found = NULL;
+  row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
+  while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+    {
+      xassert (row->enabled_p);
+      row_found = row;
+      if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
+	break;
+      ++row;
+    }
+  
+  return row_found;
+}
+
+
+/* Return the last row in the current matrix of W that is not affected
+   by changes at the start of current_buffer that occurred since the
+   last time W was redisplayed.  Value is null if no such row exists.
+
+   The global variable beg_unchanged has to contain the number of
+   bytes unchanged at the start of current_buffer.  BEG +
+   beg_unchanged is the buffer position of the first changed byte in
+   current_buffer.  Characters at positions < BEG + beg_unchanged are
+   at the same buffer positions as they were when the current matrix
+   was built.  */
+
+static struct glyph_row *
+get_last_unchanged_at_beg_row (w)
+     struct window *w;
+{
+  int first_changed_pos = BEG + beg_unchanged;
+  struct glyph_row *row;
+  struct glyph_row *row_found = NULL;
+  int yb = window_text_bottom_y (w);
+
+  /* Find the last row displaying unchanged text.  */
+  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
+	 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
+    {
+      if (/* If row ends before first_changed_pos, it is unchanged,
+	     except in some case.  */
+	  MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
+	  /* When row ends in ZV and we write at ZV it is not
+             unchanged.  */
+	  && !row->ends_at_zv_p
+	  /* When first_changed_pos is the end of a continued line,
+	     row is not unchanged because it may be no longer
+	     continued.  */
+	  && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
+	       && row->continued_p))
+	row_found = row;
+
+      /* Stop if last visible row.  */
+     if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
+	break;
+      
+      ++row;
+    }
+
+  return row_found;
+}
+
+
+/* Find the first glyph row in the current matrix of W that is not
+   affected by changes at the end of current_buffer since the last
+   time the window was redisplayed.  Return in *DELTA the number of
+   bytes by which buffer positions in unchanged text at the end of
+   current_buffer must be adjusted.  Value is null if no such row
+   exists, i.e. all rows are affected by changes.
+
+   The global variable end_unchanged is assumed to contain the number
+   of unchanged bytes at the end of current_buffer.  The buffer
+   position of the last changed byte in current_buffer is then Z -
+   end_unchanged.  */
+   
+static struct glyph_row *
+get_first_unchanged_at_end_row (w, delta, delta_bytes)
+     struct window *w;
+     int *delta, *delta_bytes;
+{
+  struct glyph_row *row;
+  struct glyph_row *row_found = NULL;
+
+  *delta = *delta_bytes = 0;
+
+  /* A value of window_end_pos >= end_unchanged means that the window
+     end is in the range of changed text.  If so, there is no
+     unchanged row at the end of W's current matrix.  */
+  xassert (!NILP (w->window_end_valid));
+  if (XFASTINT (w->window_end_pos) >= end_unchanged)
+    return NULL;
+
+  /* Set row to the last row in W's current matrix displaying text.  */
+  row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+  
+  /* End vpos should always be on text, except in an entirely empty
+     matrix.  */
+  xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row)
+	   || MATRIX_ROW_VPOS (row, w->current_matrix) == 0);
+
+  /* If matrix is entirely empty, no unchanged row exists.  */ 
+  if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+    {
+      /* The value of row is the last glyph row in the matrix having a
+	 meaningful buffer position in it.  The end position of row
+	 corresponds to window_end_pos.  This allows us to translate
+	 buffer positions in the current matrix to current buffer
+	 positions for characters not in changed text.  */
+      int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+      int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
+      int last_unchanged_pos, last_unchanged_pos_old;
+      struct glyph_row *first_text_row
+	= MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+
+      *delta = Z - Z_old;
+      *delta_bytes = Z_BYTE - Z_BYTE_old;
+
+      /* Set last_unchanged_pos to the buffer position of the last
+	 character in the buffer that has not been changed.  Z is the
+	 index + 1 of the last byte in current_buffer, i.e. by
+	 subtracting end_unchanged we get the index of the last
+	 unchanged character, and we have to add BEG to get its buffer
+	 position.  */
+      last_unchanged_pos = Z - end_unchanged + BEG;
+      last_unchanged_pos_old = last_unchanged_pos - *delta;
+      
+      /* Search backward from ROW for a row displaying a line that
+	 starts at a minimum position >= last_unchanged_pos_old.  */
+      while (row >= first_text_row)
+	{
+	  xassert (row->enabled_p);
+	  xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row));
+	  
+	  if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
+	    row_found = row;
+	  --row;
+	}
+    }
+
+  xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
+  return row_found;
+}
+
+
+/* Make sure that glyph rows in the current matrix of window W
+   reference the same glyph memory as corresponding rows in the
+   frame's frame matrix.  This function is called after scrolling W's
+   current matrix on a terminal frame in try_window_id and
+   try_window_reusing_current_matrix.  */
+
+static void
+sync_frame_with_window_matrix_rows (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph_row *window_row, *window_row_end, *frame_row;
+
+  /* Preconditions: W must be a leaf window and full-width.  Its frame
+     must have a frame matrix.  */
+  xassert (NILP (w->hchild) && NILP (w->vchild));
+  xassert (WINDOW_FULL_WIDTH_P (w));
+  xassert (!FRAME_WINDOW_P (f));
+
+  /* If W is a full-width window, glyph pointers in W's current matrix
+     have, by definition, to be the same as glyph pointers in the
+     corresponding frame matrix.  */
+  window_row = w->current_matrix->rows;
+  window_row_end = window_row + w->current_matrix->nrows;
+  frame_row = f->current_matrix->rows + XFASTINT (w->top);
+  while (window_row < window_row_end)
+    {
+      int area;
+      for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
+	frame_row->glyphs[area] = window_row->glyphs[area];
+      ++window_row, ++frame_row;
+    }
+}
+
+
+/* Try to redisplay window W by reusing its existing display.  W's
+   current matrix must be up to date when this function is called,
+   i.e. window_end_valid must not be nil.
+
+   Value is
+
+   1	if display has been updated
+   0	if otherwise unsuccessful
+   -1	if redisplay with same window start is known not to succeed
+
+   The following steps are performed:
+
+   1. Find the last row in the current matrix of W that is not
+   affected by changes at the start of current_buffer.  If no such row
+   is found, give up.
+
+   2. Find the first row in W's current matrix that is not affected by
+   changes at the end of current_buffer.  Maybe there is no such row.
+
+   3. Display lines beginning with the row + 1 found in step 1 to the
+   row found in step 2 or, if step 2 didn't find a row, to the end of
+   the window.
+
+   4. If cursor is not known to appear on the window, give up.
+
+   5. If display stopped at the row found in step 2, scroll the
+   display and current matrix as needed.
+
+   6. Maybe display some lines at the end of W, if we must.  This can
+   happen under various circumstances, like a partially visible line
+   becoming fully visible, or because newly displayed lines are displayed
+   in smaller font sizes.
+
+   7. Update W's window end information.  */
+
+  /* Check that window end is what we expect it to be.  */
 
 static int
-try_window_id (window)
-     Lisp_Object window;
-{
-  int pos, pos_byte;
-  int opoint, opoint_byte;
-  register struct window *w = XWINDOW (window);
-  register int height = window_internal_height (w);
-  FRAME_PTR f = XFRAME (w->frame);
-  int top = XFASTINT (w->top);
-  int start = marker_position (w->start);
-  int width = window_internal_width (w) - 1;
-  int hscroll = XINT (w->hscroll);
-  int lmargin = hscroll > 0 ? 1 - hscroll : 0;
-  int did_motion;
-  register int vpos;
-  register int i, tem;
-  int last_text_vpos = 0;
-  int stop_vpos;
-  int selective = (INTEGERP (current_buffer->selective_display)
-		   ? XINT (current_buffer->selective_display)
-		   : !NILP (current_buffer->selective_display) ? -1 : 0);
-  struct position val, bp, ep, xp, pp;
-  int scroll_amount = 0;
-  int delta;
-  int epto, old_tick;
-
-  int start_byte = marker_byte_position (w->start);
-
-  if (GPT - BEG < beg_unchanged)
-    beg_unchanged = GPT - BEG;
-  if (Z - GPT < end_unchanged)
-    end_unchanged = Z - GPT;
-
-  if (beg_unchanged + BEG < start)
-    return 0;			/* Give up if changes go above top of window */
-
-  /* Find position before which nothing is changed.  */
-  bp = *compute_motion (start, 0, lmargin, 0,
-			min (ZV, beg_unchanged + BEG), height,
-			/* BUG FIX: See the comment of
-                           Fpos_visible_in_window_p (window.c).  */
-			- (1 << (BITS_PER_SHORT - 1)),
-			width, hscroll,
-			pos_tab_offset (w, start, start_byte),
-			w);
-  if (bp.vpos >= height)
-    {
-      if (PT < bp.bufpos)
-	{
-	  /* All changes are beyond the window end, and point is on the screen.
-	     We don't need to change the text at all.
-	     But we need to update window_end_pos to account for
-	     any change in buffer size.  */
-	  bp = *compute_motion (start, 0, lmargin, 0,
-				ZV, height,
-				/* BUG FIX: See the comment of
-                                   Fpos_visible_in_window_p() (window.c).  */
-				- (1 << (BITS_PER_SHORT - 1)),
-				width, hscroll,
-				pos_tab_offset (w, start, start_byte), w);
-	  XSETFASTINT (w->window_end_vpos, height);
-	  XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
-	  goto findpoint;
-	}
-      return 0;
-    }
-
-  vpos = bp.vpos;
-
-  /* Find beginning of that frame line.  Must display from there.  */
-  bp = *vmotion (bp.bufpos, 0, w);
-
-  pos = bp.bufpos;
-  pos_byte = bp.bytepos;
-  val.hpos = lmargin;
-  if (pos < start)
-    return -1;
-
-  did_motion = 0;
-  /* If about to start displaying at the beginning of a continuation line,
-     really start with previous frame line, in case it was not
-     continued when last redisplayed */
-  if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
-      ||
-      /* Likewise if we have to worry about selective display.  */
-      (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
-    {
-      bp = *vmotion (bp.bufpos, -1, w);
-      --vpos;
-      pos = bp.bufpos;
-      pos_byte = bp.bytepos;
-    }
-  val.tab_offset = bp.tab_offset; /* Update tab offset.  */
-
-  if (bp.contin && bp.hpos != lmargin)
-    {
-      val.hpos = bp.prevhpos - width + lmargin;
-      val.tab_offset = bp.tab_offset + width - bp.prevhpos;
-      did_motion = 1;
-      DEC_BOTH (pos, pos_byte);
-    }
-
-  bp.vpos = vpos;
-
-  /* Find first visible newline after which no more is changed.  */
-  opoint = PT, opoint_byte = PT_BYTE;
-  TEMP_SET_PT (Z - max (end_unchanged, Z - ZV));
-  scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
-  if (selective > 0)
-    while (PT < ZV - 1 && indented_beyond_p (PT, PT_BYTE, selective))
-      scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
-  tem = PT;
-  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-
-  /* Compute the cursor position after that newline.  */
-  ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
-			height, - (1 << (BITS_PER_SHORT - 1)),
-			width, hscroll,
-			/* We have tab offset in VAL, use it.  */
-			val.tab_offset, w); 
-
-  /* If changes reach past the text available on the frame,
-     just display rest of frame.  */
-  if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
-    stop_vpos = height;
+try_window_id (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph_matrix *current_matrix = w->current_matrix;
+  struct glyph_matrix *desired_matrix = w->desired_matrix;
+  struct glyph_row *last_unchanged_at_beg_row;
+  struct glyph_row *first_unchanged_at_end_row;
+  struct glyph_row *row;
+  struct glyph_row *bottom_row;
+  int bottom_vpos;
+  struct it it;
+  int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
+  struct text_pos start_pos;
+  struct run run;
+  int first_unchanged_at_end_vpos = 0;
+  struct glyph_row *last_text_row, *last_text_row_at_end;
+  struct text_pos start;
+
+  SET_TEXT_POS_FROM_MARKER (start, w->start);
+
+  /* Check pre-conditions.  Window end must be valid, otherwise
+     the current matrix would not be up to date.  */
+  xassert (!NILP (w->window_end_valid));
+  xassert (FRAME_WINDOW_P (XFRAME (w->frame))
+	   || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
+
+  /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
+     only if buffer has really changed.  The reason is that the gap is
+     initially at Z for freshly visited files.  The code below would
+     set end_unchanged to 0 in that case.  */
+  if (MODIFF > SAVE_MODIFF)
+    {
+      if (GPT - BEG < beg_unchanged)
+	beg_unchanged = GPT - BEG;
+      if (Z - GPT < end_unchanged)
+	end_unchanged = Z - GPT;
+    }
+  
+  /* If window starts after a line end, and the last change is in
+     front of that newline, then changes don't affect the display.
+     This case happens with stealth-fontification.  */
+  row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+  if (CHARPOS (start) > BEGV
+      && Z - end_unchanged < CHARPOS (start) - 1
+      && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
+      && PT < MATRIX_ROW_END_CHARPOS (row))
+    {
+      /* We have to update window end positions because the buffer's
+	 size has changed.  */
+      w->window_end_pos
+	= make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      w->window_end_bytepos
+	= make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+      return 1;
+    }
+
+  /* Return quickly if changes are all below what is displayed in the
+     window, and if PT is in the window.  */
+  if (beg_unchanged > MATRIX_ROW_END_CHARPOS (row)
+      && PT < MATRIX_ROW_END_CHARPOS (row))
+    {
+      /* We have to update window end positions because the buffer's
+	 size has changed.  */
+      w->window_end_pos
+	= make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      w->window_end_bytepos
+	= make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+      return 1;
+    }
+
+  /* Check that window start agrees with the start of the first glyph
+     row in its current matrix.  Check this after we know the window
+     start is not in changed text, otherwise positions would not be
+     comparable.  */
+  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  if (!TEXT_POS_EQUAL_P (start, row->start.pos))
+    return 0;
+
+  /* Remember beg_unchanged and end_unchanged for debugging purposes.  */
+  IF_DEBUG (debug_beg_unchanged = beg_unchanged;
+	    debug_end_unchanged = end_unchanged);
+
+  /* Compute the position at which we have to start displaying new
+     lines.  Some of the lines at the top of the window might be
+     reusable because they are not displaying changed text.  Find the
+     last row in W's current matrix not affected by changes at the
+     start of current_buffer.  Value is null if changes start in the
+     first line of window.  */
+  last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w);
+  if (last_unchanged_at_beg_row)
+    {
+      init_to_row_end (&it, w, last_unchanged_at_beg_row);
+      start_pos = it.current.pos;
+      
+      /* Start displaying new lines in the desired matrix at the same
+	 vpos we would use in the current matrix, i.e. below
+	 last_unchanged_at_beg_row.  */
+      it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
+				     current_matrix);
+      it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
+      it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
+
+      xassert (it.hpos == 0 && it.current_x == 0);
+    }
   else
-    stop_vpos = ep.vpos;
-
-  /* If no newline before ep, the line ep is on includes some changes
-     that must be displayed.  Make sure we don't stop before it.  */
-  /* Also, if changes reach all the way until ep.bufpos,
-     it is possible that something was deleted after the
-     newline before it, so the following line must be redrawn. */
-  if (stop_vpos == ep.vpos
-      && (ep.bufpos == BEGV
-	  || FETCH_BYTE (ep.bytepos - 1) != '\n'
-	  || ep.bufpos == Z - end_unchanged))
-    stop_vpos = ep.vpos + 1;
-
-  cursor_vpos = -1;
+    {
+      /* There are no reusable lines at the start of the window.
+	 Start displaying in the first line.  */
+      start_display (&it, w, start);
+      start_pos = it.current.pos;
+    }
+
+  bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
+  bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
+  
+  /* Find the first row that is not affected by changes at the end of
+     the buffer.  Value will be null if there is no unchanged row, in
+     which case we must redisplay to the end of the window.  delta
+     will be set to the value by which buffer positions beginning with
+     first_unchanged_at_end_row have to be adjusted due to text
+     changes.  */
+  first_unchanged_at_end_row
+    = get_first_unchanged_at_end_row (w, &delta, &delta_bytes);
+  IF_DEBUG (debug_delta = delta);
+  IF_DEBUG (debug_delta_bytes = delta_bytes);
+  
+  /* Set stop_pos to the buffer position up to which we will have to
+     display new lines.  If first_unchanged_at_end_row != NULL, this
+     is the buffer position of the start of the line displayed in that
+     row.  For first_unchanged_at_end_row == NULL, use 0 to indicate
+     that we don't stop at a buffer position.  */
+  stop_pos = 0;
+  if (first_unchanged_at_end_row)
+    {
+      xassert (last_unchanged_at_beg_row == NULL
+	       || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
+      
+      /* If this is a continuation line, move forward to the next one
+	 that isn't.  Changes in lines above affect this line.
+	 Caution: this may move first_unchanged_at_end_row to a row
+	 not displaying text.  */
+      while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
+	     && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
+	     && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
+		 < it.last_visible_y))
+	++first_unchanged_at_end_row;
+
+      if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
+	  || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
+	      >= it.last_visible_y))
+	first_unchanged_at_end_row = NULL;
+      else
+	{
+	  stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
+		      + delta);
+	  first_unchanged_at_end_vpos
+	    = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
+	  xassert (stop_pos >= Z - end_unchanged);
+	}
+    }
+  else if (last_unchanged_at_beg_row == NULL)
+    return 0;
+
+
+#if GLYPH_DEBUG
+  
+  /* Either there is no unchanged row at the end, or the one we have
+     now displays text.  This is a necessary condition for the window
+     end pos calculation at the end of this function.  */
+  xassert (first_unchanged_at_end_row == NULL
+	   || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
+  
+  debug_last_unchanged_at_beg_vpos
+    = (last_unchanged_at_beg_row
+       ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
+       : -1);
+  debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
+  
+#endif /* GLYPH_DEBUG != 0 */
+
+
+  /* Display new lines.  Set last_text_row to the last new line
+     displayed which has text on it, i.e. might end up as being the
+     line where the window_end_vpos is.  */
+  w->cursor.vpos = -1;
+  last_text_row = NULL;
   overlay_arrow_seen = 0;
-  zv_strings_seen = 0;
-
-  /* If changes do not reach to bottom of window,
-     figure out how much to scroll the rest of the window */
-  if (stop_vpos < height)
-    {
-      /* Now determine how far up or down the rest of the window has moved */
-      xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
-			    Z - XFASTINT (w->window_end_pos),
-			    /* Don't care for VPOS... */
-			    1 << (BITS_PER_SHORT - 1),
-			    /* ... nor HPOS.  */
-			    1 << (BITS_PER_SHORT - 1),
-			    width, hscroll, ep.tab_offset, w);
-      scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
-
-      /* Is everything on frame below the changes whitespace?
-	 If so, no scrolling is really necessary.  */
-      for (i = ep.bytepos; i < xp.bytepos; i++)
-	{
-	  tem = FETCH_BYTE (i);
-	  if (tem != ' ' && tem != '\n' && tem != '\t')
-	    break;
-	}
-      if (i == xp.bytepos)
-	return -2;
-
-      XSETFASTINT (w->window_end_vpos,
-		   XFASTINT (w->window_end_vpos) + scroll_amount);
-
-      /* Before doing any scrolling, verify that point will be on frame. */
-      if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height))
-	{
-	  if (PT <= xp.bufpos)
+  while (it.current_y < it.last_visible_y
+	 && !fonts_changed_p
+	 && (first_unchanged_at_end_row == NULL
+	     || IT_CHARPOS (it) < stop_pos))
+    {
+      if (display_line (&it))
+	last_text_row = it.glyph_row - 1;
+    }
+
+  if (fonts_changed_p)
+    return -1;
+
+
+  /* Compute differences in buffer positions, y-positions etc.  for
+     lines reused at the bottom of the window.  Compute what we can
+     scroll.  */
+  if (first_unchanged_at_end_row)
+    {
+      dvpos = (it.vpos
+	       - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
+				  current_matrix));
+      dy = it.current_y - first_unchanged_at_end_row->y;
+      run.current_y = first_unchanged_at_end_row->y;
+      run.desired_y = run.current_y + dy;
+      run.height = it.last_visible_y - max (run.current_y, run.desired_y);
+    }
+  else
+    delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
+  IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
+
+  
+  /* Find the cursor if not already found.  We have to decide whether
+     PT will appear on this window (it sometimes doesn't, but this is
+     not a very frequent case.)  This decision has to be made before
+     the current matrix is altered.  A value of cursor.vpos < 0 means
+     that PT is either in one of the lines beginning at
+     first_unchanged_at_end_row or below the window.  Don't care for
+     lines that might be displayed later at the window end; as
+     mentioned, this is not a frequent case.  */
+  if (w->cursor.vpos < 0)
+    {
+      int last_y = min (it.last_visible_y, it.last_visible_y + dy);
+
+      /* Cursor in unchanged rows at the top?  */
+      if (PT < CHARPOS (start_pos)
+	  && last_unchanged_at_beg_row)
+	{
+	  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+	  while (row <= last_unchanged_at_beg_row
+		 && MATRIX_ROW_END_CHARPOS (row) <= PT)
+	    ++row;
+	  xassert (row <= last_unchanged_at_beg_row);
+	  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+	}
+
+      /* Start from first_unchanged_at_end_row looking for PT.  */
+      else if (first_unchanged_at_end_row)
+	{
+	  row = first_unchanged_at_end_row;
+	  while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
 	    {
-	      pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
-				    PT, height, - (1 << (BITS_PER_SHORT - 1)),
-				    width, hscroll,
-				    /* We have tab offset in EP, use it.  */
-				    ep.tab_offset, w);
-	    }
-	  else
-	    {
-	      pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
-				    PT, height, - (1 << (BITS_PER_SHORT - 1)),
-				    width, hscroll,
-				    /* We have tab offset in XP, use it. */
-				    xp.tab_offset, w);
+	      if (PT - delta >= MATRIX_ROW_START_CHARPOS (row)
+		  && PT - delta < MATRIX_ROW_END_CHARPOS (row))
+		{
+		  set_cursor_from_row (w, row, w->current_matrix, delta,
+				       delta_bytes, dy, dvpos);
+		  break;
+		}
+	      else if (MATRIX_ROW_BOTTOM_Y (row) >= last_y)
+		break;
+	      ++row;
 	    }
-	  if (pp.bufpos < PT || pp.vpos == height)
-	    return 0;
-	  cursor_vpos = pp.vpos + top;
-	  cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
-	}
-
-      if (stop_vpos - scroll_amount >= height
-	  || ep.bufpos == xp.bufpos)
-	{
-	  if (scroll_amount < 0)
-	    stop_vpos -= scroll_amount;
-	  scroll_amount = 0;
-	  /* In this path, we have altered window_end_vpos
-	     and not left it negative.
-	     We must make sure that, in case display is preempted
-	     before the frame changes to reflect what we do here,
-	     further updates will not come to try_window_id
-	     and assume the frame and window_end_vpos match.  */
-	  blank_end_of_window = 1;
-	}
-      else if (!scroll_amount)
-	{
-	  /* Even if we don't need to scroll, we must adjust the
-	     charstarts of subsequent lines (that we won't redisplay)
-	     according to the amount of text inserted or deleted.  */
-	  int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
-	  int adjust = ep.bufpos - oldpos;
-	  adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
-	}
-      else if (bp.bufpos == Z - end_unchanged)
-	{
-	  /* If reprinting everything is nearly as fast as scrolling,
-	     don't bother scrolling.  Can happen if lines are short.  */
-	  if (scroll_cost (f, bp.vpos + top - scroll_amount,
-			   top + height - max (0, scroll_amount),
-			   scroll_amount)
-	      > xp.bufpos - bp.bufpos - 20)
-	    /* Return "try normal display with same window-start."
-	       Too bad we can't prevent further scroll-thinking.  */
-	    return -2;
-	  /* If pure deletion, scroll up as many lines as possible.
-	     In common case of killing a line, this can save the
-	     following line from being overwritten by scrolling
-	     and therefore having to be redrawn.  */
-	  tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
-				    top + height - max (0, scroll_amount),
-				    scroll_amount, bp.bufpos);
-	  if (!tem)
-	    stop_vpos = height;
-	  else
+	}
+
+      /* Give up if cursor was not found.  */
+      if (w->cursor.vpos < 0)
+	{
+	  clear_glyph_matrix (w->desired_matrix);
+	  return -1;
+	}
+    }
+  
+  /* Don't let the cursor end in the scroll margins.  */
+  {
+    int this_scroll_margin, cursor_height;
+    
+    this_scroll_margin = max (0, scroll_margin);
+    this_scroll_margin = min (this_scroll_margin,
+			      XFASTINT (w->height) / 4);
+    this_scroll_margin *= CANON_Y_UNIT (it.f);
+    cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
+    
+    if ((w->cursor.y < this_scroll_margin
+	 && CHARPOS (start) > BEGV)
+	/* Don't take scroll margin into account at the bottom because
+	   old redisplay didn't do it either.  */
+	|| w->cursor.y + cursor_height > it.last_visible_y)
+      {
+	w->cursor.vpos = -1;
+	clear_glyph_matrix (w->desired_matrix);
+	return -1;
+      }
+  }
+
+  /* Scroll the display.  Do it before changing the current matrix so
+     that xterm.c doesn't get confused about where the cursor glyph is
+     found.  */
+  if (dy)
+    {
+      update_begin (f);
+	  
+      if (FRAME_WINDOW_P (f))
+	{
+	  rif->update_window_begin_hook (w);
+	  rif->scroll_run_hook (w, &run);
+	  rif->update_window_end_hook (w, 0);
+	}
+      else
+	{
+	  /* Terminal frame.  In this case, dvpos gives the number of
+	     lines to scroll by; dvpos < 0 means scroll up.  */
+	  int first_unchanged_at_end_vpos
+	    = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
+	  int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
+	  int end = XFASTINT (w->top) + window_internal_height (w);
+	  
+	  /* Perform the operation on the screen.  */
+	  if (dvpos > 0)
 	    {
-	      /* scroll_frame_lines did not properly adjust subsequent
-		 lines' charstarts in the case where the text of the
-		 screen line at bp.vpos has changed.
-		 (This can happen in a deletion that ends in mid-line.)
-		 To adjust properly, we need to make things consistent
-		 at the position ep.
-		 So do a second adjust to make that happen.
-		 Note that stop_vpos >= ep.vpos, so it is sufficient
-		 to update the charstarts for lines at ep.vpos and below.  */
-	      int oldstart
-		= FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
-	      adjust_window_charstarts (w, ep.vpos + top - 1,
-					ep.bufpos - oldstart);
+	      /* Scroll last_unchanged_at_beg_row to the end of the
+		 window down dvpos lines.  */
+	      set_terminal_window (end);
+
+	      /* On dumb terminals delete dvpos lines at the end
+		 before inserting dvpos empty lines.  */
+	      if (!scroll_region_ok)
+		ins_del_lines (end - dvpos, -dvpos);
+
+	      /* Insert dvpos empty lines in front of
+                 last_unchanged_at_beg_row.  */
+	      ins_del_lines (from, dvpos);
+	    }
+	  else if (dvpos < 0)
+	    {
+	      /* Scroll up last_unchanged_at_beg_vpos to the end of
+		 the window to last_unchanged_at_beg_vpos - |dvpos|.  */
+	      set_terminal_window (end);
+
+	      /* Delete dvpos lines in front of
+		 last_unchanged_at_beg_vpos.  ins_del_lines will set
+		 the cursor to the given vpos and emit |dvpos| delete
+		 line sequences.  */
+	      ins_del_lines (from + dvpos, dvpos);
+
+	      /* On a dumb terminal insert dvpos empty lines at the
+                 end.  */
+	      if (!scroll_region_ok)
+		ins_del_lines (end + dvpos, -dvpos);
 	    }
-	}
-      else if (scroll_amount)
-	{
-	  /* If reprinting everything is nearly as fast as scrolling,
-	     don't bother scrolling.  Can happen if lines are short.  */
-	  /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
-	     overestimate of cost of reprinting, since xp.bufpos
-	     would end up below the bottom of the window.  */
-	  if (scroll_cost (f, ep.vpos + top - scroll_amount,
-			   top + height - max (0, scroll_amount),
-			   scroll_amount)
-	      > xp.bufpos - ep.bufpos - 20)
-	    /* Return "try normal display with same window-start."
-	       Too bad we can't prevent further scroll-thinking.  */
-	    return -2;
-	  tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
-				     top + height - max (0, scroll_amount),
-				     scroll_amount, ep.bufpos);
-	  if (!tem) stop_vpos = height;
-	}
-    }
-
-  /* In any case, do not display past bottom of window */
-  if (stop_vpos >= height)
-    {
-      stop_vpos = height;
-      scroll_amount = 0;
-    }
-
-  /* Handle case where pos is before w->start --
-     can happen if part of line had been clipped and is not clipped now */
-  if (vpos == 0 && pos < marker_position (w->start))
-    Fset_marker (w->start, make_number (pos), Qnil);
-
-  val.bytepos = pos_byte;
-  val.ovstring_chars_done = 0;
-
-  /* Redisplay the lines where the text was changed */
-  last_text_vpos = vpos;
-  /* The following code is omitted because we maintain tab offset in
-     val.tab_offset.  */
-#if 0
-  tab_offset = pos_tab_offset (w, pos, pos_byte);
-  /* If we are starting display in mid-character, correct tab_offset
-     to account for passing the line that that character really starts in.  */
-  if (val.hpos < lmargin)
-    tab_offset += width;
-#endif /* 0 */
-  old_tick = MODIFF;
-  while (vpos < stop_vpos)
-    {
-      val = *display_text_line (w, pos, val.bytepos, top + vpos++,
-				val.hpos, val.tab_offset,
-				val.ovstring_chars_done);
-      /* If display_text_line ran a hook and changed some text,
-	 redisplay all the way to bottom of buffer
-	 So that we show the changes.  */
-      if (old_tick != MODIFF)
-	stop_vpos = height;
-      /* The following code is omitted because we maintain tab offset
-	 in val.tab_offset.  */
-#if 0
-      tab_offset += width;
-      if (val.vpos) tab_offset = 0;
-#endif
-      if (pos != val.bufpos)
-	last_text_vpos
-	  /* Next line, unless prev line ended in end of buffer with no cr */
-	    = vpos - (val.vpos && FETCH_BYTE (val.bytepos - 1) != '\n');
-      pos = val.bufpos;
-    }
-
-  /* There are two cases:
-     1) we have displayed down to the bottom of the window
-     2) we have scrolled lines below stop_vpos by scroll_amount  */
-
-  if (vpos == height)
-    {
-      /* If last line is continued in middle of character,
-	 include the split character in the text considered on the frame */
-      if (val.hpos < lmargin)
-	val.bufpos++;
-      XSETFASTINT (w->window_end_vpos, last_text_vpos);
-      XSETFASTINT (w->window_end_pos, Z - val.bufpos);
-    }
-
-  /* If scrolling made blank lines at window bottom,
-     redisplay to fill those lines */
-  if (scroll_amount < 0)
-    {
-      /* Don't consider these lines for general-purpose scrolling.
-	 That will save time in the scrolling computation.  */
-      FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
-      vpos = xp.vpos;
-      pos = xp.bufpos;
-      pos_byte = xp.bytepos;
-      val.hpos = xp.hpos;
-      val.tab_offset = xp.tab_offset;
-      if (pos == ZV)
-	{ /* Display from next line */
-	  vpos = height + scroll_amount;
-	  val.hpos = lmargin;
-	  val.tab_offset = 0;
-	}
-      else if (xp.contin && xp.hpos != lmargin)
-	{
-	  val.hpos = xp.prevhpos - width + lmargin;
-	  val.tab_offset = xp.tab_offset + bp.prevhpos - width;
-	  DEC_BOTH (pos, pos_byte);
-	}
-
-      blank_end_of_window = 1;
-      /* The following code is omitted because we maintain tab offset
-	 in val.tab_offset.  */
-#if 0
-      tab_offset = pos_tab_offset (w, pos, pos_byte);
-      /* If we are starting display in mid-character, correct tab_offset
-	 to account for passing the line that that character starts in.  */
-      if (val.hpos < lmargin)
-	tab_offset += width;
-#endif
-      val.bytepos = pos_byte;
-      while (vpos < height)
-	{
-	  val = *display_text_line (w, pos, val.bytepos,
-				    top + vpos++, val.hpos,
-				    val.tab_offset, val.ovstring_chars_done);
-	  /* The following code is omitted because we maintain tab
-	     offset in val.tab_offset.  */
-#if 0
-	  tab_offset += width;
-	  if (val.vpos) tab_offset = 0;
-#endif /* 0 */
-	  pos = val.bufpos;
-	}
-
-      /* Here is a case where display_text_line sets cursor_vpos wrong.
-	 Make it be fixed up, below.  */
-      if (xp.bufpos == ZV
-	  && xp.bufpos == PT)
-	cursor_vpos = -1;
-    }
-
-  /* If bottom just moved off end of frame, change mode line percentage.  */
-  if (XFASTINT (w->window_end_pos) == 0
-      && Z != val.bufpos)
-    w->update_mode_line = Qt;
-
-  /* Attempt to adjust end-of-text positions to new bottom line */
-  if (scroll_amount)
-    {
-      delta = height - xp.vpos;
-      if (delta < 0
-	  || (delta > 0 && xp.bufpos <= ZV)
-	  || (delta == 0 && xp.hpos))
-	{
-	  val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
-	  XSETFASTINT (w->window_end_pos, Z - val.bufpos);
-	  XSETFASTINT (w->window_end_vpos,
-		       XFASTINT (w->window_end_vpos) + val.vpos);
-	}
-    }
-
+	  
+	  set_terminal_window (0);
+	}
+      
+      update_end (f);
+    }
+
+  /* Shift reused rows of the current matrix to the right position.  */
+  if (dvpos < 0)
+    {
+      rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
+		     bottom_vpos, dvpos);
+      enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
+				bottom_vpos, 0);
+    }
+  else if (dvpos > 0)
+    {
+      rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
+		     bottom_vpos, dvpos);
+      enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
+				first_unchanged_at_end_vpos + dvpos, 0);
+    }
+
+  /* For frame-based redisplay, make sure that current frame and window
+     matrix are in sync with respect to glyph memory.  */
+  if (!FRAME_WINDOW_P (f))
+    sync_frame_with_window_matrix_rows (w);
+
+  /* Adjust buffer positions in reused rows.  */
+  if (delta)
+    increment_glyph_matrix_buffer_positions (current_matrix,
+					     first_unchanged_at_end_vpos + dvpos,
+					     bottom_vpos, delta, delta_bytes);
+
+  /* Adjust Y positions.  */
+  if (dy)
+    shift_glyph_matrix (w, current_matrix,
+			first_unchanged_at_end_vpos + dvpos,
+			bottom_vpos, dy);
+
+  if (first_unchanged_at_end_row)
+    first_unchanged_at_end_row += dvpos;
+
+  /* If scrolling up, there may be some lines to display at the end of
+     the window.  */
+  last_text_row_at_end = NULL;
+  if (dy < 0)
+    {
+      /* Set last_row to the glyph row in the current matrix where the
+	 window end line is found.  It has been moved up or down in
+	 the matrix by dvpos.  */
+      int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
+      struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
+
+      /* If last_row is the window end line, it should display text.  */
+      xassert (last_row->displays_text_p);
+
+      /* If window end line was partially visible before, begin
+	 displaying at that line.  Otherwise begin displaying with the
+	 line following it.  */
+      if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
+	{
+	  init_to_row_start (&it, w, last_row);
+	  it.vpos = last_vpos;
+	  it.current_y = last_row->y;
+	}
+      else
+	{
+	  init_to_row_end (&it, w, last_row);
+	  it.vpos = 1 + last_vpos;
+	  it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
+	  ++last_row;
+	}
+
+      /* We may start in a continuation line.  If so, we have to get
+	 the right continuation_lines_width and current_x.  */
+      it.continuation_lines_width = last_row->continuation_lines_width;
+      it.hpos = it.current_x = 0;
+      
+      /* Display the rest of the lines at the window end.  */
+      it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
+      while (it.current_y < it.last_visible_y
+	     && !fonts_changed_p)
+	{
+	  /* Is it always sure that the display agrees with lines in
+	     the current matrix?  I don't think so, so we mark rows
+	     displayed invalid in the current matrix by setting their
+	     enabled_p flag to zero.  */
+	  MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
+	  if (display_line (&it))
+	    last_text_row_at_end = it.glyph_row - 1;
+	}
+    }
+
+  /* Update window_end_pos and window_end_vpos.  */
+  if (first_unchanged_at_end_row
+      && first_unchanged_at_end_row->y < it.last_visible_y
+      && !last_text_row_at_end)
+    {
+      /* Window end line if one of the preserved rows from the current
+	 matrix.  Set row to the last row displaying text in current
+	 matrix starting at first_unchanged_at_end_row, after
+	 scrolling.  */
+      xassert (first_unchanged_at_end_row->displays_text_p);
+      row = find_last_row_displaying_text (w->current_matrix, &it,
+					   first_unchanged_at_end_row);
+      xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
+      
+      XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
+      w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+      XSETFASTINT (w->window_end_vpos,
+		   MATRIX_ROW_VPOS (row, w->current_matrix));
+    }
+  else if (last_text_row_at_end)
+    {
+      XSETFASTINT (w->window_end_pos,
+		   Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
+      w->window_end_bytepos
+	= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
+      XSETFASTINT (w->window_end_vpos,
+		   MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
+    }
+  else if (last_text_row)
+    {
+      /* We have displayed either to the end of the window or at the
+	 end of the window, i.e. the last row with text is to be found
+	 in the desired matrix.  */
+      XSETFASTINT (w->window_end_pos,
+		   Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      w->window_end_bytepos
+	= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
+      XSETFASTINT (w->window_end_vpos,
+		   MATRIX_ROW_VPOS (last_text_row, desired_matrix));
+    }
+  else if (first_unchanged_at_end_row == NULL
+	   && last_text_row == NULL
+	   && last_text_row_at_end == NULL)
+    {
+      /* Displayed to end of window, but no line containing text was
+	 displayed.  Lines were deleted at the end of the window.  */
+      int vpos;
+      int top_line_p = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0;
+
+      for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
+	if ((w->desired_matrix->rows[vpos + top_line_p].enabled_p
+	     && w->desired_matrix->rows[vpos + top_line_p].displays_text_p)
+	    || (!w->desired_matrix->rows[vpos + top_line_p].enabled_p
+		&& w->current_matrix->rows[vpos + top_line_p].displays_text_p))
+	  break;
+
+      w->window_end_vpos = make_number (vpos);
+    }
+  else
+    abort ();
+  
+  IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
+	    debug_end_vpos = XFASTINT (w->window_end_vpos));
+
+  /* Record that display has not been completed.  */
   w->window_end_valid = Qnil;
-
-  /* If point was not in a line that was displayed, find it */
-  if (cursor_vpos < 0)
-    {
-    findpoint:
-      val = *compute_motion (start, 0, lmargin, 0, PT, 
-			     /* Don't care for VPOS...  */
-			     1 << (BITS_PER_SHORT - 1),
-			     /* ... nor HPOS.  */
-			     1 << (BITS_PER_SHORT - 1),
-			     width, hscroll,
-			     pos_tab_offset (w, start, start_byte),
-			     w);
-      /* Admit failure if point is off frame now */
-      if (val.vpos >= height)
-	{
-	  for (vpos = 0; vpos < height; vpos++)
-	    cancel_line (vpos + top, f);
-	  return 0;
-	}
-      cursor_vpos = val.vpos + top;
-      cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
-    }
-
-  FRAME_CURSOR_X (f) = cursor_hpos;
-  FRAME_CURSOR_Y (f) = cursor_vpos;
-
-  if (debug_end_pos)
-    {
-      val = *compute_motion (start, 0, lmargin, 0, ZV,
-			     height, - (1 << (BITS_PER_SHORT - 1)),
-			     width, hscroll,
-			     pos_tab_offset (w, start, start_byte),
-			     w);
-      if (val.vpos != XFASTINT (w->window_end_vpos))
-	abort ();
-      if (XFASTINT (w->window_end_pos)
-	  != Z - val.bufpos)
-	abort ();
-    }
-
+  w->desired_matrix->no_scrolling_p = 1;
   return 1;
 }
+
+
+
+/***********************************************************************
+			More debugging support
+ ***********************************************************************/
+
+#if GLYPH_DEBUG
+
+ void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
+static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
+
+
+/* Dump the contents of glyph matrix MATRIX on stderr.  If
+   WITH_GLYPHS_P is non-zero, dump glyph contents as well.  */
+
+void
+dump_glyph_matrix (matrix, with_glyphs_p)
+     struct glyph_matrix *matrix;
+     int with_glyphs_p;
+{
+  int i;
+  for (i = 0; i < matrix->nrows; ++i)
+    dump_glyph_row (matrix, i, with_glyphs_p);
+}
+
+
+/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
+   WITH_GLYPH_SP non-zero means dump glyph contents, too.  */
+
+void
+dump_glyph_row (matrix, vpos, with_glyphs_p)
+     struct glyph_matrix *matrix;
+     int vpos, with_glyphs_p;
+{
+  struct glyph_row *row;
+  
+  if (vpos < 0 || vpos >= matrix->nrows)
+    return;
+
+  row = MATRIX_ROW (matrix, vpos);
+  
+  fprintf (stderr, "Row Start   End Used oEI><O\\CTZF    X   Y   W\n");
+  fprintf (stderr, "=============================================\n");
+  
+  fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n",
+	   row - matrix->rows,
+	   MATRIX_ROW_START_CHARPOS (row),
+	   MATRIX_ROW_END_CHARPOS (row),
+	   row->used[TEXT_AREA],
+	   row->contains_overlapping_glyphs_p,
+	   row->enabled_p,
+	   row->inverse_p,
+	   row->truncated_on_left_p,
+	   row->truncated_on_right_p,
+	   row->overlay_arrow_p,
+	   row->continued_p,
+	   MATRIX_ROW_CONTINUATION_LINE_P (row),
+	   row->displays_text_p,
+	   row->ends_at_zv_p,
+	   row->fill_line_p,
+	   row->x,
+	   row->y,
+	   row->pixel_width);
+  fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
+	   row->end.overlay_string_index);
+  fprintf (stderr, "%9d %5d\n",
+	   CHARPOS (row->start.string_pos),
+	   CHARPOS (row->end.string_pos));
+  fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
+	   row->end.dpvec_index);
+  
+  if (with_glyphs_p)
+    {
+      struct glyph *glyph, *glyph_end;
+      int prev_had_glyphs_p;
+      
+      glyph = row->glyphs[TEXT_AREA];
+      glyph_end = glyph + row->used[TEXT_AREA];
+      
+      /* Glyph for a line end in text.  */
+      if (glyph == glyph_end && glyph->charpos > 0)
+	++glyph_end;
+      
+      if (glyph < glyph_end)
+	{
+	  fprintf (stderr, "  Glyph    Type Pos   W    Code C Face LR\n");
+	  prev_had_glyphs_p = 1;
+	}
+      else
+	prev_had_glyphs_p = 0;
+      
+      while (glyph < glyph_end)
+	{
+	  if (glyph->type == CHAR_GLYPH)
+	    {
+	      fprintf (stderr,
+		       "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+		       glyph - row->glyphs[TEXT_AREA],
+		       'C',
+		       glyph->charpos,
+		       glyph->pixel_width,
+		       glyph->u.ch.code,
+		       (glyph->u.ch.code < 0x80 && glyph->u.ch.code >= ' '
+			? glyph->u.ch.code
+			: '.'),
+		       glyph->u.ch.face_id,
+		       glyph->left_box_line_p,
+		       glyph->right_box_line_p);
+	    }
+	  else if (glyph->type == STRETCH_GLYPH)
+	    {
+	      fprintf (stderr,
+		       "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+		       glyph - row->glyphs[TEXT_AREA],
+		       'S',
+		       glyph->charpos,
+		       glyph->pixel_width,
+		       0,
+		       '.',
+		       glyph->u.stretch.face_id,
+		       glyph->left_box_line_p,
+		       glyph->right_box_line_p);
+	    }
+	  else if (glyph->type == IMAGE_GLYPH)
+	    {
+	      fprintf (stderr,
+		       "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+		       glyph - row->glyphs[TEXT_AREA],
+		       'I',
+		       glyph->charpos,
+		       glyph->pixel_width,
+		       glyph->u.img.id,
+		       '.',
+		       glyph->u.img.face_id,
+		       glyph->left_box_line_p,
+		       glyph->right_box_line_p);
+	    }
+	  ++glyph;
+	}
+    }
+}
+
+
+DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
+       Sdump_glyph_matrix, 0, 1, "p",
+  "Dump the current matrix of the selected window to stderr.\n\
+Shows contents of glyph row structures.  With non-nil optional\n\
+parameter WITH-GLYPHS-P, dump glyphs as well.")
+  (with_glyphs_p)
+{
+  struct window *w = XWINDOW (selected_window);
+  struct buffer *buffer = XBUFFER (w->buffer);
+
+  fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
+	   BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
+  fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
+	   w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
+  fprintf (stderr, "=============================================\n");
+  dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
+  return Qnil;
+}
+
+
+DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
+  "Dump glyph row ROW to stderr.")
+  (row)
+     Lisp_Object row;
+{
+  CHECK_NUMBER (row, 0);
+  dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
+  return Qnil;
+}
+
+
+DEFUN ("dump-toolbar-row", Fdump_toolbar_row, Sdump_toolbar_row,
+       0, 0, "", "")
+  ()
+{
+  struct glyph_matrix *m = (XWINDOW (selected_frame->toolbar_window)
+			    ->current_matrix);
+  dump_glyph_row (m, 0, 1);
+  return Qnil;
+}
+
+
+DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
+       Strace_redisplay_toggle, 0, 0, "",
+  "Toggle tracing of redisplay.")
+     ()
+{
+  trace_redisplay_p = !trace_redisplay_p;
+  return Qnil;
+}
+       
+	
+#endif /* GLYPH_DEBUG */
+
+
 
-/* Copy LEN glyphs starting address FROM to the rope TO.
-   But don't actually copy the parts that would come in before S.
-   Value is TO, advanced past the copied data.
-   F is the frame we are displaying in.  */
-
-static GLYPH *
-copy_part_of_rope (f, to, s, from, len, face)
-     FRAME_PTR f;
-     register GLYPH *to; /* Copy to here. */
-     register GLYPH *s; /* Starting point. */
-     Lisp_Object *from;  /* Data to copy. */
-     int len;
-     int face;		/* Face to apply to glyphs which don't specify one. */
-{
-  int n = len;
-  register Lisp_Object *fp = from;
-  /* These cache the results of the last call to compute_glyph_face.  */
-  int last_code = -1;
-  int last_merged = 0;
-
-#ifdef HAVE_FACES
-  if (! FRAME_TERMCAP_P (f))
-    while (n--)
-      {
-	GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
-	int facecode;
-	unsigned int c = FAST_GLYPH_CHAR (glyph);
-
-	if (c > MAX_CHAR)
-	  /* For an invalid character code, use space.  */
-	  c = ' ';
-
-	if (FAST_GLYPH_FACE (glyph) == 0)
-	  /* If GLYPH has no face code, use FACE.  */
-	  facecode = face;
-	else if (FAST_GLYPH_FACE (glyph) == last_code)
-	  /* If it's same as previous glyph, use same result.  */
-	  facecode = last_merged;
-	else
-	  {
-	    /* Merge this glyph's face and remember the result.  */
-	    last_code = FAST_GLYPH_FACE (glyph);
-	    last_merged = facecode = compute_glyph_face (f, last_code, face);
-	  }
-
-	if (to >= s)
-	  *to = FAST_MAKE_GLYPH (c, facecode);
-	++to;
-	++fp;
-      }
+/***********************************************************************
+		     Building Desired Matrix Rows
+ ***********************************************************************/
+
+/* Return a temporary glyph row holding the glyphs of an overlay
+   arrow.  Only used for non-window-redisplay windows.  */
+
+static struct glyph_row *
+get_overlay_arrow_glyph_row (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *old = current_buffer;
+  unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
+  int arrow_len = XSTRING (Voverlay_arrow_string)->size;
+  unsigned char *arrow_end = arrow_string + arrow_len;
+  unsigned char *p;
+  struct it it;
+  int multibyte_p;
+  int n_glyphs_before;
+
+  set_buffer_temp (buffer);
+  init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
+  it.glyph_row->used[TEXT_AREA] = 0;
+  SET_TEXT_POS (it.position, 0, 0);
+
+  multibyte_p = !NILP (buffer->enable_multibyte_characters);
+  p = arrow_string;
+  while (p < arrow_end)
+    {
+      Lisp_Object face, ilisp;
+      
+      /* Get the next character.  */
+      if (multibyte_p)
+	it.c = STRING_CHAR_AND_LENGTH (p, arrow_len, it.len);
+      else
+	it.c = *p, it.len = 1;
+      p += it.len;
+      
+      /* Get its face.  */
+      XSETFASTINT (ilisp, p - arrow_string);
+      face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
+      it.face_id = compute_char_face (f, it.c, face);
+
+      /* Compute its width, get its glyphs.  */
+      n_glyphs_before = it.glyph_row->used[TEXT_AREA];
+      PRODUCE_GLYPHS (&it);
+
+      /* If this character doesn't fit any more in the line, we have
+	 to remove some glyphs.  */
+      if (it.current_x > it.last_visible_x)
+	{
+	  it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
+	  break;
+	}
+    }
+  
+  set_buffer_temp (old);
+  return it.glyph_row;
+}
+
+
+/* Insert truncation glyphs at the start of IT->glyph_row.  Truncation
+   glyphs are only inserted for terminal frames since we can't really
+   win with truncation glyphs when partially visible glyphs are
+   involved.  Which glyphs to insert is determined by
+   produce_special_glyphs.  */
+
+static void
+insert_left_trunc_glyphs (it)
+     struct it *it;
+{
+  struct it truncate_it;
+  struct glyph *from, *end, *to, *toend;
+
+  xassert (!FRAME_WINDOW_P (it->f));
+
+  /* Get the truncation glyphs.  */
+  truncate_it = *it;
+  truncate_it.charset = -1;
+  truncate_it.current_x = 0;
+  truncate_it.face_id = DEFAULT_FACE_ID;
+  truncate_it.glyph_row = &scratch_glyph_row;
+  truncate_it.glyph_row->used[TEXT_AREA] = 0;
+  CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
+  truncate_it.object = 0;
+  produce_special_glyphs (&truncate_it, IT_TRUNCATION);
+  
+  /* Overwrite glyphs from IT with truncation glyphs.  */
+  from = truncate_it.glyph_row->glyphs[TEXT_AREA];
+  end = from + truncate_it.glyph_row->used[TEXT_AREA];
+  to = it->glyph_row->glyphs[TEXT_AREA];
+  toend = to + it->glyph_row->used[TEXT_AREA];
+
+  while (from < end)
+    *to++ = *from++;
+
+  /* There may be padding glyphs left over.  Remove them.  */
+  from = to;
+  while (from < toend && CHAR_GLYPH_PADDING_P (*from))
+    ++from;
+  while (from < toend)
+    *to++ = *from++;
+
+  it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
+}
+
+
+/* Compute the pixel height and width of IT->glyph_row.
+
+   Most of the time, ascent and height of a display line will be equal
+   to the max_ascent and max_height values of the display iterator
+   structure.  This is not the case if
+
+   1. We hit ZV without displaying anything.  In this case, max_ascent
+   and max_height will be zero.
+
+   2. We have some glyphs that don't contribute to the line height.
+   (The glyph row flag contributes_to_line_height_p is for future
+   pixmap extensions).
+
+   The first case is easily covered by using default values because in
+   these cases, the line height does not really matter, except that it
+   must not be zero.  */
+
+static void
+compute_line_metrics (it)
+     struct it *it;
+{
+  struct glyph_row *row = it->glyph_row;
+  int area, i;
+
+  if (FRAME_WINDOW_P (it->f))
+    {
+      int i, top_line_height;
+
+      /* The line may consist of one space only, that was added to
+	 place the cursor on it.  If so, the row's height hasn't been
+	 computed yet.  */
+      if (row->height == 0)
+	{
+	  if (it->max_ascent + it->max_descent == 0)
+	    it->max_descent = CANON_Y_UNIT (it->f);
+	  row->ascent = it->max_ascent;
+	  row->height = it->max_ascent + it->max_descent;
+	}
+      
+      /* Compute the width of this line.  */
+      row->pixel_width = row->x;
+      for (i = 0; i < row->used[TEXT_AREA]; ++i)
+	row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
+
+      xassert (row->pixel_width >= 0);
+      xassert (row->ascent >= 0 && row->height > 0);
+
+      /* Compute how much of the line is visible.  */
+      row->visible_height = row->height;
+      
+      top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (it->w);
+      if (row->y < top_line_height)
+	row->visible_height -= top_line_height - row->y;
+      else
+	{
+	  int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
+	  if (row->y + row->height > max_y)
+	    row->visible_height -= row->y + row->height - max_y;
+	}
+    }
   else
-#endif
-    while (n--)
-      {
-	if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
-	++to;
-	++fp;
-      }
-  return to;
-}
-
-/* Correct a glyph by replacing its specified user-level face code
-   with a displayable computed face code.  */
-
-static GLYPH
-fix_glyph (f, glyph, cface)
-     FRAME_PTR f;
-     GLYPH glyph;
-     int cface;
-{
-#ifdef HAVE_FACES
-  if (! FRAME_TERMCAP_P (f))
-    {
-      if (FAST_GLYPH_FACE (glyph) != 0)
-	cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
-      glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
-    }
-#endif
-  return glyph;
-}
-
-/* Return the column of position POS / POS_BYTE in window W's buffer.
-   When used on the character at the beginning of a line,
-   starting at column 0, this says how much to subtract from
-   the column position of any character in the line
-   to get its horizontal position on the screen.  */
+    {
+      row->pixel_width = row->used[TEXT_AREA];
+      row->ascent = 0;
+      row->height = row->visible_height = 1;
+    }
+
+  /* Compute a hash code for this row.  */
+  row->hash = 0;
+  for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+    for (i = 0; i < row->used[area]; ++i)
+      row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
+		   + row->glyphs[area][i].u.val
+		   + (row->glyphs[area][i].type << 2));
+
+  it->max_ascent = it->max_descent = 0;
+}
+
+
+/* Append one space to the glyph row of iterator IT if doing a
+   window-based redisplay.  DEFAULT_FACE_P non-zero means let the
+   space have the default face, otherwise let it have the same face as
+   IT->face_id.  This function is called to make sure that there is
+   always one glyph at the end of a glyph row that the cursor can be
+   set on under window-systems.  (If there weren't such a glyph we
+   would not know how wide and tall the cursor should be displayed).  */
+
+static void
+append_space (it, default_face_p)
+     struct it *it;
+     int default_face_p;
+{
+  if (FRAME_WINDOW_P (it->f))
+    {
+      int n = it->glyph_row->used[TEXT_AREA];
+
+      if (it->glyph_row->glyphs[TEXT_AREA] + n
+	  < it->glyph_row->glyphs[1 + TEXT_AREA])
+	{
+	  /* Save some values that must not be changed.  */
+	  int saved_x = it->current_x;
+	  struct text_pos saved_pos;
+	  int saved_what = it->what;
+	  int saved_face_id = it->face_id;
+	  int saved_charset = it->charset;
+	  Lisp_Object saved_object;
+
+	  saved_object = it->object;
+	  saved_pos = it->position;
+	  
+	  it->what = IT_CHARACTER;
+	  bzero (&it->position, sizeof it->position);
+	  it->object = 0;
+	  it->c = ' ';
+	  it->len = 1;
+	  it->charset = CHARSET_ASCII;
+
+	  if (default_face_p)
+	    it->face_id = DEFAULT_FACE_ID;
+	  if (it->multibyte_p)
+	    it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
+	  else
+	    it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
+
+	  PRODUCE_GLYPHS (it);
+	  
+	  it->current_x = saved_x;
+	  it->object = saved_object;
+	  it->position = saved_pos;
+	  it->what = saved_what;
+	  it->face_id = saved_face_id;
+	  it->charset = saved_charset;
+	}
+    }
+}
+
+
+/* Extend the face of the last glyph in the text area of IT->glyph_row
+   to the end of the display line.  Called from display_line.
+   If the glyph row is empty, add a space glyph to it so that we
+   know the face to draw.  Set the glyph row flag fill_line_p.  */
+   
+static void
+extend_face_to_end_of_line (it)
+     struct it *it;
+{
+  struct face *face;
+  struct frame *f = it->f;
+
+  /* If line is already filled, do nothing.  */
+  if (it->current_x >= it->last_visible_x)
+    return;
+  
+  /* Face extension extends the background and box of IT->face_id
+     to the end of the line.  If the background equals the background
+     of the frame, we haven't to do anything.  */
+  face = FACE_FROM_ID (f, it->face_id);
+  if (FRAME_WINDOW_P (f)
+      && face->box == FACE_NO_BOX
+      && face->background == FRAME_BACKGROUND_PIXEL (f)
+      && !face->stipple)
+    return;
+
+  /* Set the glyph row flag indicating that the face of the last glyph
+     in the text area has to be drawn to the end of the text area.  */
+  it->glyph_row->fill_line_p = 1;
+
+  /* If current charset of IT is not ASCII, make sure we have the
+     ASCII face.  This will be automatically undone the next time
+     get_next_display_element returns a character from a different
+     charset.  Note that the charset will always be ASCII in unibyte
+     text.  */
+  if (it->charset != CHARSET_ASCII)
+    {
+      it->charset = CHARSET_ASCII;
+      it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
+    }
+
+  if (FRAME_WINDOW_P (f))
+    {
+      /* If the row is empty, add a space with the current face of IT,
+	 so that we know which face to draw.  */
+      if (it->glyph_row->used[TEXT_AREA] == 0)
+	{
+	  it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
+	  it->glyph_row->glyphs[TEXT_AREA][0].u.ch.face_id = it->face_id;
+	  it->glyph_row->used[TEXT_AREA] = 1;
+	}
+    }
+  else
+    {
+      /* Save some values that must not be changed.  */
+      int saved_x = it->current_x;
+      struct text_pos saved_pos;
+      Lisp_Object saved_object;
+      int saved_what = it->what;
+
+      saved_object = it->object;
+      saved_pos = it->position;
+  
+      it->what = IT_CHARACTER;
+      bzero (&it->position, sizeof it->position);
+      it->object = 0;
+      it->c = ' ';
+      it->len = 1;
+      
+      PRODUCE_GLYPHS (it);
+      
+      while (it->current_x <= it->last_visible_x)
+	PRODUCE_GLYPHS (it);
+      
+      /* Don't count these blanks really.  It would let us insert a left
+	 truncation glyph below and make us set the cursor on them, maybe.  */
+      it->current_x = saved_x;
+      it->object = saved_object;
+      it->position = saved_pos;
+      it->what = saved_what;
+    }
+}
+
+
+/* Value is non-zero if text starting at CHARPOS in current_buffer is
+   trailing whitespace.  */
 
 static int
-pos_tab_offset (w, pos, pos_byte)
-     struct window *w;
-     register int pos, pos_byte;
-{
-  int opoint = PT;
-  int opoint_byte = PT_BYTE;
-  int col;
-  int width = window_internal_width (w) - 1;
-
-  if (pos == BEGV)
-    return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0;
-
-  if (FETCH_BYTE (pos_byte - 1) == '\n')
-    return 0;
-
-  TEMP_SET_PT_BOTH (pos, pos_byte);
-  col = current_column ();
-  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-
-  return col;
-}
-
-/* Display one line of window W, starting at char position START in W's buffer.
-   START_BYTE is the corresponding byte position.
-
-   Display starting at horizontal position HPOS, expressed relative to
-   W's left edge.  In situations where the text at START shouldn't
-   start at the left margin (i.e. when the window is hscrolled, or
-   we're continuing a line which left off in the midst of a
-   multi-column character), HPOS should be negative; we throw away
-   characters up 'til hpos = 0.  So, HPOS must take hscrolling into
-   account.
-
-   TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
-
-   OVSTR_DONE is the number of chars of overlay before/after strings
-   at this position which have already been processed.
-
-   Display on position VPOS on the frame.  It is origin 0, relative to
-   the top of the frame, not W.
-
-   Returns a STRUCT POSITION giving character to start next line with
-   and where to display it, including a zero or negative hpos.
-   The vpos field is not really a vpos; it is 1 unless the line is continued */
-
-struct position val_display_text_line;
-
-static struct position *
-display_text_line (w, start, start_byte, vpos, hpos, taboffset, ovstr_done)
-     struct window *w;
-     int start;
-     int vpos;
-     int hpos;
-     int taboffset;
-     int ovstr_done;
-{
-  register int pos = start;
-  int pos_byte = start_byte;
-  register int c;
-  register GLYPH *p1;
-  int pause, limit_byte;
-  register unsigned char *p;
-  GLYPH *endp;
-  register GLYPH *leftmargin;
-  register GLYPH *p1prev;
-  register GLYPH *p1start;
-  GLYPH *p1_wide_column_end = (GLYPH *) 0;
-  int prevpos, prevpos_byte;
-  int *charstart;
-  FRAME_PTR f = XFRAME (w->frame);
-  int tab_width = XINT (current_buffer->tab_width);
-  int ctl_arrow = !NILP (current_buffer->ctl_arrow);
-  int width = window_internal_width (w) - 1;
-  struct position val;
-  int lastpos, lastpos_byte;
-  int invis;
-  int last_invis_skip = 0;
-  Lisp_Object last_invis_prop;
-  int hscroll = XINT (w->hscroll);
-  int truncate = (hscroll
-		  || (truncate_partial_width_windows
-		      && !WINDOW_FULL_WIDTH_P (w))
-		  || !NILP (current_buffer->truncate_lines));
-
-  /* 1 if this buffer has a region to highlight.  */
-  int highlight_region
-    = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
-       && XMARKER (current_buffer->mark)->buffer != 0);
-  int region_beg, region_end;
-
-  int selective = (INTEGERP (current_buffer->selective_display)
-		   ? XINT (current_buffer->selective_display)
-		   : !NILP (current_buffer->selective_display) ? -1 : 0);
-  register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
-  register struct Lisp_Char_Table *dp = window_display_table (w);
-
-  Lisp_Object default_invis_vector[3];
-  /* Number of characters of ellipsis to display after an invisible line
-     if it calls for an ellipsis.
-     Note that this value can be nonzero regardless of whether
-     selective display is enabled--you must check that separately.  */
-  int selective_rlen
-    = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
-       ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
-       : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
-  /* This is the sequence of Lisp objects to display
-     when there are invisible lines.  */
-  Lisp_Object *invis_vector_contents
-    = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
-       ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
-       : default_invis_vector);
-
-  GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
-		     || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp)))
-		     ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
-  GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
-		     || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp)))
-		     ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
-
-  /* If 1, we must handle multibyte characters.  */
-  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
-  /* Length of multibyte form of each character.  */
-  int len;
-  /* Glyphs generated should be set this bit mask if text must be
-     displayed from right to left.  */
-  GLYPH rev_dir_bit = (NILP (current_buffer->direction_reversed)
-		       ? 0 : GLYPH_MASK_REV_DIR);
-
-  /* The next buffer location at which the face should change, due
-     to overlays or text property changes.  */
-  int next_face_change;
-
-  /* The next location where the `invisible' property changes, or an
-     overlay starts or ends.  */
-  int next_boundary;
-
-  /* The face we're currently using.  */
-  int current_face = 0;
-  int i;
-
-  XSETFASTINT (default_invis_vector[2], '.');
-  default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
-
-  get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
-  if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
-  /* Show where to highlight the region.  */
-  if (highlight_region
-      /* Maybe highlight only in selected window.  */
-      && (highlight_nonselected_windows
-	  || w == XWINDOW (selected_window)
-	  || (MINI_WINDOW_P (XWINDOW (selected_window))
-	      && w == XWINDOW (Vminibuf_scroll_window))))
-    {
-      region_beg = marker_position (current_buffer->mark);
-      if (PT < region_beg)
-	{
-	  region_end = region_beg;
-	  region_beg = PT;
-	}
-      else
-	region_end = PT;
-      w->region_showing = Qt;
-    }
-  else
-    {
-      region_beg = region_end = -1;
-      w->region_showing = Qnil;
-    }
-
-  if (MINI_WINDOW_P (w)
-      && start == BEG
-      && vpos == XFASTINT (w->top))
-    {
-      if (! NILP (minibuf_prompt))
-	{
-	  int old_width = minibuf_prompt_width;
-
-	  minibuf_prompt_width
-	    = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
-			       STRING_BYTES (XSTRING (minibuf_prompt)),
-			       hpos + WINDOW_LEFT_MARGIN (w),
-			       /* Display a space if we truncate.  */
-			       ' ',
-			       1, -1,
-			       /* Truncate the prompt a little before the
-				  margin, so user input can at least start
-				  on the first line.  */
-			       (XFASTINT (w->width) > 10
-				? XFASTINT (w->width) - 4 : -1),
-			       STRING_MULTIBYTE (minibuf_prompt))
-	       - hpos - WINDOW_LEFT_MARGIN (w));
-	  hpos += minibuf_prompt_width;
-	  taboffset -= minibuf_prompt_width - old_width;
-	}
-      else
-	minibuf_prompt_width = 0;
-    }
-
-  /* If we're hscrolled at all, use compute_motion to skip over any
-     text off the left edge of the window.  compute_motion may know
-     tricks to do this faster than we can.  */
-  if (hpos < 0)
-    {
-      struct position *left_edge
-        = compute_motion (pos, vpos, hpos, 0,
-                          ZV, vpos, 0,
-                          width, hscroll, taboffset, w);
-
-      /* Retrieve the buffer position and column provided by
-         compute_motion.  We can't assume that the column will be
-         zero, because you may have multi-column characters crossing
-         the left margin.  
-
-         compute_motion may have moved us past the screen position we
-         requested, if we hit a multi-column character, or the end of
-         the line.  If so, back up.  */
-      if ((left_edge->vpos > vpos
-	   || left_edge->hpos > 0)
-	  && left_edge->bufpos > pos)
-        {
-          pos = left_edge->bufpos;
-	  pos_byte = left_edge->bytepos;
-	  DEC_BOTH (pos, pos_byte);
-          hpos = left_edge->prevhpos;
-        }
-      else
-        {
-          pos = left_edge->bufpos;
-	  pos_byte = left_edge->bytepos;
-          hpos = left_edge->hpos;
-        }
-    }
-
-  hpos += WINDOW_LEFT_MARGIN (w);
-
-  desired_glyphs->bufp[vpos] = start;
-  p1 = desired_glyphs->glyphs[vpos] + hpos;
-  p1start = p1;
-  charstart = desired_glyphs->charstarts[vpos] + hpos;
-  /* In case we don't ever write anything into it...  */
-  desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
-  leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
-  endp = leftmargin + width;
+trailing_whitespace_p (charpos)
+     int charpos;
+{
+  int bytepos = CHAR_TO_BYTE (charpos);
+  int c = 0;
+
+  while (bytepos < ZV_BYTE
+	 && (c = FETCH_CHAR (bytepos),
+	     c == ' ' || c == '\t'))
+    ++bytepos;
+
+  return bytepos >= ZV_BYTE || c == '\n' || c == '\r';
+}
+
+
+/* Highlight trailing whitespace, if any, in ROW.  */
+
+void
+highlight_trailing_whitespace (f, row)
+     struct frame *f;
+     struct glyph_row *row;
+{
+  int used = row->used[TEXT_AREA];
+  
+  if (used)
+    {
+      struct glyph *start = row->glyphs[TEXT_AREA];
+      struct glyph *glyph = start + used - 1;
+
+      /* Skip over the space glyph inserted to display the
+	 cursor at the end of a line.  */
+      if (glyph->type == CHAR_GLYPH
+	  && glyph->u.ch.code == ' '
+	  && glyph->object == 0)
+	--glyph;
+
+      /* If last glyph is a space or stretch, and it's trailing
+	 whitespace, set the face of all trailing whitespace glyphs in
+	 IT->glyph_row to `trailing-whitespace'.  */
+      if (glyph >= start
+	  && BUFFERP (glyph->object)
+	  && (glyph->type == STRETCH_GLYPH
+	      || (glyph->type == CHAR_GLYPH
+		  && glyph->u.ch.code == ' '))
+	  && trailing_whitespace_p (glyph->charpos))
+	{
+	  int face_id = lookup_named_face (f, Qtrailing_whitespace,
+					   CHARSET_ASCII);
+	  
+	  while (glyph >= start
+		 && BUFFERP (glyph->object)
+		 && (glyph->type == STRETCH_GLYPH
+		     || (glyph->type == CHAR_GLYPH
+			 && glyph->u.ch.code == ' ')))
+	    {
+	      if (glyph->type == STRETCH_GLYPH)
+		glyph->u.stretch.face_id = face_id;
+	      else
+		glyph->u.ch.face_id = face_id;
+	      --glyph;
+	    }
+	}
+    }
+}
+
+
+
+/* Construct the glyph row IT->glyph_row in the desired matrix of
+   IT->w from text at the current position of IT.  See dispextern.h
+   for an overview of struct it.  Value is non-zero if
+   IT->glyph_row displays text, as opposed to a line displaying ZV
+   only.  */
+   
+static int
+display_line (it)
+     struct it *it;
+{
+  struct glyph_row *row = it->glyph_row;
+
+  /* We always start displaying at hpos zero even if hscrolled.  */
+  xassert (it->hpos == 0 && it->current_x == 0);
+
+  /* We must not display in a row that's not a text row.  */
+  xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
+	   < it->w->desired_matrix->nrows);
+
+  /* Is IT->w showing the region?  */
+  it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
+
+  /* Clear the result glyph row and enable it.  */
+  prepare_desired_row (row);
+
+  row->y = it->current_y;
+  row->start = it->current;
+  row->continuation_lines_width = it->continuation_lines_width;
+  row->displays_text_p = 1;
 
   /* Arrange the overlays nicely for our purposes.  Usually, we call
-     display_text_line on only one line at a time, in which case this
+     display_line on only one line at a time, in which case this
      can't really hurt too much, or we call it on lines which appear
      one after another in the buffer, in which case all calls to
      recenter_overlay_lists but the first will be pretty cheap.  */
-  recenter_overlay_lists (current_buffer, pos);
-
-  /* Loop generating characters.
-     Stop at end of buffer, before newline,
-     if reach or pass continuation column,
-     or at face change.  */
-  pause = pos;
-  limit_byte = pos_byte;
-  next_face_change = pos;
-  next_boundary = pos;
-  p1prev = p1;
-  prevpos = pos;
-  prevpos_byte = pos_byte;
-
-  /* If the window is hscrolled and point is in the invisible part of the
-     current line beyond the left margin we can record the cursor location
-     right away.  */
-  if (hscroll && start <= PT && PT < pos && cursor_vpos < 0)
-    {
-      cursor_vpos = vpos;
-      cursor_hpos = p1 - leftmargin;
-    }
-
-  while (p1 < endp)
-    {
-      if (pos >= pause)
-	{
-	  int e_t_h;
-
-	  while (pos == next_boundary)
+  recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
+
+#if NO_PROMPT_IN_BUFFER
+  /* Show mini-buffer prompt, if at the beginning of a mini-buffer
+     window.  */
+  if (MINI_WINDOW_P (it->w) 
+      && MATRIX_ROW_START_CHARPOS (row) == BEG 
+      && it->vpos == 0)
+    {
+      if (NILP (minibuf_prompt))
+	minibuf_prompt_width = minibuf_prompt_pixel_width = 0;
+      else
+	{
+	  /* We would like to truncate the prompt a little bit before
+	     the right margin of the window, so that user input can
+	     start on the first line.  Set max_x to this position.  */
+	  int max_x = (it->last_visible_x - 4 * CANON_X_UNIT (it->f));
+
+	  /* We use a temporary iterator different from IT so that
+	     IT's settings are not overwritten when displaying
+	     the prompt.  */
+	  struct it ti;
+
+	  ti = *it;
+
+	  /* Display the prompt.  Set minibuf_prompt_width to the 
+	     number of glyphs generated for the prompt, set
+	     minibuf_prompt_pixel_width to its width in pixels.  */
+	  xassert (it->current_x == 0);
+	  display_string (NULL, minibuf_prompt, Qnil, 0, 0, &ti,
+			  0, 0, max_x, -1);
+	  minibuf_prompt_width = ti.hpos;
+	  minibuf_prompt_pixel_width = ti.current_x;
+
+	  /* Transfer pixel and hpos information to IT.  */
+	  it->hpos = ti.hpos;
+	  it->current_x = ti.current_x;
+	}
+    }
+#endif /* NO_PROMPT_IN_BUFFER */
+
+  /* Move over display elements that are not visible because we are
+     hscrolled.  This may stop at an x-position < IT->first_visible_x
+     if the first glyph is partially visible or if we hit a line end.  */
+  if (it->current_x < it->first_visible_x)
+    move_it_in_display_line_to (it, ZV, it->first_visible_x,
+				MOVE_TO_POS | MOVE_TO_X);
+
+  /* Get the initial row height.  This is either the height of the
+     text hscrolled, if there is any, or zero.  */
+  row->ascent = it->max_ascent;
+  row->height = it->max_ascent + it->max_descent;
+
+  /* Loop generating characters.  The loop is left with IT on the next
+     character to display.  */
+  while (1)
+    {
+      int n_glyphs_before, hpos_before, x_before;
+      int x, i, nglyphs;
+      
+      /* Retrieve the next thing to display.  Value is zero if end of
+	 buffer reached.  */
+      if (!get_next_display_element (it))
+	{
+	  /* Maybe add a space at the end of this line that is used to
+	     display the cursor there under X.  */
+	  append_space (it, 1);
+
+	  /* The position -1 below indicates a blank line not
+	     corresponding to any text, as opposed to an empty line
+	     corresponding to a line end.  */
+	  if (row->used[TEXT_AREA] <= 1)
 	    {
-	      Lisp_Object position, limit, prop, ww;
-
-	      /* Display the overlay strings here, unless we're at ZV
-		 and have already displayed the appropriate strings
-		 on an earlier line.  */
-	      if (pos < ZV || !zv_strings_seen++)
+	      row->glyphs[TEXT_AREA]->charpos = -1;
+	      row->displays_text_p = 0;
+
+	      if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
+		row->indicate_empty_line_p = 1;
+	    }
+	  
+	  it->continuation_lines_width = 0;
+	  row->ends_at_zv_p = 1;
+	  break;
+	}
+
+      /* Now, get the metrics of what we want to display.  This also
+	 generates glyphs in `row' (which is IT->glyph_row).  */
+      n_glyphs_before = row->used[TEXT_AREA];
+      x = it->current_x;
+      PRODUCE_GLYPHS (it);
+
+      /* If this display element was in marginal areas, continue with
+	 the next one.  */
+      if (it->area != TEXT_AREA)
+	{
+	  row->ascent = max (row->ascent, it->max_ascent);
+	  row->height = max (row->height, it->max_ascent + it->max_descent);
+	  set_iterator_to_next (it);
+	  continue;
+	}
+
+      /* Does the display element fit on the line?  If we truncate
+	 lines, we should draw past the right edge of the window.  If
+	 we don't truncate, we want to stop so that we can display the
+	 continuation glyph before the right margin.  If lines are
+	 continued, there are two possible strategies for characters
+	 resulting in more than 1 glyph (e.g. tabs): Display as many
+	 glyphs as possible in this line and leave the rest for the
+	 continuation line, or display the whole element in the next
+	 line.  Original redisplay did the former, so we do it also.  */
+      nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
+      hpos_before = it->hpos;
+      x_before = x;
+	  
+      if (nglyphs == 1
+	  && it->current_x < it->last_visible_x)
+	{
+	  ++it->hpos;
+	  row->ascent = max (row->ascent, it->max_ascent);
+	  row->height = max (row->height, it->max_ascent + it->max_descent);
+	  if (it->current_x - it->pixel_width < it->first_visible_x)
+	    row->x = x - it->first_visible_x;
+	}
+      else
+	{
+	  int new_x;
+	  struct glyph *glyph;
+	  
+	  for (i = 0; i < nglyphs; ++i, x = new_x)
+	    {
+	      glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
+	      new_x = x + glyph->pixel_width;
+
+	      if (/* Lines are continued.  */
+		  !it->truncate_lines_p
+		  && (/* Glyph doesn't fit on the line.  */
+		      new_x > it->last_visible_x
+		      /* Or it fits exactly on a window system frame.  */
+		      || (new_x == it->last_visible_x
+			  && FRAME_WINDOW_P (it->f))))
 		{
-		  int ovlen;
-		  unsigned char *ovstr;
-		  ovlen = overlay_strings (pos, w, &ovstr);
-
-		  if (ovlen > 0)
+		  /* End of a continued line.  */
+		  
+		  if (it->hpos == 0
+		      || (new_x == it->last_visible_x
+			  && FRAME_WINDOW_P (it->f)))
 		    {
-		      /* Skip the ones we did in a previous line.  */
-		      ovstr += ovstr_done;
-		      ovlen -= ovstr_done;
-
-		      while (ovlen > 0 && p1 < endp)
-			{
-			  int charset, cols;
-			  GLYPH g;
-
-			  if (multibyte)
-			    {
-			      c = STRING_CHAR_AND_LENGTH (ovstr, ovlen, len);
-			      ovstr += len, ovlen -= len, ovstr_done += len;
-			      charset = CHAR_CHARSET (c);
-			      cols = (charset == CHARSET_COMPOSITION
-				      ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
-				      : CHARSET_WIDTH (charset));
-			    }
-			  else
-			    {
-			      c = *ovstr++, ovlen--, ovstr_done++;
-			      cols = 1;
-			    }
-			  g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
-			  while (cols-- > 0)
-			    {
-			      if (p1 >= leftmargin && p1 < endp)
-				*p1 = g, g |= GLYPH_MASK_PADDING;
-			      p1++;
-			    }
-			}
-		      /* If we did all the overlay strings
-			 and we have room for text, clear ovstr_done
-			 just for neatness' sake.  */
-		      if (ovlen == 0 && p1 < endp)
-			ovstr_done = 0;
+		      /* Current glyph fits exactly on the line.  We
+			 must continue the line because we can't draw
+			 the cursor after the glyph.  */
+		      row->continued_p = 1;
+		      it->current_x = new_x;
+		      it->continuation_lines_width += new_x;
+		      ++it->hpos;
+		      if (i == nglyphs - 1)
+			set_iterator_to_next (it);
 		    }
+		  else
+		    {
+		      /* Display element draws past the right edge of
+			 the window.  Restore positions to values
+			 before the element.  The next line starts
+			 with current_x before the glyph that could
+			 not be displayed, so that TAB works right.  */
+		      row->used[TEXT_AREA] = n_glyphs_before + i;
+		  
+		      /* Display continuation glyphs.  */
+		      if (!FRAME_WINDOW_P (it->f))
+			produce_special_glyphs (it, IT_CONTINUATION);
+		      row->continued_p = 1;
+		      
+		      it->current_x = x;
+		      it->continuation_lines_width += x;
+		    }
+		  break;
 		}
-
-	      /* Did we reach point?  Record the cursor location.  */
-	      if (pos == PT && cursor_vpos < 0)
-		{
-		  cursor_vpos = vpos;
-		  cursor_hpos = p1 - leftmargin;
-		}
-
-	      if (pos >= ZV)
-		break;
-
-	      XSETFASTINT (position, pos);
-	      limit = Fnext_overlay_change (position);
-#ifdef USE_TEXT_PROPERTIES
-	      /* This is just an estimate to give reasonable
-		 performance; nothing should go wrong if it is too small.  */
-	      if (XFASTINT (limit) > pos + 50)
+	      else if (new_x > it->first_visible_x)
 		{
-		  int limitpos = pos + 50;
-		  XSETFASTINT (limit, limitpos);
+		  /* Increment number of glyphs actually displayed.  */
+		  ++it->hpos;
+		  
+		  if (x < it->first_visible_x)
+		    /* Glyph is partially visible, i.e. row starts at
+		       negative X position.  */
+		    row->x = x - it->first_visible_x;
 		}
-	      limit = Fnext_single_property_change (position, Qinvisible,
-						    Fcurrent_buffer (), limit);
-#endif
-	      next_boundary = XFASTINT (limit);
-	      /* if the `invisible' property is set, we can skip to
-		 the next property change.  */
-	      XSETWINDOW (ww, w);
-	      prop = Fget_char_property (position, Qinvisible, ww);
-	      if (TEXT_PROP_MEANS_INVISIBLE (prop))
+	      else
 		{
-		  if (pos < PT && next_boundary >= PT)
-		    {
-		      cursor_vpos = vpos;
-		      cursor_hpos = p1 - leftmargin;
-		    }
-		  pos = next_boundary;
-		  pos_byte = CHAR_TO_BYTE (pos);
-		  last_invis_skip = pos;
-		  last_invis_prop = prop;
+		  /* Glyph is completely off the left margin of the
+		     window.  This should not happen because of the
+		     move_it_in_display_line at the start of
+		     this function.  */
+		  abort ();
 		}
 	    }
-
-	  /* Did we reach point?  Record the cursor location.  */
-	  if (pos == PT && cursor_vpos < 0)
-	    {
-	      cursor_vpos = vpos;
-	      cursor_hpos = p1 - leftmargin;
-	    }
-
-	  /* Did we hit the end of the visible region of the buffer?
-	     Stop here.  */
-	  if (pos >= ZV)
-	    {
-	      /* Update charstarts for the end of this line.  */
-	      /* Do nothing if off the left edge or at the right edge.  */
-	      if (p1 >= leftmargin && p1 + 1 != endp)
-		{
-		  int *p2x = &charstart[(p1 < leftmargin
-					 ? leftmargin : p1)
-					- p1start];
-		  *p2x++ = pos;
-		}
-	      break;
-	    }
-
-	  /* Figure out where (if at all) the
-	     redisplay_end_trigger-hook should run.  */
-	  if (MARKERP (w->redisplay_end_trigger)
-	      && XMARKER (w->redisplay_end_trigger)->buffer != 0)
-	    e_t_h = marker_position (w->redisplay_end_trigger);
-	  else if (INTEGERP (w->redisplay_end_trigger))
-	    e_t_h = XINT (w->redisplay_end_trigger);
-	  else
-	    e_t_h = ZV;
-
-	  /* If we've gone past the place to run a hook,
-	     run the hook.  */
-	  if (pos >= e_t_h && e_t_h != ZV)
-	    {
-	      Lisp_Object args[3];
-
-	      args[0] = Qredisplay_end_trigger_functions;
-	      XSETWINDOW (args[1], w);
-	      XSETINT (args[2], e_t_h);
-
-	      /* Since we are *trying* to run these functions,
-		 don't try to run them again, even if they get an error.  */
-	      w->redisplay_end_trigger = Qnil;
-	      Frun_hook_with_args (3, args);
-
-	      e_t_h = ZV;
-	      /* Notice if it changed the face of this character.  */
-	      next_face_change = pos;
-	    }
-
-#ifdef HAVE_FACES
-	  /* Did we hit a face change?  Figure out what face we should
-	     use now.  We also hit this the first time through the
-	     loop, to see what face we should start with.  */
-	  if (pos >= next_face_change
-	      && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
-	    {
-	      int limit = pos + 50;
-
-	      current_face = compute_char_face (f, w, pos,
-						region_beg, region_end,
-						&next_face_change, limit, 0);
-	    }
-#endif
-
-	  /* Compute the next place we need to stop
-	     and do something special; set PAUSE.  */
-
-	  pause = ZV;
-
-	  if (pos < next_boundary && next_boundary < pause)
-	    pause = next_boundary;
-	  if (pos < next_face_change && next_face_change < pause)
-	    pause = next_face_change;
-
-	  if (e_t_h < pause)
-	    pause = e_t_h;
-
-	  /* Wouldn't you hate to read the next line to someone over
-             the phone?  */
-	  if (pos < PT && PT < pause)
-	    pause = PT;
-	  if (pos < GPT && GPT < pause)
-	    pause = GPT;
-
-	  /* LIMIT_BYTE is not the same place in the buffer as PAUSE.
-	     It is a limit on valid characters.
-	     We use it to bound STRING_CHAR_AND_LENGTH.  */
-	  limit_byte = ZV_BYTE;
-	  if (pos < GPT && GPT_BYTE < limit_byte)
-	    limit_byte = GPT_BYTE;
-
-	  {
-	    int temp = CHAR_TO_BYTE (pos);
-	    p = BYTE_POS_ADDR (temp);
-	  }
-	}
-
-      if (p1 >= endp)
-	break;
-
-      p1prev = p1;
-      p1_wide_column_end = (GLYPH *) 0;
-
-      if (multibyte)
-	c = STRING_CHAR_AND_LENGTH (p, limit_byte - pos_byte, len), p += len;
-      else
-	c = *p++, len = 1;
-      /* Let a display table override all standard display methods.  */
-      if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
-	{
-	  p1 = copy_part_of_rope (f, p1, leftmargin,
-				  XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
-				  XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
-				  current_face, rev_dir_bit);
-	}
-      else if (c >= 040 && c < 0177)
-	{
-	  if (p1 >= leftmargin)
-	    *p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
-	  p1++;
-	}
-      else if (c == '\n')
-	{
-#if 0
-	  /* Same as p1prev, but after the invis_vector_contents text
-	     (if we have that on this line).  */
-	  GLYPH *p1prev_modified;
-#endif
-
-	  invis = 0;
-	  if (last_invis_skip == pos
-	      && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
-	    invis = 1;
-	  while (pos + 1 < ZV
-		 && selective > 0
-		 && indented_beyond_p (pos + 1, pos_byte + 1, selective))
-	    {
-	      int opoint = PT, opoint_byte = PT_BYTE;
-
-	      invis = 1;
-	      INC_BOTH (pos, pos_byte);
-	      scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
-	      pos = PT, pos_byte = PT_BYTE;
-	      if (FETCH_BYTE (pos_byte - 1) == '\n')
-		{
-		  pos--;
-		  pos_byte--;
-		}
-	      TEMP_SET_PT_BOTH (opoint, opoint_byte);
-	    }
-	  if (invis && selective_rlen > 0 && p1 >= leftmargin)
-	    {
-#if 0
-	      GLYPH *cs, *csend;
-
-	      cs = charstart + (p1 - p1start);
-#endif
-
-	      p1 += selective_rlen;
-	      if (p1 - leftmargin > width)
-		p1 = endp;
-
-#if 0 /* This needs more work; charstarts needs to record
-	 both whether a position ho;ds an ellipsis character
-	 and what buffer position it corresponds to.  */
-	      csend = charstart + (p1 - p1start);
-	      while (cs != csend)
-		*cs++ = -2;
-	      /* The idea is to use p1prev_modified instead of p1prev
-		 in the loop below over p2x.  */
-	      p1prev_modified = p1;
-#endif
-
-	      copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
-				 (p1 - p1prev), current_face, rev_dir_bit);
-	    }
-
-	  /* Update charstarts for the newline that ended this line.  */
-	  /* Do nothing here for a char that's entirely off the left edge
-	     or if it starts at the right edge.  */
-	  if (p1 >= leftmargin && p1prev != endp)
-	    {
-	      /* Store the newline's position into charstarts
-		 for the column where the newline starts.
-		 Store -1 for the rest of the glyphs it occupies.  */
-	      int *p2x = &charstart[(p1prev < leftmargin
-				     ? leftmargin : p1prev)
-				    - p1start];
-	      int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
-	      *p2x++ = pos;
-	      while (p2x < p2)
-		*p2x++ = -1;
-	    }
-#ifdef HAVE_FACES
-	  /* Draw the face of the newline character as extending all the 
-	     way to the end of the frame line.  */
-	  if (current_face)
-	    {
-	      if (p1 < leftmargin)
-		p1 = leftmargin;
-	      while (p1 < endp)
-		*p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
-	    }
-#endif
-
-	  break;
-	}
-      else if (c == '\t')
-	{
-	  do
-	    {
-	      if (p1 >= leftmargin && p1 < endp)
-		*p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit;
-	      p1++;
-	    }
-	  while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
-		 % tab_width);
-	}
-      else if (c == Ctl ('M') && selective == -1)
-	{
-	  int opoint = PT, opoint_byte = PT_BYTE;
-	  scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
-	  pos = PT, pos_byte = PT_BYTE;
-	  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-
-	  if (FETCH_BYTE (pos_byte - 1) == '\n')
-	    pos--, pos_byte--;
-	  if (selective_rlen > 0)
-	    {
-	      p1 += selective_rlen;
-	      if (p1 - leftmargin > width)
-		p1 = endp;
-	      copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
-				 (p1 - p1prev), current_face, rev_dir_bit);
-	    }
-#ifdef HAVE_FACES
-	  /* Draw the face of the newline character as extending all the 
-	     way to the end of the frame line.  */
-	  if (current_face)
-	    {
-	      if (p1 < leftmargin)
-		p1 = leftmargin;
-	      while (p1 < endp)
-		*p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
-	    }
-#endif
-
-	  /* Update charstarts for the ^M that ended this line.  */
-	  /* Do nothing here for a char that's entirely off the left edge
-	     or if it starts at the right edge.  */
-	  if (p1 >= leftmargin && p1prev != endp)
-	    {
-	      /* Store the newline's position into charstarts
-		 for the column where the newline starts.
-		 Store -1 for the rest of the glyphs it occupies.  */
-	      int *p2x = &charstart[(p1prev < leftmargin
-				     ? leftmargin : p1prev)
-				    - p1start];
-	      int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
-	      *p2x++ = pos;
-	      while (p2x < p2)
-		*p2x++ = -1;
-	    }
+	  
+	  row->ascent = max (row->ascent, it->max_ascent);
+	  row->height = max (row->height, it->max_ascent + it->max_descent);
+	  
+	  /* End of this display line if row is continued.  */
+	  if (row->continued_p)
+	    break;
+	}
+
+      /* Is this a line end?  If yes, we're also done, after making
+	 sure that a non-default face is extended up to the right
+	 margin of the window.  */
+      if (ITERATOR_AT_END_OF_LINE_P (it))
+	{
+	  int used_before = row->used[TEXT_AREA];
+
+	  /* Add a space at the end of the line that is used to
+	     display the cursor there.  */
+	  append_space (it, 0);
+	  
+	  /* Extend the face to the end of the line.  */
+	  extend_face_to_end_of_line (it);
+
+	  /* Make sure we have the position.  */
+	  if (used_before == 0)
+	    row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
+	  
+	  /* Consume the line end.  This skips over invisible lines.  */
+	  set_iterator_to_next (it);
+	  it->continuation_lines_width = 0;
 	  break;
 	}
-      else if (c < 0200 && ctl_arrow)
-	{
-	  if (p1 >= leftmargin)
-	    *p1 = (fix_glyph
-		   (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
-			&& GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
-			? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
-		    current_face)
-		   | rev_dir_bit);
-	  p1++;
-	  if (p1 >= leftmargin && p1 < endp)
-	    *p1 = MAKE_GLYPH (f, c ^ 0100, current_face) | rev_dir_bit;
-	  p1++;
-	}
-      else
-	{
-	  /* C is a multibyte character or a character to be displayed
-             by octal form.  */
-	  int remaining_bytes = len;
-
-	  if (unibyte_display_via_language_environment
-	      && SINGLE_BYTE_CHAR_P (c)
-	      && (c >= 0240
-		  || (c >= 0200 && !NILP (Vnonascii_translation_table))))
-	    c = unibyte_char_to_multibyte (c);
-
-	  if (c >= 0400 && CHAR_VALID_P (c, 0))
-	    {
-	      /* C is a multibyte character.  */
-	      int charset = CHAR_CHARSET (c);
-	      int columns = (charset == CHARSET_COMPOSITION
-			     ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
-			     : CHARSET_WIDTH (charset));
-	      GLYPH g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
-
-	      while (columns--)
-		{
-		  if (p1 >= leftmargin && p1 < endp)
-		    *p1 = g, g |= GLYPH_MASK_PADDING;
-		  p1++;
-		}
-	      p1_wide_column_end = p1;
-	      remaining_bytes -= CHARSET_BYTES (charset);
-	    }
-
-	  while (remaining_bytes > 0)
-	    {
-	      c = *(p - remaining_bytes--);
-
-	      if (p1 >= leftmargin && p1 < endp)
-		*p1 = (fix_glyph
-		       (f,
-			(dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
-			 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
-			 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
-			current_face)
-		       | rev_dir_bit);
-	      p1++;
-	      if (p1 >= leftmargin && p1 < endp)
-		*p1 = (MAKE_GLYPH (f, (c >> 6) + '0', current_face)
-		       | rev_dir_bit);
-	      p1++;
-	      if (p1 >= leftmargin && p1 < endp)
-		*p1 = (MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face)
-		       | rev_dir_bit);
-	      p1++;
-	      if (p1 >= leftmargin && p1 < endp)
-		*p1 = (MAKE_GLYPH (f, (7 & c) + '0', current_face)
-		       | rev_dir_bit);
-	      p1++;
-	    }
-	}
-
-      prevpos = pos;
-      prevpos_byte = pos_byte;
-      pos++;
-      pos_byte += len;
-
-      /* Update charstarts for the character just output.  */
-
-      /* Do nothing here for a char that's entirely off the left edge.  */
-      if (p1 >= leftmargin)
-	{
-	  /* Store the char's position into charstarts
-	     for the first glyph occupied by this char.
-	     Store -1 for the rest of the glyphs it occupies.  */
-	  if (p1 != p1prev)
-	    {
-	      int *p2x = &charstart[(p1prev < leftmargin
-				     ? leftmargin : p1prev)
-				    - p1start];
-	      int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
-	      if (p2x < p2)
-		*p2x++ = prevpos;
-	      while (p2x < p2)
-		*p2x++ = -1;
-	    }
-	}
-    }
-
-  val.hpos = - XINT (w->hscroll);
-  if (val.hpos)
-    val.hpos++;
-
-  val.vpos = 1;
-
-  lastpos = pos;
-  lastpos_byte = pos_byte;
-
-  /* Store 0 in this charstart line for the positions where
-     there is no character.  But do leave what was recorded
-     for the character that ended the line.  */
-  /* Add 1 in the endtest to compensate for the fact that ENDP was
-     made from WIDTH, which is 1 less than the window's actual
-     internal width.  */
-  i = p1 - p1start + 1;
-  if (p1 < leftmargin)
-    i += leftmargin - p1;
-  for (; i < endp - p1start + 1; i++)
-    charstart[i] = 0;
-
-  /* Handle continuation in middle of a character */
-  /* by backing up over it */
-  if (p1 > endp)
-    {
-      /* Don't back up if we never actually displayed any text.
-	 This occurs when the minibuffer prompt takes up the whole line.  */
-      if (p1prev)
-	{
-	  /* Start the next line with that same character whose
-             character code is C and the length of multi-byte form is
-             LEN.  */
-	  pos = prevpos;
-	  pos_byte = prevpos_byte;
-
-	  if (p1_wide_column_end < endp)
-	    /* As ENDP is not in the middle of wide-column character,
-	       we can break the line at ENDP and start from the middle
-	       column in the next line.  So, adjust VAL.HPOS to skip
-	       the columns output on this line.  */
-	    val.hpos += p1prev - endp;
-	  else
+
+      /* Proceed with next display element.  Note that this skips 
+	 over lines invisible because of selective display.  */
+      set_iterator_to_next (it);
+
+      /* If we truncate lines, we are done when the last displayed
+	 glyphs reach past the right margin of the window.  */
+      if (it->truncate_lines_p
+	  && (FRAME_WINDOW_P (it->f)
+	      ? (it->current_x >= it->last_visible_x)
+	      : (it->current_x > it->last_visible_x)))
+	{
+	  /* Maybe add truncation glyphs.  */
+	  if (!FRAME_WINDOW_P (it->f))
 	    {
-	      /* We displayed a wide-column character at around ENDP.
-		 Since we can't broke it in the middle, the whole
-		 character should be driven into the next line.  */
-	      /* As the result, the actual columns occupied by the
-		 text on this line is less than WIDTH.  VAL.TAB_OFFSET
-		 must be adjusted.  */
-	      taboffset = taboffset + (p1prev - endp);
-	      /* Let's fill unused columns with TRUNCATOR or CONTINUER.  */
-	      {
-		GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0);
-		while (p1prev < endp)
-		  *p1prev++ = g;
-	      }
-	      /* If POINT is at POS, cursor should not on this line.  */
-	      lastpos = pos;
-	      lastpos_byte = pos_byte;
-	      if (PT == pos)
-		cursor_vpos = -1;
-	    }
-	}
-
-      /* Keep in this line everything up to the continuation column.  */
-      p1 = endp;
-    }
-
-  /* Finish deciding which character to start the next line on,
-     and what hpos to start it at.
-     Also set `lastpos' to the last position which counts as "on this line"
-     for cursor-positioning.  */
-
-  if (pos < ZV)
-    {
-      if (FETCH_BYTE (pos_byte) == '\n')
-	{
-	  int opoint = PT, opoint_byte = PT_BYTE;
-
-	  /* If stopped due to a newline, start next line after it */
-	  TEMP_SET_PT_BOTH (pos + 1, pos_byte + 1);
-
-	  val.tab_offset = 0;
-	  /* Check again for hidden lines, in case the newline occurred exactly
-	     at the right margin.  */
-	  while (PT < ZV && selective > 0
-		 && indented_beyond_p (PT, PT_BYTE, selective))
-	    scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
-
-	  pos = PT, pos_byte = PT_BYTE;
-	  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-	}
-      else
-	/* Stopped due to right margin of window */
-	{
-	  if (truncate)
-	    {
-	      int opoint = PT, opoint_byte = PT_BYTE;
-
-	      TEMP_SET_PT_BOTH (pos, pos_byte);
-	      *p1++ = fix_glyph (f, truncator, 0);
-	      /* Truncating => start next line after next newline,
-		 and point is on this line if it is before the newline,
-		 and skip none of first char of next line */
-	      do
-		scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
-	      while (PT < ZV && selective > 0
-		     && indented_beyond_p (PT, PT_BYTE, selective));
-	      pos = PT, pos_byte = PT_BYTE;
-	      val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
-	      TEMP_SET_PT_BOTH (opoint, opoint_byte);
-
-	      lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n');
-	      lastpos_byte = CHAR_TO_BYTE (lastpos);
-	      val.tab_offset = 0;
-	    }
-	  else
-	    {
-	      *p1++ = fix_glyph (f, continuer, 0);
-	      val.vpos = 0;
-	      DEC_BOTH (lastpos, lastpos_byte);
-	      val.tab_offset = taboffset + width;
+	      --it->glyph_row->used[TEXT_AREA];
+	      produce_special_glyphs (it, IT_TRUNCATION);
 	    }
-	}
-    }
-  else
-    val.tab_offset = 0;
-
-  /* If point is at eol or in invisible text at eol,
-     record its frame location now.  */
-
-  if (start <= PT && PT <= lastpos && cursor_vpos < 0)
-    {
-      cursor_vpos = vpos;
-      cursor_hpos = p1 - leftmargin;
-    }
-
-  if (cursor_vpos == vpos)
-    {
-      if (cursor_hpos < 0) cursor_hpos = 0;
-      if (cursor_hpos > width) cursor_hpos = width;
-      cursor_hpos += WINDOW_LEFT_MARGIN (w);
-      if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
-	{
-	  this_line_bufpos = 0;
-
-	  /* If this frame's cursor will be in its echo area,
-	     don't record a cursor from the window text,
-	     and turn off the optimization for cursor-motion-only case.  */
-	  if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
-		&& EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
-	    {
-	      FRAME_CURSOR_Y (f) = cursor_vpos;
-	      FRAME_CURSOR_X (f) = cursor_hpos;
-
-	      if (w == XWINDOW (selected_window))
-		{
-		  /* Line is not continued and did not start
-		     in middle of character */
-		  if ((hpos - WINDOW_LEFT_MARGIN (w)
-		       == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
-		      && val.vpos)
-		    {
-		      this_line_bufpos = start;
-		      this_line_buffer = current_buffer;
-		      this_line_vpos = cursor_vpos;
-		      this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w);
-		      this_line_endpos = Z - lastpos;
-		    }
-		}
-	    }
-	}
-    }
-
-  /* If hscroll and line not empty, insert truncation-at-left marker */
-  if (hscroll && lastpos != start)
-    {
-      GLYPH g = fix_glyph (f, truncator, 0);
-      *leftmargin = g;
-      if (p1 <= leftmargin)
-	p1 = leftmargin + 1;
-      else			/* MULE: it may be a wide-column character */
-	{
-	  p1prev = leftmargin + 1;
-	  while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING)
-	    *p1prev++ = g;
-	}
-    }
-
-  if (!WINDOW_RIGHTMOST_P (w))
-    {
-      endp++;
-      if (p1 < leftmargin) p1 = leftmargin;
-      while (p1 < endp) *p1++ = SPACEGLYPH;
-
-      /* Don't draw vertical bars if we're using scroll bars.  They're
-         covered up by the scroll bars, and it's distracting to see
-         them when the scroll bar windows are flickering around to be
-         reconfigured.  */
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-	{
-	  int i;
-	  for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
-	    *p1++ = SPACEGLYPH;
-	}
-      else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-	*p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
-		 ? XINT (DISP_BORDER_GLYPH (dp))
-		 : '|');
-    }
-  desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
-				   p1 - desired_glyphs->glyphs[vpos]);
-  desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
-
-  /* If the start of this line is the overlay arrow-position,
-     then put the arrow string into the display-line.  */
-
+	  
+	  row->truncated_on_right_p = 1;
+	  it->continuation_lines_width = 0;
+	  reseat_at_next_visible_line_start (it);
+	  row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
+	  it->hpos = hpos_before;
+	  it->current_x = x_before;
+	  break;
+	}
+    }
+
+  /* If line is not empty and hscrolled, maybe insert truncation glyphs
+     at the left window margin.  */
+  if (it->first_visible_x
+      && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
+    {
+      if (!FRAME_WINDOW_P (it->f))
+	insert_left_trunc_glyphs (it);
+      row->truncated_on_left_p = 1;
+    }
+
+  /* If the start of this line is the overlay arrow-position, then
+     mark this glyph row as the one containing the overlay arrow.
+     This is clearly a mess with variable size fonts.  It would be
+     better to let it be displayed like cursors under X.  */
   if (MARKERP (Voverlay_arrow_position)
       && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
-      && start == marker_position (Voverlay_arrow_position)
+      && (MATRIX_ROW_START_CHARPOS (row)
+	  == marker_position (Voverlay_arrow_position))
       && STRINGP (Voverlay_arrow_string)
       && ! overlay_arrow_seen)
     {
-      int i, i_byte;
-      int len = XSTRING (Voverlay_arrow_string)->size;
-      int arrow_end;
-
-      if (len > width)
-	len = width;
-
-      /* If the arrow string has text props, obey them when displaying.  */
-      for (i = 0, i_byte = 0; i < len; )
-	{
-	  int c;
-	  Lisp_Object face, ilisp;
-	  int newface;
-	  int idx = i;
-
-	  if (STRING_MULTIBYTE (Voverlay_arrow_string))
-	    FETCH_STRING_CHAR_ADVANCE (c, Voverlay_arrow_string, i, i_byte);
-	  else
-	    c = XSTRING (Voverlay_arrow_string)->data[i++];
-
-	  XSETFASTINT (ilisp, i);
-#ifdef HAVE_FACES
-	  if (FRAME_WINDOW_P (f))
+      /* Overlay arrow in window redisplay is a bitmap.  */
+      if (!FRAME_WINDOW_P (it->f))
+	{
+	  struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
+	  struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
+	  struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
+	  struct glyph *p = row->glyphs[TEXT_AREA];
+	  struct glyph *p2, *end;
+
+	  /* Copy the arrow glyphs.  */
+	  while (glyph < arrow_end)
+	    *p++ = *glyph++;
+
+	  /* Throw away padding glyphs.  */
+	  p2 = p;
+	  end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+	  while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
+	    ++p2;
+	  if (p2 > p)
 	    {
-	      face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
-	      newface = compute_glyph_face_1 (f, face, 0);
-	      c = FAST_MAKE_GLYPH (c, newface);
+	      while (p2 < end)
+		*p++ = *p2++;
+	      row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
 	    }
-#endif /* HAVE_FACES */
-	  leftmargin[idx] = c;
-	}
-
-      /* Bug in SunOS 4.1.1 compiler requires this intermediate variable.  */
-      arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
-      if (desired_glyphs->used[vpos] < arrow_end)
-	desired_glyphs->used[vpos] = arrow_end;
-
+	}
+      
       overlay_arrow_seen = 1;
-    }
-
-  val.bufpos = pos;
-  val.bytepos = pos_byte;
-  val.ovstring_chars_done = ovstr_done;
-  val_display_text_line = val;
-  return &val_display_text_line;
-}
+      row->overlay_arrow_p = 1;
+    }
+
+  /* Compute pixel dimensions of this line.  */
+  compute_line_metrics (it);
+
+  /* Remember the position at which this line ends.  */
+  row->end = it->current;
+
+  /* Maybe set the cursor.  If you change this, it's probably a good
+     idea to also change the code in redisplay_window for cursor
+     movement in an unchanged window.  */
+  if (it->w->cursor.vpos < 0
+      && PT >= MATRIX_ROW_START_CHARPOS (row)
+      && MATRIX_ROW_END_CHARPOS (row) >= PT
+      && !(MATRIX_ROW_END_CHARPOS (row) == PT
+	   && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+	       || !row->ends_at_zv_p)))
+    set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
+
+  /* Highlight trailing whitespace.  */
+  if (it->show_trailing_whitespace_p)
+    highlight_trailing_whitespace (it->f, it->glyph_row);
+
+  /* Prepare for the next line.  This line starts horizontally at (X
+     HPOS) = (0 0).  Vertical positions are incremented.  As a
+     convenience for the caller, IT->glyph_row is set to the next
+     row to be used.  */
+  it->current_x = it->hpos = 0;
+  it->current_y += row->height;
+  ++it->vpos;
+  ++it->glyph_row;
+  return row->displays_text_p;
+}
+
+
 
-/* Redisplay the menu bar in the frame for window W.  */
+/***********************************************************************
+			       Menu Bar
+ ***********************************************************************/
+
+/* Redisplay the menu bar in the frame for window W.
+
+   The menu bar of X frames that don't have X toolkit support is
+   displayed in a special window W->frame->menu_bar_window.
+   
+   The menu bar of terminal frames is treated specially as far as
+   glyph matrices are concerned.  Menu bar lines are not part of
+   windows, so the update is done directly on the frame matrix rows
+   for the menu bar.  */
 
 static void
 display_menu_bar (w)
      struct window *w;
 {
-  Lisp_Object items, tail;
-  register int vpos = 0;
-  register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-  int maxendcol = FRAME_WIDTH (f);
-  int hpos = 0;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct it it;
+  Lisp_Object items;
   int i;
 
+  /* Don't do all this for graphical frames.  */
 #ifdef HAVE_NTGUI
   if (!NILP (Vwindow_system))
     return;
 #endif
+#ifdef USE_X_TOOLKIT
+  if (FRAME_X_P (f))
+    return;
+#endif
 
 #ifdef USE_X_TOOLKIT
-  if (FRAME_X_P (f))
-    return;
-#endif /* USE_X_TOOLKIT */
-
-  get_display_line (f, vpos, 0);
-
-  items = FRAME_MENU_BAR_ITEMS (f);
+  xassert (!FRAME_WINDOW_P (f));
+  init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MODE_LINE_FACE_ID);
+  it.first_visible_x = 0;
+  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+#else /* not USE_X_TOOLKIT */
+  if (FRAME_WINDOW_P (f))
+    {
+      /* Menu bar lines are displayed in the desired matrix of the
+	 dummy window menu_bar_window.  */
+      struct window *menu_w;
+      xassert (WINDOWP (f->menu_bar_window));
+      menu_w = XWINDOW (f->menu_bar_window);
+      init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
+		     MODE_LINE_FACE_ID);
+      it.first_visible_x = 0;
+      it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+    }
+  else
+    {
+      /* This is a TTY frame, i.e. character hpos/vpos are used as
+	 pixel x/y.  */
+      init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
+		     MODE_LINE_FACE_ID);
+      it.first_visible_x = 0;
+      it.last_visible_x = FRAME_WIDTH (f);
+    }
+#endif /* not USE_X_TOOLKIT */
+
+  /* Clear all rows of the menu bar.  */
+  for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
+    {
+      struct glyph_row *row = it.glyph_row + i;
+      clear_glyph_row (row);
+      row->enabled_p = 1;
+      row->full_width_p = 1;
+    }
+
+  /* Make the first line of the menu bar appear in reverse video.  */
+  it.glyph_row->inverse_p = mode_line_inverse_video != 0;
+
+  /* Display all items of the menu bar.  */
+  items = FRAME_MENU_BAR_ITEMS (it.f);
   for (i = 0; i < XVECTOR (items)->size; i += 4)
     {
-      Lisp_Object pos, string;
+      Lisp_Object string;
+
+      /* Stop at nil string.  */
       string = XVECTOR (items)->contents[i + 1];
       if (NILP (string))
 	break;
 
-      XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
-
-      if (hpos < maxendcol)
-	hpos = display_string (w, vpos,
-			       XSTRING (string)->data,
-			       STRING_BYTES (XSTRING (string)),
-			       hpos, 0, 0, hpos, maxendcol,
-			       STRING_MULTIBYTE (string));
-      /* Put a space between items.  */
-      if (hpos < maxendcol)
-	{
-	  int hpos1 = hpos + 1;
-	  hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
-				 min (hpos1, maxendcol), maxendcol, 0);
-	}
-    }
-
-  FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
-  FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
+      /* Remember where item was displayed.  */
+      XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
+
+      /* Display the item, pad with one space.  */
+      if (it.current_x < it.last_visible_x)
+	display_string (NULL, string, Qnil, 0, 0, &it,
+			XSTRING (string)->size + 1, 0, 0, -1);
+    }
 
   /* Fill out the line with spaces.  */
-  if (maxendcol > hpos)
-    hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0);
-
-  /* Clear the rest of the lines allocated to the menu bar.  */
-  vpos++;
-  while (vpos < FRAME_MENU_BAR_LINES (f))
-    get_display_line (f, vpos++, 0);
-}
+  if (it.current_x < it.last_visible_x)
+    display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
+
+  /* Compute the total height of the lines.  */
+  compute_line_metrics (&it);
+}
+
+
 
-/* Display the mode line for window w */
+/***********************************************************************
+			      Mode Line
+ ***********************************************************************/
+
+/* Display the mode and/or top line of window W.  */
 
 static void
-display_mode_line (w)
+display_mode_lines (w)
      struct window *w;
 {
-  register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
-  register int left = WINDOW_LEFT_MARGIN (w);
-  register int right = WINDOW_RIGHT_MARGIN (w);
-  register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-
+  /* These will be set while the mode line specs are processed.  */
   line_number_displayed = 0;
   w->column_number_displayed = Qnil;
 
-  get_display_line (f, vpos, left);
-
-  /* Temporarily make frame F's kboard the current kboard
-     so that kboard-local variables in the mode_line_format
-     will get the right values.  */
-  push_frame_kboard (f);
-
-  display_mode_element (w, vpos, left, 0, right, right,
-			current_buffer->mode_line_format);
-
+  if (WINDOW_WANTS_MODELINE_P (w))
+    display_mode_line (w, MODE_LINE_FACE_ID, current_buffer->mode_line_format);
+  
+  if (WINDOW_WANTS_TOP_LINE_P (w))
+    display_mode_line (w, TOP_LINE_FACE_ID, current_buffer->top_line_format);
+}
+
+
+/* Display mode or top line of window W.  FACE_ID specifies which line
+   to display; it is either MODE_LINE_FACE_ID or TOP_LINE_FACE_ID.
+   FORMAT is the mode line format to display.  */
+
+static void
+display_mode_line (w, face_id, format)
+     struct window *w;
+     enum face_id face_id;
+     Lisp_Object format;
+{
+  struct it it;
+  struct face *face;
+
+  init_iterator (&it, w, -1, -1, NULL, face_id);
+  prepare_desired_row (it.glyph_row);
+
+  /* Temporarily make frame's keyboard the current kboard so that
+     kboard-local variables in the mode_line_format will get the right
+     values.  */
+  push_frame_kboard (it.f);
+  display_mode_element (&it, 0, 0, 0, format);
   pop_frame_kboard ();
 
-  FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
-
-  /* Put the mode line in inverse video.
-     Use faces if possible, since that lets us handle
-     partial-width windows and avoid inverting the scroll bar columns.  */
-#ifdef HAVE_FACES
-  if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
-    {
-      /* For a partial width window, explicitly set face of each glyph. */
-      int i;
-      unsigned int padding;
-      GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
-      for (i = left; i < right; ++i)
-	{
-	  padding = ptr[i] & GLYPH_MASK_PADDING;
-	  ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding;
-	}
-    }
-  else
-#endif
-
-  /* Make the mode line inverse video if the entire line
-     is made of mode lines.
-     I.e. if this window is full width,
-     or if it is the child of a full width window
-     (which implies that that window is split side-by-side
-     and the rest of this line is mode lines of the sibling windows).  */
-  if (WINDOW_FULL_WIDTH_P (w)
-      || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
-    FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
-}
-
-/* Contribute ELT to the mode line for window W.
-   How it translates into text depends on its data type.
-
-   VPOS is the position of the mode line being displayed.
-
-   HPOS is the position (absolute on frame) where this element's text
-   should start.  The output is truncated automatically at the right
-   edge of window W.
+  /* Fill up with spaces.  */
+  display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
+  
+  compute_line_metrics (&it);
+  it.glyph_row->full_width_p = 1;
+  it.glyph_row->mode_line_p = 1;
+  it.glyph_row->inverse_p = mode_line_inverse_video != 0;
+  it.glyph_row->continued_p = 0;
+  it.glyph_row->truncated_on_left_p = 0;
+  it.glyph_row->truncated_on_right_p = 0;
+
+  /* Make a 3D mode-line have a shadow at its right end.  */
+  face = FACE_FROM_ID (it.f, face_id);
+  extend_face_to_end_of_line (&it);
+  if (face->box != FACE_NO_BOX)
+    {
+      struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
+			    + it.glyph_row->used[TEXT_AREA] - 1);
+      last->right_box_line_p = 1;
+    }
+}
+
+
+/* Contribute ELT to the mode line for window IT->w.  How it
+   translates into text depends on its data type.
+
+   IT describes the display environment in which we display, as usual.
 
    DEPTH is the depth in recursion.  It is used to prevent
    infinite recursion here.
 
-   MINENDCOL is the hpos before which the element may not end.
-   The element is padded at the right with spaces if nec
-   to reach this column.
-
-   MAXENDCOL is the hpos past which this element may not extend.
-   If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
-   (This is necessary to make nested padding and truncation work.)
-
-   Returns the hpos of the end of the text generated by ELT.
-   The next element will receive that value as its HPOS arg,
-   so as to concatenate the elements.  */
+   FIELD_WIDTH is the number of characters the display of ELT should
+   occupy in the mode line, and PRECISION is the maximum number of
+   characters to display from ELT's representation.  See
+   display_string for details.  *
+
+   Returns the hpos of the end of the text generated by ELT.  */
 
 static int
-display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
-     struct window *w;
-     register int vpos, hpos;
+display_mode_element (it, depth, field_width, precision, elt)
+     struct it *it;
      int depth;
-     int minendcol;
-     register int maxendcol;
-     register Lisp_Object elt;
-{
+     int field_width, precision;
+     Lisp_Object elt;
+{
+  int n = 0, field, prec;
+
  tail_recurse:
   if (depth > 10)
     goto invalid;
@@ -4344,60 +10722,92 @@
     case Lisp_String:
       {
 	/* A string: output it and check for %-constructs within it.  */
-	register unsigned char c;
-	register unsigned char *this = XSTRING (elt)->data;
-
-	while (hpos < maxendcol && *this)
+	unsigned char c;
+	unsigned char *this = XSTRING (elt)->data;
+	unsigned char *lisp_string = this;
+
+	while ((precision <= 0 || n < precision)
+	       && *this
+	       && (frame_title_ptr
+		   || it->current_x < it->last_visible_x))
 	  {
 	    unsigned char *last = this;
+
+	    /* Advance to end of string or next format specifier.  */
 	    while ((c = *this++) != '\0' && c != '%')
 	      ;
+	    
 	    if (this - 1 != last)
 	      {
-		register int lim = --this - last + hpos;
+		/* Output to end of string or up to '%'.  Field width
+		   is length of string.  Don't output more than
+		   PRECISION allows us.  */
+		prec = --this - last;
+		if (precision > 0 && prec > precision - n)
+		  prec = precision - n;
+		
 		if (frame_title_ptr)
-		  hpos = store_frame_title (last, hpos, min (lim, maxendcol));
+		  n += store_frame_title (last, prec, prec);
 		else
-		  hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
-					 hpos, min (lim, maxendcol),
-					 STRING_MULTIBYTE (elt));
+		  n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
+				       it, 0, prec, 0, -1);
 	      }
 	    else /* c == '%' */
 	      {
-		register int minendcol;
-		register int spec_width = 0;
-
-		/* We can't allow -ve args due to the "%-" construct */
-		/* Argument specifies minwidth but not maxwidth
-		   (maxwidth can be specified by
-		     (<negative-number> . <stuff>) mode-line elements) */
-
+		unsigned char *percent_position = this;
+		
+		/* Get the specified minimum width.  Zero means
+		   don't pad.  */
+		field = 0;
 		while ((c = *this++) >= '0' && c <= '9')
-		  {
-		    spec_width = spec_width * 10 + (c - '0');
-		  }
-
-		minendcol = hpos + spec_width;
-		if (minendcol > maxendcol)
-		  {
-		    spec_width = maxendcol - hpos;
-		    minendcol = maxendcol;
-		  }
-
+		  field = field * 10 + c - '0';
+
+		/* Don't pad beyond the total padding allowed.  */
+		if (field_width - n > 0 && field > field_width - n)
+		  field = field_width - n;
+
+		/* Note that either PRECISION <= 0 or N < PRECISION.  */
+		prec = precision - n;
+		
 		if (c == 'M')
-		  hpos = display_mode_element (w, vpos, hpos, depth,
-					       spec_width, maxendcol,
-					       Vglobal_mode_string);
+		  n += display_mode_element (it, depth, field, prec,
+					     Vglobal_mode_string);
 		else if (c != 0)
 		  {
-		    char *spec = decode_mode_spec (w, c, spec_width,
-						   maxendcol - hpos);
+		    unsigned char *spec
+		      = decode_mode_spec (it->w, c, field, prec);
+		    
 		    if (frame_title_ptr)
-		      hpos = store_frame_title (spec, minendcol, maxendcol);
+		      n += store_frame_title (spec, field, prec);
 		    else
-		      hpos = display_string (w, vpos, spec, -1,
-					     hpos, 0, 1,
-					     minendcol, maxendcol, -1);
+		      {
+			int nglyphs_before
+			  = it->glyph_row->used[TEXT_AREA];
+			int charpos
+			  = percent_position - XSTRING (elt)->data;
+			int nwritten
+			  = display_string (spec, Qnil, elt, charpos, 0, it,
+					    field, prec, 0, -1);
+
+			/* Assign to the glyphs written above the
+			   string where the `%x' came from, position
+			   of the `%'.  */
+			if (nwritten > 0)
+			  {
+			    struct glyph *glyph
+			      = (it->glyph_row->glyphs[TEXT_AREA]
+				 + nglyphs_before);
+			    int i;
+
+			    for (i = 0; i < nwritten; ++i)
+			      {
+				glyph[i].object = elt;
+				glyph[i].charpos = charpos;
+			      }
+			    
+			    n += nwritten;
+			  }
+		      }
 		  }
 	      }
 	  }
@@ -4419,18 +10829,21 @@
 	       don't check for % within it.  */
 	    if (STRINGP (tem))
 	      {
+		prec = XSTRING (tem)->size;
+		if (precision > 0 && prec > precision - n)
+		  prec = precision - n;
 		if (frame_title_ptr)
-		  hpos = store_frame_title (XSTRING (tem)->data,
-					    minendcol, maxendcol);
+		  n += store_frame_title (XSTRING (tem)->data, -1, prec);
 		else
-		  hpos = display_string (w, vpos, XSTRING (tem)->data,
-					 STRING_BYTES (XSTRING (tem)),
-					 hpos, 0, 1, minendcol, maxendcol,
-					 STRING_MULTIBYTE (tem));
+		  n += display_string (NULL, tem, Qnil, 0, 0, it,
+				       0, prec, 0, -1);
 	      }
-	    /* Give up right away for nil or t.  */
 	    else if (!EQ (tem, elt))
-	      { elt = tem; goto tail_recurse; }
+	      {
+		/* Give up right away for nil or t.  */
+		elt = tem;
+		goto tail_recurse;
+	      }
 	  }
       }
       break;
@@ -4448,7 +10861,20 @@
 	   If first element is a symbol, process the cadr or caddr recursively
 	   according to whether the symbol's value is non-nil or nil.  */
 	car = XCONS (elt)->car;
-	if (SYMBOLP (car))
+	if (EQ (car, QCeval) && CONSP (XCDR (elt)))
+	  {
+	    /* An element of the form (:eval FORM) means evaluate FORM
+	       and use the result as mode line elements.  */
+	    struct gcpro gcpro1;
+	    Lisp_Object spec;
+
+	    spec = eval_form (XCAR (XCDR (elt)));
+	    GCPRO1 (spec);
+	    n += display_mode_element (it, depth, field_width - n,
+				       precision - n, spec);
+	    UNGCPRO;
+	  }
+	else if (SYMBOLP (car))
 	  {
 	    tem = Fboundp (car);
 	    elt = XCONS (elt)->cdr;
@@ -4478,36 +10904,37 @@
 	    register int lim = XINT (car);
 	    elt = XCONS (elt)->cdr;
 	    if (lim < 0)
-	      /* Negative int means reduce maximum width.
-		 DO NOT change MINENDCOL here!
-		 (20 -10 . foo) should truncate foo to 10 col
-		 and then pad to 20.  */
-	      maxendcol = min (maxendcol, hpos - lim);
+	      {
+		/* Negative int means reduce maximum width.  */
+		if (precision <= 0)
+		  precision = -lim;
+		else
+		  precision = min (precision, -lim);
+	      }
 	    else if (lim > 0)
 	      {
 		/* Padding specified.  Don't let it be more than
 		   current maximum.  */
-		lim += hpos;
-		if (lim > maxendcol)
-		  lim = maxendcol;
+		if (precision > 0)
+		  lim = min (precision, lim);
+
 		/* If that's more padding than already wanted, queue it.
 		   But don't reduce padding already specified even if
 		   that is beyond the current truncation point.  */
-		if (lim > minendcol)
-		  minendcol = lim;
+		field_width = max (lim, field_width);
 	      }
 	    goto tail_recurse;
 	  }
 	else if (STRINGP (car) || CONSP (car))
 	  {
 	    register int limit = 50;
-	    /* LIMIT is to protect against circular lists.  */
-	    while (CONSP (elt) && --limit > 0
-		   && hpos < maxendcol)
+	    /* Limit is to protect against circular lists.  */
+	    while (CONSP (elt)
+		   && --limit > 0
+		   && (precision <= 0 || n < precision))
 	      {
-		hpos = display_mode_element (w, vpos, hpos, depth,
-					     hpos, maxendcol,
-					     XCONS (elt)->car);
+		n += display_mode_element (it, depth, field_width - n,
+					   precision - n, XCONS (elt)->car);
 		elt = XCONS (elt)->cdr;
 	      }
 	  }
@@ -4517,22 +10944,27 @@
     default:
     invalid:
       if (frame_title_ptr)
-	hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
+	n += store_frame_title ("*invalid*", 0, precision - n);
       else
-	hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
-			       minendcol, maxendcol, 0);
-      return hpos;
-    }
-
-  if (minendcol > hpos)
-    if (frame_title_ptr)
-      hpos = store_frame_title ("", minendcol, maxendcol);
-    else
-      hpos = display_string (w, vpos, "", 0, hpos,
-			     0, 1, minendcol, maxendcol, 0);
-  return hpos;
-}
-
+	n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
+			     precision - n, 0, 0);
+      return n;
+    }
+
+  /* Pad to FIELD_WIDTH.  */
+  if (field_width > 0 && n < field_width)
+    {
+      if (frame_title_ptr)
+	n += store_frame_title ("", field_width - n, 0);
+      else
+	n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
+			     0, 0, 0);
+    }
+  
+  return n;
+}
+
+
 /* Write a null-terminated, right justified decimal representation of
    the positive integer D to BUF using a minimal field width WIDTH.  */
 
@@ -4545,24 +10977,28 @@
   register char *p = buf;
   
   if (d <= 0)
-      *p++ = '0';
+    *p++ = '0';
   else
+    {
       while (d > 0)
-      {
+	{
 	  *p++ = d % 10 + '0';
 	  d /= 10;
-      }
-  for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
+	}
+    }
+  
+  for (width -= (int) (p - buf); width > 0; --width)
+    *p++ = ' ';
   *p-- = '\0';
   while (p > buf)
-  {
+    {
       d = *buf;
       *buf++ = *p;
       *p-- = d;
-  }
-}
-
-/* Set a mnemonic character for CODING_SYSTEM (Lisp symbol) in BUF.
+    }
+}
+
+/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
    If EOL_FLAG is 1, set also a mnemonic character for end-of-line
    type of CODING_SYSTEM.  Return updated pointer into BUF.  */
 
@@ -4622,7 +11058,7 @@
 			  ? eol_mnemonic_dos : eol_mnemonic_mac));
 	}
     }
-
+  
   if (eol_flag)
     {
       /* Mention the EOL conversion if it is not the usual one.  */
@@ -4652,27 +11088,24 @@
 }
 
 /* Return a string for the output of a mode line %-spec for window W,
-   generated by character C.  SPEC_WIDTH is the field width when
-   padding to the left (%c, %l).  The value returned from this
-   function will later be truncated to width MAXWIDTH. */
+   generated by character C.  PRECISION >= 0 means don't return a
+   string longer than that value.  FIELD_WIDTH > 0 means pad the
+   string returned with spaces to that value.  */
 
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
 static char *
-decode_mode_spec (w, c, spec_width, maxwidth)
+decode_mode_spec (w, c, field_width, precision)
      struct window *w;
      register char c;
-     register int spec_width;
-     register int maxwidth;
+     int field_width, precision;
 {
   Lisp_Object obj;
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-  char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
   struct buffer *b = XBUFFER (w->buffer);
 
   obj = Qnil;
-  if (maxwidth > FRAME_WIDTH (f))
-    maxwidth = FRAME_WIDTH (f);
 
   switch (c)
     {
@@ -4730,47 +11163,36 @@
 
     case '-':
       {
-	register char *p;
 	register int i;
-	
-	if (maxwidth < sizeof (lots_of_dashes))
-	  return lots_of_dashes;
+
+	/* Let lots_of_dashes be a string of infinite length.  */
+	if (field_width <= 0
+	    || field_width > sizeof (lots_of_dashes))
+	  {
+	    for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
+	      decode_mode_spec_buf[i] = '-';
+	    decode_mode_spec_buf[i] = '\0';
+	    return decode_mode_spec_buf;
+	  }
 	else
-	  {
-	    for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
-	      *p++ = '-';
-	    *p = '\0';
-	  }
-	return decode_mode_spec_buf;
+	  return lots_of_dashes;
       }
 
     case 'b': 
       obj = b->name;
-#if 0
-      if (maxwidth >= 3 && STRING_BYTES (XSTRING (obj)) > maxwidth)
-	{
-	  bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
-	  decode_mode_spec_buf[maxwidth - 1] = '\\';
-	  decode_mode_spec_buf[maxwidth] = '\0';
-	  return decode_mode_spec_buf;
-	}
-#endif
       break;
 
     case 'c':
       {
 	int col = current_column ();
 	XSETFASTINT (w->column_number_displayed, col);
-	pint2str (decode_mode_spec_buf, spec_width, col);
+	pint2str (decode_mode_spec_buf, field_width, col);
 	return decode_mode_spec_buf;
       }
 
     case 'F':
       /* %F displays the frame name.  */
-      /* Systems that can only display a single frame at a time should
-	 NOT replace the frame name with the (constant) frame title,
-	 since then they won't be able to tell which frame is that.  */
-      if (FRAME_WINDOW_P (f) && !NILP (f->title))
+      if (!NILP (f->title))
 	return (char *) XSTRING (f->title)->data;
       if (f->explicit_name || ! FRAME_WINDOW_P (f))
 	return (char *) XSTRING (f->name)->data;
@@ -4778,17 +11200,6 @@
 
     case 'f': 
       obj = b->filename;
-#if 0
-      if (NILP (obj))
-	return "[none]";
-      else if (STRINGP (obj) && STRING_BYTES (XSTRING (obj)) > maxwidth)
-	{
-	  bcopy ("...", decode_mode_spec_buf, 3);
-	  bcopy (XSTRING (obj)->data + STRING_BYTES (XSTRING (obj)) - maxwidth + 3,
-		 decode_mode_spec_buf + 3, maxwidth - 3);
-	  return decode_mode_spec_buf;
-	}
-#endif
       break;
 
     case 'l':
@@ -4797,7 +11208,6 @@
 	int startpos_byte = marker_byte_position (w->start);
 	int line, linepos, linepos_byte, topline;
 	int nlines, junk;
-	Lisp_Object tem;
 	int height = XFASTINT (w->height);
 
 	/* If we decided that this buffer isn't suitable for line numbers, 
@@ -4887,13 +11297,16 @@
 	line_number_displayed = 1;
 
 	/* Make the string to show.  */
-	pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
+	pint2str (decode_mode_spec_buf, field_width, topline + nlines);
 	return decode_mode_spec_buf;
     no_value:
         {
 	  char* p = decode_mode_spec_buf;
-	  for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
-	  strcpy (p, "??");
+	  int pad = field_width - 2;
+	  while (pad-- > 0)
+	    *p++ = ' ';
+	  *p++ = '?';
+	  *p = '?';
 	  return decode_mode_spec_buf;
 	}
       }
@@ -5028,7 +11441,8 @@
   else
     return "";
 }
-
+
+
 /* Count up to COUNT lines starting from START / START_BYTE.
    But don't go beyond LIMIT_BYTE.
    Return the number of lines thus found (always nonnegative).
@@ -5132,269 +11546,202 @@
   return orig_count - count;
 
 }
+
+
 
-/* Display STRING on one line of window W, starting at HPOS.
-   Display at position VPOS.  Caller should have done get_display_line.
-   If VPOS == -1, display it as the current frame's title.
-   LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
-
-  TRUNCATE is GLYPH to display at end if truncated.  Zero for none.
-
-  MINCOL is the first column ok to end at.  (Pad with spaces to this col.)
-  MAXCOL is the last column ok to end at.  Truncate here.
-    -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
-  Both count from the left edge of the frame, as does HPOS.
-  The right edge of W is an implicit maximum.
-  If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
-
-  OBEY_WINDOW_WIDTH says to put spaces or vertical bars
-  at the place where the current window ends in this line
-  and not display anything beyond there.  Otherwise, only MAXCOL
-  controls where to stop output.
-
-  MULTIBYTE can be 0 meaning do not display multibyte chars,
-  1 meaning do display them, or -1 meaning obey the current buffer's
-  value of enable_multibyte_characters.
-
-  Returns ending hpos.  */
+/***********************************************************************
+			 Displaying strings
+ ***********************************************************************/
+
+/* Display a NUL-terminated string, starting with index START.
+
+   If STRING is non-null, display that C string.  Otherwise, the Lisp
+   string LISP_STRING is displayed.
+
+   If FACE_STRING is not nil, FACE_STRING_POS is a position in
+   FACE_STRING.  Display STRING or LISP_STRING with the face at
+   FACE_STRING_POS in FACE_STRING:
+
+   Display the string in the environment given by IT, but use the
+   standard display table, temporarily.
+
+   FIELD_WIDTH is the minimum number of output glyphs to produce.
+   If STRING has fewer characters than FIELD_WIDTH, pad to the right
+   with spaces.  If STRING has more characters, more than FIELD_WIDTH
+   glyphs will be produced.  FIELD_WIDTH <= 0 means don't pad.
+   
+   PRECISION is the maximum number of characters to output from
+   STRING.  PRECISION < 0  means don't truncate the string.
+
+   This is roughly equivalent to printf format specifiers:
+
+   FIELD_WIDTH	PRECISION	PRINTF
+   ----------------------------------------
+   -1		-1		%s
+   -1		10		%.10s
+   10		-1		%10s
+   20		10		%20.10s
+
+   MULTIBYTE zero means do not display multibyte chars, > 0 means do
+   display them, and < 0 means obey the current buffer's value of
+   enable_multibyte_characters.
+
+   Value is the number of glyphs produced.  */
 
 static int
-display_string (w, vpos, string, length, hpos, truncate,
-		obey_window_width, mincol, maxcol, multibyte)
-     struct window *w;
+display_string (string, lisp_string, face_string, face_string_pos,
+		start, it, field_width, precision, max_x, multibyte)
      unsigned char *string;
-     int length;
-     int vpos, hpos;
-     GLYPH truncate;
-     int obey_window_width;
-     int mincol, maxcol;
+     Lisp_Object lisp_string;
+     int start;
+     struct it *it;
+     int field_width, precision, max_x;
      int multibyte;
 {
-  register int c;
-  int truncated;
-  register GLYPH *p1;
-  int hscroll = XINT (w->hscroll);
-  int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
-  register GLYPH *start;
-  register GLYPH *end;
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-  struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
-  GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
-  int window_width = XFASTINT (w->width);
-
-  /* Use the standard display table, not the window's display table.
-     We don't want the mode line in rot13.  */
-  register struct Lisp_Char_Table *dp = 0;
-  int i;
-
-  if (multibyte == -1)
-    multibyte = !NILP (current_buffer->enable_multibyte_characters);
-  /* Now multibyte is 1 if we should display multibyte characters.  */
-
-  if (DISP_TABLE_P (Vstandard_display_table))
-    dp = XCHAR_TABLE (Vstandard_display_table);
-
-  if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
-  p1 = p1start;
-  start = desired_glyphs->glyphs[vpos];
-
-  if (obey_window_width)
-    {
-      start += XFASTINT (w->left);
-      end = start + window_width - (truncate != 0);
-
-      if (!WINDOW_RIGHTMOST_P (w))
-	{
-	  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+  int hpos_at_start = it->hpos;
+  int saved_face_id = it->face_id;
+  struct glyph_row *row = it->glyph_row;
+
+  /* Initialize the iterator IT for iteration over STRING beginning
+     with index START.  We assume that IT may be modified here (which
+     means that display_line has to do something when displaying a
+     mini-buffer prompt, which it does).  */
+  reseat_to_string (it, string, lisp_string, start,
+		    precision, field_width, multibyte);
+
+  /* If displaying STRING, set up the face of the iterator
+     from LISP_STRING, if that's given.  */
+  if (STRINGP (face_string))
+    {
+      int endptr;
+      struct face *face;
+      
+      it->face_id
+	= face_at_string_position (it->w, face_string, face_string_pos,
+				   0, it->region_beg_charpos,
+				   it->region_end_charpos,
+				   &endptr, it->base_face_id);
+      face = FACE_FROM_ID (it->f, it->face_id);
+      it->face_box_p = face->box != FACE_NO_BOX;
+    }
+
+  /* Set max_x to the maximum allowed X position.  Don't let it go
+     beyond the right edge of the window.  */
+  if (max_x <= 0)
+    max_x = it->last_visible_x;
+  else
+    max_x = min (max_x, it->last_visible_x);
+
+  /* Skip over display elements that are not visible. because IT->w is
+     hscrolled.  */
+  if (it->current_x < it->first_visible_x)
+    move_it_in_display_line_to (it, 100000, it->first_visible_x,
+				MOVE_TO_POS | MOVE_TO_X);
+
+  row->ascent = it->max_ascent;
+  row->height = it->max_ascent + it->max_descent;
+
+  /* This condition is for the case that we are called with current_x
+     past last_visible_x.  */
+  while (it->current_x < max_x)
+    {
+      int x_before, x, n_glyphs_before, i, nglyphs;
+
+      /* Get the next display element.  */
+      if (!get_next_display_element (it))
+	break;
+
+      /* Produce glyphs.  */
+      x_before = it->current_x;
+      n_glyphs_before = it->glyph_row->used[TEXT_AREA];
+      PRODUCE_GLYPHS (it);
+
+      nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
+      i = 0;
+      x = x_before;
+      while (i < nglyphs)
+	{
+	  struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
+	  
+	  if (!it->truncate_lines_p
+	      && x + glyph->pixel_width > max_x)
 	    {
-	      int i;
-
-	      for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
-		*end-- = ' ';
-	    }
-	  else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-	    *end-- = '|';
-	}
-    }
-
-  if (! obey_window_width
-      || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
-    end = desired_glyphs->glyphs[vpos] + maxcol;
-
-  /* Store 0 in charstart for these columns.  */
-  for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
-    desired_glyphs->charstarts[vpos][i] = 0;
-
-  if (maxcol >= 0 && mincol > maxcol)
-    mincol = maxcol;
-
-  if (length < 0)
-    /* We need this value for multibyte characters.  */
-    length = strlen (string);
-
-  /* We set truncated to 1 if we get stopped by trying to pass END
-     (that is, trying to pass MAXCOL.)  */
-  truncated = 0;
-  while (1)
-    {
-      int len;
-
-      if (length <= 0)
-	break;
-      if (multibyte)
-	c = STRING_CHAR_AND_LENGTH (string, length, len);
-      else
-	c = *string, len = 1;
-
-      string += len, length -= len;
-
-      if (p1 >= end)
-	{
-	  truncated = 1;
-	  break;
-	}
-
-      if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
-	{
-	  p1 = copy_part_of_rope (f, p1, start,
-				  XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
-				  XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
-				  0);
-	}
-      else if (c >= 040 && c < 0177)
-	{
-	  if (p1 >= start)
-	    *p1 = c;
-	  p1++;
-	}
-      else if (c == '\t')
-	{
-	  do
-	    {
-	      if (p1 >= start && p1 < end)
-		*p1 = SPACEGLYPH;
-	      p1++;
+	      /* End of continued line or max_x reached.  */
+	      it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
+	      it->current_x = x;
+	      break;
 	    }
-	  while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
-	}
-      else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
-	{
-	  if (p1 >= start)
-	    *p1 = (fix_glyph
-		   (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
-			&& GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
-			? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
-		    0));
-	  p1++;
-	  if (p1 >= start && p1 < end)
-	    *p1 = c ^ 0100;
-	  p1++;
-	}
-      else
-	{
-	  /* C is a multibyte character, control character or a binary
-             byte data.  */
-	  int remaining_bytes = len;
-
-	  if (c >= 0400 && CHAR_VALID_P (c, 0))
+	  else if (x + glyph->pixel_width > it->first_visible_x)
+	    {
+	      /* Glyph is at least partially visible.  */
+	      ++it->hpos;
+	      if (x < it->first_visible_x)
+		it->glyph_row->x = x - it->first_visible_x;
+	    }
+	  else
 	    {
-	      /* C is a multibyte character.  */	  
-	      int charset = CHAR_CHARSET (c);
-	      int columns = (charset == CHARSET_COMPOSITION
-			     ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
-			     : CHARSET_WIDTH (charset));
-
-	      remaining_bytes -= CHARSET_BYTES (charset);
-	      if (p1 < start)
-		{
-		  /* Since we can't show the left part of C, fill all
-		     columns with spaces.  */
-		  columns -= start - p1;
-		  p1 = start;
-		  while (columns--)
-		    {
-		      if (p1 < end)
-			*p1 = SPACEGLYPH;
-		      p1++;
-		    }
-		}
-	      else if (p1 + columns > end)
-		{
-		  /* Since we can't show the right part of C, fill all
-		     columns with TRUNCATE if TRUNCATE is specified.  */
-		  if (truncate)
-		    {
-		      while (p1 < end)
-			*p1++ = fix_glyph (f, truncate, 0);
-		      /* And tell the line is truncated.  */
-		      truncated = 1;
-		    }
-		  break;
-		}
-	      else
-		{
-		  /* We can show the whole glyph of C.  */
-		  *p1++ = c;
-		  while (--columns)
-		    *p1++ = c | GLYPH_MASK_PADDING;
-		}
+	      /* Glyph is off the left margin of the display area.
+		 Should not happen.  */
+	      abort ();
 	    }
 
-	  while (remaining_bytes > 0)
+	  row->ascent = max (row->ascent, it->max_ascent);
+	  row->height = max (row->height, it->max_ascent + it->max_descent);
+	  x += glyph->pixel_width;
+	  ++i;
+	}
+
+      /* Stop if max_x reached.  */
+      if (i < nglyphs)
+	break;
+
+      /* Stop at line ends.  */
+      if (ITERATOR_AT_END_OF_LINE_P (it))
+	{
+	  it->continuation_lines_width = 0;
+	  break;
+	}
+
+      set_iterator_to_next (it);
+
+      /* Stop if truncating at the right edge.  */
+      if (it->truncate_lines_p
+	  && it->current_x >= it->last_visible_x)
+	{
+	  /* Add truncation mark, but don't do it if the line is
+	     truncated at a padding space.  */
+	  if (IT_CHARPOS (*it) < it->string_nchars)
 	    {
-	      c = *(string - remaining_bytes--);
-
-	      if (p1 >= start)
-		*p1 = (fix_glyph
-		       (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
-			    && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
-			    ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
-			0));
-	      p1++;
-	      if (p1 >= start && p1 < end)
-		*p1 = (c >> 6) + '0';
-	      p1++;
-	      if (p1 >= start && p1 < end)
-		*p1 = (7 & (c >> 3)) + '0';
-	      p1++;
-	      if (p1 >= start && p1 < end)
-		*p1 = (7 & c) + '0';
-	      p1++;
+	      if (!FRAME_WINDOW_P (it->f))
+		produce_special_glyphs (it, IT_TRUNCATION);
+	      it->glyph_row->truncated_on_right_p = 1;
 	    }
-	}
-    }
-
-  if (truncated)
-    {
-      p1 = end;
-      if (truncate) *p1++ = fix_glyph (f, truncate, 0);
-    }
-  else if (mincol >= 0)
-    {
-      end = desired_glyphs->glyphs[vpos] + mincol;
-      while (p1 < end)
-	*p1++ = SPACEGLYPH;
-    }
-
-  {
-    register int len = p1 - desired_glyphs->glyphs[vpos];
-
-    if (len > desired_glyphs->used[vpos])
-      desired_glyphs->used[vpos] = len;
-    desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
-
-    return len;
-  }
-}
+	  break;
+	}
+    }
+
+  /* Maybe insert a truncation at the left.  */
+  if (it->first_visible_x
+      && IT_CHARPOS (*it) > 0)
+    {
+      if (!FRAME_WINDOW_P (it->f))
+	insert_left_trunc_glyphs (it);
+      it->glyph_row->truncated_on_left_p = 1;
+    }
+
+  it->face_id = saved_face_id;
+  
+  /* Value is number of columns displayed.  */
+  return it->hpos - hpos_at_start;
+}
+
+
 
-/* This is like a combination of memq and assq.
-   Return 1 if PROPVAL appears as an element of LIST
-   or as the car of an element of LIST.
-   If PROPVAL is a list, compare each element against LIST
-   in that way, and return 1 if any element of PROPVAL is found in LIST.
-   Otherwise return 0.
-   This function cannot quit.  */
+/* This is like a combination of memq and assq.  Return 1 if PROPVAL
+   appears as an element of LIST or as the car of an element of LIST.
+   If PROPVAL is a list, compare each element against LIST in that
+   way, and return 1 if any element of PROPVAL is found in LIST.
+   Otherwise return 0.  This function cannot quit.  */
 
 int
 invisible_p (propval, list)
@@ -5430,13 +11777,12 @@
   return 0;
 }
 
-/* Return 1 if PROPVAL appears as the car of an element of LIST
-   and the cdr of that element is non-nil.
-   If PROPVAL is a list, check each element of PROPVAL in that way,
-   and the first time some element is found,
-   return 1 if the cdr of that element is non-nil.
-   Otherwise return 0.
-   This function cannot quit.  */
+
+/* Return 1 if PROPVAL appears as the car of an element of LIST and
+   the cdr of that element is non-nil.  If PROPVAL is a list, check
+   each element of PROPVAL in that way, and the first time some
+   element is found, return 1 if the cdr of that element is non-nil.
+   Otherwise return 0.  This function cannot quit.  */
 
 int
 invisible_ellipsis_p (propval, list)
@@ -5467,13 +11813,30 @@
       }
   return 0;
 }
+
+
 
+/***********************************************************************
+			    Initialization
+ ***********************************************************************/
+
 void
 syms_of_xdisp ()
 {
+  echo_area_message = previous_echo_area_message = Qnil;
+  staticpro (&echo_area_message);
+  staticpro (&previous_echo_area_message);
+
   staticpro (&Qinhibit_redisplay);
   Qinhibit_redisplay = intern ("inhibit-redisplay");
 
+#if GLYPH_DEBUG
+  defsubr (&Sdump_glyph_matrix);
+  defsubr (&Sdump_glyph_row);
+  defsubr (&Sdump_toolbar_row);
+  defsubr (&Strace_redisplay_toggle);
+#endif
+
   staticpro (&Qmenu_bar_update_hook);
   Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
 
@@ -5488,10 +11851,51 @@
 
   staticpro (&Qredisplay_end_trigger_functions);
   Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
-
+  
   staticpro (&Qinhibit_point_motion_hooks);
   Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
 
+  staticpro (&Qdisplay);
+  Qdisplay = intern ("display");
+  staticpro (&Qleft_margin);
+  Qspace_width = intern ("space-width");
+  staticpro (&Qspace_width);
+  Qheight = intern ("height");
+  staticpro (&Qheight);
+  Qraise = intern ("raise");
+  staticpro (&Qraise);
+  Qspace = intern ("space");
+  staticpro (&Qspace);
+  Qleft_margin = intern ("left-margin");
+  staticpro (&Qright_margin);
+  Qright_margin = intern ("right-margin");
+  Qalign_to = intern ("align-to");
+  staticpro (&Qalign_to);
+  QCalign_to = intern (":align-to");
+  staticpro (&QCalign_to);
+  Qwidth = intern ("width");
+  staticpro (&Qwidth);
+  Qrelative_width = intern ("relative-width");
+  staticpro (&Qrelative_width);
+  QCrelative_width = intern (":relative-width");
+  staticpro (&QCrelative_width);
+  QCrelative_height = intern (":relative-height");
+  staticpro (&QCrelative_height);
+  QCeval = intern (":eval");
+  staticpro (&QCeval);
+  QCwhen = intern (":when");
+  staticpro (&QCwhen);
+  Qfontified = intern ("fontified");
+  staticpro (&Qfontified);
+  Qfontification_functions = intern ("fontification-functions");
+  staticpro (&Qfontification_functions);
+  Qshow_trailing_whitespace = intern ("show-trailing-whitespace");
+  staticpro (&Qshow_trailing_whitespace);
+  Qtrailing_whitespace = intern ("trailing-whitespace");
+  staticpro (&Qtrailing_whitespace);
+  Qimage = intern ("image");
+  staticpro (&Qimage);
+
   staticpro (&last_arrow_position);
   staticpro (&last_arrow_string);
   last_arrow_position = Qnil;
@@ -5531,7 +11935,9 @@
 of the top or bottom of the window.");
   scroll_margin = 0;
 
+#if GLYPH_DEBUG
   DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
+#endif
 
   DEFVAR_BOOL ("truncate-partial-width-windows",
 	       &truncate_partial_width_windows,
@@ -5543,7 +11949,7 @@
   mode_line_inverse_video = 1;
 
   DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
-    "*Maximum buffer size (in characters) for line number display\n\
+    "*Maximum buffer size for which line number should be displayed.\n\
 If the buffer is bigger than this, the line number does not appear\n\
 in the mode line.");
   line_number_display_limit = 1000000;
@@ -5559,13 +11965,13 @@
 `frame-title-format' and `icon-title-format'.");
 
   DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
-    "Template for displaying the titlebar of visible frames.\n\
+    "Template for displaying the title bar of visible frames.\n\
 \(Assuming the window manager supports this feature.)\n\
 This variable has the same structure as `mode-line-format' (which see),\n\
 and is used only on frames for which no explicit name has been set\n\
 \(see `modify-frame-parameters').");
   DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
-    "Template for displaying the titlebar of an iconified frame.\n\
+    "Template for displaying the title bar of an iconified frame.\n\
 \(Assuming the window manager supports this feature.)\n\
 This variable has the same structure as `mode-line-format' (which see),\n\
 and is used only on frames for which no explicit name has been set\n\
@@ -5596,20 +12002,43 @@
   Vwindow_size_change_functions = Qnil;
 
   DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
-    "List of functions to call before redisplaying a window with scrolling.\n\
+    "List of Functions to call before redisplaying a window with scrolling.\n\
 Each function is called with two arguments, the window\n\
 and its new display-start position.  Note that the value of `window-end'\n\
 is not valid when these functions are called.");
   Vwindow_scroll_functions = Qnil;
-
-  DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap,
-    "*Number of characters of overlap when scrolling a one-line window.\n\
-This commonly affects the minibuffer window, hence the name of the variable.");
-  minibuffer_scroll_overlap = 20;
+  
+  DEFVAR_BOOL ("auto-resize-toolbars", &auto_resize_toolbars_p,
+    "*Non-nil means automatically resize toolbars.\n\
+This increases a toolbar's height if not all toolbar items are visible.\n\
+It decreases a toolbar's height when it would display blank lines\n\
+otherwise.");
+  auto_resize_toolbars_p = 1;
+  
+  DEFVAR_BOOL ("auto-raise-toolbar-buttons", &auto_raise_toolbar_buttons_p,
+    "*Non-nil means raise toolbar buttons when the mouse moves over them.");
+  auto_raise_toolbar_buttons_p = 1;
+
+  DEFVAR_INT ("toolbar-button-margin", &toolbar_button_margin,
+    "*Margin around toolbar buttons in pixels.");
+  toolbar_button_margin = 1;
+
+  DEFVAR_INT ("toolbar-button-relief", &toolbar_button_relief,
+    "Relief thickness of toolbar buttons.");
+  toolbar_button_relief = 3;
+
+  DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
+    "List of functions to call to fontify regions of text.\n\
+Each function is called with one argument POS.  Functions must\n\
+fontify a region starting at POS in the current buffer, and give\n\
+fontified regions the property `fontified'.\n\
+This variable automatically becomes buffer-local when set.");
+  Vfontification_functions = Qnil;
+  Fmake_local_variable (Qfontification_functions);
 
   DEFVAR_BOOL ("unibyte-display-via-language-environment",
-	       &unibyte_display_via_language_environment,
-   "*Non-nil means display unibyte text according to language environment.\n\
+               &unibyte_display_via_language_environment,
+    "*Non-nil means display unibyte text according to language environment.\n\
 Specifically this means that unibyte non-ASCII characters\n\
 are displayed by converting them to the equivalent multibyte characters\n\
 according to the current language environment.  As a result, they are\n\
@@ -5617,35 +12046,57 @@
   unibyte_display_via_language_environment = 0;
 }
 
-/* initialize the window system */
+
+/* Initialize this module when Emacs starts.  */
+
 void
 init_xdisp ()
 {
   Lisp_Object root_window;
-#ifndef COMPILER_REGISTER_BUG
-  register
-#endif /* COMPILER_REGISTER_BUG */
-    struct window *mini_w;
-
-  this_line_bufpos = 0;
+  struct window *mini_w;
+
+  CHARPOS (this_line_start_pos) = 0;
 
   mini_w = XWINDOW (minibuf_window);
   root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
 
   echo_area_glyphs = 0;
   previous_echo_glyphs = 0;
+  echo_area_message = previous_echo_area_message = Qnil;
 
   if (!noninteractive)
     {
-      FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
-      XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f));
+      struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
+      int i;
+
+      XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
       set_window_height (root_window,
-			 FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f),
+			 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
 			 0);
       XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
       set_window_height (minibuf_window, 1, 0);
 
       XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
       XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
-    }
-}
+
+      scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
+      scratch_glyph_row.glyphs[TEXT_AREA + 1]
+	= scratch_glyphs + MAX_SCRATCH_GLYPHS;
+
+      /* The default ellipsis glyphs `...'.  */ 
+      for (i = 0; i < 3; ++i)
+	XSETFASTINT (default_invis_vector[i], '.');
+    }
+
+#ifdef HAVE_WINDOW_SYSTEM
+  {
+    /* Allocate the buffer for frame titles.  */
+    int size = 100;
+    frame_title_buf = (char *) xmalloc (size);
+    frame_title_buf_end = frame_title_buf + size;
+    frame_title_ptr = NULL;
+  }
+#endif /* HAVE_WINDOW_SYSTEM */
+}
+
+