/* Graphical user interface functions for the Microsoft Windows API.
-Copyright (C) 1989, 1992-2014 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <fcntl.h>
#include <unistd.h>
+#include <c-ctype.h>
+
#include "lisp.h"
#include "w32term.h"
#include "frame.h"
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
-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)
typedef LONG (WINAPI * ImmGetCompositionString_Proc)
(IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
-typedef HWND (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
-typedef HWND (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
+typedef BOOL (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
+typedef BOOL (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
IN COMPOSITIONFORM *form);
typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
typedef BOOL (WINAPI * GetMonitorInfo_Proc)
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);
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);
/* Convert (0, 0) in the client area to screen co-ordinates. */
ClientToScreen (FRAME_W32_WINDOW (f), &pt);
- /* Remember x_pixels_diff and y_pixels_diff. */
- f->x_pixels_diff = pt.x - rect.left;
- f->y_pixels_diff = pt.y - rect.top;
-
*xptr = rect.left;
*yptr = rect.top;
}
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;
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));
/* 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. */
void
x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int result;
+ bool result;
if (NILP (arg) && NILP (oldval))
return;
if (FRAME_X_WINDOW (f) != 0)
{
- adjust_frame_size (f, -1, -1, 3, 0);
+ adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
if (FRAME_VISIBLE_P (f))
x_clear_under_internal_border (f);
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, 1);
+ adjust_frame_size (f, -1, -1, 2, true, Qmenu_bar_lines);
/* Not sure whether this is needed. */
x_clear_under_internal_border (f);
int old_height = FRAME_TOOL_BAR_HEIGHT (f);
int lines = (height + unit - 1) / unit;
int old_text_height = FRAME_TEXT_HEIGHT (f);
+ Lisp_Object fullscreen;
/* 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;
- FRAME_TEXT_HEIGHT (f)
- = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f));
- FRAME_LINES (f)
- = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
- /* Store the `tool-bar-lines' and `height' frame parameters. */
+ /* 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)));
/* Recalculate toolbar height. */
f->n_tool_bar_rows = 0;
- adjust_frame_size (f, -1, -1, 4, 0);
-
+ adjust_frame_size (f, -1, -1,
+ ((!f->tool_bar_redisplayed_once
+ && (NILP (fullscreen =
+ get_frame_param (f, Qfullscreen))
+ || EQ (fullscreen, Qfullwidth))) ? 1
+ : (old_height == 0 || height == 0) ? 2
+ : 4),
+ false, Qtool_bar_lines);
+
+ /* 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);
}
+static void
+w32_set_title_bar_text (struct frame *f, Lisp_Object name)
+{
+ if (FRAME_W32_WINDOW (f))
+ {
+ block_input ();
+#ifdef __CYGWIN__
+ GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
+ GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
+#else
+ /* The frame's title many times shows the name of the file
+ visited in the selected window's buffer, so it makes sense to
+ support non-ASCII characters outside of the current system
+ codepage in the title. */
+ if (w32_unicode_filenames)
+ {
+ Lisp_Object encoded_title = ENCODE_UTF_8 (name);
+ wchar_t *title_w;
+ int tlen = pMultiByteToWideChar (CP_UTF8, 0, SSDATA (encoded_title),
+ -1, NULL, 0);
+
+ if (tlen > 0)
+ {
+ /* Windows truncates the title text beyond what fits on
+ a single line, so we can limit the length to some
+ reasonably large value, and use alloca. */
+ if (tlen > 10000)
+ tlen = 10000;
+ title_w = alloca ((tlen + 1) * sizeof (wchar_t));
+ pMultiByteToWideChar (CP_UTF8, 0, SSDATA (encoded_title), -1,
+ title_w, tlen);
+ title_w[tlen] = L'\0';
+ SetWindowTextW (FRAME_W32_WINDOW (f), title_w);
+ }
+ else /* Conversion to UTF-16 failed, so we punt. */
+ SetWindowTextA (FRAME_W32_WINDOW (f),
+ SSDATA (ENCODE_SYSTEM (name)));
+ }
+ else
+ SetWindowTextA (FRAME_W32_WINDOW (f), SSDATA (ENCODE_SYSTEM (name)));
+#endif
+ unblock_input ();
+ }
+}
/* Change the name of frame F to NAME. If NAME is nil, set F's name to
w32_id_name.
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. */
if (! NILP (f->title))
name = f->title;
- if (FRAME_W32_WINDOW (f))
- {
- block_input ();
- GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
- GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
- unblock_input ();
- }
+ w32_set_title_bar_text (f, name);
}
/* This function should be called when the user's lisp code has
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
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.
if (NILP (name))
name = f->name;
- if (FRAME_W32_WINDOW (f))
- {
- block_input ();
- GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
- GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
- unblock_input ();
- }
+ w32_set_title_bar_text (f, name);
}
void
}
static void
-w32_createwindow (struct frame *f)
+w32_createwindow (struct frame *f, int *coords)
{
HWND hwnd;
RECT rect;
- Lisp_Object top = Qunbound;
- Lisp_Object left = Qunbound;
- struct w32_display_info *dpyinfo = &one_w32_display_info;
+ int top;
+ int left;
rect.left = rect.top = 0;
rect.right = FRAME_PIXEL_WIDTH (f);
if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
{
- XSETINT (left, f->left_pos);
- XSETINT (top, f->top_pos);
+ left = f->left_pos;
+ top = f->top_pos;
}
- else if (EQ (left, Qunbound) && EQ (top, Qunbound))
+ else
{
- /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
- for anything that is not a number and is not Qunbound. */
- left = x_get_arg (dpyinfo, Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
- top = x_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
+ left = coords[0];
+ top = coords[1];
}
FRAME_W32_WINDOW (f) = hwnd
= CreateWindow (EMACS_CLASS,
f->namebuf,
f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
- EQ (left, Qunbound) ? CW_USEDEFAULT : XINT (left),
- EQ (top, Qunbound) ? CW_USEDEFAULT : XINT (top),
- rect.right - rect.left,
- rect.bottom - rect.top,
+ left, top,
+ rect.right - rect.left, rect.bottom - rect.top,
NULL,
NULL,
hinst,
the patch for XP is not publicly available until XP SP3,
and older versions will never be patched. */
CoInitialize (NULL);
- w32_createwindow ((struct frame *) msg.wParam);
+ w32_createwindow ((struct frame *) msg.wParam,
+ (int *) msg.lParam);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
emacs_abort ();
break;
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;
{
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;
field being reset to nil. */
f = x_window_to_frame (dpyinfo, hwnd);
if (!(f && FRAME_LIVE_P (f)))
- break;
+ goto dflt;
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;
+ goto dflt;
form.dwStyle = CFS_RECT;
form.ptCurrentPos.x = w32_system_caret_x;
/* Punt if the window was deleted behind our back. */
if (!BUFFERP (w->contents))
- break;
+ goto dflt;
context = get_ime_context_fn (hwnd);
if (!context)
- break;
+ goto dflt;
set_ime_composition_window_fn (context, &form);
release_ime_context_fn (hwnd, context);
}
+ /* We should "goto dflt" here to pass WM_IME_STARTCOMPOSITION to
+ DefWindowProc, so that the composition window will actually
+ be displayed. But doing so causes trouble with displaying
+ dialog boxes, such as the file selection dialog or font
+ selection dialog. So something else is needed to fix the
+ former without breaking the latter. See bug#11732. */
break;
case WM_IME_ENDCOMPOSITION:
my_create_window (struct frame * f)
{
MSG msg;
+ static int coords[2];
+ Lisp_Object left, top;
+ struct w32_display_info *dpyinfo = &one_w32_display_info;
- if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
+ /* When called with RES_TYPE_NUMBER, x_get_arg will return zero for
+ anything that is not a number and is not Qunbound. */
+ left = x_get_arg (dpyinfo, Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
+ top = x_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
+ if (EQ (left, Qunbound))
+ coords[0] = CW_USEDEFAULT;
+ else
+ coords[0] = XINT (left);
+ if (EQ (top, Qunbound))
+ coords[1] = CW_USEDEFAULT;
+ else
+ coords[1] = XINT (top);
+
+ if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW,
+ (WPARAM)f, (LPARAM)coords))
emacs_abort ();
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
}
/* 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 ();
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);
struct frame *f;
Lisp_Object frame, tem;
Lisp_Object name;
- int minibuffer_only = 0;
+ bool minibuffer_only = false;
long window_prompting = 0;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
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);
/* 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
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);
}
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, 1);
+ 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
"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);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
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);
x_default_parameter (f, parameters, Qscroll_bar_height, Qnil,
"scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER);
- /* Consider frame official, now. */
- f->official = true;
+ /* Allow x_set_window_size, now. */
+ f->can_x_set_window_size = true;
- adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 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 ();
+ /* Process fullscreen parameter here in the hope that normalizing a
+ fullheight/fullwidth frame will produce the size set by the last
+ adjust_frame_size call. */
+ x_default_parameter (f, parameters, Qfullscreen, Qnil,
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+
/* Make the window appear on the frame and enable display, unless
the caller says not to. However, with explicit parent, Emacs
cannot control visibility, so don't try. */
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;
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));
}
DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
- doc: /* Return the "vendor ID" string of the W32 system (Microsoft).
-The optional argument DISPLAY specifies which display to ask about.
-DISPLAY should be either a frame or a display name (a string).
+ doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
+
+\(Labeling every distributor as a "vendor" embodies the false assumption
+that operating systems cannot be developed and distributed noncommercially.)
+
+For GNU and Unix systems, this queries the X server software; for
+MS-Windows, this queries the OS.
+
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be a terminal object, a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display. */)
- (Lisp_Object display)
+ (Lisp_Object terminal)
{
return build_string ("Microsoft Corp.");
}
DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
- doc: /* Return the version numbers of the server of DISPLAY.
-The value is a list of three integers: the major and minor
-version numbers of the X Protocol in use, and the distributor-specific
-release number. See also the function `x-server-vendor'.
+ doc: /* Return the version numbers of the GUI software on TERMINAL.
+The value is a list of three integers specifying the version of the GUI
+software in use.
-The optional argument DISPLAY specifies which display to ask about.
-DISPLAY should be either a frame or a display name (a string).
+For GNU and Unix system, the first 2 numbers are the version of the X
+Protocol used on TERMINAL and the 3rd number is the distributor-specific
+release number. For MS-Windows, the 3 numbers report the version and
+the build number of the OS.
+
+See also the function `x-server-vendor'.
+
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be a terminal object, a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display. */)
- (Lisp_Object display)
+ (Lisp_Object terminal)
{
return list3i (w32_major_version, w32_minor_version, w32_build_number);
}
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;
{
char basename[ MAX_PATH ], *str;
- lispstrcpy (basename, Vinvocation_name);
+ lispstpcpy (basename, Vinvocation_name);
str = strrchr (basename, '.');
if (str) *str = 0;
Vinvocation_name = build_string (basename);
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3;
struct kboard *kb;
- int face_change_count_before = face_change_count;
+ bool face_change_before = face_change;
Lisp_Object buffer;
struct buffer *old_buffer;
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);
#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);
}
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;
SET_FRAME_COLS (f, 0);
SET_FRAME_LINES (f, 0);
adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
- height * FRAME_LINE_HEIGHT (f), 0, 1);
+ height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
Fmodify_frame_parameters (frame, colors);
}
- f->no_split = 1;
+ f->no_split = true;
UNGCPRO;
below. And the frame needs to be on Vframe_list or making it
visible won't work. */
Vframe_list = Fcons (frame, Vframe_list);
- f->official = true;
+ 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
+ and similar will set face_change, which leads to the
clearing of all current matrices. Since this isn't necessary
- here, avoid it by resetting face_change_count to the value it
+ here, avoid it by resetting face_change to the value it
had before we created the tip frame. */
- face_change_count = face_change_count_before;
+ face_change = face_change_before;
/* Discard the unwind_protect. */
return unbind_to (count, frame);
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 ();
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;
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];
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])
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
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;
}
}
}
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;
}
}
/* 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 ();
#else /* !CYGWIN */
- current_dir = ENCODE_FILE (current_dir);
+ const char file_url_str[] = "file:///";
+ const int file_url_len = sizeof (file_url_str) - 1;
+ if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
+ {
+ /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
+ start a thread in some rare system configurations, for
+ unknown reasons. That thread is started in the context of
+ the Emacs process, but out of control of our code, and seems
+ to never exit afterwards. Each such thread reserves 8MB of
+ stack space (because that's the value recorded in the Emacs
+ executable at link time: Emacs needs a large stack). So a
+ large enough number of invocations of w32-shell-execute can
+ potentially cause the Emacs process to run out of available
+ address space, which is nasty. To work around this, we
+ convert such URLs to local file names, which seems to prevent
+ those threads from starting. See bug #20220. */
+ char *p = SSDATA (document) + file_url_len;
+
+ if (c_isalpha (*p) && p[1] == ':' && IS_DIRECTORY_SEP (p[2]))
+ document = Fsubstring_no_properties (document,
+ make_number (file_url_len), Qnil);
+ }
/* We have a situation here. If DOCUMENT is a relative file name,
but its name includes leading directories, i.e. it lives not in
CURRENT_DIR, but in its subdirectory, then ShellExecute below
Lisp_Object absdoc_encoded = ENCODE_FILE (absdoc);
if (faccessat (AT_FDCWD, SSDATA (absdoc_encoded), F_OK, AT_EACCESS) == 0)
- document = absdoc_encoded;
+ {
+ /* ShellExecute fails if DOCUMENT is a UNC with forward
+ slashes (expand-file-name above converts all backslashes
+ to forward slashes). Now that we know DOCUMENT is a
+ file, we can mirror all forward slashes into backslashes. */
+ unixtodos_filename (SSDATA (absdoc_encoded));
+ document = absdoc_encoded;
+ }
else
document = ENCODE_FILE (document);
}
else
document = ENCODE_FILE (document);
UNGCPRO;
+
+ current_dir = ENCODE_FILE (current_dir);
if (use_unicode)
{
wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
/* 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;
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);
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;
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);
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.
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_HEAP, 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.
MessageBeep (sound_type);
}
+DEFUN ("w32--menu-bar-in-use", Fw32__menu_bar_in_use, Sw32__menu_bar_in_use,
+ 0, 0, 0,
+ doc: /* Return non-nil when a menu-bar menu is being used.
+Internal use only. */)
+ (void)
+{
+ return menubar_in_use ? Qt : Qnil;
+}
+
\f
/***********************************************************************
Initialization
defsubr (&Sx_open_connection);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
+ defsubr (&Sx_frame_geometry);
defsubr (&Sx_synchronize);
/* W32 specific functions */
defsubr (&Sw32_toggle_lock_key);
defsubr (&Sw32_window_exists_p);
defsubr (&Sw32_frame_rect);
+ defsubr (&Sw32_frame_menu_bar_size);
defsubr (&Sw32_battery_status);
+ defsubr (&Sw32__menu_bar_in_use);
#ifdef WINDOWSNT
defsubr (&Sfile_system_info);