/* Timer ID used for button2 emulation */
#define BUTTON_2_TIMER_ID 1
-extern Lisp_Object
-mswindows_get_toolbar_button_text (struct frame* f, int command_id);
-extern Lisp_Object
-mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
-extern Lisp_Object
-mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id);
-
static Lisp_Object mswindows_find_frame (HWND hwnd);
static Lisp_Object mswindows_find_console (HWND hwnd);
static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods,
/* Number of wait handles */
static int mswindows_waitable_count=0;
#endif /* HAVE_MSG_SELECT */
+
/* Brush for painting widgets */
static HBRUSH widget_brush = 0;
static LONG last_widget_brushed = 0;
SOCKET s; /* Socket handle (which is a Win32 handle) */
OVERLAPPED ov; /* Overlapped I/O structure */
void* buffer; /* Buffer. Allocated for input stream only */
- unsigned int bufsize; /* Number of bytes last read */
- unsigned int bufpos; /* Position in buffer for next fetch */
+ unsigned long bufsize; /* Number of bytes last read */
+ unsigned long bufpos; /* Position in buffer for next fetch */
unsigned int error_p :1; /* I/O Error seen */
unsigned int eof_p :1; /* EOF Error seen */
unsigned int pending_p :1; /* There is a pending I/O operation */
}
static ssize_t
-winsock_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+winsock_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
}
static Lisp_Object
-make_winsock_stream_1 (SOCKET s, LPARAM param, CONST char *mode)
+make_winsock_stream_1 (SOCKET s, LPARAM param, const char *mode)
{
Lisp_Object obj;
Lstream *lstr = Lstream_new (lstream_winsock, mode);
/************************************************************************/
static int
-mswindows_user_event_p (struct Lisp_Event* sevt)
+mswindows_user_event_p (Lisp_Event* sevt)
{
return (sevt->event_type == key_press_event
|| sevt->event_type == button_press_event
Lisp_Object object)
{
Lisp_Object event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* e = XEVENT (event);
+ Lisp_Event* e = XEVENT (event);
e->event_type = misc_user_event;
e->channel = channel;
+ e->timestamp = GetTickCount ();
e->event.misc.function = function;
e->event.misc.object = object;
}
void
-mswindows_enqueue_magic_event (HWND hwnd, UINT message)
+mswindows_enqueue_magic_event (HWND hwnd, UINT msg)
{
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* event = XEVENT (emacs_event);
+ Lisp_Event* event = XEVENT (emacs_event);
event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil;
event->timestamp = GetMessageTime();
event->event_type = magic_event;
- EVENT_MSWINDOWS_MAGIC_TYPE (event) = message;
+ EVENT_MSWINDOWS_MAGIC_TYPE (event) = msg;
mswindows_enqueue_dispatch_event (emacs_event);
}
static void
-mswindows_enqueue_process_event (struct Lisp_Process* p)
+mswindows_enqueue_process_event (Lisp_Process* p)
{
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* event = XEVENT (emacs_event);
+ Lisp_Event* event = XEVENT (emacs_event);
Lisp_Object process;
XSETPROCESS (process, p);
}
static void
-mswindows_enqueue_mouse_button_event (HWND hwnd, UINT message, POINTS where, DWORD when)
+mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, DWORD when)
{
/* We always use last message time, because mouse button
recognition will fail */
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* event = XEVENT(emacs_event);
+ Lisp_Event* event = XEVENT(emacs_event);
event->channel = mswindows_find_frame(hwnd);
event->timestamp = when;
event->event.button.button =
- (message==WM_LBUTTONDOWN || message==WM_LBUTTONUP) ? 1 :
- ((message==WM_RBUTTONDOWN || message==WM_RBUTTONUP) ? 3 : 2);
+ (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 :
+ ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2);
event->event.button.x = where.x;
event->event.button.y = where.y;
event->event.button.modifiers = mswindows_modifier_state (NULL, 0);
- if (message==WM_LBUTTONDOWN || message==WM_MBUTTONDOWN ||
- message==WM_RBUTTONDOWN)
+ if (msg==WM_LBUTTONDOWN || msg==WM_MBUTTONDOWN ||
+ msg==WM_RBUTTONDOWN)
{
event->event_type = button_press_event;
SetCapture (hwnd);
mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods)
{
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* event = XEVENT(emacs_event);
+ Lisp_Event* event = XEVENT(emacs_event);
event->channel = mswindows_find_console(hwnd);
event->timestamp = GetMessageTime();
mswindows_dequeue_dispatch_event ()
{
Lisp_Object event;
- struct Lisp_Event* sevt;
+ Lisp_Event* sevt;
assert (!NILP(mswindows_u_dispatch_event_queue) ||
!NILP(mswindows_s_dispatch_event_queue));
*/
Lisp_Object
-mswindows_cancel_dispatch_event (struct Lisp_Event *match)
+mswindows_cancel_dispatch_event (Lisp_Event *match)
{
Lisp_Object event;
Lisp_Object previous_event = Qnil;
EVENT_CHAIN_LOOP (event, *head)
{
- struct Lisp_Event *e = XEVENT (event);
+ Lisp_Event *e = XEVENT (event);
if ((e->event_type == match->event_type) &&
((e->event_type == timeout_event) ?
(e->event.timeout.interval_id == match->event.timeout.interval_id) :
return result;
}
+/*
+ * KEYBOARD_ONLY_P is set to non-zero when we are called from
+ * QUITP, and are interesting in keyboard messages only.
+ */
static void
mswindows_drain_windows_queue ()
{
MSG msg;
+
+ /* should call mswindows_need_event_in_modal_loop() if in modal loop */
+ assert (!mswindows_in_modal_loop);
+
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
- /* we have to translate messages that are not sent to the main
- window. this is so that key presses work ok in things like
- edit fields. however, we *musn't* translate message for the
+ /* We have to translate messages that are not sent to the main
+ window. This is so that key presses work ok in things like
+ edit fields. However, we *musn't* translate message for the
main window as this is handled in the wnd proc. */
- if ( GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD )
+ if (GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD)
{
TranslateMessage (&msg);
}
+ else if (msg.message == WM_PAINT)
+ {
+ /* hdc will be NULL unless this is a subwindow - in which case we
+ shouldn't have received a paint message for it here. */
+ assert (msg.wParam == 0);
+
+ /* Queue a magic event for handling when safe */
+ mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT);
+
+ /* Don't dispatch. WM_PAINT is always the last message in the
+ queue so it's OK to just return. */
+ return;
+ }
DispatchMessage (&msg);
mswindows_unmodalize_signal_maybe ();
}
return;
}
- /* Have to drain Windows message queue first, otherwise, we may miss
- quit char when called from quit_p */
- mswindows_drain_windows_queue ();
-
while (NILP (mswindows_u_dispatch_event_queue)
&& NILP (mswindows_s_dispatch_event_queue))
{
{
struct console *c = tty_find_console_from_fd (i);
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event* event = XEVENT (emacs_event);
+ Lisp_Event* event = XEVENT (emacs_event);
assert (c);
if (read_event_from_tty_or_stream_desc (event, c, i))
{
if (FD_ISSET (i, &process_only_mask))
{
- struct Lisp_Process *p =
+ Lisp_Process *p =
get_process_from_usid (FD_TO_USID(i));
mswindows_enqueue_process_event (p);
{
int ix = active - WAIT_OBJECT_0;
/* First, try to find which process' output has signaled */
- struct Lisp_Process *p =
+ Lisp_Process *p =
get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix]));
if (p != NULL)
{
mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
{
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
- struct Lisp_Event *event = XEVENT (emacs_event);
+ Lisp_Event *event = XEVENT (emacs_event);
if (KillTimer (NULL, id_timer))
--mswindows_pending_timers_count;
{ mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } };
if (!(hszItem || DdeCmpStringHandles (hszItem, mswindows_dde_service)) &&
- !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)));
+ !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)))
return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs,
sizeof (pairs), 0L, 0, uFmt, 0));
}
if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))
{
DWORD len = DdeGetData (hdata, NULL, 0, 0);
- char *cmd = alloca (len+1);
+ LPBYTE cmd = (LPBYTE) alloca (len+1);
char *end;
char *filename;
struct gcpro gcpro1, gcpro2;
Lisp_Object l_dndlist = Qnil;
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
Lisp_Object frmcons, devcons, concons;
- struct Lisp_Event *event = XEVENT (emacs_event);
+ Lisp_Event *event = XEVENT (emacs_event);
DdeGetData (hdata, cmd, len, 0);
cmd[len] = '\0';
#endif
/*
+ * Helper to do repainting - repaints can happen both from the windows
+ * procedure and from magic events
+ */
+void
+mswindows_handle_paint (struct frame *frame)
+ {
+ HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame);
+
+ /* According to the docs we need to check GetUpdateRect() before
+ actually doing a WM_PAINT */
+ if (GetUpdateRect (hwnd, NULL, FALSE))
+ {
+ PAINTSTRUCT paintStruct;
+ int x, y, width, height;
+
+ BeginPaint (hwnd, &paintStruct);
+ x = paintStruct.rcPaint.left;
+ y = paintStruct.rcPaint.top;
+ width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
+ height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
+ /* Normally we want to ignore expose events when child
+ windows are unmapped, however once we are in the guts of
+ WM_PAINT we need to make sure that we don't register
+ unmaps then because they will not actually occur. */
+ if (!check_for_ignored_expose (frame, x, y, width, height))
+ {
+ hold_ignored_expose_registration = 1;
+ mswindows_redraw_exposed_area (frame, x, y, width, height);
+ hold_ignored_expose_registration = 0;
+ }
+ EndPaint (hwnd, &paintStruct);
+ }
+ }
+
+/*
+ * Returns 1 if a key is a real modifier or special key, which
+ * is better handled by DefWindowProc
+ */
+static int
+key_needs_default_processing_p (UINT vkey)
+{
+ if (mswindows_meta_activates_menu && vkey == VK_MENU)
+ return 1;
+
+ return 0;
+}
+
+/*
* The windows procedure for the window class XEMACS_CLASS
*/
LRESULT WINAPI
Lisp_Object emacs_event = Qnil;
Lisp_Object fobj = Qnil;
- struct Lisp_Event *event;
+ Lisp_Event *event;
struct frame *frame;
struct mswindows_frame* msframe;
SetKeyboardState (keymap);
}
};
- goto defproc;
+ if (key_needs_default_processing_p (wParam))
+ goto defproc;
+ else
+ break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
/* Clear control and alt modifiers unless AltGr is pressed */
keymap [VK_RCONTROL] = 0;
keymap [VK_LMENU] = 0;
- if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) || !(keymap [VK_RMENU] & 0x80))
+ if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80)
+ || !(keymap [VK_RMENU] & 0x80))
{
keymap [VK_LCONTROL] = 0;
keymap [VK_CONTROL] = 0;
SetKeyboardState (keymap_orig);
} /* else */
}
- /* F10 causes menu activation by default. We do not want this */
- if (wParam != VK_F10 && (mswindows_meta_activates_menu || wParam != VK_MENU))
+ if (key_needs_default_processing_p (wParam))
goto defproc;
- break;
+ else
+ break;
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
{
/* I think this is safe since the text will only go away
when the toolbar does...*/
- GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS,
- tttext->lpszText);
+ TO_EXTERNAL_FORMAT (LISP_STRING, btext,
+ C_STRING_ALLOCA, tttext->lpszText,
+ Qnative);
}
#endif
}
else if (nmhdr->code == TCN_SELCHANGE)
{
TC_ITEM item;
- int index = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
+ int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
frame = XFRAME (mswindows_find_frame (hwnd));
item.mask = TCIF_PARAM;
- SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)index,
+ SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx,
(LPARAM)&item);
mswindows_handle_gui_wm_command (frame, 0, item.lParam);
break;
case WM_PAINT:
- {
- /* According to the docs we need to check GetUpdateRect() before
- actually doing a WM_PAINT */
- if (GetUpdateRect (hwnd, NULL, FALSE))
- {
- PAINTSTRUCT paintStruct;
- int x, y, width, height;
-
- frame = XFRAME (mswindows_find_frame (hwnd));
-
- BeginPaint (hwnd, &paintStruct);
- x = paintStruct.rcPaint.left;
- y = paintStruct.rcPaint.top;
- width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
- height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
- /* Normally we want to ignore expose events when child
- windows are unmapped, however once we are in the guts of
- WM_PAINT we need to make sure that we don't register
- unmaps then because they will not actually occur. */
- if (!check_for_ignored_expose (frame, x, y, width, height))
- {
- hold_ignored_expose_registration = 1;
- mswindows_redraw_exposed_area (frame, x, y, width, height);
- hold_ignored_expose_registration = 0;
- }
-
- EndPaint (hwnd, &paintStruct);
- }
- else
- goto defproc;
- }
+ /* hdc will be NULL unless this is a subwindow - in which case we
+ shouldn't have received a paint message for it here. */
+ assert (wParam == 0);
+
+ /* Can't queue a magic event because windows goes modal and sends paint
+ messages directly to the windows procedure when doing solid drags
+ and the message queue doesn't get processed. */
+ mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
break;
case WM_SIZE:
VOID_TO_LISP (image_instance, ii);
if (IMAGE_INSTANCEP (image_instance)
&&
- IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)
- &&
- !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance)))
+ IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET))
{
/* set colors for the buttons */
HDC hdc = (HDC)wParam;
GCPRO3 (emacs_event, l_dndlist, l_item);
- if (!DragQueryPoint ((HANDLE) wParam, &point))
+ if (!DragQueryPoint ((HDROP) wParam, &point))
point.x = point.y = -1; /* outside client area */
event->event_type = misc_user_event;
event->event.misc.y = point.y;
event->event.misc.function = Qdragdrop_drop_dispatch;
- filecount = DragQueryFile ((HANDLE) wParam, 0xffffffff, NULL, 0);
+ filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0);
for (i=0; i<filecount; i++)
{
- len = DragQueryFile ((HANDLE) wParam, i, NULL, 0);
+ len = DragQueryFile ((HDROP) wParam, i, NULL, 0);
/* The URLs that we make here aren't correct according to section
* 3.10 of rfc1738 because they're missing the //<host>/ part and
* because they may contain reserved characters. But that's OK. */
#else
filename = (char *)xmalloc (len+6);
strcpy (filename, "file:");
- DragQueryFile ((HANDLE) wParam, i, filename+5, len+1);
+ DragQueryFile ((HDROP) wParam, i, filename+5, len+1);
dostounix_filename (filename+5);
#endif
l_item = make_string (filename, strlen (filename));
l_dndlist = Fcons (l_item, l_dndlist);
xfree (filename);
}
- DragFinish ((HANDLE) wParam);
+ DragFinish ((HDROP) wParam);
event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
mswindows_enqueue_dispatch_event (emacs_event);
static void
emacs_mswindows_remove_timeout (int id)
{
- struct Lisp_Event match_against;
+ Lisp_Event match_against;
Lisp_Object emacs_event;
if (KillTimer (NULL, id))
* Return the next event
*/
static void
-emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
+emacs_mswindows_next_event (Lisp_Event *emacs_event)
{
Lisp_Object event, event2;
* Handle a magic event off the dispatch queue.
*/
static void
-emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
+emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event)
{
switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event))
{
case XM_BUMPQUEUE:
break;
+ case WM_PAINT:
+ mswindows_handle_paint (XFRAME (EVENT_CHANNEL (emacs_event)));
+ break;
+
case WM_SETFOCUS:
case WM_KILLFOCUS:
{
#ifndef HAVE_MSG_SELECT
static HANDLE
-get_process_input_waitable (struct Lisp_Process *process)
+get_process_input_waitable (Lisp_Process *process)
{
Lisp_Object instr, outstr, p;
XSETPROCESS (p, process);
}
static void
-emacs_mswindows_select_process (struct Lisp_Process *process)
+emacs_mswindows_select_process (Lisp_Process *process)
{
HANDLE hev = get_process_input_waitable (process);
}
static void
-emacs_mswindows_unselect_process (struct Lisp_Process *process)
+emacs_mswindows_unselect_process (Lisp_Process *process)
{
/* Process handle is removed in the event loop as soon
as it is signaled, so don't bother here about it */
static void
emacs_mswindows_quit_p (void)
{
- MSG msg;
-
/* Quit cannot happen in modal loop: all program
input is dedicated to Windows. */
if (mswindows_in_modal_loop)
return;
- /* Drain windows queue. This sets up number of quit characters in the queue
- * (and also processes wm focus change, move, resize, etc messages).
- * We don't want to process WM_PAINT messages because this function can be
- * called from almost anywhere and the windows' states may be changing. */
- while (PeekMessage (&msg, NULL, 0, WM_PAINT-1, PM_REMOVE) ||
- PeekMessage (&msg, NULL, WM_PAINT+1, WM_USER-1, PM_REMOVE))
- DispatchMessage (&msg);
+ /* Drain windows queue. This sets up number of quit characters in
+ the queue */
+ mswindows_drain_windows_queue ();
if (mswindows_quit_chars_count > 0)
{
/* Yes there's a hidden one... Throw it away */
- struct Lisp_Event match_against;
+ Lisp_Event match_against;
Lisp_Object emacs_event;
+ int critical_p = 0;
match_against.event_type = key_press_event;
match_against.event.key.modifiers = FAKE_MOD_QUIT;
- emacs_event = mswindows_cancel_dispatch_event (&match_against);
- assert (!NILP (emacs_event));
+ while (mswindows_quit_chars_count-- > 0)
+ {
+ emacs_event = mswindows_cancel_dispatch_event (&match_against);
+ assert (!NILP (emacs_event));
+
+ if (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT)
+ critical_p = 1;
- Vquit_flag = (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT
- ? Qcritical : Qt);
+ Fdeallocate_event(emacs_event);
+ }
- Fdeallocate_event(emacs_event);
- --mswindows_quit_chars_count;
+ Vquit_flag = critical_p ? Qcritical : Qt;
}
}
If we've still got pointers to it in this file, we're gonna lose hard.
*/
void
-debug_process_finalization (struct Lisp_Process *p)
+debug_process_finalization (Lisp_Process *p)
{
#if 0 /* #### */
Lisp_Object instr, outstr;
mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console;
#ifdef HAVE_MSG_SELECT
mswindows_event_stream->select_process_cb =
- (void (*)(struct Lisp_Process*))event_stream_unixoid_select_process;
+ (void (*)(Lisp_Process*))event_stream_unixoid_select_process;
mswindows_event_stream->unselect_process_cb =
- (void (*)(struct Lisp_Process*))event_stream_unixoid_unselect_process;
+ (void (*)(Lisp_Process*))event_stream_unixoid_unselect_process;
mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair;
mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair;
#else
mswindows_s_dispatch_event_queue = Qnil;
staticpro (&mswindows_s_dispatch_event_queue);
mswindows_s_dispatch_event_queue_tail = Qnil;
- pdump_wire (&mswindows_u_dispatch_event_queue_tail);
+ pdump_wire (&mswindows_s_dispatch_event_queue_tail);
mswindows_error_caught_in_modal_loop = Qnil;
staticpro (&mswindows_error_caught_in_modal_loop);