]> code.delx.au - gnu-emacs/blobdiff - src/w32fns.c
Merge from origin/emacs-24
[gnu-emacs] / src / w32fns.c
index 412e91e045e339387af4b7c978c7e1c177a68d53..deda2eab26d5edee7d3b460b408a1596fb8e2429 100644 (file)
@@ -89,27 +89,10 @@ extern void w32_free_menu_strings (HWND);
 extern const char *map_w32_filename (const char *, const char **);
 extern char * w32_strerror (int error_no);
 
-/* If non-NULL, a handle to a frame where to display the hourglass cursor.  */
-static HWND hourglass_hwnd = NULL;
-
 #ifndef IDC_HAND
 #define IDC_HAND MAKEINTRESOURCE(32649)
 #endif
 
-Lisp_Object Qsuppress_icon;
-Lisp_Object Qundefined_color;
-Lisp_Object Qcancel_timer;
-Lisp_Object Qfont_param;
-Lisp_Object Qhyper;
-Lisp_Object Qsuper;
-Lisp_Object Qmeta;
-Lisp_Object Qalt;
-Lisp_Object Qctrl;
-Lisp_Object Qcontrol;
-Lisp_Object Qshift;
-static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
-
-
 /* Prefix for system colors.  */
 #define SYSTEM_COLOR_PREFIX "System"
 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
@@ -228,16 +211,12 @@ static int w32_unicode_gui;
 
 /* From w32menu.c  */
 extern HMENU current_popup_menu;
-static int menubar_in_use = 0;
+int menubar_in_use = 0;
 
 /* From w32uniscribe.c  */
 extern void syms_of_w32uniscribe (void);
 extern int uniscribe_available;
 
-/* Function prototypes for hourglass support.  */
-static void w32_show_hourglass (struct frame *);
-static void w32_hide_hourglass (void);
-
 #ifdef WINDOWSNT
 /* From w32inevt.c */
 extern int faked_key;
@@ -271,9 +250,9 @@ static unsigned int sound_type = 0xFFFFFFFF;
    the first display on the list.  */
 
 struct w32_display_info *
-check_x_display_info (Lisp_Object frame)
+check_x_display_info (Lisp_Object object)
 {
-  if (NILP (frame))
+  if (NILP (object))
     {
       struct frame *sf = XFRAME (selected_frame);
 
@@ -282,14 +261,23 @@ check_x_display_info (Lisp_Object frame)
       else
        return &one_w32_display_info;
     }
-  else if (STRINGP (frame))
-    return x_display_info_for_name (frame);
+  else if (TERMINALP (object))
+    {
+      struct terminal *t = decode_live_terminal (object);
+
+      if (t->type != output_w32)
+        error ("Terminal %d is not a W32 display", t->id);
+
+      return t->display_info.w32;
+    }
+  else if (STRINGP (object))
+    return x_display_info_for_name (object);
   else
     {
       struct frame *f;
 
-      CHECK_LIVE_FRAME (frame);
-      f = XFRAME (frame);
+      CHECK_LIVE_FRAME (object);
+      f = XFRAME (object);
       if (! FRAME_W32_P (f))
        error ("Non-W32 frame used");
       return FRAME_DISPLAY_INFO (f);
@@ -336,8 +324,7 @@ void x_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
 void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
 void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
 void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
-
-
+void x_set_internal_border_width (struct frame *f, Lisp_Object, Lisp_Object);
 \f
 
 /* Store the screen positions of frame F into XPTR and YPTR.
@@ -723,8 +710,7 @@ w32_default_color_map (void)
 
   cmap = Qnil;
 
-  for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
-       pc++, i++)
+  for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++)
     cmap = Fcons (Fcons (build_string (pc->name),
                         make_number (pc->colorref)),
                  cmap);
@@ -1147,7 +1133,8 @@ gamma_correct (struct frame *f, COLORREF *color)
    If ALLOC is nonzero, allocate a new colormap cell.  */
 
 int
-w32_defined_color (struct frame *f, const char *color, XColor *color_def, int alloc)
+w32_defined_color (struct frame *f, const char *color, XColor *color_def,
+                  bool alloc_p)
 {
   register Lisp_Object tem;
   COLORREF w32_color_ref;
@@ -1181,7 +1168,7 @@ w32_defined_color (struct frame *f, const char *color, XColor *color_def, int al
              entry = entry->next;
            }
 
-         if (entry == NULL && alloc)
+         if (entry == NULL && alloc_p)
            {
              /* not already mapped, so add to list */
              entry = xmalloc (sizeof (struct w32_palette_entry));
@@ -1234,7 +1221,7 @@ x_decode_color (struct frame *f, Lisp_Object arg, int def)
 
   /* w32_defined_color is responsible for coping with failures
      by looking for a near-miss.  */
-  if (w32_defined_color (f, SDATA (arg), &cdef, 1))
+  if (w32_defined_color (f, SDATA (arg), &cdef, true))
     return cdef.pixel;
 
   /* defined_color failed; return an ultimate default.  */
@@ -1370,23 +1357,23 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     {
       CHECK_NUMBER (Vx_window_horizontal_drag_shape);
       horizontal_drag_cursor
-       = XCreateFontCursor (FRAME_X_DISPLAY (f),
+       = XCreateFontCursor (FRAME_W32_DISPLAY (f),
                             XINT (Vx_window_horizontal_drag_shape));
     }
   else
     horizontal_drag_cursor
-      = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+      = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
 
   if (!NILP (Vx_window_vertical_drag_shape))
     {
       CHECK_NUMBER (Vx_window_vertical_drag_shape);
       vertical_drag_cursor
-       = XCreateFontCursor (FRAME_X_DISPLAY (f),
+       = XCreateFontCursor (FRAME_W32_DISPLAY (f),
                             XINT (Vx_window_vertical_drag_shape));
     }
   else
     vertical_drag_cursor
-      = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_v_double_arrow);
+      = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_v_double_arrow);
 
   /* Check and report errors with the above calls.  */
   x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
@@ -1538,7 +1525,7 @@ x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 void
 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
-  int result;
+  bool result;
 
   if (NILP (arg) && NILP (oldval))
     return;
@@ -1608,8 +1595,53 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   unblock_input ();
 #endif
 }
-
 \f
+void
+x_clear_under_internal_border (struct frame *f)
+{
+  int border = FRAME_INTERNAL_BORDER_WIDTH (f);
+
+  /* Clear border if it's larger than before.  */
+  if (border != 0)
+    {
+      HDC hdc = get_frame_dc (f);
+      int width = FRAME_PIXEL_WIDTH (f);
+      int height = FRAME_PIXEL_HEIGHT (f);
+
+      block_input ();
+      w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
+      w32_clear_area (f, hdc, 0, 0, border, height);
+      w32_clear_area (f, hdc, width - border, 0, border, height);
+      w32_clear_area (f, hdc, 0, height - border, width, border);
+      release_frame_dc (f, hdc);
+      unblock_input ();
+    }
+}
+
+
+void
+x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+  int border;
+
+  CHECK_TYPE_RANGED_INTEGER (int, arg);
+  border = max (XINT (arg), 0);
+
+  if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
+    {
+      FRAME_INTERNAL_BORDER_WIDTH (f) = border;
+
+      if (FRAME_X_WINDOW (f) != 0)
+       {
+         adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
+
+         if (FRAME_VISIBLE_P (f))
+           x_clear_under_internal_border (f);
+       }
+    }
+}
+
+
 void
 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
@@ -1630,7 +1662,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   FRAME_MENU_BAR_LINES (f) = 0;
   FRAME_MENU_BAR_HEIGHT (f) = 0;
   if (nlines)
-    FRAME_EXTERNAL_MENU_BAR (f) = 1;
+    {
+      FRAME_EXTERNAL_MENU_BAR (f) = 1;
+      windows_or_buffers_changed = 23;
+    }
   else
     {
       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
@@ -1639,11 +1674,16 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 
       /* Adjust the frame size so that the client (text) dimensions
         remain the same.  This depends on FRAME_EXTERNAL_MENU_BAR being
-        set correctly.  */
-      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
-      do_pending_window_change (0);
+        set correctly.  Note that we resize twice: The first time upon
+        a request from the window manager who wants to keep the height
+        of the outer rectangle (including decorations) unchanged, and a
+        second time because we want to keep the height of the inner
+        rectangle (without the decorations unchanged).  */
+      adjust_frame_size (f, -1, -1, 2, true, Qmenu_bar_lines);
+
+      /* Not sure whether this is needed.  */
+      x_clear_under_internal_border (f);
     }
-  adjust_frame_glyphs (f);
 }
 
 
@@ -1657,8 +1697,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 void
 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
-  int delta, nlines, root_height;
-  int unit = FRAME_LINE_HEIGHT (f);
+  int nlines;
 
   /* Treat tool bars like menu bars.  */
   if (FRAME_MINIBUF_ONLY_P (f))
@@ -1670,66 +1709,54 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   else
     nlines = 0;
 
-  /* Make sure we redisplay all windows in this frame.  */
-  windows_or_buffers_changed = 23;
+  x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+}
 
-  /* DELTA is in pixels now.  */
-  delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit;
 
-  /* Don't resize the tool-bar to more than we have room for.  Note: The
-     calculations below and the subsequent call to resize_frame_windows
-     are inherently flawed because they can make the toolbar higher than
-     the containing frame.  */
-  if (delta > 0)
-    {
-      root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)));
-      if (root_height - delta < unit)
-       {
-         delta = root_height - unit;
-         /* When creating a new frame and toolbar mode is enabled, we
-            need at least one toolbar line.  */
-         nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1);
-       }
-    }
+/* Set the pixel height of the tool bar of frame F to HEIGHT.  */
+void
+x_change_tool_bar_height (struct frame *f, int height)
+{
+  Lisp_Object frame;
+  int unit = FRAME_LINE_HEIGHT (f);
+  int old_height = FRAME_TOOL_BAR_HEIGHT (f);
+  int lines = (height + unit - 1) / unit;
+  int old_text_height = FRAME_TEXT_HEIGHT (f);
 
-  FRAME_TOOL_BAR_LINES (f) = nlines;
-  FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
-  ++windows_or_buffers_changed;
-  resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1);
-  adjust_frame_glyphs (f);
+  /* Make sure we redisplay all windows in this frame.  */
+  windows_or_buffers_changed = 23;
+
+  /* Recalculate tool bar and frame text sizes.  */
+  FRAME_TOOL_BAR_HEIGHT (f) = height;
+  FRAME_TOOL_BAR_LINES (f) = lines;
+  /* Store `tool-bar-lines' and `height' frame parameters.  */
+  store_frame_param (f, Qtool_bar_lines, make_number (lines));
+  store_frame_param (f, Qheight, make_number (FRAME_LINES (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
-     tool bar disappears.  This is so because the internal border is
-     below the tool bar if one is displayed, but is below the menu bar
-     if there isn't a tool bar.  The tool bar draws into the area
-     below the menu bar.  */
   if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
     {
       clear_frame (f);
       clear_current_matrices (f);
     }
 
-  /* If the tool bar gets smaller, the internal border below it
-     has to be cleared.  It was formerly part of the display
-     of the larger tool bar, and updating windows won't clear it.  */
-  if (FRAME_INTERNAL_BORDER_WIDTH (f) != 0 && FRAME_VISIBLE_P (f))
-    {
-      int height = FRAME_INTERNAL_BORDER_WIDTH (f);
-      int width = FRAME_PIXEL_WIDTH (f);
-      int y = nlines * unit;
-      HDC hdc = get_frame_dc (f);
+  if ((height < old_height) && WINDOWP (f->tool_bar_window))
+    clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
 
-      block_input ();
-      w32_clear_area (f, hdc, 0, y, width, height);
-      release_frame_dc (f, hdc);
-      unblock_input ();
-    }
+  /* Recalculate toolbar height.  */
+  f->n_tool_bar_rows = 0;
 
-  if (delta < 0 && WINDOWP (f->tool_bar_window))
-    clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+  adjust_frame_size (f, -1, -1,
+                    (!f->tool_bar_redisplayed_once ? 1
+                     : (old_height == 0 || height == 0) ? 2
+                     : 4),
+                    false, Qtool_bar_lines);
 
-  run_window_configuration_change_hook (f);
+  /* adjust_frame_size might not have done anything, garbage frame
+     here.  */
+  adjust_frame_glyphs (f);
+  SET_FRAME_GARBAGED (f);
+  if (FRAME_X_WINDOW (f))
+    x_clear_under_internal_border (f);
 }
 
 
@@ -1745,7 +1772,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
        F->explicit_name is set, ignore the new name; otherwise, set it.  */
 
 void
-x_set_name (struct frame *f, Lisp_Object name, int explicit)
+x_set_name (struct frame *f, Lisp_Object name, bool explicit)
 {
   /* Make sure that requests from lisp code override requests from
      Emacs redisplay code.  */
@@ -1800,7 +1827,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
 void
 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
-  x_set_name (f, arg, 1);
+  x_set_name (f, arg, true);
 }
 
 /* This function should be called by Emacs redisplay code to set the
@@ -1809,7 +1836,7 @@ x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 void
 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
-  x_set_name (f, arg, 0);
+  x_set_name (f, arg, false);
 }
 \f
 /* Change the title of frame F to NAME.
@@ -1848,6 +1875,16 @@ x_set_scroll_bar_default_width (struct frame *f)
     = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
 }
 
+
+void
+x_set_scroll_bar_default_height (struct frame *f)
+{
+  int unit = FRAME_LINE_HEIGHT (f);
+
+  FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
+  FRAME_CONFIG_SCROLL_BAR_LINES (f)
+    = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
+}
 \f
 /* Subroutines for creating a frame.  */
 
@@ -1902,7 +1939,7 @@ w32_init_class (HINSTANCE hinst)
 }
 
 static HWND
-w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
+w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
 {
   return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
                       /* Position and size of scroll bar.  */
@@ -1910,6 +1947,15 @@ w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
                       FRAME_W32_WINDOW (f), NULL, hinst, NULL);
 }
 
+static HWND
+w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
+{
+  return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE,
+                      /* Position and size of scroll bar.  */
+                      bar->left, bar->top, bar->width, bar->height,
+                      FRAME_W32_WINDOW (f), NULL, hinst, NULL);
+}
+
 static void
 w32_createwindow (struct frame *f, int *coords)
 {
@@ -1956,7 +2002,8 @@ w32_createwindow (struct frame *f, int *coords)
       SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
       SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
       SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
-      SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+      SetWindowLong (hwnd, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+      SetWindowLong (hwnd, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
       SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
 
       /* Enable drag-n-drop.  */
@@ -2371,7 +2418,8 @@ w32_name_of_message (UINT msg)
       M (WM_EMACS_KILL),
       M (WM_EMACS_CREATEWINDOW),
       M (WM_EMACS_DONE),
-      M (WM_EMACS_CREATESCROLLBAR),
+      M (WM_EMACS_CREATEVSCROLLBAR),
+      M (WM_EMACS_CREATEHSCROLLBAR),
       M (WM_EMACS_SHOWWINDOW),
       M (WM_EMACS_SETWINDOWPOS),
       M (WM_EMACS_DESTROYWINDOW),
@@ -2388,6 +2436,7 @@ w32_name_of_message (UINT msg)
       M (WM_EMACS_SHOW_CARET),
       M (WM_EMACS_HIDE_CARET),
       M (WM_EMACS_SETCURSOR),
+      M (WM_EMACS_SHOWCURSOR),
       M (WM_EMACS_PAINT),
       M (WM_CHAR),
 #undef M
@@ -2495,7 +2544,7 @@ w32_msg_pump (deferred_msg * msg_buf)
                  thread-safe.  The next line is okay because the cons
                  cell is never made into garbage and is not relocated by
                  GC.  */
-             XSETCAR (XIL ((EMACS_INT) msg.lParam), Qnil);
+             XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil);
              if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
                emacs_abort ();
              break;
@@ -2503,16 +2552,10 @@ w32_msg_pump (deferred_msg * msg_buf)
              {
                int vk_code = (int) msg.wParam;
                int cur_state = (GetKeyState (vk_code) & 1);
-               Lisp_Object new_state = XIL ((EMACS_INT) msg.lParam);
-
-               /* NB: This code must be thread-safe.  It is safe to
-                   call NILP because symbols are not relocated by GC,
-                   and pointer here is not touched by GC (so the markbit
-                   can't be set).  Numbers are safe because they are
-                   immediate values.  */
-               if (NILP (new_state)
-                   || (NUMBERP (new_state)
-                       && ((XUINT (new_state)) & 1) != cur_state))
+               int new_state = msg.lParam;
+
+               if (new_state == -1
+                   || ((new_state & 1) != cur_state))
                  {
                    one_w32_display_info.faked_key = vk_code;
 
@@ -3446,6 +3489,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
          track_mouse_event_fn (&tme);
          track_mouse_window = hwnd;
        }
+    case WM_HSCROLL:
     case WM_VSCROLL:
       if (w32_mouse_move_interval <= 0
          || (msg == WM_MOUSEMOVE && button_state == 0))
@@ -3784,10 +3828,14 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       return 0;
 
     case WM_WINDOWPOSCHANGING:
-      /* Don't restrict the sizing of tip frames.  */
-      if (frame_resize_pixelwise || hwnd == tip_window)
-       return 0;
+      /* Don't restrict the sizing of any kind of frames.  If the window
+        manager doesn't, there's no reason to do it ourselves.  */
+#if 0
+        if (frame_resize_pixelwise || hwnd == tip_window)
+#endif
+         return 0;
 
+#if 0
       /* Don't restrict the sizing of fullscreened frames, allowing them to be
          flush with the sides of the screen.  */
       f = x_window_to_frame (dpyinfo, hwnd);
@@ -3810,7 +3858,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            DWORD font_width;
            DWORD line_height;
            DWORD internal_border;
-           DWORD scrollbar_extra;
+           DWORD vscrollbar_extra;
+           DWORD hscrollbar_extra;
            RECT wr;
 
            wp.length = sizeof (wp);
@@ -3821,7 +3870,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
            line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
            internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
-           scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
+           vscrollbar_extra = GetWindowLong (hwnd, WND_VSCROLLBAR_INDEX);
+           hscrollbar_extra = GetWindowLong (hwnd, WND_HSCROLLBAR_INDEX);
 
            leave_crit ();
 
@@ -3832,10 +3882,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            /* Force width and height of client area to be exact
               multiples of the character cell dimensions.  */
            wdiff = (lppos->cx - (rect.right - rect.left)
-                    - 2 * internal_border - scrollbar_extra)
+                    - 2 * internal_border - vscrollbar_extra)
              % font_width;
            hdiff = (lppos->cy - (rect.bottom - rect.top)
-                    - 2 * internal_border)
+                    - 2 * internal_border - hscrollbar_extra)
              % line_height;
 
            if (wdiff || hdiff)
@@ -3870,6 +3920,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       }
 
       goto dflt;
+#endif
 
     case WM_GETMINMAXINFO:
       /* Hack to allow resizing the Emacs frame above the screen size.
@@ -3904,9 +3955,20 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
        return 0;
       }
 
-    case WM_EMACS_CREATESCROLLBAR:
-      return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
-                                           (struct scroll_bar *) lParam);
+    case WM_EMACS_SHOWCURSOR:
+      {
+       ShowCursor ((BOOL) wParam);
+
+       return 0;
+      }
+
+    case WM_EMACS_CREATEVSCROLLBAR:
+      return (LRESULT) w32_createvscrollbar ((struct frame *) wParam,
+                                            (struct scroll_bar *) lParam);
+
+    case WM_EMACS_CREATEHSCROLLBAR:
+      return (LRESULT) w32_createhscrollbar ((struct frame *) wParam,
+                                            (struct scroll_bar *) lParam);
 
     case WM_EMACS_SHOWWINDOW:
       return ShowWindow ((HWND) wParam, (WPARAM) lParam);
@@ -4126,7 +4188,8 @@ my_create_tip_window (struct frame *f)
       SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
 
       /* Tip frames have no scrollbars.  */
-      SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
+      SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0);
+      SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0);
 
       /* Do this to discard the default setting specified by our parent. */
       ShowWindow (tip_window, SW_HIDE);
@@ -4137,7 +4200,7 @@ my_create_tip_window (struct frame *f)
 /* Create and set up the w32 window for frame F.  */
 
 static void
-w32_window (struct frame *f, long window_prompting, int minibuffer_only)
+w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
 {
   block_input ();
 
@@ -4146,7 +4209,7 @@ w32_window (struct frame *f, long window_prompting, int minibuffer_only)
      for the window manager, so GC relocation won't bother it.
 
      Elsewhere we specify the window name for the window manager.  */
-  f->namebuf = xstrdup (SSDATA (Vx_resource_name));
+  f->namebuf = xlispstrdup (Vx_resource_name);
 
   my_create_window (f);
 
@@ -4356,9 +4419,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   struct frame *f;
   Lisp_Object frame, tem;
   Lisp_Object name;
-  int minibuffer_only = 0;
+  bool minibuffer_only = false;
   long window_prompting = 0;
-  int width, height;
   ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object display;
@@ -4417,17 +4479,18 @@ This function is an internal primitive--use `make-frame' instead.  */)
   else if (EQ (tem, Qonly))
     {
       f = make_minibuffer_frame ();
-      minibuffer_only = 1;
+      minibuffer_only = true;
     }
   else if (WINDOWP (tem))
     f = make_frame_without_minibuffer (tem, kb, display);
   else
-    f = make_frame (1);
+    f = make_frame (true);
 
   XSETFRAME (frame, f);
 
-  /* By default, make scrollbars the system standard width. */
-  x_set_scroll_bar_default_width (f);
+  /* By default, make scrollbars the system standard width and height. */
+  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
+  FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
 
   f->terminal = dpyinfo->terminal;
 
@@ -4453,16 +4516,17 @@ This function is an internal primitive--use `make-frame' instead.  */)
 #endif /* GLYPH_DEBUG */
 
   /* Specify the parent under which to make this window.  */
-
   if (!NILP (parent))
     {
-      f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
-      f->output_data.w32->explicit_parent = 1;
+      /* Cast to UINT_PTR shuts up compiler warnings about cast to
+        pointer from integer of different size.  */
+      f->output_data.w32->parent_desc = (Window) (UINT_PTR) XFASTINT (parent);
+      f->output_data.w32->explicit_parent = true;
     }
   else
     {
       f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
-      f->output_data.w32->explicit_parent = 0;
+      f->output_data.w32->explicit_parent = false;
     }
 
   /* Set the name; the functions to which we pass f expect the name to
@@ -4470,13 +4534,13 @@ This function is an internal primitive--use `make-frame' instead.  */)
   if (EQ (name, Qunbound) || NILP (name))
     {
       fset_name (f, build_string (dpyinfo->w32_id_name));
-      f->explicit_name = 0;
+      f->explicit_name = false;
     }
   else
     {
       fset_name (f, name);
-      f->explicit_name = 1;
-      /* use the frame's title when getting resources for this frame.  */
+      f->explicit_name = true;
+      /* Use the frame's title when getting resources for this frame.  */
       specbind (Qx_resource_name, name);
     }
 
@@ -4486,9 +4550,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   x_default_parameter (f, parameters, Qfont_backend, Qnil,
                       "fontBackend", "FontBackend", RES_TYPE_STRING);
+
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
   x_default_font_parameter (f, parameters);
+
   x_default_parameter (f, parameters, Qborder_width, make_number (2),
                       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
 
@@ -4502,7 +4568,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
                         "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
        parameters = Fcons (Fcons (Qinternal_border_width, value),
-                            parameters);
+                           parameters);
     }
   /* Default internalBorderWidth to 0 on Windows to match other programs.  */
   x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
@@ -4513,6 +4579,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
                       NULL, NULL, RES_TYPE_NUMBER);
   x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
                       "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
+  x_default_parameter (f, parameters, Qhorizontal_scroll_bars, Qnil,
+                      "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
 
   /* Also do the stuff which must be set before the window exists.  */
   x_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
@@ -4533,57 +4601,43 @@ This function is an internal primitive--use `make-frame' instead.  */)
                       "rightFringe", "RightFringe", RES_TYPE_NUMBER);
   /* Process alpha here (Bug#16619).  */
   x_default_parameter (f, parameters, Qalpha, Qnil,
-                       "alpha", "Alpha", RES_TYPE_NUMBER);
+                      "alpha", "Alpha", RES_TYPE_NUMBER);
 
-  /* Init faces before x_default_parameter is called for scroll-bar
-     parameters because that function calls x_set_scroll_bar_width,
-     which calls change_frame_size, which calls Fset_window_buffer,
-     which runs hooks, which call Fvertical_motion.  At the end, we
-     end up in init_iterator with a null face cache, which should not
-     happen.  */
+  /* Init faces first since we need the frame's column width/line
+     height in various occasions.  */
   init_frame_faces (f);
 
-  /* Avoid calling window-configuration-change-hook; otherwise we
-     could get an infloop in next_frame since the frame is not yet in
-     Vframe_list.  */
-  {
-    ptrdiff_t count2 = SPECPDL_INDEX ();
-
-    record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code);
-    inhibit_lisp_code = Qt;
-
-    /* PXW: This is a duplicate from below.  We have to do it here since
-       otherwise x_set_tool_bar_lines will work with the character sizes
-       installed by init_frame_faces while the frame's pixel size is still
-       calculated from a character size of 1 and we subsequently hit the
-       eassert (height >= 0) assertion in window_box_height.  The
-       non-pixelwise code apparently worked around this because it had one
-       frame line vs one toolbar line which left us with a zero root
-       window height which was obviously wrong as well ...  */
-    change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1);
-
-    /* The X resources controlling the menu-bar and tool-bar are
-       processed specially at startup, and reflected in the mode
-       variables; ignore them here.  */
-    x_default_parameter (f, parameters, Qmenu_bar_lines,
-                        NILP (Vmenu_bar_mode)
-                        ? make_number (0) : make_number (1),
-                        NULL, NULL, RES_TYPE_NUMBER);
-    x_default_parameter (f, parameters, Qtool_bar_lines,
-                        NILP (Vtool_bar_mode)
-                        ? make_number (0) : make_number (1),
-                        NULL, NULL, RES_TYPE_NUMBER);
-
-    unbind_to (count2, Qnil);
-  }
+  /* The following call of change_frame_size is needed since otherwise
+     x_set_tool_bar_lines will already work with the character sizes
+     installed by init_frame_faces while the frame's pixel size is
+     still calculated from a character size of 1 and we subsequently
+     hit the (height >= 0) assertion in window_box_height.
+
+     The non-pixelwise code apparently worked around this because it
+     had one frame line vs one toolbar line which left us with a zero
+     root window height which was obviously wrong as well ...  */
+  adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
+                    Qx_create_frame_1);
+
+  /* The X resources controlling the menu-bar and tool-bar are
+     processed specially at startup, and reflected in the mode
+     variables; ignore them here.  */
+  x_default_parameter (f, parameters, Qmenu_bar_lines,
+                      NILP (Vmenu_bar_mode)
+                      ? make_number (0) : make_number (1),
+                      NULL, NULL, RES_TYPE_NUMBER);
+  x_default_parameter (f, parameters, Qtool_bar_lines,
+                      NILP (Vtool_bar_mode)
+                      ? make_number (0) : make_number (1),
+                      NULL, NULL, RES_TYPE_NUMBER);
 
   x_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
                       "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
   x_default_parameter (f, parameters, Qtitle, Qnil,
                       "title", "Title", RES_TYPE_STRING);
   x_default_parameter (f, parameters, Qfullscreen, Qnil,
-                       "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+                      "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
   f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
@@ -4598,7 +4652,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
 
-  window_prompting = x_figure_window_size (f, parameters, 1);
+  window_prompting = x_figure_window_size (f, parameters, true);
 
   tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
@@ -4626,21 +4680,20 @@ This function is an internal primitive--use `make-frame' instead.  */)
                       "cursorType", "CursorType", RES_TYPE_SYMBOL);
   x_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
                       "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
+  x_default_parameter (f, parameters, Qscroll_bar_height, Qnil,
+                      "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER);
+
+  /* Allow x_set_window_size, now.  */
+  f->can_x_set_window_size = true;
 
-  /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
-     Change will not be effected unless different from the current
-     FRAME_LINES (f).  */
-  width = FRAME_TEXT_WIDTH (f);
-  height = FRAME_TEXT_HEIGHT (f);
-  FRAME_TEXT_HEIGHT (f) = 0;
-  SET_FRAME_WIDTH (f, 0);
-  change_frame_size (f, width, height, 1, 0, 0, 1);
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true,
+                    Qx_create_frame_2);
 
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
      bar so that its size can be taken into account.  */
   block_input ();
-  x_wm_set_size_hint (f, window_prompting, 0);
+  x_wm_set_size_hint (f, window_prompting, false);
   unblock_input ();
 
   /* Make the window appear on the frame and enable display, unless
@@ -4710,7 +4763,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
 
   CHECK_STRING (color);
 
-  if (w32_defined_color (f, SDATA (color), &foo, 0))
+  if (w32_defined_color (f, SDATA (color), &foo, false))
     return Qt;
   else
     return Qnil;
@@ -4725,7 +4778,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
 
   CHECK_STRING (color);
 
-  if (w32_defined_color (f, SDATA (color), &foo, 0))
+  if (w32_defined_color (f, SDATA (color), &foo, false))
     return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel),
                   (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel),
                   (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel));
@@ -4984,7 +5037,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
   return Qnil;
 }
 
-static BOOL CALLBACK
+static BOOL CALLBACK ALIGN_STACK
 w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData)
 {
   Lisp_Object *monitor_list = (Lisp_Object *) dwData;
@@ -5311,7 +5364,7 @@ terminate Emacs if we can't open the connection.
   {
     char basename[ MAX_PATH ], *str;
 
-    strcpy (basename, SDATA (Vinvocation_name));
+    lispstpcpy (basename, Vinvocation_name);
     str = strrchr (basename, '.');
     if (str) *str = 0;
     Vinvocation_name = build_string (basename);
@@ -5523,100 +5576,6 @@ no value of TYPE (always string in the MS Windows case).  */)
 
 #endif /* TODO */
 
-\f
-/***********************************************************************
-                               Busy cursor
- ***********************************************************************/
-
-void
-w32_note_current_window (void)
-{
-  struct frame * f = SELECTED_FRAME ();
-
-  if (!FRAME_W32_P (f))
-    return;
-
-  hourglass_hwnd = FRAME_W32_WINDOW (f);
-}
-
-void
-show_hourglass (struct atimer *timer)
-{
-  struct frame *f;
-
-  hourglass_atimer = NULL;
-
-  block_input ();
-  f = x_window_to_frame (&one_w32_display_info,
-                                      hourglass_hwnd);
-
-  if (f)
-    f->output_data.w32->hourglass_p = 0;
-  else
-    f = SELECTED_FRAME ();
-
-  if (!FRAME_W32_P (f))
-    {
-      unblock_input ();
-      return;
-    }
-
-  w32_show_hourglass (f);
-  unblock_input ();
-}
-
-void
-hide_hourglass (void)
-{
-  block_input ();
-  w32_hide_hourglass ();
-  unblock_input ();
-}
-
-
-/* Display an hourglass cursor.  Set the hourglass_p flag in display info
-   to indicate that an hourglass cursor is shown.  */
-
-static void
-w32_show_hourglass (struct frame *f)
-{
-  if (!hourglass_shown_p)
-    {
-      f->output_data.w32->hourglass_p = 1;
-      if (!menubar_in_use && !current_popup_menu)
-       SetCursor (f->output_data.w32->hourglass_cursor);
-      hourglass_shown_p = 1;
-    }
-}
-
-
-/* Hide the hourglass cursor on all frames, if it is currently shown.  */
-
-static void
-w32_hide_hourglass (void)
-{
-  if (hourglass_shown_p)
-    {
-      struct frame *f = x_window_to_frame (&one_w32_display_info,
-                                          hourglass_hwnd);
-      if (f)
-       f->output_data.w32->hourglass_p = 0;
-      else
-       /* If frame was deleted, restore to selected frame's cursor.  */
-       f = SELECTED_FRAME ();
-
-      if (FRAME_W32_P (f))
-       SetCursor (f->output_data.w32->current_cursor);
-      else
-       /* No cursors on non GUI frames - restore to stock arrow cursor.  */
-       SetCursor (w32_load_cursor (IDC_ARROW));
-
-      hourglass_shown_p = 0;
-    }
-}
-
-
-\f
 /***********************************************************************
                                Tool tips
  ***********************************************************************/
@@ -5702,14 +5661,15 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   frame = Qnil;
   GCPRO3 (parms, name, frame);
   /* Make a frame without minibuffer nor mode-line.  */
-  f = make_frame (0);
+  f = make_frame (false);
   f->wants_modeline = 0;
   XSETFRAME (frame, f);
 
-  buffer = Fget_buffer_create (build_string (" *tip*"));
+  AUTO_STRING (tip, " *tip*");
+  buffer = Fget_buffer_create (tip);
   /* Use set_window_buffer instead of Fset_window_buffer (see
      discussion of bug#11984, bug#12025, bug#12026).  */
-  set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, 0, 0);
+  set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (buffer));
   bset_truncate_lines (current_buffer, Qnil);
@@ -5739,19 +5699,19 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
 #endif /* GLYPH_DEBUG */
   FRAME_KBOARD (f) = kb;
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
-  f->output_data.w32->explicit_parent = 0;
+  f->output_data.w32->explicit_parent = false;
 
   /* Set the name; the functions to which we pass f expect the name to
      be set.  */
   if (EQ (name, Qunbound) || NILP (name))
     {
       fset_name (f, build_string (dpyinfo->w32_id_name));
-      f->explicit_name = 0;
+      f->explicit_name = false;
     }
   else
     {
       fset_name (f, name);
-      f->explicit_name = 1;
+      f->explicit_name = true;
       /* use the frame's title when getting resources for this frame.  */
       specbind (Qx_resource_name, name);
     }
@@ -5801,19 +5761,18 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
                       "cursorColor", "Foreground", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qborder_color, build_string ("black"),
                       "borderColor", "BorderColor", RES_TYPE_STRING);
+  x_default_parameter (f, parms, Qalpha, Qnil,
+                       "alpha", "Alpha", RES_TYPE_NUMBER);
 
-  /* Init faces before x_default_parameter is called for scroll-bar
-     parameters because that function calls x_set_scroll_bar_width,
-     which calls change_frame_size, which calls Fset_window_buffer,
-     which runs hooks, which call Fvertical_motion.  At the end, we
-     end up in init_iterator with a null face cache, which should not
-     happen.  */
+  /* Init faces before x_default_parameter is called for the
+     scroll-bar-width parameter because otherwise we end up in
+     init_iterator with a null face cache, which should not happen.  */
   init_frame_faces (f);
 
   f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
 
-  window_prompting = x_figure_window_size (f, parms, 0);
+  window_prompting = x_figure_window_size (f, parms, false);
 
   /* No fringes on tip frame.  */
   f->fringe_cols = 0;
@@ -5838,9 +5797,10 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
      from the current FRAME_LINES (f).  */
   width = FRAME_COLS (f);
   height = FRAME_LINES (f);
-  FRAME_LINES (f) = 0;
   SET_FRAME_COLS (f, 0);
-  change_frame_size (f, width, height, 1, 0, 0, 0);
+  SET_FRAME_LINES (f, 0);
+  adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
+                    height * FRAME_LINE_HEIGHT (f), 0, true, Qnil);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -5872,7 +5832,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
       Fmodify_frame_parameters (frame, colors);
   }
 
-  f->no_split = 1;
+  f->no_split = true;
 
   UNGCPRO;
 
@@ -5885,6 +5845,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
      below.  And the frame needs to be on Vframe_list or making it
      visible won't work.  */
   Vframe_list = Fcons (frame, Vframe_list);
+  f->can_x_set_window_size = true;
 
   /* Setting attributes of faces of the tooltip frame from resources
      and similar will increment face_change_count, which leads to the
@@ -6018,7 +5979,8 @@ Text larger than the specified size is clipped.  */)
   int root_x, root_y;
   struct buffer *old_buffer;
   struct text_pos pos;
-  int i, width, height, seen_reversed_p;
+  int i, width, height;
+  bool seen_reversed_p;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   ptrdiff_t count = SPECPDL_INDEX ();
@@ -6147,7 +6109,7 @@ Text larger than the specified size is clipped.  */)
 
   FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
   adjust_frame_glyphs (f);
-  w->pseudo_window_p = 1;
+  w->pseudo_window_p = true;
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
@@ -6159,7 +6121,8 @@ Text larger than the specified size is clipped.  */)
   try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
 
   /* Compute width and height of the tooltip.  */
-  width = height = seen_reversed_p = 0;
+  width = height = 0;
+  seen_reversed_p = false;
   for (i = 0; i < w->desired_matrix->nrows; ++i)
     {
       struct glyph_row *row = &w->desired_matrix->rows[i];
@@ -6171,7 +6134,7 @@ Text larger than the specified size is clipped.  */)
        break;
 
       /* Let the row go over the full width of the frame.  */
-      row->full_width_p = 1;
+      row->full_width_p = true;
 
       row_width = row->pixel_width;
       if (row->used[TEXT_AREA])
@@ -6182,7 +6145,7 @@ Text larger than the specified size is clipped.  */)
                 place the cursor there.  Don't include the width of
                 this glyph.  */
              last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
-             if (INTEGERP (last->object))
+             if (NILP (last->object))
                row_width -= last->pixel_width;
            }
          else
@@ -6192,10 +6155,10 @@ Text larger than the specified size is clipped.  */)
                 Don't count that glyph.  */
              struct glyph *g = row->glyphs[TEXT_AREA];
 
-             if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
+             if (g->type == STRETCH_GLYPH && NILP (g->object))
                {
                  row_width -= g->pixel_width;
-                 seen_reversed_p = 1;
+                 seen_reversed_p = true;
                }
            }
        }
@@ -6236,12 +6199,12 @@ Text larger than the specified size is clipped.  */)
 
          if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
            break;
-         row->full_width_p = 1;
+         row->full_width_p = true;
          row_width = row->pixel_width;
          if (row->used[TEXT_AREA] && !row->reversed_p)
            {
              last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
-             if (INTEGERP (last->object))
+             if (NILP (last->object))
                row_width -= last->pixel_width;
            }
 
@@ -6293,8 +6256,8 @@ Text larger than the specified size is clipped.  */)
   }
 
   /* Draw into the window.  */
-  w->must_be_updated_p = 1;
-  update_single_window (w, 1);
+  w->must_be_updated_p = true;
+  update_single_window (w);
 
   unblock_input ();
 
@@ -6913,24 +6876,33 @@ operations:
                specified DOCUMENT.
  \"find\"    - initiate search starting from DOCUMENT, which must specify
                a directory.
+ \"delete\"  - move DOCUMENT, a file or a directory, to Recycle Bin.
+ \"copy\"    - copy DOCUMENT, which must be a file or a directory, into
+               the clipboard.
+ \"cut\"     - move DOCUMENT, a file or a directory, into the clipboard.
+ \"paste\"   - paste the file whose name is in the clipboard into DOCUMENT,
+               which must be a directory.
+ \"pastelink\"
+           - create a shortcut in DOCUMENT (which must be a directory)
+               the file or directory whose name is in the clipboard.
  \"runas\"   - run DOCUMENT, which must be an excutable file, with
                elevated privileges (a.k.a. \"as Administrator\").
  \"properties\"
-           - open the the property sheet dialog for DOCUMENT; works
-               for *.lnk desktop shortcuts, and little or nothing else.
+           - open the property sheet dialog for DOCUMENT.
  nil       - invoke the default OPERATION, or \"open\" if default is
                not defined or unavailable.
 
 DOCUMENT is typically the name of a document file or a URL, but can
 also be an executable program to run, or a directory to open in the
-Windows Explorer.  If it is a file, it must be a local one; this
-function does not support remote file names.
+Windows Explorer.  If it is a file or a directory, it must be a local
+one; this function does not support remote file names.
 
 If DOCUMENT is an executable program, the optional third arg PARAMETERS
-can be a string containing command line parameters that will be passed
-to the program.  Some values of OPERATION also require parameters (e.g.,
-\"printto\" requires the printer address).  Otherwise, PARAMETERS should
-be nil or unspecified.
+can be a string containing command line parameters, separated by blanks,
+that will be passed to the program.  Some values of OPERATION also require
+parameters (e.g., \"printto\" requires the printer address).  Otherwise,
+PARAMETERS should be nil or unspecified.  Note that double quote characters
+in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\".
 
 Optional fourth argument SHOW-FLAG can be used to control how the
 application will be displayed when it is invoked.  If SHOW-FLAG is nil
@@ -6948,11 +6920,13 @@ a ShowWindow flag:
   char *errstr;
   Lisp_Object current_dir = BVAR (current_buffer, directory);;
   wchar_t *doc_w = NULL, *params_w = NULL, *ops_w = NULL;
+#ifdef CYGWIN
   intptr_t result;
-#ifndef CYGWIN
+#else
   int use_unicode = w32_unicode_filenames;
   char *doc_a = NULL, *params_a = NULL, *ops_a = NULL;
   Lisp_Object absdoc, handler;
+  BOOL success;
   struct gcpro gcpro1;
 #endif
 
@@ -6980,7 +6954,48 @@ a ShowWindow flag:
                                     GUI_SDATA (current_dir),
                                     (INTEGERP (show_flag)
                                      ? XINT (show_flag) : SW_SHOWDEFAULT));
+
+  if (result > 32)
+    return Qt;
+
+  switch (result)
+    {
+    case SE_ERR_ACCESSDENIED:
+      errstr = w32_strerror (ERROR_ACCESS_DENIED);
+      break;
+    case SE_ERR_ASSOCINCOMPLETE:
+    case SE_ERR_NOASSOC:
+      errstr = w32_strerror (ERROR_NO_ASSOCIATION);
+      break;
+    case SE_ERR_DDEBUSY:
+    case SE_ERR_DDEFAIL:
+      errstr = w32_strerror (ERROR_DDE_FAIL);
+      break;
+    case SE_ERR_DDETIMEOUT:
+      errstr = w32_strerror (ERROR_TIMEOUT);
+      break;
+    case SE_ERR_DLLNOTFOUND:
+      errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
+      break;
+    case SE_ERR_FNF:
+      errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
+      break;
+    case SE_ERR_OOM:
+      errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
+      break;
+    case SE_ERR_PNF:
+      errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
+      break;
+    case SE_ERR_SHARE:
+      errstr = w32_strerror (ERROR_SHARING_VIOLATION);
+      break;
+    default:
+      errstr = w32_strerror (0);
+      break;
+    }
+
 #else  /* !CYGWIN */
+
   current_dir = ENCODE_FILE (current_dir);
   /* We have a situation here.  If DOCUMENT is a relative file name,
      but its name includes leading directories, i.e. it lives not in
@@ -7017,6 +7032,7 @@ a ShowWindow flag:
   if (use_unicode)
     {
       wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
+      SHELLEXECUTEINFOW shexinfo_w;
 
       /* Encode filename, current directory and parameters, and
         convert operation to UTF-16.  */
@@ -7050,14 +7066,28 @@ a ShowWindow flag:
            *d++ = *s++;
          *d = 0;
        }
-      result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
-                                        current_dir_w,
-                                        (INTEGERP (show_flag)
-                                         ? XINT (show_flag) : SW_SHOWDEFAULT));
+
+      /* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST
+        flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is
+        able to invoke verbs from shortcut menu extensions, not just
+        static verbs listed in the Registry.  */
+      memset (&shexinfo_w, 0, sizeof (shexinfo_w));
+      shexinfo_w.cbSize = sizeof (shexinfo_w);
+      shexinfo_w.fMask =
+       SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
+      shexinfo_w.hwnd = NULL;
+      shexinfo_w.lpVerb = ops_w;
+      shexinfo_w.lpFile = doc_w;
+      shexinfo_w.lpParameters = params_w;
+      shexinfo_w.lpDirectory = current_dir_w;
+      shexinfo_w.nShow =
+       (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
+      success = ShellExecuteExW (&shexinfo_w);
     }
   else
     {
       char document_a[MAX_PATH], current_dir_a[MAX_PATH];
+      SHELLEXECUTEINFOA shexinfo_a;
 
       filename_to_ansi (SSDATA (current_dir), current_dir_a);
       filename_to_ansi (SSDATA (document), document_a);
@@ -7072,51 +7102,27 @@ a ShowWindow flag:
          /* Assume OPERATION is pure ASCII.  */
          ops_a = SSDATA (operation);
        }
-      result = (intptr_t) ShellExecuteA (NULL, ops_a, doc_a, params_a,
-                                        current_dir_a,
-                                        (INTEGERP (show_flag)
-                                         ? XINT (show_flag) : SW_SHOWDEFAULT));
+      memset (&shexinfo_a, 0, sizeof (shexinfo_a));
+      shexinfo_a.cbSize = sizeof (shexinfo_a);
+      shexinfo_a.fMask =
+       SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
+      shexinfo_a.hwnd = NULL;
+      shexinfo_a.lpVerb = ops_a;
+      shexinfo_a.lpFile = doc_a;
+      shexinfo_a.lpParameters = params_a;
+      shexinfo_a.lpDirectory = current_dir_a;
+      shexinfo_a.nShow =
+       (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
+      success = ShellExecuteExA (&shexinfo_a);
     }
-#endif /* !CYGWIN */
 
-  if (result > 32)
+  if (success)
     return Qt;
 
-  switch (result)
-    {
-    case SE_ERR_ACCESSDENIED:
-      errstr = w32_strerror (ERROR_ACCESS_DENIED);
-      break;
-    case SE_ERR_ASSOCINCOMPLETE:
-    case SE_ERR_NOASSOC:
-      errstr = w32_strerror (ERROR_NO_ASSOCIATION);
-      break;
-    case SE_ERR_DDEBUSY:
-    case SE_ERR_DDEFAIL:
-      errstr = w32_strerror (ERROR_DDE_FAIL);
-      break;
-    case SE_ERR_DDETIMEOUT:
-      errstr = w32_strerror (ERROR_TIMEOUT);
-      break;
-    case SE_ERR_DLLNOTFOUND:
-      errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
-      break;
-    case SE_ERR_FNF:
-      errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
-      break;
-    case SE_ERR_OOM:
-      errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
-      break;
-    case SE_ERR_PNF:
-      errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
-      break;
-    case SE_ERR_SHARE:
-      errstr = w32_strerror (ERROR_SHARING_VIOLATION);
-      break;
-    default:
-      errstr = w32_strerror (0);
-      break;
-    }
+  errstr = w32_strerror (0);
+
+#endif /* !CYGWIN */
+
   /* The error string might be encoded in the locale's encoding.  */
   if (!NILP (Vlocale_coding_system))
     {
@@ -7246,7 +7252,7 @@ The return value is the hotkey-id if registered, otherwise nil.  */)
       /* Notify input thread about new hot-key definition, so that it
         takes effect without needing to switch focus.  */
       PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
-                        (WPARAM) XLI (key), 0);
+                        (WPARAM) XINT (key), 0);
     }
 
   return key;
@@ -7266,10 +7272,17 @@ DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
 
   if (!NILP (item))
     {
+      LPARAM lparam;
+
+      eassert (CONSP (item));
+      /* Pass the tail of the list as a pointer to a Lisp_Cons cell,
+        so that it works in a --with-wide-int build as well.  */
+      lparam = (LPARAM) XUNTAG (item, Lisp_Cons);
+
       /* Notify input thread about hot-key definition being removed, so
         that it takes effect without needing focus switch.  */
       if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
-                            (WPARAM) XINT (XCAR (item)), (LPARAM) XLI (item)))
+                            (WPARAM) XINT (XCAR (item)), lparam))
        {
          MSG msg;
          GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -7324,10 +7337,15 @@ DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
        doc: /* Toggle the state of the lock key KEY.
 KEY can be `capslock', `kp-numlock', or `scroll'.
 If the optional parameter NEW-STATE is a number, then the state of KEY
-is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
+is set to off if the low bit of NEW-STATE is zero, otherwise on.
+If NEW-STATE is omitted or nil, the function toggles the state,
+
+Value is the new state of the key, or nil if the function failed
+to change the state.  */)
   (Lisp_Object key, Lisp_Object new_state)
 {
   int vk_code;
+  LPARAM lparam;
 
   if (EQ (key, intern ("capslock")))
     vk_code = VK_CAPITAL;
@@ -7341,8 +7359,12 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
   if (!dwWindowsThreadId)
     return make_number (w32_console_toggle_lock_key (vk_code, new_state));
 
+  if (NILP (new_state))
+    lparam = -1;
+  else
+    lparam = (XUINT (new_state)) & 1;
   if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
-                        (WPARAM) vk_code, (LPARAM) XLI (new_state)))
+                        (WPARAM) vk_code, lparam))
     {
       MSG msg;
       GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -7372,6 +7394,37 @@ This is a direct interface to the Windows API FindWindow function.  */)
   return Qt;
 }
 
+DEFUN ("w32-frame-menu-bar-size", Fw32_frame_menu_bar_size, Sw32_frame_menu_bar_size, 0, 1, 0,
+       doc: /* Return sizes of menu bar on frame FRAME.
+The return value is a list of four elements: The current width and
+height of FRAME's menu bar in pixels, the height of one menu bar line in
+a wrapped menu bar in pixels, and the height of a single line menu bar
+in pixels.
+
+If FRAME is omitted or nil, the selected frame is used.  */)
+  (Lisp_Object frame)
+{
+  struct frame *f = decode_any_frame (frame);
+  MENUBARINFO menu_bar;
+  int width, height, single_height, wrapped_height;
+
+  block_input ();
+
+  single_height = GetSystemMetrics (SM_CYMENU);
+  wrapped_height = GetSystemMetrics (SM_CYMENUSIZE);
+  menu_bar.cbSize = sizeof (menu_bar);
+  menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+  menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+  width = menu_bar.rcBar.right - menu_bar.rcBar.left;
+  height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
+
+  unblock_input ();
+
+  return list4 (make_number (width), make_number (height),
+               make_number (wrapped_height), make_number (single_height));
+}
+
 DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0,
        doc: /* Return boundary rectangle of FRAME in screen coordinates.
 FRAME must be a live frame and defaults to the selected one.
@@ -7386,15 +7439,131 @@ title bar and decorations.  */)
   struct frame *f = decode_live_frame (frame);
   RECT rect;
 
+  block_input ();
+
   if (!NILP (client))
     GetClientRect (FRAME_W32_WINDOW (f), &rect);
   else
     GetWindowRect (FRAME_W32_WINDOW (f), &rect);
 
+  unblock_input ();
+
   return list4 (make_number (rect.left), make_number (rect.top),
                make_number (rect.right), make_number (rect.bottom));
 }
 
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+       doc: /* Return geometric attributes of frame FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is an association list containing the following
+elements (all size values are in pixels).
+
+- `frame-outer-size' is a cons of the outer width and height of FRAME.
+  The outer size includes the title bar and the external borders as well
+  as any menu and/or tool bar of frame.
+
+- `border' is a cons of the horizontal and vertical width of FRAME's
+  external borders.
+
+- `title-bar-height' is the height of the title bar of FRAME.
+
+- `menu-bar-external' if `t' means the menu bar is by default external
+  (not included in the inner size of FRAME).
+
+- `menu-bar-size' is a cons of the width and height of the menu bar of
+  FRAME.
+
+- `tool-bar-external' if `t' means the tool bar is by default external
+  (not included in the inner size of FRAME).
+
+- `tool-bar-side' tells tells on which side the tool bar on FRAME is by
+  default and can be one of `left', `top', `right' or `bottom'.
+
+- `tool-bar-size' is a cons of the width and height of the tool bar of
+  FRAME.
+
+- `frame-inner-size' is a cons of the inner width and height of FRAME.
+  This excludes FRAME's title bar and external border as well as any
+  external menu and/or tool bar.  */)
+  (Lisp_Object frame)
+{
+  struct frame *f = decode_live_frame (frame);
+  Lisp_Object geometry = Qnil;
+  RECT frame_outer_edges, frame_inner_edges;
+  MENUBARINFO menu_bar;
+  int  border_width, border_height, title_height;
+  int single_bar_height, wrapped_bar_height, menu_bar_height;
+  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+
+  block_input ();
+
+  /* Outer frame rectangle, including outer borders and title bar. */
+  GetWindowRect (FRAME_W32_WINDOW (f), &frame_outer_edges);
+  /* Inner frame rectangle, excluding borders and title bar.  */
+  GetClientRect (FRAME_W32_WINDOW (f), &frame_inner_edges);
+  /* Outer border.  */
+  border_width = GetSystemMetrics (SM_CXFRAME);
+  border_height = GetSystemMetrics (SM_CYFRAME);
+  /* Title bar.  */
+  title_height = GetSystemMetrics (SM_CYCAPTION);
+  /* Menu bar.  */
+  menu_bar.cbSize = sizeof (menu_bar);
+  menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+  menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+  single_bar_height = GetSystemMetrics (SM_CYMENU);
+  wrapped_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
+  unblock_input ();
+
+  menu_bar_height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
+  /* Fix menu bar height reported by GetMenuBarInfo.  */
+  if (menu_bar_height > single_bar_height)
+    /* A wrapped menu bar.  */
+    menu_bar_height += single_bar_height - wrapped_bar_height;
+  else if (menu_bar_height > 0)
+    /* A single line menu bar.  */
+    menu_bar_height = single_bar_height;
+
+  return
+    listn (CONSTYPE_PURE, 10,
+          Fcons (Qframe_position,
+                 Fcons (make_number (frame_outer_edges.left),
+                        make_number (frame_outer_edges.top))),
+          Fcons (Qframe_outer_size,
+                 Fcons (make_number
+                        (frame_outer_edges.right - frame_outer_edges.left),
+                        make_number
+                        (frame_outer_edges.bottom - frame_outer_edges.top))),
+          Fcons (Qexternal_border_size,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? Fcons (make_number (0), make_number (0))
+                  : Fcons (make_number (border_width),
+                           make_number (border_height)))),
+          Fcons (Qtitle_height,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? make_number (0)
+                  : make_number (title_height))),
+          Fcons (Qmenu_bar_external, Qt),
+          Fcons (Qmenu_bar_size,
+                 Fcons (make_number
+                        (menu_bar.rcBar.right - menu_bar.rcBar.left),
+                        make_number (menu_bar_height))),
+          Fcons (Qtool_bar_external, Qnil),
+          Fcons (Qtool_bar_position, Qtop),
+          Fcons (Qtool_bar_size,
+                 Fcons (make_number (FRAME_TOOL_BAR_LINES (f)
+                                     ? (FRAME_PIXEL_WIDTH (f)
+                                        - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+                                     : 0),
+                        make_number (FRAME_TOOL_BAR_HEIGHT (f)))),
+          Fcons (Qframe_inner_size,
+                 Fcons (make_number
+                        (frame_inner_edges.right - frame_inner_edges.left),
+                        make_number
+                        (frame_inner_edges.bottom - frame_inner_edges.top))));
+}
+
 DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
        doc: /* Get power status information from Windows system.
 
@@ -7536,8 +7705,8 @@ If the underlying system call fails, value is nil.  */)
       (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
       = GetProcAddress (hKernel, "GetDiskFreeSpaceExA");
     bool have_pfn_GetDiskFreeSpaceEx =
-      (w32_unicode_filenames && pfn_GetDiskFreeSpaceExW
-       || !w32_unicode_filenames && pfn_GetDiskFreeSpaceExA);
+      ((w32_unicode_filenames && pfn_GetDiskFreeSpaceExW)
+       || (!w32_unicode_filenames && pfn_GetDiskFreeSpaceExA));
 
     /* On Windows, we may need to specify the root directory of the
        volume holding FILENAME.  */
@@ -8059,17 +8228,19 @@ frame_parm_handler w32_frame_parm_handlers[] =
   x_set_mouse_color,
   x_explicitly_set_name,
   x_set_scroll_bar_width,
+  x_set_scroll_bar_height,
   x_set_title,
   x_set_unsplittable,
   x_set_vertical_scroll_bars,
+  x_set_horizontal_scroll_bars,
   x_set_visibility,
   x_set_tool_bar_lines,
   0, /* x_set_scroll_bar_foreground, */
   0, /* x_set_scroll_bar_background, */
   x_set_screen_gamma,
   x_set_line_spacing,
-  x_set_fringe_width,
-  x_set_fringe_width,
+  x_set_left_fringe,
+  x_set_right_fringe,
   0, /* x_set_wait_for_wm, */
   x_set_fullscreen,
   x_set_font_backend,
@@ -8086,7 +8257,6 @@ syms_of_w32fns (void)
 
   w32_visible_system_caret_hwnd = NULL;
 
-  DEFSYM (Qsuppress_icon, "suppress-icon");
   DEFSYM (Qundefined_color, "undefined-color");
   DEFSYM (Qcancel_timer, "cancel-timer");
   DEFSYM (Qhyper, "hyper");
@@ -8101,8 +8271,6 @@ syms_of_w32fns (void)
   DEFSYM (Qworkarea, "workarea");
   DEFSYM (Qmm_size, "mm-size");
   DEFSYM (Qframes, "frames");
-  /* This is the end of symbol initialization.  */
-
 
   Fput (Qundefined_color, Qerror_conditions,
        listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
@@ -8390,6 +8558,7 @@ only be necessary if the default setting causes problems.  */);
   defsubr (&Sx_open_connection);
   defsubr (&Sx_close_connection);
   defsubr (&Sx_display_list);
+  defsubr (&Sx_frame_geometry);
   defsubr (&Sx_synchronize);
 
   /* W32 specific functions */
@@ -8406,6 +8575,7 @@ only be necessary if the default setting causes problems.  */);
   defsubr (&Sw32_toggle_lock_key);
   defsubr (&Sw32_window_exists_p);
   defsubr (&Sw32_frame_rect);
+  defsubr (&Sw32_frame_menu_bar_size);
   defsubr (&Sw32_battery_status);
 
 #ifdef WINDOWSNT
@@ -8414,9 +8584,6 @@ only be necessary if the default setting causes problems.  */);
 #endif
 
   defsubr (&Sset_message_beep);
-
-  hourglass_hwnd = NULL;
-
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
   tip_timer = Qnil;