comparison src/event-msw.c @ 404:2f8bb876ab1d r21-2-32

Import from CVS: tag r21-2-32
author cvs
date Mon, 13 Aug 2007 11:16:07 +0200
parents a86b2b5e0111
children b8cc9ab3f761
comparison
equal deleted inserted replaced
403:9f011ab08d48 404:2f8bb876ab1d
1 /* The mswindows event_stream interface. 1 /* The mswindows event_stream interface.
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996 Ben Wing. 4 Copyright (C) 1996, 2000 Ben Wing.
5 Copyright (C) 1997 Jonathan Harris. 5 Copyright (C) 1997 Jonathan Harris.
6 6
7 This file is part of XEmacs. 7 This file is part of XEmacs.
8 8
9 XEmacs is free software; you can redistribute it and/or modify it 9 XEmacs is free software; you can redistribute it and/or modify it
39 #ifdef HAVE_SCROLLBARS 39 #ifdef HAVE_SCROLLBARS
40 # include "scrollbar-msw.h" 40 # include "scrollbar-msw.h"
41 #endif 41 #endif
42 42
43 #ifdef HAVE_MENUBARS 43 #ifdef HAVE_MENUBARS
44 # include "menubar.h"
44 # include "menubar-msw.h" 45 # include "menubar-msw.h"
45 #endif 46 #endif
46 47
47 #ifdef HAVE_DRAGNDROP 48 #ifdef HAVE_DRAGNDROP
48 # include "dragdrop.h" 49 # include "dragdrop.h"
71 typedef unsigned int SOCKET; 72 typedef unsigned int SOCKET;
72 #endif 73 #endif
73 #include <io.h> 74 #include <io.h>
74 #include <errno.h> 75 #include <errno.h>
75 76
77 #if !(defined(__CYGWIN32__) || defined(__MINGW32__))
78 # include <shlobj.h> /* For IShellLink */
79 #endif
80
76 #if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20) 81 #if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20)
77 typedef NMHDR *LPNMHDR; 82 typedef NMHDR *LPNMHDR;
78 #endif 83 #endif
79 84
80 #ifdef HAVE_MENUBARS 85 #ifdef HAVE_MENUBARS
138 Decremented in mswindows_dequeue_dispatch_event() */ 143 Decremented in mswindows_dequeue_dispatch_event() */
139 int mswindows_quit_chars_count = 0; 144 int mswindows_quit_chars_count = 0;
140 145
141 /* These are Lisp integers; see DEFVARS in this file for description. */ 146 /* These are Lisp integers; see DEFVARS in this file for description. */
142 int mswindows_dynamic_frame_resize; 147 int mswindows_dynamic_frame_resize;
143 int mswindows_meta_activates_menu; 148 int mswindows_alt_by_itself_activates_menu;
144 int mswindows_num_mouse_buttons; 149 int mswindows_num_mouse_buttons;
145 int mswindows_mouse_button_max_skew_x; 150 int mswindows_mouse_button_max_skew_x;
146 int mswindows_mouse_button_max_skew_y; 151 int mswindows_mouse_button_max_skew_y;
147 int mswindows_mouse_button_tolerance; 152 int mswindows_mouse_button_tolerance;
148 153
177 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */ 182 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */
178 183
179 struct ntpipe_slurp_stream_shared_data 184 struct ntpipe_slurp_stream_shared_data
180 { 185 {
181 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ 186 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
182 /* This is a manual-reset object. */ 187 /* This is a manual-reset object. */
183 HANDLE hev_caller; /* Caller blocks on this, and we signal it */ 188 HANDLE hev_caller; /* Caller blocks on this, and we signal it */
184 /* This is a manual-reset object. */ 189 /* This is a manual-reset object. */
185 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */ 190 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */
186 /* This is a manual-reset object. */ 191 /* This is a manual-reset object. */
187 HANDLE hpipe; /* Pipe read end handle. */ 192 HANDLE hpipe; /* Pipe read end handle. */
188 LONG die_p; /* Thread must exit ASAP if non-zero */ 193 LONG die_p; /* Thread must exit ASAP if non-zero */
189 BOOL eof_p : 1; /* Set when thread saw EOF */ 194 BOOL eof_p : 1; /* Set when thread saw EOF */
190 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ 195 BOOL error_p : 1; /* Read error other than EOF/broken pipe */
191 BOOL inuse_p : 1; /* this structure is in use */ 196 BOOL inuse_p : 1; /* this structure is in use */
220 s->inuse_p = 0; 225 s->inuse_p = 0;
221 } 226 }
222 } 227 }
223 228
224 static struct ntpipe_slurp_stream_shared_data* 229 static struct ntpipe_slurp_stream_shared_data*
225 slurper_allocate_shared_data() 230 slurper_allocate_shared_data (void)
226 { 231 {
227 int i=0; 232 int i=0;
228 for (i=0; i<MAX_SLURP_STREAMS; i++) 233 for (i=0; i<MAX_SLURP_STREAMS; i++)
229 { 234 {
230 if (!shared_data_block[i].inuse_p) 235 if (!shared_data_block[i].inuse_p)
467 472
468 struct ntpipe_shove_stream 473 struct ntpipe_shove_stream
469 { 474 {
470 LPARAM user_data; /* Any user data stored in the stream object */ 475 LPARAM user_data; /* Any user data stored in the stream object */
471 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ 476 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
472 /* This is an auto-reset object. */ 477 /* This is an auto-reset object. */
473 HANDLE hpipe; /* Pipe write end handle. */ 478 HANDLE hpipe; /* Pipe write end handle. */
474 HANDLE hthread; /* Reader thread handle. */ 479 HANDLE hthread; /* Reader thread handle. */
475 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */ 480 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */
476 DWORD size; /* Number of bytes to write */ 481 DWORD size; /* Number of bytes to write */
477 LONG die_p; /* Thread must exit ASAP if non-zero */ 482 LONG die_p; /* Thread must exit ASAP if non-zero */
869 mswindows_enqueue_dispatch_event (Lisp_Object event) 874 mswindows_enqueue_dispatch_event (Lisp_Object event)
870 { 875 {
871 int user_p = mswindows_user_event_p (XEVENT(event)); 876 int user_p = mswindows_user_event_p (XEVENT(event));
872 enqueue_event (event, 877 enqueue_event (event,
873 user_p ? &mswindows_u_dispatch_event_queue : 878 user_p ? &mswindows_u_dispatch_event_queue :
874 &mswindows_s_dispatch_event_queue, 879 &mswindows_s_dispatch_event_queue,
875 user_p ? &mswindows_u_dispatch_event_queue_tail : 880 user_p ? &mswindows_u_dispatch_event_queue_tail :
876 &mswindows_s_dispatch_event_queue_tail); 881 &mswindows_s_dispatch_event_queue_tail);
877 882
878 /* Avoid blocking on WaitMessage */ 883 /* Avoid blocking on WaitMessage */
879 PostMessage (NULL, XM_BUMPQUEUE, 0, 0); 884 PostMessage (NULL, XM_BUMPQUEUE, 0, 0);
880 } 885 }
881 886
989 /* 994 /*
990 * Remove and return the first emacs event on the dispatch queue. 995 * Remove and return the first emacs event on the dispatch queue.
991 * Give a preference to user events over non-user ones. 996 * Give a preference to user events over non-user ones.
992 */ 997 */
993 static Lisp_Object 998 static Lisp_Object
994 mswindows_dequeue_dispatch_event () 999 mswindows_dequeue_dispatch_event (void)
995 { 1000 {
996 Lisp_Object event; 1001 Lisp_Object event;
997 Lisp_Event* sevt; 1002 Lisp_Event* sevt;
998 1003
999 assert (!NILP(mswindows_u_dispatch_event_queue) || 1004 assert (!NILP(mswindows_u_dispatch_event_queue) ||
1000 !NILP(mswindows_s_dispatch_event_queue)); 1005 !NILP(mswindows_s_dispatch_event_queue));
1001 1006
1002 event = dequeue_event ( 1007 event = dequeue_event (
1003 NILP(mswindows_u_dispatch_event_queue) ? 1008 NILP(mswindows_u_dispatch_event_queue) ?
1004 &mswindows_s_dispatch_event_queue : 1009 &mswindows_s_dispatch_event_queue :
1005 &mswindows_u_dispatch_event_queue, 1010 &mswindows_u_dispatch_event_queue,
1006 NILP(mswindows_u_dispatch_event_queue) ? 1011 NILP(mswindows_u_dispatch_event_queue) ?
1007 &mswindows_s_dispatch_event_queue_tail : 1012 &mswindows_s_dispatch_event_queue_tail :
1008 &mswindows_u_dispatch_event_queue_tail); 1013 &mswindows_u_dispatch_event_queue_tail);
1009 1014
1010 sevt = XEVENT(event); 1015 sevt = XEVENT(event);
1011 if (sevt->event_type == key_press_event 1016 if (sevt->event_type == key_press_event
1032 { 1037 {
1033 Lisp_Object event; 1038 Lisp_Object event;
1034 Lisp_Object previous_event = Qnil; 1039 Lisp_Object previous_event = Qnil;
1035 int user_p = mswindows_user_event_p (match); 1040 int user_p = mswindows_user_event_p (match);
1036 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : 1041 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue :
1037 &mswindows_s_dispatch_event_queue; 1042 &mswindows_s_dispatch_event_queue;
1038 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : 1043 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail :
1039 &mswindows_s_dispatch_event_queue_tail; 1044 &mswindows_s_dispatch_event_queue_tail;
1040 1045
1041 assert (match->event_type == timeout_event 1046 assert (match->event_type == timeout_event
1042 || match->event_type == key_press_event); 1047 || match->event_type == key_press_event);
1043 1048
1044 EVENT_CHAIN_LOOP (event, *head) 1049 EVENT_CHAIN_LOOP (event, *head)
1219 Lisp_Object result = Qt; 1224 Lisp_Object result = Qt;
1220 struct gcpro gcpro1; 1225 struct gcpro gcpro1;
1221 GCPRO1 (result); 1226 GCPRO1 (result);
1222 1227
1223 if (NILP(mswindows_error_caught_in_modal_loop)) 1228 if (NILP(mswindows_error_caught_in_modal_loop))
1224 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil); 1229 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil);
1225 UNGCPRO; 1230 UNGCPRO;
1226 return result; 1231 return result;
1227 } 1232 }
1228 1233
1229 /* 1234 /*
1230 * KEYBOARD_ONLY_P is set to non-zero when we are called from 1235 * KEYBOARD_ONLY_P is set to non-zero when we are called from
1231 * QUITP, and are interesting in keyboard messages only. 1236 * QUITP, and are interesting in keyboard messages only.
1232 */ 1237 */
1233 static void 1238 static void
1234 mswindows_drain_windows_queue () 1239 mswindows_drain_windows_queue (void)
1235 { 1240 {
1236 MSG msg; 1241 MSG msg;
1237 1242
1238 /* should call mswindows_need_event_in_modal_loop() if in modal loop */ 1243 /* should call mswindows_need_event_in_modal_loop() if in modal loop */
1239 assert (!mswindows_in_modal_loop); 1244 assert (!mswindows_in_modal_loop);
1241 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) 1246 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
1242 { 1247 {
1243 /* We have to translate messages that are not sent to the main 1248 /* We have to translate messages that are not sent to the main
1244 window. This is so that key presses work ok in things like 1249 window. This is so that key presses work ok in things like
1245 edit fields. However, we *musn't* translate message for the 1250 edit fields. However, we *musn't* translate message for the
1246 main window as this is handled in the wnd proc. */ 1251 main window as this is handled in the wnd proc.
1247 if (GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD) 1252 We also have to avoid generating paint magic events for windows
1253 that aren't XEmacs frames */
1254 if (GetWindowLong (msg.hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP))
1248 { 1255 {
1249 TranslateMessage (&msg); 1256 TranslateMessage (&msg);
1250 } 1257 }
1251 else if (msg.message == WM_PAINT) 1258 else if (msg.message == WM_PAINT)
1252 { 1259 {
1260 struct mswindows_frame* msframe;
1261
1253 /* hdc will be NULL unless this is a subwindow - in which case we 1262 /* hdc will be NULL unless this is a subwindow - in which case we
1254 shouldn't have received a paint message for it here. */ 1263 shouldn't have received a paint message for it here. */
1255 assert (msg.wParam == 0); 1264 assert (msg.wParam == 0);
1256 1265
1257 /* Queue a magic event for handling when safe */ 1266 /* Queue a magic event for handling when safe */
1258 mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT); 1267 msframe = FRAME_MSWINDOWS_DATA (
1259 1268 XFRAME (mswindows_find_frame (msg.hwnd)));
1269 if (!msframe->paint_pending)
1270 {
1271 msframe->paint_pending = 1;
1272 mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT);
1273 }
1260 /* Don't dispatch. WM_PAINT is always the last message in the 1274 /* Don't dispatch. WM_PAINT is always the last message in the
1261 queue so it's OK to just return. */ 1275 queue so it's OK to just return. */
1262 return; 1276 return;
1263 } 1277 }
1264 DispatchMessage (&msg); 1278 DispatchMessage (&msg);
1353 { 1367 {
1354 if (FD_ISSET (windows_fd, &temp_mask)) 1368 if (FD_ISSET (windows_fd, &temp_mask))
1355 { 1369 {
1356 mswindows_drain_windows_queue (); 1370 mswindows_drain_windows_queue ();
1357 } 1371 }
1372 else
1373 {
1358 #ifdef HAVE_TTY 1374 #ifdef HAVE_TTY
1359 /* Look for a TTY event */ 1375 /* Look for a TTY event */
1360 for (i = 0; i < MAXDESC-1; i++) 1376 for (i = 0; i < MAXDESC-1; i++)
1361 {
1362 /* To avoid race conditions (among other things, an infinite
1363 loop when called from Fdiscard_input()), we must return
1364 user events ahead of process events. */
1365 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
1366 { 1377 {
1367 struct console *c = tty_find_console_from_fd (i); 1378 /* To avoid race conditions (among other things, an infinite
1368 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 1379 loop when called from Fdiscard_input()), we must return
1369 Lisp_Event* event = XEVENT (emacs_event); 1380 user events ahead of process events. */
1370 1381 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
1371 assert (c);
1372 if (read_event_from_tty_or_stream_desc (event, c, i))
1373 { 1382 {
1374 mswindows_enqueue_dispatch_event (emacs_event); 1383 struct console *c = tty_find_console_from_fd (i);
1375 return; 1384 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1385 Lisp_Event* event = XEVENT (emacs_event);
1386
1387 assert (c);
1388 if (read_event_from_tty_or_stream_desc (event, c, i))
1389 {
1390 mswindows_enqueue_dispatch_event (emacs_event);
1391 return;
1392 }
1376 } 1393 }
1377 } 1394 }
1378 } 1395 #endif
1379 #endif 1396 /* Look for a process event */
1380 /* Look for a process event */ 1397 for (i = 0; i < MAXDESC-1; i++)
1381 for (i = 0; i < MAXDESC-1; i++)
1382 {
1383 if (FD_ISSET (i, &temp_mask))
1384 { 1398 {
1385 if (FD_ISSET (i, &process_only_mask)) 1399 if (FD_ISSET (i, &temp_mask))
1386 { 1400 {
1387 Lisp_Process *p = 1401 if (FD_ISSET (i, &process_only_mask))
1388 get_process_from_usid (FD_TO_USID(i)); 1402 {
1389 1403 Lisp_Process *p =
1390 mswindows_enqueue_process_event (p); 1404 get_process_from_usid (FD_TO_USID(i));
1391 } 1405
1392 else 1406 mswindows_enqueue_process_event (p);
1393 { 1407 }
1394 /* We might get here when a fake event came 1408 else
1395 through a signal. Return a dummy event, so 1409 {
1396 that a cycle of the command loop will 1410 /* We might get here when a fake event came
1397 occur. */ 1411 through a signal. Return a dummy event, so
1398 drain_signal_event_pipe (); 1412 that a cycle of the command loop will
1399 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); 1413 occur. */
1414 drain_signal_event_pipe ();
1415 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1416 }
1400 } 1417 }
1401 } 1418 }
1402 } 1419 }
1403 } 1420 }
1404 else if (active==-1) 1421 else if (active==-1)
1413 { 1430 {
1414 assert(0); 1431 assert(0);
1415 } 1432 }
1416 #else 1433 #else
1417 /* Now try getting a message or process event */ 1434 /* Now try getting a message or process event */
1418 active = MsgWaitForMultipleObjects (mswindows_waitable_count, 1435 active = MsgWaitForMultipleObjects (mswindows_waitable_count,
1419 mswindows_waitable_handles, 1436 mswindows_waitable_handles,
1420 FALSE, badly_p ? INFINITE : 0, 1437 FALSE, badly_p ? INFINITE : 0,
1421 QS_ALLINPUT); 1438 QS_ALLINPUT);
1422 1439
1423 /* This will assert if handle being waited for becomes abandoned. 1440 /* This will assert if handle being waited for becomes abandoned.
1424 Not the case currently tho */ 1441 Not the case currently tho */
1425 assert ((!badly_p && active == WAIT_TIMEOUT) || 1442 assert ((!badly_p && active == WAIT_TIMEOUT) ||
1426 (active >= WAIT_OBJECT_0 && 1443 (active >= WAIT_OBJECT_0 &&
1427 active <= WAIT_OBJECT_0 + mswindows_waitable_count)); 1444 active <= WAIT_OBJECT_0 + mswindows_waitable_count));
1428 1445
1429 if (active == WAIT_TIMEOUT) 1446 if (active == WAIT_TIMEOUT)
1430 { 1447 {
1431 /* No luck trying - just return what we've already got */ 1448 /* No luck trying - just return what we've already got */
1432 return; 1449 return;
1433 } 1450 }
1434 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count) 1451 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count)
1435 { 1452 {
1436 /* Got your message, thanks */ 1453 /* Got your message, thanks */
1437 mswindows_drain_windows_queue (); 1454 mswindows_drain_windows_queue ();
1438 } 1455 }
1439 else 1456 else
1440 { 1457 {
1441 int ix = active - WAIT_OBJECT_0; 1458 int ix = active - WAIT_OBJECT_0;
1442 /* First, try to find which process' output has signaled */ 1459 /* First, try to find which process' output has signaled */
1443 Lisp_Process *p = 1460 Lisp_Process *p =
1444 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix])); 1461 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix]));
1445 if (p != NULL) 1462 if (p != NULL)
1446 { 1463 {
1447 /* Found a signaled process input handle */ 1464 /* Found a signaled process input handle */
1448 mswindows_enqueue_process_event (p); 1465 mswindows_enqueue_process_event (p);
1449 } 1466 }
1450 else 1467 else
1451 { 1468 {
1452 /* None. This means that the process handle itself has signaled. 1469 /* None. This means that the process handle itself has signaled.
1453 Remove the handle from the wait vector, and make status_notify 1470 Remove the handle from the wait vector, and make status_notify
1454 note the exited process */ 1471 note the exited process */
1455 mswindows_waitable_handles [ix] = 1472 mswindows_waitable_handles [ix] =
1456 mswindows_waitable_handles [--mswindows_waitable_count]; 1473 mswindows_waitable_handles [--mswindows_waitable_count];
1457 kick_status_notify (); 1474 kick_status_notify ();
1458 /* Have to return something: there may be no accompanying 1475 /* Have to return something: there may be no accompanying
1459 process event */ 1476 process event */
1460 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); 1477 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1461 } 1478 }
1462 } 1479 }
1463 #endif 1480 #endif
1464 } /* while */ 1481 } /* while */
1465 } 1482 }
1466 1483
1467 /************************************************************************/ 1484 /************************************************************************/
1468 /* Event generators */ 1485 /* Event generators */
1469 /************************************************************************/ 1486 /************************************************************************/
1612 1629
1613 /* 1630 /*
1614 * Helper to do repainting - repaints can happen both from the windows 1631 * Helper to do repainting - repaints can happen both from the windows
1615 * procedure and from magic events 1632 * procedure and from magic events
1616 */ 1633 */
1617 void 1634 static void
1618 mswindows_handle_paint (struct frame *frame) 1635 mswindows_handle_paint (struct frame *frame)
1619 { 1636 {
1620 HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame); 1637 HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame);
1621 1638
1622 /* According to the docs we need to check GetUpdateRect() before 1639 /* According to the docs we need to check GetUpdateRect() before
1623 actually doing a WM_PAINT */ 1640 actually doing a WM_PAINT */
1624 if (GetUpdateRect (hwnd, NULL, FALSE)) 1641 if (GetUpdateRect (hwnd, NULL, FALSE))
1625 { 1642 {
1626 PAINTSTRUCT paintStruct; 1643 PAINTSTRUCT paintStruct;
1627 int x, y, width, height; 1644 int x, y, width, height;
1628 1645
1629 BeginPaint (hwnd, &paintStruct); 1646 BeginPaint (hwnd, &paintStruct);
1630 x = paintStruct.rcPaint.left; 1647 x = paintStruct.rcPaint.left;
1631 y = paintStruct.rcPaint.top; 1648 y = paintStruct.rcPaint.top;
1632 width = paintStruct.rcPaint.right - paintStruct.rcPaint.left; 1649 width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
1633 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top; 1650 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
1634 /* Normally we want to ignore expose events when child 1651 /* Normally we want to ignore expose events when child
1635 windows are unmapped, however once we are in the guts of 1652 windows are unmapped, however once we are in the guts of
1636 WM_PAINT we need to make sure that we don't register 1653 WM_PAINT we need to make sure that we don't register
1637 unmaps then because they will not actually occur. */ 1654 unmaps then because they will not actually occur. */
1638 if (!check_for_ignored_expose (frame, x, y, width, height)) 1655 if (!check_for_ignored_expose (frame, x, y, width, height))
1639 { 1656 {
1640 hold_ignored_expose_registration = 1; 1657 hold_ignored_expose_registration = 1;
1641 mswindows_redraw_exposed_area (frame, x, y, width, height); 1658 mswindows_redraw_exposed_area (frame, x, y, width, height);
1642 hold_ignored_expose_registration = 0; 1659 hold_ignored_expose_registration = 0;
1643 } 1660 }
1644 EndPaint (hwnd, &paintStruct); 1661 EndPaint (hwnd, &paintStruct);
1645 } 1662 }
1646 } 1663 }
1647 1664
1648 /* 1665 /*
1649 * Returns 1 if a key is a real modifier or special key, which 1666 * Returns 1 if a key is a real modifier or special key, which
1650 * is better handled by DefWindowProc 1667 * is better handled by DefWindowProc
1651 */ 1668 */
1652 static int 1669 static int
1653 key_needs_default_processing_p (UINT vkey) 1670 key_needs_default_processing_p (UINT vkey)
1654 { 1671 {
1655 if (mswindows_meta_activates_menu && vkey == VK_MENU) 1672 if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU)
1656 return 1; 1673 return 1;
1657 1674
1658 return 0; 1675 return 0;
1659 } 1676 }
1660 1677
1671 1688
1672 Lisp_Event *event; 1689 Lisp_Event *event;
1673 struct frame *frame; 1690 struct frame *frame;
1674 struct mswindows_frame* msframe; 1691 struct mswindows_frame* msframe;
1675 1692
1693 assert (!GetWindowLong (hwnd, GWL_USERDATA));
1676 switch (message) 1694 switch (message)
1677 { 1695 {
1678 case WM_DESTROYCLIPBOARD: 1696 case WM_DESTROYCLIPBOARD:
1679 /* We own the clipboard and someone else wants it. Delete our 1697 /* We own the clipboard and someone else wants it. Delete our
1680 cached copy of the clipboard contents so we'll ask for it from 1698 cached copy of the clipboard contents so we'll ask for it from
1681 Windows again when someone does a paste. */ 1699 Windows again when someone does a paste. */
1682 handle_selection_clear(QCLIPBOARD); 1700 handle_selection_clear(QCLIPBOARD);
1683 break; 1701 break;
1684 1702
1685 case WM_ERASEBKGND: 1703 case WM_ERASEBKGND:
1686 /* Erase background only during non-dynamic sizing */ 1704 /* Erase background only during non-dynamic sizing */
1687 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); 1705 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1688 if (msframe->sizing && !mswindows_dynamic_frame_resize) 1706 if (msframe->sizing && !mswindows_dynamic_frame_resize)
1689 goto defproc; 1707 goto defproc;
1690 return 1; 1708 return 1;
1691 1709
1692 case WM_CLOSE: 1710 case WM_CLOSE:
1693 fobj = mswindows_find_frame (hwnd); 1711 fobj = mswindows_find_frame (hwnd);
1694 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt)); 1712 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt));
1695 break; 1713 break;
1696 1714
1697 case WM_KEYUP: 1715 case WM_KEYUP:
1698 case WM_SYSKEYUP: 1716 case WM_SYSKEYUP:
1699 /* See Win95 comment under WM_KEYDOWN */ 1717 /* See Win95 comment under WM_KEYDOWN */
1700 { 1718 {
1701 BYTE keymap[256]; 1719 BYTE keymap[256];
1702 1720 int should_set_keymap = 0;
1703 if (wParam == VK_CONTROL) 1721
1704 { 1722 if (wParam == VK_CONTROL)
1705 GetKeyboardState (keymap); 1723 {
1706 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80; 1724 GetKeyboardState (keymap);
1725 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80;
1726 should_set_keymap = 1;
1727 }
1728 else if (wParam == VK_MENU)
1729 {
1730 GetKeyboardState (keymap);
1731 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80;
1732 should_set_keymap = 1;
1733 }
1734
1735 if (should_set_keymap
1736 && (message != WM_SYSKEYUP
1737 || NILP (Vmenu_accelerator_enabled)))
1707 SetKeyboardState (keymap); 1738 SetKeyboardState (keymap);
1708 } 1739
1709 else if (wParam == VK_MENU) 1740 }
1710 { 1741 if (key_needs_default_processing_p (wParam))
1711 GetKeyboardState (keymap); 1742 goto defproc;
1712 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80; 1743 else
1713 SetKeyboardState (keymap); 1744 break;
1714 } 1745
1715 }; 1746 case WM_KEYDOWN:
1716 if (key_needs_default_processing_p (wParam)) 1747 case WM_SYSKEYDOWN:
1717 goto defproc; 1748 /* In some locales the right-hand Alt key is labelled AltGr. This key
1718 else 1749 * should produce alternative charcaters when combined with another key.
1750 * eg on a German keyboard pressing AltGr+q should produce '@'.
1751 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if
1752 * TranslateMessage() is called with *any* combination of Ctrl+Alt down,
1753 * it translates as if AltGr were down.
1754 * We get round this by removing all modifiers from the keymap before
1755 * calling TranslateMessage() unless AltGr is *really* down. */
1756 {
1757 BYTE keymap[256];
1758 int has_AltGr = mswindows_current_layout_has_AltGr ();
1759 int mods;
1760 int extendedp = lParam & 0x1000000;
1761 Lisp_Object keysym;
1762
1763 frame = XFRAME (mswindows_find_frame (hwnd));
1764 GetKeyboardState (keymap);
1765 mods = mswindows_modifier_state (keymap, has_AltGr);
1766
1767 /* Handle non-printables */
1768 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
1769 extendedp)))
1770 mswindows_enqueue_keypress_event (hwnd, keysym, mods);
1771 else /* Normal keys & modifiers */
1772 {
1773 Emchar quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
1774 BYTE keymap_orig[256];
1775 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
1776 MSG msg, tranmsg;
1777 int potential_accelerator = 0;
1778 int got_accelerator = 0;
1779
1780 msg.hwnd = hwnd;
1781 msg.message = message;
1782 msg.wParam = wParam;
1783 msg.lParam = lParam;
1784 msg.time = GetMessageTime();
1785 msg.pt = pnt;
1786
1787 /* GetKeyboardState() does not work as documented on Win95. We have
1788 * to loosely track Left and Right modifiers on behalf of the OS,
1789 * without screwing up Windows NT which tracks them properly. */
1790 if (wParam == VK_CONTROL)
1791 keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
1792 else if (wParam == VK_MENU)
1793 keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
1794
1795 memcpy (keymap_orig, keymap, 256);
1796
1797 if (!NILP (Vmenu_accelerator_enabled) &&
1798 !(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN)
1799 potential_accelerator = 1;
1800
1801 /* Remove shift modifier from an ascii character */
1802 mods &= ~XEMACS_MOD_SHIFT;
1803
1804 /* Clear control and alt modifiers unless AltGr is pressed */
1805 keymap [VK_RCONTROL] = 0;
1806 keymap [VK_LMENU] = 0;
1807 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80)
1808 || !(keymap [VK_RMENU] & 0x80))
1809 {
1810 keymap [VK_LCONTROL] = 0;
1811 keymap [VK_CONTROL] = 0;
1812 keymap [VK_RMENU] = 0;
1813 keymap [VK_MENU] = 0;
1814 }
1815 SetKeyboardState (keymap);
1816
1817 /* Maybe generate some WM_[SYS]CHARs in the queue */
1818 TranslateMessage (&msg);
1819
1820 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)
1821 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE))
1822 {
1823 int mods1 = mods;
1824 WPARAM ch = tranmsg.wParam;
1825
1826 /* If a quit char with no modifiers other than control and
1827 shift, then mark it with a fake modifier, which is removed
1828 upon dequeueing the event */
1829 /* #### This might also not withstand localization, if
1830 quit character is not a latin-1 symbol */
1831 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) && quit_ch + 'a' - 1 == ch)
1832 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) && quit_ch == ch))
1833 && ((mods & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) == 0))
1834 {
1835 mods1 |= FAKE_MOD_QUIT;
1836 ++mswindows_quit_chars_count;
1837 }
1838 else if (potential_accelerator && !got_accelerator &&
1839 msw_char_is_accelerator (frame, ch))
1840 {
1841 got_accelerator = 1;
1842 break;
1843 }
1844 mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1);
1845 } /* while */
1846 SetKeyboardState (keymap_orig);
1847 /* This generates WM_SYSCHAR messages, which are interpreted
1848 by DefWindowProc as the menu selections. */
1849 if (got_accelerator)
1850 {
1851 TranslateMessage (&msg);
1852 goto defproc;
1853 }
1854 } /* else */
1855 }
1856 if (key_needs_default_processing_p (wParam))
1857 goto defproc;
1858 else
1859 break;
1860
1861 case WM_MBUTTONDOWN:
1862 case WM_MBUTTONUP:
1863 /* Real middle mouse button has nothing to do with emulated one:
1864 if one wants to exercise fingers playing chords on the mouse,
1865 he is allowed to do that! */
1866 mswindows_enqueue_mouse_button_event (hwnd, message,
1867 MAKEPOINTS (lParam), GetMessageTime());
1719 break; 1868 break;
1720 1869
1721 case WM_KEYDOWN: 1870 case WM_LBUTTONUP:
1722 case WM_SYSKEYDOWN: 1871 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1723 /* In some locales the right-hand Alt key is labelled AltGr. This key 1872 msframe->last_click_time = GetMessageTime();
1724 * should produce alternative charcaters when combined with another key. 1873
1725 * eg on a German keyboard pressing AltGr+q should produce '@'. 1874 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1726 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if 1875 msframe->button2_need_lbutton = 0;
1727 * TranslateMessage() is called with *any* combination of Ctrl+Alt down, 1876 if (msframe->ignore_next_lbutton_up)
1728 * it translates as if AltGr were down. 1877 {
1729 * We get round this by removing all modifiers from the keymap before 1878 msframe->ignore_next_lbutton_up = 0;
1730 * calling TranslateMessage() unless AltGr is *really* down. */ 1879 }
1731 { 1880 else if (msframe->button2_is_down)
1732 BYTE keymap[256]; 1881 {
1733 int has_AltGr = mswindows_current_layout_has_AltGr (); 1882 msframe->button2_is_down = 0;
1734 int mods; 1883 msframe->ignore_next_rbutton_up = 1;
1735 int extendedp = lParam & 0x1000000; 1884 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1736 Lisp_Object keysym; 1885 MAKEPOINTS (lParam), GetMessageTime());
1737 1886 }
1738 GetKeyboardState (keymap); 1887 else
1739 mods = mswindows_modifier_state (keymap, has_AltGr); 1888 {
1740 1889 if (msframe->button2_need_rbutton)
1741 /* Handle non-printables */
1742 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
1743 extendedp)))
1744 mswindows_enqueue_keypress_event (hwnd, keysym, mods);
1745 else /* Normal keys & modifiers */
1746 {
1747 int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
1748 BYTE keymap_orig[256];
1749 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
1750 MSG msg;
1751
1752 msg.hwnd = hwnd;
1753 msg.message = message;
1754 msg.wParam = wParam;
1755 msg.lParam = lParam;
1756 msg.time = GetMessageTime();
1757 msg.pt = pnt;
1758
1759 /* GetKeyboardState() does not work as documented on Win95. We have
1760 * to loosely track Left and Right modifiers on behalf of the OS,
1761 * without screwing up Windows NT which tracks them properly. */
1762 if (wParam == VK_CONTROL)
1763 keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
1764 else if (wParam == VK_MENU)
1765 keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
1766
1767 memcpy (keymap_orig, keymap, 256);
1768
1769 /* Remove shift modifier from an ascii character */
1770 mods &= ~MOD_SHIFT;
1771
1772 /* Clear control and alt modifiers unless AltGr is pressed */
1773 keymap [VK_RCONTROL] = 0;
1774 keymap [VK_LMENU] = 0;
1775 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80)
1776 || !(keymap [VK_RMENU] & 0x80))
1777 { 1890 {
1778 keymap [VK_LCONTROL] = 0; 1891 msframe->button2_need_rbutton = 0;
1779 keymap [VK_CONTROL] = 0; 1892 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1780 keymap [VK_RMENU] = 0; 1893 MAKEPOINTS (lParam), GetMessageTime());
1781 keymap [VK_MENU] = 0;
1782 } 1894 }
1783 SetKeyboardState (keymap); 1895 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP,
1784 1896 MAKEPOINTS (lParam), GetMessageTime());
1785 /* Maybe generate some WM_[SYS]CHARs in the queue */ 1897 }
1786 TranslateMessage (&msg); 1898 break;
1787 1899
1788 while (PeekMessage (&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) 1900 case WM_RBUTTONUP:
1789 || PeekMessage (&msg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) 1901 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1902 msframe->last_click_time = GetMessageTime();
1903
1904 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1905 msframe->button2_need_rbutton = 0;
1906 if (msframe->ignore_next_rbutton_up)
1907 {
1908 msframe->ignore_next_rbutton_up = 0;
1909 }
1910 else if (msframe->button2_is_down)
1911 {
1912 msframe->button2_is_down = 0;
1913 msframe->ignore_next_lbutton_up = 1;
1914 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1915 MAKEPOINTS (lParam), GetMessageTime());
1916 }
1917 else
1918 {
1919 if (msframe->button2_need_lbutton)
1790 { 1920 {
1791 int mods1 = mods; 1921 msframe->button2_need_lbutton = 0;
1792 WPARAM ch = msg.wParam; 1922 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1793 1923 MAKEPOINTS (lParam), GetMessageTime());
1794 /* If a quit char with no modifiers other than control and 1924 }
1795 shift, then mark it with a fake modifier, which is removed 1925 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP,
1796 upon dequeueing the event */ 1926 MAKEPOINTS (lParam), GetMessageTime());
1797 /* #### This might also not withstand localization, if 1927 }
1798 quit character is not a latin-1 symbol */
1799 if (((quit_ch < ' ' && (mods & MOD_CONTROL) && quit_ch + 'a' - 1 == ch)
1800 || (quit_ch >= ' ' && !(mods & MOD_CONTROL) && quit_ch == ch))
1801 && ((mods & ~(MOD_CONTROL | MOD_SHIFT)) == 0))
1802 {
1803 mods1 |= FAKE_MOD_QUIT;
1804 ++mswindows_quit_chars_count;
1805 }
1806
1807 mswindows_enqueue_keypress_event (hwnd, make_char(ch), mods1);
1808 } /* while */
1809 SetKeyboardState (keymap_orig);
1810 } /* else */
1811 }
1812 if (key_needs_default_processing_p (wParam))
1813 goto defproc;
1814 else
1815 break; 1928 break;
1816 1929
1817 case WM_MBUTTONDOWN: 1930 case WM_LBUTTONDOWN:
1818 case WM_MBUTTONUP: 1931 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1819 /* Real middle mouse button has nothing to do with emulated one: 1932
1820 if one wants to exercise fingers playing chords on the mouse, 1933 if (msframe->button2_need_lbutton)
1821 he is allowed to do that! */
1822 mswindows_enqueue_mouse_button_event (hwnd, message,
1823 MAKEPOINTS (lParam), GetMessageTime());
1824 break;
1825
1826 case WM_LBUTTONUP:
1827 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1828 msframe->last_click_time = GetMessageTime();
1829
1830 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1831 msframe->button2_need_lbutton = 0;
1832 if (msframe->ignore_next_lbutton_up)
1833 {
1834 msframe->ignore_next_lbutton_up = 0;
1835 }
1836 else if (msframe->button2_is_down)
1837 {
1838 msframe->button2_is_down = 0;
1839 msframe->ignore_next_rbutton_up = 1;
1840 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1841 MAKEPOINTS (lParam), GetMessageTime());
1842 }
1843 else
1844 {
1845 if (msframe->button2_need_rbutton)
1846 {
1847 msframe->button2_need_rbutton = 0;
1848 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1849 MAKEPOINTS (lParam), GetMessageTime());
1850 }
1851 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP,
1852 MAKEPOINTS (lParam), GetMessageTime());
1853 }
1854 break;
1855
1856 case WM_RBUTTONUP:
1857 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1858 msframe->last_click_time = GetMessageTime();
1859
1860 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1861 msframe->button2_need_rbutton = 0;
1862 if (msframe->ignore_next_rbutton_up)
1863 {
1864 msframe->ignore_next_rbutton_up = 0;
1865 }
1866 else if (msframe->button2_is_down)
1867 {
1868 msframe->button2_is_down = 0;
1869 msframe->ignore_next_lbutton_up = 1;
1870 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1871 MAKEPOINTS (lParam), GetMessageTime());
1872 }
1873 else
1874 {
1875 if (msframe->button2_need_lbutton)
1876 {
1877 msframe->button2_need_lbutton = 0;
1878 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1879 MAKEPOINTS (lParam), GetMessageTime());
1880 }
1881 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP,
1882 MAKEPOINTS (lParam), GetMessageTime());
1883 }
1884 break;
1885
1886 case WM_LBUTTONDOWN:
1887 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1888
1889 if (msframe->button2_need_lbutton)
1890 {
1891 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1892 msframe->button2_need_lbutton = 0;
1893 msframe->button2_need_rbutton = 0;
1894 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
1895 {
1896 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
1897 MAKEPOINTS (lParam), GetMessageTime());
1898 msframe->button2_is_down = 1;
1899 }
1900 else
1901 {
1902 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1903 msframe->last_click_point, msframe->last_click_time);
1904 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1905 MAKEPOINTS (lParam), GetMessageTime());
1906 }
1907 }
1908 else
1909 {
1910 mswindows_set_chord_timer (hwnd);
1911 msframe->button2_need_rbutton = 1;
1912 msframe->last_click_point = MAKEPOINTS (lParam);
1913 }
1914 msframe->last_click_time = GetMessageTime();
1915 break;
1916
1917 case WM_RBUTTONDOWN:
1918 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1919
1920 if (msframe->button2_need_rbutton)
1921 {
1922 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1923 msframe->button2_need_lbutton = 0;
1924 msframe->button2_need_rbutton = 0;
1925 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
1926 {
1927 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
1928 MAKEPOINTS (lParam), GetMessageTime());
1929 msframe->button2_is_down = 1;
1930 }
1931 else
1932 {
1933 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1934 msframe->last_click_point, msframe->last_click_time);
1935 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1936 MAKEPOINTS (lParam), GetMessageTime());
1937 }
1938 }
1939 else
1940 {
1941 mswindows_set_chord_timer (hwnd);
1942 msframe->button2_need_lbutton = 1;
1943 msframe->last_click_point = MAKEPOINTS (lParam);
1944 }
1945 msframe->last_click_time = GetMessageTime();
1946 break;
1947
1948 case WM_TIMER:
1949 if (wParam == BUTTON_2_TIMER_ID)
1950 {
1951 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1952 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1953
1954 if (msframe->button2_need_lbutton)
1955 {
1956 msframe->button2_need_lbutton = 0;
1957 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1958 msframe->last_click_point, msframe->last_click_time);
1959 }
1960 else if (msframe->button2_need_rbutton)
1961 {
1962 msframe->button2_need_rbutton = 0;
1963 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1964 msframe->last_click_point, msframe->last_click_time);
1965 }
1966 }
1967 else
1968 assert ("Spurious timer fired" == 0);
1969 break;
1970
1971 case WM_MOUSEMOVE:
1972 /* Optimization: don't report mouse movement while size is changing */
1973 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1974 if (!msframe->sizing)
1975 {
1976 /* When waiting for the second mouse button to finish
1977 button2 emulation, and have moved too far, just pretend
1978 as if timer has expired. This improves drag-select feedback */
1979 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton)
1980 && !mswindows_button2_near_enough (msframe->last_click_point,
1981 MAKEPOINTS (lParam)))
1982 { 1934 {
1983 KillTimer (hwnd, BUTTON_2_TIMER_ID); 1935 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1984 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); 1936 msframe->button2_need_lbutton = 0;
1985 } 1937 msframe->button2_need_rbutton = 0;
1986 1938 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
1987 emacs_event = Fmake_event (Qnil, Qnil);
1988 event = XEVENT(emacs_event);
1989
1990 event->channel = mswindows_find_frame(hwnd);
1991 event->timestamp = GetMessageTime();
1992 event->event_type = pointer_motion_event;
1993 event->event.motion.x = MAKEPOINTS(lParam).x;
1994 event->event.motion.y = MAKEPOINTS(lParam).y;
1995 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0);
1996
1997 mswindows_enqueue_dispatch_event (emacs_event);
1998 }
1999 break;
2000
2001 case WM_CANCELMODE:
2002 ReleaseCapture ();
2003 /* Queue a `cancel-mode-internal' misc user event, so mouse
2004 selection would be canceled if any */
2005 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd),
2006 Qcancel_mode_internal, Qnil);
2007 break;
2008
2009 case WM_NOTIFY:
2010 {
2011 LPNMHDR nmhdr = (LPNMHDR)lParam;
2012
2013 if (nmhdr->code == TTN_NEEDTEXT)
2014 {
2015 #ifdef HAVE_TOOLBARS
2016 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
2017 Lisp_Object btext;
2018
2019 /* find out which toolbar */
2020 frame = XFRAME (mswindows_find_frame (hwnd));
2021 btext = mswindows_get_toolbar_button_text ( frame,
2022 nmhdr->idFrom );
2023
2024 tttext->lpszText = NULL;
2025 tttext->hinst = NULL;
2026
2027 if (!NILP(btext))
2028 { 1939 {
2029 /* I think this is safe since the text will only go away 1940 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
2030 when the toolbar does...*/ 1941 MAKEPOINTS (lParam), GetMessageTime());
2031 TO_EXTERNAL_FORMAT (LISP_STRING, btext, 1942 msframe->button2_is_down = 1;
2032 C_STRING_ALLOCA, tttext->lpszText,
2033 Qnative);
2034 }
2035 #endif
2036 }
2037 /* handle tree view callbacks */
2038 else if (nmhdr->code == TVN_SELCHANGED)
2039 {
2040 NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam;
2041 frame = XFRAME (mswindows_find_frame (hwnd));
2042 mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam);
2043 }
2044 /* handle tab control callbacks */
2045 else if (nmhdr->code == TCN_SELCHANGE)
2046 {
2047 TC_ITEM item;
2048 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
2049 frame = XFRAME (mswindows_find_frame (hwnd));
2050
2051 item.mask = TCIF_PARAM;
2052 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx,
2053 (LPARAM)&item);
2054
2055 mswindows_handle_gui_wm_command (frame, 0, item.lParam);
2056 }
2057 }
2058 break;
2059
2060 case WM_PAINT:
2061 /* hdc will be NULL unless this is a subwindow - in which case we
2062 shouldn't have received a paint message for it here. */
2063 assert (wParam == 0);
2064
2065 /* Can't queue a magic event because windows goes modal and sends paint
2066 messages directly to the windows procedure when doing solid drags
2067 and the message queue doesn't get processed. */
2068 mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
2069 break;
2070
2071 case WM_SIZE:
2072 /* We only care about this message if our size has really changed */
2073 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED)
2074 {
2075 RECT rect;
2076 int columns, rows;
2077
2078 fobj = mswindows_find_frame (hwnd);
2079 frame = XFRAME (fobj);
2080 msframe = FRAME_MSWINDOWS_DATA (frame);
2081
2082 /* We cannot handle frame map and unmap hooks right in
2083 this routine, because these may throw. We queue
2084 magic events to run these hooks instead - kkm */
2085
2086 if (wParam==SIZE_MINIMIZED)
2087 {
2088 /* Iconified */
2089 FRAME_VISIBLE_P (frame) = 0;
2090 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
2091 }
2092 else
2093 {
2094 GetClientRect(hwnd, &rect);
2095 FRAME_PIXWIDTH(frame) = rect.right;
2096 FRAME_PIXHEIGHT(frame) = rect.bottom;
2097
2098 pixel_to_real_char_size (frame, rect.right, rect.bottom,
2099 &FRAME_MSWINDOWS_CHARWIDTH (frame),
2100 &FRAME_MSWINDOWS_CHARHEIGHT (frame));
2101
2102 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows);
2103 change_frame_size (frame, rows, columns, 1);
2104
2105 /* If we are inside frame creation, we have to apply geometric
2106 properties now. */
2107 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2108 {
2109 /* Yes, we have to size again */
2110 mswindows_size_frame_internal ( frame,
2111 FRAME_MSWINDOWS_TARGET_RECT
2112 (frame));
2113 /* Reset so we do not get here again. The SetWindowPos call in
2114 * mswindows_size_frame_internal can cause recursion here. */
2115 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2116 {
2117 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame));
2118 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0;
2119 }
2120 } 1943 }
2121 else 1944 else
2122 { 1945 {
2123 if (!msframe->sizing && !FRAME_VISIBLE_P (frame)) 1946 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
2124 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME); 1947 msframe->last_click_point, msframe->last_click_time);
2125 FRAME_VISIBLE_P (frame) = 1; 1948 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
2126 1949 MAKEPOINTS (lParam), GetMessageTime());
2127 if (!msframe->sizing || mswindows_dynamic_frame_resize)
2128 redisplay ();
2129 } 1950 }
2130 } 1951 }
1952 else
1953 {
1954 mswindows_set_chord_timer (hwnd);
1955 msframe->button2_need_rbutton = 1;
1956 msframe->last_click_point = MAKEPOINTS (lParam);
1957 }
1958 msframe->last_click_time = GetMessageTime();
1959 break;
1960
1961 case WM_RBUTTONDOWN:
1962 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1963
1964 if (msframe->button2_need_rbutton)
1965 {
1966 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1967 msframe->button2_need_lbutton = 0;
1968 msframe->button2_need_rbutton = 0;
1969 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
1970 {
1971 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
1972 MAKEPOINTS (lParam), GetMessageTime());
1973 msframe->button2_is_down = 1;
1974 }
1975 else
1976 {
1977 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1978 msframe->last_click_point, msframe->last_click_time);
1979 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1980 MAKEPOINTS (lParam), GetMessageTime());
1981 }
1982 }
1983 else
1984 {
1985 mswindows_set_chord_timer (hwnd);
1986 msframe->button2_need_lbutton = 1;
1987 msframe->last_click_point = MAKEPOINTS (lParam);
1988 }
1989 msframe->last_click_time = GetMessageTime();
1990 break;
1991
1992 case WM_TIMER:
1993 if (wParam == BUTTON_2_TIMER_ID)
1994 {
1995 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1996 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1997
1998 if (msframe->button2_need_lbutton)
1999 {
2000 msframe->button2_need_lbutton = 0;
2001 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
2002 msframe->last_click_point, msframe->last_click_time);
2003 }
2004 else if (msframe->button2_need_rbutton)
2005 {
2006 msframe->button2_need_rbutton = 0;
2007 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
2008 msframe->last_click_point, msframe->last_click_time);
2009 }
2010 }
2011 else
2012 assert ("Spurious timer fired" == 0);
2013 break;
2014
2015 case WM_MOUSEMOVE:
2016 /* Optimization: don't report mouse movement while size is changing */
2017 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2018 if (!msframe->sizing)
2019 {
2020 /* When waiting for the second mouse button to finish
2021 button2 emulation, and have moved too far, just pretend
2022 as if timer has expired. This improves drag-select feedback */
2023 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton)
2024 && !mswindows_button2_near_enough (msframe->last_click_point,
2025 MAKEPOINTS (lParam)))
2026 {
2027 KillTimer (hwnd, BUTTON_2_TIMER_ID);
2028 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0);
2029 }
2030
2031 emacs_event = Fmake_event (Qnil, Qnil);
2032 event = XEVENT(emacs_event);
2033
2034 event->channel = mswindows_find_frame(hwnd);
2035 event->timestamp = GetMessageTime();
2036 event->event_type = pointer_motion_event;
2037 event->event.motion.x = MAKEPOINTS(lParam).x;
2038 event->event.motion.y = MAKEPOINTS(lParam).y;
2039 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0);
2040
2041 mswindows_enqueue_dispatch_event (emacs_event);
2042 }
2043 break;
2044
2045 case WM_CANCELMODE:
2046 ReleaseCapture ();
2047 /* Queue a `cancel-mode-internal' misc user event, so mouse
2048 selection would be canceled if any */
2049 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd),
2050 Qcancel_mode_internal, Qnil);
2051 break;
2052
2053 case WM_NOTIFY:
2054 {
2055 LPNMHDR nmhdr = (LPNMHDR)lParam;
2056
2057 if (nmhdr->code == TTN_NEEDTEXT)
2058 {
2059 #ifdef HAVE_TOOLBARS
2060 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
2061 Lisp_Object btext;
2062
2063 /* find out which toolbar */
2064 frame = XFRAME (mswindows_find_frame (hwnd));
2065 btext = mswindows_get_toolbar_button_text ( frame,
2066 nmhdr->idFrom );
2067
2068 tttext->lpszText = NULL;
2069 tttext->hinst = NULL;
2070
2071 if (!NILP(btext))
2072 {
2073 /* I think this is safe since the text will only go away
2074 when the toolbar does...*/
2075 TO_EXTERNAL_FORMAT (LISP_STRING, btext,
2076 C_STRING_ALLOCA, tttext->lpszText,
2077 Qnative);
2078 }
2079 #endif
2080 }
2081 /* handle tree view callbacks */
2082 else if (nmhdr->code == TVN_SELCHANGED)
2083 {
2084 NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam;
2085 frame = XFRAME (mswindows_find_frame (hwnd));
2086 mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam);
2087 }
2088 /* handle tab control callbacks */
2089 else if (nmhdr->code == TCN_SELCHANGE)
2090 {
2091 TC_ITEM item;
2092 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
2093 frame = XFRAME (mswindows_find_frame (hwnd));
2094
2095 item.mask = TCIF_PARAM;
2096 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx,
2097 (LPARAM)&item);
2098
2099 mswindows_handle_gui_wm_command (frame, 0, item.lParam);
2100 }
2101 }
2102 break;
2103
2104 case WM_PAINT:
2105 /* hdc will be NULL unless this is a subwindow - in which case we
2106 shouldn't have received a paint message for it here. */
2107 assert (wParam == 0);
2108
2109 /* Can't queue a magic event because windows goes modal and sends paint
2110 messages directly to the windows procedure when doing solid drags
2111 and the message queue doesn't get processed. */
2112 mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
2113 break;
2114
2115 case WM_SIZE:
2116 /* We only care about this message if our size has really changed */
2117 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED)
2118 {
2119 RECT rect;
2120 int columns, rows;
2121
2122 fobj = mswindows_find_frame (hwnd);
2123 frame = XFRAME (fobj);
2124 msframe = FRAME_MSWINDOWS_DATA (frame);
2125
2126 /* We cannot handle frame map and unmap hooks right in
2127 this routine, because these may throw. We queue
2128 magic events to run these hooks instead - kkm */
2129
2130 if (wParam==SIZE_MINIMIZED)
2131 {
2132 /* Iconified */
2133 FRAME_VISIBLE_P (frame) = 0;
2134 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
2135 }
2136 else
2137 {
2138 GetClientRect(hwnd, &rect);
2139 FRAME_PIXWIDTH(frame) = rect.right;
2140 FRAME_PIXHEIGHT(frame) = rect.bottom;
2141
2142 pixel_to_real_char_size (frame, rect.right, rect.bottom,
2143 &FRAME_MSWINDOWS_CHARWIDTH (frame),
2144 &FRAME_MSWINDOWS_CHARHEIGHT (frame));
2145
2146 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows);
2147 change_frame_size (frame, rows, columns, 1);
2148
2149 /* If we are inside frame creation, we have to apply geometric
2150 properties now. */
2151 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2152 {
2153 /* Yes, we have to size again */
2154 mswindows_size_frame_internal ( frame,
2155 FRAME_MSWINDOWS_TARGET_RECT
2156 (frame));
2157 /* Reset so we do not get here again. The SetWindowPos call in
2158 * mswindows_size_frame_internal can cause recursion here. */
2159 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2160 {
2161 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame));
2162 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0;
2163 }
2164 }
2165 else
2166 {
2167 if (!msframe->sizing && !FRAME_VISIBLE_P (frame))
2168 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
2169 FRAME_VISIBLE_P (frame) = 1;
2170
2171 if (!msframe->sizing || mswindows_dynamic_frame_resize)
2172 redisplay ();
2173 }
2174 }
2175 }
2176 break;
2177
2178 case WM_DISPLAYCHANGE:
2179 {
2180 struct device *d;
2181
2182 fobj = mswindows_find_frame (hwnd);
2183 frame = XFRAME (fobj);
2184 d = XDEVICE (FRAME_DEVICE (frame));
2185
2186 DEVICE_MSWINDOWS_HORZRES(d) = LOWORD (lParam);
2187 DEVICE_MSWINDOWS_VERTRES(d) = HIWORD (lParam);
2188 DEVICE_MSWINDOWS_BITSPIXEL(d) = wParam;
2189 break;
2190 }
2191
2192 /* Misc magic events which only require that the frame be identified */
2193 case WM_SETFOCUS:
2194 case WM_KILLFOCUS:
2195 mswindows_enqueue_magic_event (hwnd, message);
2196 break;
2197
2198 case WM_WINDOWPOSCHANGING:
2199 {
2200 WINDOWPOS *wp = (LPWINDOWPOS) lParam;
2201 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) };
2202 GetWindowPlacement(hwnd, &wpl);
2203
2204 /* Only interested if size is changing and we're not being iconified */
2205 if (wpl.showCmd != SW_SHOWMINIMIZED
2206 && wpl.showCmd != SW_SHOWMAXIMIZED
2207 && !(wp->flags & SWP_NOSIZE))
2208 {
2209 RECT ncsize = { 0, 0, 0, 0 };
2210 int pixwidth, pixheight;
2211 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE),
2212 GetMenu(hwnd) != NULL,
2213 GetWindowLong (hwnd, GWL_EXSTYLE));
2214
2215 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)),
2216 wp->cx - (ncsize.right - ncsize.left),
2217 wp->cy - (ncsize.bottom - ncsize.top),
2218 &pixwidth, &pixheight);
2219
2220 /* Convert client sizes to window sizes */
2221 pixwidth += (ncsize.right - ncsize.left);
2222 pixheight += (ncsize.bottom - ncsize.top);
2223
2224 if (wpl.showCmd != SW_SHOWMAXIMIZED)
2225 {
2226 /* Adjust so that the bottom or right doesn't move if it's
2227 * the top or left that's being changed */
2228 RECT rect;
2229 GetWindowRect (hwnd, &rect);
2230
2231 if (rect.left != wp->x)
2232 wp->x += wp->cx - pixwidth;
2233 if (rect.top != wp->y)
2234 wp->y += wp->cy - pixheight;
2235 }
2236
2237 wp->cx = pixwidth;
2238 wp->cy = pixheight;
2239 }
2240 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts
2241 window position if the user tries to track window too small */
2242 }
2243 goto defproc;
2244
2245 case WM_ENTERSIZEMOVE:
2246 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2247 msframe->sizing = 1;
2248 return 0;
2249
2250 case WM_EXITSIZEMOVE:
2251 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2252 msframe->sizing = 0;
2253 /* Queue noop event */
2254 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
2255 return 0;
2256
2257 #ifdef HAVE_SCROLLBARS
2258 case WM_VSCROLL:
2259 case WM_HSCROLL:
2260 {
2261 /* Direction of scroll is determined by scrollbar instance. */
2262 int code = (int) LOWORD(wParam);
2263 int pos = (short int) HIWORD(wParam);
2264 HWND hwndScrollBar = (HWND) lParam;
2265 struct gcpro gcpro1, gcpro2;
2266
2267 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos);
2268 GCPRO2 (emacs_event, fobj);
2269 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */
2270 {
2271 /* Error during event pumping - cancel scroll */
2272 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0);
2273 }
2274 UNGCPRO;
2275 break;
2276 }
2277
2278 case WM_MOUSEWHEEL:
2279 {
2280 int keys = LOWORD (wParam); /* Modifier key flags */
2281 int delta = (short) HIWORD (wParam); /* Wheel rotation amount */
2282 struct gcpro gcpro1, gcpro2;
2283
2284 if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta))
2285 {
2286 GCPRO2 (emacs_event, fobj);
2287 mswindows_pump_outstanding_events (); /* Can GC */
2288 UNGCPRO;
2289 }
2290 else
2291 goto defproc;
2292 break;
2293 }
2294 #endif
2295
2296 #ifdef HAVE_MENUBARS
2297 case WM_INITMENU:
2298 if (UNBOUNDP (mswindows_handle_wm_initmenu (
2299 (HMENU) wParam,
2300 XFRAME (mswindows_find_frame (hwnd)))))
2301 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2302 break;
2303
2304 case WM_INITMENUPOPUP:
2305 if (!HIWORD(lParam))
2306 {
2307 if (UNBOUNDP (mswindows_handle_wm_initmenupopup (
2308 (HMENU) wParam,
2309 XFRAME (mswindows_find_frame (hwnd)))))
2310 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2311 }
2312 break;
2313
2314 #endif /* HAVE_MENUBARS */
2315
2316 case WM_COMMAND:
2317 {
2318 WORD id = LOWORD (wParam);
2319 WORD nid = HIWORD (wParam);
2320 HWND cid = (HWND)lParam;
2321 frame = XFRAME (mswindows_find_frame (hwnd));
2322
2323 #ifdef HAVE_TOOLBARS
2324 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
2325 break;
2326 #endif
2327 /* widgets in a buffer only eval a callback for suitable events.*/
2328 switch (nid)
2329 {
2330 case BN_CLICKED:
2331 case EN_CHANGE:
2332 case CBN_EDITCHANGE:
2333 case CBN_SELCHANGE:
2334 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
2335 return 0;
2336 }
2337 /* menubars always must come last since the hashtables do not
2338 always exist*/
2339 #ifdef HAVE_MENUBARS
2340 if (!NILP (mswindows_handle_wm_command (frame, id)))
2341 break;
2342 #endif
2343
2344 return DefWindowProc (hwnd, message, wParam, lParam);
2345 /* Bite me - a spurious command. This used to not be able to
2346 happen but with the introduction of widgets its now
2347 possible. */
2348 }
2349 break;
2350
2351 case WM_CTLCOLORBTN:
2352 case WM_CTLCOLORLISTBOX:
2353 case WM_CTLCOLOREDIT:
2354 case WM_CTLCOLORSTATIC:
2355 case WM_CTLCOLORSCROLLBAR:
2356 {
2357 /* if we get an opportunity to paint a widget then do so if
2358 there is an appropriate face */
2359 HWND crtlwnd = (HWND)lParam;
2360 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
2361 if (ii)
2362 {
2363 Lisp_Object image_instance;
2364 VOID_TO_LISP (image_instance, ii);
2365 if (IMAGE_INSTANCEP (image_instance)
2366 &&
2367 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET))
2368 {
2369 /* set colors for the buttons */
2370 HDC hdc = (HDC)wParam;
2371 if (last_widget_brushed != ii)
2372 {
2373 if (widget_brush)
2374 DeleteObject (widget_brush);
2375 widget_brush = CreateSolidBrush
2376 (COLOR_INSTANCE_MSWINDOWS_COLOR
2377 (XCOLOR_INSTANCE
2378 (FACE_BACKGROUND
2379 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2380 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2381 }
2382 last_widget_brushed = ii;
2383 SetTextColor
2384 (hdc,
2385 COLOR_INSTANCE_MSWINDOWS_COLOR
2386 (XCOLOR_INSTANCE
2387 (FACE_FOREGROUND
2388 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2389 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2390 SetBkMode (hdc, OPAQUE);
2391 SetBkColor
2392 (hdc,
2393 COLOR_INSTANCE_MSWINDOWS_COLOR
2394 (XCOLOR_INSTANCE
2395 (FACE_BACKGROUND
2396 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2397 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2398 return (LRESULT)widget_brush;
2399 }
2400 }
2401 }
2402 goto defproc;
2403
2404 #ifdef HAVE_DRAGNDROP
2405 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */
2406 {
2407 UINT filecount, i, len;
2408 POINT point;
2409 char* filename;
2410 char* fname;
2411
2412 Lisp_Object l_dndlist = Qnil, l_item = Qnil;
2413 struct gcpro gcpro1, gcpro2, gcpro3;
2414
2415 emacs_event = Fmake_event (Qnil, Qnil);
2416 event = XEVENT(emacs_event);
2417
2418 GCPRO3 (emacs_event, l_dndlist, l_item);
2419
2420 if (!DragQueryPoint ((HDROP) wParam, &point))
2421 point.x = point.y = -1; /* outside client area */
2422
2423 event->event_type = misc_user_event;
2424 event->channel = mswindows_find_frame(hwnd);
2425 event->timestamp = GetMessageTime();
2426 event->event.misc.button = 1; /* #### Should try harder */
2427 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0);
2428 event->event.misc.x = point.x;
2429 event->event.misc.y = point.y;
2430 event->event.misc.function = Qdragdrop_drop_dispatch;
2431
2432 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0);
2433 for (i=0; i<filecount; i++)
2434 {
2435 len = DragQueryFile ((HDROP) wParam, i, NULL, 0);
2436 /* The URLs that we make here aren't correct according to section
2437 * 3.10 of rfc1738 because they're missing the //<host>/ part and
2438 * because they may contain reserved characters. But that's OK -
2439 * they just need to be good enough to keep dragdrop.el happy. */
2440 fname = (char *)xmalloc (len+1);
2441 DragQueryFile ((HANDLE) wParam, i, fname, len+1);
2442
2443 /* May be a shell link aka "shortcut" - replace fname if so */
2444 #if !(defined(__CYGWIN32__) || defined(__MINGW32__))
2445 /* cygwin doesn't define this COM stuff */
2446 if (!stricmp (fname + strlen (fname) - 4, ".LNK"))
2447 {
2448 IShellLink* psl;
2449
2450 if (CoCreateInstance (&CLSID_ShellLink, NULL,
2451 CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl) == S_OK)
2452 {
2453 IPersistFile* ppf;
2454
2455 if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile,
2456 &ppf) == S_OK)
2457 {
2458 WORD wsz[MAX_PATH];
2459 WIN32_FIND_DATA wfd;
2460 LPSTR resolved = (char *) xmalloc (MAX_PATH+1);
2461
2462 MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, MAX_PATH);
2463
2464 if ((ppf->lpVtbl->Load (ppf, wsz, STGM_READ) == S_OK) &&
2465 (psl->lpVtbl->GetPath (psl, resolved, MAX_PATH,
2466 &wfd, 0)==S_OK))
2467 {
2468 xfree (fname);
2469 fname = resolved;
2470 len = strlen (fname);
2471 }
2472
2473 ppf->lpVtbl->Release (ppf);
2474 }
2475
2476 psl->lpVtbl->Release (psl);
2477 }
2478 }
2479 #endif
2480
2481 #ifdef __CYGWIN32__
2482 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
2483 strcpy (filename, "file:");
2484 cygwin32_win32_to_posix_path_list (fname, filename+5);
2485 #else
2486 filename = (char *)xmalloc (len+6);
2487 strcat (strcpy (filename, "file:"), fname);
2488 dostounix_filename (filename+5);
2489 #endif
2490 xfree (fname);
2491 l_item = make_string (filename, strlen (filename));
2492 l_dndlist = Fcons (l_item, l_dndlist);
2493 xfree (filename);
2494 }
2495 DragFinish ((HDROP) wParam);
2496
2497 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
2498 mswindows_enqueue_dispatch_event (emacs_event);
2499 UNGCPRO;
2500 }
2501 break;
2502 #endif
2503
2504 defproc:
2505 default:
2506 return DefWindowProc (hwnd, message, wParam, lParam);
2131 } 2507 }
2132 break;
2133
2134 /* Misc magic events which only require that the frame be identified */
2135 case WM_SETFOCUS:
2136 case WM_KILLFOCUS:
2137 mswindows_enqueue_magic_event (hwnd, message);
2138 break;
2139
2140 case WM_WINDOWPOSCHANGING:
2141 {
2142 WINDOWPOS *wp = (LPWINDOWPOS) lParam;
2143 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) };
2144 GetWindowPlacement(hwnd, &wpl);
2145
2146 /* Only interested if size is changing and we're not being iconified */
2147 if (wpl.showCmd != SW_SHOWMINIMIZED
2148 && wpl.showCmd != SW_SHOWMAXIMIZED
2149 && !(wp->flags & SWP_NOSIZE))
2150 {
2151 RECT ncsize = { 0, 0, 0, 0 };
2152 int pixwidth, pixheight;
2153 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE),
2154 GetMenu(hwnd) != NULL,
2155 GetWindowLong (hwnd, GWL_EXSTYLE));
2156
2157 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)),
2158 wp->cx - (ncsize.right - ncsize.left),
2159 wp->cy - (ncsize.bottom - ncsize.top),
2160 &pixwidth, &pixheight);
2161
2162 /* Convert client sizes to window sizes */
2163 pixwidth += (ncsize.right - ncsize.left);
2164 pixheight += (ncsize.bottom - ncsize.top);
2165
2166 if (wpl.showCmd != SW_SHOWMAXIMIZED)
2167 {
2168 /* Adjust so that the bottom or right doesn't move if it's
2169 * the top or left that's being changed */
2170 RECT rect;
2171 GetWindowRect (hwnd, &rect);
2172
2173 if (rect.left != wp->x)
2174 wp->x += wp->cx - pixwidth;
2175 if (rect.top != wp->y)
2176 wp->y += wp->cy - pixheight;
2177 }
2178
2179 wp->cx = pixwidth;
2180 wp->cy = pixheight;
2181 }
2182 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts
2183 window position if the user tries to track window too small */
2184 }
2185 goto defproc;
2186
2187 case WM_ENTERSIZEMOVE:
2188 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2189 msframe->sizing = 1;
2190 return 0;
2191
2192 case WM_EXITSIZEMOVE:
2193 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2194 msframe->sizing = 0;
2195 /* Queue noop event */
2196 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
2197 return 0;
2198
2199 #ifdef HAVE_SCROLLBARS
2200 case WM_VSCROLL:
2201 case WM_HSCROLL:
2202 {
2203 /* Direction of scroll is determined by scrollbar instance. */
2204 int code = (int) LOWORD(wParam);
2205 int pos = (short int) HIWORD(wParam);
2206 HWND hwndScrollBar = (HWND) lParam;
2207 struct gcpro gcpro1, gcpro2;
2208
2209 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos);
2210 GCPRO2 (emacs_event, fobj);
2211 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */
2212 {
2213 /* Error during event pumping - cancel scroll */
2214 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0);
2215 }
2216 UNGCPRO;
2217 break;
2218 }
2219
2220 case WM_MOUSEWHEEL:
2221 {
2222 int keys = LOWORD (wParam); /* Modifier key flags */
2223 int delta = (short) HIWORD (wParam); /* Wheel rotation amount */
2224 struct gcpro gcpro1, gcpro2;
2225
2226 if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta))
2227 {
2228 GCPRO2 (emacs_event, fobj);
2229 mswindows_pump_outstanding_events (); /* Can GC */
2230 UNGCPRO;
2231 }
2232 else
2233 goto defproc;
2234 break;
2235 }
2236 #endif
2237
2238 #ifdef HAVE_MENUBARS
2239 case WM_INITMENU:
2240 if (UNBOUNDP (mswindows_handle_wm_initmenu (
2241 (HMENU) wParam,
2242 XFRAME (mswindows_find_frame (hwnd)))))
2243 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2244 break;
2245
2246 case WM_INITMENUPOPUP:
2247 if (!HIWORD(lParam))
2248 {
2249 if (UNBOUNDP (mswindows_handle_wm_initmenupopup (
2250 (HMENU) wParam,
2251 XFRAME (mswindows_find_frame (hwnd)))))
2252 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2253 }
2254 break;
2255
2256 #endif /* HAVE_MENUBARS */
2257
2258 case WM_COMMAND:
2259 {
2260 WORD id = LOWORD (wParam);
2261 WORD nid = HIWORD (wParam);
2262 HWND cid = (HWND)lParam;
2263 frame = XFRAME (mswindows_find_frame (hwnd));
2264
2265 #ifdef HAVE_TOOLBARS
2266 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
2267 break;
2268 #endif
2269 /* widgets in a buffer only eval a callback for suitable events.*/
2270 switch (nid)
2271 {
2272 case BN_CLICKED:
2273 case EN_CHANGE:
2274 case CBN_EDITCHANGE:
2275 case CBN_SELCHANGE:
2276 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
2277 return 0;
2278 }
2279 /* menubars always must come last since the hashtables do not
2280 always exist*/
2281 #ifdef HAVE_MENUBARS
2282 if (!NILP (mswindows_handle_wm_command (frame, id)))
2283 break;
2284 #endif
2285
2286 return DefWindowProc (hwnd, message, wParam, lParam);
2287 /* Bite me - a spurious command. This used to not be able to
2288 happen but with the introduction of widgets its now
2289 possible. */
2290 }
2291 break;
2292
2293 case WM_CTLCOLORBTN:
2294 case WM_CTLCOLORLISTBOX:
2295 case WM_CTLCOLOREDIT:
2296 case WM_CTLCOLORSTATIC:
2297 case WM_CTLCOLORSCROLLBAR:
2298 {
2299 /* if we get an opportunity to paint a widget then do so if
2300 there is an appropriate face */
2301 HWND crtlwnd = (HWND)lParam;
2302 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
2303 if (ii)
2304 {
2305 Lisp_Object image_instance;
2306 VOID_TO_LISP (image_instance, ii);
2307 if (IMAGE_INSTANCEP (image_instance)
2308 &&
2309 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET))
2310 {
2311 /* set colors for the buttons */
2312 HDC hdc = (HDC)wParam;
2313 if (last_widget_brushed != ii)
2314 {
2315 if (widget_brush)
2316 DeleteObject (widget_brush);
2317 widget_brush = CreateSolidBrush
2318 (COLOR_INSTANCE_MSWINDOWS_COLOR
2319 (XCOLOR_INSTANCE
2320 (FACE_BACKGROUND
2321 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2322 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2323 }
2324 last_widget_brushed = ii;
2325 SetTextColor
2326 (hdc,
2327 COLOR_INSTANCE_MSWINDOWS_COLOR
2328 (XCOLOR_INSTANCE
2329 (FACE_FOREGROUND
2330 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2331 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2332 SetBkMode (hdc, OPAQUE);
2333 SetBkColor
2334 (hdc,
2335 COLOR_INSTANCE_MSWINDOWS_COLOR
2336 (XCOLOR_INSTANCE
2337 (FACE_BACKGROUND
2338 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2339 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2340 return (LRESULT)widget_brush;
2341 }
2342 }
2343 }
2344 goto defproc;
2345
2346 #ifdef HAVE_DRAGNDROP
2347 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */
2348 {
2349 UINT filecount, i, len;
2350 POINT point;
2351 char* filename;
2352 #ifdef __CYGWIN32__
2353 char* fname;
2354 #endif
2355 Lisp_Object l_dndlist = Qnil, l_item = Qnil;
2356 struct gcpro gcpro1, gcpro2, gcpro3;
2357
2358 emacs_event = Fmake_event (Qnil, Qnil);
2359 event = XEVENT(emacs_event);
2360
2361 GCPRO3 (emacs_event, l_dndlist, l_item);
2362
2363 if (!DragQueryPoint ((HDROP) wParam, &point))
2364 point.x = point.y = -1; /* outside client area */
2365
2366 event->event_type = misc_user_event;
2367 event->channel = mswindows_find_frame(hwnd);
2368 event->timestamp = GetMessageTime();
2369 event->event.misc.button = 1; /* #### Should try harder */
2370 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0);
2371 event->event.misc.x = point.x;
2372 event->event.misc.y = point.y;
2373 event->event.misc.function = Qdragdrop_drop_dispatch;
2374
2375 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0);
2376 for (i=0; i<filecount; i++)
2377 {
2378 len = DragQueryFile ((HDROP) wParam, i, NULL, 0);
2379 /* The URLs that we make here aren't correct according to section
2380 * 3.10 of rfc1738 because they're missing the //<host>/ part and
2381 * because they may contain reserved characters. But that's OK. */
2382 #ifdef __CYGWIN32__
2383 fname = (char *)xmalloc (len+1);
2384 DragQueryFile ((HANDLE) wParam, i, fname, len+1);
2385 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
2386 strcpy (filename, "file:");
2387 cygwin32_win32_to_posix_path_list (fname, filename+5);
2388 xfree (fname);
2389 #else
2390 filename = (char *)xmalloc (len+6);
2391 strcpy (filename, "file:");
2392 DragQueryFile ((HDROP) wParam, i, filename+5, len+1);
2393 dostounix_filename (filename+5);
2394 #endif
2395 l_item = make_string (filename, strlen (filename));
2396 l_dndlist = Fcons (l_item, l_dndlist);
2397 xfree (filename);
2398 }
2399 DragFinish ((HDROP) wParam);
2400
2401 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
2402 mswindows_enqueue_dispatch_event (emacs_event);
2403 UNGCPRO;
2404 }
2405 break;
2406 #endif
2407
2408 defproc:
2409 default:
2410 return DefWindowProc (hwnd, message, wParam, lParam);
2411 }
2412 return (0); 2508 return (0);
2413 } 2509 }
2414 2510
2415 2511
2416 /************************************************************************/ 2512 /************************************************************************/
2485 has_AltGr = mswindows_current_layout_has_AltGr (); 2581 has_AltGr = mswindows_current_layout_has_AltGr ();
2486 } 2582 }
2487 2583
2488 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) 2584 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80))
2489 { 2585 {
2490 mods |= (keymap [VK_LMENU] & 0x80) ? MOD_META : 0; 2586 mods |= (keymap [VK_LMENU] & 0x80) ? XEMACS_MOD_META : 0;
2491 mods |= (keymap [VK_RCONTROL] & 0x80) ? MOD_CONTROL : 0; 2587 mods |= (keymap [VK_RCONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0;
2492 } 2588 }
2493 else 2589 else
2494 { 2590 {
2495 mods |= (keymap [VK_MENU] & 0x80) ? MOD_META : 0; 2591 mods |= (keymap [VK_MENU] & 0x80) ? XEMACS_MOD_META : 0;
2496 mods |= (keymap [VK_CONTROL] & 0x80) ? MOD_CONTROL : 0; 2592 mods |= (keymap [VK_CONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0;
2497 } 2593 }
2498 2594
2499 mods |= (keymap [VK_SHIFT] & 0x80) ? MOD_SHIFT : 0; 2595 mods |= (keymap [VK_SHIFT] & 0x80) ? XEMACS_MOD_SHIFT : 0;
2500 2596
2501 return mods; 2597 return mods;
2502 } 2598 }
2503 2599
2504 /* 2600 /*
2552 case VK_SNAPSHOT: return KEYSYM ("print"); 2648 case VK_SNAPSHOT: return KEYSYM ("print");
2553 case VK_INSERT: return KEYSYM ("kp-insert"); 2649 case VK_INSERT: return KEYSYM ("kp-insert");
2554 case VK_DELETE: return KEYSYM ("kp-delete"); 2650 case VK_DELETE: return KEYSYM ("kp-delete");
2555 case VK_HELP: return KEYSYM ("help"); 2651 case VK_HELP: return KEYSYM ("help");
2556 #if 0 /* FSF Emacs allows these to return configurable syms/mods */ 2652 #if 0 /* FSF Emacs allows these to return configurable syms/mods */
2557 case VK_LWIN return KEYSYM (""); 2653 case VK_LWIN return KEYSYM ("");
2558 case VK_RWIN return KEYSYM (""); 2654 case VK_RWIN return KEYSYM ("");
2559 #endif 2655 #endif
2560 case VK_APPS: return KEYSYM ("menu"); 2656 case VK_APPS: return KEYSYM ("menu");
2561 case VK_NUMPAD0: return KEYSYM ("kp-0"); 2657 case VK_NUMPAD0: return KEYSYM ("kp-0");
2562 case VK_NUMPAD1: return KEYSYM ("kp-1"); 2658 case VK_NUMPAD1: return KEYSYM ("kp-1");
2563 case VK_NUMPAD2: return KEYSYM ("kp-2"); 2659 case VK_NUMPAD2: return KEYSYM ("kp-2");
2715 { 2811 {
2716 case XM_BUMPQUEUE: 2812 case XM_BUMPQUEUE:
2717 break; 2813 break;
2718 2814
2719 case WM_PAINT: 2815 case WM_PAINT:
2720 mswindows_handle_paint (XFRAME (EVENT_CHANNEL (emacs_event))); 2816 {
2817 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
2818 mswindows_handle_paint (f);
2819 (FRAME_MSWINDOWS_DATA (f))->paint_pending = 0;
2820 }
2721 break; 2821 break;
2722 2822
2723 case WM_SETFOCUS: 2823 case WM_SETFOCUS:
2724 case WM_KILLFOCUS: 2824 case WM_KILLFOCUS:
2725 { 2825 {
2776 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) 2876 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT)
2777 return (network_connection_p (p) 2877 return (network_connection_p (p)
2778 ? get_winsock_stream_waitable (XLSTREAM (instr)) 2878 ? get_winsock_stream_waitable (XLSTREAM (instr))
2779 : get_ntpipe_input_stream_waitable (XLSTREAM (instr))); 2879 : get_ntpipe_input_stream_waitable (XLSTREAM (instr)));
2780 #else 2880 #else
2781 return get_ntpipe_input_stream_waitable (XLSTREAM (instr)); 2881 return get_ntpipe_input_stream_waitable (XLSTREAM (instr));
2782 #endif 2882 #endif
2783 } 2883 }
2784 2884
2785 static void 2885 static void
2786 emacs_mswindows_select_process (Lisp_Process *process) 2886 emacs_mswindows_select_process (Lisp_Process *process)
2864 while (mswindows_quit_chars_count-- > 0) 2964 while (mswindows_quit_chars_count-- > 0)
2865 { 2965 {
2866 emacs_event = mswindows_cancel_dispatch_event (&match_against); 2966 emacs_event = mswindows_cancel_dispatch_event (&match_against);
2867 assert (!NILP (emacs_event)); 2967 assert (!NILP (emacs_event));
2868 2968
2869 if (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT) 2969 if (XEVENT(emacs_event)->event.key.modifiers & XEMACS_MOD_SHIFT)
2870 critical_p = 1; 2970 critical_p = 1;
2871 2971
2872 Fdeallocate_event(emacs_event); 2972 Fdeallocate_event(emacs_event);
2873 } 2973 }
2874 2974
2948 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream)))); 3048 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream))));
2949 } 3049 }
2950 3050
2951 USID 3051 USID
2952 emacs_mswindows_delete_stream_pair (Lisp_Object instream, 3052 emacs_mswindows_delete_stream_pair (Lisp_Object instream,
2953 Lisp_Object outstream) 3053 Lisp_Object outstream)
2954 { 3054 {
2955 /* Oh nothing special here for Win32 at all */ 3055 /* Oh nothing special here for Win32 at all */
2956 #if defined (HAVE_UNIX_PROCESSES) 3056 #if defined (HAVE_UNIX_PROCESSES)
2957 int in = (NILP(instream) 3057 int in = (NILP(instream)
2958 ? -1 3058 ? -1
3010 mswindows_pending_timers_count = 0; 3110 mswindows_pending_timers_count = 0;
3011 3111
3012 mswindows_event_stream = xnew (struct event_stream); 3112 mswindows_event_stream = xnew (struct event_stream);
3013 3113
3014 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; 3114 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p;
3115 mswindows_event_stream->force_event_pending = 0;
3015 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; 3116 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event;
3016 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; 3117 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event;
3017 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; 3118 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout;
3018 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; 3119 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout;
3019 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; 3120 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p;
3050 pdump_wire (&mswindows_s_dispatch_event_queue_tail); 3151 pdump_wire (&mswindows_s_dispatch_event_queue_tail);
3051 3152
3052 mswindows_error_caught_in_modal_loop = Qnil; 3153 mswindows_error_caught_in_modal_loop = Qnil;
3053 staticpro (&mswindows_error_caught_in_modal_loop); 3154 staticpro (&mswindows_error_caught_in_modal_loop);
3054 3155
3055 DEFVAR_BOOL ("mswindows-meta-activates-menu", &mswindows_meta_activates_menu /* 3156 DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu",
3056 *Controls whether pressing and releasing the Meta (Alt) key should 3157 &mswindows_alt_by_itself_activates_menu /*
3057 activate the menubar. 3158 *Controls whether pressing and releasing the Alt key activates the menubar.
3159 This applies only if no intervening key was pressed. See also
3160 `menu-accelerator-enabled', which is probably the behavior you actually want.
3058 Default is t. 3161 Default is t.
3059 */ ); 3162 */ );
3060 3163
3061 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /* 3164 DEFVAR_BOOL ("mswindows-dynamic-frame-resize",
3165 &mswindows_dynamic_frame_resize /*
3062 *Controls redrawing frame contents during mouse-drag or keyboard resize 3166 *Controls redrawing frame contents during mouse-drag or keyboard resize
3063 operation. When non-nil, the frame is redrawn while being resized. When 3167 operation. When non-nil, the frame is redrawn while being resized. When
3064 nil, frame is not redrawn, and exposed areas are filled with default 3168 nil, frame is not redrawn, and exposed areas are filled with default
3065 MDI application background color. Note that this option only has effect 3169 MDI application background color. Note that this option only has effect
3066 if "Show window contents while dragging" is on in system Display/Plus! 3170 if "Show window contents while dragging" is on in system Display/Plus!
3067 settings. 3171 settings.
3068 Default is t on fast machines, nil on slow. 3172 Default is t on fast machines, nil on slow.
3069 */ ); 3173 */ );
3070 3174
3071 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */ 3175 DEFVAR_INT ("mswindows-mouse-button-tolerance",
3072 DEFVAR_INT ("mswindows-mouse-button-tolerance", &mswindows_mouse_button_tolerance /* 3176 &mswindows_mouse_button_tolerance /*
3073 *Analogue of double click interval for faking middle mouse events. 3177 *Analogue of double click interval for faking middle mouse events.
3074 The value is the minimum time in milliseconds that must elapse between 3178 The value is the minimum time in milliseconds that must elapse between
3075 left/right button down events before they are considered distinct events. 3179 left/right button down events before they are considered distinct events.
3076 If both mouse buttons are depressed within this interval, a middle mouse 3180 If both mouse buttons are depressed within this interval, a middle mouse
3077 button down event is generated instead. 3181 button down event is generated instead.
3078 If negative or zero, currently set system default is used instead. 3182 If negative or zero, currently set system default is used instead.
3079 */ ); 3183 */ );
3080 3184
3081 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */
3082 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /* 3185 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /*
3083 Number of physical mouse buttons. 3186 Number of physical mouse buttons.
3084 */ ); 3187 */ );
3085 3188
3086 DEFVAR_INT ("mswindows-mouse-button-max-skew-x", &mswindows_mouse_button_max_skew_x /* 3189 DEFVAR_INT ("mswindows-mouse-button-max-skew-x",
3190 &mswindows_mouse_button_max_skew_x /*
3087 *Maximum horizontal distance in pixels between points in which left and 3191 *Maximum horizontal distance in pixels between points in which left and
3088 right button clicks occurred for them to be translated into single 3192 right button clicks occurred for them to be translated into single
3089 middle button event. Clicks must occur in time not longer than defined 3193 middle button event. Clicks must occur in time not longer than defined
3090 by the variable `mswindows-mouse-button-tolerance'. 3194 by the variable `mswindows-mouse-button-tolerance'.
3091 If negative or zero, currently set system default is used instead. 3195 If negative or zero, currently set system default is used instead.
3092 */ ); 3196 */ );
3093 3197
3094 DEFVAR_INT ("mswindows-mouse-button-max-skew-y", &mswindows_mouse_button_max_skew_y /* 3198 DEFVAR_INT ("mswindows-mouse-button-max-skew-y",
3199 &mswindows_mouse_button_max_skew_y /*
3095 *Maximum vertical distance in pixels between points in which left and 3200 *Maximum vertical distance in pixels between points in which left and
3096 right button clicks occurred for them to be translated into single 3201 right button clicks occurred for them to be translated into single
3097 middle button event. Clicks must occur in time not longer than defined 3202 middle button event. Clicks must occur in time not longer than defined
3098 by the variable `mswindows-mouse-button-tolerance'. 3203 by the variable `mswindows-mouse-button-tolerance'.
3099 If negative or zero, currently set system default is used instead. 3204 If negative or zero, currently set system default is used instead.
3100 */ ); 3205 */ );
3101 3206
3102 mswindows_mouse_button_max_skew_x = 0; 3207 mswindows_mouse_button_max_skew_x = 0;
3103 mswindows_mouse_button_max_skew_y = 0; 3208 mswindows_mouse_button_max_skew_y = 0;
3104 mswindows_mouse_button_tolerance = 0; 3209 mswindows_mouse_button_tolerance = 0;
3105 mswindows_meta_activates_menu = 1; 3210 mswindows_alt_by_itself_activates_menu = 1;
3106 } 3211 }
3107 3212
3108 void 3213 void
3109 syms_of_event_mswindows (void) 3214 syms_of_event_mswindows (void)
3110 { 3215 {