#include <limits.h>
#include <errno.h>
#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "lisp.h"
#include "w32term.h"
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
-/* Nonzero if using Windows. */
-
-static int w32_in_use;
-
Lisp_Object Qsuppress_icon;
Lisp_Object Qundefined_color;
Lisp_Object Qcancel_timer;
Lisp_Object Qctrl;
Lisp_Object Qcontrol;
Lisp_Object Qshift;
+static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
/* Prefix for system colors. */
#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
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);
typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
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;
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
static unsigned int sound_type = 0xFFFFFFFF;
#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
-\f
-/* Error if we are not connected to MS-Windows. */
-void
-check_w32 (void)
-{
- if (! w32_in_use)
- error ("MS-Windows not in use or not initialized");
-}
-
-/* Nonzero if we can use mouse menus.
- You should not call this unless HAVE_MENUS is defined. */
-
-int
-have_menus_p (void)
-{
- return w32_in_use;
-}
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
- and checking validity for W32. */
-
-FRAME_PTR
-check_x_frame (Lisp_Object frame)
-{
- FRAME_PTR f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
- if (! FRAME_W32_P (f))
- error ("Non-W32 frame used");
- return f;
-}
-
/* Let the user specify a display with a frame.
nil stands for the selected frame--or, if that is not a w32 frame,
the first display on the list. */
/* Return the Emacs frame-object corresponding to an w32 window.
It could be the frame's main window or an icon window. */
-/* This function can be called during GC, so use GC_xxx type test macros. */
-
struct frame *
x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc)
{
Lisp_Object tail, frame;
struct frame *f;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
continue;
\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 *);
*yptr = rect.top;
}
+/* Returns the window rectangle appropriate for the given fullscreen mode.
+ The normal rect parameter was the window's rectangle prior to entering
+ fullscreen mode. If multiple monitor support is available, the nearest
+ monitor to the window is chosen. */
+
+void
+w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal, RECT *rect)
+{
+ struct MONITOR_INFO mi = { sizeof(mi) };
+ if (monitor_from_window_fn && get_monitor_info_fn)
+ {
+ HMONITOR monitor =
+ monitor_from_window_fn (hwnd, MONITOR_DEFAULT_TO_NEAREST);
+ get_monitor_info_fn (monitor, &mi);
+ }
+ else
+ {
+ mi.rcMonitor.left = 0;
+ mi.rcMonitor.top = 0;
+ mi.rcMonitor.right = GetSystemMetrics (SM_CXSCREEN);
+ mi.rcMonitor.bottom = GetSystemMetrics (SM_CYSCREEN);
+ mi.rcWork.left = 0;
+ mi.rcWork.top = 0;
+ mi.rcWork.right = GetSystemMetrics (SM_CXMAXIMIZED);
+ mi.rcWork.bottom = GetSystemMetrics (SM_CYMAXIMIZED);
+ }
+
+ switch (fsmode)
+ {
+ case FULLSCREEN_BOTH:
+ rect->left = mi.rcMonitor.left;
+ rect->top = mi.rcMonitor.top;
+ rect->right = mi.rcMonitor.right;
+ rect->bottom = mi.rcMonitor.bottom;
+ break;
+ case FULLSCREEN_MAXIMIZED:
+ rect->left = mi.rcWork.left;
+ rect->top = mi.rcWork.top;
+ rect->right = mi.rcWork.right;
+ rect->bottom = mi.rcWork.bottom;
+ break;
+ case FULLSCREEN_WIDTH:
+ rect->left = mi.rcWork.left;
+ rect->top = normal.top;
+ rect->right = mi.rcWork.right;
+ rect->bottom = normal.bottom;
+ break;
+ case FULLSCREEN_HEIGHT:
+ rect->left = normal.left;
+ rect->top = mi.rcWork.top;
+ rect->right = normal.right;
+ rect->bottom = mi.rcWork.bottom;
+ break;
+ case FULLSCREEN_NONE:
+ default:
+ *rect = normal;
+ break;
+ }
+}
+
\f
DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
if (FRAME_W32_WINDOW (f))
{
- if (STRING_MULTIBYTE (name))
- name = ENCODE_SYSTEM (name);
-
block_input ();
- SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
+ GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
+ GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
unblock_input ();
}
}
if (FRAME_W32_WINDOW (f))
{
- if (STRING_MULTIBYTE (name))
- name = ENCODE_SYSTEM (name);
-
block_input ();
- SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
+ GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
+ GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
unblock_input ();
}
}
static BOOL
w32_init_class (HINSTANCE hinst)
{
-
if (w32_unicode_gui)
{
WNDCLASSW uwc;
static int
modifier_set (int vkey)
{
- if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
- return (GetKeyState (vkey) & 0x1);
+ /* Warning: The fact that VK_NUMLOCK is not treated as the other 2
+ toggle keys is not an omission! If you want to add it, you will
+ have to make changes in the default sub-case of the WM_KEYDOWN
+ switch, because if the NUMLOCK modifier is set, the code there
+ will directly convert any key that looks like an ASCII letter,
+ and also downcase those that look like upper-case ASCII. */
+ if (vkey == VK_CAPITAL)
+ {
+ if (NILP (Vw32_enable_caps_lock))
+ return 0;
+ else
+ return (GetKeyState (vkey) & 0x1);
+ }
+ if (vkey == VK_SCROLL)
+ {
+ if (NILP (Vw32_scroll_lock_modifier)
+ /* w32-scroll-lock-modifier can be any non-nil value that is
+ not one of the modifiers, in which case it shall be ignored. */
+ || !( EQ (Vw32_scroll_lock_modifier, Qhyper)
+ || EQ (Vw32_scroll_lock_modifier, Qsuper)
+ || EQ (Vw32_scroll_lock_modifier, Qmeta)
+ || EQ (Vw32_scroll_lock_modifier, Qalt)
+ || EQ (Vw32_scroll_lock_modifier, Qcontrol)
+ || EQ (Vw32_scroll_lock_modifier, Qshift)))
+ return 0;
+ else
+ return (GetKeyState (vkey) & 0x1);
+ }
+
if (!modifiers_recorded)
return (GetKeyState (vkey) & 0x8000);
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.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
- + WINDOW_HEADER_LINE_HEIGHT (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);
/* Don't restrict the sizing of tip frames. */
if (hwnd == tip_window)
return 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);
+ if (f && FRAME_PREV_FSMODE (f) != FULLSCREEN_NONE)
+ return 0;
+
{
WINDOWPLACEMENT wp;
LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
return retval;
}
+ case WM_EMACS_FILENOTIFY:
+ my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+ return 1;
default:
/* Check for messages registered at runtime. */
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
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)
{
XSETFRAME (frame, f);
- /* Note that Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
/* By default, make scrollbars the system standard width. */
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
/* 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;
specbind (Qx_resource_name, name);
}
- f->resx = dpyinfo->resx;
- f->resy = dpyinfo->resy;
-
if (uniscribe_available)
register_font_driver (&uniscribe_font_driver, f);
register_font_driver (&w32font_driver, f);
doc: /* Give FRAME input focus, raising to foreground if necessary. */)
(Lisp_Object frame)
{
- x_focus_on_frame (check_x_frame (frame));
+ x_focus_on_frame (decode_window_system_frame (frame));
return Qnil;
}
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
- FRAME_PTR f = check_x_frame (frame);
+ FRAME_PTR f = decode_window_system_frame (frame);
CHECK_STRING (color);
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
- FRAME_PTR f = check_x_frame (frame);
+ FRAME_PTR f = decode_window_system_frame (frame);
CHECK_STRING (color);
if (w32_defined_color (f, SDATA (color), &foo, 0))
- return list3 (make_number ((GetRValue (foo.pixel) << 8)
- | GetRValue (foo.pixel)),
- make_number ((GetGValue (foo.pixel) << 8)
- | GetGValue (foo.pixel)),
- make_number ((GetBValue (foo.pixel) << 8)
- | GetBValue (foo.pixel)));
+ return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel),
+ (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel),
+ (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel));
else
return Qnil;
}
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);
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);
If omitted or nil, that stands for the selected frame's display. */)
(Lisp_Object display)
{
- return Fcons (make_number (w32_major_version),
- Fcons (make_number (w32_minor_version),
- Fcons (make_number (w32_build_number), Qnil)));
+ return list3i (w32_major_version, w32_minor_version, w32_build_number);
}
DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
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;
+ double mm_per_pixel;
- hdc = GetDC (dpyinfo->root_window);
+ hdc = GetDC (NULL);
+ mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
+ / GetDeviceCaps (hdc, HORZRES));
+ ReleaseDC (NULL, hdc);
- cap = GetDeviceCaps (hdc, HORZSIZE);
-
- 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,
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 (make_unibyte_string (mi.szDevice,
+ strlen (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
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_char_width (register struct frame *f)
-{
- return FRAME_COLUMN_WIDTH (f);
-}
-
-int
-x_char_height (register struct frame *f)
-{
- return FRAME_LINE_HEIGHT (f);
-}
-
int
x_screen_planes (register struct frame *f)
{
if (dpyinfo == 0)
error ("Cannot connect to server %s", SDATA (name));
- w32_in_use = 1;
XSETFASTINT (Vwindow_system_version, w32_major_version);
return dpyinfo;
/* If initialization has already been done, return now to avoid
overwriting critical parts of one_w32_display_info. */
- if (w32_in_use)
+ if (window_system_available (NULL))
return Qnil;
if (! NILP (xrm_string))
error ("Cannot connect to server %s", SDATA (display));
}
- w32_in_use = 1;
-
XSETFASTINT (Vwindow_system_version, w32_major_version);
return Qnil;
}
(Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
CHECK_STRING (prop);
FRAME nil or omitted means use the selected frame. Value is PROP. */)
(Lisp_Object prop, Lisp_Object frame)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
CHECK_STRING (prop);
(Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
int rc;
Lisp_Object prop_value = Qnil;
Lisp_Object last_show_tip_args;
-static Lisp_Object
+static void
unwind_create_tip_frame (Lisp_Object frame)
{
Lisp_Object deleted;
tip_window = NULL;
tip_frame = Qnil;
}
-
- return deleted;
}
Lisp_Object buffer;
struct buffer *old_buffer;
- check_w32 ();
-
/* Use this general default value to start with until we know if
this frame has a specified name. */
Vx_resource_name = Vinvocation_name;
Finsert (1, &text);
set_buffer_internal_1 (old_buffer);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
record_unwind_protect (unwind_create_tip_frame, frame);
/* By setting the output method, we're essentially saying that
specbind (Qx_resource_name, name);
}
- f->resx = dpyinfo->resx;
- f->resy = dpyinfo->resy;
-
if (uniscribe_available)
register_font_driver (&uniscribe_font_driver, f);
register_font_driver (&w32font_driver, f);
GCPRO4 (string, parms, frame, timeout);
CHECK_STRING (string);
- f = check_x_frame (frame);
+ f = decode_window_system_frame (frame);
if (NILP (timeout))
timeout = make_number (5);
else
/* Set up the frame's root window. */
w = XWINDOW (FRAME_ROOT_WINDOW (f));
- wset_left_col (w, make_number (0));
- wset_top_line (w, make_number (0));
+ w->left_col = 0;
+ w->top_line = 0;
if (CONSP (Vx_max_tooltip_size)
&& INTEGERP (XCAR (Vx_max_tooltip_size))
&& INTEGERP (XCDR (Vx_max_tooltip_size))
&& XINT (XCDR (Vx_max_tooltip_size)) > 0)
{
- wset_total_cols (w, XCAR (Vx_max_tooltip_size));
- wset_total_lines (w, XCDR (Vx_max_tooltip_size));
+ w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
+ w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
}
else
{
- wset_total_cols (w, make_number (80));
- wset_total_lines (w, make_number (40));
+ w->total_cols = 80;
+ w->total_lines = 40;
}
- FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
+ FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
adjust_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+ set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents));
bset_truncate_lines (current_buffer, Qnil);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
int row_width;
/* Stop at the first empty row at the end. */
- if (!row->enabled_p || !row->displays_text_p)
+ if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
/* Let the row go over the full width of the frame. */
/* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
not in pixels. */
width /= WINDOW_FRAME_COLUMN_WIDTH (w);
- wset_total_cols (w, make_number (width));
+ w->total_cols = width;
FRAME_TOTAL_COLS (f) = width;
adjust_glyphs (f);
w->pseudo_window_p = 1;
struct glyph *last;
int row_width;
- if (!row->enabled_p || !row->displays_text_p)
+ if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
row->full_width_p = 1;
row_width = row->pixel_width;
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
/* Let redisplay know that we have made the frame visible already. */
- f->async_visible = 1;
+ SET_FRAME_VISIBLE (f, 1);
ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
}
#define FILE_NAME_COMBO_BOX cmb13
#define FILE_NAME_LIST lst1
-#ifdef NTGUI_UNICODE
-#define GUISTR(x) (L ## x)
-typedef wchar_t guichar_t;
-#else /* !NTGUI_UNICODE */
-#define GUISTR(x) x
-typedef char guichar_t;
-#endif /* NTGUI_UNICODE */
-
/* Callback for altering the behavior of the Open File dialog.
Makes the Filename text field contain "Current Directory" and be
read-only when "Directories" is selected in the filter. This
block_input ();
file_details->lpfnHook = file_dialog_callback;
-#ifdef NTGUI_UNICODE
- file_opened = GetOpenFileNameW (file_details);
-#else /* !NTGUI_UNICODE */
- file_opened = GetOpenFileNameA (file_details);
-#endif /* NTGUI_UNICODE */
+ file_opened = GUI_FN (GetOpenFileName) (file_details);
unblock_input ();
unbind_to (count, Qnil);
}
{
/* Get an Emacs string from the value Windows gave us. */
#ifdef NTGUI_UNICODE
- filename = from_unicode (
- make_unibyte_string (
- (char*) filename_buf,
- /* we get one of the two final 0 bytes for free. */
- 1 + sizeof (wchar_t) * wcslen (filename_buf)));
+ filename = from_unicode_buffer (filename_buf);
#else /* !NTGUI_UNICODE */
- dostounix_filename (filename_buf);
+ dostounix_filename (filename_buf, 0);
filename = DECODE_FILE (build_string (filename_buf));
#endif /* NTGUI_UNICODE */
If optional parameter FRAME is not specified, use selected frame. */)
(Lisp_Object command, Lisp_Object frame)
{
- FRAME_PTR f = check_x_frame (frame);
+ FRAME_PTR f = decode_window_system_frame (frame);
CHECK_NUMBER (command);
CHECK_STRING (document);
/* Encode filename, current directory and parameters. */
- current_dir = ENCODE_FILE (BVAR (current_buffer, directory));
- document = ENCODE_FILE (document);
+ current_dir = BVAR (current_buffer, directory);
+
+#ifdef CYGWIN
+ current_dir = Fcygwin_convert_file_name_to_windows (current_dir, Qt);
+ if (STRINGP (document))
+ document = Fcygwin_convert_file_name_to_windows (document, Qt);
+#endif /* CYGWIN */
+
+ current_dir = GUI_ENCODE_FILE (current_dir);
+ if (STRINGP (document))
+ document = GUI_ENCODE_FILE (document);
if (STRINGP (parameters))
- parameters = ENCODE_SYSTEM (parameters);
-
- if ((int) ShellExecute (NULL,
- (STRINGP (operation) ?
- SDATA (operation) : NULL),
- SDATA (document),
- (STRINGP (parameters) ?
- SDATA (parameters) : NULL),
- SDATA (current_dir),
- (INTEGERP (show_flag) ?
- XINT (show_flag) : SW_SHOWDEFAULT))
+ parameters = GUI_ENCODE_SYSTEM (parameters);
+
+ if ((int) GUI_FN (ShellExecute) (NULL,
+ (STRINGP (operation) ?
+ GUI_SDATA (operation) : NULL),
+ GUI_SDATA (document),
+ (STRINGP (parameters) ?
+ GUI_SDATA (parameters) : NULL),
+ GUI_SDATA (current_dir),
+ (INTEGERP (show_flag) ?
+ XINT (show_flag) : SW_SHOWDEFAULT))
> 32)
return Qt;
errstr = w32_strerror (0);
CHECK_VECTOR (key);
- if (XFASTINT (Flength (key)) != 1)
+ if (ASIZE (key) != 1)
return Qnil;
GCPRO1 (key);
- c = Faref (key, make_number (0));
+ c = AREF (key, 0);
if (CONSP (c) && lucid_event_type_list_p (c))
c = Fevent_convert_list (c);
}
\f
+#ifdef WINDOWSNT
DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
doc: /* Return storage information about the file system FILENAME is on.
Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
return value;
}
+#endif /* WINDOWSNT */
+
\f
DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
0, 0, 0, doc: /* Return the name of Windows default printer device. */)
DWORD data;
} version;
+ /* Cache the module handle of Emacs itself. */
+ hinst = GetModuleHandle (NULL);
+
/* Cache the version of the operating system. */
version.data = GetVersion ();
w32_major_version = version.info.major;
syms_of_w32fns (void)
{
globals_of_w32fns ();
- /* This is zero if not using MS-Windows. */
- w32_in_use = 0;
track_mouse_window = NULL;
w32_visible_system_caret_hwnd = NULL;
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. */
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);
defsubr (&Sw32_window_exists_p);
defsubr (&Sw32_battery_status);
+#ifdef WINDOWSNT
defsubr (&Sfile_system_info);
+#endif
+
defsubr (&Sdefault_printer_name);
defsubr (&Sset_message_beep);
- check_window_system_func = check_w32;
-
hourglass_hwnd = NULL;
defsubr (&Sx_show_tip);
GetProcAddress (user32_lib, "MonitorFromPoint");
get_monitor_info_fn = (GetMonitorInfo_Proc)
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");
syms_of_w32uniscribe ();
}
+typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
+ PULONG);
+
+#define BACKTRACE_LIMIT_MAX 62
+
+int
+w32_backtrace (void **buffer, int limit)
+{
+ static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace = NULL;
+ HMODULE hm_kernel32 = NULL;
+
+ if (!s_pfn_CaptureStackBackTrace)
+ {
+ hm_kernel32 = LoadLibrary ("Kernel32.dll");
+ s_pfn_CaptureStackBackTrace =
+ (CaptureStackBackTrace_proc) GetProcAddress (hm_kernel32,
+ "RtlCaptureStackBackTrace");
+ }
+ if (s_pfn_CaptureStackBackTrace)
+ return s_pfn_CaptureStackBackTrace (0, min (BACKTRACE_LIMIT_MAX, limit),
+ buffer, NULL);
+ return 0;
+}
+
void
emacs_abort (void)
{
button = MessageBox (NULL,
"A fatal error has occurred!\n\n"
"Would you like to attach a debugger?\n\n"
- "Select YES to debug, NO to abort Emacs"
+ "Select:\n"
+ "YES -- to debug Emacs, or\n"
+ "NO -- to abort Emacs and produce a backtrace\n"
+ " (emacs_backtrace.txt in current directory)."
#if __GNUC__
"\n\n(type \"gdb -p <emacs-PID>\" and\n"
"\"continue\" inside GDB before clicking YES.)"
exit (2); /* tell the compiler we will never return */
case IDNO:
default:
- abort ();
- break;
+ {
+ void *stack[BACKTRACE_LIMIT_MAX + 1];
+ int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1);
+
+ if (i)
+ {
+#ifdef CYGWIN
+ int stderr_fd = 2;
+#else
+ HANDLE errout = GetStdHandle (STD_ERROR_HANDLE);
+ int stderr_fd = -1;
+#endif
+ int errfile_fd = -1;
+ int j;
+
+#ifndef CYGWIN
+ if (errout && errout != INVALID_HANDLE_VALUE)
+ stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY);
+#endif
+ if (stderr_fd >= 0)
+ write (stderr_fd, "\r\nBacktrace:\r\n", 14);
+#ifdef CYGWIN
+#define _open open
+#endif
+ errfile_fd = _open ("emacs_backtrace.txt", O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
+ if (errfile_fd >= 0)
+ {
+ lseek (errfile_fd, 0L, SEEK_END);
+ write (errfile_fd, "\r\nBacktrace:\r\n", 14);
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ char buf[INT_BUFSIZE_BOUND (void *)];
+
+ /* stack[] gives the return addresses, whereas we want
+ the address of the call, so decrease each address
+ by approximate size of 1 CALL instruction. */
+ sprintf (buf, "0x%p\r\n", (char *)stack[j] - sizeof(void *));
+ if (stderr_fd >= 0)
+ write (stderr_fd, buf, strlen (buf));
+ if (errfile_fd >= 0)
+ write (errfile_fd, buf, strlen (buf));
+ }
+ if (i == BACKTRACE_LIMIT_MAX)
+ {
+ if (stderr_fd >= 0)
+ write (stderr_fd, "...\r\n", 5);
+ if (errfile_fd >= 0)
+ write (errfile_fd, "...\r\n", 5);
+ }
+ if (errfile_fd >= 0)
+ close (errfile_fd);
+ }
+ abort ();
+ break;
+ }
}
}
+
+#ifdef NTGUI_UNICODE
+
+Lisp_Object
+ntgui_encode_system (Lisp_Object str)
+{
+ Lisp_Object encoded;
+ to_unicode (str, &encoded);
+ return encoded;
+}
+
+#endif /* NTGUI_UNICODE */