Merge from trunk.
authorEli Zaretskii <eliz@gnu.org>
Thu, 26 Sep 2013 07:37:16 +0000 (10:37 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 26 Sep 2013 07:37:16 +0000 (10:37 +0300)
21 files changed:
1  2 
configure.ac
lisp/faces.el
lisp/mouse.el
src/alloc.c
src/dispextern.h
src/dispnew.c
src/keyboard.c
src/keyboard.h
src/menu.c
src/msdos.c
src/nsmenu.m
src/term.c
src/termchar.h
src/termhooks.h
src/w32console.c
src/w32fns.c
src/w32menu.c
src/w32term.h
src/window.c
src/xdisp.c
src/xmenu.c

diff --combined configure.ac
@@@ -266,13 -266,9 +266,9 @@@ AC_SUBST(cache_file
  
  ## This is an option because I do not know if all info/man support
  ## compressed files, nor how to test if they do so.
- OPTION_DEFAULT_ON([compress-info],[don't compress the installed Info pages])
- if test $with_compress_info = yes; then
-    GZIP_INFO=yes
- else
-    GZIP_INFO=
- fi
- AC_SUBST(GZIP_INFO)
+ OPTION_DEFAULT_ON([compress-install],
+   [don't compress some files (.el, .info, etc.) when installing.  Equivalent to:
+ make GZIP_PROG= install])
  
  AC_ARG_WITH([pkg-config-prog],dnl
  [AS_HELP_STRING([--with-pkg-config-prog=FILENAME],
@@@ -447,6 -443,17 +443,17 @@@ case "${srcdir}" i
    *  ) srcdir=`(cd "$srcdir"; pwd)` ;;
  esac
  
+ #### When building with MinGW inside the MSYS tree, 'pwd' produces
+ #### directories relative to the root of the MSYS tree,
+ #### e.g. '/home/user/foo' instead of '/d/MSYS/home/user/foo'.  When
+ #### such a value of srcdir is written to the top-level Makefile, it
+ #### gets propagated to src/epaths.h, and that causes temacs to fail,
+ #### because, being a MinGW program that knows nothing of MSYS root
+ #### substitution, it cannot find the data directory.  "pwd -W"
+ #### produces Windows-style 'd:/foo/bar' absolute directory names, so
+ #### we use it here to countermand that lossage.
+ test "$MSYSTEM" = "MINGW32" && srcdir=`(cd "$srcdir"; pwd -W | sed -e 's,^\([[A-Za-z]]\):,/\1,')`
  ### Canonicalize the configuration name.
  
  AC_CANONICAL_HOST
@@@ -780,10 -787,28 +787,28 @@@ AC_DEFUN([gl_GCC_VERSION_IFELSE]
    ]
  )
  
+ # clang is unduly picky about some things.
+ AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
+   [AC_COMPILE_IFELSE(
+      [AC_LANG_PROGRAM([[
+         #ifndef __clang__
+           #error "not clang"
+         #endif
+         ]])],
+      [emacs_cv_clang=yes],
+      [emacs_cv_clang=no])])
  # When compiling with GCC, prefer -isystem to -I when including system
  # include files, to avoid generating useless diagnostics for the files.
  if test "$gl_gcc_warnings" != yes; then
    isystem='-I'
+   if test "$emacs_cv_clang" = yes
+   then
+      # Turn off some warnings if supported.
+      gl_WARN_ADD([-Wno-switch])
+      gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare])
+      gl_WARN_ADD([-Wno-pointer-sign])
+   fi
  else
    isystem='-isystem '
  
    # The following line should be removable at some point.
    nw="$nw -Wsuggest-attribute=pure"
  
-   # clang is unduly picky about some things.
-   AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
-     [AC_COMPILE_IFELSE(
-        [AC_LANG_PROGRAM([[
-           #ifndef __clang__
-             #error "not clang"
-           #endif
-           ]])],
-        [emacs_cv_clang=yes],
-        [emacs_cv_clang=no])])
+   # This part is merely for shortening the command line,
+   # since -Wno-FOO needs to be added below regardless.
+   nw="$nw -Wmissing-field-initializers"
+   nw="$nw -Wswitch"
+   nw="$nw -Wtype-limits"
+   nw="$nw -Wunused-parameter"
    if test $emacs_cv_clang = yes; then
      nw="$nw -Wcast-align"
    fi
      gl_WARN_ADD([-Wno-unused-value])
    fi
  
-   gl_WARN_ADD([-fdiagnostics-show-option])
-   gl_WARN_ADD([-funit-at-a-time])
    AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
    AH_VERBATIM([FORTIFY_SOURCE],
    [/* Enable compile-time and run-time bounds-checking, and some warnings,
@@@ -943,6 -962,9 +962,9 @@@ AC_PATH_PROG(INSTALL_INFO, install-info
  dnl Don't use GZIP, which is used by gzip for additional parameters.
  AC_PATH_PROG(GZIP_PROG, gzip)
  
+ test $with_compress_install != yes && test -n "$GZIP_PROG" && \
+    GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)"
  if test $opsys = gnu-linux; then
    AC_PATH_PROG(PAXCTL, paxctl,,
      [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin])
@@@ -1020,19 -1042,30 +1042,30 @@@ dnl (Don't use `-z nocombreloc' as -z t
  dnl Treat GCC specially since it just gives a non-fatal `unrecognized option'
  dnl if not built to support GNU ld.
  
- late_LDFLAGS=$LDFLAGS
+ dnl For a long time, -znocombreloc was added to LDFLAGS rather than
+ dnl LD_SWITCH_SYSTEM_TEMACS.  That is:
+ dnl * inappropriate, as LDFLAGS is a user option but this is essential.
+ dnl   Eg "make LDFLAGS=... all" could run into problems,
+ dnl   http://bugs.debian.org/684788
+ dnl * unnecessary, since temacs is the only thing that actually needs it.
+ dnl   Indeed this is where it was originally, prior to:
+ dnl   http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-03/msg00170.html
+ late_LDFLAGS="$LDFLAGS"
  if test x$GCC = xyes; then
-   LDFLAGS="$LDFLAGS -Wl,-znocombreloc"
+   LDFLAGS_NOCOMBRELOC="-Wl,-znocombreloc"
  else
-   LDFLAGS="$LDFLAGS -znocombreloc"
+   LDFLAGS_NOCOMBRELOC="-znocombreloc"
  fi
  
+ LDFLAGS="$LDFLAGS $LDFLAGS_NOCOMBRELOC"
  AC_MSG_CHECKING([for -znocombreloc])
  AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
    [AC_MSG_RESULT(yes)],
-   LDFLAGS=$late_LDFLAGS
+   LDFLAGS_NOCOMBRELOC=
    [AC_MSG_RESULT(no)])
  
+ LDFLAGS="$late_LDFLAGS"
  
  dnl The function dump-emacs will not be defined and temacs will do
  dnl (load "loadup") automatically unless told otherwise.
@@@ -1606,7 -1639,10 +1639,10 @@@ fail
                  [AC_MSG_ERROR([`--with-ns' was specified, but the include
    files are missing or cannot be compiled.])])
  
-   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
+   macfont_file=""
+   if test "${NS_IMPL_COCOA}" = "yes"; then
+     AC_MSG_CHECKING([for OSX 10.4 or newer])
+     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
                                       [
  #ifdef MAC_OS_X_VERSION_MAX_ALLOWED
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
                    ])],
                    ns_osx_have_104=yes,
                    ns_osx_have_104=no)
+     AC_MSG_RESULT([$ns_osx_have_104])
+     if test $ns_osx_have_104 = no; then
+        AC_MSG_ERROR([`OSX 10.4 or newer is required']);
+     fi
+     AC_MSG_CHECKING([for OSX 10.5 or newer])
+     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
+                                      [
+ #ifdef MAC_OS_X_VERSION_MAX_ALLOWED
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+  ; /* OK */
+ #else
+ #error "OSX 10.5 not found"
+ #endif
+ #endif
+                   ])],
+                   ns_osx_have_105=yes,
+                   ns_osx_have_105=no)
+     AC_MSG_RESULT([$ns_osx_have_105])
+     if test $ns_osx_have_105 = yes; then
+       macfont_file="macfont.o"
+     fi
+   fi
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <Foundation/NSObjCRuntime.h>],
                                       [NSInteger i;])],
                    ns_have_nsinteger=yes,
                    ns_have_nsinteger=no)
-   if test $ns_osx_have_104 = no; then
-      AC_MSG_ERROR([`OSX 10.4 or newer is required']);
-   fi
    if test $ns_have_nsinteger = yes; then
      AC_DEFINE(NS_HAVE_NSINTEGER, 1, [Define to 1 if `NSInteger' is defined.])
    fi
@@@ -1660,7 -1716,8 +1716,8 @@@ if test "${HAVE_NS}" = yes; the
       leimdir="\${ns_appresdir}/leim"
       INSTALL_ARCH_INDEP_EXTRA=
    fi
-   NS_OBJC_OBJ="nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o"
+   NS_OBJC_OBJ="nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o $macfont_file"
  fi
  CFLAGS="$tmp_CFLAGS"
  CPPFLAGS="$tmp_CPPFLAGS"
  
  if test "$window_system" = none && test "$gl_gcc_warnings" = yes; then
     # Too many warnings for now.
+    nw=
+    nw="$nw -Wsuggest-attribute=const"
+    nw="$nw -Wsuggest-attribute=noreturn"
+    gl_MANYWARN_COMPLEMENT([WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
     gl_WARN_ADD([-Wno-unused-variable])
     gl_WARN_ADD([-Wno-unused-but-set-variable])
     gl_WARN_ADD([-Wno-unused-but-set-parameter])
@@@ -1836,8 -1898,11 +1898,8 @@@ to configure.]
     fi
  fi
  
 -### If we're using X11, we should use the X menu package.
 -HAVE_MENUS=no
 -case ${HAVE_X11} in
 -  yes ) HAVE_MENUS=yes ;;
 -esac
 +### We always support menus.
 +HAVE_MENUS=yes
  
  # Does the opsystem file prohibit the use of the GNU malloc?
  # Assume not, until told otherwise.
@@@ -2340,7 -2405,6 +2402,6 @@@ if test "$HAVE_GSETTINGS" = "yes" || te
      SAVE_LIBS="$LIBS"
      CFLAGS="$SETTINGS_CFLAGS $CFLAGS"
      LIBS="$SETTINGS_LIBS $LIBS"
-     AC_CHECK_FUNCS([g_type_init])
      CFLAGS="$SAVE_CFLAGS"
      LIBS="$SAVE_LIBS"
  fi
@@@ -3119,9 -3183,15 +3180,9 @@@ if test "${HAVE_NS}" = "yes"; the
      ## Extra CFLAGS applied to src/*.m files.
      GNU_OBJC_CFLAGS="$GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE"
    fi
 -  # We also have mouse menus.
 -  HAVE_MENUS=yes
    OTHER_FILES=ns-app
  fi
  
 -if test "${HAVE_W32}" = "yes"; then
 -  HAVE_MENUS=yes
 -fi
 -
  ### Use session management (-lSM -lICE) if available
  HAVE_X_SM=no
  LIBXSM=
@@@ -3631,6 -3701,8 +3692,8 @@@ AC_SUBST(KRB5LIB
  AC_SUBST(DESLIB)
  AC_SUBST(KRB4LIB)
  
+ AC_CHECK_HEADERS(valgrind/valgrind.h)
  AC_CHECK_FUNCS_ONCE(tzset)
  AC_MSG_CHECKING(whether localtime caches TZ)
  AC_CACHE_VAL(emacs_cv_localtime_cache,
@@@ -4600,7 -4672,9 +4663,7 @@@ AC_SUBST(OLDXMENU_DEPS
  
  if test "${HAVE_MENUS}" = "yes" ; then
    AC_DEFINE(HAVE_MENUS, 1,
 -          [Define to 1 if you have mouse menus.
 -           (This is automatic if you use X, but the option to specify it remains.)
 -           It is also defined with other window systems that support xmenu.c.])
 +          [Define to 1 if you have mouse menus.  (This is supported in all configurations, but the option to specify it remains.)])
  fi
  
  if test "${GNU_MALLOC}" = "yes" ; then
@@@ -4636,6 -4710,24 +4699,24 @@@ AC_SUBST(CYGWIN_OBJ
  AC_SUBST(PRE_ALLOC_OBJ)
  AC_SUBST(POST_ALLOC_OBJ)
  
+ dnl Call this 'FORTIFY_SOUR' so that it sorts before the 'FORTIFY_SOURCE'
+ dnl verbatim defined above.  The tricky name is apropos, as this hack
+ dnl makes Fortify go sour!
+ AH_VERBATIM([FORTIFY_SOUR],
+ [/* Without the following workaround, Emacs runs slowly on OS X 10.8.
+    The workaround disables some useful run-time checking, so it
+    should be conditional to the platforms with the performance bug.
+    Perhaps Apple will fix this some day; also see m4/extern-inline.m4.  */
+ #if defined __APPLE__ && defined __GNUC__
+ # ifndef _DONT_USE_CTYPE_INLINE_
+ #  define _DONT_USE_CTYPE_INLINE_
+ # endif
+ # ifndef _FORTIFY_SOURCE
+ #  define _FORTIFY_SOURCE 0
+ # endif
+ #endif
+ ])
  # Configure gnulib.  Although this does not affect CFLAGS or LIBS permanently.
  # it temporarily reverts them to their pre-pkg-config values,
  # because gnulib needs to work with both src (which uses the
@@@ -4718,6 -4810,8 +4799,8 @@@ if test x$ac_enable_profiling != x ; th
    esac
  fi
  
+ LD_SWITCH_SYSTEM_TEMACS="$LDFLAGS_NOCOMBRELOC $LD_SWITCH_SYSTEM_TEMACS"
  AC_SUBST(LD_SWITCH_SYSTEM_TEMACS)
  
  ## MinGW-specific post-link processing of temacs.
diff --combined lisp/faces.el
@@@ -1921,6 -1921,11 +1921,11 @@@ Return nil if there is no face.
  ;;; Frame creation.
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
+ (declare-function x-display-list "xfns.c" ())
+ (declare-function x-open-connection "xfns.c"
+                 (display &optional xrm-string must-succeed))
+ (declare-function x-get-resource "frame.c"
+                 (attribute class &optional component subclass))
  (declare-function x-parse-geometry "frame.c" (string))
  (defvar x-display-name)
  
@@@ -2135,15 -2140,8 +2140,15 @@@ terminal type to a different value.
  (defun tty-set-up-initial-frame-faces ()
    (let ((frame (selected-frame)))
      (frame-set-background-mode frame t)
 -    (face-set-after-frame-default frame)))
 -
 +    (face-set-after-frame-default frame)
 +    (make-face 'tty-menu-enabled-face)
 +    (make-face 'tty-menu-disabled-face)
 +    (make-face 'tty-menu-selected-face)
 +    (set-face-foreground 'tty-menu-enabled-face "yellow")
 +    (set-face-foreground 'tty-menu-disabled-face "white")
 +    (set-face-background 'tty-menu-enabled-face "blue")
 +    (set-face-background 'tty-menu-disabled-face "blue")
 +    (set-face-background 'tty-menu-selected-face "red")))
  
  \f
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --combined lisp/mouse.el
@@@ -144,6 -144,79 +144,6 @@@ Expects to be bound to `down-mouse-1' i
  \f
  ;; Provide a mode-specific menu on a mouse button.
  
 -(defun popup-menu (menu &optional position prefix)
 -  "Popup the given menu and call the selected option.
 -MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
 -`x-popup-menu'.
 -The menu is shown at the place where POSITION specifies. About
 -the form of POSITION, see `popup-menu-normalize-position'.
 -PREFIX is the prefix argument (if any) to pass to the command."
 -  (let* ((map (cond
 -             ((keymapp menu) menu)
 -             ((and (listp menu) (keymapp (car menu))) menu)
 -             (t (let* ((map (easy-menu-create-menu (car menu) (cdr menu)))
 -                       (filter (when (symbolp map)
 -                                 (plist-get (get map 'menu-prop) :filter))))
 -                  (if filter (funcall filter (symbol-function map)) map)))))
 -       event cmd
 -       (position (popup-menu-normalize-position position)))
 -    ;; The looping behavior was taken from lmenu's popup-menu-popup
 -    (while (and map (setq event
 -                        ;; map could be a prefix key, in which case
 -                        ;; we need to get its function cell
 -                        ;; definition.
 -                        (x-popup-menu position (indirect-function map))))
 -      ;; Strangely x-popup-menu returns a list.
 -      ;; mouse-major-mode-menu was using a weird:
 -      ;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
 -      (setq cmd
 -          (if (and (not (keymapp map)) (listp map))
 -              ;; We were given a list of keymaps.  Search them all
 -              ;; in sequence until a first binding is found.
 -              (let ((mouse-click (apply 'vector event))
 -                    binding)
 -                (while (and map (null binding))
 -                  (setq binding (lookup-key (car map) mouse-click))
 -                  (if (numberp binding)       ; `too long'
 -                      (setq binding nil))
 -                  (setq map (cdr map)))
 -                binding)
 -            ;; We were given a single keymap.
 -            (lookup-key map (apply 'vector event))))
 -      ;; Clear out echoing, which perhaps shows a prefix arg.
 -      (message "")
 -      ;; Maybe try again but with the submap.
 -      (setq map (if (keymapp cmd) cmd)))
 -    ;; If the user did not cancel by refusing to select,
 -    ;; and if the result is a command, run it.
 -    (when (and (null map) (commandp cmd))
 -      (setq prefix-arg prefix)
 -      ;; `setup-specified-language-environment', for instance,
 -      ;; expects this to be set from a menu keymap.
 -      (setq last-command-event (car (last event)))
 -      ;; mouse-major-mode-menu was using `command-execute' instead.
 -      (call-interactively cmd))))
 -
 -(defun popup-menu-normalize-position (position)
 -  "Convert the POSITION to the form which `popup-menu' expects internally.
 -POSITION can an event, a posn- value, a value having
 -form ((XOFFSET YOFFSET) WINDOW), or nil.
 -If nil, the current mouse position is used."
 -  (pcase position
 -    ;; nil -> mouse cursor position
 -    (`nil
 -     (let ((mp (mouse-pixel-position)))
 -       (list (list (cadr mp) (cddr mp)) (car mp))))
 -    ;; Value returned from `event-end' or `posn-at-point'.
 -    ((pred posnp)
 -     (let ((xy (posn-x-y position)))
 -       (list (list (car xy) (cdr xy))
 -           (posn-window position))))
 -    ;; Event.
 -    ((pred eventp)
 -     (popup-menu-normalize-position (event-end position)))
 -    (t position)))
 -
  (defun minor-mode-menu-from-indicator (indicator)
    "Show menu for minor mode specified by INDICATOR.
  Interactively, INDICATOR is read using completion.
@@@ -1074,22 -1147,21 +1074,21 @@@ regardless of where you click.
        (deactivate-mark)))
    (or mouse-yank-at-point (mouse-set-point click))
    (let ((primary
-        (cond
-         ((eq (framep (selected-frame)) 'w32)
-          ;; MS-Windows emulates PRIMARY in x-get-selection, but not
-          ;; in x-get-selection-value (the latter only accesses the
-          ;; clipboard).  So try PRIMARY first, in case they selected
-          ;; something with the mouse in the current Emacs session.
-          (or (x-get-selection 'PRIMARY)
-              (x-get-selection-value)))
-         ((fboundp 'x-get-selection-value) ; MS-DOS and X.
-          ;; On X, x-get-selection-value supports more formats and
-          ;; encodings, so use it in preference to x-get-selection.
-          (or (x-get-selection-value)
-              (x-get-selection 'PRIMARY)))
-         ;; FIXME: What about xterm-mouse-mode etc.?
-         (t
-          (x-get-selection 'PRIMARY)))))
+          (if (fboundp 'x-get-selection-value)
+              (if (eq (framep (selected-frame)) 'w32)
+                  ;; MS-Windows emulates PRIMARY in x-get-selection, but not
+                  ;; in x-get-selection-value (the latter only accesses the
+                  ;; clipboard).  So try PRIMARY first, in case they selected
+                  ;; something with the mouse in the current Emacs session.
+                  (or (x-get-selection 'PRIMARY)
+                      (x-get-selection-value))
+                ;; Else MS-DOS or X.
+                ;; On X, x-get-selection-value supports more formats and
+                ;; encodings, so use it in preference to x-get-selection.
+                (or (x-get-selection-value)
+                    (x-get-selection 'PRIMARY)))
+            ;; FIXME: What about xterm-mouse-mode etc.?
+            (x-get-selection 'PRIMARY))))
      (unless primary
        (error "No selection is available"))
      (push-mark (point))
diff --combined src/alloc.c
@@@ -20,8 -20,6 +20,6 @@@ along with GNU Emacs.  If not, see <htt
  
  #include <config.h>
  
- #define LISP_INLINE EXTERN_INLINE
  #include <stdio.h>
  #include <limits.h>           /* For CHAR_BIT.  */
  
  
  #include <verify.h>
  
+ #if (defined ENABLE_CHECKING                  \
+      && defined HAVE_VALGRIND_VALGRIND_H      \
+      && !defined USE_VALGRIND)
+ # define USE_VALGRIND 1
+ #endif
+ #if USE_VALGRIND
+ #include <valgrind/valgrind.h>
+ #include <valgrind/memcheck.h>
+ static bool valgrind_p;
+ #endif
  /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
     Doable only if GC_MARK_STACK.  */
  #if ! GC_MARK_STACK
@@@ -971,7 -981,7 +981,7 @@@ struct ablock
  #define ABLOCKS_BASE(abase) (abase)
  #else
  #define ABLOCKS_BASE(abase) \
-   (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void**)abase)[-1])
+   (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1])
  #endif
  
  /* The list of free ablock.   */
@@@ -1026,7 -1036,7 +1036,7 @@@ lisp_align_malloc (size_t nbytes, enum 
  
        aligned = (base == abase);
        if (!aligned)
-       ((void**)abase)[-1] = base;
+       ((void **) abase)[-1] = base;
  
  #ifdef DOUG_LEA_MALLOC
        /* Back to a reasonable maximum of mmap'ed areas.  */
@@@ -2003,6 -2013,34 +2013,34 @@@ INIT must be an integer that represent
    return val;
  }
  
+ verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T);
+ verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0);
+ static ptrdiff_t
+ bool_vector_payload_bytes (ptrdiff_t nr_bits,
+                            ptrdiff_t *exact_needed_bytes_out)
+ {
+   ptrdiff_t exact_needed_bytes;
+   ptrdiff_t needed_bytes;
+   eassert_and_assume (nr_bits >= 0);
+   exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
+   needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_SIZE_T) / CHAR_BIT;
+   if (needed_bytes == 0)
+     {
+       /* Always allocate at least one machine word of payload so that
+          bool-vector operations in data.c don't need a special case
+          for empty vectors.  */
+       needed_bytes = sizeof (size_t);
+     }
+   if (exact_needed_bytes_out != NULL)
+     *exact_needed_bytes_out = exact_needed_bytes;
+   return needed_bytes;
+ }
  
  DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
         doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
@@@ -2011,37 -2049,43 +2049,43 @@@ LENGTH must be a number.  INIT matters 
  {
    register Lisp_Object val;
    struct Lisp_Bool_Vector *p;
-   ptrdiff_t length_in_chars;
-   EMACS_INT length_in_elts;
-   int bits_per_value;
-   int extra_bool_elts = ((bool_header_size - header_size + word_size - 1)
-                        / word_size);
+   ptrdiff_t exact_payload_bytes;
+   ptrdiff_t total_payload_bytes;
+   ptrdiff_t needed_elements;
  
    CHECK_NATNUM (length);
+   if (PTRDIFF_MAX < XFASTINT (length))
+     memory_full (SIZE_MAX);
  
-   bits_per_value = sizeof (EMACS_INT) * BOOL_VECTOR_BITS_PER_CHAR;
+   total_payload_bytes = bool_vector_payload_bytes
+     (XFASTINT (length), &exact_payload_bytes);
  
-   length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value;
+   eassert_and_assume (exact_payload_bytes <= total_payload_bytes);
+   eassert_and_assume (0 <= exact_payload_bytes);
  
-   val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
+   needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size)
+                                        + total_payload_bytes),
+                              word_size) / word_size;
  
-   /* No Lisp_Object to trace in there.  */
+   p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
+   XSETVECTOR (val, p);
    XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
  
-   p = XBOOL_VECTOR (val);
    p->size = XFASTINT (length);
-   length_in_chars = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
-                    / BOOL_VECTOR_BITS_PER_CHAR);
-   if (length_in_chars)
+   if (exact_payload_bytes)
      {
-       memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars);
+       memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes);
  
        /* Clear any extraneous bits in the last byte.  */
-       p->data[length_in_chars - 1]
+       p->data[exact_payload_bytes - 1]
        &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
      }
  
+   /* Clear padding at the end.  */
+   memset (p->data + exact_payload_bytes,
+           0,
+           total_payload_bytes - exact_payload_bytes);
    return val;
  }
  
      roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1)
    };
  
- /* ROUNDUP_SIZE must be a power of 2.  */
- verify ((roundup_size & (roundup_size - 1)) == 0);
  /* Verify assumptions described above.  */
  verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
  verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
  
- /* Round up X to nearest mult-of-ROUNDUP_SIZE.  */
- #define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1))
+ /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time.  */
+ #define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size)
+ /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime.  */
+ #define vroundup(x) (assume ((x) >= 0), vroundup_ct (x))
  
  /* Rounding helps to maintain alignment constraints if USE_LSB_TAG.  */
  
- #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *)))
+ #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *)))
  
  /* Size of the minimal vector allocated from block.  */
  
- #define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object))
+ #define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object))
  
  /* Size of the largest vector allocated from block.  */
  
  
  #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
  
- /* Get and set the next field in block-allocated vectorlike objects on
-    the free list.  Doing it this way respects C's aliasing rules.
-    We could instead make 'contents' a union, but that would mean
-    changes everywhere that the code uses 'contents'.  */
- static struct Lisp_Vector *
- next_in_free_list (struct Lisp_Vector *v)
- {
-   intptr_t i = XLI (v->contents[0]);
-   return (struct Lisp_Vector *) i;
- }
- static void
- set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next)
- {
-   v->contents[0] = XIL ((intptr_t) next);
- }
  /* Common shortcut to setup vector on a free list.  */
  
  #define SETUP_ON_FREE_LIST(v, nbytes, tmp)            \
      eassert ((nbytes) % roundup_size == 0);           \
      (tmp) = VINDEX (nbytes);                          \
      eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX);     \
-     set_next_in_free_list (v, vector_free_lists[tmp]);        \
+     v->u.next = vector_free_lists[tmp];                       \
      vector_free_lists[tmp] = (v);                     \
      total_free_vector_slots += (nbytes) / word_size;  \
    } while (0)
@@@ -2644,7 -2670,7 +2670,7 @@@ struct large_vecto
      struct large_vector *vector;
  #if USE_LSB_TAG
      /* We need to maintain ROUNDUP_SIZE alignment for the vector member.  */
-     unsigned char c[vroundup (sizeof (struct large_vector *))];
+     unsigned char c[vroundup_ct (sizeof (struct large_vector *))];
  #endif
    } next;
    struct Lisp_Vector v;
@@@ -2727,7 -2753,7 +2753,7 @@@ allocate_vector_from_block (size_t nbyt
    if (vector_free_lists[index])
      {
        vector = vector_free_lists[index];
-       vector_free_lists[index] = next_in_free_list (vector);
+       vector_free_lists[index] = vector->u.next;
        total_free_vector_slots -= nbytes / word_size;
        return vector;
      }
        {
        /* This vector is larger than requested.  */
        vector = vector_free_lists[index];
-       vector_free_lists[index] = next_in_free_list (vector);
+       vector_free_lists[index] = vector->u.next;
        total_free_vector_slots -= nbytes / word_size;
  
        /* Excess bytes are used for the smaller vector,
@@@ -2785,10 -2811,14 +2811,14 @@@ vector_nbytes (struct Lisp_Vector *v
    if (size & PSEUDOVECTOR_FLAG)
      {
        if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
-       size = (bool_header_size
-               + (((struct Lisp_Bool_Vector *) v)->size
-                  + BOOL_VECTOR_BITS_PER_CHAR - 1)
-               / BOOL_VECTOR_BITS_PER_CHAR);
+         {
+           struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
+           ptrdiff_t payload_bytes =
+               bool_vector_payload_bytes (bv->size, NULL);
+           eassert_and_assume (payload_bytes >= 0);
+           size = bool_header_size + ROUNDUP (payload_bytes, word_size);
+         }
        else
        size = (header_size
                + ((size & PSEUDOVECTOR_SIZE_MASK)
@@@ -2859,7 -2889,7 +2889,7 @@@ sweep_vectors (void
                free_this_block = 1;
              else
                {
-                 int tmp;
+                 size_t tmp;
                  SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
                }
            }
          total_vectors++;
          if (vector->header.size & PSEUDOVECTOR_FLAG)
            {
-             struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector;
              /* All non-bool pseudovectors are small enough to be allocated
                 from vector blocks.  This code should be redesigned if some
                 pseudovector type grows beyond VBLOCK_BYTES_MAX.  */
              eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
-             total_vector_slots
-               += (bool_header_size
-                   + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
-                      / BOOL_VECTOR_BITS_PER_CHAR)) / word_size;
+               total_vector_slots += vector_nbytes (vector) / word_size;
            }
          else
            total_vector_slots
@@@ -2941,7 -2965,7 +2965,7 @@@ allocate_vectorlike (ptrdiff_t len
        else
        {
          struct large_vector *lv
-           = lisp_malloc ((offsetof (struct large_vector, v.contents)
+           = lisp_malloc ((offsetof (struct large_vector, v.u.contents)
                            + len * word_size),
                           MEM_TYPE_VECTORLIKE);
          lv->next.vector = large_vectors;
@@@ -2995,7 -3019,7 +3019,7 @@@ allocate_pseudovector (int memlen, int 
  
    /* Only the first lisplen slots will be traced normally by the GC.  */
    for (i = 0; i < lisplen; ++i)
-     v->contents[i] = Qnil;
+     v->u.contents[i] = Qnil;
  
    XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
    return v;
@@@ -3083,7 -3107,7 +3107,7 @@@ See also the function `vector'.  */
    p = allocate_vector (XFASTINT (length));
    sizei = XFASTINT (length);
    for (i = 0; i < sizei; i++)
-     p->contents[i] = init;
+     p->u.contents[i] = init;
  
    XSETVECTOR (vector, p);
    return vector;
@@@ -3101,21 -3125,23 +3125,23 @@@ usage: (vector &rest OBJECTS)  */
    register struct Lisp_Vector *p = XVECTOR (val);
  
    for (i = 0; i < nargs; i++)
-     p->contents[i] = args[i];
+     p->u.contents[i] = args[i];
    return val;
  }
  
  void
  make_byte_code (struct Lisp_Vector *v)
  {
-   if (v->header.size > 1 && STRINGP (v->contents[1])
-       && STRING_MULTIBYTE (v->contents[1]))
+   /* Don't allow the global zero_vector to become a byte code object. */
+   eassert(0 < v->header.size);
+   if (v->header.size > 1 && STRINGP (v->u.contents[1])
+       && STRING_MULTIBYTE (v->u.contents[1]))
      /* BYTECODE-STRING must have been produced by Emacs 20.2 or the
         earlier because they produced a raw 8-bit string for byte-code
         and now such a byte-code string is loaded as multibyte while
         raw 8-bit characters converted to multibyte form.  Thus, now we
         must convert them back to the original unibyte form.  */
-     v->contents[1] = Fstring_as_unibyte (v->contents[1]);
+     v->u.contents[1] = Fstring_as_unibyte (v->u.contents[1]);
    XSETPVECTYPE (v, PVEC_COMPILED);
  }
  
@@@ -3150,7 -3176,7 +3176,7 @@@ usage: (make-byte-code ARGLIST BYTE-COD
       to be setcar'd).  */
  
    for (i = 0; i < nargs; i++)
-     p->contents[i] = args[i];
+     p->u.contents[i] = args[i];
    make_byte_code (p);
    XSETCOMPILED (val, p);
    return val;
@@@ -3378,6 -3404,7 +3404,6 @@@ make_save_obj_obj_obj_obj (Lisp_Object 
    return val;
  }
  
 -#if defined HAVE_NS || defined HAVE_NTGUI
  Lisp_Object
  make_save_ptr (void *a)
  {
    p->data[0].pointer = a;
    return val;
  }
 -#endif
  
  Lisp_Object
  make_save_ptr_int (void *a, ptrdiff_t b)
@@@ -4296,6 -4324,11 +4322,11 @@@ mark_maybe_object (Lisp_Object obj
    void *po;
    struct mem_node *m;
  
+ #if USE_VALGRIND
+   if (valgrind_p)
+     VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
+ #endif
    if (INTEGERP (obj))
      return;
  
@@@ -4364,6 -4397,11 +4395,11 @@@ mark_maybe_pointer (void *p
  {
    struct mem_node *m;
  
+ #if USE_VALGRIND
+   if (valgrind_p)
+     VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
+ #endif
    /* Quickly rule out some values which can't point to Lisp data.
       USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT.
       Otherwise, assume that Lisp data is aligned on even addresses.  */
@@@ -5131,7 -5169,7 +5167,7 @@@ Does not copy symbols.  Copies strings 
        size &= PSEUDOVECTOR_SIZE_MASK;
        vec = XVECTOR (make_pure_vector (size));
        for (i = 0; i < size; i++)
-       vec->contents[i] = Fpurecopy (AREF (obj, i));
+       vec->u.contents[i] = Fpurecopy (AREF (obj, i));
        if (COMPILEDP (obj))
        {
          XSETPVECTYPE (vec, PVEC_COMPILED);
@@@ -5622,7 -5660,7 +5658,7 @@@ mark_vectorlike (struct Lisp_Vector *pt
       The distinction is used e.g. by Lisp_Process which places extra
       non-Lisp_Object fields at the end of the structure...  */
    for (i = 0; i < size; i++) /* ...and then mark its elements.  */
-     mark_object (ptr->contents[i]);
+     mark_object (ptr->u.contents[i]);
  }
  
  /* Like mark_vectorlike but optimized for char-tables (and
@@@ -5639,7 -5677,7 +5675,7 @@@ mark_char_table (struct Lisp_Vector *pt
    VECTOR_MARK (ptr);
    for (i = 0; i < size; i++)
      {
-       Lisp_Object val = ptr->contents[i];
+       Lisp_Object val = ptr->u.contents[i];
  
        if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit))
        continue;
@@@ -5844,10 -5882,10 +5880,10 @@@ mark_object (Lisp_Object arg
              VECTOR_MARK (ptr);
              for (i = 0; i < size; i++)
                if (i != COMPILED_CONSTANTS)
-                 mark_object (ptr->contents[i]);
+                 mark_object (ptr->u.contents[i]);
              if (size > COMPILED_CONSTANTS)
                {
-                 obj = ptr->contents[COMPILED_CONSTANTS];
+                 obj = ptr->u.contents[COMPILED_CONSTANTS];
                  goto loop;
                }
            }
@@@ -6612,6 -6650,10 +6648,10 @@@ init_alloc (void
  #endif
    Vgc_elapsed = make_float (0.0);
    gcs_done = 0;
+ #if USE_VALGRIND
+   valgrind_p = RUNNING_ON_VALGRIND != 0;
+ #endif
  }
  
  void
diff --combined src/dispextern.h
@@@ -49,18 -49,16 +49,16 @@@ typedef struct 
  #endif
  
  INLINE_HEADER_BEGIN
- #ifndef DISPEXTERN_INLINE
- # define DISPEXTERN_INLINE INLINE
- #endif
  
  #include <c-strcase.h>
DISPEXTERN_INLINE int
+ INLINE int
  xstrcasecmp (char const *a, char const *b)
  {
    return c_strcasecmp (a, b);
  }
  
  #ifdef HAVE_X_WINDOWS
+ #include <X11/Xresource.h> /* for XrmDatabase */
  typedef struct x_display_info Display_Info;
  typedef XImage * XImagePtr;
  typedef XImagePtr XImagePtr_or_DC;
@@@ -288,10 -286,10 +286,10 @@@ typedef struct 
  } GLYPH;
  
  /* Return a glyph's character code.  */
DISPEXTERN_INLINE int GLYPH_CHAR (GLYPH glyph) { return glyph.ch; }
+ INLINE int GLYPH_CHAR (GLYPH glyph) { return glyph.ch; }
  
  /* Return a glyph's face ID.  */
DISPEXTERN_INLINE int GLYPH_FACE (GLYPH glyph) { return glyph.face_id; }
+ INLINE int GLYPH_FACE (GLYPH glyph) { return glyph.face_id; }
  
  #define SET_GLYPH_CHAR(glyph, char) ((glyph).ch = (char))
  #define SET_GLYPH_FACE(glyph, face) ((glyph).face_id = (face))
  
  /* The following are valid only if GLYPH_CODE_P (gc).  */
  
DISPEXTERN_INLINE int
+ INLINE int
  GLYPH_CODE_CHAR (Lisp_Object gc)
  {
    return (CONSP (gc)
          : XINT (gc) & MAX_CHAR);
  }
  
DISPEXTERN_INLINE int
+ INLINE int
  GLYPH_CODE_FACE (Lisp_Object gc)
  {
    return CONSP (gc) ? XINT (XCDR (gc)) : XINT (gc) >> CHARACTERBITS;
@@@ -794,7 -792,10 +792,10 @@@ enum glyph_row_are
     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.  */
+    glyph structure array.
+    NOTE: layout of first four members of this structure is important,
+    see clear_glyph_row and copy_row_except_pointers to check why.  */
  
  struct glyph_row
  {
       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];
+   /* Number of glyphs actually filled in areas.  This could have size
+      LAST_AREA, but it's 1 + LAST_AREA to simplify offset calculations.  */
+   short used[1 + LAST_AREA];
+   /* Hash code.  This hash code is available as soon as the row
+      is constructed, i.e. after a call to display_line.  */
+   unsigned hash;
  
    /* Window-relative x and y-position of the top-left corner of this
       row.  If y < 0, this means that eabs (y) pixels of the row are
       in last row when checking if row is fully visible.  */
    int extra_line_spacing;
  
-   /* 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 than the position of the first
@@@ -1195,12 -1197,6 +1197,6 @@@ struct glyph_row *matrix_row (struct gl
        ((ROW)->phys_height - (ROW)->phys_ascent        \
         > (ROW)->height - (ROW)->ascent)
  
- /* True means that fonts have been loaded since the last glyph
-    matrix adjustments.  The function redisplay_internal adjusts glyph
-    matrices when this flag is true.  */
- extern bool fonts_changed_p;
  /* A glyph for a space.  */
  
  extern struct glyph space_glyph;
@@@ -1428,31 -1424,31 +1424,31 @@@ struct glyph_strin
  #define CURRENT_MODE_LINE_FACE_ID(W)          \
        (CURRENT_MODE_LINE_FACE_ID_3((W), XWINDOW (selected_window), (W)))
  
- /* Return the current height of the mode line of window W.  If not
-    known from current_mode_line_height, look at W's current glyph
-    matrix, or return a default based on the height of the font of the
-    face `mode-line'.  */
+ /* Return the current height of the mode line of window W.  If not known
+    from W->mode_line_height, look at W's current glyph matrix, or return
+    a default based on the height of the font of the face `mode-line'.  */
  
- #define CURRENT_MODE_LINE_HEIGHT(W)                           \
-      (current_mode_line_height >= 0                           \
-       ? current_mode_line_height                              \
-       : (MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix)                \
-        ? MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix)        \
-        : estimate_mode_line_height (XFRAME ((W)->frame),      \
-                                     CURRENT_MODE_LINE_FACE_ID (W))))
+ #define CURRENT_MODE_LINE_HEIGHT(W)                                   \
+   (W->mode_line_height >= 0                                           \
+    ? W->mode_line_height                                              \
+    : (W->mode_line_height                                             \
+       = (MATRIX_MODE_LINE_HEIGHT (W->current_matrix)                  \
+        ? MATRIX_MODE_LINE_HEIGHT (W->current_matrix)                  \
+        : estimate_mode_line_height                                    \
+            (XFRAME (W->frame), CURRENT_MODE_LINE_FACE_ID (W)))))
  
- /* Return the current height of the header line of window W.  If not
-    known from current_header_line_height, look at W's current glyph
-    matrix, or return an estimation based on the height of the font of
-    the face `header-line'.  */
+ /* Return the current height of the header line of window W.  If not known
+    from W->header_line_height, look at W's current glyph matrix, or return
+    an estimation based on the height of the font of the face `header-line'.  */
  
  #define CURRENT_HEADER_LINE_HEIGHT(W)                         \
-       (current_header_line_height >= 0                                \
-        ? current_header_line_height                           \
-        : (MATRIX_HEADER_LINE_HEIGHT ((W)->current_matrix)     \
-         ? MATRIX_HEADER_LINE_HEIGHT ((W)->current_matrix)     \
-         : estimate_mode_line_height (XFRAME ((W)->frame),     \
-                                      HEADER_LINE_FACE_ID)))
+   (W->header_line_height >= 0                                 \
+    ? W->header_line_height                                    \
+    : (W->header_line_height                                   \
+       = (MATRIX_HEADER_LINE_HEIGHT (W->current_matrix)                \
+        ? MATRIX_HEADER_LINE_HEIGHT (W->current_matrix)        \
+        : estimate_mode_line_height                            \
+            (XFRAME (W->frame), HEADER_LINE_FACE_ID))))
  
  /* Return the height of the desired mode line of window W.  */
  
@@@ -1829,7 -1825,7 +1825,7 @@@ struct face_cach
  #endif /* not HAVE_WINDOW_SYSTEM */
  
  /* Return true if G contains a valid character code.  */
DISPEXTERN_INLINE bool
+ INLINE bool
  GLYPH_CHAR_VALID_P (GLYPH g)
  {
    return CHAR_VALID_P (GLYPH_CHAR (g));
     encodes a char code in the lower CHARACTERBITS bits and a (very small)
     face-id in the upper bits, or it may be a cons (CHAR . FACE-ID).  */
  
DISPEXTERN_INLINE bool
+ INLINE bool
  GLYPH_CODE_P (Lisp_Object gc)
  {
    return (CONSP (gc)
@@@ -2710,7 -2706,7 +2706,7 @@@ typedef struct 
    unsigned mouse_face_hidden : 1;
  } Mouse_HLInfo;
  
DISPEXTERN_INLINE void
+ INLINE void
  reset_mouse_highlight (Mouse_HLInfo *hlinfo)
  {
  
@@@ -2802,11 -2798,6 +2798,6 @@@ struct redisplay_interfac
    /* Flush the display of frame F.  For X, this is XFlush.  */
    void (*flush_display) (struct frame *f);
  
-   /* Flush the display of frame F if non-NULL.  This is called
-      during redisplay, and should be NULL on systems which flush
-      automatically before reading input.  */
-   void (*flush_display_optional) (struct frame *f);
    /* Clear the mouse highlight in window W, if there is any.  */
    void (*clear_window_mouse_face) (struct window *w);
  
@@@ -3200,12 -3191,10 +3191,10 @@@ int in_display_vector_p (struct it *)
  int frame_mode_line_height (struct frame *);
  extern Lisp_Object Qtool_bar;
  extern bool redisplaying_p;
- extern int help_echo_showing_p;
- extern int current_mode_line_height, current_header_line_height;
+ extern bool help_echo_showing_p;
  extern Lisp_Object help_echo_string, help_echo_window;
  extern Lisp_Object help_echo_object, previous_help_echo_string;
  extern ptrdiff_t help_echo_pos;
- extern struct frame *last_mouse_frame;
  extern int last_tool_bar_item;
  extern void reseat_at_previous_visible_line_start (struct it *);
  extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
@@@ -3215,6 -3204,7 +3204,7 @@@ extern ptrdiff_t compute_display_string
  extern ptrdiff_t compute_display_string_end (ptrdiff_t,
                                             struct bidi_string_data *);
  extern void produce_stretch_glyph (struct it *);
+ extern int merge_glyphless_glyph_face (struct it *);
  
  #ifdef HAVE_WINDOW_SYSTEM
  
@@@ -3266,7 -3256,6 +3256,7 @@@ extern int clear_mouse_face (Mouse_HLIn
  extern int cursor_in_mouse_face_p (struct window *w);
  extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
                                          int, int, enum draw_glyphs_face);
 +extern void display_tty_menu_item (const char *, int, int, int, int, int);
  
  /* Flags passed to try_window.  */
  #define TRY_WINDOW_CHECK_MARGINS      (1 << 0)
@@@ -3404,7 -3393,7 +3394,7 @@@ extern frame_parm_handler x_frame_parm_
  
  extern void start_hourglass (void);
  extern void cancel_hourglass (void);
- extern int hourglass_shown_p;
+ extern bool hourglass_shown_p;
  /* If non-null, an asynchronous timer that, when it expires, displays
     an hourglass cursor on all frames.  */
  extern struct atimer *hourglass_atimer;
@@@ -3438,8 -3427,6 +3428,8 @@@ extern void hide_hourglass (void)
  
  int popup_activated (void);
  
 +/* Defined in dispnew.c */
 +
  extern Lisp_Object buffer_posn_from_coords (struct window *,
                                              int *, int *,
                                              struct display_pos *,
@@@ -3454,13 -3441,9 +3444,10 @@@ extern Lisp_Object marginal_area_strin
                                           Lisp_Object *,
                                           int *, int *, int *, int *);
  extern void redraw_frame (struct frame *);
- extern void cancel_line (int, struct frame *);
- extern void init_desired_glyphs (struct frame *);
  extern bool update_frame (struct frame *, bool, bool);
 +extern void update_frame_with_menu (struct frame *);
  extern void bitch_at_user (void);
- void adjust_glyphs (struct frame *);
- struct glyph_matrix *save_current_matrix (struct frame *);
+ extern void adjust_frame_glyphs (struct frame *);
  void free_glyphs (struct frame *);
  void free_window_matrices (struct window *);
  void check_glyph_memory (void);
@@@ -3484,7 -3467,7 +3471,7 @@@ void change_frame_size (struct frame *
  void init_display (void);
  void syms_of_display (void);
  extern Lisp_Object Qredisplay_dont_pause;
 -void spec_glyph_lookup_face (struct window *, GLYPH *);
 +extern void spec_glyph_lookup_face (struct window *, GLYPH *);
  
  /* Defined in terminal.c */
  
@@@ -3546,6 -3529,7 +3533,7 @@@ enum resource_type
    RES_TYPE_BOOLEAN_NUMBER
  };
  
+ extern Display_Info *check_x_display_info (Lisp_Object);
  extern Lisp_Object x_get_arg (Display_Info *, Lisp_Object,
                                Lisp_Object, const char *, const char *class,
                                enum resource_types);
@@@ -3557,6 -3541,13 +3545,13 @@@ extern Lisp_Object x_default_parameter 
                                          Lisp_Object, Lisp_Object,
                                          const char *, const char *,
                                          enum resource_types);
+ extern char *x_get_string_resource (XrmDatabase, const char *,
+                                   const char *);
+ #ifndef HAVE_NS /* These both used on W32 and X only.  */
+ extern bool x_mouse_grabbed (Display_Info *);
+ extern void x_redo_mouse_highlight (Display_Info *);
+ #endif /* HAVE_NS */
  
  #endif /* HAVE_WINDOW_SYSTEM */
  
diff --combined src/dispnew.c
@@@ -20,8 -20,6 +20,6 @@@ along with GNU Emacs.  If not, see <htt
  
  #include <config.h>
  
- #define DISPEXTERN_INLINE EXTERN_INLINE
  #include "sysstdio.h"
  #include <unistd.h>
  
@@@ -77,7 -75,6 +75,6 @@@ struct di
  static void update_frame_line (struct frame *, int);
  static int required_matrix_height (struct window *);
  static int required_matrix_width (struct window *);
- static void adjust_frame_glyphs (struct frame *);
  static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
  static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
  static void fill_up_frame_row_with_spaces (struct glyph_row *, int);
@@@ -105,30 -102,12 +102,12 @@@ static void set_window_cursor_after_upd
  static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
  static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
  
- /* True upon entry to redisplay means do not assume anything about
-    current contents of actual terminal frame; clear and redraw it.  */
- bool frame_garbaged;
  /* True means last display completed.  False means it was preempted.  */
  
  bool display_completed;
  
  Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
  
\f
- /* The currently selected frame.  In a single-frame version, this
-    variable always equals the_only_frame.  */
- Lisp_Object 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.  */
- struct frame *last_nonminibuf_frame;
  /* True means SIGWINCH happened when not safe.  */
  
  static bool delayed_size_change;
@@@ -152,16 -131,6 +131,6 @@@ static int glyph_pool_count
  
  static struct frame *frame_matrix_frame;
  
- /* True 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 true during display.  The
-    reason fonts can be loaded so late is that fonts of fontsets are
-    loaded on demand.  Another reason is that a line contains many
-    characters displayed by zero width or very narrow glyphs of
-    variable-width fonts.  */
- bool fonts_changed_p;
  /* Convert vpos and hpos from frame to window and vice versa.
     This may only be used for terminal frames.  */
  
@@@ -433,7 -402,7 +402,7 @@@ adjust_glyph_matrix (struct window *w, 
                                  || right != matrix->right_margin_glyphs);
  
        if (!marginal_areas_changed_p
-         && !fonts_changed_p
+         && !XFRAME (w->frame)->fonts_changed
          && !header_line_changed_p
          && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
          && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
@@@ -794,9 -763,11 +763,11 @@@ clear_current_matrices (register struc
      clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
  #endif
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
    /* Clear the matrix of the tool-bar window, if any.  */
    if (WINDOWP (f->tool_bar_window))
      clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+ #endif
  
    /* Clear current window matrices.  */
    eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
@@@ -817,8 -788,10 +788,10 @@@ clear_desired_matrices (register struc
      clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
  #endif
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
    if (WINDOWP (f->tool_bar_window))
      clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
+ #endif
  
    /* Do it for window matrices.  */
    eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
@@@ -859,41 -832,16 +832,16 @@@ clear_window_matrices (struct window *w
        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.  */
- static struct glyph_row null_row;
+ /* Clear glyph row ROW.  NOTE: this code relies on the current
+    layout of `glyphs' and `used' fields of `struct glyph_row'.  */
  
  void
  clear_glyph_row (struct glyph_row *row)
  {
-   struct glyph *p[1 + LAST_AREA];
-   /* 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];
- #if 0 /* At some point, some bit-fields of struct glyph were not set,
-        which made glyphs unequal when compared with GLYPH_EQUAL_P.
-        Redisplay outputs such glyphs, and flickering effects were
-        the result.  This also depended on the contents of memory
-        returned by xmalloc.  If flickering happens again, activate
-        the code below.  If the flickering is gone with that, chances
-        are that the flickering has the same reason as here.  */
-   memset (p[0], 0, (char *) p[LAST_AREA] - (char *) p[0]);
- #endif
+   enum { off = offsetof (struct glyph_row, used) };
+   /* Zero everything except pointers in `glyphs'.  */
+   memset (row->used, 0, sizeof *row - off);
  }
  
  
@@@ -1032,29 -980,17 +980,17 @@@ swap_glyph_pointers (struct glyph_row *
  }
  
  
- /* Copy glyph row structure FROM to glyph row structure TO, except
-    that glyph pointers, the `used' counts, and the hash values in the
-    structures are left unchanged.  */
+ /* Copy glyph row structure FROM to glyph row structure TO, except that
+    glyph pointers, the `used' counts, and the hash values in the structures
+    are left unchanged.  NOTE: this code relies on the current layout of
+    `glyphs', `used', `hash' and `x' fields of `struct glyph_row'.  */
  
  static void
  copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
  {
-   struct glyph *pointers[1 + LAST_AREA];
-   short used[LAST_AREA];
-   unsigned hashval;
-   /* Save glyph pointers of TO.  */
-   memcpy (pointers, to->glyphs, sizeof to->glyphs);
-   memcpy (used, to->used, sizeof to->used);
-   hashval = to->hash;
-   /* Do a structure assignment.  */
-   *to = *from;
-   /* Restore original pointers of TO.  */
-   memcpy (to->glyphs, pointers, sizeof to->glyphs);
-   memcpy (to->used, used, sizeof to->used);
-   to->hash = hashval;
+   enum { off = offsetof (struct glyph_row, x) };
+   memcpy (&to->x, &from->x, sizeof *to - off);
  }
  
  
@@@ -1799,37 -1735,17 +1735,17 @@@ allocate_matrices_for_window_redisplay 
      }
  }
  
- /* 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.  */
+ /* Allocate/reallocate glyph matrices of a single frame F.
+    This function must be called when a new frame is created,
+    its size changes, or its window configuration changes.  */
  
  void
- adjust_glyphs (struct frame *f)
+ adjust_frame_glyphs (struct frame *f)
  {
    /* Block input so that expose events and other events that access
       glyph matrices are not processed while we are changing them.  */
    block_input ();
  
-   if (f)
-     adjust_frame_glyphs (f);
-   else
-     {
-       Lisp_Object tail, lisp_frame;
-       FOR_EACH_FRAME (tail, lisp_frame)
-       adjust_frame_glyphs (XFRAME (lisp_frame));
-     }
-   unblock_input ();
- }
- /* Allocate/reallocate glyph matrices of a single frame F.  */
- static void
- adjust_frame_glyphs (struct frame *f)
- {
    if (FRAME_WINDOW_P (f))
      adjust_frame_glyphs_for_window_redisplay (f);
    else
    adjust_decode_mode_spec_buffer (f);
  
    f->glyphs_initialized_p = 1;
+   unblock_input ();
  }
  
  /* Return true if any window in the tree has nonzero window margins.  See
@@@ -1913,7 -1831,7 +1831,7 @@@ fake_current_matrices (Lisp_Object wind
  /* Save away the contents of frame F's current frame matrix.  Value is
     a glyph matrix holding the contents of F's current frame matrix.  */
  
- struct glyph_matrix *
+ static struct glyph_matrix *
  save_current_matrix (struct frame *f)
  {
    int i;
        struct glyph_row *from = f->current_matrix->rows + i;
        struct glyph_row *to = saved->rows + i;
        ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
 +
        to->glyphs[TEXT_AREA] = xmalloc (nbytes);
        memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
        to->used[TEXT_AREA] = from->used[TEXT_AREA];
 +      to->enabled_p = from->enabled_p;
 +      to->hash = from->hash;
 +      if (from->used[LEFT_MARGIN_AREA])
 +      {
 +        nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
 +        to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
 +        memcpy (to->glyphs[LEFT_MARGIN_AREA],
 +                from->glyphs[LEFT_MARGIN_AREA], nbytes);
 +        to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
 +      }
 +      if (from->used[RIGHT_MARGIN_AREA])
 +      {
 +        nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
 +        to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
 +        memcpy (to->glyphs[RIGHT_MARGIN_AREA],
 +                from->glyphs[RIGHT_MARGIN_AREA], nbytes);
 +        to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
 +      }
      }
  
    return saved;
@@@ -1967,30 -1866,9 +1885,30 @@@ restore_current_matrix (struct frame *f
        struct glyph_row *from = saved->rows + i;
        struct glyph_row *to = f->current_matrix->rows + i;
        ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
 +
        memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
        to->used[TEXT_AREA] = from->used[TEXT_AREA];
        xfree (from->glyphs[TEXT_AREA]);
 +      nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
 +      if (nbytes)
 +      {
 +        memcpy (to->glyphs[LEFT_MARGIN_AREA],
 +                from->glyphs[LEFT_MARGIN_AREA], nbytes);
 +        to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
 +        xfree (from->glyphs[LEFT_MARGIN_AREA]);
 +      }
 +      else
 +      to->used[LEFT_MARGIN_AREA] = 0;
 +      nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
 +      if (nbytes)
 +      {
 +        memcpy (to->glyphs[RIGHT_MARGIN_AREA],
 +                from->glyphs[RIGHT_MARGIN_AREA], nbytes);
 +        to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
 +        xfree (from->glyphs[RIGHT_MARGIN_AREA]);
 +      }
 +      else
 +      to->used[RIGHT_MARGIN_AREA] = 0;
      }
  
    xfree (saved->rows);
@@@ -2110,10 -1988,9 +2028,9 @@@ adjust_frame_glyphs_for_window_redispla
    /* Allocate/reallocate window matrices.  */
    allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
  
- #ifdef HAVE_X_WINDOWS
+ #if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
    /* Allocate/ reallocate matrices of the dummy window used to display
       the menu bar under X when no X toolkit support is available.  */
- #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
    {
      /* Allocate a dummy window if not already done.  */
      struct window *w;
      w->total_cols = FRAME_TOTAL_COLS (f);
      allocate_matrices_for_window_redisplay (w);
    }
- #endif /* not USE_X_TOOLKIT && not USE_GTK */
- #endif /* HAVE_X_WINDOWS */
+ #endif
  
- #ifndef USE_GTK
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
    {
      /* Allocate/ reallocate matrices of the tool bar window.  If we
         don't have a tool bar window yet, make one.  */
@@@ -2214,6 -2090,7 +2130,7 @@@ free_glyphs (struct frame *f
        }
  #endif
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
        /* Free the tool bar window and its glyph matrices.  */
        if (!NILP (f->tool_bar_window))
        {
          w->desired_matrix = w->current_matrix = NULL;
          fset_tool_bar_window (f, Qnil);
        }
+ #endif
  
        /* Release frame glyph matrices.  Reset fields to zero in
         case we are called a second time.  */
@@@ -3105,6 -2983,7 +3023,7 @@@ update_frame (struct frame *f, bool for
        update_window (XWINDOW (f->menu_bar_window), 1);
  #endif
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
        /* Update the tool-bar window, if present.  */
        if (WINDOWP (f->tool_bar_window))
        {
              fset_desired_tool_bar_string (f, tem);
            }
        }
+ #endif
  
        /* Update windows.  */
        paused_p = update_window_tree (root_window, force_p);
        update_end (f);
-       /* This flush is a performance bottleneck under X,
-        and it doesn't seem to be necessary anyway (in general).
-          It is necessary when resizing the window with the mouse, or
-        at least the fringes are not redrawn in a timely manner.  ++kfs */
-       if (f->force_flush_display_p)
-       {
-         FRAME_RIF (f)->flush_display (f);
-         f->force_flush_display_p = 0;
-       }
      }
    else
      {
    return paused_p;
  }
  
 +/* Update a TTY frame F that has a menu dropped down over some of its
 +   glyphs.  This is like the second part of update_frame, but it
 +   doesn't call build_frame_matrix, because we already have the
 +   desired matrix prepared, and don't want it to be overwritten by the
 +   text of the normal display.  */
 +void
 +update_frame_with_menu (struct frame *f)
 +{
 +  struct window *root_window = XWINDOW (f->root_window);
 +  bool paused_p;
 +
 +  eassert (FRAME_TERMCAP_P (f));
 +
 +  /* We are working on frame matrix basis.  Set the frame on whose
 +     frame matrix we operate.  */
 +  set_frame_matrix_frame (f);
 +
 +  /* Update the display  */
 +  update_begin (f);
 +  /* Force update_frame_1 not to stop due to pending input, and not
 +     try scrolling.  */
 +  paused_p = update_frame_1 (f, 1, 1);
 +  update_end (f);
 +
 +  if (FRAME_TTY (f)->termscript)
 +    fflush (FRAME_TTY (f)->termscript);
 +  fflush (FRAME_TTY (f)->output);
 +  /* Check window matrices for lost pointers.  */
 +#if GLYPH_DEBUG
 +#if 0
 +      /* We cannot possibly survive the matrix pointers check, since
 +       we have overwritten parts of the frame glyph matrix without
 +       making any updates to the window matrices.  */
 +  check_window_matrix_pointers (root_window);
 +#endif
 +  add_frame_display_history (f, paused_p);
 +#endif
 +
 +  /* Reset flags indicating that a window should be updated.  */
 +  set_window_update_flags (root_window, 0);
 +}
  
  \f
  /************************************************************************
@@@ -4568,7 -4396,7 +4477,7 @@@ update_frame_1 (struct frame *f, bool f
        }
      }
  
-   lint_assume (0 <= FRAME_LINES (f));
+   assume (0 <= FRAME_LINES (f));
    pause_p = 0 < i && i < FRAME_LINES (f) - 1;
  
    /* Now just clean up termcap drivers and set cursor, etc.  */
@@@ -5608,8 -5436,10 +5517,10 @@@ change_frame_size_1 (struct frame *f, i
        if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
        FrameCols (FRAME_TTY (f)) = newwidth;
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
        if (WINDOWP (f->tool_bar_window))
        XWINDOW (f->tool_bar_window)->total_cols = newwidth;
+ #endif
      }
  
    FRAME_LINES (f) = newheight;
        w->cursor.vpos = w->cursor.y = 0;
    }
  
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
    calculate_costs (f);
    SET_FRAME_GARBAGED (f);
    f->resized_p = 1;
diff --combined src/keyboard.c
@@@ -20,9 -20,6 +20,6 @@@ along with GNU Emacs.  If not, see <htt
  
  #include <config.h>
  
- #define BLOCKINPUT_INLINE EXTERN_INLINE
- #define KEYBOARD_INLINE EXTERN_INLINE
  #include "sysstdio.h"
  
  #include "lisp.h"
@@@ -292,7 -289,7 +289,7 @@@ static struct input_event * volatile kb
     at inopportune times.  */
  
  /* Symbols to head events.  */
 -static Lisp_Object Qmouse_movement;
 +Lisp_Object Qmouse_movement;
  static Lisp_Object Qscroll_bar_movement;
  Lisp_Object Qswitch_frame;
  static Lisp_Object Qfocus_in, Qfocus_out;
@@@ -357,8 -354,6 +354,8 @@@ Lisp_Object Qvertical_line
  static Lisp_Object Qvertical_scroll_bar;
  Lisp_Object Qmenu_bar;
  
 +static Lisp_Object Qecho_keystrokes;
 +
  static void recursive_edit_unwind (Lisp_Object buffer);
  static Lisp_Object command_loop (void);
  static Lisp_Object Qcommand_execute;
@@@ -1310,7 -1305,7 +1307,7 @@@ some_mouse_moved (void
     sans error-handling encapsulation.  */
  
  static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
 -                              bool, bool, bool);
 +                              bool, bool, bool, bool);
  void safe_run_hooks (Lisp_Object);
  static void adjust_point_for_property (ptrdiff_t, bool);
  
@@@ -1436,7 -1431,7 +1433,7 @@@ command_loop_1 (void
  
        /* Read next key sequence; i gets its length.  */
        i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
 -                           Qnil, 0, 1, 1);
 +                           Qnil, 0, 1, 1, 0);
  
        /* A filter may have run while we were reading the input.  */
        if (! FRAME_LIVE_P (XFRAME (selected_frame)))
      }
  }
  
 +Lisp_Object
 +read_menu_command (void)
 +{
 +  Lisp_Object cmd;
 +  Lisp_Object keybuf[30];
 +  ptrdiff_t count = SPECPDL_INDEX ();
 +  int i;
 +
 +  /* We don't want to echo the keystrokes while navigating the
 +     menus.  */
 +  specbind (Qecho_keystrokes, make_number (0));
 +
 +  i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
 +                       Qnil, 0, 1, 1, 1);
 +
 +  unbind_to (count, Qnil);
 +
 +  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 +    Fkill_emacs (Qnil);
 +  if (i == 0 || i == -1)
 +    return Qt;
 +
 +  return read_key_sequence_cmd;
 +}
 +
  /* Adjust point to a boundary of a region that has such a property
     that should be treated intangible.  For the moment, we check
     `composition', `display' and `invisible' properties.
@@@ -2388,7 -2358,6 +2385,7 @@@ read_decoded_event_from_main_queue (str
  /* Read a character from the keyboard; call the redisplay if needed.  */
  /* commandflag 0 means do not autosave, but do redisplay.
     -1 means do not redisplay, but do autosave.
 +   -2 means do neither.
     1 means do both.  */
  
  /* The arguments MAP is for menu prompting.  MAP is a keymap.
@@@ -2624,10 -2593,8 +2621,8 @@@ read_char (int commandflag, Lisp_Objec
  
    if (/* There currently is something in the echo area.  */
        !NILP (echo_area_buffer[0])
-       && (/* And it's either not from echoing.  */
-         !EQ (echo_area_buffer[0], echo_message_buffer)
-         /* Or it's an echo from a different kboard.  */
-         || echo_kboard != current_kboard
+       && (/* It's an echo from a different kboard.  */
+         echo_kboard != current_kboard
          /* Or we explicitly allow overwriting whatever there is.  */
          || ok_to_echo_at_next_pause == NULL))
      cancel_echoing ();
  
    /* Maybe auto save due to number of keystrokes.  */
  
 -  if (commandflag != 0
 +  if (commandflag != 0 && commandflag != -2
        && auto_save_interval > 0
        && num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
        && !detect_input_pending_run_timers (0))
         9 at 200k, 11 at 300k, and 12 at 500k.  It is 15 at 1 meg.  */
  
        /* Auto save if enough time goes by without input.  */
 -      if (commandflag != 0
 +      if (commandflag != 0 && commandflag != -2
          && num_nonmacro_input_events > last_auto_save
          && INTEGERP (Vauto_save_timeout)
          && XINT (Vauto_save_timeout) > 0)
@@@ -3903,22 -3870,7 +3898,22 @@@ kbd_buffer_get_event (KBOARD **kbp
            }
        }
        else
 -      wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
 +      {
 +        bool do_display = true;
 +
 +        if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
 +          {
 +            struct tty_display_info *tty = CURTTY ();
 +
 +            /* When this TTY is displaying a menu, we must prevent
 +               any redisplay, because we modify the frame's glyph
 +               matrix behind the back of the display engine.  */
 +            if (tty->showing_menu)
 +              do_display = false;
 +          }
 +
 +        wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
 +      }
  
        if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
        gobble_input ();
@@@ -4389,7 -4341,7 +4384,7 @@@ decode_timer (Lisp_Object timer, struc
  
    if (! (VECTORP (timer) && ASIZE (timer) == 9))
      return 0;
-   vector = XVECTOR (timer)->contents;
+   vector = XVECTOR (timer)->u.contents;
    if (! NILP (vector[0]))
      return 0;
  
@@@ -8046,7 -7998,7 +8041,7 @@@ process_tool_bar_item (Lisp_Object key
         discard any previously made item.  */
        for (i = 0; i < ntool_bar_items; i += TOOL_BAR_ITEM_NSLOTS)
        {
-         Lisp_Object *v = XVECTOR (tool_bar_items_vector)->contents + i;
+         Lisp_Object *v = XVECTOR (tool_bar_items_vector)->u.contents + i;
  
          if (EQ (key, v[TOOL_BAR_ITEM_KEY]))
            {
@@@ -8370,7 -8322,7 +8365,7 @@@ append_tool_bar_item (void
    /* Append entries from tool_bar_item_properties to the end of
       tool_bar_items_vector.  */
    vcopy (tool_bar_items_vector, ntool_bar_items,
-        XVECTOR (tool_bar_item_properties)->contents, TOOL_BAR_ITEM_NSLOTS);
+        XVECTOR (tool_bar_item_properties)->u.contents, TOOL_BAR_ITEM_NSLOTS);
    ntool_bar_items += TOOL_BAR_ITEM_NSLOTS;
  }
  
@@@ -8839,9 -8791,6 +8834,9 @@@ test_undefined (Lisp_Object binding
  
     Echo starting immediately unless `prompt' is 0.
  
 +   If PREVENT_REDISPLAY is non-zero, avoid redisplay by calling
 +   read_char with a suitable COMMANDFLAG argument.
 +
     Where a key sequence ends depends on the currently active keymaps.
     These include any minor mode keymaps active in the current buffer,
     the current buffer's local map, and the global map.
  static int
  read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                   bool dont_downcase_last, bool can_return_switch_frame,
 -                 bool fix_current_buffer)
 +                 bool fix_current_buffer, bool prevent_redisplay)
  {
    ptrdiff_t count = SPECPDL_INDEX ();
  
      {
        if (!NILP (prompt))
        {
 -        /* Install the string STR as the beginning of the string of
 -           echoing, so that it serves as a prompt for the next
 +        /* Install the string PROMPT as the beginning of the string
 +           of echoing, so that it serves as a prompt for the next
             character.  */
          kset_echo_string (current_kboard, prompt);
          current_kboard->echo_after_prompt = SCHARS (prompt);
          {
            KBOARD *interrupted_kboard = current_kboard;
            struct frame *interrupted_frame = SELECTED_FRAME ();
 -          key = read_char (NILP (prompt),
 +          /* Calling read_char with COMMANDFLAG = -2 avoids
 +             redisplay in read_char and its subroutines.  */
 +          key = read_char (prevent_redisplay ? -2 : NILP (prompt),
                             current_binding, last_nonmenu_event,
                               &used_mouse_menu, NULL);
            if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
@@@ -9809,7 -9756,7 +9804,7 @@@ read_key_sequence_vs (Lisp_Object promp
  
    i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
                         prompt, ! NILP (dont_downcase_last),
 -                       ! NILP (can_return_switch_frame), 0);
 +                       ! NILP (can_return_switch_frame), 0, 0);
  
  #if 0  /* The following is fine for code reading a key sequence and
          then proceeding with a lengthy computation, but it's not good
@@@ -9921,20 -9868,7 +9916,7 @@@ detect_input_pending_run_timers (bool d
      get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
  
    if (old_timers_run != timers_run && do_display)
-     {
-       redisplay_preserve_echo_area (8);
-       /* The following fixes a bug when using lazy-lock with
-        lazy-lock-defer-on-the-fly set to t, i.e.  when fontifying
-        from an idle timer function.  The symptom of the bug is that
-        the cursor sometimes doesn't become visible until the next X
-        event is processed.  --gerd.  */
-       {
-         Lisp_Object tail, frame;
-         FOR_EACH_FRAME (tail, frame)
-           if (FRAME_RIF (XFRAME (frame)))
-             FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
-       }
-     }
+     redisplay_preserve_echo_area (8);
  
    return input_pending;
  }
@@@ -9985,7 -9919,7 +9967,7 @@@ DEFUN ("recent-keys", Frecent_keys, Sre
         doc: /* Return vector of last 300 events, not counting those from keyboard macros.  */)
    (void)
  {
-   Lisp_Object *keys = XVECTOR (recent_keys)->contents;
+   Lisp_Object *keys = XVECTOR (recent_keys)->u.contents;
    Lisp_Object val;
  
    if (total_keys < NUM_RECENT_KEYS)
@@@ -10011,7 -9945,7 +9993,7 @@@ See also `this-command-keys-vector'.  *
    (void)
  {
    return make_event_array (this_command_key_count,
-                          XVECTOR (this_command_keys)->contents);
+                          XVECTOR (this_command_keys)->u.contents);
  }
  
  DEFUN ("this-command-keys-vector", Fthis_command_keys_vector, Sthis_command_keys_vector, 0, 0, 0,
@@@ -10023,7 -9957,7 +10005,7 @@@ See also `this-command-keys'.  */
    (void)
  {
    return Fvector (this_command_key_count,
-                 XVECTOR (this_command_keys)->contents);
+                 XVECTOR (this_command_keys)->u.contents);
  }
  
  DEFUN ("this-single-command-keys", Fthis_single_command_keys,
@@@ -10038,7 -9972,7 +10020,7 @@@ The value is always a vector.  */
  {
    return Fvector (this_command_key_count
                  - this_single_command_key_start,
-                 (XVECTOR (this_command_keys)->contents
+                 (XVECTOR (this_command_keys)->u.contents
                   + this_single_command_key_start));
  }
  
@@@ -10052,8 -9986,7 +10034,7 @@@ shows the events before all translation
  The value is always a vector.  */)
    (void)
  {
-   return Fvector (raw_keybuf_count,
-                 (XVECTOR (raw_keybuf)->contents));
+   return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->u.contents);
  }
  
  DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
@@@ -11069,8 -11002,6 +11050,8 @@@ syms_of_keyboard (void
  
    DEFSYM (Qhelp_form_show, "help-form-show");
  
 +  DEFSYM (Qecho_keystrokes, "echo-keystrokes");
 +
    Fset (Qinput_method_exit_on_first_char, Qnil);
    Fset (Qinput_method_use_echo_area, Qnil);
  
diff --combined src/keyboard.h
@@@ -22,9 -22,6 +22,6 @@@ along with GNU Emacs.  If not, see <htt
  #include "termhooks.h"
  
  INLINE_HEADER_BEGIN
- #ifndef KEYBOARD_INLINE
- # define KEYBOARD_INLINE INLINE
- #endif
  
  /* Most code should use this macro to access Lisp fields in struct kboard.  */
  
@@@ -179,42 -176,42 +176,42 @@@ struct kboar
      ptrdiff_t echo_after_prompt;
    };
  
KEYBOARD_INLINE void
+ INLINE void
  kset_default_minibuffer_frame (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vdefault_minibuffer_frame) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_defining_kbd_macro (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (defining_kbd_macro) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_input_decode_map (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vinput_decode_map) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_last_command (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vlast_command) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_last_kbd_macro (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vlast_kbd_macro) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_prefix_arg (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vprefix_arg) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_system_key_alist (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vsystem_key_alist) = val;
  }
KEYBOARD_INLINE void
+ INLINE void
  kset_window_system (struct kboard *kb, Lisp_Object val)
  {
    kb->INTERNAL_FIELD (Vwindow_system) = val;
@@@ -453,7 -450,7 +450,7 @@@ extern Lisp_Object Qswitch_frame
  extern Lisp_Object Qevent_kind;
  
  /* The values of Qevent_kind properties.  */
 -extern Lisp_Object Qmouse_click;
 +extern Lisp_Object Qmouse_click, Qmouse_movement;
  
  extern Lisp_Object Qhelp_echo;
  
diff --combined src/menu.c
@@@ -50,16 -50,10 +50,16 @@@ extern HMENU current_popup_menu
  
  #include "menu.h"
  
 -/* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
 +/* Return non-zero if menus can handle radio and toggle buttons.  */
 +static bool
 +have_boxes (void)
 +{
  #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
 -#define HAVE_BOXES 1
 +  if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)))
 +    return 1;
  #endif
 +  return 0;
 +}
  
  Lisp_Object menu_items;
  
@@@ -289,14 -283,13 +289,14 @@@ single_keymap_panes (Lisp_Object keymap
  
    push_menu_pane (pane_name, prefix);
  
 -#ifndef HAVE_BOXES
 -  /* Remember index for first item in this pane so we can go back and
 -     add a prefix when (if) we see the first button.  After that, notbuttons
 -     is set to 0, to mark that we have seen a button and all non button
 -     items need a prefix.  */
 -  skp.notbuttons = menu_items_used;
 -#endif
 +  if (!have_boxes ())
 +    {
 +      /* Remember index for first item in this pane so we can go back
 +       and add a prefix when (if) we see the first button.  After
 +       that, notbuttons is set to 0, to mark that we have seen a
 +       button and all non button items need a prefix.  */
 +      skp.notbuttons = menu_items_used;
 +    }
  
    GCPRO1 (skp.pending_maps);
    map_keymap_canonical (keymap, single_menu_item, Qnil, &skp);
@@@ -352,72 -345,77 +352,72 @@@ single_menu_item (Lisp_Object key, Lisp
        return;
      }
  
 -#if defined (HAVE_X_WINDOWS) || defined (MSDOS)
 -#ifndef HAVE_BOXES
    /* Simulate radio buttons and toggle boxes by putting a prefix in
       front of them.  */
 -  {
 -    Lisp_Object prefix = Qnil;
 -    Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
 -    if (!NILP (type))
 -      {
 -      Lisp_Object selected
 -        = AREF (item_properties, ITEM_PROPERTY_SELECTED);
 +  if (!have_boxes ())
 +    {
 +      Lisp_Object prefix = Qnil;
 +      Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
 +      if (!NILP (type))
 +      {
 +        Lisp_Object selected
 +          = AREF (item_properties, ITEM_PROPERTY_SELECTED);
  
 -      if (skp->notbuttons)
 -        /* The first button. Line up previous items in this menu.  */
 -        {
 -          int idx = skp->notbuttons; /* Index for first item this menu.  */
 -          int submenu = 0;
 -          Lisp_Object tem;
 -          while (idx < menu_items_used)
 -            {
 -              tem
 -                = AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
 -              if (NILP (tem))
 -                {
 -                  idx++;
 -                  submenu++;          /* Skip sub menu.  */
 -                }
 -              else if (EQ (tem, Qlambda))
 -                {
 -                  idx++;
 -                  submenu--;          /* End sub menu.  */
 -                }
 -              else if (EQ (tem, Qt))
 -                idx += 3;             /* Skip new pane marker. */
 -              else if (EQ (tem, Qquote))
 -                idx++;                /* Skip a left, right divider. */
 -              else
 -                {
 -                  if (!submenu && SREF (tem, 0) != '\0'
 -                      && SREF (tem, 0) != '-')
 -                    ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
 -                           concat2 (build_string ("    "), tem));
 -                  idx += MENU_ITEMS_ITEM_LENGTH;
 -                }
 -            }
 -          skp->notbuttons = 0;
 -        }
 +        if (skp->notbuttons)
 +          /* The first button. Line up previous items in this menu.  */
 +          {
 +            int idx = skp->notbuttons; /* Index for first item this menu.  */
 +            int submenu = 0;
 +            Lisp_Object tem;
 +            while (idx < menu_items_used)
 +              {
 +                tem
 +                  = AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
 +                if (NILP (tem))
 +                  {
 +                    idx++;
 +                    submenu++;                /* Skip sub menu.  */
 +                  }
 +                else if (EQ (tem, Qlambda))
 +                  {
 +                    idx++;
 +                    submenu--;                /* End sub menu.  */
 +                  }
 +                else if (EQ (tem, Qt))
 +                  idx += 3;           /* Skip new pane marker. */
 +                else if (EQ (tem, Qquote))
 +                  idx++;              /* Skip a left, right divider. */
 +                else
 +                  {
 +                    if (!submenu && SREF (tem, 0) != '\0'
 +                        && SREF (tem, 0) != '-')
 +                      ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
 +                            concat2 (build_string ("    "), tem));
 +                    idx += MENU_ITEMS_ITEM_LENGTH;
 +                  }
 +              }
 +            skp->notbuttons = 0;
 +          }
  
 -      /* Calculate prefix, if any, for this item.  */
 -      if (EQ (type, QCtoggle))
 -        prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
 -      else if (EQ (type, QCradio))
 -        prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
 -      }
 -    /* Not a button. If we have earlier buttons, then we need a prefix.  */
 -    else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
 -           && SREF (item_string, 0) != '-')
 -      prefix = build_string ("    ");
 +        /* Calculate prefix, if any, for this item.  */
 +        if (EQ (type, QCtoggle))
 +          prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
 +        else if (EQ (type, QCradio))
 +          prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
 +      }
 +      /* Not a button. If we have earlier buttons, then we need a prefix.  */
 +      else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
 +             && SREF (item_string, 0) != '-')
 +      prefix = build_string ("    ");
  
 -    if (!NILP (prefix))
 -      item_string = concat2 (prefix, item_string);
 +      if (!NILP (prefix))
 +      item_string = concat2 (prefix, item_string);
    }
 -#endif /* not HAVE_BOXES */
  
 -#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 -  if (!NILP (map))
 +  if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
 +      && !NILP (map))
      /* Indicate visually that this is a submenu.  */
      item_string = concat2 (item_string, build_string (" >"));
 -#endif
 -
 -#endif /* HAVE_X_WINDOWS || MSDOS */
  
    push_menu_item (item_string, enabled, key,
                  AREF (item_properties, ITEM_PROPERTY_DEF),
  
  #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
    /* Display a submenu using the toolkit.  */
 -  if (! (NILP (map) || NILP (enabled)))
 +  if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame))
 +      && ! (NILP (map) || NILP (enabled)))
      {
        push_submenu_start ();
        single_keymap_panes (map, Qnil, key, skp->maxdepth - 1);
@@@ -458,16 -455,6 +458,16 @@@ keymap_panes (Lisp_Object *keymaps, ptr
    finish_menu_items ();
  }
  
 +/* Encode a menu string as appropriate for menu-updating-frame's type.  */
 +static Lisp_Object
 +encode_menu_string (Lisp_Object str)
 +{
 +  /* TTY menu strings are encoded by write_glyphs, when they are
 +     delivered to the glass, so no need to encode them here.  */
 +  if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame)))
 +    return str;
 +  return ENCODE_MENU_STRING (str);
 +}
  
  /* Push the items in a single pane defined by the alist PANE.  */
  static void
@@@ -479,13 -466,13 +479,13 @@@ list_of_items (Lisp_Object pane
      {
        item = XCAR (tail);
        if (STRINGP (item))
 -      push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
 +      push_menu_item (encode_menu_string (item), Qnil, Qnil, Qt,
                        Qnil, Qnil, Qnil, Qnil);
        else if (CONSP (item))
        {
          item1 = XCAR (item);
          CHECK_STRING (item1);
 -        push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
 +        push_menu_item (encode_menu_string (item1), Qt, XCDR (item),
                          Qt, Qnil, Qnil, Qnil, Qnil);
        }
        else
@@@ -510,7 -497,7 +510,7 @@@ list_of_panes (Lisp_Object menu
        elt = XCAR (tail);
        pane_name = Fcar (elt);
        CHECK_STRING (pane_name);
 -      push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
 +      push_menu_pane (encode_menu_string (pane_name), Qnil);
        pane_data = Fcdr (elt);
        CHECK_CONS (pane_data);
        list_of_items (pane_data);
@@@ -627,7 -614,6 +627,7 @@@ digest_single_submenu (int start, int e
    int submenu_depth = 0;
    widget_value **submenu_stack;
    bool panes_seen = 0;
 +  struct frame *f = XFRAME (Vmenu_updating_frame);
  
    submenu_stack = alloca (menu_items_used * sizeof *submenu_stack);
    wv = xmalloc_widget_value ();
  
          pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
  
 -#ifdef HAVE_NTGUI
 -        if (STRINGP (pane_name))
 +        /* TTY menus display menu items via tty_write_glyphs, which
 +           will encode the strings as appropriate.  */
 +        if (!FRAME_TERMCAP_P (f))
            {
 -            if (unicode_append_menu)
 -              /* Encode as UTF-8 for now.  */
 -              pane_name = ENCODE_UTF_8 (pane_name);
 -            else if (STRING_MULTIBYTE (pane_name))
 -              pane_name = ENCODE_SYSTEM (pane_name);
 +#ifdef HAVE_NTGUI
 +            if (STRINGP (pane_name))
 +              {
 +                if (unicode_append_menu)
 +                  /* Encode as UTF-8 for now.  */
 +                  pane_name = ENCODE_UTF_8 (pane_name);
 +                else if (STRING_MULTIBYTE (pane_name))
 +                  pane_name = ENCODE_SYSTEM (pane_name);
  
 -            ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 -          }
 +                ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 +              }
  #elif defined (USE_LUCID) && defined (HAVE_XFT)
 -        if (STRINGP (pane_name))
 -            {
 -              pane_name = ENCODE_UTF_8 (pane_name);
 -            ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 -            }
 +            if (STRINGP (pane_name))
 +              {
 +                pane_name = ENCODE_UTF_8 (pane_name);
 +                ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 +              }
  #elif !defined (HAVE_MULTILINGUAL_MENU)
 -        if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
 -          {
 -            pane_name = ENCODE_MENU_STRING (pane_name);
 -            ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 -          }
 +            if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
 +              {
 +                pane_name = ENCODE_MENU_STRING (pane_name);
 +                ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
 +              }
  #endif
 +          }
  
          pane_string = (NILP (pane_name)
                         ? "" : SSDATA (pane_name));
          selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
          help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
  
 -#ifdef HAVE_NTGUI
 -        if (STRINGP (item_name))
 +        /* TTY menu items and their descriptions will be encoded by
 +           tty_write_glyphs.  */
 +        if (!FRAME_TERMCAP_P (f))
            {
 -            if (unicode_append_menu)
 -              item_name = ENCODE_UTF_8 (item_name);
 -            else if (STRING_MULTIBYTE (item_name))
 -              item_name = ENCODE_SYSTEM (item_name);
 +#ifdef HAVE_NTGUI
 +            if (STRINGP (item_name))
 +              {
 +                if (unicode_append_menu)
 +                  item_name = ENCODE_UTF_8 (item_name);
 +                else if (STRING_MULTIBYTE (item_name))
 +                  item_name = ENCODE_SYSTEM (item_name);
  
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 -          }
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 +              }
  
 -        if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
 -          {
 -            descrip = ENCODE_SYSTEM (descrip);
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 -          }
 +            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
 +              {
 +                descrip = ENCODE_SYSTEM (descrip);
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 +              }
  #elif USE_LUCID
 -        if (STRINGP (item_name))
 -          {
 -              item_name = ENCODE_UTF_8 (item_name);
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 -          }
 +            if (STRINGP (item_name))
 +              {
 +                item_name = ENCODE_UTF_8 (item_name);
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 +              }
  
 -        if (STRINGP (descrip))
 -          {
 -            descrip = ENCODE_UTF_8 (descrip);
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 -          }
 +            if (STRINGP (descrip))
 +              {
 +                descrip = ENCODE_UTF_8 (descrip);
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 +              }
  #elif !defined (HAVE_MULTILINGUAL_MENU)
 -          if (STRING_MULTIBYTE (item_name))
 -          {
 -            item_name = ENCODE_MENU_STRING (item_name);
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 -          }
 +            if (STRING_MULTIBYTE (item_name))
 +              {
 +                item_name = ENCODE_MENU_STRING (item_name);
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
 +              }
  
 -          if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
 -          {
 -            descrip = ENCODE_MENU_STRING (descrip);
 -            ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 -          }
 +            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
 +              {
 +                descrip = ENCODE_MENU_STRING (descrip);
 +                ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
 +              }
  #endif
 +          }
  
          wv = xmalloc_widget_value ();
          if (prev_wv)
@@@ -1101,6 -1077,8 +1101,6 @@@ no quit occurs and `x-popup-menu' retur
    {
      bool get_current_pos_p = 0;
  
 -    check_window_system (SELECTED_FRAME ());
 -
      /* Decode the first argument: find the window and the coordinates.  */
      if (EQ (position, Qt)
        || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
      xpos += XINT (x);
      ypos += XINT (y);
  
 -    /* FIXME: Find a more general check!  */
 -    if (!(FRAME_X_P (f) || FRAME_MSDOS_P (f)
 -        || FRAME_W32_P (f) || FRAME_NS_P (f)))
 -      error ("Can not put GUI menu on this terminal");
 -
      XSETFRAME (Vmenu_updating_frame, f);
    }
  #endif /* HAVE_MENUS */
  #ifdef HAVE_MENUS
  #ifdef HAVE_WINDOW_SYSTEM
    /* Hide a previous tip, if any.  */
 -  Fx_hide_tip ();
 +  if (!FRAME_TERMCAP_P (f))
 +    Fx_hide_tip ();
  #endif
  
  #ifdef HAVE_NTGUI     /* FIXME: Is it really w32-specific?  --Stef  */
       can occur if you press ESC or click outside a menu without selecting
       a menu item.
    */
 -  if (current_popup_menu)
 +  if (current_popup_menu && FRAME_W32_P (f))
      {
        discard_menu_items ();
-       FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+       FRAME_DISPLAY_INFO (f)->grabbed = 0;
        UNGCPRO;
        return Qnil;
      }
  #endif
  
    /* Display them in a menu.  */
 -  block_input ();
  
    /* FIXME: Use a terminal hook!  */
  #if defined HAVE_NTGUI
 -  selection = w32_menu_show (f, xpos, ypos, for_click,
 -                           keymaps, title, &error_name);
 -#elif defined HAVE_NS
 -  selection = ns_menu_show (f, xpos, ypos, for_click,
 -                          keymaps, title, &error_name);
 -#else /* MSDOS and X11 */
 +  if (FRAME_W32_P (f))
 +    selection = w32_menu_show (f, xpos, ypos, for_click,
 +                             keymaps, title, &error_name);
 +  else
 +#endif
 +#if defined HAVE_NS
 +  if (FRAME_NS_P (f))
 +    selection = ns_menu_show (f, xpos, ypos, for_click,
 +                            keymaps, title, &error_name);
 +  else
 +#endif
 +#if (defined (HAVE_X_WINDOWS) || defined (MSDOS))
    /* Assume last_event_timestamp is the timestamp of the button event.
       Is this assumption ever violated?  We can't use the timestamp
       stored within POSITION because there the top bits from the actual
       timestamp may be truncated away (Bug#4930).  */
 -  selection = xmenu_show (f, xpos, ypos, for_click,
 -                        keymaps, title, &error_name,
 -                        last_event_timestamp);
 +  if (FRAME_X_P (f) || FRAME_MSDOS_P (f))
 +    selection = xmenu_show (f, xpos, ypos, for_click,
 +                          keymaps, title, &error_name,
 +                          last_event_timestamp);
 +  else
  #endif
 -
 -  unblock_input ();
 +  if (FRAME_TERMCAP_P (f))
 +    selection = tty_menu_show (f, xpos, ypos, for_click,
 +                             keymaps, title, &error_name);
  
  #ifdef HAVE_NS
    unbind_to (specpdl_count, Qnil);
  #endif
  
  #ifdef HAVE_NTGUI     /* FIXME: Is it really w32-specific?  --Stef  */
 -  FRAME_DISPLAY_INFO (f)->grabbed = 0;
 +  if (FRAME_W32_P (f))
-     FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
++    FRAME_DISPLAY_INFO (f)->grabbed = 0;
  #endif
  
  #endif /* HAVE_MENUS */
diff --combined src/msdos.c
@@@ -408,7 -408,7 +408,7 @@@ static int term_setup_done
  
  static unsigned short outside_cursor;
  
- /* Similar to the_only_frame.  */
+ /* The only display since MS-DOS does not support multiple ones.  */
  struct tty_display_info the_only_display_info;
  
  /* Support for DOS/V (allows Japanese characters to be displayed on
@@@ -1222,7 -1222,7 +1222,7 @@@ IT_cmgoto (struct frame *f
  static void
  IT_update_begin (struct frame *f)
  {
-   struct tty_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
+   struct tty_display_info *display_info = FRAME_DISPLAY_INFO (f);
    Mouse_HLInfo *hlinfo = &display_info->mouse_highlight;
    struct frame *mouse_face_frame = hlinfo->mouse_face_mouse_frame;
  
  static void
  IT_update_end (struct frame *f)
  {
-   struct tty_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+   struct tty_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  
    if (dpyinfo->termscript)
      fprintf (dpyinfo->termscript, "\n<UPDATE_END\n");
@@@ -1379,6 -1379,13 +1379,6 @@@ IT_delete_glyphs (struct frame *f, int 
    emacs_abort ();
  }
  
 -/* set-window-configuration on window.c needs this.  */
 -void
 -x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 -{
 -  set_menu_bar_lines (f, value, oldval);
 -}
 -
  /* This was copied from xfaces.c  */
  
  extern Lisp_Object Qbackground_color;
@@@ -2387,7 -2394,7 +2387,7 @@@ Each input key receives two values in t
  and then the scan code.  */)
    (void)
  {
-   Lisp_Object val, *keys = XVECTOR (recent_doskeys)->contents;
+   Lisp_Object val, *keys = XVECTOR (recent_doskeys)->u.contents;
  
    if (total_doskeys < NUM_RECENT_DOSKEYS)
      return Fvector (total_doskeys, keys);
diff --combined src/nsmenu.m
@@@ -833,8 -833,6 +833,8 @@@ ns_menu_show (struct frame *f, int x, i
    ptrdiff_t specpdl_count = SPECPDL_INDEX ();
    widget_value *wv, *first_wv = 0;
  
 +  block_input ();
 +
    p.x = x; p.y = y;
  
    /* now parse stage 2 as in ns_update_menubar */
    popup_activated_flag = 0;
    [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
  
 +  unblock_input ();
    return tem;
  }
  
@@@ -1242,7 -1239,7 +1242,7 @@@ update_frame_tool_bar (struct frame *f
  {
    /* 1) come up w/identifier */
    NSString *identifier
-       = [NSString stringWithFormat: @"%u", [img hash]];
+     = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
    [activeIdentifiers addObject: identifier];
  
    /* 2) create / reuse item */
diff --combined src/term.c
@@@ -56,8 -56,6 +56,8 @@@ static int been_here = -1
  #include "xterm.h"
  #endif
  
 +#include "menu.h"
 +
  /* The name of the default console device.  */
  #ifdef WINDOWSNT
  #define DEV_TTY  "CONOUT$"
@@@ -304,11 -302,7 +304,11 @@@ tty_hide_cursor (struct tty_display_inf
    if (tty->cursor_hidden == 0)
      {
        tty->cursor_hidden = 1;
 +#ifdef WINDOWSNT
 +      w32con_hide_cursor ();
 +#else
        OUTPUT_IF (tty, tty->TS_cursor_invisible);
 +#endif
      }
  }
  
@@@ -321,13 -315,9 +321,13 @@@ tty_show_cursor (struct tty_display_inf
    if (tty->cursor_hidden)
      {
        tty->cursor_hidden = 0;
 +#ifdef WINDOWSNT
 +      w32con_show_cursor ();
 +#else
        OUTPUT_IF (tty, tty->TS_cursor_normal);
        if (visible_cursor)
          OUTPUT_IF (tty, tty->TS_cursor_visible);
 +#endif
      }
  }
  
@@@ -1810,27 -1800,10 +1810,10 @@@ append_glyphless_glyph (struct it *it, 
  static void
  produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
  {
-   int face_id;
-   int len;
+   int len, face_id = merge_glyphless_glyph_face (it);
    char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
    char const *str = "    ";
  
-   /* Get a face ID for the glyph by utilizing a cache (the same way as
-      done for `escape-glyph' in get_next_display_element).  */
-   if (it->f == last_glyphless_glyph_frame
-       && it->face_id == last_glyphless_glyph_face_id)
-     {
-       face_id = last_glyphless_glyph_merged_face_id;
-     }
-   else
-     {
-       /* Merge the `glyphless-char' face into the current face.  */
-       face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
-       last_glyphless_glyph_frame = it->f;
-       last_glyphless_glyph_face_id = it->face_id;
-       last_glyphless_glyph_merged_face_id = face_id;
-     }
    if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
      {
        /* As there's no way to produce a thin space, we produce a space
@@@ -2782,1123 -2755,6 +2765,1123 @@@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_sto
  #endif /* HAVE_GPM */
  
  \f
 +/***********************************************************************
 +                             Menus
 + ***********************************************************************/
 +
 +#if defined (HAVE_MENUS) && !defined (MSDOS)
 +
 +/* TTY menu implementation and main ideas are borrowed from msdos.c.
 +
 +   However, unlike on MSDOS, where the menu text is drawn directly to
 +   the display video memory, on a TTY we use display_string (see
 +   display_tty_menu_item in xdisp.c) to put the glyphs produced from
 +   the menu items directly into the frame's 'desired_matrix' glyph
 +   matrix, and then call update_frame_with_menu to deliver the results
 +   to the glass.  The previous contents of the screen, in the form of
 +   the current_matrix, is stashed away, and used to restore screen
 +   contents when the menu selection changes or when the final
 +   selection is made and the menu should be popped down.
 +
 +   The idea of this implementation was suggested by Gerd Moellmann.  */
 +
 +#define TTYM_FAILURE -1
 +#define TTYM_SUCCESS 1
 +#define TTYM_NO_SELECT 2
 +#define TTYM_IA_SELECT 3
 +
 +/* These hold text of the current and the previous menu help messages.  */
 +static const char *menu_help_message, *prev_menu_help_message;
 +/* Pane number and item number of the menu item which generated the
 +   last menu help message.  */
 +static int menu_help_paneno, menu_help_itemno;
 +
 +static int menu_x, menu_y;
 +
 +static Lisp_Object Qtty_menu_navigation_map, Qtty_menu_exit;
 +static Lisp_Object Qtty_menu_prev_item, Qtty_menu_next_item;
 +static Lisp_Object Qtty_menu_next_menu, Qtty_menu_prev_menu;
 +static Lisp_Object Qtty_menu_select, Qtty_menu_ignore;
 +static Lisp_Object Qtty_menu_mouse_movement;
 +
 +typedef struct tty_menu_struct
 +{
 +  int count;
 +  char **text;
 +  struct tty_menu_struct **submenu;
 +  int *panenumber; /* Also used as enable.  */
 +  int allocated;
 +  int panecount;
 +  int width;
 +  const char **help_text;
 +} tty_menu;
 +
 +/* Create a brand new menu structure.  */
 +
 +static tty_menu *
 +tty_menu_create (void)
 +{
 +  tty_menu *menu;
 +
 +  menu = (tty_menu *) xmalloc (sizeof (tty_menu));
 +  menu->allocated = menu->count = menu->panecount = menu->width = 0;
 +  return menu;
 +}
 +
 +/* Allocate some (more) memory for MENU ensuring that there is room for one
 +   for item.  */
 +
 +static void
 +tty_menu_make_room (tty_menu *menu)
 +{
 +  if (menu->allocated == 0)
 +    {
 +      int count = menu->allocated = 10;
 +      menu->text = (char **) xmalloc (count * sizeof (char *));
 +      menu->submenu = (tty_menu **) xmalloc (count * sizeof (tty_menu *));
 +      menu->panenumber = (int *) xmalloc (count * sizeof (int));
 +      menu->help_text = (const char **) xmalloc (count * sizeof (char *));
 +    }
 +  else if (menu->allocated == menu->count)
 +    {
 +      int count = menu->allocated = menu->allocated + 10;
 +      menu->text
 +      = (char **) xrealloc (menu->text, count * sizeof (char *));
 +      menu->submenu
 +      = (tty_menu **) xrealloc (menu->submenu, count * sizeof (tty_menu *));
 +      menu->panenumber
 +      = (int *) xrealloc (menu->panenumber, count * sizeof (int));
 +      menu->help_text
 +      = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
 +    }
 +}
 +
 +/* Search the given menu structure for a given pane number.  */
 +
 +static tty_menu *
 +tty_menu_search_pane (tty_menu *menu, int pane)
 +{
 +  int i;
 +  tty_menu *try;
 +
 +  for (i = 0; i < menu->count; i++)
 +    if (menu->submenu[i])
 +      {
 +      if (pane == menu->panenumber[i])
 +        return menu->submenu[i];
 +      if ((try = tty_menu_search_pane (menu->submenu[i], pane)))
 +        return try;
 +      }
 +  return (tty_menu *) 0;
 +}
 +
 +/* Determine how much screen space a given menu needs.  */
 +
 +static void
 +tty_menu_calc_size (tty_menu *menu, int *width, int *height)
 +{
 +  int i, h2, w2, maxsubwidth, maxheight;
 +
 +  maxsubwidth = menu->width;
 +  maxheight = menu->count;
 +  for (i = 0; i < menu->count; i++)
 +    {
 +      if (menu->submenu[i])
 +      {
 +        tty_menu_calc_size (menu->submenu[i], &w2, &h2);
 +        if (w2 > maxsubwidth) maxsubwidth = w2;
 +        if (i + h2 > maxheight) maxheight = i + h2;
 +      }
 +    }
 +  *width = maxsubwidth;
 +  *height = maxheight;
 +}
 +
 +static void
 +mouse_get_xy (int *x, int *y)
 +{
 +  struct frame *sf = SELECTED_FRAME ();
 +  Lisp_Object lmx, lmy, lisp_dummy;
 +  enum scroll_bar_part part_dummy;
 +  Time time_dummy;
 +
 +  if (FRAME_TERMINAL (sf)->mouse_position_hook)
 +    (*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1,
 +                                                 &lisp_dummy, &part_dummy,
 +                                               &lmx, &lmy,
 +                                               &time_dummy);
 +  if (!NILP (lmx))
 +    {
 +      *x = XINT (lmx);
 +      *y = XINT (lmy);
 +    }
 +}
 +
 +/* Display MENU at (X,Y) using FACES.  */
 +
 +static void
 +tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
 +                int mx, int my, int disp_help)
 +{
 +  int i, face, width, enabled, mousehere, row, col;
 +  struct frame *sf = SELECTED_FRAME ();
 +  struct tty_display_info *tty = FRAME_TTY (sf);
 +
 +  menu_help_message = NULL;
 +
 +  width = menu->width;
 +  col = cursorX (tty);
 +  row = cursorY (tty);
 +#if 0
 +  IT_update_begin (sf);               /* FIXME: do we need an update_begin_hook? */
 +#endif
 +  for (i = 0; i < menu->count; i++)
 +    {
 +      int max_width = width + 2; /* +2 for padding blanks on each side */
 +
 +      cursor_to (sf, y + i, x);
 +      if (menu->submenu[i])
 +      max_width += 2; /* for displaying " >" after the item */
 +      enabled
 +      = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
 +      mousehere = (y + i == my && x <= mx && mx < x + max_width);
 +      face = faces[enabled + mousehere * 2];
 +      /* Display the menu help string for the i-th menu item even if
 +       the menu item is currently disabled.  That's what the GUI
 +       code does.  */
 +      if (disp_help && enabled + mousehere * 2 >= 2)
 +      {
 +        menu_help_message = menu->help_text[i];
 +        menu_help_paneno = pn - 1;
 +        menu_help_itemno = i;
 +      }
 +      display_tty_menu_item (menu->text[i], max_width, face, x, y + i,
 +                           menu->submenu[i] != NULL);
 +    }
 +  update_frame_with_menu (sf);
 +  cursor_to (sf, row, col);
 +}
 +
 +/* --------------------------- X Menu emulation ---------------------- */
 +
 +/* Report availability of menus.  */
 +
 +int
 +have_menus_p (void) {  return 1; }
 +
 +/* Create a new pane and place it on the outer-most level.  */
 +
 +static int
 +tty_menu_add_pane (tty_menu *menu, const char *txt)
 +{
 +  int len;
 +  const char *p;
 +
 +  tty_menu_make_room (menu);
 +  menu->submenu[menu->count] = tty_menu_create ();
 +  menu->text[menu->count] = (char *)txt;
 +  menu->panenumber[menu->count] = ++menu->panecount;
 +  menu->help_text[menu->count] = NULL;
 +  menu->count++;
 +
 +  /* Update the menu width, if necessary.  */
 +  for (len = 0, p = txt; *p; )
 +    {
 +      int ch_len;
 +      int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
 +
 +      len += CHAR_WIDTH (ch);
 +      p += ch_len;
 +    }
 +
 +  if (len > menu->width)
 +    menu->width = len;
 +
 +  return menu->panecount;
 +}
 +
 +/* Create a new item in a menu pane.  */
 +
 +int
 +tty_menu_add_selection (tty_menu *menu, int pane,
 +                      char *txt, int enable, char const *help_text)
 +{
 +  int len;
 +  char *p;
 +
 +  if (pane)
 +    if (!(menu = tty_menu_search_pane (menu, pane)))
 +      return TTYM_FAILURE;
 +  tty_menu_make_room (menu);
 +  menu->submenu[menu->count] = (tty_menu *) 0;
 +  menu->text[menu->count] = txt;
 +  menu->panenumber[menu->count] = enable;
 +  menu->help_text[menu->count] = help_text;
 +  menu->count++;
 +
 +  /* Update the menu width, if necessary.  */
 +  for (len = 0, p = txt; *p; )
 +    {
 +      int ch_len;
 +      int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
 +
 +      len += CHAR_WIDTH (ch);
 +      p += ch_len;
 +    }
 +
 +  if (len > menu->width)
 +    menu->width = len;
 +
 +  return TTYM_SUCCESS;
 +}
 +
 +/* Decide where the menu would be placed if requested at (X,Y).  */
 +
 +void
 +tty_menu_locate (tty_menu *menu, int x, int y,
 +               int *ulx, int *uly, int *width, int *height)
 +{
 +  tty_menu_calc_size (menu, width, height);
 +  *ulx = x + 1;
 +  *uly = y;
 +  *width += 2;
 +}
 +
 +struct tty_menu_state
 +{
 +  struct glyph_matrix *screen_behind;
 +  tty_menu *menu;
 +  int pane;
 +  int x, y;
 +};
 +
 +/* Save away the contents of frame F's current frame matrix, and
 +   enable all its rows.  Value is a glyph matrix holding the contents
 +   of F's current frame matrix with all its glyph rows enabled.  */
 +
 +struct glyph_matrix *
 +save_and_enable_current_matrix (struct frame *f)
 +{
 +  int i;
 +  struct glyph_matrix *saved = xzalloc (sizeof *saved);
 +  saved->nrows = f->current_matrix->nrows;
 +  saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
 +
 +  for (i = 0; i < saved->nrows; ++i)
 +    {
 +      struct glyph_row *from = f->current_matrix->rows + i;
 +      struct glyph_row *to = saved->rows + i;
 +      ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
 +
 +      to->glyphs[TEXT_AREA] = xmalloc (nbytes);
 +      memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
 +      to->used[TEXT_AREA] = from->used[TEXT_AREA];
 +      /* Make sure every row is enabled, or else update_frame will not
 +       redraw them.  (Rows that are identical to what is already on
 +       screen will not be redrawn anyway.)  */
 +      to->enabled_p = 1;
 +      to->hash = from->hash;
 +      if (from->used[LEFT_MARGIN_AREA])
 +      {
 +        nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
 +        to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
 +        memcpy (to->glyphs[LEFT_MARGIN_AREA],
 +                from->glyphs[LEFT_MARGIN_AREA], nbytes);
 +        to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
 +      }
 +      if (from->used[RIGHT_MARGIN_AREA])
 +      {
 +        nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
 +        to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
 +        memcpy (to->glyphs[RIGHT_MARGIN_AREA],
 +                from->glyphs[RIGHT_MARGIN_AREA], nbytes);
 +        to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
 +      }
 +    }
 +
 +  return saved;
 +}
 +
 +/* Restore the contents of frame F's desired frame matrix from SAVED,
 +   and free memory associated with SAVED.  */
 +
 +static void
 +restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
 +{
 +  int i;
 +
 +  for (i = 0; i < saved->nrows; ++i)
 +    {
 +      struct glyph_row *from = saved->rows + i;
 +      struct glyph_row *to = f->desired_matrix->rows + i;
 +      ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
 +
 +      eassert (to->glyphs[TEXT_AREA] != from->glyphs[TEXT_AREA]);
 +      memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
 +      to->used[TEXT_AREA] = from->used[TEXT_AREA];
 +      to->enabled_p = from->enabled_p;
 +      to->hash = from->hash;
 +      nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
 +      if (nbytes)
 +      {
 +        eassert (to->glyphs[LEFT_MARGIN_AREA] != from->glyphs[LEFT_MARGIN_AREA]);
 +        memcpy (to->glyphs[LEFT_MARGIN_AREA],
 +                from->glyphs[LEFT_MARGIN_AREA], nbytes);
 +        to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
 +      }
 +      else
 +      to->used[LEFT_MARGIN_AREA] = 0;
 +      nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
 +      if (nbytes)
 +      {
 +        eassert (to->glyphs[RIGHT_MARGIN_AREA] != from->glyphs[RIGHT_MARGIN_AREA]);
 +        memcpy (to->glyphs[RIGHT_MARGIN_AREA],
 +                from->glyphs[RIGHT_MARGIN_AREA], nbytes);
 +        to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
 +      }
 +      else
 +      to->used[RIGHT_MARGIN_AREA] = 0;
 +    }
 +}
 +
 +static void
 +free_saved_screen (struct glyph_matrix *saved)
 +{
 +  int i;
 +
 +  if (!saved)
 +    return;   /* already freed */
 +
 +  for (i = 0; i < saved->nrows; ++i)
 +    {
 +      struct glyph_row *from = saved->rows + i;
 +
 +      xfree (from->glyphs[TEXT_AREA]);
 +      if (from->used[LEFT_MARGIN_AREA])
 +      xfree (from->glyphs[LEFT_MARGIN_AREA]);
 +      if (from->used[RIGHT_MARGIN_AREA])
 +      xfree (from->glyphs[RIGHT_MARGIN_AREA]);
 +    }
 +
 +  xfree (saved->rows);
 +  xfree (saved);
 +}
 +
 +/* Update the display of frame F from its saved contents.  */
 +static void
 +screen_update (struct frame *f, struct glyph_matrix *mtx)
 +{
 +  restore_desired_matrix (f, mtx);
 +  update_frame_with_menu (f);
 +}
 +
 +/* Read user input and return X and Y coordinates where that input
 +   puts us.  We only consider mouse movement and click events and
 +   keyboard movement commands; the rest are ignored.
 +
 +   Value is -1 if C-g was pressed, 1 if an item was selected, zero
 +   otherwise.  */
 +static int
 +read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
 +               bool *first_time)
 +{
 +  if (*first_time)
 +    {
 +      *first_time = false;
 +      /* FIXME: Following 2 or 3 lines are temporary!  */
 +      menu_x = *x;
 +      menu_y = *y;
 +      sf->mouse_moved = 1;
 +      return 0;
 +    }
 +
 +  while (1)
 +    {
 +#if 1
 +      extern Lisp_Object read_menu_command (void);
 +      Lisp_Object cmd;
 +      int usable_input = 1;
 +      int st = 0;
 +      struct tty_display_info *tty = FRAME_TTY (sf);
 +      Lisp_Object saved_mouse_tracking = do_mouse_tracking;
 +
 +      /* Signal the keyboard reading routines we are displaying a menu
 +       on this terminal.  */
 +      tty->showing_menu = 1;
 +      /* We want mouse movements be reported by read_menu_command.  */
 +      do_mouse_tracking = Qt;
 +      do {
 +      cmd = read_menu_command ();
 +      } while (NILP (cmd));
 +      tty->showing_menu = 0;
 +      do_mouse_tracking = saved_mouse_tracking;
 +
 +      if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
 +      return -1;
 +      if (EQ (cmd, Qtty_menu_mouse_movement))
 +      {
 +        int mx, my;
 +
 +        mouse_get_xy (&mx, &my);
 +        *x = mx;
 +        *y = my;
 +      }
 +      else if (EQ (cmd, Qtty_menu_next_menu))
 +      *x += 1;
 +      else if (EQ (cmd, Qtty_menu_prev_menu))
 +      *x -= 1;
 +      else if (EQ (cmd, Qtty_menu_next_item))
 +      {
 +        if (*y < max_y)
 +          *y += 1;
 +      }
 +      else if (EQ (cmd, Qtty_menu_prev_item))
 +      {
 +        if (*y > min_y)
 +          *y -= 1;
 +      }
 +      else if (EQ (cmd, Qtty_menu_select))
 +      st = 1;
 +      else if (!EQ (cmd, Qtty_menu_ignore))
 +      usable_input = 0;
 +      if (usable_input)
 +      sf->mouse_moved = 1;
 +#else
 +      int volatile dx = 0;
 +      int volatile dy = 0;
 +      int volatile st = 0;
 +
 +      *x += dx;
 +      *y += dy;
 +      if (dx != 0 || dy != 0)
 +      sf->mouse_moved = 1;
 +      Sleep (300);
 +#endif
 +      menu_x = *x;
 +      menu_y = *y;
 +      return st;
 +    }
 +  return 0;
 +}
 +
 +/* FIXME */
 +static bool mouse_visible;
 +static void
 +mouse_off (void)
 +{
 +  mouse_visible = false;
 +}
 +
 +static void
 +mouse_on (void)
 +{
 +  mouse_visible = true;
 +}
 +
 +static bool
 +mouse_pressed (int b, int *x, int *y)
 +{
 +  return false;
 +}
 +
 +static bool
 +mouse_button_depressed (int b, int *x, int *y)
 +{
 +  return false;
 +}
 +
 +static bool
 +mouse_released (int b, int *x, int *y)
 +{
 +  return true;
 +}
 +
 +/* Display menu, wait for user's response, and return that response.  */
 +int
 +tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
 +                 int x0, int y0, char **txt,
 +                 void (*help_callback)(char const *, int, int))
 +{
 +  struct tty_menu_state *state;
 +  int statecount, x, y, i, b, leave, result, onepane;
 +  int title_faces[4];         /* face to display the menu title */
 +  int faces[4], buffers_num_deleted = 0;
 +  struct frame *sf = SELECTED_FRAME ();
 +  struct tty_display_info *tty = FRAME_TTY (sf);
 +  bool first_time;
 +  Lisp_Object saved_echo_area_message, selectface;
 +
 +  /* Don't allow non-positive x0 and y0, lest the menu will wrap
 +     around the display.  */
 +  if (x0 <= 0)
 +    x0 = 1;
 +  if (y0 <= 0)
 +    y0 = 1;
 +
 +#if 0
 +  /* We will process all the mouse events directly.  */
 +  mouse_preempted++;
 +#endif
 +
 +  state = alloca (menu->panecount * sizeof (struct tty_menu_state));
 +  memset (state, 0, sizeof (*state));
 +  faces[0]
 +    = lookup_derived_face (sf, intern ("tty-menu-disabled-face"),
 +                         DEFAULT_FACE_ID, 1);
 +  faces[1]
 +    = lookup_derived_face (sf, intern ("tty-menu-enabled-face"),
 +                         DEFAULT_FACE_ID, 1);
 +  selectface = intern ("tty-menu-selected-face");
 +  faces[2] = lookup_derived_face (sf, selectface,
 +                                faces[0], 1);
 +  faces[3] = lookup_derived_face (sf, selectface,
 +                                faces[1], 1);
 +
 +  /* Make sure the menu title is always displayed with
 +     `tty-menu-selected-face', no matter where the mouse pointer is.  */
 +  for (i = 0; i < 4; i++)
 +    title_faces[i] = faces[3];
 +
 +  statecount = 1;
 +
 +  /* Don't let the title for the "Buffers" popup menu include a
 +     digit (which is ugly).
 +
 +     This is a terrible kludge, but I think the "Buffers" case is
 +     the only one where the title includes a number, so it doesn't
 +     seem to be necessary to make this more general.  */
 +  if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
 +    {
 +      menu->text[0][7] = '\0';
 +      buffers_num_deleted = 1;
 +    }
 +
 +#if 0
 +  /* We need to save the current echo area message, so that we could
 +     restore it below, before we exit.  See the commentary below,
 +     before the call to message_with_string.  */
 +  saved_echo_area_message = Fcurrent_message ();
 +#endif
 +  /* Force update of the current frame, so that the desired and the
 +     current matrices are identical.  */
 +  update_frame_with_menu (sf);
 +  state[0].menu = menu;
 +  mouse_off ();       /* FIXME */
 +  state[0].screen_behind = save_and_enable_current_matrix (sf);
 +
 +  /* Turn off the cursor.  Otherwise it shows through the menu
 +     panes, which is ugly.  */
 +  tty_hide_cursor (tty);
 +
 +  /* Display the menu title.  We subtract 1 from x0 and y0 because we
 +     want to interpret them as zero-based column and row coordinates,
 +     and also because we want the first item of the menu, not its
 +     title, to appear at x0,y0.  */
 +  tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0);
 +  if (buffers_num_deleted)
 +    menu->text[0][7] = ' ';
 +  if ((onepane = menu->count == 1 && menu->submenu[0]))
 +    {
 +      menu->width = menu->submenu[0]->width;
 +      state[0].menu = menu->submenu[0];
 +    }
 +  else
 +    {
 +      state[0].menu = menu;
 +    }
 +  state[0].x = x0 - 1;
 +  state[0].y = y0;
 +  state[0].pane = onepane;
 +
 +  x = state[0].x;
 +  y = state[0].y;
 +  first_time = true;
 +
 +  leave = 0;
 +  while (!leave)
 +    {
 +      int mouse_button_count = 3; /* FIXME */
 +      int input_status;
 +      int min_y = state[0].y, max_y = min_y + state[0].menu->count - 1;
 +
 +      if (!mouse_visible) mouse_on ();
 +      input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
 +      if (input_status)
 +      {
 +        if (input_status == -1)
 +          {
 +            /* Remove the last help-echo, so that it doesn't
 +               re-appear after "Quit".  */
 +            show_help_echo (Qnil, Qnil, Qnil, Qnil);
 +            result = TTYM_NO_SELECT;
 +          }
 +        leave = 1;
 +      }
 +      if (sf->mouse_moved && input_status != -1)
 +      {
 +        sf->mouse_moved = 0;
 +        result = TTYM_IA_SELECT;
 +        for (i = 0; i < statecount; i++)
 +          if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
 +            {
 +              int dy = y - state[i].y;
 +              if (0 <= dy && dy < state[i].menu->count)
 +                {
 +                  if (!state[i].menu->submenu[dy])
 +                    {
 +                      if (state[i].menu->panenumber[dy])
 +                        result = TTYM_SUCCESS;
 +                      else
 +                        result = TTYM_IA_SELECT;
 +                    }
 +                  *pane = state[i].pane - 1;
 +                  *selidx = dy;
 +                  /* We hit some part of a menu, so drop extra menus that
 +                     have been opened.  That does not include an open and
 +                     active submenu.  */
 +                  if (i != statecount - 2
 +                      || state[i].menu->submenu[dy] != state[i+1].menu)
 +                    while (i != statecount - 1)
 +                      {
 +                        statecount--;
 +                        mouse_off (); /* FIXME */
 +                        screen_update (sf, state[statecount].screen_behind);
 +                        state[statecount].screen_behind = NULL;
 +                      }
 +                  if (i == statecount - 1 && state[i].menu->submenu[dy])
 +                    {
 +                      tty_menu_display (state[i].menu,
 +                                        state[i].x,
 +                                        state[i].y,
 +                                        state[i].pane,
 +                                        faces, x, y, 1);
 +                      state[statecount].menu = state[i].menu->submenu[dy];
 +                      state[statecount].pane = state[i].menu->panenumber[dy];
 +                      mouse_off (); /* FIXME */
 +                      state[statecount].screen_behind
 +                        = save_and_enable_current_matrix (sf);
 +                      state[statecount].x
 +                        = state[i].x + state[i].menu->width + 2;
 +                      state[statecount].y = y;
 +                      statecount++;
 +                    }
 +                }
 +            }
 +        tty_menu_display (state[statecount - 1].menu,
 +                          state[statecount - 1].x,
 +                          state[statecount - 1].y,
 +                          state[statecount - 1].pane,
 +                          faces, x, y, 1);
 +      }
 +
 +      /* Display the help-echo message for the currently-selected menu
 +       item.  */
 +      if ((menu_help_message || prev_menu_help_message)
 +        && menu_help_message != prev_menu_help_message)
 +      {
 +        help_callback (menu_help_message,
 +                       menu_help_paneno, menu_help_itemno);
 +        tty_hide_cursor (tty);
 +        prev_menu_help_message = menu_help_message;
 +      }
 +#if 0
 +      /* We are busy-waiting for the mouse to move, so let's be nice
 +       to other Windows applications by releasing our time slice.  */
 +      Sleep (20);     /* FIXME */
 +
 +      for (b = 0; b < mouse_button_count && !leave; b++)
 +      {
 +        /* Only leave if user both pressed and released the mouse, and in
 +           that order.  This avoids popping down the menu pane unless
 +           the user is really done with it.  */
 +        if (mouse_pressed (b, &x, &y))
 +          {
 +            while (mouse_button_depressed (b, &x, &y))
 +              Sleep (20);     /* FIXME */
 +            leave = 1;
 +          }
 +        (void) mouse_released (b, &x, &y);
 +      }
 +#endif
 +    }
 +
 +  mouse_off ();                       /* FIXME */
 +  sf->mouse_moved = 0;
 +  /* FIXME: Since we set the fram's garbaged flag, do we need this
 +     call to screen_update?  */
 +  screen_update (sf, state[0].screen_behind);
 +#if 0
 +  /* We have a situation here.  ScreenUpdate has just restored the
 +     screen contents as it was before we started drawing this menu.
 +     That includes any echo area message that could have been
 +     displayed back then.  (In reality, that echo area message will
 +     almost always be the ``keystroke echo'' that echoes the sequence
 +     of menu items chosen by the user.)  However, if the menu had some
 +     help messages, then displaying those messages caused Emacs to
 +     forget about the original echo area message.  So when
 +     ScreenUpdate restored it, it created a discrepancy between the
 +     actual screen contents and what Emacs internal data structures
 +     know about it.
 +
 +     To avoid this conflict, we force Emacs to restore the original
 +     echo area message as we found it when we entered this function.
 +     The irony of this is that we then erase the restored message
 +     right away, so the only purpose of restoring it is so that
 +     erasing it works correctly...  */
 +  if (! NILP (saved_echo_area_message))
 +    message_with_string ("%s", saved_echo_area_message, 0);
 +  message (0);
 +#endif
 +  while (statecount--)
 +    free_saved_screen (state[statecount].screen_behind);
 +  tty_show_cursor (tty);      /* turn cursor back on */
 +
 +/* Clean up any mouse events that are waiting inside Emacs event queue.
 +     These events are likely to be generated before the menu was even
 +     displayed, probably because the user pressed and released the button
 +     (which invoked the menu) too quickly.  If we don't remove these events,
 +     Emacs will process them after we return and surprise the user.  */
 +  discard_mouse_events ();
 +#if 0
 +  mouse_clear_clicks ();
 +#endif
 +  if (!kbd_buffer_events_waiting ())
 +    clear_input_pending ();
 +#if 0
 +  /* Allow mouse events generation by dos_rawgetc.  */
 +  mouse_preempted--;
 +#endif
 +  SET_FRAME_GARBAGED (sf);
 +  return result;
 +}
 +
 +/* Dispose of a menu.  */
 +
 +void
 +tty_menu_destroy (tty_menu *menu)
 +{
 +  int i;
 +  if (menu->allocated)
 +    {
 +      for (i = 0; i < menu->count; i++)
 +      if (menu->submenu[i])
 +        tty_menu_destroy (menu->submenu[i]);
 +      xfree (menu->text);
 +      xfree (menu->submenu);
 +      xfree (menu->panenumber);
 +      xfree (menu->help_text);
 +    }
 +  xfree (menu);
 +  menu_help_message = prev_menu_help_message = NULL;
 +}
 +
 +static struct frame *tty_menu_help_frame;
 +
 +/* Show help HELP_STRING, or clear help if HELP_STRING is null.
 +
 +   PANE is the pane number, and ITEM is the menu item number in
 +   the menu (currently not used).
 +
 +   This cannot be done with generating a HELP_EVENT because
 +   XMenuActivate contains a loop that doesn't let Emacs process
 +   keyboard events.
 +
 +   FIXME: Do we need this in TTY menus?  */
 +
 +static void
 +tty_menu_help_callback (char const *help_string, int pane, int item)
 +{
 +  Lisp_Object *first_item;
 +  Lisp_Object pane_name;
 +  Lisp_Object menu_object;
 +
 +  first_item = XVECTOR (menu_items)->contents;
 +  if (EQ (first_item[0], Qt))
 +    pane_name = first_item[MENU_ITEMS_PANE_NAME];
 +  else if (EQ (first_item[0], Qquote))
 +    /* This shouldn't happen, see xmenu_show.  */
 +    pane_name = empty_unibyte_string;
 +  else
 +    pane_name = first_item[MENU_ITEMS_ITEM_NAME];
 +
 +  /* (menu-item MENU-NAME PANE-NUMBER)  */
 +  menu_object = list3 (Qmenu_item, pane_name, make_number (pane));
 +  show_help_echo (help_string ? build_string (help_string) : Qnil,
 +                Qnil, menu_object, make_number (item));
 +}
 +
 +static void
 +tty_pop_down_menu (Lisp_Object arg)
 +{
 +  tty_menu *menu = XSAVE_POINTER (arg, 0);
 +
 +  block_input ();
 +  tty_menu_destroy (menu);
 +  unblock_input ();
 +}
 +
 +Lisp_Object
 +tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
 +             Lisp_Object title, const char **error_name)
 +{
 +  tty_menu *menu;
 +  int pane, selidx, lpane, status;
 +  Lisp_Object entry, pane_prefix;
 +  char *datap;
 +  int ulx, uly, width, height;
 +  int dispwidth, dispheight;
 +  int i, j, lines, maxlines;
 +  int maxwidth;
 +  int dummy_int;
 +  unsigned int dummy_uint;
 +  ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 +
 +  if (! FRAME_TERMCAP_P (f))
 +    emacs_abort ();
 +
 +  *error_name = 0;
 +  if (menu_items_n_panes == 0)
 +    return Qnil;
 +
 +  if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
 +    {
 +      *error_name = "Empty menu";
 +      return Qnil;
 +    }
 +
 +  /* Make the menu on that window.  */
 +  menu = tty_menu_create ();
 +  if (menu == NULL)
 +    {
 +      *error_name = "Can't create menu";
 +      return Qnil;
 +    }
 +
 +  /* Don't GC while we prepare and show the menu, because we give the
 +     menu functions pointers to the contents of strings.  */
 +  inhibit_garbage_collection ();
 +
 +  /* Adjust coordinates to be root-window-relative.  */
 +  x += f->left_pos;
 +  y += f->top_pos;
 +
 +  /* Create all the necessary panes and their items.  */
 +  maxwidth = maxlines = lines = i = 0;
 +  lpane = TTYM_FAILURE;
 +  while (i < menu_items_used)
 +    {
 +      if (EQ (AREF (menu_items, i), Qt))
 +      {
 +        /* Create a new pane.  */
 +        Lisp_Object pane_name, prefix;
 +        const char *pane_string;
 +
 +          maxlines = max (maxlines, lines);
 +          lines = 0;
 +        pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
 +        prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
 +        pane_string = (NILP (pane_name)
 +                       ? "" : SSDATA (pane_name));
 +        if (keymaps && !NILP (prefix))
 +          pane_string++;
 +
 +        lpane = tty_menu_add_pane (menu, pane_string);
 +        if (lpane == TTYM_FAILURE)
 +          {
 +            tty_menu_destroy (menu);
 +            *error_name = "Can't create pane";
 +            return Qnil;
 +          }
 +        i += MENU_ITEMS_PANE_LENGTH;
 +
 +        /* Find the width of the widest item in this pane.  */
 +        j = i;
 +        while (j < menu_items_used)
 +          {
 +            Lisp_Object item;
 +            item = AREF (menu_items, j);
 +            if (EQ (item, Qt))
 +              break;
 +            if (NILP (item))
 +              {
 +                j++;
 +                continue;
 +              }
 +            width = SBYTES (item);
 +            if (width > maxwidth)
 +              maxwidth = width;
 +
 +            j += MENU_ITEMS_ITEM_LENGTH;
 +          }
 +      }
 +      /* Ignore a nil in the item list.
 +       It's meaningful only for dialog boxes.  */
 +      else if (EQ (AREF (menu_items, i), Qquote))
 +      i += 1;
 +      else
 +      {
 +        /* Create a new item within current pane.  */
 +        Lisp_Object item_name, enable, descrip, help;
 +        char *item_data;
 +        char const *help_string;
 +
 +        item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
 +        enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
 +        descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
 +        help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
 +        help_string = STRINGP (help) ? SSDATA (help) : NULL;
 +
 +        if (!NILP (descrip))
 +          {
 +            /* if alloca is fast, use that to make the space,
 +               to reduce gc needs.  */
 +            item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
 +            memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
 +            for (j = SCHARS (item_name); j < maxwidth; j++)
 +              item_data[j] = ' ';
 +            memcpy (item_data + j, SSDATA (descrip), SBYTES (descrip));
 +            item_data[j + SBYTES (descrip)] = 0;
 +          }
 +        else
 +          item_data = SSDATA (item_name);
 +
 +        if (lpane == TTYM_FAILURE
 +            || (tty_menu_add_selection (menu, lpane, item_data,
 +                                        !NILP (enable), help_string)
 +                == TTYM_FAILURE))
 +          {
 +            tty_menu_destroy (menu);
 +            *error_name = "Can't add selection to menu";
 +            return Qnil;
 +          }
 +        i += MENU_ITEMS_ITEM_LENGTH;
 +          lines++;
 +      }
 +    }
 +
 +  maxlines = max (maxlines, lines);
 +
 +  /* All set and ready to fly.  */
 +  dispwidth = f->text_cols;
 +  dispheight = f->text_lines;
 +  x = min (x, dispwidth);
 +  y = min (y, dispheight);
 +  x = max (x, 1);
 +  y = max (y, 1);
 +  tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
 +  if (ulx+width > dispwidth)
 +    {
 +      x -= (ulx + width) - dispwidth;
 +      ulx = dispwidth - width;
 +    }
 +  if (uly+height > dispheight)
 +    {
 +      y -= (uly + height) - dispheight;
 +      uly = dispheight - height;
 +    }
 +
 +  if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 2)
 +    {
 +      /* Move the menu away of the echo area, to avoid overwriting the
 +       menu with help echo messages or vice versa.  */
 +      if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
 +      {
 +        y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
 +        uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
 +      }
 +      else
 +      {
 +        y -= 2;
 +        uly -= 2;
 +      }
 +    }
 +
 +  if (ulx < 0) x -= ulx;
 +  if (uly < 0) y -= uly;
 +
 +#if 0
 +  /* This code doesn't make sense on a TTY, since it can easily annul
 +     the adjustments above that carefully avoid truncation of the menu
 +     items.  */
 +  if (! for_click)
 +    {
 +      /* If position was not given by a mouse click, adjust so upper left
 +         corner of the menu as a whole ends up at given coordinates.  This
 +         is what x-popup-menu says in its documentation.  */
 +      x += width/2;
 +      y += 1.5*height/(maxlines+2);
 +    }
 +#endif
 +
 +  pane = selidx = 0;
 +
 +  record_unwind_protect (tty_pop_down_menu, make_save_ptr (menu));
 +
 +  tty_menu_help_frame = f;    /* FIXME: This seems unused.  */
 +  specbind (Qoverriding_terminal_local_map,
 +          Fsymbol_value (Qtty_menu_navigation_map));
 +  status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
 +                            tty_menu_help_callback);
 +  entry = pane_prefix = Qnil;
 +
 +  switch (status)
 +    {
 +    case TTYM_SUCCESS:
 +      /* Find the item number SELIDX in pane number PANE.  */
 +      i = 0;
 +      while (i < menu_items_used)
 +      {
 +        if (EQ (AREF (menu_items, i), Qt))
 +          {
 +            if (pane == 0)
 +              pane_prefix
 +                = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
 +            pane--;
 +            i += MENU_ITEMS_PANE_LENGTH;
 +          }
 +        else
 +          {
 +            if (pane == -1)
 +              {
 +                if (selidx == 0)
 +                  {
 +                    entry
 +                      = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
 +                    if (keymaps != 0)
 +                      {
 +                        entry = Fcons (entry, Qnil);
 +                        if (!NILP (pane_prefix))
 +                          entry = Fcons (pane_prefix, entry);
 +                      }
 +                    break;
 +                  }
 +                selidx--;
 +              }
 +            i += MENU_ITEMS_ITEM_LENGTH;
 +          }
 +      }
 +      break;
 +
 +    case TTYM_FAILURE:
 +      *error_name = "Can't activate menu";
 +    case TTYM_IA_SELECT:
 +      break;
 +    case TTYM_NO_SELECT:
 +      /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
 +       the menu was invoked with a mouse event as POSITION).  */
 +      if (! for_click)
 +        Fsignal (Qquit, Qnil);
 +      break;
 +    }
 +
 +  unbind_to (specpdl_count, Qnil);
 +
 +  return entry;
 +}
 +
 +#endif        /* HAVE_MENUS && !MSDOS */
 +
 +\f
  #ifndef MSDOS
  /***********************************************************************
                            Initialization
@@@ -4061,12 -2917,8 +4044,8 @@@ dissociate_if_controlling_tty (int fd
  struct terminal *
  init_tty (const char *name, const char *terminal_type, bool must_succeed)
  {
- #ifdef TERMINFO
-   char **address = 0;
- #else
    char *area;
    char **address = &area;
- #endif
    int status;
    struct tty_display_info *tty = NULL;
    struct terminal *terminal = NULL;
    /* On some systems, tgetent tries to access the controlling
       terminal.  */
    block_tty_out_signal ();
- #ifdef TERMINFO
-   status = tgetent (0, terminal_type);
- #else
    status = tgetent (tty->termcap_term_buffer, terminal_type);
    if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
      emacs_abort ();
- #endif
    unblock_tty_out_signal ();
  
    if (status < 0)
@@@ -4194,9 -3042,7 +4169,7 @@@ use the Bourne shell command `TERM=... 
                     terminal_type);
      }
  
- #ifndef TERMINFO
    area = tty->termcap_strings_buffer;
- #endif
    tty->TS_ins_line = tgetstr ("al", address);
    tty->TS_ins_multi_lines = tgetstr ("AL", address);
    tty->TS_bell = tgetstr ("bl", address);
@@@ -4668,14 -3514,4 +4641,14 @@@ bigger, or it may make it blink, or it 
  
    encode_terminal_src = NULL;
    encode_terminal_dst = NULL;
 +
 +  DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
 +  DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item");
 +  DEFSYM (Qtty_menu_next_menu, "tty-menu-next-menu");
 +  DEFSYM (Qtty_menu_prev_menu, "tty-menu-prev-menu");
 +  DEFSYM (Qtty_menu_select, "tty-menu-select");
 +  DEFSYM (Qtty_menu_ignore, "tty-menu-ignore");
 +  DEFSYM (Qtty_menu_exit, "tty-menu-exit");
 +  DEFSYM (Qtty_menu_mouse_movement, "tty-menu-mouse-movement");
 +  DEFSYM (Qtty_menu_navigation_map, "tty-menu-navigation-map");
  }
diff --combined src/termchar.h
@@@ -30,9 -30,7 +30,7 @@@ struct tty_outpu
    /* There is nothing else here at the moment... */
  };
  
- #ifndef TERMINFO
  enum { TERMCAP_BUFFER_SIZE = 4096 };
- #endif
  
  /* Parameters that are shared between frames on the same tty device. */
  
@@@ -78,7 -76,6 +76,6 @@@ struct tty_display_inf
       mouse-face.  */
    Mouse_HLInfo mouse_highlight;
  
- #ifndef TERMINFO
    /* Buffer used internally by termcap (see tgetent in the Termcap
       manual).  Only init_tty should use this.  */
    char termcap_term_buffer[TERMCAP_BUFFER_SIZE];
@@@ -86,7 -83,6 +83,6 @@@
    /* Buffer storing terminal description strings (see tgetstr in the
       Termcap manual).  Only init_tty should use this.  */
    char termcap_strings_buffer[TERMCAP_BUFFER_SIZE];
- #endif
  
    /* Strings, numbers and flags taken from the termcap entry.  */
  
    /* Nonzero means use ^S/^Q for flow control.  */
  
    unsigned flow_control : 1;
 +
 +  /* Non-zero means we are displaying a TTY menu on this tty.  */
 +  unsigned showing_menu : 1;
  };
  
  /* A chain of structures for all tty devices currently in use. */
diff --combined src/termhooks.h
@@@ -26,11 -26,9 +26,9 @@@ along with GNU Emacs.  If not, see <htt
  #include "systime.h" /* for Time */
  
  INLINE_HEADER_BEGIN
- #ifndef TERMHOOKS_INLINE
- # define TERMHOOKS_INLINE INLINE
- #endif
  
  enum scroll_bar_part {
+   scroll_bar_nowhere = -1,
    scroll_bar_above_handle,
    scroll_bar_handle,
    scroll_bar_below_handle,
    scroll_bar_move_ratio
  };
  
- /* If the value of the frame parameter changed, whis hook is called.
-    For example, if going from fullscreen to not fullscreen this hook
-    may do something OS dependent, like extended window manager hints on X11.  */
- extern void (*fullscreen_hook) (struct frame *f);
  /* Output method of a terminal (and frames on this terminal, respectively).  */
  
  enum output_method
@@@ -498,7 -491,7 +491,7 @@@ struct termina
       windows.  */
    void (*frame_raise_lower_hook) (struct frame *f, int raise_flag);
  
-   /* If the value of the frame parameter changed, whis hook is called.
+   /* If the value of the frame parameter changed, this hook is called.
       For example, if going from fullscreen to not fullscreen this hook
       may do something OS dependent, like extended window manager hints on X11.  */
    void (*fullscreen_hook) (struct frame *f);
  
  /* Most code should use these functions to set Lisp fields in struct
     terminal.  */
TERMHOOKS_INLINE void
+ INLINE void
  tset_charset_list (struct terminal *t, Lisp_Object val)
  {
    t->charset_list = val;
  }
TERMHOOKS_INLINE void
+ INLINE void
  tset_selection_alist (struct terminal *t, Lisp_Object val)
  {
    t->Vselection_alist = val;
@@@ -663,14 -656,6 +656,14 @@@ extern unsigned char *encode_terminal_c
  extern void close_gpm (int gpm_fd);
  #endif
  
 +#ifdef WINDOWSNT
 +extern int cursorX (struct tty_display_info *);
 +extern int cursorY (struct tty_display_info *);
 +#else
 +#define cursorX(t)  curX(t)
 +#define cursorY(t)  curY(t)
 +#endif
 +
  INLINE_HEADER_END
  
  #endif /* EMACS_TERMHOOKS_H */
diff --combined src/w32console.c
@@@ -62,7 -62,6 +62,7 @@@ static HANDLE prev_screen, cur_screen
  static WORD   char_attr_normal;
  static DWORD  prev_console_mode;
  
 +static CONSOLE_CURSOR_INFO console_cursor_info;
  #ifndef USE_SEPARATE_SCREEN
  static CONSOLE_CURSOR_INFO prev_console_cursor;
  #endif
@@@ -96,22 -95,6 +96,22 @@@ w32con_move_cursor (struct frame *f, in
    SetConsoleCursorPosition (cur_screen, cursor_coords);
  }
  
 +void
 +w32con_hide_cursor (void)
 +{
 +  GetConsoleCursorInfo (cur_screen, &console_cursor_info);
 +  console_cursor_info.bVisible = FALSE;
 +  SetConsoleCursorInfo (cur_screen, &console_cursor_info);
 +}
 +
 +void
 +w32con_show_cursor (void)
 +{
 +  GetConsoleCursorInfo (cur_screen, &console_cursor_info);
 +  console_cursor_info.bVisible = TRUE;
 +  SetConsoleCursorInfo (cur_screen, &console_cursor_info);
 +}
 +
  /* Clear from cursor to end of screen.  */
  static void
  w32con_clear_to_end (struct frame *f)
@@@ -569,21 -552,6 +569,21 @@@ Wcm_clear (struct tty_display_info *tty
  }
  
  
 +/* Report the current cursor position.  The following two functions
 +   are used in term.c's tty menu code, so they are not really
 +   "stubs".  */
 +int
 +cursorX (struct tty_display_info *tty)
 +{
 +  return cursor_coords.X;
 +}
 +
 +int
 +cursorY (struct tty_display_info *tty)
 +{
 +  return cursor_coords.Y;
 +}
 +
  /***********************************************************************
                                Faces
   ***********************************************************************/
@@@ -630,7 -598,6 +630,6 @@@ voi
  initialize_w32_display (struct terminal *term, int *width, int *height)
  {
    CONSOLE_SCREEN_BUFFER_INFO  info;
-   Mouse_HLInfo *hlinfo;
  
    term->rif = 0; /* No window based redisplay on the console.  */
    term->cursor_to_hook                = w32con_move_cursor;
diff --combined src/w32fns.c
@@@ -277,7 -277,7 +277,7 @@@ check_x_display_info (Lisp_Object frame
        struct frame *sf = XFRAME (selected_frame);
  
        if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
-       return FRAME_W32_DISPLAY_INFO (sf);
+       return FRAME_DISPLAY_INFO (sf);
        else
        return &one_w32_display_info;
      }
        f = XFRAME (frame);
        if (! FRAME_W32_P (f))
        error ("Non-W32 frame used");
-       return FRAME_W32_DISPLAY_INFO (f);
+       return FRAME_DISPLAY_INFO (f);
      }
  }
  \f
@@@ -307,7 -307,7 +307,7 @@@ x_window_to_frame (struct w32_display_i
    FOR_EACH_FRAME (tail, frame)
      {
        f = XFRAME (frame);
-       if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
+       if (!FRAME_W32_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
        continue;
  
        if (FRAME_W32_WINDOW (f) == wdesc)
@@@ -1027,18 -1027,18 +1027,18 @@@ w32_regenerate_palette (struct frame *f
    int                   i;
  
    /* don't bother trying to create palette if not supported */
-   if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
+   if (! FRAME_DISPLAY_INFO (f)->has_palette)
      return;
  
    log_palette = (LOGPALETTE *)
      alloca (sizeof (LOGPALETTE) +
-            FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
+            FRAME_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
    log_palette->palVersion = 0x300;
-   log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
+   log_palette->palNumEntries = FRAME_DISPLAY_INFO (f)->num_colors;
  
-   list = FRAME_W32_DISPLAY_INFO (f)->color_list;
+   list = FRAME_DISPLAY_INFO (f)->color_list;
    for (i = 0;
-        i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
+        i < FRAME_DISPLAY_INFO (f)->num_colors;
         i++, list = list->next)
      log_palette->palPalEntry[i] = list->entry;
  
  
    enter_crit ();
  
-   if (FRAME_W32_DISPLAY_INFO (f)->palette)
-     DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
-   FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
+   if (FRAME_DISPLAY_INFO (f)->palette)
+     DeleteObject (FRAME_DISPLAY_INFO (f)->palette);
+   FRAME_DISPLAY_INFO (f)->palette = new_palette;
  
    /* Realize display palette and garbage all frames. */
    release_frame_dc (f, get_frame_dc (f));
  void
  w32_map_color (struct frame *f, COLORREF color)
  {
-   struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
+   struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
  
    if (NILP (Vw32_enable_palette))
      return;
    list = xmalloc (sizeof (struct w32_palette_entry));
    SET_W32_COLOR (list->entry, color);
    list->refcount = 1;
-   list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
-   FRAME_W32_DISPLAY_INFO (f)->color_list = list;
-   FRAME_W32_DISPLAY_INFO (f)->num_colors++;
+   list->next = FRAME_DISPLAY_INFO (f)->color_list;
+   FRAME_DISPLAY_INFO (f)->color_list = list;
+   FRAME_DISPLAY_INFO (f)->num_colors++;
  
    /* set flag that palette must be regenerated */
-   FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
+   FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
  }
  
  void
  w32_unmap_color (struct frame *f, COLORREF color)
  {
-   struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
-   struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
+   struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
+   struct w32_palette_entry **prev = &FRAME_DISPLAY_INFO (f)->color_list;
  
    if (NILP (Vw32_enable_palette))
      return;
            {
              *prev = list->next;
              xfree (list);
-             FRAME_W32_DISPLAY_INFO (f)->num_colors--;
+             FRAME_DISPLAY_INFO (f)->num_colors--;
              break;
            }
          else
      }
  
    /* set flag that palette must be regenerated */
-   FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
+   FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
  }
  #endif
  
@@@ -1235,7 -1235,7 +1235,7 @@@ x_decode_color (struct frame *f, Lisp_O
    else if (strcmp (SDATA (arg), "white") == 0)
      return WHITE_PIX_DEFAULT (f);
  
-   if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
+   if ((FRAME_DISPLAY_INFO (f)->n_planes * FRAME_DISPLAY_INFO (f)->n_cbits) == 1)
      return def;
  
    /* w32_defined_color is responsible for coping with failures
@@@ -1637,7 -1637,7 +1637,7 @@@ x_set_menu_bar_lines (struct frame *f, 
        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
        do_pending_window_change (0);
      }
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
  }
  
  
@@@ -1679,7 -1679,7 +1679,7 @@@ x_set_tool_bar_lines (struct frame *f, 
  
    FRAME_TOOL_BAR_LINES (f) = nlines;
    resize_frame_windows (f, FRAME_LINES (f), 0);
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
  
    /* We also have to make sure that the internal border at the top of
       the frame, below the menu bar or tool bar, is redrawn when the
@@@ -1752,10 -1752,10 +1752,10 @@@ x_set_name (struct frame *f, Lisp_Objec
      {
        /* Check for no change needed in this very common case
         before we do any consing.  */
-       if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
+       if (!strcmp (FRAME_DISPLAY_INFO (f)->w32_id_name,
                   SDATA (f->name)))
        return;
-       name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
+       name = build_string (FRAME_DISPLAY_INFO (f)->w32_id_name);
      }
    else
      CHECK_STRING (name);
@@@ -1890,16 -1890,11 +1890,11 @@@ w32_init_class (HINSTANCE hinst
  static HWND
  w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
  {
-   return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
-                       /* Position and size of scroll bar.  */
-                       XINT (bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                         XINT (bar->top),
-                       XINT (bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                         XINT (bar->height),
-                       FRAME_W32_WINDOW (f),
-                       NULL,
-                       hinst,
-                       NULL));
+   return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
+                      /* Position and size of scroll bar.  */
+                      XINT (bar->left), XINT (bar->top),
+                      XINT (bar->width), XINT (bar->height),
+                      FRAME_W32_WINDOW (f), NULL, hinst, NULL);
  }
  
  static void
@@@ -4232,7 -4227,7 +4227,7 @@@ unwind_create_frame (Lisp_Object frame
    if (NILP (Fmemq (frame, Vframe_list)))
      {
  #ifdef GLYPH_DEBUG
-       struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+       struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  #endif
  
        x_free_frame_resources (f);
@@@ -4258,7 -4253,7 +4253,7 @@@ do_unwind_create_frame (Lisp_Object fra
  static void
  x_default_font_parameter (struct frame *f, Lisp_Object parms)
  {
-   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
    Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
                                RES_TYPE_STRING);
    Lisp_Object font;
@@@ -4392,9 -4387,9 +4387,9 @@@ This function is an internal primitive-
    if (! STRINGP (f->icon_name))
      fset_icon_name (f, Qnil);
  
- /*  FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
+ /*  FRAME_DISPLAY_INFO (f) = dpyinfo; */
  
-   /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe.  */
+   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
    record_unwind_protect (do_unwind_create_frame, frame);
  #ifdef GLYPH_DEBUG
    image_cache_refcount =
      }
    else
      {
-       f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+       f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
        f->output_data.w32->explicit_parent = 0;
      }
  
                         "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
  
    f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
-   f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
  
    f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
    f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
  
    /* Now consider the frame official.  */
    f->terminal->reference_count++;
-   FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+   FRAME_DISPLAY_INFO (f)->reference_count++;
    Vframe_list = Fcons (frame, Vframe_list);
  
    /* We need to do this after creating the window, so that the
  Lisp_Object
  x_get_focus_frame (struct frame *frame)
  {
-   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
+   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
    Lisp_Object xfocus;
    if (! dpyinfo->w32_focus_frame)
      return Qnil;
    return xfocus;
  }
  
- DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
-        doc: /* Give FRAME input focus, raising to foreground if necessary.  */)
-   (Lisp_Object frame)
- {
-   x_focus_on_frame (decode_window_system_frame (frame));
-   return Qnil;
- }
\f
  DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
         doc: /* Internal function called by `color-defined-p', which see.
  \(Note that the Nextstep version of this function ignores FRAME.)  */)
@@@ -5131,7 -5117,7 +5117,7 @@@ SOUND is nil to use the normal beep.  *
  int
  x_screen_planes (register struct frame *f)
  {
-   return FRAME_W32_DISPLAY_INFO (f)->n_planes;
+   return FRAME_DISPLAY_INFO (f)->n_planes;
  }
  \f
  /* Return the display structure for the display named NAME.
@@@ -5201,11 -5187,6 +5187,6 @@@ terminate Emacs if we can't open the co
    if (! NILP (xrm_string))
      CHECK_STRING (xrm_string);
  
- #if 0
-   if (! EQ (Vwindow_system, intern ("w32")))
-     error ("Not using Microsoft Windows");
- #endif
    /* Allow color mapping to be defined externally; first look in user's
       HOME directory, then in Emacs etc dir for a file called rgb.txt. */
    {
@@@ -5486,10 -5467,7 +5467,10 @@@ show_hourglass (struct atimer *timer
      f = SELECTED_FRAME ();
  
    if (!FRAME_W32_P (f))
 -    return;
 +    {
 +      unblock_input ();
 +      return;
 +    }
  
    w32_show_hourglass (f);
    unblock_input ();
@@@ -5668,7 -5646,7 +5649,7 @@@ x_create_tip_frame (struct w32_display_
    dpyinfo_refcount = dpyinfo->reference_count;
  #endif /* GLYPH_DEBUG */
    FRAME_KBOARD (f) = kb;
-   f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
    f->output_data.w32->explicit_parent = 0;
  
    /* Set the name; the functions to which we pass f expect the name to
    init_frame_faces (f);
  
    f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
-   f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
  
    window_prompting = x_figure_window_size (f, parms, 0);
  
  
    /* Now that the frame is official, it counts as a reference to
       its display.  */
-   FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+   FRAME_DISPLAY_INFO (f)->reference_count++;
    f->terminal->reference_count++;
  
    /* It is now ok to make the frame official even if we get an error
@@@ -5851,8 -5829,8 +5832,8 @@@ compute_tip_xy (struct frame *f
        /* Default min and max values.  */
        min_x = 0;
        min_y = 0;
-       max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f));
-       max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f));
+       max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
+       max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
  
        block_input ();
        GetCursorPos (&pt);
@@@ -6038,7 -6016,7 +6019,7 @@@ Text larger than the specified size is 
  
    /* Create a frame for the tooltip, and record it in the global
       variable tip_frame.  */
-   frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
+   frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string);
    f = XFRAME (frame);
  
    /* Set up the frame's root window.  */
      }
  
    FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
    w->pseudo_window_p = 1;
  
    /* Display the tooltip text in a temporary buffer.  */
        width /= WINDOW_FRAME_COLUMN_WIDTH (w);
        w->total_cols = width;
        FRAME_TOTAL_COLS (f) = width;
-       adjust_glyphs (f);
+       adjust_frame_glyphs (f);
        w->pseudo_window_p = 1;
        clear_glyph_matrix (w->desired_matrix);
        clear_glyph_matrix (w->current_matrix);
@@@ -7865,7 -7843,6 +7846,6 @@@ only be necessary if the default settin
    defsubr (&Sx_close_connection);
    defsubr (&Sx_display_list);
    defsubr (&Sx_synchronize);
-   defsubr (&Sx_focus_frame);
  
    /* W32 specific functions */
  
diff --combined src/w32menu.c
@@@ -231,7 -231,7 +231,7 @@@ otherwise it is "Question". */
      unblock_input ();
  
      discard_menu_items ();
-     FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+     FRAME_DISPLAY_INFO (f)->grabbed = 0;
  
      if (error_name) error (error_name);
      return selection;
@@@ -421,7 -421,7 +421,7 @@@ set_frame_menubar (struct frame *f, boo
  
        /* Save the frame's previous menu bar contents data.  */
        if (previous_menu_items_used)
-       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->u.contents,
                previous_menu_items_used * word_size);
  
        /* Fill in menu_items with the current menu bar contents.
@@@ -682,8 -682,6 +682,8 @@@ w32_menu_show (struct frame *f, int x, 
        return Qnil;
      }
  
 +  block_input ();
 +
    /* Create a tree of widget_value objects
       representing the panes and their items.  */
    wv = xmalloc_widget_value ();
    /* Clean up extraneous mouse events which might have been generated
       during the call. */
    discard_mouse_events ();
-   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+   FRAME_DISPLAY_INFO (f)->grabbed = 0;
  
    /* Free the widget_value objects we used to specify the contents.  */
    free_menubar_widget_value_tree (first_wv);
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
 +                unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
        }
      }
    else if (!for_click)
 -    /* Make "Cancel" equivalent to C-g.  */
 -    Fsignal (Qquit, Qnil);
 +    {
 +      unblock_input ();
 +      /* Make "Cancel" equivalent to C-g.  */
 +      Fsignal (Qquit, Qnil);
 +    }
  
 +  unblock_input ();
    return Qnil;
  }
  \f
@@@ -1130,7 -1123,7 +1130,7 @@@ w32_dialog_show (struct frame *f, int k
    lw_pop_up_all_widgets (dialog_id);
  
    /* Process events that apply to the menu.  */
-   popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
+   popup_get_selection ((XEvent *) 0, FRAME_DISPLAY_INFO (f), dialog_id);
  
    lw_destroy_all_widgets (dialog_id);
  
diff --combined src/w32term.h
@@@ -179,6 -179,37 +179,37 @@@ struct w32_display_inf
       frame.  It differs from w32_focus_frame when we're using a global
       minibuffer.  */
    struct frame *x_highlight_frame;
+   /* The frame waiting to be auto-raised in w32_read_socket.  */
+   struct frame *w32_pending_autoraise_frame;
+   /* The frame where the mouse was last time we reported a mouse event.  */
+   struct frame *last_mouse_frame;
+   /* The frame where the mouse was last time we reported a mouse motion.  */
+   struct frame *last_mouse_motion_frame;
+   /* The frame where the mouse was last time we reported a mouse position.  */
+   struct frame *last_mouse_glyph_frame;
+   /* Position where the mouse was last time we reported a motion.
+      This is a position on last_mouse_motion_frame.  */
+   int last_mouse_motion_x;
+   int last_mouse_motion_y;
+   /* Where the mouse was last time we reported a mouse position.
+      This is a rectangle on last_mouse_glyph_frame.  */
+   RECT last_mouse_glyph;
+   /* The scroll bar in which the last motion event occurred.  */
+   struct scroll_bar *last_mouse_scroll_bar;
+   /* Mouse position on the scroll bar above.
+      FIXME: shouldn't it be a member of struct scroll_bar?  */
+   int last_mouse_scroll_bar_pos;
+   /* Time of last mouse movement.  */
+   Time last_mouse_movement_time;
  };
  
  /* This is a chain of structures for all the displays currently in use.  */
@@@ -199,8 -230,6 +230,6 @@@ Lisp_Object display_x_get_resource (str
                                      Lisp_Object, Lisp_Object,
                                      Lisp_Object, Lisp_Object);
  
- extern void x_focus_on_frame (struct frame *f);
  /* also defined in xterm.h XXX: factor out to common header */
  
  extern struct w32_display_info *w32_term_init (Lisp_Object,
@@@ -211,7 -240,6 +240,6 @@@ extern void x_set_window_size (struct f
                                int cols, int rows);
  extern int x_display_pixel_height (struct w32_display_info *);
  extern int x_display_pixel_width (struct w32_display_info *);
- extern void x_sync (struct frame *);
  extern Lisp_Object x_get_focus_frame (struct frame *);
  extern void x_set_mouse_position (struct frame *f, int h, int v);
  extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
@@@ -236,10 -264,6 +264,10 @@@ extern int w32_kbd_mods_to_emacs (DWOR
  
  extern Lisp_Object x_get_focus_frame (struct frame *);
  
 +/* w32console.c */
 +extern void w32con_hide_cursor (void);
 +extern void w32con_show_cursor (void);
 +
  \f
  #define PIX_TYPE COLORREF
  
@@@ -384,22 -408,11 +412,11 @@@ extern struct w32_output w32term_displa
  #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset)
  
  /* This gives the w32_display_info structure for the display F is on.  */
- #define FRAME_W32_DISPLAY_INFO(f) (&one_w32_display_info)
- #define FRAME_X_DISPLAY_INFO(f) (&one_w32_display_info)
+ #define FRAME_DISPLAY_INFO(f) (&one_w32_display_info)
  
  /* This is the `Display *' which frame F is on.  */
  #define FRAME_X_DISPLAY(f) (0)
  
- /* Value is the smallest width of any character in any font on frame F.  */
- #define FRAME_SMALLEST_CHAR_WIDTH(F) \
-      FRAME_W32_DISPLAY_INFO(F)->smallest_char_width
- /* Value is the smallest height of any font on frame F.  */
- #define FRAME_SMALLEST_FONT_HEIGHT(F) \
-      FRAME_W32_DISPLAY_INFO(F)->smallest_font_height
  #define FRAME_NORMAL_PLACEMENT(F) ((F)->output_data.w32->normal_placement)
  #define FRAME_PREV_FSMODE(F)      ((F)->output_data.w32->prev_fsmode)
  
@@@ -491,21 -504,12 +508,12 @@@ struct scroll_bar 
  #define SET_SCROLL_BAR_W32_WINDOW(ptr, id) \
    (SCROLL_BAR_UNPACK ((ptr)->w32_window_low, (ptr)->w32_window_high, (intptr_t) id))
  
- /* Extract the X widget of the scroll bar from a struct scroll_bar.  */
- #define SCROLL_BAR_X_WIDGET(ptr) \
-   ((Widget) SCROLL_BAR_PACK ((ptr)->x_widget_low, (ptr)->x_widget_high))
- /* Store a widget id in a struct scroll_bar.  */
- #define SET_SCROLL_BAR_X_WIDGET(ptr, w) \
-   (SCROLL_BAR_UNPACK ((ptr)->x_widget_low, (ptr)->x_widget_high, (int) w))
  /* Return the inside width of a vertical scroll bar, given the outside
     width.  */
  #define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
    ((width) \
     - VERTICAL_SCROLL_BAR_LEFT_BORDER \
-    - VERTICAL_SCROLL_BAR_RIGHT_BORDER \
-    - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2)
+    - VERTICAL_SCROLL_BAR_RIGHT_BORDER)
  
  /* Return the length of the rectangle within which the top of the
     handle must stay.  This isn't equivalent to the inside height,
  /* Minimum lengths for scroll bar handles, in pixels.  */
  #define VERTICAL_SCROLL_BAR_MIN_HANDLE (vertical_scroll_bar_min_handle)
  
- /* Trimming off a few pixels from each side prevents
-    text from glomming up against the scroll bar */
- #define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0)
\f
  struct frame;  /* from frame.h */
  
  extern void w32_fill_rect (struct frame *, HDC, COLORREF, RECT *);
diff --combined src/window.c
@@@ -20,8 -20,6 +20,6 @@@ along with GNU Emacs.  If not, see <htt
  
  #include <config.h>
  
- #define WINDOW_INLINE EXTERN_INLINE
  #include <stdio.h>
  
  #include "lisp.h"
  #include "blockinput.h"
  #include "intervals.h"
  #include "termhooks.h"                /* For FRAME_TERMINAL.  */
- #ifdef HAVE_X_WINDOWS
- #include "xterm.h"
- #endif        /* HAVE_X_WINDOWS */
- #ifdef HAVE_NTGUI
- #include "w32term.h"
- #endif
+ #ifdef HAVE_WINDOW_SYSTEM
+ #include TERM_HEADER
+ #endif /* HAVE_WINDOW_SYSTEM */
  #ifdef MSDOS
  #include "msdos.h"
  #endif
- #ifdef HAVE_NS
- #include "nsterm.h"
- #endif
  
  Lisp_Object Qwindowp, Qwindow_live_p;
  static Lisp_Object Qwindow_valid_p;
@@@ -1386,6 -1377,7 +1377,7 @@@ window_from_coordinates (struct frame *
    cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
    foreach_window (f, check_window_containing, &cw);
  
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
    /* If not found above, see if it's in the tool bar window, if a tool
       bar exists.  */
    if (NILP (window)
        *part = ON_TEXT;
        window = f->tool_bar_window;
      }
+ #endif
  
    return window;
  }
@@@ -2952,7 -2945,7 +2945,7 @@@ window-start value is reasonable when t
        }
      }
  
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
    unblock_input ();
  
    run_window_configuration_change_hook (f);
@@@ -3426,6 -3419,7 +3419,7 @@@ make_window (void
       non-Lisp data, so do it only for slots which should not be zero.  */
    w->nrows_scale_factor = w->ncols_scale_factor = 1;
    w->left_fringe_width = w->right_fringe_width = -1;
+   w->mode_line_height = w->header_line_height = -1;
    w->phys_cursor_type = -1;
    w->phys_cursor_width = -1;
    w->scroll_bar_width = -1;
@@@ -3651,7 -3645,7 +3645,7 @@@ be applied on the Elisp level.  */
    windows_or_buffers_changed++;
    FRAME_WINDOW_SIZES_CHANGED (f) = 1;
  
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
    unblock_input ();
  
    run_window_configuration_change_hook (f);
@@@ -3921,7 -3915,7 +3915,7 @@@ set correctly.  See the code of `split-
  
    block_input ();
    window_resize_apply (p, horflag);
-   adjust_glyphs (f);
+   adjust_frame_glyphs (f);
    /* Set buffer of NEW to buffer of reference window.  Don't run
       any hooks.  */
    set_window_buffer (new, r->contents, 0, 1);
@@@ -4050,7 -4044,7 +4044,7 @@@ Signal an error when WINDOW is the onl
          recombine_windows (sibling);
        }
  
-       adjust_glyphs (f);
+       adjust_frame_glyphs (f);
  
        if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
        /* We deleted the frame's selected window.  */
@@@ -4137,7 -4131,7 +4131,7 @@@ grow_mini_window (struct window *w, in
        w->total_lines -= XINT (value);
        /* Enforce full redisplay.  FIXME: make it more selective.  */
        windows_or_buffers_changed++;
-       adjust_glyphs (f);
+       adjust_frame_glyphs (f);
        unblock_input ();
      }
  }
@@@ -4171,7 -4165,7 +4165,7 @@@ shrink_mini_window (struct window *w
          w->total_lines = 1;
          /* Enforce full redisplay.  FIXME: make it more selective.  */
          windows_or_buffers_changed++;
-         adjust_glyphs (f);
+         adjust_frame_glyphs (f);
          unblock_input ();
        }
        /* If the above failed for whatever strange reason we must make a
@@@ -4212,7 -4206,7 +4206,7 @@@ DEFUN ("resize-mini-window-internal", F
  
        windows_or_buffers_changed++;
        FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-       adjust_glyphs (f);
+       adjust_frame_glyphs (f);
        unblock_input ();
  
        run_window_configuration_change_hook (f);
@@@ -4483,7 -4477,7 +4477,7 @@@ window_scroll_pixel_based (Lisp_Object 
                 visible.  */
              w->vscroll = (it.last_visible_y
                            - it.current_y + it.max_ascent + it.max_descent);
-             adjust_glyphs (it.f);
+             adjust_frame_glyphs (it.f);
            }
          else
            {
@@@ -5118,9 -5112,9 +5112,9 @@@ and redisplay normally--don't erase an
          /* Invalidate pixel data calculated for all compositions.  */
          for (i = 0; i < n_compositions; i++)
            composition_table[i]->font = NULL;
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
          WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+ #endif
          Fredraw_frame (WINDOW_FRAME (w));
          SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
        }
@@@ -5407,7 -5401,7 +5401,7 @@@ struct saved_windo
  };
  
  #define SAVED_WINDOW_N(swv,n) \
-   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
+   ((struct saved_window *) (XVECTOR ((swv)->u.contents[(n)])))
  
  DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
         doc: /* Return t if OBJECT is a window-configuration object.  */)
@@@ -5542,23 -5536,17 +5536,23 @@@ the return value is nil.  Otherwise th
          || data->frame_cols != previous_frame_cols)
        change_frame_size (f, data->frame_lines,
                           data->frame_cols, 0, 0, 0);
 -#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
 +#ifdef HAVE_MENUS
        if (data->frame_menu_bar_lines
          != previous_frame_menu_bar_lines)
 -      x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
 -                            make_number (0));
 +      {
 +        if (FRAME_WINDOW_P (f))
 +          x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
 +                                make_number (0));
 +        else  /* TTY or MSDOS */
 +          set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
 +                              make_number (0));
 +      }
 +#endif
  #ifdef HAVE_WINDOW_SYSTEM
        if (data->frame_tool_bar_lines
          != previous_frame_tool_bar_lines)
        x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
                              make_number (0));
 -#endif
  #endif
  
        /* "Swap out" point from the selected window's buffer
          || previous_frame_cols != FRAME_COLS (f))
        change_frame_size (f, previous_frame_lines, previous_frame_cols,
                           0, 0, 0);
 -#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
 +#ifdef HAVE_MENUS
        if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
 -      x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
 -                            make_number (0));
 +      {
 +        if (FRAME_WINDOW_P (f))
 +          x_set_menu_bar_lines (f,
 +                                make_number (previous_frame_menu_bar_lines),
 +                                make_number (0));
 +        else  /* TTY or MSDOS */
 +          set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
 +                              make_number (0));
 +      }
 +#endif
  #ifdef HAVE_WINDOW_SYSTEM
        if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
        x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
                              make_number (0));
 -#endif
  #endif
  
        /* Now, free glyph matrices in windows that were not reused.  */
            ++n;
        }
  
-       adjust_glyphs (f);
+       adjust_frame_glyphs (f);
        unblock_input ();
  
        /* Scan dead buffer windows.  */
@@@ -6102,7 -6083,7 +6096,7 @@@ apply_window_adjustment (struct window 
    clear_glyph_matrix (w->current_matrix);
    w->window_end_valid = 0;
    windows_or_buffers_changed++;
-   adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
+   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
  }
  
  \f
@@@ -6368,7 -6349,7 +6362,7 @@@ If PIXELS-P is non-nil, the return valu
          /* Adjust glyph matrix of the frame if the virtual display
             area becomes larger than before.  */
          if (w->vscroll < 0 && w->vscroll < old_dy)
-           adjust_glyphs (f);
+           adjust_frame_glyphs (f);
  
          /* Prevent redisplay shortcuts.  */
          XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
@@@ -6524,7 -6505,6 +6518,6 @@@ init_window_once (void
    Vterminal_frame = selected_frame;
    minibuf_window = f->minibuffer_window;
    selected_window = f->selected_window;
-   last_nonminibuf_frame = f;
  
    window_initialized = 1;
  }
diff --combined src/xdisp.c
@@@ -1,7 -1,6 +1,6 @@@
  /* Display generation from window structure and buffer text.
  
- Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
- Inc.
+ Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
  
@@@ -299,19 -298,9 +298,9 @@@ along with GNU Emacs.  If not, see <htt
  #include "font.h"
  #include "fontset.h"
  #include "blockinput.h"
- #ifdef HAVE_X_WINDOWS
- #include "xterm.h"
- #endif
- #ifdef HAVE_NTGUI
- #include "w32term.h"
- #endif
- #ifdef HAVE_NS
- #include "nsterm.h"
- #endif
- #ifdef USE_GTK
- #include "gtkutil.h"
- #endif
+ #ifdef HAVE_WINDOW_SYSTEM
+ #include TERM_HEADER
+ #endif /* HAVE_WINDOW_SYSTEM */
  
  #ifndef FRAME_X_OUTPUT
  #define FRAME_X_OUTPUT(f) ((f)->output_data.x)
@@@ -426,11 -415,11 +415,11 @@@ Lisp_Object Qboth, Qboth_horiz, Qtext_i
  /* Non-zero means print newline to stdout before next mini-buffer
     message.  */
  
int noninteractive_need_newline;
bool noninteractive_need_newline;
  
  /* Non-zero means print newline to message log before next message.  */
  
- static int message_log_need_newline;
+ static bool message_log_need_newline;
  
  /* Three markers that message_dolog uses.
     It could allocate them itself, but that causes trouble
@@@ -489,7 -478,7 +478,7 @@@ Lisp_Object Qmenu_bar_update_hook
  
  /* Nonzero if an overlay arrow has been displayed in this window.  */
  
- static int overlay_arrow_seen;
+ static bool overlay_arrow_seen;
  
  /* Vector containing glyphs for an ellipsis `...'.  */
  
@@@ -511,7 -500,7 +500,7 @@@ static Lisp_Object Vmessage_stack
  /* Nonzero means multibyte characters were enabled when the echo area
     message was specified.  */
  
- static int message_enable_multibyte;
+ static bool message_enable_multibyte;
  
  /* Nonzero if we should redraw the mode lines on the next redisplay.  */
  
@@@ -522,14 -511,10 +511,10 @@@ int update_mode_lines
  
  int windows_or_buffers_changed;
  
- /* Nonzero means a frame's cursor type has been changed.  */
- static int cursor_type_changed;
  /* Nonzero after display_mode_line if %l was used and it displayed a
     line number.  */
  
- static int line_number_displayed;
+ static bool line_number_displayed;
  
  /* The name of the *Messages* buffer, a string.  */
  
@@@ -551,12 -536,12 +536,12 @@@ static Lisp_Object Vwith_echo_area_save
  /* Non-zero means display_echo_area should display the last echo area
     message again.  Set by redisplay_preserve_echo_area.  */
  
- static int display_last_displayed_message_p;
+ static bool display_last_displayed_message_p;
  
  /* Nonzero if echo area is being used by print; zero if being used by
     message.  */
  
- static int message_buf_print;
+ static bool message_buf_print;
  
  /* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable.  */
  
@@@ -566,7 -551,7 +551,7 @@@ static Lisp_Object Qmessage_truncate_li
  /* Set to 1 in clear_message to make redisplay_internal aware
     of an emptied echo area.  */
  
- static int message_cleared_p;
+ static bool message_cleared_p;
  
  /* A scratch glyph row with contents used for generating truncation
     glyphs.  Also used in direct_output_for_insert.  */
@@@ -581,13 -566,7 +566,7 @@@ static int last_height
  
  /* Non-zero if there's a help-echo in the echo area.  */
  
- int help_echo_showing_p;
- /* If >= 0, computed, exact values of mode-line and header-line height
-    to use in the macros CURRENT_MODE_LINE_HEIGHT and
-    CURRENT_HEADER_LINE_HEIGHT.  */
- int current_mode_line_height, current_header_line_height;
+ bool help_echo_showing_p;
  
  /* The maximum distance to look ahead for text properties.  Values
     that are too small let us call compute_char_face and similar
@@@ -763,7 -742,7 +742,7 @@@ Lisp_Object previous_help_echo_string
  #ifdef HAVE_WINDOW_SYSTEM
  
  /* Non-zero means an hourglass cursor is currently shown.  */
int hourglass_shown_p;
bool hourglass_shown_p;
  
  /* If non-null, an asynchronous timer that, when it expires, displays
     an hourglass cursor on all frames.  */
@@@ -933,11 -912,8 +912,8 @@@ static int in_ellipses_for_invisible_te
  #ifdef HAVE_WINDOW_SYSTEM
  
  static void x_consider_frame_title (Lisp_Object);
- static int tool_bar_lines_needed (struct frame *, int *);
  static void update_tool_bar (struct frame *, int);
- static void build_desired_tool_bar_string (struct frame *f);
  static int redisplay_tool_bar (struct frame *);
- static void display_tool_bar_line (struct it *, int);
  static void notice_overwritten_cursor (struct window *,
                                         enum glyph_row_area,
                                         int, int, int, int);
@@@ -1359,12 -1335,12 +1335,12 @@@ pos_visible_p (struct window *w, ptrdif
  
    /* Compute exact mode line heights.  */
    if (WINDOW_WANTS_MODELINE_P (w))
-     current_mode_line_height
+     w->mode_line_height
        = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
                           BVAR (current_buffer, mode_line_format));
  
    if (WINDOW_WANTS_HEADER_LINE_P (w))
-     current_header_line_height
+     w->header_line_height
        = display_mode_line (w, HEADER_LINE_FACE_ID,
                           BVAR (current_buffer, header_line_format));
  
    if (old_buffer)
      set_buffer_internal_1 (old_buffer);
  
-   current_header_line_height = current_mode_line_height = -1;
    if (visible_p && w->hscroll > 0)
      *x -=
        window_hscroll_limited (w, WINDOW_XFRAME (w))
@@@ -1908,8 -1882,7 +1882,7 @@@ pixel_to_glyph_coords (struct frame *f
     text, or we can't tell because W's current matrix is not up to
     date.  */
  
- static
- struct glyph *
+ static struct glyph *
  x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
                  int *dx, int *dy, int *area)
  {
@@@ -4500,8 -4473,8 +4473,8 @@@ setup_for_ellipsis (struct it *it, int 
    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->header.size;
+       it->dpvec = v->u.contents;
+       it->dpend = v->u.contents + v->header.size;
      }
    else
      {
@@@ -6688,17 -6661,59 +6661,59 @@@ lookup_glyphless_char_display (int c, s
    return glyphless_method;
  }
  
- /* 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.  */
+ /* Merge escape glyph face and cache the result.  */
  
  static struct frame *last_escape_glyph_frame = NULL;
  static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
  static int last_escape_glyph_merged_face_id = 0;
  
- struct frame *last_glyphless_glyph_frame = NULL;
- int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
- int last_glyphless_glyph_merged_face_id = 0;
+ static int
+ merge_escape_glyph_face (struct it *it)
+ {
+   int face_id;
+   if (it->f == last_escape_glyph_frame
+       && it->face_id == last_escape_glyph_face_id)
+     face_id = last_escape_glyph_merged_face_id;
+   else
+     {
+       /* Merge the `escape-glyph' face into the current face.  */
+       face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id);
+       last_escape_glyph_frame = it->f;
+       last_escape_glyph_face_id = it->face_id;
+       last_escape_glyph_merged_face_id = face_id;
+     }
+   return face_id;
+ }
+ /* Likewise for glyphless glyph face.  */
+ static struct frame *last_glyphless_glyph_frame = NULL;
+ static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+ static int last_glyphless_glyph_merged_face_id = 0;
+ int
+ merge_glyphless_glyph_face (struct it *it)
+ {
+   int face_id;
+   if (it->f == last_glyphless_glyph_frame
+       && it->face_id == last_glyphless_glyph_face_id)
+     face_id = last_glyphless_glyph_merged_face_id;
+   else
+     {
+       /* Merge the `glyphless-char' face into the current face.  */
+       face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+       last_glyphless_glyph_frame = it->f;
+       last_glyphless_glyph_face_id = it->face_id;
+       last_glyphless_glyph_merged_face_id = face_id;
+     }
+   return face_id;
+ }
+ /* 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.  */
  
  static int
  get_next_display_element (struct it *it)
              if (v->header.size)
                {
                  it->dpvec_char_len = it->len;
-                 it->dpvec = v->contents;
-                 it->dpend = v->contents + v->header.size;
+                 it->dpvec = v->u.contents;
+                 it->dpend = v->u.contents + v->header.size;
                  it->current.dpvec_index = 0;
                  it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
                      g = GLYPH_CODE_CHAR (gc);
                      lface_id = GLYPH_CODE_FACE (gc);
                    }
-                 if (lface_id)
-                   {
-                     face_id = merge_faces (it->f, Qt, lface_id, it->face_id);
-                   }
-                 else if (it->f == last_escape_glyph_frame
-                          && it->face_id == last_escape_glyph_face_id)
-                   {
-                     face_id = last_escape_glyph_merged_face_id;
-                   }
-                 else
-                   {
-                     /* Merge the escape-glyph face into the current face.  */
-                     face_id = merge_faces (it->f, Qescape_glyph, 0,
-                                            it->face_id);
-                     last_escape_glyph_frame = it->f;
-                     last_escape_glyph_face_id = it->face_id;
-                     last_escape_glyph_merged_face_id = face_id;
-                   }
+                 face_id = (lface_id
+                            ? merge_faces (it->f, Qt, lface_id, it->face_id)
+                            : merge_escape_glyph_face (it));
  
                  XSETINT (it->ctl_chars[0], g);
                  XSETINT (it->ctl_chars[1], c ^ 0100);
                  escape_glyph = GLYPH_CODE_CHAR (gc);
                  lface_id = GLYPH_CODE_FACE (gc);
                }
-             if (lface_id)
-               {
-                 /* The display table specified a face.
-                    Merge it into face_id and also into escape_glyph.  */
-                 face_id = merge_faces (it->f, Qt, lface_id,
-                                        it->face_id);
-               }
-             else if (it->f == last_escape_glyph_frame
-                      && it->face_id == last_escape_glyph_face_id)
-               {
-                 face_id = last_escape_glyph_merged_face_id;
-               }
-             else
-               {
-                 /* Merge the escape-glyph face into the current face.  */
-                 face_id = merge_faces (it->f, Qescape_glyph, 0,
-                                        it->face_id);
-                 last_escape_glyph_frame = it->f;
-                 last_escape_glyph_face_id = it->face_id;
-                 last_escape_glyph_merged_face_id = face_id;
-               }
+             face_id = (lface_id
+                        ? merge_faces (it->f, Qt, lface_id, it->face_id)
+                        : merge_escape_glyph_face (it));
  
              /* Draw non-ASCII hyphen with just highlighting: */
  
@@@ -9552,7 -9536,20 +9536,20 @@@ message_dolog (const char *m, ptrdiff_
  
        old_deactivate_mark = Vdeactivate_mark;
        oldbuf = current_buffer;
-       Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+       /* Ensure the Messages buffer exists, and switch to it.
+          If we created it, set the major-mode.  */
+       {
+         int newbuffer = 0;
+         if (NILP (Fget_buffer (Vmessages_buffer_name))) newbuffer = 1;
+         Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+         if (newbuffer &&
+             !NILP (Ffboundp (intern ("messages-buffer-mode"))))
+           call0 (intern ("messages-buffer-mode"));
+       }
        bset_undo_list (current_buffer, Qt);
  
        oldpoint = message_dolog_marker1;
@@@ -10778,11 -10775,9 +10775,9 @@@ clear_garbaged_frames (void
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
-               {
-                 redraw_frame (f);
-                 f->force_flush_display_p = 1;
-               }
-             clear_current_matrices (f);
+               redraw_frame (f);
+             else
+               clear_current_matrices (f);
              changed_count++;
              f->garbaged = 0;
              f->resized_p = 0;
@@@ -10870,7 -10865,7 +10865,7 @@@ echo_area_display (int update_frame_p
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
              update_single_window (w, 1);
-             FRAME_RIF (f)->flush_display (f);
+             flush_frame (f);
            }
          else
            update_frame (f, 1, 1);
@@@ -11458,10 -11453,6 +11453,6 @@@ update_menu_bar (struct frame *f, int s
  
  #ifdef HAVE_WINDOW_SYSTEM
  
- /* Where the mouse was last time we reported a mouse event.  */
- struct frame *last_mouse_frame;
  /* Tool-bar item index of the item on which a mouse button was pressed
     or -1.  */
  
@@@ -11579,6 -11570,7 +11570,7 @@@ update_tool_bar (struct frame *f, int s
      }
  }
  
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
  
  /* Set F->desired_tool_bar_string to a Lisp string representing frame
     F's desired tool-bar contents.  F->tool_bar_items must have
@@@ -11916,6 -11908,11 +11908,11 @@@ tool_bar_lines_needed (struct frame *f
    return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
  }
  
+ #endif /* !USE_GTK && !HAVE_NS */
+ #if defined USE_GTK || defined HAVE_NS
+ EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
+ #endif
  
  DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
         0, 1, 0,
  If FRAME is nil or omitted, use the selected frame.  */)
    (Lisp_Object frame)
  {
+   int nlines = 0;
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
    struct frame *f = decode_any_frame (frame);
    struct window *w;
-   int nlines = 0;
  
    if (WINDOWP (f->tool_bar_window)
        && (w = XWINDOW (f->tool_bar_window),
          nlines = tool_bar_lines_needed (f, NULL);
        }
      }
+ #endif
    return make_number (nlines);
  }
  
  static int
  redisplay_tool_bar (struct frame *f)
  {
-   struct window *w;
-   struct it it;
-   struct glyph_row *row;
  #if defined (USE_GTK) || defined (HAVE_NS)
    if (FRAME_EXTERNAL_TOOL_BAR (f))
      update_frame_tool_bar (f);
    return 0;
- #endif
+ #else /* !USE_GTK && !HAVE_NS */
+   struct window *w;
+   struct it it;
+   struct glyph_row *row;
  
    /* If frame hasn't a tool-bar window or if it is zero-height, don't
       do anything.  This means you must start with tool-bar-lines
          if (WINDOW_TOTAL_LINES (w) != old_height)
            {
              clear_glyph_matrix (w->desired_matrix);
-             fonts_changed_p = 1;
+             f->fonts_changed = 1;
              return 1;
            }
        }
                {
                  clear_glyph_matrix (w->desired_matrix);
                  f->n_tool_bar_rows = nrows;
-                 fonts_changed_p = 1;
+                 f->fonts_changed = 1;
                  return 1;
                }
            }
  
    f->minimize_tool_bar_window_p = 0;
    return 0;
+ #endif /* USE_GTK || HAVE_NS */
  }
  
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
  
  /* Get information about the tool-bar item which is displayed in GLYPH
     on frame F.  Return in *PROP_IDX the index where tool-bar item
@@@ -12279,7 -12282,7 +12282,7 @@@ note_tool_bar_highlight (struct frame *
  {
    Lisp_Object window = f->tool_bar_window;
    struct window *w = XWINDOW (window);
-   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
    Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
    int hpos, vpos;
    struct glyph *glyph;
    clear_mouse_face (hlinfo);
  
    /* Mouse is down, but on different tool-bar item?  */
-   mouse_down_p = (dpyinfo->grabbed
-                 && f == last_mouse_frame
-                 && FRAME_LIVE_P (f));
+   mouse_down_p = (x_mouse_grabbed (dpyinfo)
+                 && f == dpyinfo->last_mouse_frame);
    if (mouse_down_p
        && last_tool_bar_item != prop_idx)
      return;
      help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
  }
  
+ #endif /* !USE_GTK && !HAVE_NS */
  #endif /* HAVE_WINDOW_SYSTEM */
  
  
@@@ -12990,15 -12995,6 +12995,6 @@@ redisplay_internal (void
    last_glyphless_glyph_frame = NULL;
    last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
  
-   /* 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 face_change_count is non-zero, init_iterator will free all
       realized faces, which includes the faces referenced from current
       matrices.  So, we can't reuse current matrices in this case.  */
        struct frame *f = XFRAME (frame);
  
        if (FRAME_VISIBLE_P (f))
-       ++number_of_visible_frames;
+       {
+         ++number_of_visible_frames;
+         /* Adjust matrices for visible frames only.  */
+         if (f->fonts_changed)
+           {
+             adjust_frame_glyphs (f);
+             f->fonts_changed = 0;
+           }
+         /* If cursor type has been changed on the frame
+            other than selected, consider all frames.  */
+         if (f != sf && f->cursor_type_changed)
+           update_mode_lines++;
+       }
        clear_desired_matrices (f);
      }
  
      }
  
    consider_all_windows_p = (update_mode_lines
-                           || buffer_shared_and_changed ()
-                           || cursor_type_changed);
+                           || buffer_shared_and_changed ());
  
    /* If specs for an arrow have changed, do thorough redisplay
       to ensure we remove any arrow that should no longer exist.  */
        if (!display_last_displayed_message_p)
        message_cleared_p = 0;
  
-       if (fonts_changed_p)
-       goto retry;
-       else if (window_height_changed_p)
+       if (window_height_changed_p)
        {
          consider_all_windows_p = 1;
          ++update_mode_lines;
        && !current_buffer->prevent_redisplay_optimizations_p
        && FRAME_VISIBLE_P (XFRAME (w->frame))
        && !FRAME_OBSCURED_P (XFRAME (w->frame))
+       && !XFRAME (w->frame)->cursor_type_changed
        /* Make sure recorded data applies to current buffer, etc.  */
        && this_line_buffer == current_buffer
        && match_p
              && !EQ (FRAME_TTY (f)->top_frame, frame))
            continue;
  
+       retry_frame:
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
              /* Mark all the scroll bars to be removed; we'll redeem
              if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
                FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
  
-             /* If fonts changed, display again.  */
-             /* ??? rms: I suspect it is a mistake to jump all the way
-                back to retry here.  It should just retry this frame.  */
-             if (fonts_changed_p)
-               goto retry;
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                {
+                 /* If fonts changed on visible frame, display again.  */
+                 if (f->fonts_changed)
+                   {
+                     adjust_frame_glyphs (f);
+                     f->fonts_changed = 0;
+                     goto retry_frame;
+                   }
                  /* See if we have to hscroll.  */
                  if (!f->already_hscrolled_p)
                    {
                      f->already_hscrolled_p = 1;
                      if (hscroll_windows (f->root_window))
-                       goto retry;
+                       goto retry_frame;
                    }
  
                  /* Prevent various kinds of signals during display
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pending |= update_frame (f, 0, 0);
+                 f->cursor_type_changed = 0;
                  f->updated_p = 1;
                }
            }
  
      update:
        /* If fonts changed, display again.  */
-       if (fonts_changed_p)
+       if (sf->fonts_changed)
        goto retry;
  
        /* Prevent various kinds of signals during display update.
  
          XWINDOW (selected_window)->must_be_updated_p = 1;
          pending = update_frame (sf, 0, 0);
+         sf->cursor_type_changed = 0;
        }
  
        /* We may have called echo_area_display at the top of this
        {
          XWINDOW (mini_window)->must_be_updated_p = 1;
          pending |= update_frame (mini_frame, 0, 0);
+         mini_frame->cursor_type_changed = 0;
          if (!pending && hscroll_windows (mini_window))
            goto retry;
        }
  
        update_mode_lines = 0;
        windows_or_buffers_changed = 0;
-       cursor_type_changed = 0;
      }
  
    /* Start SIGIO interrupts coming again.  Having them off during the
@@@ -13649,9 -13661,7 +13661,7 @@@ redisplay_preserve_echo_area (int from_
    else
      redisplay_internal ();
  
-   if (FRAME_RIF (SELECTED_FRAME ()) != NULL
-       && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
-     FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
+   flush_frame (SELECTED_FRAME ());
  }
  
  
@@@ -14993,7 -15003,7 +15003,7 @@@ try_cursor_movement (Lisp_Object window
         cases.  */
        && !update_mode_lines
        && !windows_or_buffers_changed
-       && !cursor_type_changed
+       && !f->cursor_type_changed
        /* Can't use this case if highlighting a region.  When a
           region exists, cursor movement has to do more than just
           set the cursor.  */
@@@ -15340,9 -15350,8 +15350,8 @@@ set_vertical_scroll_bar (struct window 
  /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
     selected_window is redisplayed.
  
-    We can return without actually redisplaying the window if
-    fonts_changed_p.  In that case, redisplay_internal will
-    retry.  */
+    We can return without actually redisplaying the window if fonts has been
+    changed on window's frame.  In that case, redisplay_internal will retry.  */
  
  static void
  redisplay_window (Lisp_Object window, int just_this_one_p)
        debug_method_add (w, "try_window_id %d", tem);
  #endif
  
-       if (fonts_changed_p)
+       if (f->fonts_changed)
        goto need_larger_matrices;
        if (tem > 0)
        goto done;
          IF_DEBUG (debug_method_add (w, "1"));
          if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
            /* -1 means we need to scroll.
-              0 means we need new matrices, but fonts_changed_p
+              0 means we need new matrices, but fonts_changed
               is set in that case, so we will detect it below.  */
            goto try_to_scroll;
        }
  
-       if (fonts_changed_p)
+       if (f->fonts_changed)
        goto need_larger_matrices;
  
        if (w->cursor.vpos >= 0)
    /* Redisplay the window.  */
    if (!current_matrix_up_to_date_p
        || windows_or_buffers_changed
-       || cursor_type_changed
+       || f->cursor_type_changed
        /* Don't use try_window_reusing_current_matrix in this case
         because it can have changed the buffer.  */
        || !NILP (Vwindow_scroll_functions)
    /* 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)
+   if (f->fonts_changed)
      goto need_larger_matrices;
  
    /* If cursor did not appear assume that the middle of the window is
        if (WINDOW_WANTS_MODELINE_P (w)
          && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
        {
-         fonts_changed_p = 1;
+         f->fonts_changed = 1;
+         w->mode_line_height = -1;
          MATRIX_MODE_LINE_ROW (w->current_matrix)->height
            = DESIRED_MODE_LINE_HEIGHT (w);
        }
        if (WINDOW_WANTS_HEADER_LINE_P (w)
          && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
        {
-         fonts_changed_p = 1;
+         f->fonts_changed = 1;
+         w->header_line_height = -1;
          MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
            = DESIRED_HEADER_LINE_HEIGHT (w);
        }
  
-       if (fonts_changed_p)
+       if (f->fonts_changed)
        goto need_larger_matrices;
      }
  
      }
  #endif /* HAVE_WINDOW_SYSTEM */
  
-   /* We go to this label, with fonts_changed_p set,
-      if it is necessary to try again using larger glyph matrices.
+   /* We go to this label, with fonts_changed set, if it is
+      necessary to try again using larger glyph matrices.
       We have to redeem the scroll bar even in this case,
       because the loop in redisplay_internal expects that.  */
   need_larger_matrices:
@@@ -16269,7 -16280,7 +16280,7 @@@ try_window (Lisp_Object window, struct 
      {
        if (display_line (&it))
        last_text_row = it.glyph_row - 1;
-       if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
+       if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
        return 0;
      }
  
@@@ -16367,7 -16378,7 +16378,7 @@@ try_window_reusing_current_matrix (stru
        /* Don't try to reuse the display if windows have been split
         or such.  */
        || windows_or_buffers_changed
-       || cursor_type_changed)
+       || f->cursor_type_changed)
      return 0;
  
    /* Can't do this if region may have changed.  */
        w->cursor.vpos = -1;
        last_text_row = last_reused_text_row = NULL;
  
-       while (it.current_y < it.last_visible_y
-            && !fonts_changed_p)
+       while (it.current_y < it.last_visible_y && !f->fonts_changed)
        {
          /* If we have reached into the characters in the START row,
             that means the line boundaries have changed.  So we
        if (pt_row == NULL)
        w->cursor.vpos = -1;
        last_text_row = NULL;
-       while (it.current_y < it.last_visible_y && !fonts_changed_p)
+       while (it.current_y < it.last_visible_y && !f->fonts_changed)
        if (display_line (&it))
          last_text_row = it.glyph_row - 1;
  
@@@ -17139,7 -17149,7 +17149,7 @@@ try_window_id (struct window *w
      GIVE_UP (1);
  
    /* This flag is used to prevent redisplay optimizations.  */
-   if (windows_or_buffers_changed || cursor_type_changed)
+   if (windows_or_buffers_changed || f->cursor_type_changed)
      GIVE_UP (2);
  
    /* Verify that narrowing has not changed.
          row = row_containing_pos (w, PT, r0, NULL, 0);
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
-         else
-           emacs_abort ();
          return 1;
        }
      }
          row = row_containing_pos (w, PT, r0, NULL, 0);
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
-         else
-           emacs_abort ();
          return 2;
        }
      }
    last_text_row = NULL;
    overlay_arrow_seen = 0;
    while (it.current_y < it.last_visible_y
-        && !fonts_changed_p
+        && !f->fonts_changed
         && (first_unchanged_at_end_row == NULL
             || IT_CHARPOS (it) < stop_pos))
      {
        last_text_row = it.glyph_row - 1;
      }
  
-   if (fonts_changed_p)
+   if (f->fonts_changed)
      return -1;
  
  
  
        /* 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)
+       while (it.current_y < it.last_visible_y && !f->fonts_changed)
        {
          /* Is it always sure that the display agrees with lines in
             the current matrix?  I don't think so, so we mark rows
@@@ -19262,7 -19267,7 +19267,7 @@@ display_line (struct it *it
        >= it->w->desired_matrix->nrows)
      {
        it->w->nrows_scale_factor++;
-       fonts_changed_p = 1;
+       it->f->fonts_changed = 1;
        return 0;
      }
  
@@@ -20575,128 -20580,7 +20580,128 @@@ display_menu_bar (struct window *w
    compute_line_metrics (&it);
  }
  
 +#ifdef HAVE_MENUS
 +/* Deep copy of a glyph row, including the glyphs.  */
 +static void
 +deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
 +{
 +  int area, i, sum_used = 0;
 +  struct glyph *pointers[1 + LAST_AREA];
 +
 +  /* Save glyph pointers of TO.  */
 +  memcpy (pointers, to->glyphs, sizeof to->glyphs);
 +
 +  /* Do a structure assignment.  */
 +  *to = *from;
 +
 +  /* Restore original pointers of TO.  */
 +  memcpy (to->glyphs, pointers, sizeof to->glyphs);
  
 +  /* Count how many glyphs to copy and update glyph pointers.  */
 +  for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
 +    {
 +      if (area > LEFT_MARGIN_AREA)
 +      {
 +        eassert (from->glyphs[area] - from->glyphs[area - 1]
 +                 == from->used[area - 1]);
 +        to->glyphs[area] = to->glyphs[area - 1] + to->used[area - 1];
 +      }
 +      sum_used += from->used[area];
 +    }
 +
 +  /* Copy the glyphs.  */
 +  eassert (sum_used <= to->glyphs[LAST_AREA] - to->glyphs[LEFT_MARGIN_AREA]);
 +  for (i = 0; i < sum_used; i++)
 +    to->glyphs[LEFT_MARGIN_AREA][i] = from->glyphs[LEFT_MARGIN_AREA][i];
 +}
 +
 +/* Display one menu item on a TTY, by overwriting the glyphs in the
 +   desired glyph matrix with glyphs produced from the menu item text.
 +   Called from term.c to display TTY drop-down menus one item at a
 +   time.
 +
 +   ITEM_TEXT is the menu item text as a C string.
 +
 +   FACE_ID is the face ID to be used for this menu item.  FACE_ID
 +   could specify one of 3 faces: a face for an enabled item, a face
 +   for a disabled item, or a face for a selected item.
 +
 +   X and Y are coordinates of the first glyph in the desired matrix to
 +   be overwritten by the menu item.  Since this is a TTY, Y is the
 +   zero-based number of the glyph row and X is the zero-based glyph
 +   number in the row, starting from left, where to start displaying
 +   the item.
 +
 +   SUBMENU non-zero means this menu item drops down a submenu, which
 +   should be indicated by displaying a proper visual cue after the
 +   item text.  */
 +
 +void
 +display_tty_menu_item (const char *item_text, int width, int face_id,
 +                     int x, int y, int submenu)
 +{
 +  struct it it;
 +  struct frame *f = SELECTED_FRAME ();
 +  struct window *w = XWINDOW (f->selected_window);
 +  int saved_used, saved_truncated, saved_width, saved_reversed;
 +  struct glyph_row *row;
 +  size_t item_len = strlen (item_text);
 +
 +  eassert (FRAME_TERMCAP_P (f));
 +
 +  init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
 +  it.first_visible_x = 0;
 +  it.last_visible_x = FRAME_COLS (f) - 1;
 +  row = it.glyph_row;
 +  /* Start with the row contents from the current matrix.  */
 +  deep_copy_glyph_row (row, f->current_matrix->rows + y);
 +  saved_width = row->full_width_p;
 +  row->full_width_p = 1;
 +  saved_reversed = row->reversed_p;
 +  row->reversed_p = 0;
 +  row->enabled_p = 1;
 +
 +  /* Arrange for the menu item glyphs to start at (X,Y) and have the
 +     desired face.  */
 +  it.current_x = it.hpos = x;
 +  it.current_y = it.vpos = y;
 +  saved_used = row->used[TEXT_AREA];
 +  saved_truncated = row->truncated_on_right_p;
 +  row->used[TEXT_AREA] = x;
 +  it.face_id = face_id;
 +  it.line_wrap = TRUNCATE;
 +
 +  /* FIXME: This should be controlled by a user option.  See the
 +     comments in redisplay_tool_bar and display_mode_line about this.
 +     Also, if paragraph_embedding could ever be R2L, changes will be
 +     needed to avoid shifting to the right the row characters in
 +     term.c:append_glyph.  */
 +  it.paragraph_embedding = L2R;
 +
 +  /* Pad with a space on the left.  */
 +  display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
 +  width--;
 +  /* Display the menu item, pad with spaces to WIDTH.  */
 +  if (submenu)
 +    {
 +      display_string (item_text, Qnil, Qnil, 0, 0, &it,
 +                    item_len, 0, FRAME_COLS (f) - 1, -1);
 +      width -= item_len;
 +      /* Indicate with " >" that there's a submenu.  */
 +      display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
 +                    FRAME_COLS (f) - 1, -1);
 +    }
 +  else
 +    display_string (item_text, Qnil, Qnil, 0, 0, &it,
 +                  width, 0, FRAME_COLS (f) - 1, -1);
 +
 +  row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
 +  row->truncated_on_right_p = saved_truncated;
 +  row->hash = row_hash (row);
 +  row->full_width_p = saved_width;
 +  row->reversed_p = saved_reversed;
 +}
 +#endif        /* HAVE_MENUS */
  \f
  /***********************************************************************
                              Mode Line
@@@ -24111,12 -23995,12 +24116,12 @@@ draw_glyphs (struct window *w, int x, s
  
  #define IT_EXPAND_MATRIX_WIDTH(it, area)              \
    {                                                   \
-     if (!fonts_changed_p                              \
+     if (!it->f->fonts_changed                         \
        && (it->glyph_row->glyphs[area]                 \
            < it->glyph_row->glyphs[area + 1]))         \
        {                                                       \
        it->w->ncols_scale_factor++;                    \
-       fonts_changed_p = 1;                            \
+       it->f->fonts_changed = 1;                       \
        }                                                       \
    }
  
@@@ -25032,21 -24916,7 +25037,7 @@@ produce_glyphless_glyph (struct it *it
    base_height = it->ascent + it->descent;
    base_width = font->average_width;
  
-   /* Get a face ID for the glyph by utilizing a cache (the same way as
-      done for `escape-glyph' in get_next_display_element).  */
-   if (it->f == last_glyphless_glyph_frame
-       && it->face_id == last_glyphless_glyph_face_id)
-     {
-       face_id = last_glyphless_glyph_merged_face_id;
-     }
-   else
-     {
-       /* Merge the `glyphless-char' face into the current face.  */
-       face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
-       last_glyphless_glyph_frame = it->f;
-       last_glyphless_glyph_face_id = it->face_id;
-       last_glyphless_glyph_merged_face_id = face_id;
-     }
+   face_id = merge_glyphless_glyph_face (it);
  
    if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
      {
@@@ -26087,7 -25957,7 +26078,7 @@@ set_frame_cursor_types (struct frame *f
      FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
  
    /* Make sure the cursor gets redrawn.  */
-   cursor_type_changed = 1;
+   f->cursor_type_changed = 1;
  }
  
  
@@@ -26138,7 -26008,7 +26129,7 @@@ get_window_cursor_type (struct window *
  
    /* Detect a nonselected window or nonselected frame.  */
    else if (w != XWINDOW (f->selected_window)
-          || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
+          || f != FRAME_DISPLAY_INFO (f)->x_highlight_frame)
      {
        *active_cursor = 0;
  
@@@ -26835,10 -26705,13 +26826,13 @@@ show_mouse_face (Mouse_HLInfo *hlinfo, 
    /* Change the mouse cursor.  */
    if (FRAME_WINDOW_P (f))
      {
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
        if (draw == DRAW_NORMAL_TEXT
          && !EQ (hlinfo->mouse_face_window, f->tool_bar_window))
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
-       else if (draw == DRAW_MOUSE_FACE)
+       else
+ #endif
+       if (draw == DRAW_MOUSE_FACE)
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
        else
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
@@@ -27507,7 -27380,7 +27501,7 @@@ fast_find_string_pos (struct window *w
  #endif        /* not used */
  
  /* Find the positions of the first and the last glyphs in window W's
-    current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT
+    current matrix that occlude positions [STARTPOS..ENDPOS) in OBJECT
     (assumed to be a string), and return in HLINFO's mouse_face_*
     members the pixel and column/row coordinates of those glyphs.  */
  
@@@ -27523,7 -27396,7 +27517,7 @@@ mouse_face_from_string_pos (struct wind
    int found = 0;
  
    /* Find the glyph row with at least one position in the range
-      [STARTPOS..ENDPOS], and the first glyph in that row whose
+      [STARTPOS..ENDPOS), and the first glyph in that row whose
       position belongs to that range.  */
    for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
         r->enabled_p && r->y < yb;
          e = g + r->used[TEXT_AREA];
          for (gx = r->x; g < e; gx += g->pixel_width, ++g)
            if (EQ (g->object, object)
-               && startpos <= g->charpos && g->charpos <= endpos)
+               && startpos <= g->charpos && g->charpos < endpos)
              {
                hlinfo->mouse_face_beg_row
                  = MATRIX_ROW_VPOS (r, w->current_matrix);
          g = e + r->used[TEXT_AREA];
          for ( ; g > e; --g)
            if (EQ ((g-1)->object, object)
-               && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos)
+               && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
              {
                hlinfo->mouse_face_beg_row
                  = MATRIX_ROW_VPOS (r, w->current_matrix);
        found = 0;
        for ( ; g < e; ++g)
        if (EQ (g->object, object)
-           && startpos <= g->charpos && g->charpos <= endpos)
+           && startpos <= g->charpos && g->charpos < endpos)
          {
            found = 1;
            break;
        e = g + r->used[TEXT_AREA];
        for ( ; e > g; --e)
        if (EQ ((e-1)->object, object)
-           && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos)
+           && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
          break;
        hlinfo->mouse_face_end_col = e - g;
  
        for (gx = r->x ; e < g; ++e)
        {
          if (EQ (e->object, object)
-             && startpos <= e->charpos && e->charpos <= endpos)
+             && startpos <= e->charpos && e->charpos < endpos)
            break;
          gx += e->pixel_width;
        }
@@@ -27682,7 -27555,7 +27676,7 @@@ on_hot_spot_p (Lisp_Object hot_spot, in
        if (VECTORP (XCDR (hot_spot)))
        {
          struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
-         Lisp_Object *poly = v->contents;
+         Lisp_Object *poly = v->u.contents;
          ptrdiff_t n = v->header.size;
          ptrdiff_t i;
          int inside = 0;
@@@ -27788,7 -27661,7 +27782,7 @@@ define_frame_cursor1 (struct frame *f, 
        cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
  #ifdef HAVE_X_WINDOWS
        else if (EQ (pointer, intern ("vdrag")))
-       cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+       cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
  #endif
        else if (EQ (pointer, intern ("hourglass")))
        cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
@@@ -27951,7 -27824,7 +27945,7 @@@ note_mode_line_or_margin_highlight (Lis
        /* Change the mouse pointer according to what is under it.  */
        if (FRAME_WINDOW_P (f))
        {
-         dpyinfo = FRAME_X_DISPLAY_INFO (f);
+         dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
              cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
            }
          else
            /* Default mode-line pointer.  */
-           cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+           cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
  #endif
      }
@@@ -28176,7 -28049,7 +28170,7 @@@ note_mouse_highlight (struct frame *f, 
    w = XWINDOW (window);
    frame_to_window_pixel_xy (w, &x, &y);
  
- #ifdef HAVE_WINDOW_SYSTEM
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
    /* Handle tool-bar window differently since it doesn't display a
       buffer.  */
    if (EQ (window, f->tool_bar_window))
              if (NILP (s))
                s = make_number (0);
              if (NILP (e))
-               e = make_number (SCHARS (object) - 1);
+               e = make_number (SCHARS (object));
              mouse_face_from_string_pos (w, hlinfo, object,
                                          XINT (s), XINT (e));
              hlinfo->mouse_face_past_end = 0;
@@@ -29089,9 -28962,11 +29083,11 @@@ expose_frame (struct frame *f, int x, i
    TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
    mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
  
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
    if (WINDOWP (f->tool_bar_window))
      mouse_face_overwritten_p
        |= expose_window (XWINDOW (f->tool_bar_window), &r);
+ #endif
  
  #ifdef HAVE_X_WINDOWS
  #ifndef MSDOS
@@@ -29817,8 -29692,6 +29813,6 @@@ Its value should be an ASCII acronym st
  void
  init_xdisp (void)
  {
-   current_header_line_height = current_mode_line_height = -1;
    CHARPOS (this_line_start_pos) = 0;
  
    if (!noninteractive)
diff --combined src/xmenu.c
@@@ -498,7 -498,7 +498,7 @@@ If FRAME is nil or not given, use the s
        memset (&ev, 0, sizeof ev);
        ev.xbutton.display = FRAME_X_DISPLAY (f);
        ev.xbutton.window = XtWindow (menubar);
-       ev.xbutton.root = FRAME_X_DISPLAY_INFO (f)->root_window;
+       ev.xbutton.root = FRAME_DISPLAY_INFO (f)->root_window;
        ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
        ev.xbutton.button = Button1;
        ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
@@@ -990,7 -990,7 +990,7 @@@ set_frame_menubar (struct frame *f, boo
  
        /* Save the frame's previous menu bar contents data.  */
        if (previous_menu_items_used)
-       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->u.contents,
                previous_menu_items_used * word_size);
  
        /* Fill in menu_items with the current menu bar contents.
@@@ -1367,7 -1367,7 +1367,7 @@@ menu_position_func (GtkMenu *menu, gin
  {
    struct next_popup_x_y *data = user_data;
    GtkRequisition req;
-   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
+   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (data->f);
    int disp_width = x_display_pixel_width (dpyinfo);
    int disp_height = x_display_pixel_height (dpyinfo);
  
@@@ -1449,7 -1449,7 +1449,7 @@@ create_and_show_popup_menu (struct fram
    if (for_click)
      {
        for (i = 0; i < 5; i++)
-         if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+         if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
            break;
      }
  
  
    /* Must reset this manually because the button release event is not passed
       to Emacs event loop. */
-   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+   FRAME_DISPLAY_INFO (f)->grabbed = 0;
  }
  
  #else /* not USE_GTK */
@@@ -1543,7 -1543,7 +1543,7 @@@ create_and_show_popup_menu (struct fram
    event->send_event = 0;
    event->display = FRAME_X_DISPLAY (f);
    event->time = CurrentTime;
-   event->root = FRAME_X_DISPLAY_INFO (f)->root_window;
+   event->root = FRAME_DISPLAY_INFO (f)->root_window;
    event->window = event->subwindow = event->root;
    event->x = x;
    event->y = y;
    event->state = 0;
    event->button = 0;
    for (i = 0; i < 5; i++)
-     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+     if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
        event->button = i;
  
    /* Don't allow any geometry request from the user.  */
                                    make_number (menu_id & ~(-1 << (fact)))));
  
      /* Process events that apply to the menu.  */
-     popup_get_selection (0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
+     popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
  
      unbind_to (specpdl_count, Qnil);
    }
@@@ -1618,8 -1618,6 +1618,8 @@@ xmenu_show (struct frame *f, int x, in
        return Qnil;
      }
  
 +  block_input ();
 +
    /* Create a tree of widget_value objects
       representing the panes and their items.  */
    wv = xmalloc_widget_value ();
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
 +                unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
        }
      }
    else if (!for_click)
 -    /* Make "Cancel" equivalent to C-g.  */
 -    Fsignal (Qquit, Qnil);
 +    {
 +      unblock_input ();
 +      /* Make "Cancel" equivalent to C-g.  */
 +      Fsignal (Qquit, Qnil);
 +    }
  
 +  unblock_input ();
    return Qnil;
  }
  \f
@@@ -1969,7 -1962,7 +1969,7 @@@ create_and_show_dialog (struct frame *f
                             Fcons (make_number (dialog_id >> (fact)),
                                    make_number (dialog_id & ~(-1 << (fact)))));
  
-     popup_get_selection (0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
+     popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
  
      unbind_to (count, Qnil);
    }
@@@ -2194,7 -2187,7 +2194,7 @@@ menu_help_callback (char const *help_st
    Lisp_Object pane_name;
    Lisp_Object menu_object;
  
-   first_item = XVECTOR (menu_items)->contents;
+   first_item = XVECTOR (menu_items)->u.contents;
    if (EQ (first_item[0], Qt))
      pane_name = first_item[MENU_ITEMS_PANE_NAME];
    else if (EQ (first_item[0], Qquote))
@@@ -2225,13 -2218,13 +2225,13 @@@ pop_down_menu (Lisp_Object arg
  #ifdef HAVE_X_WINDOWS
    /* Assume the mouse has moved out of the X window.
       If it has actually moved in, we will get an EnterNotify.  */
-   x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
+   x_mouse_leave (FRAME_DISPLAY_INFO (f));
  
    /* State that no mouse buttons are now held.
       (The oldXMenu code doesn't track this info for us.)
       That is not necessarily true, but the fiction leads to reasonable
       results, and it is a pain to ask which are actually held now.  */
-   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+   FRAME_DISPLAY_INFO (f)->grabbed = 0;
  
  #endif /* HAVE_X_WINDOWS */
  
@@@ -2268,8 -2261,6 +2268,8 @@@ xmenu_show (struct frame *f, int x, in
        return Qnil;
      }
  
 +  block_input ();
 +
    /* Figure out which root window F is on.  */
    XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
                &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
    if (menu == NULL)
      {
        *error_name = "Can't create menu";
 +      unblock_input ();
        return Qnil;
      }
  
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
 +            unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_PANE_LENGTH;
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
 +            unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
        /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
         the menu was invoked with a mouse event as POSITION).  */
        if (! for_click)
 -        Fsignal (Qquit, Qnil);
 +      {
 +        unblock_input ();
 +        Fsignal (Qquit, Qnil);
 +      }
        break;
      }
  
 +  unblock_input ();
    unbind_to (specpdl_count, Qnil);
  
    return entry;