Use xstrdup and build_unibyte_string where applicable.
[bpt/emacs.git] / src / w32fns.c
index d7ac0dd..c43b7d4 100644 (file)
@@ -106,6 +106,7 @@ Lisp_Object Qalt;
 Lisp_Object Qctrl;
 Lisp_Object Qcontrol;
 Lisp_Object Qshift;
+static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
 
 
 /* Prefix for system colors.  */
@@ -131,6 +132,15 @@ static HWND track_mouse_window;
 #ifndef MONITOR_DEFAULT_TO_NEAREST
 #define MONITOR_DEFAULT_TO_NEAREST 2
 #endif
+#ifndef MONITORINFOF_PRIMARY
+#define MONITORINFOF_PRIMARY 1
+#endif
+#ifndef SM_XVIRTUALSCREEN
+#define SM_XVIRTUALSCREEN 76
+#endif
+#ifndef SM_YVIRTUALSCREEN
+#define SM_YVIRTUALSCREEN 77
+#endif
 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
    To avoid a compile error on one or the other, redefine with a new name.  */
 struct MONITOR_INFO
@@ -141,6 +151,18 @@ struct MONITOR_INFO
     DWORD   dwFlags;
 };
 
+#ifndef CCHDEVICENAME
+#define CCHDEVICENAME 32
+#endif
+struct MONITOR_INFO_EX
+{
+    DWORD   cbSize;
+    RECT    rcMonitor;
+    RECT    rcWork;
+    DWORD   dwFlags;
+    char    szDevice[CCHDEVICENAME];
+};
+
 /* Reportedly, MSVC does not have this in its headers.  */
 #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
 DECLARE_HANDLE(HMONITOR);
@@ -159,6 +181,10 @@ typedef BOOL (WINAPI * GetMonitorInfo_Proc)
   (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
 typedef HMONITOR (WINAPI * MonitorFromWindow_Proc)
   (IN HWND hwnd, IN DWORD dwFlags);
+typedef BOOL CALLBACK (* MonitorEnum_Proc)
+  (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData);
+typedef BOOL (WINAPI * EnumDisplayMonitors_Proc)
+  (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
 
 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ImmGetCompositionString_Proc get_composition_string_fn = NULL;
@@ -168,6 +194,7 @@ ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
 MonitorFromPoint_Proc monitor_from_point_fn = NULL;
 GetMonitorInfo_Proc get_monitor_info_fn = NULL;
 MonitorFromWindow_Proc monitor_from_window_fn = NULL;
+EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL;
 
 #ifdef NTGUI_UNICODE
 #define unicode_append_menu AppendMenuW
@@ -258,7 +285,7 @@ check_x_display_info (Lisp_Object frame)
     return x_display_info_for_name (frame);
   else
     {
-      FRAME_PTR f;
+      struct frame *f;
 
       CHECK_LIVE_FRAME (frame);
       f = XFRAME (frame);
@@ -291,7 +318,7 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc)
 
 \f
 static Lisp_Object unwind_create_frame (Lisp_Object);
-static Lisp_Object unwind_create_tip_frame (Lisp_Object);
+static void unwind_create_tip_frame (Lisp_Object);
 static void my_create_window (struct frame *);
 static void my_create_tip_window (struct frame *);
 
@@ -317,7 +344,7 @@ void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
    not Emacs's own window.  */
 
 void
-x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
+x_real_positions (struct frame *f, int *xptr, int *yptr)
 {
   POINT pt;
   RECT rect;
@@ -992,7 +1019,7 @@ x_to_w32_color (const char * colorname)
 }
 
 void
-w32_regenerate_palette (FRAME_PTR f)
+w32_regenerate_palette (struct frame *f)
 {
   struct w32_palette_entry * list;
   LOGPALETTE *          log_palette;
@@ -1042,7 +1069,7 @@ w32_regenerate_palette (FRAME_PTR f)
 #if 0
 /* Keep these around in case we ever want to track color usage. */
 void
-w32_map_color (FRAME_PTR f, COLORREF color)
+w32_map_color (struct frame *f, COLORREF color)
 {
   struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
 
@@ -1073,7 +1100,7 @@ w32_map_color (FRAME_PTR f, COLORREF color)
 }
 
 void
-w32_unmap_color (FRAME_PTR f, COLORREF color)
+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;
@@ -1126,7 +1153,7 @@ gamma_correct (struct frame *f, COLORREF *color)
    If ALLOC is nonzero, allocate a new colormap cell.  */
 
 int
-w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc)
+w32_defined_color (struct frame *f, const char *color, XColor *color_def, int alloc)
 {
   register Lisp_Object tem;
   COLORREF w32_color_ref;
@@ -1197,7 +1224,7 @@ w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc)
    ARG says.  */
 
 int
-x_decode_color (FRAME_PTR f, Lisp_Object arg, int def)
+x_decode_color (struct frame *f, Lisp_Object arg, int def)
 {
   XColor cdef;
 
@@ -1498,7 +1525,7 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 
 
 void
-x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   set_frame_cursor_types (f, arg);
 
@@ -1760,7 +1787,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
    specified a name for the frame; the name will override any set by the
    redisplay code.  */
 void
-x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   x_set_name (f, arg, 1);
 }
@@ -1769,7 +1796,7 @@ x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
    name; names set this way will never override names set by the user's
    lisp code.  */
 void
-x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   x_set_name (f, arg, 0);
 }
@@ -3175,22 +3202,41 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
          HIMC context;
          struct window *w;
 
+         /* Implementation note: The code below does something that
+            one shouldn't do: it accesses the window object from a
+            separate thread, while the main (a.k.a. "Lisp") thread
+            runs and can legitimately delete and even GC it.  That is
+            why we are extra careful not to futz with a window that
+            is different from the one recorded when the system caret
+            coordinates were last modified.  That is also why we are
+            careful not to move the IME window if the window
+            described by W was deleted, as indicated by its buffer
+            field being reset to nil.  */
          f = x_window_to_frame (dpyinfo, hwnd);
+         if (!(f && FRAME_LIVE_P (f)))
+           break;
          w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+         /* Punt if someone changed the frame's selected window
+            behind our back. */
+         if (w != w32_system_caret_window)
+           break;
 
          form.dwStyle = CFS_RECT;
          form.ptCurrentPos.x = w32_system_caret_x;
          form.ptCurrentPos.y = w32_system_caret_y;
 
          form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
-         form.rcArea.top = WINDOW_TOP_EDGE_Y (w);
-         if (BUFFERP (w->contents))
-           form.rcArea.top += WINDOW_HEADER_LINE_HEIGHT (w);
+         form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
+                            + w32_system_caret_hdr_height);
          form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
                               - WINDOW_RIGHT_MARGIN_WIDTH (w)
                               - WINDOW_RIGHT_FRINGE_WIDTH (w));
          form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
-                               - WINDOW_MODE_LINE_HEIGHT (w));
+                               - w32_system_caret_mode_height);
+
+         /* Punt if the window was deleted behind our back.  */
+         if (!BUFFERP (w->contents))
+           break;
 
          context = get_ime_context_fn (hwnd);
 
@@ -4078,12 +4124,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.  */
-
-  {
-    char *str = SSDATA (Vx_resource_name);
-    f->namebuf = xmalloc (strlen (str) + 1);
-    strcpy (f->namebuf, str);
-  }
+  f->namebuf = xstrdup (SSDATA (Vx_resource_name));
 
   my_create_window (f);
 
@@ -4136,9 +4177,6 @@ x_icon (struct frame *f, Lisp_Object parms)
 
   block_input ();
 
-  if (! EQ (icon_x, Qunbound))
-    x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
-
 #if 0 /* TODO */
   /* Start up iconic or window? */
   x_wm_set_window_state
@@ -4214,6 +4252,12 @@ unwind_create_frame (Lisp_Object frame)
   return Qnil;
 }
 
+static void
+do_unwind_create_frame (Lisp_Object frame)
+{
+  unwind_create_frame (frame);
+}
+
 static void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
@@ -4354,7 +4398,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
 /*  FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
 
   /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe.  */
-  record_unwind_protect (unwind_create_frame, frame);
+  record_unwind_protect (do_unwind_create_frame, frame);
 #ifdef GLYPH_DEBUG
   image_cache_refcount =
     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
@@ -4596,7 +4640,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
   (Lisp_Object color, Lisp_Object frame)
 {
   XColor foo;
-  FRAME_PTR f = decode_window_system_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   CHECK_STRING (color);
 
@@ -4611,7 +4655,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
   (Lisp_Object color, Lisp_Object frame)
 {
   XColor foo;
-  FRAME_PTR f = decode_window_system_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   CHECK_STRING (color);
 
@@ -4657,7 +4701,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
        doc: /* Return the width in pixels of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel width for all
+physical monitors associated with DISPLAY.  To get information for
+each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object display)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4670,7 +4718,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
        doc: /* Return the height in pixels of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel height for all
+physical monitors associated with DISPLAY.  To get information for
+each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object display)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4762,41 +4814,46 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height,
        doc: /* Return the height in millimeters of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the height in millimeters for
+all physical monitors associated with DISPLAY.  To get information
+for each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object display)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
   HDC hdc;
-  int cap;
+  double mm_per_pixel;
 
-  hdc = GetDC (dpyinfo->root_window);
+  hdc = GetDC (NULL);
+  mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
+                 / GetDeviceCaps (hdc, VERTRES));
+  ReleaseDC (NULL, hdc);
 
-  cap = GetDeviceCaps (hdc, VERTSIZE);
-
-  ReleaseDC (dpyinfo->root_window, hdc);
-
-  return make_number (cap);
+  return make_number (x_display_pixel_height (dpyinfo) * mm_per_pixel + 0.5);
 }
 
 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
        doc: /* Return the width in millimeters of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the width in millimeters for
+all physical monitors associated with TERMINAL.  To get information
+for each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object display)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
-
   HDC hdc;
-  int cap;
-
-  hdc = GetDC (dpyinfo->root_window);
+  double mm_per_pixel;
 
-  cap = GetDeviceCaps (hdc, HORZSIZE);
+  hdc = GetDC (NULL);
+  mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
+                 / GetDeviceCaps (hdc, HORZRES));
+  ReleaseDC (NULL, hdc);
 
-  ReleaseDC (dpyinfo->root_window, hdc);
-
-  return make_number (cap);
+  return make_number (x_display_pixel_width (dpyinfo) * mm_per_pixel + 0.5);
 }
 
 DEFUN ("x-display-backing-store", Fx_display_backing_store,
@@ -4848,6 +4905,202 @@ If omitted or nil, that stands for the selected frame's display.  */)
   return Qnil;
 }
 
+static BOOL CALLBACK
+w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData)
+{
+  Lisp_Object *monitor_list = (Lisp_Object *) dwData;
+
+  *monitor_list = Fcons (make_save_ptr (monitor), *monitor_list);
+
+  return TRUE;
+}
+
+static Lisp_Object
+w32_display_monitor_attributes_list (void)
+{
+  Lisp_Object attributes_list = Qnil, primary_monitor_attributes = Qnil;
+  Lisp_Object monitor_list = Qnil, monitor_frames, rest, frame;
+  int i, n_monitors;
+  HMONITOR *monitors;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+
+  if (!(enum_display_monitors_fn && get_monitor_info_fn
+       && monitor_from_window_fn))
+    return Qnil;
+
+  if (!enum_display_monitors_fn (NULL, NULL, w32_monitor_enum,
+                                (LPARAM) &monitor_list)
+      || NILP (monitor_list))
+    return Qnil;
+
+  n_monitors = 0;
+  for (rest = monitor_list; CONSP (rest); rest = XCDR (rest))
+    n_monitors++;
+
+  monitors = xmalloc (n_monitors * sizeof (*monitors));
+  for (i = 0; i < n_monitors; i++)
+    {
+      monitors[i] = XSAVE_POINTER (XCAR (monitor_list), 0);
+      monitor_list = XCDR (monitor_list);
+    }
+
+  monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
+  FOR_EACH_FRAME (rest, frame)
+    {
+      struct frame *f = XFRAME (frame);
+
+      if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
+       {
+         HMONITOR monitor =
+           monitor_from_window_fn (FRAME_W32_WINDOW (f),
+                                   MONITOR_DEFAULT_TO_NEAREST);
+
+         for (i = 0; i < n_monitors; i++)
+           if (monitors[i] == monitor)
+             break;
+
+         if (i < n_monitors)
+           ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
+       }
+    }
+
+  GCPRO3 (attributes_list, primary_monitor_attributes, monitor_frames);
+
+  for (i = 0; i < n_monitors; i++)
+    {
+      Lisp_Object geometry, workarea, name, attributes = Qnil;
+      HDC hdc;
+      int width_mm, height_mm;
+      struct MONITOR_INFO_EX mi;
+
+      mi.cbSize = sizeof (mi);
+      if (!get_monitor_info_fn (monitors[i], (struct MONITOR_INFO *) &mi))
+       continue;
+
+      hdc = CreateDCA ("DISPLAY", mi.szDevice, NULL, NULL);
+      if (hdc == NULL)
+       continue;
+      width_mm = GetDeviceCaps (hdc, HORZSIZE);
+      height_mm = GetDeviceCaps (hdc, VERTSIZE);
+      DeleteDC (hdc);
+
+      attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
+                         attributes);
+
+      name = DECODE_SYSTEM (build_unibyte_string (mi.szDevice));
+
+      attributes = Fcons (Fcons (Qname, name), attributes);
+
+      attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
+                         attributes);
+
+      workarea = list4i (mi.rcWork.left, mi.rcWork.top,
+                        mi.rcWork.right - mi.rcWork.left,
+                        mi.rcWork.bottom - mi.rcWork.top);
+      attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
+
+      geometry = list4i (mi.rcMonitor.left, mi.rcMonitor.top,
+                        mi.rcMonitor.right - mi.rcMonitor.left,
+                        mi.rcMonitor.bottom - mi.rcMonitor.top);
+      attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
+
+      if (mi.dwFlags & MONITORINFOF_PRIMARY)
+       primary_monitor_attributes = attributes;
+      else
+       attributes_list = Fcons (attributes, attributes_list);
+    }
+
+  if (!NILP (primary_monitor_attributes))
+    attributes_list = Fcons (primary_monitor_attributes, attributes_list);
+
+  UNGCPRO;
+
+  xfree (monitors);
+
+  return attributes_list;
+}
+
+static Lisp_Object
+w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo)
+{
+  Lisp_Object geometry, workarea, frames, rest, frame, attributes = Qnil;
+  HDC hdc;
+  double mm_per_pixel;
+  int pixel_width, pixel_height, width_mm, height_mm;
+  RECT workarea_rect;
+
+  /* Fallback: treat (possibly) multiple physical monitors as if they
+     formed a single monitor as a whole.  This should provide a
+     consistent result at least on single monitor environments.  */
+  attributes = Fcons (Fcons (Qname, build_string ("combined screen")),
+                     attributes);
+
+  frames = Qnil;
+  FOR_EACH_FRAME (rest, frame)
+    {
+      struct frame *f = XFRAME (frame);
+
+      if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
+       frames = Fcons (frame, frames);
+    }
+  attributes = Fcons (Fcons (Qframes, frames), attributes);
+
+  pixel_width = x_display_pixel_width (dpyinfo);
+  pixel_height = x_display_pixel_height (dpyinfo);
+
+  hdc = GetDC (NULL);
+  mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
+                 / GetDeviceCaps (hdc, HORZRES));
+  width_mm = pixel_width * mm_per_pixel + 0.5;
+  mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
+                 / GetDeviceCaps (hdc, VERTRES));
+  height_mm = pixel_height * mm_per_pixel + 0.5;
+  ReleaseDC (NULL, hdc);
+  attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
+                     attributes);
+
+  /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but
+     we don't care.  */
+  geometry = list4i (GetSystemMetrics (SM_XVIRTUALSCREEN),
+                    GetSystemMetrics (SM_YVIRTUALSCREEN),
+                    pixel_width, pixel_height);
+  if (SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0))
+    workarea = list4i (workarea_rect.left, workarea_rect.top,
+                      workarea_rect.right - workarea_rect.left,
+                      workarea_rect.bottom - workarea_rect.top);
+  else
+    workarea = geometry;
+  attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
+
+  attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
+
+  return list1 (attributes);
+}
+
+DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list,
+       Sw32_display_monitor_attributes_list,
+       0, 1, 0,
+       doc: /* Return a list of physical monitor attributes on the W32 display DISPLAY.
+
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Internal use only, use `display-monitor-attributes-list' instead.  */)
+  (Lisp_Object display)
+{
+  struct w32_display_info *dpyinfo = check_x_display_info (display);
+  Lisp_Object attributes_list;
+
+  block_input ();
+  attributes_list = w32_display_monitor_attributes_list ();
+  if (NILP (attributes_list))
+    attributes_list = w32_display_monitor_attributes_list_fallback (dpyinfo);
+  unblock_input ();
+
+  return attributes_list;
+}
+
 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
        doc: /* Set the sound generated when the bell is rung.
 SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
@@ -4878,19 +5131,6 @@ SOUND is nil to use the normal beep.  */)
   return sound;
 }
 
-\f
-int
-x_pixel_width (register struct frame *f)
-{
-  return FRAME_PIXEL_WIDTH (f);
-}
-
-int
-x_pixel_height (register struct frame *f)
-{
-  return FRAME_PIXEL_HEIGHT (f);
-}
-
 int
 x_screen_planes (register struct frame *f)
 {
@@ -5332,7 +5572,7 @@ Window tip_window;
 Lisp_Object last_show_tip_args;
 
 
-static Lisp_Object
+static void
 unwind_create_tip_frame (Lisp_Object frame)
 {
   Lisp_Object deleted;
@@ -5343,8 +5583,6 @@ unwind_create_tip_frame (Lisp_Object frame)
       tip_window = NULL;
       tip_frame = Qnil;
     }
-
-  return deleted;
 }
 
 
@@ -6367,7 +6605,7 @@ screen saver if defined.
 If optional parameter FRAME is not specified, use selected frame.  */)
   (Lisp_Object command, Lisp_Object frame)
 {
-  FRAME_PTR f = decode_window_system_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   CHECK_NUMBER (command);
 
@@ -7340,6 +7578,10 @@ syms_of_w32fns (void)
   DEFSYM (Qcontrol, "control");
   DEFSYM (Qshift, "shift");
   DEFSYM (Qfont_param, "font-parameter");
+  DEFSYM (Qgeometry, "geometry");
+  DEFSYM (Qworkarea, "workarea");
+  DEFSYM (Qmm_size, "mm-size");
+  DEFSYM (Qframes, "frames");
   /* This is the end of symbol initialization.  */
 
 
@@ -7629,6 +7871,7 @@ only be necessary if the default setting causes problems.  */);
 
   defsubr (&Sw32_define_rgb_color);
   defsubr (&Sw32_default_color_map);
+  defsubr (&Sw32_display_monitor_attributes_list);
   defsubr (&Sw32_send_sys_command);
   defsubr (&Sw32_shell_execute);
   defsubr (&Sw32_register_hot_key);
@@ -7690,6 +7933,8 @@ globals_of_w32fns (void)
     GetProcAddress (user32_lib, "GetMonitorInfoA");
   monitor_from_window_fn = (MonitorFromWindow_Proc)
     GetProcAddress (user32_lib, "MonitorFromWindow");
+  enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
+    GetProcAddress (user32_lib, "EnumDisplayMonitors");
 
   {
     HMODULE imm32_lib = GetModuleHandle ("imm32.dll");