comparison src/event-msw.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children e804706bfb8c
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
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, 2000 Ben Wing. 4 Copyright (C) 1996 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"
45 # include "menubar-msw.h" 44 # include "menubar-msw.h"
46 #endif 45 #endif
47 46
48 #ifdef HAVE_DRAGNDROP 47 #ifdef HAVE_DRAGNDROP
49 # include "dragdrop.h" 48 # include "dragdrop.h"
55 #include "buffer.h" 54 #include "buffer.h"
56 #include "faces.h" 55 #include "faces.h"
57 #include "lstream.h" 56 #include "lstream.h"
58 #include "process.h" 57 #include "process.h"
59 #include "redisplay.h" 58 #include "redisplay.h"
60 #include "select.h"
61 #include "window.h"
62 #include "sysproc.h" 59 #include "sysproc.h"
63 #include "syswait.h" 60 #include "syswait.h"
64 #include "systime.h" 61 #include "systime.h"
65 #include "sysdep.h" 62 #include "sysdep.h"
66 #include "objects-msw.h" 63 #include "objects-msw.h"
67 64
68 #include "events-mod.h" 65 #include "events-mod.h"
69 #ifdef HAVE_MSG_SELECT 66 #ifdef HAVE_MSG_SELECT
70 #include "sysfile.h" 67 #include "sysfile.h"
71 #include "console-tty.h" 68 #include "console-tty.h"
72 #elif defined(CYGWIN) 69 #elif defined(__CYGWIN32__)
73 typedef unsigned int SOCKET; 70 typedef unsigned int SOCKET;
74 #endif 71 #endif
75 #include <io.h> 72 #include <io.h>
76 #include <errno.h> 73 #include <errno.h>
77
78 #if !(defined(CYGWIN) || defined(MINGW))
79 # include <shlobj.h> /* For IShellLink */
80 #endif
81 74
82 #ifdef HAVE_MENUBARS 75 #ifdef HAVE_MENUBARS
83 #define ADJR_MENUFLAG TRUE 76 #define ADJR_MENUFLAG TRUE
84 #else 77 #else
85 #define ADJR_MENUFLAG FALSE 78 #define ADJR_MENUFLAG FALSE
90 #define FAKE_MOD_QUIT 0x80 83 #define FAKE_MOD_QUIT 0x80
91 84
92 /* Timer ID used for button2 emulation */ 85 /* Timer ID used for button2 emulation */
93 #define BUTTON_2_TIMER_ID 1 86 #define BUTTON_2_TIMER_ID 1
94 87
88 extern Lisp_Object
89 mswindows_get_toolbar_button_text (struct frame* f, int command_id);
90 extern Lisp_Object
91 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
92 extern Lisp_Object
93 mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id);
94
95 static Lisp_Object mswindows_find_frame (HWND hwnd); 95 static Lisp_Object mswindows_find_frame (HWND hwnd);
96 static Lisp_Object mswindows_find_console (HWND hwnd); 96 static Lisp_Object mswindows_find_console (HWND hwnd);
97 static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, 97 static Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods);
98 int extendedp);
99 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr); 98 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr);
100 static void mswindows_set_chord_timer (HWND hwnd); 99 static void mswindows_set_chord_timer (HWND hwnd);
101 static int mswindows_button2_near_enough (POINTS p1, POINTS p2); 100 static int mswindows_button2_near_enough (POINTS p1, POINTS p2);
102 static int mswindows_current_layout_has_AltGr (void); 101 static int mswindows_current_layout_has_AltGr (void);
103 static int mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
104 int downp, int keyp);
105 102
106 static struct event_stream *mswindows_event_stream; 103 static struct event_stream *mswindows_event_stream;
107 104
108 #ifdef HAVE_MSG_SELECT 105 #ifdef HAVE_MSG_SELECT
109 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask; 106 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
130 static HANDLE mswindows_waitable_handles[MAX_WAITABLE]; 127 static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
131 128
132 /* Number of wait handles */ 129 /* Number of wait handles */
133 static int mswindows_waitable_count=0; 130 static int mswindows_waitable_count=0;
134 #endif /* HAVE_MSG_SELECT */ 131 #endif /* HAVE_MSG_SELECT */
135
136 /* Brush for painting widgets */ 132 /* Brush for painting widgets */
137 static HBRUSH widget_brush = 0; 133 static HBRUSH widget_brush = 0;
138 static LONG last_widget_brushed = 0; 134 static LONG last_widget_brushed = 0;
139 135
140 /* Count of quit chars currently in the queue */ 136 /* Count of quit chars currently in the queue */
142 Decremented in mswindows_dequeue_dispatch_event() */ 138 Decremented in mswindows_dequeue_dispatch_event() */
143 int mswindows_quit_chars_count = 0; 139 int mswindows_quit_chars_count = 0;
144 140
145 /* These are Lisp integers; see DEFVARS in this file for description. */ 141 /* These are Lisp integers; see DEFVARS in this file for description. */
146 int mswindows_dynamic_frame_resize; 142 int mswindows_dynamic_frame_resize;
147 int mswindows_alt_by_itself_activates_menu;
148 int mswindows_num_mouse_buttons; 143 int mswindows_num_mouse_buttons;
149 int mswindows_mouse_button_max_skew_x; 144 int mswindows_mouse_button_max_skew_x;
150 int mswindows_mouse_button_max_skew_y; 145 int mswindows_mouse_button_max_skew_y;
151 int mswindows_mouse_button_tolerance; 146 int mswindows_mouse_button_tolerance;
152
153 #ifdef DEBUG_XEMACS
154 int mswindows_debug_events;
155 #endif
156 147
157 /* This is the event signaled by the event pump. 148 /* This is the event signaled by the event pump.
158 See mswindows_pump_outstanding_events for comments */ 149 See mswindows_pump_outstanding_events for comments */
159 static Lisp_Object mswindows_error_caught_in_modal_loop; 150 static Lisp_Object mswindows_error_caught_in_modal_loop;
160 static int mswindows_in_modal_loop; 151 static int mswindows_in_modal_loop;
185 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */ 176 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */
186 177
187 struct ntpipe_slurp_stream_shared_data 178 struct ntpipe_slurp_stream_shared_data
188 { 179 {
189 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ 180 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
190 /* This is a manual-reset object. */ 181 /* This is a manual-reset object. */
191 HANDLE hev_caller; /* Caller blocks on this, and we signal it */ 182 HANDLE hev_caller; /* Caller blocks on this, and we signal it */
192 /* This is a manual-reset object. */ 183 /* This is a manual-reset object. */
193 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */ 184 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */
194 /* This is a manual-reset object. */ 185 /* This is a manual-reset object. */
195 HANDLE hpipe; /* Pipe read end handle. */ 186 HANDLE hpipe; /* Pipe read end handle. */
196 LONG die_p; /* Thread must exit ASAP if non-zero */ 187 LONG die_p; /* Thread must exit ASAP if non-zero */
197 BOOL eof_p : 1; /* Set when thread saw EOF */ 188 BOOL eof_p : 1; /* Set when thread saw EOF */
198 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ 189 BOOL error_p : 1; /* Read error other than EOF/broken pipe */
199 BOOL inuse_p : 1; /* this structure is in use */ 190 BOOL inuse_p : 1; /* this structure is in use */
200 LONG lock_count; /* Client count of this struct, 0=safe to free */ 191 LONG lock_count; /* Client count of this struct, 0=safe to free */
201 BYTE onebyte; /* One byte buffer read by thread */ 192 BYTE onebyte; /* One byte buffer read by thread */
202 }; 193 };
203 194
204 #define MAX_SLURP_STREAMS 32 195 #define MAX_SLURP_STREAMS 32
205 struct ntpipe_slurp_stream_shared_data 196 struct ntpipe_slurp_stream_shared_data
206 shared_data_block[MAX_SLURP_STREAMS]={{0}}; 197 shared_data_block[MAX_SLURP_STREAMS]={{0}};
207 198
208 struct ntpipe_slurp_stream 199 struct ntpipe_slurp_stream
209 { 200 {
210 LPARAM user_data; /* Any user data stored in the stream object */ 201 LPARAM user_data; /* Any user data stored in the stream object */
228 s->inuse_p = 0; 219 s->inuse_p = 0;
229 } 220 }
230 } 221 }
231 222
232 static struct ntpipe_slurp_stream_shared_data* 223 static struct ntpipe_slurp_stream_shared_data*
233 slurper_allocate_shared_data (void) 224 slurper_allocate_shared_data()
234 { 225 {
235 int i=0; 226 int i=0;
236 for (i=0; i<MAX_SLURP_STREAMS; i++) 227 for (i=0; i<MAX_SLURP_STREAMS; i++)
237 { 228 {
238 if (!shared_data_block[i].inuse_p) 229 if (!shared_data_block[i].inuse_p)
272 /* Before we notify caller, we unsignal our event. */ 263 /* Before we notify caller, we unsignal our event. */
273 ResetEvent (s->hev_thread); 264 ResetEvent (s->hev_thread);
274 265
275 /* Now we got something to notify caller, either a byte or an 266 /* Now we got something to notify caller, either a byte or an
276 error/eof indication. Before we do, allow internal pipe 267 error/eof indication. Before we do, allow internal pipe
277 buffer to accumulate little bit more data. 268 buffer to accumulate little bit more data.
278 Reader function pulses this event before waiting for 269 Reader function pulses this event before waiting for
279 a character, to avoid pipe delay, and to get the byte 270 a character, to avoid pipe delay, and to get the byte
280 immediately. */ 271 immediately. */
281 if (!s->die_p) 272 if (!s->die_p)
282 WaitForSingleObject (s->hev_unsleep, PIPE_READ_DELAY); 273 WaitForSingleObject (s->hev_unsleep, PIPE_READ_DELAY);
361 { 352 {
362 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream); 353 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream);
363 return s->thread_data->hev_caller; 354 return s->thread_data->hev_caller;
364 } 355 }
365 356
366 static ssize_t 357 static int
367 ntpipe_slurp_reader (Lstream *stream, unsigned char *data, size_t size) 358 ntpipe_slurp_reader (Lstream *stream, unsigned char *data, size_t size)
368 { 359 {
369 /* This function must be called from the main thread only */ 360 /* This function must be called from the main thread only */
370 struct ntpipe_slurp_stream_shared_data* s = 361 struct ntpipe_slurp_stream_shared_data* s =
371 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; 362 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data;
372 363
373 if (!s->die_p) 364 if (!s->die_p)
374 { 365 {
375 DWORD wait_result; 366 DWORD wait_result;
376 /* Disallow pipe read delay for the thread: we need a character 367 /* Disallow pipe read delay for the thread: we need a character
377 ASAP */ 368 ASAP */
378 SetEvent (s->hev_unsleep); 369 SetEvent (s->hev_unsleep);
379 370
380 /* Check if we have a character ready. Give it a short delay, 371 /* Check if we have a character ready. Give it a short delay,
381 for the thread to awake from pipe delay, just ion case*/ 372 for the thread to awake from pipe delay, just ion case*/
382 wait_result = WaitForSingleObject (s->hev_caller, 2); 373 wait_result = WaitForSingleObject (s->hev_caller, 2);
383 374
384 /* Revert to the normal sleep behavior. */ 375 /* Revert to the normal sleep behavior. */
425 fail if the next call fails. */ 416 fail if the next call fails. */
426 if (bytes_available) 417 if (bytes_available)
427 ReadFile (s->hpipe, data, min (bytes_available, size), 418 ReadFile (s->hpipe, data, min (bytes_available, size),
428 &bytes_read, NULL); 419 &bytes_read, NULL);
429 } 420 }
430 421
431 /* Now we can unblock thread, so it attempts to read more */ 422 /* Now we can unblock thread, so it attempts to read more */
432 SetEvent (s->hev_thread); 423 SetEvent (s->hev_thread);
433 return bytes_read + 1; 424 return bytes_read + 1;
434 } 425 }
435 } 426 }
436 return 0; 427 return 0;
437 } 428 }
438 429
439 static int 430 static int
440 ntpipe_slurp_closer (Lstream *stream) 431 ntpipe_slurp_closer (Lstream *stream)
441 { 432 {
442 /* This function must be called from the main thread only */ 433 /* This function must be called from the main thread only */
443 struct ntpipe_slurp_stream_shared_data* s = 434 struct ntpipe_slurp_stream_shared_data* s =
444 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; 435 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data;
445 436
446 /* Force thread to stop */ 437 /* Force thread to stop */
447 InterlockedIncrement (&s->die_p); 438 InterlockedIncrement (&s->die_p);
448 439
469 /************************************************************************/ 460 /************************************************************************/
470 461
471 #define NTPIPE_SHOVE_STREAM_DATA(stream) \ 462 #define NTPIPE_SHOVE_STREAM_DATA(stream) \
472 LSTREAM_TYPE_DATA (stream, ntpipe_shove) 463 LSTREAM_TYPE_DATA (stream, ntpipe_shove)
473 464
474 #define MAX_SHOVE_BUFFER_SIZE 512 465 #define MAX_SHOVE_BUFFER_SIZE 128
475 466
476 struct ntpipe_shove_stream 467 struct ntpipe_shove_stream
477 { 468 {
478 LPARAM user_data; /* Any user data stored in the stream object */ 469 LPARAM user_data; /* Any user data stored in the stream object */
479 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ 470 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
480 /* This is an auto-reset object. */ 471 /* This is an auto-reset object. */
481 HANDLE hpipe; /* Pipe write end handle. */ 472 HANDLE hpipe; /* Pipe write end handle. */
482 HANDLE hthread; /* Reader thread handle. */ 473 HANDLE hthread; /* Reader thread handle. */
483 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */ 474 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */
484 DWORD size; /* Number of bytes to write */ 475 DWORD size; /* Number of bytes to write */
485 LONG die_p; /* Thread must exit ASAP if non-zero */ 476 LONG die_p; /* Thread must exit ASAP if non-zero */
497 { 488 {
498 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam; 489 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam;
499 490
500 for (;;) 491 for (;;)
501 { 492 {
502 DWORD bytes_written; 493 DWORD bytes_written;
503 494
504 /* Block on event and wait for a job */ 495 /* Block on event and wait for a job */
505 InterlockedIncrement (&s->idle_p); 496 InterlockedIncrement (&s->idle_p);
506 WaitForSingleObject (s->hev_thread, INFINITE); 497 WaitForSingleObject (s->hev_thread, INFINITE);
507 498
508 /* Write passed buffer if any */ 499 if (s->die_p)
509 if (s->size > 0) 500 break;
501
502 /* Write passed buffer */
503 if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL)
504 || bytes_written != s->size)
510 { 505 {
511 if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL) 506 s->error_p = TRUE;
512 || bytes_written != s->size) 507 InterlockedIncrement (&s->die_p);
513 {
514 s->error_p = TRUE;
515 InterlockedIncrement (&s->die_p);
516 }
517 /* Set size to zero so we won't write it again if the closer sets
518 die_p and kicks us */
519 s->size = 0;
520 } 508 }
521 509
522 if (s->die_p) 510 if (s->die_p)
523 break; 511 break;
524 } 512 }
537 s->die_p = 0; 525 s->die_p = 0;
538 s->error_p = FALSE; 526 s->error_p = FALSE;
539 s->hpipe = hpipe; 527 s->hpipe = hpipe;
540 s->user_data = param; 528 s->user_data = param;
541 529
542 /* Create reader thread. This could fail, so do not 530 /* Create reader thread. This could fail, so do not
543 create the event until thread is created */ 531 create the event until thread is created */
544 s->hthread = CreateThread (NULL, 0, shove_thread, (LPVOID)s, 532 s->hthread = CreateThread (NULL, 0, shove_thread, (LPVOID)s,
545 CREATE_SUSPENDED, &thread_id_unused); 533 CREATE_SUSPENDED, &thread_id_unused);
546 if (s->hthread == NULL) 534 if (s->hthread == NULL)
547 { 535 {
548 Lstream_delete (lstr); 536 Lstream_delete (lstr);
549 return Qnil; 537 return Qnil;
550 } 538 }
551 539
552 /* Set the priority of the thread higher so we don't end up waiting
553 on it to send things. */
554 if (!SetThreadPriority (s->hthread, THREAD_PRIORITY_HIGHEST))
555 {
556 CloseHandle (s->hthread);
557 Lstream_delete (lstr);
558 return Qnil;
559 }
560
561 /* hev_thread is an auto-reset event, initially nonsignaled */ 540 /* hev_thread is an auto-reset event, initially nonsignaled */
562 s->hev_thread = CreateEvent (NULL, FALSE, FALSE, NULL); 541 s->hev_thread = CreateEvent (NULL, FALSE, FALSE, NULL);
563 542
564 /* Now let it go */ 543 /* Now let it go */
565 ResumeThread (s->hthread); 544 ResumeThread (s->hthread);
575 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); 554 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
576 return s->user_data; 555 return s->user_data;
577 } 556 }
578 #endif 557 #endif
579 558
580 static ssize_t 559 static int
581 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size) 560 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
582 { 561 {
583 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); 562 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
584 563
585 if (s->error_p) 564 if (s->error_p)
596 s->size = size; 575 s->size = size;
597 576
598 /* Start output */ 577 /* Start output */
599 InterlockedDecrement (&s->idle_p); 578 InterlockedDecrement (&s->idle_p);
600 SetEvent (s->hev_thread); 579 SetEvent (s->hev_thread);
601 /* Give it a chance to run -- this dramatically improves performance
602 of things like crypt. */
603 (void) SwitchToThread ();
604 return size; 580 return size;
605 } 581 }
606 582
607 static int 583 static int
608 ntpipe_shove_was_blocked_p (Lstream *stream) 584 ntpipe_shove_was_blocked_p (Lstream *stream)
617 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); 593 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
618 594
619 /* Force thread stop */ 595 /* Force thread stop */
620 InterlockedIncrement (&s->die_p); 596 InterlockedIncrement (&s->die_p);
621 597
622 /* Thread will end upon unblocking. If it's already unblocked this will 598 /* Close pipe handle, possibly breaking it */
623 do nothing, but the thread won't look at die_p until it's written any 599 CloseHandle (s->hpipe);
624 pending output. */ 600
601 /* Thread will end upon unblocking */
625 SetEvent (s->hev_thread); 602 SetEvent (s->hev_thread);
626 603
627 /* Wait while thread terminates */ 604 /* Wait while thread terminates */
628 WaitForSingleObject (s->hthread, INFINITE); 605 WaitForSingleObject (s->hthread, INFINITE);
629
630 /* Close pipe handle, possibly breaking it */
631 CloseHandle (s->hpipe);
632
633 /* Close the thread handle */
634 CloseHandle (s->hthread); 606 CloseHandle (s->hthread);
635 607
636 /* Destroy the event */ 608 /* Destroy the event */
637 CloseHandle (s->hev_thread); 609 CloseHandle (s->hev_thread);
638 610
658 { 630 {
659 LPARAM user_data; /* Any user data stored in the stream object */ 631 LPARAM user_data; /* Any user data stored in the stream object */
660 SOCKET s; /* Socket handle (which is a Win32 handle) */ 632 SOCKET s; /* Socket handle (which is a Win32 handle) */
661 OVERLAPPED ov; /* Overlapped I/O structure */ 633 OVERLAPPED ov; /* Overlapped I/O structure */
662 void* buffer; /* Buffer. Allocated for input stream only */ 634 void* buffer; /* Buffer. Allocated for input stream only */
663 unsigned long bufsize; /* Number of bytes last read */ 635 unsigned int bufsize; /* Number of bytes last read */
664 unsigned long bufpos; /* Position in buffer for next fetch */ 636 unsigned int bufpos; /* Position in buffer for next fetch */
665 unsigned int error_p :1; /* I/O Error seen */ 637 unsigned int error_p :1; /* I/O Error seen */
666 unsigned int eof_p :1; /* EOF Error seen */ 638 unsigned int eof_p :1; /* EOF Error seen */
667 unsigned int pending_p :1; /* There is a pending I/O operation */ 639 unsigned int pending_p :1; /* There is a pending I/O operation */
668 unsigned int blocking_p :1; /* Last write attempt would block */ 640 unsigned int blocking_p :1; /* Last write attempt would block */
669 }; 641 };
691 } 663 }
692 else if (str->bufsize == 0) 664 else if (str->bufsize == 0)
693 str->eof_p = 1; 665 str->eof_p = 1;
694 } 666 }
695 667
696 static ssize_t 668 static int
697 winsock_reader (Lstream *stream, unsigned char *data, size_t size) 669 winsock_reader (Lstream *stream, unsigned char *data, size_t size)
698 { 670 {
699 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream); 671 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
700 672
701 /* If the current operation is not yet complete, there's nothing to 673 /* If the current operation is not yet complete, there's nothing to
724 696
725 if (str->eof_p) 697 if (str->eof_p)
726 return 0; 698 return 0;
727 if (str->error_p) 699 if (str->error_p)
728 return -1; 700 return -1;
729 701
730 /* Return as much of buffer as we have */ 702 /* Return as much of buffer as we have */
731 size = min (size, (size_t) (str->bufsize - str->bufpos)); 703 size = min (size, (size_t) (str->bufsize - str->bufpos));
732 memcpy (data, (void*)((BYTE*)str->buffer + str->bufpos), size); 704 memcpy (data, (void*)((BYTE*)str->buffer + str->bufpos), size);
733 str->bufpos += size; 705 str->bufpos += size;
734 706
737 winsock_initiate_read (str); 709 winsock_initiate_read (str);
738 710
739 return size; 711 return size;
740 } 712 }
741 713
742 static ssize_t 714 static int
743 winsock_writer (Lstream *stream, const unsigned char *data, size_t size) 715 winsock_writer (Lstream *stream, CONST unsigned char *data, size_t size)
744 { 716 {
745 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream); 717 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
746 718
747 if (str->pending_p) 719 if (str->pending_p)
748 { 720 {
765 if (str->error_p) 737 if (str->error_p)
766 return -1; 738 return -1;
767 739
768 if (size == 0) 740 if (size == 0)
769 return 0; 741 return 0;
770 742
771 { 743 {
772 ResetEvent (str->ov.hEvent); 744 ResetEvent (str->ov.hEvent);
773 745
774 /* Docs indicate that 4th parameter to WriteFile can be NULL since this is 746 /* Docs indicate that 4th parameter to WriteFile can be NULL since this is
775 * an overlapped operation. This fails on Win95 with winsock 1.x so we 747 * an overlapped operation. This fails on Win95 with winsock 1.x so we
811 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream); 783 struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
812 return str->blocking_p; 784 return str->blocking_p;
813 } 785 }
814 786
815 static Lisp_Object 787 static Lisp_Object
816 make_winsock_stream_1 (SOCKET s, LPARAM param, const char *mode) 788 make_winsock_stream_1 (SOCKET s, LPARAM param, CONST char *mode)
817 { 789 {
818 Lisp_Object obj; 790 Lisp_Object obj;
819 Lstream *lstr = Lstream_new (lstream_winsock, mode); 791 Lstream *lstr = Lstream_new (lstream_winsock, mode);
820 struct winsock_stream *str = WINSOCK_STREAM_DATA (lstr); 792 struct winsock_stream *str = WINSOCK_STREAM_DATA (lstr);
821 793
879 /************************************************************************/ 851 /************************************************************************/
880 /* Dispatch queue management */ 852 /* Dispatch queue management */
881 /************************************************************************/ 853 /************************************************************************/
882 854
883 static int 855 static int
884 mswindows_user_event_p (Lisp_Event* sevt) 856 mswindows_user_event_p (struct Lisp_Event* sevt)
885 { 857 {
886 return (sevt->event_type == key_press_event 858 return (sevt->event_type == key_press_event
887 || sevt->event_type == button_press_event 859 || sevt->event_type == button_press_event
888 || sevt->event_type == button_release_event 860 || sevt->event_type == button_release_event
889 || sevt->event_type == misc_user_event); 861 || sevt->event_type == misc_user_event);
890 } 862 }
891 863
892 /* 864 /*
893 * Add an emacs event to the proper dispatch queue 865 * Add an emacs event to the proper dispatch queue
894 */ 866 */
895 void 867 static void
896 mswindows_enqueue_dispatch_event (Lisp_Object event) 868 mswindows_enqueue_dispatch_event (Lisp_Object event)
897 { 869 {
898 int user_p = mswindows_user_event_p (XEVENT(event)); 870 int user_p = mswindows_user_event_p (XEVENT(event));
899 enqueue_event (event, 871 enqueue_event (event,
900 user_p ? &mswindows_u_dispatch_event_queue : 872 user_p ? &mswindows_u_dispatch_event_queue :
901 &mswindows_s_dispatch_event_queue, 873 &mswindows_s_dispatch_event_queue,
902 user_p ? &mswindows_u_dispatch_event_queue_tail : 874 user_p ? &mswindows_u_dispatch_event_queue_tail :
903 &mswindows_s_dispatch_event_queue_tail); 875 &mswindows_s_dispatch_event_queue_tail);
904 876
905 /* Avoid blocking on WaitMessage */ 877 /* Avoid blocking on WaitMessage */
906 PostMessage (NULL, XM_BUMPQUEUE, 0, 0); 878 PostMessage (NULL, XM_BUMPQUEUE, 0, 0);
907 } 879 }
908 880
915 void 887 void
916 mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function, 888 mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function,
917 Lisp_Object object) 889 Lisp_Object object)
918 { 890 {
919 Lisp_Object event = Fmake_event (Qnil, Qnil); 891 Lisp_Object event = Fmake_event (Qnil, Qnil);
920 Lisp_Event* e = XEVENT (event); 892 struct Lisp_Event* e = XEVENT (event);
921 893
922 e->event_type = misc_user_event; 894 e->event_type = misc_user_event;
923 e->channel = channel; 895 e->channel = channel;
924 e->timestamp = GetTickCount ();
925 e->event.misc.function = function; 896 e->event.misc.function = function;
926 e->event.misc.object = object; 897 e->event.misc.object = object;
927 898
928 mswindows_enqueue_dispatch_event (event); 899 mswindows_enqueue_dispatch_event (event);
929 } 900 }
930 901
931 void 902 void
932 mswindows_enqueue_magic_event (HWND hwnd, UINT msg) 903 mswindows_enqueue_magic_event (HWND hwnd, UINT message)
933 { 904 {
934 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 905 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
935 Lisp_Event* event = XEVENT (emacs_event); 906 struct Lisp_Event* event = XEVENT (emacs_event);
936 907
937 event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil; 908 event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil;
938 event->timestamp = GetMessageTime(); 909 event->timestamp = GetMessageTime();
939 event->event_type = magic_event; 910 event->event_type = magic_event;
940 EVENT_MSWINDOWS_MAGIC_TYPE (event) = msg; 911 EVENT_MSWINDOWS_MAGIC_TYPE (event) = message;
941 912
942 mswindows_enqueue_dispatch_event (emacs_event); 913 mswindows_enqueue_dispatch_event (emacs_event);
943 } 914 }
944 915
945 static void 916 static void
946 mswindows_enqueue_process_event (Lisp_Process* p) 917 mswindows_enqueue_process_event (struct Lisp_Process* p)
947 { 918 {
948 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 919 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
949 Lisp_Event* event = XEVENT (emacs_event); 920 struct Lisp_Event* event = XEVENT (emacs_event);
950 Lisp_Object process; 921 Lisp_Object process;
951 XSETPROCESS (process, p); 922 XSETPROCESS (process, p);
952 923
953 event->event_type = process_event; 924 event->event_type = process_event;
954 event->timestamp = GetTickCount (); 925 event->timestamp = GetTickCount ();
956 927
957 mswindows_enqueue_dispatch_event (emacs_event); 928 mswindows_enqueue_dispatch_event (emacs_event);
958 } 929 }
959 930
960 static void 931 static void
961 mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, 932 mswindows_enqueue_mouse_button_event (HWND hwnd, UINT message, POINTS where, DWORD when)
962 DWORD when) 933 {
963 {
964 int downp = (msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN ||
965 msg == WM_RBUTTONDOWN);
966 934
967 /* We always use last message time, because mouse button 935 /* We always use last message time, because mouse button
968 events may get delayed, and XEmacs double click 936 events may get delayed, and XEmacs double click
969 recognition will fail */ 937 recognition will fail */
970 938
971 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 939 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
972 Lisp_Event* event = XEVENT (emacs_event); 940 struct Lisp_Event* event = XEVENT(emacs_event);
973 941
974 mswindows_handle_sticky_modifiers (0, 0, downp, 0); 942 event->channel = mswindows_find_frame(hwnd);
975 event->channel = mswindows_find_frame (hwnd);
976 event->timestamp = when; 943 event->timestamp = when;
977 event->event.button.button = 944 event->event.button.button =
978 (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 : 945 (message==WM_LBUTTONDOWN || message==WM_LBUTTONUP) ? 1 :
979 ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2); 946 ((message==WM_RBUTTONDOWN || message==WM_RBUTTONUP) ? 3 : 2);
980 event->event.button.x = where.x; 947 event->event.button.x = where.x;
981 event->event.button.y = where.y; 948 event->event.button.y = where.y;
982 event->event.button.modifiers = mswindows_modifier_state (NULL, 0); 949 event->event.button.modifiers = mswindows_modifier_state (NULL, 0);
983 950
984 if (downp) 951 if (message==WM_LBUTTONDOWN || message==WM_MBUTTONDOWN ||
952 message==WM_RBUTTONDOWN)
985 { 953 {
986 event->event_type = button_press_event; 954 event->event_type = button_press_event;
987 SetCapture (hwnd); 955 SetCapture (hwnd);
988 /* we need this to make sure the main window regains the focus 956 /* we need this to make sure the main window regains the focus
989 from control subwindows */ 957 from control subwindows */
996 else 964 else
997 { 965 {
998 event->event_type = button_release_event; 966 event->event_type = button_release_event;
999 ReleaseCapture (); 967 ReleaseCapture ();
1000 } 968 }
1001 969
1002 mswindows_enqueue_dispatch_event (emacs_event); 970 mswindows_enqueue_dispatch_event (emacs_event);
1003 } 971 }
1004 972
1005 static void 973 static void
1006 mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods) 974 mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods)
1007 { 975 {
1008 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 976 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1009 Lisp_Event* event = XEVENT(emacs_event); 977 struct Lisp_Event* event = XEVENT(emacs_event);
1010 978
1011 event->channel = mswindows_find_console(hwnd); 979 event->channel = mswindows_find_console(hwnd);
1012 event->timestamp = GetMessageTime(); 980 event->timestamp = GetMessageTime();
1013 event->event_type = key_press_event; 981 event->event_type = key_press_event;
1014 event->event.key.keysym = keysym; 982 event->event.key.keysym = keysym;
1019 /* 987 /*
1020 * Remove and return the first emacs event on the dispatch queue. 988 * Remove and return the first emacs event on the dispatch queue.
1021 * Give a preference to user events over non-user ones. 989 * Give a preference to user events over non-user ones.
1022 */ 990 */
1023 static Lisp_Object 991 static Lisp_Object
1024 mswindows_dequeue_dispatch_event (void) 992 mswindows_dequeue_dispatch_event ()
1025 { 993 {
1026 Lisp_Object event; 994 Lisp_Object event;
1027 Lisp_Event* sevt; 995 struct Lisp_Event* sevt;
1028 996
1029 assert (!NILP(mswindows_u_dispatch_event_queue) || 997 assert (!NILP(mswindows_u_dispatch_event_queue) ||
1030 !NILP(mswindows_s_dispatch_event_queue)); 998 !NILP(mswindows_s_dispatch_event_queue));
1031 999
1032 event = dequeue_event ( 1000 event = dequeue_event (
1033 NILP(mswindows_u_dispatch_event_queue) ? 1001 NILP(mswindows_u_dispatch_event_queue) ?
1034 &mswindows_s_dispatch_event_queue : 1002 &mswindows_s_dispatch_event_queue :
1035 &mswindows_u_dispatch_event_queue, 1003 &mswindows_u_dispatch_event_queue,
1036 NILP(mswindows_u_dispatch_event_queue) ? 1004 NILP(mswindows_u_dispatch_event_queue) ?
1037 &mswindows_s_dispatch_event_queue_tail : 1005 &mswindows_s_dispatch_event_queue_tail :
1038 &mswindows_u_dispatch_event_queue_tail); 1006 &mswindows_u_dispatch_event_queue_tail);
1039 1007
1040 sevt = XEVENT(event); 1008 sevt = XEVENT(event);
1041 if (sevt->event_type == key_press_event 1009 if (sevt->event_type == key_press_event
1056 * event in the queue and that of the given event is non-zero. 1024 * event in the queue and that of the given event is non-zero.
1057 * For all other event types, this function aborts. 1025 * For all other event types, this function aborts.
1058 */ 1026 */
1059 1027
1060 Lisp_Object 1028 Lisp_Object
1061 mswindows_cancel_dispatch_event (Lisp_Event *match) 1029 mswindows_cancel_dispatch_event (struct Lisp_Event *match)
1062 { 1030 {
1063 Lisp_Object event; 1031 Lisp_Object event;
1064 Lisp_Object previous_event = Qnil; 1032 Lisp_Object previous_event = Qnil;
1065 int user_p = mswindows_user_event_p (match); 1033 int user_p = mswindows_user_event_p (match);
1066 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : 1034 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue :
1067 &mswindows_s_dispatch_event_queue; 1035 &mswindows_s_dispatch_event_queue;
1068 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : 1036 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail :
1069 &mswindows_s_dispatch_event_queue_tail; 1037 &mswindows_s_dispatch_event_queue_tail;
1070 1038
1071 assert (match->event_type == timeout_event 1039 assert (match->event_type == timeout_event
1072 || match->event_type == key_press_event); 1040 || match->event_type == key_press_event);
1073 1041
1074 EVENT_CHAIN_LOOP (event, *head) 1042 EVENT_CHAIN_LOOP (event, *head)
1075 { 1043 {
1076 Lisp_Event *e = XEVENT (event); 1044 struct Lisp_Event *e = XEVENT (event);
1077 if ((e->event_type == match->event_type) && 1045 if ((e->event_type == match->event_type) &&
1078 ((e->event_type == timeout_event) ? 1046 ((e->event_type == timeout_event) ?
1079 (e->event.timeout.interval_id == match->event.timeout.interval_id) : 1047 (e->event.timeout.interval_id == match->event.timeout.interval_id) :
1080 /* Must be key_press_event */ 1048 /* Must be key_press_event */
1081 ((e->event.key.modifiers & match->event.key.modifiers) != 0))) 1049 ((e->event.key.modifiers & match->event.key.modifiers) != 0)))
1086 { 1054 {
1087 XSET_EVENT_NEXT (previous_event, XEVENT_NEXT (event)); 1055 XSET_EVENT_NEXT (previous_event, XEVENT_NEXT (event));
1088 if (EQ (*tail, event)) 1056 if (EQ (*tail, event))
1089 *tail = previous_event; 1057 *tail = previous_event;
1090 } 1058 }
1091 1059
1092 return event; 1060 return event;
1093 } 1061 }
1094 previous_event = event; 1062 previous_event = event;
1095 } 1063 }
1096 return Qnil; 1064 return Qnil;
1127 { 1095 {
1128 int ix = find_waitable_handle (h); 1096 int ix = find_waitable_handle (h);
1129 if (ix < 0) 1097 if (ix < 0)
1130 return; 1098 return;
1131 1099
1132 mswindows_waitable_handles [ix] = 1100 mswindows_waitable_handles [ix] =
1133 mswindows_waitable_handles [--mswindows_waitable_count]; 1101 mswindows_waitable_handles [--mswindows_waitable_count];
1134 } 1102 }
1135 #endif /* HAVE_MSG_SELECT */ 1103 #endif /* HAVE_MSG_SELECT */
1136 1104
1137 1105
1151 mswindows_protect_modal_loop (Lisp_Object (*bfun) (Lisp_Object barg), 1119 mswindows_protect_modal_loop (Lisp_Object (*bfun) (Lisp_Object barg),
1152 Lisp_Object barg) 1120 Lisp_Object barg)
1153 { 1121 {
1154 Lisp_Object tmp; 1122 Lisp_Object tmp;
1155 1123
1156 ++mswindows_in_modal_loop; 1124 ++mswindows_in_modal_loop;
1157 tmp = condition_case_1 (Qt, 1125 tmp = condition_case_1 (Qt,
1158 bfun, barg, 1126 bfun, barg,
1159 mswindows_modal_loop_error_handler, Qnil); 1127 mswindows_modal_loop_error_handler, Qnil);
1160 --mswindows_in_modal_loop; 1128 --mswindows_in_modal_loop;
1161 1129
1175 Fsignal (sym, data); 1143 Fsignal (sym, data);
1176 } 1144 }
1177 } 1145 }
1178 1146
1179 /* 1147 /*
1180 * This is an unsafe part of event pump, guarded by 1148 * This is an unsafe part of event pump, guarded by
1181 * condition_case. See mswindows_pump_outstanding_events 1149 * condition_case. See mswindows_pump_outstanding_events
1182 */ 1150 */
1183 static Lisp_Object 1151 static Lisp_Object
1184 mswindows_unsafe_pump_events (Lisp_Object u_n_u_s_e_d) 1152 mswindows_unsafe_pump_events (Lisp_Object u_n_u_s_e_d)
1185 { 1153 {
1199 if (do_redisplay) 1167 if (do_redisplay)
1200 redisplay (); 1168 redisplay ();
1201 1169
1202 Fdeallocate_event (event); 1170 Fdeallocate_event (event);
1203 UNGCPRO; 1171 UNGCPRO;
1204 1172
1205 /* Qt becomes return value of mswindows_pump_outstanding_events 1173 /* Qt becomes return value of mswindows_pump_outstanding_events
1206 once we get here */ 1174 once we get here */
1207 return Qt; 1175 return Qt;
1208 } 1176 }
1209 1177
1247 /* This function can call lisp */ 1215 /* This function can call lisp */
1248 1216
1249 Lisp_Object result = Qt; 1217 Lisp_Object result = Qt;
1250 struct gcpro gcpro1; 1218 struct gcpro gcpro1;
1251 GCPRO1 (result); 1219 GCPRO1 (result);
1252 1220
1253 if (NILP(mswindows_error_caught_in_modal_loop)) 1221 if (NILP(mswindows_error_caught_in_modal_loop))
1254 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil); 1222 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil);
1255 UNGCPRO; 1223 UNGCPRO;
1256 return result; 1224 return result;
1257 } 1225 }
1258 1226
1259 /* 1227 static void
1260 * KEYBOARD_ONLY_P is set to non-zero when we are called from 1228 mswindows_drain_windows_queue ()
1261 * QUITP, and are interesting in keyboard messages only.
1262 */
1263 static void
1264 mswindows_drain_windows_queue (void)
1265 { 1229 {
1266 MSG msg; 1230 MSG msg;
1267
1268 /* should call mswindows_need_event_in_modal_loop() if in modal loop */
1269 assert (!mswindows_in_modal_loop);
1270
1271 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) 1231 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
1272 { 1232 {
1273 /* We have to translate messages that are not sent to an XEmacs 1233 /* we have to translate messages that are not sent to the main
1274 frame. This is so that key presses work ok in things like 1234 window. this is so that key presses work ok in things like
1275 edit fields. However, we *musn't* translate message for XEmacs 1235 edit fields. however, we *musn't* translate message for the
1276 frames as this is handled in the wnd proc. 1236 main window as this is handled in the wnd proc. */
1277 We also have to avoid generating paint magic events for windows 1237 if ( GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD )
1278 that aren't XEmacs frames */
1279 /* GetClassName will truncate a longer class name. By adding one
1280 extra character, we are forcing textual comparison to fail
1281 if the name is longer than XEMACS_CLASS */
1282 char class_name_buf [sizeof (XEMACS_CLASS) + 2] = "";
1283 GetClassName (msg.hwnd, class_name_buf, sizeof (class_name_buf) - 1);
1284 if (stricmp (class_name_buf, XEMACS_CLASS) != 0)
1285 { 1238 {
1286 /* Not an XEmacs frame */
1287 TranslateMessage (&msg); 1239 TranslateMessage (&msg);
1288 }
1289 else if (msg.message == WM_PAINT)
1290 {
1291 struct mswindows_frame* msframe;
1292
1293 /* hdc will be NULL unless this is a subwindow - in which case we
1294 shouldn't have received a paint message for it here. */
1295 assert (msg.wParam == 0);
1296
1297 /* Queue a magic event for handling when safe */
1298 msframe =
1299 FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (msg.hwnd)));
1300 if (!msframe->paint_pending)
1301 {
1302 msframe->paint_pending = 1;
1303 mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT);
1304 }
1305 /* Don't dispatch. WM_PAINT is always the last message in the
1306 queue so it's OK to just return. */
1307 return;
1308 } 1240 }
1309 DispatchMessage (&msg); 1241 DispatchMessage (&msg);
1310 mswindows_unmodalize_signal_maybe (); 1242 mswindows_unmodalize_signal_maybe ();
1311 } 1243 }
1312 } 1244 }
1313 1245
1314 /* 1246 /*
1315 * This is a special flavor of the mswindows_need_event function, 1247 * This is a special flavor of the mswindows_need_event function,
1316 * used while in event pump. Actually, there is only kind of events 1248 * used while in event pump. Actually, there is only kind of events
1317 * allowed while in event pump: a timer. An attempt to fetch any 1249 * allowed while in event pump: a timer. An attempt to fetch any
1318 * other event leads to a deadlock, as there's no source of user input 1250 * other event leads to a deadlock, as there's no source of user input
1319 * ('cause event pump mirrors windows modal loop, which is a sole 1251 * ('cause event pump mirrors windows modal loop, which is a sole
1342 while (NILP (mswindows_s_dispatch_event_queue)) 1274 while (NILP (mswindows_s_dispatch_event_queue))
1343 { 1275 {
1344 /* We'll deadlock if go waiting */ 1276 /* We'll deadlock if go waiting */
1345 if (mswindows_pending_timers_count == 0) 1277 if (mswindows_pending_timers_count == 0)
1346 error ("Deadlock due to an attempt to call next-event in a wrong context"); 1278 error ("Deadlock due to an attempt to call next-event in a wrong context");
1347 1279
1348 /* Fetch and dispatch any pending timers */ 1280 /* Fetch and dispatch any pending timers */
1349 GetMessage (&msg, NULL, WM_TIMER, WM_TIMER); 1281 GetMessage (&msg, NULL, WM_TIMER, WM_TIMER);
1350 DispatchMessage (&msg); 1282 DispatchMessage (&msg);
1351 } 1283 }
1352 } 1284 }
1367 { 1299 {
1368 mswindows_need_event_in_modal_loop (badly_p); 1300 mswindows_need_event_in_modal_loop (badly_p);
1369 return; 1301 return;
1370 } 1302 }
1371 1303
1304 /* Have to drain Windows message queue first, otherwise, we may miss
1305 quit char when called from quit_p */
1306 mswindows_drain_windows_queue ();
1307
1372 while (NILP (mswindows_u_dispatch_event_queue) 1308 while (NILP (mswindows_u_dispatch_event_queue)
1373 && NILP (mswindows_s_dispatch_event_queue)) 1309 && NILP (mswindows_s_dispatch_event_queue))
1374 { 1310 {
1375 #ifdef HAVE_MSG_SELECT 1311 #ifdef HAVE_MSG_SELECT
1376 int i; 1312 int i;
1377 SELECT_TYPE temp_mask = input_wait_mask; 1313 SELECT_TYPE temp_mask = input_wait_mask;
1378 EMACS_TIME sometime; 1314 EMACS_TIME sometime;
1379 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this; 1315 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;
1380 1316
1381 if (badly_p) 1317 if (badly_p)
1382 pointer_to_this = 0; 1318 pointer_to_this = 0;
1383 else 1319 else
1384 { 1320 {
1385 EMACS_SET_SECS_USECS (sometime, 0, 0); 1321 EMACS_SET_SECS_USECS (sometime, 0, 0);
1386 EMACS_TIME_TO_SELECT_TIME (sometime, select_time_to_block); 1322 EMACS_TIME_TO_SELECT_TIME (sometime, select_time_to_block);
1387 pointer_to_this = &select_time_to_block; 1323 pointer_to_this = &select_time_to_block;
1388 } 1324 }
1389 1325
1390 active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this); 1326 active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
1391 1327
1392 if (active == 0) 1328 if (active == 0)
1393 { 1329 {
1394 assert (!badly_p);
1395 return; /* timeout */ 1330 return; /* timeout */
1396 } 1331 }
1397 else if (active > 0) 1332 else if (active > 0)
1398 { 1333 {
1399 if (FD_ISSET (windows_fd, &temp_mask)) 1334 if (FD_ISSET (windows_fd, &temp_mask))
1400 { 1335 {
1401 mswindows_drain_windows_queue (); 1336 mswindows_drain_windows_queue ();
1402 } 1337 }
1403 else 1338 #ifdef HAVE_TTY
1339 /* Look for a TTY event */
1340 for (i = 0; i < MAXDESC-1; i++)
1404 { 1341 {
1405 #ifdef HAVE_TTY 1342 /* To avoid race conditions (among other things, an infinite
1406 /* Look for a TTY event */ 1343 loop when called from Fdiscard_input()), we must return
1407 for (i = 0; i < MAXDESC-1; i++) 1344 user events ahead of process events. */
1345 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
1408 { 1346 {
1409 /* To avoid race conditions (among other things, an infinite 1347 struct console *c = tty_find_console_from_fd (i);
1410 loop when called from Fdiscard_input()), we must return 1348 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1411 user events ahead of process events. */ 1349 struct Lisp_Event* event = XEVENT (emacs_event);
1412 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) 1350
1351 assert (c);
1352 if (read_event_from_tty_or_stream_desc (event, c, i))
1413 { 1353 {
1414 struct console *c = tty_find_console_from_fd (i); 1354 mswindows_enqueue_dispatch_event (emacs_event);
1415 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 1355 return;
1416 Lisp_Event* event = XEVENT (emacs_event);
1417
1418 assert (c);
1419 if (read_event_from_tty_or_stream_desc (event, c, i))
1420 {
1421 mswindows_enqueue_dispatch_event (emacs_event);
1422 return;
1423 }
1424 } 1356 }
1425 } 1357 }
1426 #endif 1358 }
1427 /* Look for a process event */ 1359 #endif
1428 for (i = 0; i < MAXDESC-1; i++) 1360 /* Look for a process event */
1361 for (i = 0; i < MAXDESC-1; i++)
1362 {
1363 if (FD_ISSET (i, &temp_mask))
1429 { 1364 {
1430 if (FD_ISSET (i, &temp_mask)) 1365 if (FD_ISSET (i, &process_only_mask))
1431 { 1366 {
1432 if (FD_ISSET (i, &process_only_mask)) 1367 struct Lisp_Process *p =
1433 { 1368 get_process_from_usid (FD_TO_USID(i));
1434 Lisp_Process *p = 1369
1435 get_process_from_usid (FD_TO_USID(i)); 1370 mswindows_enqueue_process_event (p);
1436 1371 }
1437 mswindows_enqueue_process_event (p); 1372 else
1438 } 1373 {
1439 else 1374 /* We might get here when a fake event came
1440 { 1375 through a signal. Return a dummy event, so
1441 /* We might get here when a fake event came 1376 that a cycle of the command loop will
1442 through a signal. Return a dummy event, so 1377 occur. */
1443 that a cycle of the command loop will 1378 drain_signal_event_pipe ();
1444 occur. */ 1379 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1445 drain_signal_event_pipe ();
1446 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1447 }
1448 } 1380 }
1449 } 1381 }
1450 } 1382 }
1451 } 1383 }
1452 else if (active==-1) 1384 else if (active==-1)
1461 { 1393 {
1462 assert(0); 1394 assert(0);
1463 } 1395 }
1464 #else 1396 #else
1465 /* Now try getting a message or process event */ 1397 /* Now try getting a message or process event */
1466 active = MsgWaitForMultipleObjects (mswindows_waitable_count, 1398 active = MsgWaitForMultipleObjects (mswindows_waitable_count,
1467 mswindows_waitable_handles, 1399 mswindows_waitable_handles,
1468 FALSE, badly_p ? INFINITE : 0, 1400 FALSE, badly_p ? INFINITE : 0,
1469 QS_ALLINPUT); 1401 QS_ALLINPUT);
1470 1402
1471 /* This will assert if handle being waited for becomes abandoned. 1403 /* This will assert if handle being waited for becomes abandoned.
1472 Not the case currently tho */ 1404 Not the case currently tho */
1473 assert ((!badly_p && active == WAIT_TIMEOUT) || 1405 assert ((!badly_p && active == WAIT_TIMEOUT) ||
1474 (active >= WAIT_OBJECT_0 && 1406 (active >= WAIT_OBJECT_0 &&
1475 active <= WAIT_OBJECT_0 + mswindows_waitable_count)); 1407 active <= WAIT_OBJECT_0 + mswindows_waitable_count));
1476 1408
1477 if (active == WAIT_TIMEOUT) 1409 if (active == WAIT_TIMEOUT)
1478 { 1410 {
1479 /* No luck trying - just return what we've already got */ 1411 /* No luck trying - just return what we've already got */
1480 return; 1412 return;
1481 } 1413 }
1482 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count) 1414 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count)
1483 { 1415 {
1484 /* Got your message, thanks */ 1416 /* Got your message, thanks */
1485 mswindows_drain_windows_queue (); 1417 mswindows_drain_windows_queue ();
1486 } 1418 }
1487 else 1419 else
1488 { 1420 {
1489 int ix = active - WAIT_OBJECT_0; 1421 int ix = active - WAIT_OBJECT_0;
1490 /* First, try to find which process' output has signaled */ 1422 /* First, try to find which process' output has signaled */
1491 Lisp_Process *p = 1423 struct Lisp_Process *p =
1492 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix])); 1424 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix]));
1493 if (p != NULL) 1425 if (p != NULL)
1494 { 1426 {
1495 /* Found a signaled process input handle */ 1427 /* Found a signaled process input handle */
1496 mswindows_enqueue_process_event (p); 1428 mswindows_enqueue_process_event (p);
1497 } 1429 }
1498 else 1430 else
1499 { 1431 {
1500 /* None. This means that the process handle itself has signaled. 1432 /* None. This means that the process handle itself has signaled.
1501 Remove the handle from the wait vector, and make status_notify 1433 Remove the handle from the wait vector, and make status_notify
1502 note the exited process */ 1434 note the exited process */
1503 mswindows_waitable_handles [ix] = 1435 mswindows_waitable_handles [ix] =
1504 mswindows_waitable_handles [--mswindows_waitable_count]; 1436 mswindows_waitable_handles [--mswindows_waitable_count];
1505 kick_status_notify (); 1437 kick_status_notify ();
1506 /* We need to return a process event here so that 1438 /* Have to return something: there may be no accompanying
1507 (1) accept-process-output will return when called on this 1439 process event */
1508 process, and (2) status notifications will happen in 1440 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1509 accept-process-output, sleep-for, and sit-for. */ 1441 }
1510 /* #### horrible kludge till my real process fixes go in. 1442 }
1511 */ 1443 #endif
1512 if (!NILP (Vprocess_list)) 1444 } /* while */
1513 {
1514 Lisp_Object vaffanculo = XCAR (Vprocess_list);
1515 mswindows_enqueue_process_event (XPROCESS (vaffanculo));
1516 }
1517 else /* trash me soon. */
1518 /* Have to return something: there may be no accompanying
1519 process event */
1520 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
1521 }
1522 }
1523 #endif
1524 } /* while */
1525 } 1445 }
1526 1446
1527 /************************************************************************/ 1447 /************************************************************************/
1528 /* Event generators */ 1448 /* Event generators */
1529 /************************************************************************/ 1449 /************************************************************************/
1530 1450
1531 /* 1451 /*
1532 * Callback procedure for synchronous timer messages 1452 * Callback procedure for synchronous timer messages
1533 */ 1453 */
1534 static void CALLBACK 1454 static void CALLBACK
1535 mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime) 1455 mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
1536 { 1456 {
1537 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 1457 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1538 Lisp_Event *event = XEVENT (emacs_event); 1458 struct Lisp_Event *event = XEVENT (emacs_event);
1539 1459
1540 if (KillTimer (NULL, id_timer)) 1460 if (KillTimer (NULL, id_timer))
1541 --mswindows_pending_timers_count; 1461 --mswindows_pending_timers_count;
1542 1462
1543 event->channel = Qnil; 1463 event->channel = Qnil;
1548 event->event.timeout.object = Qnil; 1468 event->event.timeout.object = Qnil;
1549 1469
1550 mswindows_enqueue_dispatch_event (emacs_event); 1470 mswindows_enqueue_dispatch_event (emacs_event);
1551 } 1471 }
1552 1472
1553 /* 1473 /*
1554 * Callback procedure for dde messages 1474 * Callback procedure for dde messages
1555 * 1475 *
1556 * We execute a dde Open("file") by simulating a file drop, so dde support 1476 * We execute a dde Open("file") by simulating a file drop, so dde support
1557 * depends on dnd support. 1477 * depends on dnd support.
1558 */ 1478 */
1559 #ifdef HAVE_DRAGNDROP 1479 #ifdef HAVE_DRAGNDROP
1560 HDDEDATA CALLBACK 1480 HDDEDATA CALLBACK
1561 mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv, 1481 mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
1562 HSZ hszTopic, HSZ hszItem, HDDEDATA hdata, 1482 HSZ hszTopic, HSZ hszItem, HDDEDATA hdata,
1563 DWORD dwData1, DWORD dwData2) 1483 DWORD dwData1, DWORD dwData2)
1564 { 1484 {
1565 switch (uType) 1485 switch (uType)
1566 { 1486 {
1567 case XTYP_CONNECT: 1487 case XTYP_CONNECT:
1568 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)) 1488 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))
1569 return (HDDEDATA)TRUE; 1489 return (HDDEDATA)TRUE;
1570 return (HDDEDATA)FALSE; 1490 return (HDDEDATA)FALSE;
1571 1491
1574 /* We only support one {service,topic} pair */ 1494 /* We only support one {service,topic} pair */
1575 HSZPAIR pairs[2] = { 1495 HSZPAIR pairs[2] = {
1576 { mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } }; 1496 { mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } };
1577 1497
1578 if (!(hszItem || DdeCmpStringHandles (hszItem, mswindows_dde_service)) && 1498 if (!(hszItem || DdeCmpStringHandles (hszItem, mswindows_dde_service)) &&
1579 !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))) 1499 !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)));
1580 return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs, 1500 return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs,
1581 sizeof (pairs), 0L, 0, uFmt, 0)); 1501 sizeof (pairs), 0L, 0, uFmt, 0));
1582 } 1502 }
1583 return (HDDEDATA)NULL; 1503 return (HDDEDATA)NULL;
1584 1504
1585 case XTYP_EXECUTE: 1505 case XTYP_EXECUTE:
1586 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)) 1506 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))
1587 { 1507 {
1588 DWORD len = DdeGetData (hdata, NULL, 0, 0); 1508 DWORD len = DdeGetData (hdata, NULL, 0, 0);
1589 LPBYTE cmd = (LPBYTE) alloca (len+1); 1509 char *cmd = alloca (len+1);
1590 char *end; 1510 char *end;
1591 char *filename; 1511 char *filename;
1592 struct gcpro gcpro1, gcpro2; 1512 struct gcpro gcpro1, gcpro2;
1593 Lisp_Object l_dndlist = Qnil; 1513 Lisp_Object l_dndlist = Qnil;
1594 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 1514 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1595 Lisp_Object frmcons, devcons, concons; 1515 Lisp_Object frmcons, devcons, concons;
1596 Lisp_Event *event = XEVENT (emacs_event); 1516 struct Lisp_Event *event = XEVENT (emacs_event);
1597 1517
1598 DdeGetData (hdata, cmd, len, 0); 1518 DdeGetData (hdata, cmd, len, 0);
1599 cmd[len] = '\0'; 1519 cmd[len] = '\0';
1600 DdeFreeDataHandle (hdata); 1520 DdeFreeDataHandle (hdata);
1601 1521
1623 if (*(++end)==']') 1543 if (*(++end)==']')
1624 end++; 1544 end++;
1625 if (*end) 1545 if (*end)
1626 return DDE_FNOTPROCESSED; 1546 return DDE_FNOTPROCESSED;
1627 1547
1628 #ifdef CYGWIN 1548 #ifdef __CYGWIN32__
1629 filename = alloca (cygwin32_win32_to_posix_path_list_buf_size (cmd) + 5); 1549 filename = alloca (cygwin32_win32_to_posix_path_list_buf_size (cmd) + 5);
1630 strcpy (filename, "file:"); 1550 strcpy (filename, "file:");
1631 cygwin32_win32_to_posix_path_list (cmd, filename+5); 1551 cygwin32_win32_to_posix_path_list (cmd, filename+5);
1632 #else 1552 #else
1633 dostounix_filename (cmd); 1553 dostounix_filename (cmd);
1659 Fcons (l_dndlist, Qnil)); 1579 Fcons (l_dndlist, Qnil));
1660 mswindows_enqueue_dispatch_event (emacs_event); 1580 mswindows_enqueue_dispatch_event (emacs_event);
1661 UNGCPRO; 1581 UNGCPRO;
1662 return (HDDEDATA) DDE_FACK; 1582 return (HDDEDATA) DDE_FACK;
1663 } 1583 }
1664 DdeFreeDataHandle (hdata); 1584 DdeFreeDataHandle (hdata);
1665 return (HDDEDATA) DDE_FNOTPROCESSED; 1585 return (HDDEDATA) DDE_FNOTPROCESSED;
1666 1586
1667 default: 1587 default:
1668 return (HDDEDATA) NULL; 1588 return (HDDEDATA) NULL;
1669 } 1589 }
1670 } 1590 }
1671 #endif 1591 #endif
1672
1673 /*
1674 * Helper to do repainting - repaints can happen both from the windows
1675 * procedure and from magic events
1676 */
1677 static void
1678 mswindows_handle_paint (struct frame *frame)
1679 {
1680 HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame);
1681
1682 /* According to the docs we need to check GetUpdateRect() before
1683 actually doing a WM_PAINT */
1684 if (GetUpdateRect (hwnd, NULL, FALSE))
1685 {
1686 PAINTSTRUCT paintStruct;
1687 int x, y, width, height;
1688
1689 BeginPaint (hwnd, &paintStruct);
1690 x = paintStruct.rcPaint.left;
1691 y = paintStruct.rcPaint.top;
1692 width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
1693 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
1694 /* Normally we want to ignore expose events when child
1695 windows are unmapped, however once we are in the guts of
1696 WM_PAINT we need to make sure that we don't register
1697 unmaps then because they will not actually occur. */
1698 /* #### commenting out the next line seems to fix some problems
1699 but not all. only andy currently understands this stuff and
1700 he needs to review it more carefully. --ben */
1701 if (!check_for_ignored_expose (frame, x, y, width, height))
1702 {
1703 hold_ignored_expose_registration = 1;
1704 mswindows_redraw_exposed_area (frame, x, y, width, height);
1705 hold_ignored_expose_registration = 0;
1706 }
1707 EndPaint (hwnd, &paintStruct);
1708 }
1709 }
1710
1711 /*
1712 * Returns 1 if a key is a real modifier or special key, which
1713 * is better handled by DefWindowProc
1714 */
1715 static int
1716 key_needs_default_processing_p (UINT vkey)
1717 {
1718 if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU
1719 /* if we let ALT activate the menu like this, then sticky ALT-modified
1720 keystrokes become impossible. */
1721 && !modifier_keys_are_sticky)
1722 return 1;
1723
1724 return 0;
1725 }
1726
1727 /* key-handling code is always ugly. It just ends up working out
1728 that way.
1729
1730 #### Most of the sticky-modifier code below is copied from similar
1731 code in event-Xt.c. They should somehow or other be merged.
1732
1733 Here are some pointers:
1734
1735 -- DOWN_MASK indicates which modifiers should be treated as "down"
1736 when the corresponding upstroke happens. It gets reset for
1737 a particular modifier when that modifier goes up, and reset
1738 for all modifiers when a non-modifier key is pressed. Example:
1739
1740 I press Control-A-Shift and then release Control-A-Shift.
1741 I want the Shift key to be sticky but not the Control key.
1742
1743 -- If a modifier key is sticky, I can unstick it by pressing
1744 the modifier key again. */
1745
1746 static WPARAM last_downkey;
1747 static int need_to_add_mask, down_mask;
1748
1749 #define XEMSW_LCONTROL (1<<0)
1750 #define XEMSW_RCONTROL (1<<1)
1751 #define XEMSW_LSHIFT (1<<2)
1752 #define XEMSW_RSHIFT (1<<3)
1753 #define XEMSW_LMENU (1<<4)
1754 #define XEMSW_RMENU (1<<5)
1755
1756 static int
1757 mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
1758 int downp, int keyp)
1759 {
1760 int mods = 0;
1761
1762 if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
1763 return 0;
1764
1765 if (! (keyp &&
1766 (wParam == VK_CONTROL || wParam == VK_LCONTROL ||
1767 wParam == VK_RCONTROL ||
1768 wParam == VK_MENU || wParam == VK_LMENU ||
1769 wParam == VK_RMENU ||
1770 wParam == VK_SHIFT || wParam == VK_LSHIFT ||
1771 wParam == VK_RSHIFT)))
1772 { /* Not a modifier key */
1773 if (downp && keyp && !last_downkey)
1774 last_downkey = wParam;
1775 /* If I hold press-and-release the Control key and then press
1776 and hold down the right arrow, I want it to auto-repeat
1777 Control-Right. On the other hand, if I do the same but
1778 manually press the Right arrow a bunch of times, I want
1779 to see one Control-Right and then a bunch of Rights.
1780 This means that we need to distinguish between an
1781 auto-repeated key and a key pressed and released a bunch
1782 of times. */
1783 else if ((downp && !keyp) ||
1784 (downp && keyp && last_downkey &&
1785 (wParam != last_downkey ||
1786 /* the "previous key state" bit indicates autorepeat */
1787 ! (lParam & (1 << 30)))))
1788 {
1789 need_to_add_mask = 0;
1790 last_downkey = 0;
1791 }
1792 if (downp)
1793 down_mask = 0;
1794
1795 mods = need_to_add_mask;
1796 }
1797 else /* Modifier key pressed */
1798 {
1799 /* If a non-modifier key was pressed in the middle of a bunch
1800 of modifiers, then it unsticks all the modifiers that were
1801 previously pressed. We cannot unstick the modifiers until
1802 now because we want to check for auto-repeat of the
1803 non-modifier key. */
1804
1805 if (last_downkey)
1806 {
1807 last_downkey = 0;
1808 need_to_add_mask = 0;
1809 }
1810
1811 #define FROB(mask) \
1812 do { \
1813 if (downp && keyp) \
1814 { \
1815 /* If modifier key is already sticky, \
1816 then unstick it. Note that we do \
1817 not test down_mask to deal with the \
1818 unlikely but possible case that the \
1819 modifier key auto-repeats. */ \
1820 if (need_to_add_mask & mask) \
1821 { \
1822 need_to_add_mask &= ~mask; \
1823 down_mask &= ~mask; \
1824 } \
1825 else \
1826 down_mask |= mask; \
1827 } \
1828 else \
1829 { \
1830 if (down_mask & mask) \
1831 { \
1832 down_mask &= ~mask; \
1833 need_to_add_mask |= mask; \
1834 } \
1835 } \
1836 } while (0)
1837
1838 if ((wParam == VK_CONTROL && (lParam & 0x1000000))
1839 || wParam == VK_RCONTROL)
1840 FROB (XEMSW_RCONTROL);
1841 if ((wParam == VK_CONTROL && !(lParam & 0x1000000))
1842 || wParam == VK_LCONTROL)
1843 FROB (XEMSW_LCONTROL);
1844
1845 if ((wParam == VK_SHIFT && (lParam & 0x1000000))
1846 || wParam == VK_RSHIFT)
1847 FROB (XEMSW_RSHIFT);
1848 if ((wParam == VK_SHIFT && !(lParam & 0x1000000))
1849 || wParam == VK_LSHIFT)
1850 FROB (XEMSW_LSHIFT);
1851
1852 if ((wParam == VK_MENU && (lParam & 0x1000000))
1853 || wParam == VK_RMENU)
1854 FROB (XEMSW_RMENU);
1855 if ((wParam == VK_MENU && !(lParam & 0x1000000))
1856 || wParam == VK_LMENU)
1857 FROB (XEMSW_LMENU);
1858 }
1859 #undef FROB
1860
1861 if (mods && downp)
1862 {
1863 BYTE keymap[256];
1864
1865 GetKeyboardState (keymap);
1866
1867 if (mods & XEMSW_LCONTROL)
1868 {
1869 keymap [VK_CONTROL] |= 0x80;
1870 keymap [VK_LCONTROL] |= 0x80;
1871 }
1872 if (mods & XEMSW_RCONTROL)
1873 {
1874 keymap [VK_CONTROL] |= 0x80;
1875 keymap [VK_RCONTROL] |= 0x80;
1876 }
1877
1878 if (mods & XEMSW_LSHIFT)
1879 {
1880 keymap [VK_SHIFT] |= 0x80;
1881 keymap [VK_LSHIFT] |= 0x80;
1882 }
1883 if (mods & XEMSW_RSHIFT)
1884 {
1885 keymap [VK_SHIFT] |= 0x80;
1886 keymap [VK_RSHIFT] |= 0x80;
1887 }
1888
1889 if (mods & XEMSW_LMENU)
1890 {
1891 keymap [VK_MENU] |= 0x80;
1892 keymap [VK_LMENU] |= 0x80;
1893 }
1894 if (mods & XEMSW_RMENU)
1895 {
1896 keymap [VK_MENU] |= 0x80;
1897 keymap [VK_RMENU] |= 0x80;
1898 }
1899
1900 SetKeyboardState (keymap);
1901 return 1;
1902 }
1903
1904 return 0;
1905 }
1906
1907 static void
1908 clear_sticky_modifiers (void)
1909 {
1910 need_to_add_mask = 0;
1911 last_downkey = 0;
1912 down_mask = 0;
1913 }
1914
1915 #ifdef DEBUG_XEMACS
1916
1917 #if 0
1918
1919 static void
1920 output_modifier_keyboard_state (void)
1921 {
1922 BYTE keymap[256];
1923
1924 GetKeyboardState (keymap);
1925
1926 stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1927 keymap[VK_MENU] & 0x80 ? 1 : 0,
1928 keymap[VK_MENU] & 0x1 ? 1 : 0,
1929 keymap[VK_LMENU] & 0x80 ? 1 : 0,
1930 keymap[VK_LMENU] & 0x1 ? 1 : 0,
1931 keymap[VK_RMENU] & 0x80 ? 1 : 0,
1932 keymap[VK_RMENU] & 0x1 ? 1 : 0);
1933 stderr_out ("GetKeyboardState VK_CONTROL %d %d VK_LCONTROL %d %d VK_RCONTROL %d %d\n",
1934 keymap[VK_CONTROL] & 0x80 ? 1 : 0,
1935 keymap[VK_CONTROL] & 0x1 ? 1 : 0,
1936 keymap[VK_LCONTROL] & 0x80 ? 1 : 0,
1937 keymap[VK_LCONTROL] & 0x1 ? 1 : 0,
1938 keymap[VK_RCONTROL] & 0x80 ? 1 : 0,
1939 keymap[VK_RCONTROL] & 0x1 ? 1 : 0);
1940 stderr_out ("GetKeyboardState VK_SHIFT %d %d VK_LSHIFT %d %d VK_RSHIFT %d %d\n",
1941 keymap[VK_SHIFT] & 0x80 ? 1 : 0,
1942 keymap[VK_SHIFT] & 0x1 ? 1 : 0,
1943 keymap[VK_LSHIFT] & 0x80 ? 1 : 0,
1944 keymap[VK_LSHIFT] & 0x1 ? 1 : 0,
1945 keymap[VK_RSHIFT] & 0x80 ? 1 : 0,
1946 keymap[VK_RSHIFT] & 0x1 ? 1 : 0);
1947 }
1948
1949 #endif
1950
1951 /* try to debug the stuck-alt-key problem.
1952
1953 #### this happens only inconsistently, and may only happen when using
1954 StickyKeys in the Win2000 accessibility section of the control panel,
1955 which is extremely broken for other reasons. */
1956
1957 static void
1958 output_alt_keyboard_state (void)
1959 {
1960 BYTE keymap[256];
1961 SHORT keystate[3];
1962 // SHORT asyncstate[3];
1963
1964 GetKeyboardState (keymap);
1965 keystate[0] = GetKeyState (VK_MENU);
1966 keystate[1] = GetKeyState (VK_LMENU);
1967 keystate[2] = GetKeyState (VK_RMENU);
1968 /* Doing this interferes with key processing. */
1969 /* asyncstate[0] = GetAsyncKeyState (VK_MENU); */
1970 /* asyncstate[1] = GetAsyncKeyState (VK_LMENU); */
1971 /* asyncstate[2] = GetAsyncKeyState (VK_RMENU); */
1972
1973 stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1974 keymap[VK_MENU] & 0x80 ? 1 : 0,
1975 keymap[VK_MENU] & 0x1 ? 1 : 0,
1976 keymap[VK_LMENU] & 0x80 ? 1 : 0,
1977 keymap[VK_LMENU] & 0x1 ? 1 : 0,
1978 keymap[VK_RMENU] & 0x80 ? 1 : 0,
1979 keymap[VK_RMENU] & 0x1 ? 1 : 0);
1980 stderr_out ("GetKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1981 keystate[0] & 0x8000 ? 1 : 0,
1982 keystate[0] & 0x1 ? 1 : 0,
1983 keystate[1] & 0x8000 ? 1 : 0,
1984 keystate[1] & 0x1 ? 1 : 0,
1985 keystate[2] & 0x8000 ? 1 : 0,
1986 keystate[2] & 0x1 ? 1 : 0);
1987 /* stderr_out ("GetAsyncKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n", */
1988 /* asyncstate[0] & 0x8000 ? 1 : 0, */
1989 /* asyncstate[0] & 0x1 ? 1 : 0, */
1990 /* asyncstate[1] & 0x8000 ? 1 : 0, */
1991 /* asyncstate[1] & 0x1 ? 1 : 0, */
1992 /* asyncstate[2] & 0x8000 ? 1 : 0, */
1993 /* asyncstate[2] & 0x1 ? 1 : 0); */
1994 }
1995
1996 #endif /* DEBUG_XEMACS */
1997
1998 1592
1999 /* 1593 /*
2000 * The windows procedure for the window class XEMACS_CLASS 1594 * The windows procedure for the window class XEMACS_CLASS
2001 */ 1595 */
2002 LRESULT WINAPI 1596 LRESULT WINAPI
2003 mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam) 1597 mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2004 { 1598 {
2005 /* Note: Remember to initialize emacs_event and event before use. 1599 /* Note: Remember to initialize emacs_event and event before use.
2006 This code calls code that can GC. You must GCPRO before calling such code. */ 1600 This code calls code that can GC. You must GCPRO before calling such code. */
2007 Lisp_Object emacs_event = Qnil; 1601 Lisp_Object emacs_event = Qnil;
2008 Lisp_Object fobj = Qnil; 1602 Lisp_Object fobj = Qnil;
2009 1603
2010 Lisp_Event *event; 1604 struct Lisp_Event *event;
2011 struct frame *frame; 1605 struct frame *frame;
2012 struct mswindows_frame* msframe; 1606 struct mswindows_frame* msframe;
2013 1607
2014 assert (!GetWindowLong (hwnd, GWL_USERDATA)); 1608 switch (message)
2015 switch (message_) 1609 {
2016 { 1610 case WM_ERASEBKGND:
2017 case WM_DESTROYCLIPBOARD: 1611 /* Erase background only during non-dynamic sizing */
2018 /* We own the clipboard and someone else wants it. Delete our 1612 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2019 cached copy of the clipboard contents so we'll ask for it from 1613 if (msframe->sizing && !mswindows_dynamic_frame_resize)
2020 Windows again when someone does a paste, and destroy any memory 1614 goto defproc;
2021 objects we hold on the clipboard that are not in the list of types 1615 return 1;
2022 that Windows will delete itself. */ 1616
2023 mswindows_destroy_selection (QCLIPBOARD); 1617 case WM_CLOSE:
2024 handle_selection_clear (QCLIPBOARD); 1618 fobj = mswindows_find_frame (hwnd);
2025 break; 1619 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt));
2026 1620 break;
2027 case WM_ERASEBKGND: 1621
2028 /* Erase background only during non-dynamic sizing */ 1622 case WM_KEYUP:
2029 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); 1623 case WM_SYSKEYUP:
2030 if (msframe->sizing && !mswindows_dynamic_frame_resize) 1624 /* See Win95 comment under WM_KEYDOWN */
2031 goto defproc; 1625 {
2032 return 1; 1626 BYTE keymap[256];
2033 1627
2034 case WM_CLOSE: 1628 if (wParam == VK_CONTROL)
2035 fobj = mswindows_find_frame (hwnd); 1629 {
2036 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt)); 1630 GetKeyboardState (keymap);
2037 break; 1631 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80;
2038 1632 SetKeyboardState (keymap);
2039 case WM_KEYUP: 1633 }
2040 case WM_SYSKEYUP: 1634 else if (wParam == VK_MENU)
2041 1635 {
2042 /* See Win95 comment under WM_KEYDOWN */ 1636 GetKeyboardState (keymap);
1637 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80;
1638 SetKeyboardState (keymap);
1639 }
1640 };
1641 goto defproc;
1642
1643 case WM_KEYDOWN:
1644 case WM_SYSKEYDOWN:
1645 /* In some locales the right-hand Alt key is labelled AltGr. This key
1646 * should produce alternative charcaters when combined with another key.
1647 * eg on a German keyboard pressing AltGr+q should produce '@'.
1648 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if
1649 * TranslateMessage() is called with *any* combination of Ctrl+Alt down,
1650 * it translates as if AltGr were down.
1651 * We get round this by removing all modifiers from the keymap before
1652 * calling TranslateMessage() unless AltGr is *really* down. */
1653 {
1654 BYTE keymap[256];
1655 int has_AltGr = mswindows_current_layout_has_AltGr ();
1656 int mods;
1657 Lisp_Object keysym;
1658
1659 GetKeyboardState (keymap);
1660 mods = mswindows_modifier_state (keymap, has_AltGr);
1661
1662 /* Handle those keys for which TranslateMessage won't generate a WM_CHAR */
1663 if (!NILP (keysym = mswindows_key_to_emacs_keysym(wParam, mods)))
1664 mswindows_enqueue_keypress_event (hwnd, keysym, mods);
1665 else
1666 {
1667 int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
1668 BYTE keymap_orig[256];
1669 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
1670 MSG msg;
1671
1672 msg.hwnd = hwnd;
1673 msg.message = message;
1674 msg.wParam = wParam;
1675 msg.lParam = lParam;
1676 msg.time = GetMessageTime();
1677 msg.pt = pnt;
1678
1679 /* GetKeyboardState() does not work as documented on Win95. We have
1680 * to loosely track Left and Right modifiers on behalf of the OS,
1681 * without screwing up Windows NT which tracks them properly. */
1682 if (wParam == VK_CONTROL)
1683 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
1684 else if (wParam == VK_MENU)
1685 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] |= 0x80;
1686
1687 memcpy (keymap_orig, keymap, 256);
1688
1689 /* Remove shift modifier from an ascii character */
1690 mods &= ~MOD_SHIFT;
1691
1692 /* Clear control and alt modifiers unless AltGr is pressed */
1693 keymap [VK_RCONTROL] = 0;
1694 keymap [VK_LMENU] = 0;
1695 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) || !(keymap [VK_RMENU] & 0x80))
1696 {
1697 keymap [VK_LCONTROL] = 0;
1698 keymap [VK_CONTROL] = 0;
1699 keymap [VK_RMENU] = 0;
1700 keymap [VK_MENU] = 0;
1701 }
1702 SetKeyboardState (keymap);
1703
1704 /* Maybe generate some WM_[SYS]CHARs in the queue */
1705 TranslateMessage (&msg);
1706
1707 while (PeekMessage (&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)
1708 || PeekMessage (&msg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE))
1709 {
1710 int mods1 = mods;
1711 WPARAM ch = msg.wParam;
1712
1713 /* If a quit char with no modifiers other than control and
1714 shift, then mark it with a fake modifier, which is removed
1715 upon dequeueing the event */
1716 /* #### This might also not withstand localization, if
1717 quit character is not a latin-1 symbol */
1718 if (((quit_ch < ' ' && (mods & MOD_CONTROL) && quit_ch + 'a' - 1 == ch)
1719 || (quit_ch >= ' ' && !(mods & MOD_CONTROL) && quit_ch == ch))
1720 && ((mods & ~(MOD_CONTROL | MOD_SHIFT)) == 0))
1721 {
1722 mods1 |= FAKE_MOD_QUIT;
1723 ++mswindows_quit_chars_count;
1724 }
1725
1726 mswindows_enqueue_keypress_event (hwnd, make_char(ch), mods1);
1727 } /* while */
1728 SetKeyboardState (keymap_orig);
1729 } /* else */
1730 }
1731 /* F10 causes menu activation by default. We do not want this */
1732 if (wParam != VK_F10)
1733 goto defproc;
1734 break;
1735
1736 case WM_MBUTTONDOWN:
1737 case WM_MBUTTONUP:
1738 /* Real middle mouse button has nothing to do with emulated one:
1739 if one wants to exercise fingers playing chords on the mouse,
1740 he is allowed to do that! */
1741 mswindows_enqueue_mouse_button_event (hwnd, message,
1742 MAKEPOINTS (lParam), GetMessageTime());
1743 break;
1744
1745 case WM_LBUTTONUP:
1746 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1747 msframe->last_click_time = GetMessageTime();
1748
1749 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1750 msframe->button2_need_lbutton = 0;
1751 if (msframe->ignore_next_lbutton_up)
2043 { 1752 {
2044 BYTE keymap[256]; 1753 msframe->ignore_next_lbutton_up = 0;
2045 int should_set_keymap = 0; 1754 }
2046 1755 else if (msframe->button2_is_down)
2047 #ifdef DEBUG_XEMACS 1756 {
2048 if (mswindows_debug_events) 1757 msframe->button2_is_down = 0;
1758 msframe->ignore_next_rbutton_up = 1;
1759 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1760 MAKEPOINTS (lParam), GetMessageTime());
1761 }
1762 else
1763 {
1764 if (msframe->button2_need_rbutton)
2049 { 1765 {
2050 stderr_out ("%s wparam=%d lparam=%d\n", 1766 msframe->button2_need_rbutton = 0;
2051 message_ == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP", 1767 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
2052 wParam, (int)lParam); 1768 MAKEPOINTS (lParam), GetMessageTime());
2053 output_alt_keyboard_state (); 1769 }
2054 } 1770 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP,
2055 #endif /* DEBUG_XEMACS */ 1771 MAKEPOINTS (lParam), GetMessageTime());
2056 1772 }
2057 mswindows_handle_sticky_modifiers (wParam, lParam, 0, 1); 1773 break;
2058 if (wParam == VK_CONTROL) 1774
1775 case WM_RBUTTONUP:
1776 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1777 msframe->last_click_time = GetMessageTime();
1778
1779 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1780 msframe->button2_need_rbutton = 0;
1781 if (msframe->ignore_next_rbutton_up)
1782 {
1783 msframe->ignore_next_rbutton_up = 0;
1784 }
1785 else if (msframe->button2_is_down)
1786 {
1787 msframe->button2_is_down = 0;
1788 msframe->ignore_next_lbutton_up = 1;
1789 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
1790 MAKEPOINTS (lParam), GetMessageTime());
1791 }
1792 else
1793 {
1794 if (msframe->button2_need_lbutton)
2059 { 1795 {
2060 GetKeyboardState (keymap); 1796 msframe->button2_need_lbutton = 0;
2061 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80; 1797 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
2062 should_set_keymap = 1; 1798 MAKEPOINTS (lParam), GetMessageTime());
2063 } 1799 }
2064 else if (wParam == VK_MENU) 1800 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP,
1801 MAKEPOINTS (lParam), GetMessageTime());
1802 }
1803 break;
1804
1805 case WM_LBUTTONDOWN:
1806 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1807
1808 if (msframe->button2_need_lbutton)
1809 {
1810 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1811 msframe->button2_need_lbutton = 0;
1812 msframe->button2_need_rbutton = 0;
1813 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
2065 { 1814 {
2066 GetKeyboardState (keymap); 1815 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
2067 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80; 1816 MAKEPOINTS (lParam), GetMessageTime());
2068 should_set_keymap = 1; 1817 msframe->button2_is_down = 1;
2069 }
2070
2071 if (should_set_keymap)
2072 // && (message_ != WM_SYSKEYUP
2073 // || NILP (Vmenu_accelerator_enabled)))
2074 SetKeyboardState (keymap);
2075
2076 }
2077
2078 if (key_needs_default_processing_p (wParam))
2079 goto defproc;
2080 else
2081 break;
2082
2083 case WM_KEYDOWN:
2084 case WM_SYSKEYDOWN:
2085
2086 /* In some locales the right-hand Alt key is labelled AltGr. This key
2087 * should produce alternative charcaters when combined with another key.
2088 * eg on a German keyboard pressing AltGr+q should produce '@'.
2089 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if
2090 * TranslateMessage() is called with *any* combination of Ctrl+Alt down,
2091 * it translates as if AltGr were down.
2092 * We get round this by removing all modifiers from the keymap before
2093 * calling TranslateMessage() unless AltGr is *really* down. */
2094 {
2095 BYTE keymap_trans[256];
2096 BYTE keymap_orig[256];
2097 BYTE keymap_sticky[256];
2098 int has_AltGr = mswindows_current_layout_has_AltGr ();
2099 int mods = 0;
2100 int extendedp = lParam & 0x1000000;
2101 Lisp_Object keysym;
2102 int sticky_changed;
2103
2104 #ifdef DEBUG_XEMACS
2105 if (mswindows_debug_events)
2106 {
2107 stderr_out ("%s wparam=%d lparam=%d\n",
2108 message_ == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
2109 wParam, (int)lParam);
2110 output_alt_keyboard_state ();
2111 }
2112 #endif /* DEBUG_XEMACS */
2113
2114 GetKeyboardState (keymap_orig);
2115 frame = XFRAME (mswindows_find_frame (hwnd));
2116 if ((sticky_changed =
2117 mswindows_handle_sticky_modifiers (wParam, lParam, 1, 1)))
2118 {
2119 GetKeyboardState (keymap_sticky);
2120 if (keymap_sticky[VK_MENU] & 0x80)
2121 {
2122 message_ = WM_SYSKEYDOWN;
2123 /* We have to set the "context bit" so that the
2124 TranslateMessage() call below that generates the
2125 SYSCHAR message does its thing; see the documentation
2126 on WM_SYSKEYDOWN */
2127 lParam |= 1 << 29;
2128 }
2129 } 1818 }
2130 else 1819 else
2131 memcpy (keymap_sticky, keymap_orig, 256);
2132
2133 mods = mswindows_modifier_state (keymap_sticky, has_AltGr);
2134
2135 /* Handle non-printables */
2136 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
2137 extendedp)))
2138 { 1820 {
2139 mswindows_enqueue_keypress_event (hwnd, keysym, mods); 1821 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
2140 if (sticky_changed) 1822 msframe->last_click_point, msframe->last_click_time);
2141 SetKeyboardState (keymap_orig); 1823 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1824 MAKEPOINTS (lParam), GetMessageTime());
2142 } 1825 }
2143 else /* Normal keys & modifiers */ 1826 }
1827 else
1828 {
1829 mswindows_set_chord_timer (hwnd);
1830 msframe->button2_need_rbutton = 1;
1831 msframe->last_click_point = MAKEPOINTS (lParam);
1832 }
1833 msframe->last_click_time = GetMessageTime();
1834 break;
1835
1836 case WM_RBUTTONDOWN:
1837 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1838
1839 if (msframe->button2_need_rbutton)
1840 {
1841 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1842 msframe->button2_need_lbutton = 0;
1843 msframe->button2_need_rbutton = 0;
1844 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
2144 { 1845 {
2145 Emchar quit_ch = 1846 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
2146 CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); 1847 MAKEPOINTS (lParam), GetMessageTime());
2147 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; 1848 msframe->button2_is_down = 1;
2148 MSG msg, tranmsg; 1849 }
2149 int potential_accelerator = 0; 1850 else
2150 int got_accelerator = 0; 1851 {
1852 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1853 msframe->last_click_point, msframe->last_click_time);
1854 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1855 MAKEPOINTS (lParam), GetMessageTime());
1856 }
1857 }
1858 else
1859 {
1860 mswindows_set_chord_timer (hwnd);
1861 msframe->button2_need_lbutton = 1;
1862 msframe->last_click_point = MAKEPOINTS (lParam);
1863 }
1864 msframe->last_click_time = GetMessageTime();
1865 break;
1866
1867 case WM_TIMER:
1868 if (wParam == BUTTON_2_TIMER_ID)
1869 {
1870 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1871 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1872
1873 if (msframe->button2_need_lbutton)
1874 {
1875 msframe->button2_need_lbutton = 0;
1876 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
1877 msframe->last_click_point, msframe->last_click_time);
1878 }
1879 else if (msframe->button2_need_rbutton)
1880 {
1881 msframe->button2_need_rbutton = 0;
1882 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
1883 msframe->last_click_point, msframe->last_click_time);
1884 }
1885 }
1886 else
1887 assert ("Spurious timer fired" == 0);
1888 break;
1889
1890 case WM_MOUSEMOVE:
1891 /* Optimization: don't report mouse movement while size is changing */
1892 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
1893 if (!msframe->sizing)
1894 {
1895 /* When waiting for the second mouse button to finish
1896 button2 emulation, and have moved too far, just pretend
1897 as if timer has expired. This improves drag-select feedback */
1898 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton)
1899 && !mswindows_button2_near_enough (msframe->last_click_point,
1900 MAKEPOINTS (lParam)))
1901 {
1902 KillTimer (hwnd, BUTTON_2_TIMER_ID);
1903 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0);
1904 }
1905
1906 emacs_event = Fmake_event (Qnil, Qnil);
1907 event = XEVENT(emacs_event);
1908
1909 event->channel = mswindows_find_frame(hwnd);
1910 event->timestamp = GetMessageTime();
1911 event->event_type = pointer_motion_event;
1912 event->event.motion.x = MAKEPOINTS(lParam).x;
1913 event->event.motion.y = MAKEPOINTS(lParam).y;
1914 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0);
1915
1916 mswindows_enqueue_dispatch_event (emacs_event);
1917 }
1918 break;
1919
1920 case WM_CANCELMODE:
1921 ReleaseCapture ();
1922 /* Queue a `cancel-mode-internal' misc user event, so mouse
1923 selection would be canceled if any */
1924 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd),
1925 Qcancel_mode_internal, Qnil);
1926 break;
1927
1928 #ifdef HAVE_TOOLBARS
1929 case WM_NOTIFY:
1930 {
1931 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
1932 Lisp_Object btext;
1933 if (tttext->hdr.code == TTN_NEEDTEXT)
1934 {
1935 /* find out which toolbar */
1936 frame = XFRAME (mswindows_find_frame (hwnd));
1937 btext = mswindows_get_toolbar_button_text ( frame,
1938 tttext->hdr.idFrom );
2151 1939
2152 msg.hwnd = hwnd; 1940 tttext->lpszText = NULL;
2153 msg.message = message_; 1941 tttext->hinst = NULL;
2154 msg.wParam = wParam; 1942
2155 msg.lParam = lParam; 1943 if (!NILP(btext))
2156 msg.time = GetMessageTime(); 1944 {
2157 msg.pt = pnt; 1945 /* I think this is safe since the text will only go away
2158 1946 when the toolbar does...*/
2159 /* GetKeyboardState() does not work as documented on Win95. We have 1947 GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS,
2160 * to loosely track Left and Right modifiers on behalf of the OS, 1948 tttext->lpszText);
2161 * without screwing up Windows NT which tracks them properly. */ 1949 }
2162 if (wParam == VK_CONTROL) 1950 #if 0
2163 { 1951 tttext->uFlags |= TTF_DI_SETITEM;
2164 keymap_orig[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; 1952 #endif
2165 keymap_sticky[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; 1953 }
2166 } 1954 }
2167 else if (wParam == VK_MENU) 1955 break;
2168 { 1956 #endif
2169 keymap_orig[extendedp ? VK_RMENU : VK_LMENU] |= 0x80; 1957
2170 keymap_sticky[extendedp ? VK_RMENU : VK_LMENU] |= 0x80; 1958 case WM_PAINT:
2171 } 1959 {
2172 1960 PAINTSTRUCT paintStruct;
2173 if (!NILP (Vmenu_accelerator_enabled) && 1961
2174 !(mods & XEMACS_MOD_SHIFT) && message_ == WM_SYSKEYDOWN) 1962 frame = XFRAME (mswindows_find_frame (hwnd));
2175 potential_accelerator = 1; 1963
2176 1964 BeginPaint (hwnd, &paintStruct);
2177 /* Remove shift modifier from an ascii character */ 1965 mswindows_redraw_exposed_area (frame,
2178 mods &= ~XEMACS_MOD_SHIFT; 1966 paintStruct.rcPaint.left, paintStruct.rcPaint.top,
2179 1967 paintStruct.rcPaint.right, paintStruct.rcPaint.bottom);
2180 memcpy (keymap_trans, keymap_sticky, 256); 1968 EndPaint (hwnd, &paintStruct);
2181 1969 }
2182 /* Clear control and alt modifiers unless AltGr is pressed */ 1970 break;
2183 keymap_trans[VK_RCONTROL] = 0; 1971
2184 keymap_trans[VK_LMENU] = 0; 1972 case WM_SIZE:
2185 if (!has_AltGr || !(keymap_trans[VK_LCONTROL] & 0x80) 1973 /* We only care about this message if our size has really changed */
2186 || !(keymap_trans[VK_RMENU] & 0x80)) 1974 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED)
2187 { 1975 {
2188 keymap_trans[VK_LCONTROL] = 0; 1976 RECT rect;
2189 keymap_trans[VK_CONTROL] = 0; 1977 int columns, rows;
2190 keymap_trans[VK_RMENU] = 0; 1978
2191 keymap_trans[VK_MENU] = 0; 1979 fobj = mswindows_find_frame (hwnd);
2192 } 1980 frame = XFRAME (fobj);
2193 SetKeyboardState (keymap_trans); 1981 msframe = FRAME_MSWINDOWS_DATA (frame);
2194 1982
2195 /* Maybe generate some WM_[SYS]CHARs in the queue */ 1983 /* We cannot handle frame map and unmap hooks right in
2196 TranslateMessage (&msg); 1984 this routine, because these may throw. We queue
2197 1985 magic events to run these hooks instead - kkm */
2198 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) 1986
2199 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, 1987 if (wParam==SIZE_MINIMIZED)
2200 PM_REMOVE))
2201 {
2202 int mods1 = mods;
2203 WPARAM ch = tranmsg.wParam;
2204
2205 /* If a quit char with no modifiers other than control and
2206 shift, then mark it with a fake modifier, which is removed
2207 upon dequeueing the event */
2208 /* #### This might also not withstand localization, if
2209 quit character is not a latin-1 symbol */
2210 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL)
2211 && quit_ch + 'a' - 1 == ch)
2212 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL)
2213 && quit_ch == ch))
2214 && ((mods & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT))
2215 == 0))
2216 {
2217 mods1 |= FAKE_MOD_QUIT;
2218 ++mswindows_quit_chars_count;
2219 }
2220 else if (potential_accelerator && !got_accelerator &&
2221 mswindows_char_is_accelerator (frame, ch))
2222 {
2223 got_accelerator = 1;
2224 break;
2225 }
2226 mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1);
2227 } /* while */
2228
2229 /* This generates WM_SYSCHAR messages, which are interpreted
2230 by DefWindowProc as the menu selections. */
2231 if (got_accelerator)
2232 {
2233 SetKeyboardState (keymap_sticky);
2234 TranslateMessage (&msg);
2235 SetKeyboardState (keymap_orig);
2236 goto defproc;
2237 }
2238
2239 SetKeyboardState (keymap_orig);
2240 } /* else */
2241 }
2242
2243 if (key_needs_default_processing_p (wParam))
2244 goto defproc;
2245 else
2246 break;
2247
2248 case WM_MBUTTONDOWN:
2249 case WM_MBUTTONUP:
2250 /* Real middle mouse button has nothing to do with emulated one:
2251 if one wants to exercise fingers playing chords on the mouse,
2252 he is allowed to do that! */
2253 mswindows_enqueue_mouse_button_event (hwnd, message_,
2254 MAKEPOINTS (lParam), GetMessageTime());
2255 break;
2256
2257 case WM_LBUTTONUP:
2258 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2259 msframe->last_click_time = GetMessageTime();
2260
2261 KillTimer (hwnd, BUTTON_2_TIMER_ID);
2262 msframe->button2_need_lbutton = 0;
2263 if (msframe->ignore_next_lbutton_up)
2264 { 1988 {
2265 msframe->ignore_next_lbutton_up = 0; 1989 /* Iconified */
2266 } 1990 FRAME_VISIBLE_P (frame) = 0;
2267 else if (msframe->button2_is_down) 1991 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
2268 {
2269 msframe->button2_is_down = 0;
2270 msframe->ignore_next_rbutton_up = 1;
2271 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
2272 MAKEPOINTS (lParam), GetMessageTime());
2273 } 1992 }
2274 else 1993 else
2275 { 1994 {
2276 if (msframe->button2_need_rbutton) 1995 GetClientRect(hwnd, &rect);
1996 FRAME_PIXWIDTH(frame) = rect.right;
1997 FRAME_PIXHEIGHT(frame) = rect.bottom;
1998
1999 pixel_to_real_char_size (frame, rect.right, rect.bottom,
2000 &FRAME_MSWINDOWS_CHARWIDTH (frame),
2001 &FRAME_MSWINDOWS_CHARHEIGHT (frame));
2002
2003 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows);
2004 change_frame_size (frame, rows, columns, 1);
2005
2006 /* If we are inside frame creation, we have to apply geometric
2007 properties now. */
2008 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2277 { 2009 {
2278 msframe->button2_need_rbutton = 0; 2010 /* Yes, we have to size again */
2279 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, 2011 mswindows_size_frame_internal ( frame,
2280 MAKEPOINTS (lParam), GetMessageTime()); 2012 FRAME_MSWINDOWS_TARGET_RECT
2281 } 2013 (frame));
2282 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP, 2014 /* Reset so we do not get here again. The SetWindowPos call in
2283 MAKEPOINTS (lParam), GetMessageTime()); 2015 * mswindows_size_frame_internal can cause recursion here. */
2284 } 2016 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2285 break; 2017 {
2286 2018 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame));
2287 case WM_RBUTTONUP: 2019 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0;
2288 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); 2020 }
2289 msframe->last_click_time = GetMessageTime();
2290
2291 KillTimer (hwnd, BUTTON_2_TIMER_ID);
2292 msframe->button2_need_rbutton = 0;
2293 if (msframe->ignore_next_rbutton_up)
2294 {
2295 msframe->ignore_next_rbutton_up = 0;
2296 }
2297 else if (msframe->button2_is_down)
2298 {
2299 msframe->button2_is_down = 0;
2300 msframe->ignore_next_lbutton_up = 1;
2301 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP,
2302 MAKEPOINTS (lParam), GetMessageTime());
2303 }
2304 else
2305 {
2306 if (msframe->button2_need_lbutton)
2307 {
2308 msframe->button2_need_lbutton = 0;
2309 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN,
2310 MAKEPOINTS (lParam), GetMessageTime());
2311 }
2312 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP,
2313 MAKEPOINTS (lParam), GetMessageTime());
2314 }
2315 break;
2316
2317 case WM_LBUTTONDOWN:
2318 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2319
2320 if (msframe->button2_need_lbutton)
2321 {
2322 KillTimer (hwnd, BUTTON_2_TIMER_ID);
2323 msframe->button2_need_lbutton = 0;
2324 msframe->button2_need_rbutton = 0;
2325 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam)))
2326 {
2327 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN,
2328 MAKEPOINTS (lParam), GetMessageTime());
2329 msframe->button2_is_down = 1;
2330 } 2021 }
2331 else 2022 else
2332 { 2023 {
2333 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, 2024 if (!msframe->sizing && !FRAME_VISIBLE_P (frame))
2334 msframe->last_click_point, msframe->last_click_time); 2025 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
2335 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, 2026 FRAME_VISIBLE_P (frame) = 1;
2336 MAKEPOINTS (lParam), GetMessageTime()); 2027
2028 if (!msframe->sizing || mswindows_dynamic_frame_resize)
2029 redisplay ();
2337 } 2030 }
2338 } 2031 }
2339 else 2032 }
2033 break;
2034
2035 /* Misc magic events which only require that the frame be identified */
2036 case WM_SETFOCUS:
2037 case WM_KILLFOCUS:
2038 mswindows_enqueue_magic_event (hwnd, message);
2039 break;
2040
2041 case WM_WINDOWPOSCHANGING:
2042 {
2043 WINDOWPOS *wp = (LPWINDOWPOS) lParam;
2044 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) };
2045 GetWindowPlacement(hwnd, &wpl);
2046
2047 /* Only interested if size is changing and we're not being iconified */
2048 if (wpl.showCmd != SW_SHOWMINIMIZED
2049 && wpl.showCmd != SW_SHOWMAXIMIZED
2050 && !(wp->flags & SWP_NOSIZE))
2051 {
2052 RECT ncsize = { 0, 0, 0, 0 };
2053 int pixwidth, pixheight;
2054 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE),
2055 GetMenu(hwnd) != NULL,
2056 GetWindowLong (hwnd, GWL_EXSTYLE));
2057
2058 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)),
2059 wp->cx - (ncsize.right - ncsize.left),
2060 wp->cy - (ncsize.bottom - ncsize.top),
2061 &pixwidth, &pixheight);
2062
2063 /* Convert client sizes to window sizes */
2064 pixwidth += (ncsize.right - ncsize.left);
2065 pixheight += (ncsize.bottom - ncsize.top);
2066
2067 if (wpl.showCmd != SW_SHOWMAXIMIZED)
2068 {
2069 /* Adjust so that the bottom or right doesn't move if it's
2070 * the top or left that's being changed */
2071 RECT rect;
2072 GetWindowRect (hwnd, &rect);
2073
2074 if (rect.left != wp->x)
2075 wp->x += wp->cx - pixwidth;
2076 if (rect.top != wp->y)
2077 wp->y += wp->cy - pixheight;
2078 }
2079
2080 wp->cx = pixwidth;
2081 wp->cy = pixheight;
2082 }
2083 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts
2084 window position if the user tries to track window too small */
2085 }
2086 goto defproc;
2087
2088 case WM_ENTERSIZEMOVE:
2089 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2090 msframe->sizing = 1;
2091 return 0;
2092
2093 case WM_EXITSIZEMOVE:
2094 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2095 msframe->sizing = 0;
2096 /* Queue noop event */
2097 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
2098 return 0;
2099
2100 #ifdef HAVE_SCROLLBARS
2101 case WM_VSCROLL:
2102 case WM_HSCROLL:
2103 {
2104 /* Direction of scroll is determined by scrollbar instance. */
2105 int code = (int) LOWORD(wParam);
2106 int pos = (short int) HIWORD(wParam);
2107 HWND hwndScrollBar = (HWND) lParam;
2108 struct gcpro gcpro1, gcpro2;
2109
2110 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos);
2111 GCPRO2 (emacs_event, fobj);
2112 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */
2340 { 2113 {
2341 mswindows_set_chord_timer (hwnd); 2114 /* Error during event pumping - cancel scroll */
2342 msframe->button2_need_rbutton = 1; 2115 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0);
2343 msframe->last_click_point = MAKEPOINTS (lParam);
2344 } 2116 }
2345 msframe->last_click_time = GetMessageTime(); 2117 UNGCPRO;
2346 break; 2118 break;
2347 2119 }
2348 case WM_RBUTTONDOWN: 2120 #endif
2349 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); 2121
2350 2122 #ifdef HAVE_MENUBARS
2351 if (msframe->button2_need_rbutton) 2123 case WM_INITMENU:
2124 if (UNBOUNDP (mswindows_handle_wm_initmenu (
2125 (HMENU) wParam,
2126 XFRAME (mswindows_find_frame (hwnd)))))
2127 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2128 break;
2129
2130 case WM_INITMENUPOPUP:
2131 if (!HIWORD(lParam))
2132 {
2133 if (UNBOUNDP (mswindows_handle_wm_initmenupopup (
2134 (HMENU) wParam,
2135 XFRAME (mswindows_find_frame (hwnd)))))
2136 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2137 }
2138 break;
2139
2140 #endif /* HAVE_MENUBARS */
2141
2142 case WM_COMMAND:
2143 {
2144 WORD id = LOWORD (wParam);
2145 WORD nid = HIWORD (wParam);
2146 HWND cid = (HWND)lParam;
2147 frame = XFRAME (mswindows_find_frame (hwnd));
2148
2149 #ifdef HAVE_TOOLBARS
2150 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
2151 break;
2152 #endif
2153 /* widgets in a buffer only eval a callback for suitable events.*/
2154 switch (nid)
2352 { 2155 {
2353 KillTimer (hwnd, BUTTON_2_TIMER_ID); 2156 case BN_CLICKED:
2354 msframe->button2_need_lbutton = 0; 2157 case EN_CHANGE:
2355 msframe->button2_need_rbutton = 0; 2158 case CBN_EDITCHANGE:
2356 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) 2159 case CBN_SELCHANGE:
2160 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
2161 return 0;
2162 }
2163 /* menubars always must come last since the hashtables do not
2164 always exist*/
2165 #ifdef HAVE_MENUBARS
2166 if (!NILP (mswindows_handle_wm_command (frame, id)))
2167 break;
2168 #endif
2169
2170 return DefWindowProc (hwnd, message, wParam, lParam);
2171 /* Bite me - a spurious command. This used to not be able to
2172 happen but with the introduction of widgets its now
2173 possible. */
2174 }
2175 break;
2176
2177 case WM_CTLCOLORBTN:
2178 case WM_CTLCOLORLISTBOX:
2179 case WM_CTLCOLOREDIT:
2180 case WM_CTLCOLORSTATIC:
2181 case WM_CTLCOLORSCROLLBAR:
2182 {
2183 /* if we get an opportunity to paint a widget then do so if
2184 there is an appropriate face */
2185 HWND crtlwnd = (HWND)lParam;
2186 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
2187 if (ii)
2188 {
2189 Lisp_Object image_instance;
2190 VOID_TO_LISP (image_instance, ii);
2191 if (IMAGE_INSTANCEP (image_instance)
2192 &&
2193 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)
2194 &&
2195 !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance)))
2357 { 2196 {
2358 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, 2197 /* set colors for the buttons */
2359 MAKEPOINTS (lParam), GetMessageTime()); 2198 HDC hdc = (HDC)wParam;
2360 msframe->button2_is_down = 1; 2199 if (last_widget_brushed != ii)
2361 } 2200 {
2362 else 2201 if (widget_brush)
2363 { 2202 DeleteObject (widget_brush);
2364 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, 2203 widget_brush = CreateSolidBrush
2365 msframe->last_click_point, msframe->last_click_time); 2204 (COLOR_INSTANCE_MSWINDOWS_COLOR
2366 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, 2205 (XCOLOR_INSTANCE
2367 MAKEPOINTS (lParam), GetMessageTime()); 2206 (FACE_BACKGROUND
2207 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2208 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2209 }
2210 last_widget_brushed = ii;
2211 SetTextColor
2212 (hdc,
2213 COLOR_INSTANCE_MSWINDOWS_COLOR
2214 (XCOLOR_INSTANCE
2215 (FACE_FOREGROUND
2216 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2217 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2218 SetBkMode (hdc, OPAQUE);
2219 SetBkColor
2220 (hdc,
2221 COLOR_INSTANCE_MSWINDOWS_COLOR
2222 (XCOLOR_INSTANCE
2223 (FACE_BACKGROUND
2224 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2225 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2226 return (LRESULT)widget_brush;
2368 } 2227 }
2369 } 2228 }
2370 else 2229 }
2230 goto defproc;
2231
2232 #ifdef HAVE_DRAGNDROP
2233 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */
2234 {
2235 UINT filecount, i, len;
2236 POINT point;
2237 char* filename;
2238 #ifdef __CYGWIN32__
2239 char* fname;
2240 #endif
2241 Lisp_Object l_dndlist = Qnil, l_item = Qnil;
2242 struct gcpro gcpro1, gcpro2, gcpro3;
2243
2244 emacs_event = Fmake_event (Qnil, Qnil);
2245 event = XEVENT(emacs_event);
2246
2247 GCPRO3 (emacs_event, l_dndlist, l_item);
2248
2249 if (!DragQueryPoint ((HANDLE) wParam, &point))
2250 point.x = point.y = -1; /* outside client area */
2251
2252 event->event_type = misc_user_event;
2253 event->channel = mswindows_find_frame(hwnd);
2254 event->timestamp = GetMessageTime();
2255 event->event.misc.button = 1; /* #### Should try harder */
2256 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0);
2257 event->event.misc.x = point.x;
2258 event->event.misc.y = point.y;
2259 event->event.misc.function = Qdragdrop_drop_dispatch;
2260
2261 filecount = DragQueryFile ((HANDLE) wParam, 0xffffffff, NULL, 0);
2262 for (i=0; i<filecount; i++)
2371 { 2263 {
2372 mswindows_set_chord_timer (hwnd); 2264 len = DragQueryFile ((HANDLE) wParam, i, NULL, 0);
2373 msframe->button2_need_lbutton = 1; 2265 /* The URLs that we make here aren't correct according to section
2374 msframe->last_click_point = MAKEPOINTS (lParam); 2266 * 3.10 of rfc1738 because they're missing the //<host>/ part and
2267 * because they may contain reserved characters. But that's OK. */
2268 #ifdef __CYGWIN32__
2269 fname = (char *)xmalloc (len+1);
2270 DragQueryFile ((HANDLE) wParam, i, fname, len+1);
2271 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
2272 strcpy (filename, "file:");
2273 cygwin32_win32_to_posix_path_list (fname, filename+5);
2274 xfree (fname);
2275 #else
2276 filename = (char *)xmalloc (len+6);
2277 strcpy (filename, "file:");
2278 DragQueryFile ((HANDLE) wParam, i, filename+5, len+1);
2279 dostounix_filename (filename+5);
2280 #endif
2281 l_item = make_string (filename, strlen (filename));
2282 l_dndlist = Fcons (l_item, l_dndlist);
2283 xfree (filename);
2375 } 2284 }
2376 msframe->last_click_time = GetMessageTime(); 2285 DragFinish ((HANDLE) wParam);
2377 break; 2286
2378 2287 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
2379 case WM_TIMER: 2288 mswindows_enqueue_dispatch_event (emacs_event);
2380 if (wParam == BUTTON_2_TIMER_ID) 2289 UNGCPRO;
2381 { 2290 }
2382 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); 2291 break;
2383 KillTimer (hwnd, BUTTON_2_TIMER_ID); 2292 #endif
2384 2293
2385 if (msframe->button2_need_lbutton) 2294 defproc:
2386 { 2295 default:
2387 msframe->button2_need_lbutton = 0; 2296 return DefWindowProc (hwnd, message, wParam, lParam);
2388 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, 2297 }
2389 msframe->last_click_point, msframe->last_click_time);
2390 }
2391 else if (msframe->button2_need_rbutton)
2392 {
2393 msframe->button2_need_rbutton = 0;
2394 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN,
2395 msframe->last_click_point, msframe->last_click_time);
2396 }
2397 }
2398 else
2399 assert ("Spurious timer fired" == 0);
2400 break;
2401
2402 case WM_MOUSEMOVE:
2403 /* Optimization: don't report mouse movement while size is changing */
2404 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2405 if (!msframe->sizing)
2406 {
2407 /* When waiting for the second mouse button to finish
2408 button2 emulation, and have moved too far, just pretend
2409 as if timer has expired. This improves drag-select feedback */
2410 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton)
2411 && !mswindows_button2_near_enough (msframe->last_click_point,
2412 MAKEPOINTS (lParam)))
2413 {
2414 KillTimer (hwnd, BUTTON_2_TIMER_ID);
2415 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0);
2416 }
2417
2418 emacs_event = Fmake_event (Qnil, Qnil);
2419 event = XEVENT(emacs_event);
2420
2421 event->channel = mswindows_find_frame(hwnd);
2422 event->timestamp = GetMessageTime();
2423 event->event_type = pointer_motion_event;
2424 event->event.motion.x = MAKEPOINTS(lParam).x;
2425 event->event.motion.y = MAKEPOINTS(lParam).y;
2426 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0);
2427
2428 mswindows_enqueue_dispatch_event (emacs_event);
2429 }
2430 break;
2431
2432 case WM_CANCELMODE:
2433 ReleaseCapture ();
2434 /* Queue a `cancel-mode-internal' misc user event, so mouse
2435 selection would be canceled if any */
2436 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd),
2437 Qcancel_mode_internal, Qnil);
2438 break;
2439
2440 case WM_NOTIFY:
2441 {
2442 LPNMHDR nmhdr = (LPNMHDR)lParam;
2443
2444 if (nmhdr->code == TTN_NEEDTEXT)
2445 {
2446 #ifdef HAVE_TOOLBARS
2447 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
2448 Lisp_Object btext;
2449
2450 /* find out which toolbar */
2451 frame = XFRAME (mswindows_find_frame (hwnd));
2452 btext = mswindows_get_toolbar_button_text ( frame,
2453 nmhdr->idFrom );
2454
2455 tttext->lpszText = NULL;
2456 tttext->hinst = NULL;
2457
2458 if (!NILP(btext))
2459 {
2460 /* I think this is safe since the text will only go away
2461 when the toolbar does...*/
2462 TO_EXTERNAL_FORMAT (LISP_STRING, btext,
2463 C_STRING_ALLOCA, tttext->lpszText,
2464 Qnative);
2465 }
2466 #endif
2467 }
2468 /* handle tree view callbacks */
2469 else if (nmhdr->code == TVN_SELCHANGED)
2470 {
2471 NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam;
2472 frame = XFRAME (mswindows_find_frame (hwnd));
2473 mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam);
2474 }
2475 /* handle tab control callbacks */
2476 else if (nmhdr->code == TCN_SELCHANGE)
2477 {
2478 TC_ITEM item;
2479 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
2480 frame = XFRAME (mswindows_find_frame (hwnd));
2481
2482 item.mask = TCIF_PARAM;
2483 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx,
2484 (LPARAM)&item);
2485
2486 mswindows_handle_gui_wm_command (frame, 0, item.lParam);
2487 }
2488 }
2489 break;
2490
2491 case WM_PAINT:
2492 /* hdc will be NULL unless this is a subwindow - in which case we
2493 shouldn't have received a paint message for it here. */
2494 assert (wParam == 0);
2495
2496 /* Can't queue a magic event because windows goes modal and sends paint
2497 messages directly to the windows procedure when doing solid drags
2498 and the message queue doesn't get processed. */
2499 mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
2500 break;
2501
2502 case WM_SIZE:
2503 /* We only care about this message if our size has really changed */
2504 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED)
2505 {
2506 RECT rect;
2507 int columns, rows;
2508
2509 fobj = mswindows_find_frame (hwnd);
2510 frame = XFRAME (fobj);
2511 msframe = FRAME_MSWINDOWS_DATA (frame);
2512
2513 /* We cannot handle frame map and unmap hooks right in
2514 this routine, because these may throw. We queue
2515 magic events to run these hooks instead - kkm */
2516
2517 if (wParam==SIZE_MINIMIZED)
2518 {
2519 /* Iconified */
2520 FRAME_VISIBLE_P (frame) = 0;
2521 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
2522 }
2523 else
2524 {
2525 GetClientRect(hwnd, &rect);
2526 FRAME_PIXWIDTH(frame) = rect.right;
2527 FRAME_PIXHEIGHT(frame) = rect.bottom;
2528
2529 pixel_to_real_char_size (frame, rect.right, rect.bottom,
2530 &FRAME_MSWINDOWS_CHARWIDTH (frame),
2531 &FRAME_MSWINDOWS_CHARHEIGHT (frame));
2532
2533 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows);
2534 change_frame_size (frame, rows, columns, 1);
2535
2536 /* If we are inside frame creation, we have to apply geometric
2537 properties now. */
2538 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2539 {
2540 /* Yes, we have to size again */
2541 mswindows_size_frame_internal ( frame,
2542 FRAME_MSWINDOWS_TARGET_RECT
2543 (frame));
2544 /* Reset so we do not get here again. The SetWindowPos call in
2545 * mswindows_size_frame_internal can cause recursion here. */
2546 if (FRAME_MSWINDOWS_TARGET_RECT (frame))
2547 {
2548 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame));
2549 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0;
2550 }
2551 }
2552 else
2553 {
2554 if (!msframe->sizing && !FRAME_VISIBLE_P (frame))
2555 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
2556 FRAME_VISIBLE_P (frame) = 1;
2557
2558 if (!msframe->sizing || mswindows_dynamic_frame_resize)
2559 redisplay ();
2560 }
2561 }
2562 }
2563 break;
2564
2565 case WM_DISPLAYCHANGE:
2566 {
2567 struct device *d;
2568 DWORD message_tick = GetMessageTime ();
2569
2570 fobj = mswindows_find_frame (hwnd);
2571 frame = XFRAME (fobj);
2572 d = XDEVICE (FRAME_DEVICE (frame));
2573
2574 /* Do this only once per message. XEmacs can receive this message
2575 through as many frames as it currently has open. Message time
2576 will be the same for all these messages. Despite extreme
2577 efficiency, the code below has about one in 4 billion
2578 probability that the HDC is not recreated, provided that
2579 XEmacs is running sufficiently longer than 52 days. */
2580 if (DEVICE_MSWINDOWS_UPDATE_TICK(d) != message_tick)
2581 {
2582 DEVICE_MSWINDOWS_UPDATE_TICK(d) = message_tick;
2583 DeleteDC (DEVICE_MSWINDOWS_HCDC(d));
2584 DEVICE_MSWINDOWS_HCDC(d) = CreateCompatibleDC (NULL);
2585 }
2586 }
2587 break;
2588
2589 /* Misc magic events which only require that the frame be identified */
2590 case WM_SETFOCUS:
2591 case WM_KILLFOCUS:
2592 mswindows_enqueue_magic_event (hwnd, message_);
2593 break;
2594
2595 case WM_WINDOWPOSCHANGING:
2596 {
2597 WINDOWPOS *wp = (LPWINDOWPOS) lParam;
2598 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) };
2599 GetWindowPlacement(hwnd, &wpl);
2600
2601 /* Only interested if size is changing and we're not being iconified */
2602 if (wpl.showCmd != SW_SHOWMINIMIZED
2603 && wpl.showCmd != SW_SHOWMAXIMIZED
2604 && !(wp->flags & SWP_NOSIZE))
2605 {
2606 RECT ncsize = { 0, 0, 0, 0 };
2607 int pixwidth, pixheight;
2608 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE),
2609 GetMenu(hwnd) != NULL,
2610 GetWindowLong (hwnd, GWL_EXSTYLE));
2611
2612 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)),
2613 wp->cx - (ncsize.right - ncsize.left),
2614 wp->cy - (ncsize.bottom - ncsize.top),
2615 &pixwidth, &pixheight);
2616
2617 /* Convert client sizes to window sizes */
2618 pixwidth += (ncsize.right - ncsize.left);
2619 pixheight += (ncsize.bottom - ncsize.top);
2620
2621 if (wpl.showCmd != SW_SHOWMAXIMIZED)
2622 {
2623 /* Adjust so that the bottom or right doesn't move if it's
2624 * the top or left that's being changed */
2625 RECT rect;
2626 GetWindowRect (hwnd, &rect);
2627
2628 if (rect.left != wp->x)
2629 wp->x += wp->cx - pixwidth;
2630 if (rect.top != wp->y)
2631 wp->y += wp->cy - pixheight;
2632 }
2633
2634 wp->cx = pixwidth;
2635 wp->cy = pixheight;
2636 }
2637 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts
2638 window position if the user tries to track window too small */
2639 }
2640 goto defproc;
2641
2642 case WM_ENTERSIZEMOVE:
2643 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2644 msframe->sizing = 1;
2645 return 0;
2646
2647 case WM_EXITSIZEMOVE:
2648 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd)));
2649 msframe->sizing = 0;
2650 /* Queue noop event */
2651 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
2652 return 0;
2653
2654 #ifdef HAVE_SCROLLBARS
2655 case WM_VSCROLL:
2656 case WM_HSCROLL:
2657 {
2658 /* Direction of scroll is determined by scrollbar instance. */
2659 int code = (int) LOWORD(wParam);
2660 int pos = (short int) HIWORD(wParam);
2661 HWND hwndScrollBar = (HWND) lParam;
2662 struct gcpro gcpro1, gcpro2;
2663
2664 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos);
2665 GCPRO2 (emacs_event, fobj);
2666 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */
2667 {
2668 /* Error during event pumping - cancel scroll */
2669 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0);
2670 }
2671 UNGCPRO;
2672 break;
2673 }
2674
2675 case WM_MOUSEWHEEL:
2676 {
2677 int keys = LOWORD (wParam); /* Modifier key flags */
2678 int delta = (short) HIWORD (wParam); /* Wheel rotation amount */
2679 struct gcpro gcpro1, gcpro2;
2680
2681 if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta))
2682 {
2683 GCPRO2 (emacs_event, fobj);
2684 mswindows_pump_outstanding_events (); /* Can GC */
2685 UNGCPRO;
2686 }
2687 else
2688 goto defproc;
2689 break;
2690 }
2691 #endif
2692
2693 #ifdef HAVE_MENUBARS
2694 case WM_INITMENU:
2695 if (UNBOUNDP (mswindows_handle_wm_initmenu (
2696 (HMENU) wParam,
2697 XFRAME (mswindows_find_frame (hwnd)))))
2698 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2699 break;
2700
2701 case WM_INITMENUPOPUP:
2702 if (!HIWORD(lParam))
2703 {
2704 if (UNBOUNDP (mswindows_handle_wm_initmenupopup (
2705 (HMENU) wParam,
2706 XFRAME (mswindows_find_frame (hwnd)))))
2707 SendMessage (hwnd, WM_CANCELMODE, 0, 0);
2708 }
2709 break;
2710
2711 #endif /* HAVE_MENUBARS */
2712
2713 case WM_COMMAND:
2714 {
2715 WORD id = LOWORD (wParam);
2716 WORD nid = HIWORD (wParam);
2717 HWND cid = (HWND)lParam;
2718 frame = XFRAME (mswindows_find_frame (hwnd));
2719
2720 #ifdef HAVE_TOOLBARS
2721 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
2722 break;
2723 #endif
2724 /* widgets in a buffer only eval a callback for suitable events.*/
2725 switch (nid)
2726 {
2727 case BN_CLICKED:
2728 case EN_CHANGE:
2729 case CBN_EDITCHANGE:
2730 case CBN_SELCHANGE:
2731 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
2732 return 0;
2733 }
2734 /* menubars always must come last since the hashtables do not
2735 always exist*/
2736 #ifdef HAVE_MENUBARS
2737 if (!NILP (mswindows_handle_wm_command (frame, id)))
2738 break;
2739 #endif
2740
2741 return DefWindowProc (hwnd, message_, wParam, lParam);
2742 /* Bite me - a spurious command. This used to not be able to
2743 happen but with the introduction of widgets its now
2744 possible. */
2745 }
2746 break;
2747
2748 case WM_CTLCOLORBTN:
2749 case WM_CTLCOLORLISTBOX:
2750 case WM_CTLCOLOREDIT:
2751 case WM_CTLCOLORSTATIC:
2752 case WM_CTLCOLORSCROLLBAR:
2753 {
2754 /* if we get an opportunity to paint a widget then do so if
2755 there is an appropriate face */
2756 HWND crtlwnd = (HWND)lParam;
2757 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
2758 if (ii)
2759 {
2760 Lisp_Object image_instance;
2761 VOID_TO_LISP (image_instance, ii);
2762 if (IMAGE_INSTANCEP (image_instance)
2763 &&
2764 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET))
2765 {
2766 /* set colors for the buttons */
2767 HDC hdc = (HDC)wParam;
2768 if (last_widget_brushed != ii)
2769 {
2770 if (widget_brush)
2771 DeleteObject (widget_brush);
2772 widget_brush = CreateSolidBrush
2773 (COLOR_INSTANCE_MSWINDOWS_COLOR
2774 (XCOLOR_INSTANCE
2775 (FACE_BACKGROUND
2776 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2777 XIMAGE_INSTANCE_FRAME (image_instance)))));
2778 }
2779 last_widget_brushed = ii;
2780 SetTextColor
2781 (hdc,
2782 COLOR_INSTANCE_MSWINDOWS_COLOR
2783 (XCOLOR_INSTANCE
2784 (FACE_FOREGROUND
2785 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2786 XIMAGE_INSTANCE_FRAME (image_instance)))));
2787 SetBkMode (hdc, OPAQUE);
2788 SetBkColor
2789 (hdc,
2790 COLOR_INSTANCE_MSWINDOWS_COLOR
2791 (XCOLOR_INSTANCE
2792 (FACE_BACKGROUND
2793 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2794 XIMAGE_INSTANCE_FRAME (image_instance)))));
2795 return (LRESULT)widget_brush;
2796 }
2797 }
2798 }
2799 goto defproc;
2800
2801 #ifdef HAVE_DRAGNDROP
2802 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */
2803 {
2804 UINT filecount, i, len;
2805 POINT point;
2806 char* filename;
2807 char* fname;
2808
2809 Lisp_Object l_dndlist = Qnil, l_item = Qnil;
2810 struct gcpro gcpro1, gcpro2, gcpro3;
2811
2812 emacs_event = Fmake_event (Qnil, Qnil);
2813 event = XEVENT(emacs_event);
2814
2815 GCPRO3 (emacs_event, l_dndlist, l_item);
2816
2817 if (!DragQueryPoint ((HDROP) wParam, &point))
2818 point.x = point.y = -1; /* outside client area */
2819
2820 event->event_type = misc_user_event;
2821 event->channel = mswindows_find_frame(hwnd);
2822 event->timestamp = GetMessageTime();
2823 event->event.misc.button = 1; /* #### Should try harder */
2824 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0);
2825 event->event.misc.x = point.x;
2826 event->event.misc.y = point.y;
2827 event->event.misc.function = Qdragdrop_drop_dispatch;
2828
2829 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0);
2830 for (i=0; i<filecount; i++)
2831 {
2832 len = DragQueryFile ((HDROP) wParam, i, NULL, 0);
2833 /* The URLs that we make here aren't correct according to section
2834 * 3.10 of rfc1738 because they're missing the //<host>/ part and
2835 * because they may contain reserved characters. But that's OK -
2836 * they just need to be good enough to keep dragdrop.el happy. */
2837 fname = (char *)xmalloc (len+1);
2838 DragQueryFile ((HANDLE) wParam, i, fname, len+1);
2839
2840 /* May be a shell link aka "shortcut" - replace fname if so */
2841 #if !(defined(CYGWIN) || defined(MINGW))
2842 /* cygwin doesn't define this COM stuff */
2843 if (!stricmp (fname + strlen (fname) - 4, ".LNK"))
2844 {
2845 IShellLink* psl;
2846
2847 if (CoCreateInstance (&CLSID_ShellLink, NULL,
2848 CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl) == S_OK)
2849 {
2850 IPersistFile* ppf;
2851
2852 if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile,
2853 &ppf) == S_OK)
2854 {
2855 WORD wsz[MAX_PATH];
2856 WIN32_FIND_DATA wfd;
2857 LPSTR resolved = (char *) xmalloc (MAX_PATH+1);
2858
2859 MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, MAX_PATH);
2860
2861 if ((ppf->lpVtbl->Load (ppf, wsz, STGM_READ) == S_OK) &&
2862 (psl->lpVtbl->GetPath (psl, resolved, MAX_PATH,
2863 &wfd, 0)==S_OK))
2864 {
2865 xfree (fname);
2866 fname = resolved;
2867 len = strlen (fname);
2868 }
2869
2870 ppf->lpVtbl->Release (ppf);
2871 }
2872
2873 psl->lpVtbl->Release (psl);
2874 }
2875 }
2876 #endif
2877
2878 #ifdef CYGWIN
2879 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
2880 strcpy (filename, "file:");
2881 cygwin32_win32_to_posix_path_list (fname, filename+5);
2882 #else
2883 filename = (char *)xmalloc (len+6);
2884 strcat (strcpy (filename, "file:"), fname);
2885 dostounix_filename (filename+5);
2886 #endif
2887 xfree (fname);
2888 l_item = make_string (filename, strlen (filename));
2889 l_dndlist = Fcons (l_item, l_dndlist);
2890 xfree (filename);
2891 }
2892 DragFinish ((HDROP) wParam);
2893
2894 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
2895 mswindows_enqueue_dispatch_event (emacs_event);
2896 UNGCPRO;
2897 }
2898 break;
2899 #endif
2900
2901 defproc:
2902 default:
2903 return DefWindowProc (hwnd, message_, wParam, lParam);
2904 }
2905 return (0); 2298 return (0);
2906 } 2299 }
2907 2300
2908 2301
2909 /************************************************************************/ 2302 /************************************************************************/
2965 } 2358 }
2966 2359
2967 2360
2968 /* Returns the state of the modifier keys in the format expected by the 2361 /* Returns the state of the modifier keys in the format expected by the
2969 * Lisp_Event key_data, button_data and motion_data modifiers member */ 2362 * Lisp_Event key_data, button_data and motion_data modifiers member */
2970 static int 2363 int mswindows_modifier_state (BYTE* keymap, int has_AltGr)
2971 mswindows_modifier_state (BYTE* keymap, int has_AltGr)
2972 { 2364 {
2973 int mods = 0; 2365 int mods = 0;
2974 BYTE keymap2[256];
2975 2366
2976 if (keymap == NULL) 2367 if (keymap == NULL)
2977 { 2368 {
2978 keymap = keymap2; 2369 keymap = (BYTE*) alloca(256);
2979 GetKeyboardState (keymap); 2370 GetKeyboardState (keymap);
2980 has_AltGr = mswindows_current_layout_has_AltGr (); 2371 has_AltGr = mswindows_current_layout_has_AltGr ();
2981 } 2372 }
2982 2373
2983 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) 2374 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80))
2984 { 2375 {
2985 mods |= (keymap [VK_LMENU] & 0x80) ? XEMACS_MOD_META : 0; 2376 mods |= (keymap [VK_LMENU] & 0x80) ? MOD_META : 0;
2986 mods |= (keymap [VK_RCONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0; 2377 mods |= (keymap [VK_RCONTROL] & 0x80) ? MOD_CONTROL : 0;
2987 } 2378 }
2988 else 2379 else
2989 { 2380 {
2990 mods |= (keymap [VK_MENU] & 0x80) ? XEMACS_MOD_META : 0; 2381 mods |= (keymap [VK_MENU] & 0x80) ? MOD_META : 0;
2991 mods |= (keymap [VK_CONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0; 2382 mods |= (keymap [VK_CONTROL] & 0x80) ? MOD_CONTROL : 0;
2992 } 2383 }
2993 2384
2994 mods |= (keymap [VK_SHIFT] & 0x80) ? XEMACS_MOD_SHIFT : 0; 2385 mods |= (keymap [VK_SHIFT] & 0x80) ? MOD_SHIFT : 0;
2995 2386
2996 return mods; 2387 return mods;
2997 } 2388 }
2998 2389
2999 /* 2390 /*
3000 * Translate a mswindows virtual key to a keysym. 2391 * Translate a mswindows virtual key to a keysym.
3001 * Only returns non-Qnil for keys that don't generate WM_CHAR messages 2392 * Only returns non-Qnil for keys that don't generate WM_CHAR messages
3002 * or whose ASCII codes (like space) xemacs doesn't like. 2393 * or whose ASCII codes (like space) xemacs doesn't like.
3003 * Virtual key values are defined in winresrc.h 2394 * Virtual key values are defined in winresrc.h
2395 * XXX I'm not sure that KEYSYM("name") is the best thing to use here.
3004 */ 2396 */
3005 Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, 2397 Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods)
3006 int extendedp) 2398 {
3007 { 2399 switch (mswindows_key)
3008 if (extendedp) /* Keys not present on a 82 key keyboard */ 2400 {
3009 { 2401 /* First the predefined ones */
3010 switch (mswindows_key) 2402 case VK_BACK: return QKbackspace;
3011 { 2403 case VK_TAB: return QKtab;
3012 case VK_RETURN: return KEYSYM ("kp-enter"); 2404 case '\n': return QKlinefeed; /* No VK_LINEFEED in winresrc.h */
3013 case VK_PRIOR: return KEYSYM ("prior"); 2405 case VK_RETURN: return QKreturn;
3014 case VK_NEXT: return KEYSYM ("next"); 2406 case VK_ESCAPE: return QKescape;
3015 case VK_END: return KEYSYM ("end"); 2407 case VK_SPACE: return QKspace;
3016 case VK_HOME: return KEYSYM ("home"); 2408 case VK_DELETE: return QKdelete;
3017 case VK_LEFT: return KEYSYM ("left"); 2409
3018 case VK_UP: return KEYSYM ("up"); 2410 /* The rest */
3019 case VK_RIGHT: return KEYSYM ("right"); 2411 case VK_CLEAR: return KEYSYM ("clear"); /* Should do ^L ? */
3020 case VK_DOWN: return KEYSYM ("down"); 2412 case VK_PRIOR: return KEYSYM ("prior");
3021 case VK_INSERT: return KEYSYM ("insert"); 2413 case VK_NEXT: return KEYSYM ("next");
3022 case VK_DELETE: return QKdelete; 2414 case VK_END: return KEYSYM ("end");
3023 } 2415 case VK_HOME: return KEYSYM ("home");
3024 } 2416 case VK_LEFT: return KEYSYM ("left");
3025 else 2417 case VK_UP: return KEYSYM ("up");
3026 { 2418 case VK_RIGHT: return KEYSYM ("right");
3027 switch (mswindows_key) 2419 case VK_DOWN: return KEYSYM ("down");
3028 { 2420 case VK_SELECT: return KEYSYM ("select");
3029 case VK_BACK: return QKbackspace; 2421 case VK_PRINT: return KEYSYM ("print");
3030 case VK_TAB: return QKtab; 2422 case VK_EXECUTE: return KEYSYM ("execute");
3031 case '\n': return QKlinefeed; 2423 case VK_SNAPSHOT: return KEYSYM ("print");
3032 case VK_CLEAR: return KEYSYM ("clear"); 2424 case VK_INSERT: return KEYSYM ("insert");
3033 case VK_RETURN: return QKreturn; 2425 case VK_HELP: return KEYSYM ("help");
3034 case VK_ESCAPE: return QKescape; 2426 #if 0 /* XXX What are these supposed to do? */
3035 case VK_SPACE: return QKspace; 2427 case VK_LWIN return KEYSYM ("");
3036 case VK_PRIOR: return KEYSYM ("kp-prior"); 2428 case VK_RWIN return KEYSYM ("");
3037 case VK_NEXT: return KEYSYM ("kp-next"); 2429 #endif
3038 case VK_END: return KEYSYM ("kp-end"); 2430 case VK_APPS: return KEYSYM ("menu");
3039 case VK_HOME: return KEYSYM ("kp-home"); 2431 case VK_F1: return KEYSYM ("f1");
3040 case VK_LEFT: return KEYSYM ("kp-left"); 2432 case VK_F2: return KEYSYM ("f2");
3041 case VK_UP: return KEYSYM ("kp-up"); 2433 case VK_F3: return KEYSYM ("f3");
3042 case VK_RIGHT: return KEYSYM ("kp-right"); 2434 case VK_F4: return KEYSYM ("f4");
3043 case VK_DOWN: return KEYSYM ("kp-down"); 2435 case VK_F5: return KEYSYM ("f5");
3044 case VK_SELECT: return KEYSYM ("select"); 2436 case VK_F6: return KEYSYM ("f6");
3045 case VK_PRINT: return KEYSYM ("print"); 2437 case VK_F7: return KEYSYM ("f7");
3046 case VK_EXECUTE: return KEYSYM ("execute"); 2438 case VK_F8: return KEYSYM ("f8");
3047 case VK_SNAPSHOT: return KEYSYM ("print"); 2439 case VK_F9: return KEYSYM ("f9");
3048 case VK_INSERT: return KEYSYM ("kp-insert"); 2440 case VK_F10: return KEYSYM ("f10");
3049 case VK_DELETE: return KEYSYM ("kp-delete"); 2441 case VK_F11: return KEYSYM ("f11");
3050 case VK_HELP: return KEYSYM ("help"); 2442 case VK_F12: return KEYSYM ("f12");
3051 #if 0 /* FSF Emacs allows these to return configurable syms/mods */ 2443 case VK_F13: return KEYSYM ("f13");
3052 case VK_LWIN return KEYSYM (""); 2444 case VK_F14: return KEYSYM ("f14");
3053 case VK_RWIN return KEYSYM (""); 2445 case VK_F15: return KEYSYM ("f15");
3054 #endif 2446 case VK_F16: return KEYSYM ("f16");
3055 case VK_APPS: return KEYSYM ("menu"); 2447 case VK_F17: return KEYSYM ("f17");
3056 case VK_NUMPAD0: return KEYSYM ("kp-0"); 2448 case VK_F18: return KEYSYM ("f18");
3057 case VK_NUMPAD1: return KEYSYM ("kp-1"); 2449 case VK_F19: return KEYSYM ("f19");
3058 case VK_NUMPAD2: return KEYSYM ("kp-2"); 2450 case VK_F20: return KEYSYM ("f20");
3059 case VK_NUMPAD3: return KEYSYM ("kp-3"); 2451 case VK_F21: return KEYSYM ("f21");
3060 case VK_NUMPAD4: return KEYSYM ("kp-4"); 2452 case VK_F22: return KEYSYM ("f22");
3061 case VK_NUMPAD5: return KEYSYM ("kp-5"); 2453 case VK_F23: return KEYSYM ("f23");
3062 case VK_NUMPAD6: return KEYSYM ("kp-6"); 2454 case VK_F24: return KEYSYM ("f24");
3063 case VK_NUMPAD7: return KEYSYM ("kp-7"); 2455 }
3064 case VK_NUMPAD8: return KEYSYM ("kp-8");
3065 case VK_NUMPAD9: return KEYSYM ("kp-9");
3066 case VK_MULTIPLY: return KEYSYM ("kp-multiply");
3067 case VK_ADD: return KEYSYM ("kp-add");
3068 case VK_SEPARATOR: return KEYSYM ("kp-separator");
3069 case VK_SUBTRACT: return KEYSYM ("kp-subtract");
3070 case VK_DECIMAL: return KEYSYM ("kp-decimal");
3071 case VK_DIVIDE: return KEYSYM ("kp-divide");
3072 case VK_F1: return KEYSYM ("f1");
3073 case VK_F2: return KEYSYM ("f2");
3074 case VK_F3: return KEYSYM ("f3");
3075 case VK_F4: return KEYSYM ("f4");
3076 case VK_F5: return KEYSYM ("f5");
3077 case VK_F6: return KEYSYM ("f6");
3078 case VK_F7: return KEYSYM ("f7");
3079 case VK_F8: return KEYSYM ("f8");
3080 case VK_F9: return KEYSYM ("f9");
3081 case VK_F10: return KEYSYM ("f10");
3082 case VK_F11: return KEYSYM ("f11");
3083 case VK_F12: return KEYSYM ("f12");
3084 case VK_F13: return KEYSYM ("f13");
3085 case VK_F14: return KEYSYM ("f14");
3086 case VK_F15: return KEYSYM ("f15");
3087 case VK_F16: return KEYSYM ("f16");
3088 case VK_F17: return KEYSYM ("f17");
3089 case VK_F18: return KEYSYM ("f18");
3090 case VK_F19: return KEYSYM ("f19");
3091 case VK_F20: return KEYSYM ("f20");
3092 case VK_F21: return KEYSYM ("f21");
3093 case VK_F22: return KEYSYM ("f22");
3094 case VK_F23: return KEYSYM ("f23");
3095 case VK_F24: return KEYSYM ("f24");
3096 }
3097 }
3098 return Qnil; 2456 return Qnil;
3099 } 2457 }
3100 2458
3101 /* 2459 /*
3102 * Find the console that matches the supplied mswindows window handle 2460 * Find the console that matches the supplied mswindows window handle
3150 } 2508 }
3151 2509
3152 static void 2510 static void
3153 emacs_mswindows_remove_timeout (int id) 2511 emacs_mswindows_remove_timeout (int id)
3154 { 2512 {
3155 Lisp_Event match_against; 2513 struct Lisp_Event match_against;
3156 Lisp_Object emacs_event; 2514 Lisp_Object emacs_event;
3157 2515
3158 if (KillTimer (NULL, id)) 2516 if (KillTimer (NULL, id))
3159 --mswindows_pending_timers_count; 2517 --mswindows_pending_timers_count;
3160 2518
3186 2544
3187 /* 2545 /*
3188 * Return the next event 2546 * Return the next event
3189 */ 2547 */
3190 static void 2548 static void
3191 emacs_mswindows_next_event (Lisp_Event *emacs_event) 2549 emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
3192 { 2550 {
3193 Lisp_Object event, event2; 2551 Lisp_Object event, event2;
3194 2552
3195 mswindows_need_event (1); 2553 mswindows_need_event (1);
3196 2554
3197 event = mswindows_dequeue_dispatch_event (); 2555 event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue));
3198 XSETEVENT (event2, emacs_event); 2556 XSETEVENT (event2, emacs_event);
3199 Fcopy_event (event, event2); 2557 Fcopy_event (event, event2);
3200 Fdeallocate_event (event); 2558 Fdeallocate_event (event);
3201 } 2559 }
3202 2560
3203 /* 2561 /*
3204 * Handle a magic event off the dispatch queue. 2562 * Handle a magic event off the dispatch queue.
3205 */ 2563 */
3206 static void 2564 static void
3207 emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event) 2565 emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
3208 { 2566 {
3209 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)) 2567 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event))
3210 { 2568 {
3211 case XM_BUMPQUEUE: 2569 case XM_BUMPQUEUE:
3212 break; 2570 break;
3213 2571
3214 case WM_PAINT:
3215 {
3216 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
3217 mswindows_handle_paint (f);
3218 (FRAME_MSWINDOWS_DATA (f))->paint_pending = 0;
3219 }
3220 break;
3221
3222 case WM_SETFOCUS: 2572 case WM_SETFOCUS:
3223 case WM_KILLFOCUS: 2573 case WM_KILLFOCUS:
3224 { 2574 {
3225 Lisp_Object frame = EVENT_CHANNEL (emacs_event); 2575 Lisp_Object frame = EVENT_CHANNEL (emacs_event);
3226 struct frame *f = XFRAME (frame); 2576 struct frame *f = XFRAME (frame);
3227 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS); 2577 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS);
3228 Lisp_Object conser; 2578 Lisp_Object conser;
3229 struct gcpro gcpro1; 2579
3230 2580 /* struct gcpro gcpro1; */
3231 /* On focus change, clear all memory of sticky modifiers 2581
3232 to avoid non-intuitive behavior. */ 2582 /* Clear sticky modifiers here (if we had any) */
3233 clear_sticky_modifiers ();
3234 2583
3235 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); 2584 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
3236 GCPRO1 (conser); 2585 /* GCPRO1 (conser); XXX Not necessary? */
3237 emacs_handle_focus_change_preliminary (conser); 2586 emacs_handle_focus_change_preliminary (conser);
3238 /* Under X the stuff up to here is done in the X event handler. 2587 /* Under X the stuff up to here is done in the X event handler.
3239 I Don't know why */ 2588 I Don't know why */
3240 emacs_handle_focus_change_final (conser); 2589 emacs_handle_focus_change_final (conser);
3241 UNGCPRO; 2590 /* UNGCPRO; */
3242 2591
3243 } 2592 }
3244 break; 2593 break;
3245 2594
3246 case XM_MAPFRAME: 2595 case XM_MAPFRAME:
3247 case XM_UNMAPFRAME: 2596 case XM_UNMAPFRAME:
3248 { 2597 {
3249 Lisp_Object frame = EVENT_CHANNEL (emacs_event); 2598 Lisp_Object frame = EVENT_CHANNEL (emacs_event);
3250 va_run_hook_with_args (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) 2599 va_run_hook_with_args (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)
3251 == XM_MAPFRAME ? 2600 == XM_MAPFRAME ?
3252 Qmap_frame_hook : Qunmap_frame_hook, 2601 Qmap_frame_hook : Qunmap_frame_hook,
3253 1, frame); 2602 1, frame);
3254 } 2603 }
3255 break; 2604 break;
3256 2605
3257 /* #### What about Enter & Leave */ 2606 /* #### What about Enter & Leave */
3258 #if 0 2607 #if 0
3259 va_run_hook_with_args (in_p ? Qmouse_enter_frame_hook : 2608 va_run_hook_with_args (in_p ? Qmouse_enter_frame_hook :
3260 Qmouse_leave_frame_hook, 1, frame); 2609 Qmouse_leave_frame_hook, 1, frame);
3261 #endif 2610 #endif
3265 } 2614 }
3266 } 2615 }
3267 2616
3268 #ifndef HAVE_MSG_SELECT 2617 #ifndef HAVE_MSG_SELECT
3269 static HANDLE 2618 static HANDLE
3270 get_process_input_waitable (Lisp_Process *process) 2619 get_process_input_waitable (struct Lisp_Process *process)
3271 { 2620 {
3272 Lisp_Object instr, outstr, p; 2621 Lisp_Object instr, outstr, p;
3273 XSETPROCESS (p, process); 2622 XSETPROCESS (p, process);
3274 get_process_streams (process, &instr, &outstr); 2623 get_process_streams (process, &instr, &outstr);
3275 assert (!NILP (instr)); 2624 assert (!NILP (instr));
3276 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) 2625 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT)
3277 return (network_connection_p (p) 2626 return (network_connection_p (p)
3278 ? get_winsock_stream_waitable (XLSTREAM (instr)) 2627 ? get_winsock_stream_waitable (XLSTREAM (instr))
3279 : get_ntpipe_input_stream_waitable (XLSTREAM (instr))); 2628 : get_ntpipe_input_stream_waitable (XLSTREAM (instr)));
3280 #else 2629 #else
3281 return get_ntpipe_input_stream_waitable (XLSTREAM (instr)); 2630 return get_ntpipe_input_stream_waitable (XLSTREAM (instr));
3282 #endif 2631 #endif
3283 } 2632 }
3284 2633
3285 static void 2634 static void
3286 emacs_mswindows_select_process (Lisp_Process *process) 2635 emacs_mswindows_select_process (struct Lisp_Process *process)
3287 { 2636 {
3288 HANDLE hev = get_process_input_waitable (process); 2637 HANDLE hev = get_process_input_waitable (process);
3289 2638
3290 if (!add_waitable_handle (hev)) 2639 if (!add_waitable_handle (hev))
3291 error ("Too many active processes"); 2640 error ("Too many active processes");
3306 } 2655 }
3307 #endif 2656 #endif
3308 } 2657 }
3309 2658
3310 static void 2659 static void
3311 emacs_mswindows_unselect_process (Lisp_Process *process) 2660 emacs_mswindows_unselect_process (struct Lisp_Process *process)
3312 { 2661 {
3313 /* Process handle is removed in the event loop as soon 2662 /* Process handle is removed in the event loop as soon
3314 as it is signaled, so don't bother here about it */ 2663 as it is signaled, so don't bother here about it */
3315 HANDLE hev = get_process_input_waitable (process); 2664 HANDLE hev = get_process_input_waitable (process);
3316 remove_waitable_handle (hev); 2665 remove_waitable_handle (hev);
3340 } 2689 }
3341 2690
3342 static void 2691 static void
3343 emacs_mswindows_quit_p (void) 2692 emacs_mswindows_quit_p (void)
3344 { 2693 {
2694 MSG msg;
2695
3345 /* Quit cannot happen in modal loop: all program 2696 /* Quit cannot happen in modal loop: all program
3346 input is dedicated to Windows. */ 2697 input is dedicated to Windows. */
3347 if (mswindows_in_modal_loop) 2698 if (mswindows_in_modal_loop)
3348 return; 2699 return;
3349 2700
3350 /* Drain windows queue. This sets up number of quit characters in 2701 /* Drain windows queue. This sets up number of quit characters in the queue
3351 the queue */ 2702 * (and also processes wm focus change, move, resize, etc messages).
3352 mswindows_drain_windows_queue (); 2703 * We don't want to process WM_PAINT messages because this function can be
2704 * called from almost anywhere and the windows' states may be changing. */
2705 while (PeekMessage (&msg, NULL, 0, WM_PAINT-1, PM_REMOVE) ||
2706 PeekMessage (&msg, NULL, WM_PAINT+1, WM_USER-1, PM_REMOVE))
2707 DispatchMessage (&msg);
3353 2708
3354 if (mswindows_quit_chars_count > 0) 2709 if (mswindows_quit_chars_count > 0)
3355 { 2710 {
3356 /* Yes there's a hidden one... Throw it away */ 2711 /* Yes there's a hidden one... Throw it away */
3357 Lisp_Event match_against; 2712 struct Lisp_Event match_against;
3358 Lisp_Object emacs_event; 2713 Lisp_Object emacs_event;
3359 int critical_p = 0;
3360 2714
3361 match_against.event_type = key_press_event; 2715 match_against.event_type = key_press_event;
3362 match_against.event.key.modifiers = FAKE_MOD_QUIT; 2716 match_against.event.key.modifiers = FAKE_MOD_QUIT;
3363 2717
3364 while (mswindows_quit_chars_count-- > 0) 2718 emacs_event = mswindows_cancel_dispatch_event (&match_against);
3365 { 2719 assert (!NILP (emacs_event));
3366 emacs_event = mswindows_cancel_dispatch_event (&match_against); 2720
3367 assert (!NILP (emacs_event)); 2721 Vquit_flag = (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT
3368 2722 ? Qcritical : Qt);
3369 if (XEVENT(emacs_event)->event.key.modifiers & XEMACS_MOD_SHIFT) 2723
3370 critical_p = 1; 2724 Fdeallocate_event(emacs_event);
3371 2725 --mswindows_quit_chars_count;
3372 Fdeallocate_event(emacs_event);
3373 }
3374
3375 Vquit_flag = critical_p ? Qcritical : Qt;
3376 } 2726 }
3377 } 2727 }
3378 2728
3379 USID 2729 USID
3380 emacs_mswindows_create_stream_pair (void* inhandle, void* outhandle, 2730 emacs_mswindows_create_stream_pair (void* inhandle, void* outhandle,
3448 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream)))); 2798 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream))));
3449 } 2799 }
3450 2800
3451 USID 2801 USID
3452 emacs_mswindows_delete_stream_pair (Lisp_Object instream, 2802 emacs_mswindows_delete_stream_pair (Lisp_Object instream,
3453 Lisp_Object outstream) 2803 Lisp_Object outstream)
3454 { 2804 {
3455 /* Oh nothing special here for Win32 at all */ 2805 /* Oh nothing special here for Win32 at all */
3456 #if defined (HAVE_UNIX_PROCESSES) 2806 #if defined (HAVE_UNIX_PROCESSES)
3457 int in = (NILP(instream) 2807 int in = (NILP(instream)
3458 ? -1 2808 ? -1
3482 #ifndef HAVE_X_WINDOWS 2832 #ifndef HAVE_X_WINDOWS
3483 /* This is called from GC when a process object is about to be freed. 2833 /* This is called from GC when a process object is about to be freed.
3484 If we've still got pointers to it in this file, we're gonna lose hard. 2834 If we've still got pointers to it in this file, we're gonna lose hard.
3485 */ 2835 */
3486 void 2836 void
3487 debug_process_finalization (Lisp_Process *p) 2837 debug_process_finalization (struct Lisp_Process *p)
3488 { 2838 {
3489 #if 0 /* #### */ 2839 #if 0 /* #### */
3490 Lisp_Object instr, outstr; 2840 Lisp_Object instr, outstr;
3491 2841
3492 get_process_streams (p, &instr, &outstr); 2842 get_process_streams (p, &instr, &outstr);
3500 #endif 2850 #endif
3501 2851
3502 /************************************************************************/ 2852 /************************************************************************/
3503 /* initialization */ 2853 /* initialization */
3504 /************************************************************************/ 2854 /************************************************************************/
3505 2855
3506 void 2856 void
3507 reinit_vars_of_event_mswindows (void) 2857 vars_of_event_mswindows (void)
3508 { 2858 {
2859 mswindows_u_dispatch_event_queue = Qnil;
2860 staticpro (&mswindows_u_dispatch_event_queue);
2861 mswindows_u_dispatch_event_queue_tail = Qnil;
2862
2863 mswindows_s_dispatch_event_queue = Qnil;
2864 staticpro (&mswindows_s_dispatch_event_queue);
2865 mswindows_s_dispatch_event_queue_tail = Qnil;
2866
2867 mswindows_error_caught_in_modal_loop = Qnil;
2868 staticpro (&mswindows_error_caught_in_modal_loop);
3509 mswindows_in_modal_loop = 0; 2869 mswindows_in_modal_loop = 0;
3510 mswindows_pending_timers_count = 0; 2870 mswindows_pending_timers_count = 0;
3511 2871
3512 mswindows_event_stream = xnew (struct event_stream); 2872 mswindows_event_stream = xnew (struct event_stream);
3513 2873
3514 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; 2874 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p;
3515 mswindows_event_stream->force_event_pending = 0;
3516 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; 2875 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event;
3517 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; 2876 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event;
3518 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; 2877 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout;
3519 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; 2878 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout;
3520 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; 2879 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p;
3521 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; 2880 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console;
3522 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; 2881 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console;
3523 #ifdef HAVE_MSG_SELECT 2882 #ifdef HAVE_MSG_SELECT
3524 mswindows_event_stream->select_process_cb = 2883 mswindows_event_stream->select_process_cb =
3525 (void (*)(Lisp_Process*))event_stream_unixoid_select_process; 2884 (void (*)(struct Lisp_Process*))event_stream_unixoid_select_process;
3526 mswindows_event_stream->unselect_process_cb = 2885 mswindows_event_stream->unselect_process_cb =
3527 (void (*)(Lisp_Process*))event_stream_unixoid_unselect_process; 2886 (void (*)(struct Lisp_Process*))event_stream_unixoid_unselect_process;
3528 mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair; 2887 mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair;
3529 mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair; 2888 mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair;
3530 #else 2889 #else
3531 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; 2890 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process;
3532 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; 2891 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process;
3533 mswindows_event_stream->create_stream_pair_cb = emacs_mswindows_create_stream_pair; 2892 mswindows_event_stream->create_stream_pair_cb = emacs_mswindows_create_stream_pair;
3534 mswindows_event_stream->delete_stream_pair_cb = emacs_mswindows_delete_stream_pair; 2893 mswindows_event_stream->delete_stream_pair_cb = emacs_mswindows_delete_stream_pair;
3535 #endif 2894 #endif
3536 } 2895
3537 2896 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /*
3538 void
3539 vars_of_event_mswindows (void)
3540 {
3541 reinit_vars_of_event_mswindows ();
3542
3543 mswindows_u_dispatch_event_queue = Qnil;
3544 staticpro (&mswindows_u_dispatch_event_queue);
3545 mswindows_u_dispatch_event_queue_tail = Qnil;
3546 pdump_wire (&mswindows_u_dispatch_event_queue_tail);
3547
3548 mswindows_s_dispatch_event_queue = Qnil;
3549 staticpro (&mswindows_s_dispatch_event_queue);
3550 mswindows_s_dispatch_event_queue_tail = Qnil;
3551 pdump_wire (&mswindows_s_dispatch_event_queue_tail);
3552
3553 mswindows_error_caught_in_modal_loop = Qnil;
3554 staticpro (&mswindows_error_caught_in_modal_loop);
3555
3556
3557 #ifdef DEBUG_XEMACS
3558 DEFVAR_INT ("mswindows-debug-events", &mswindows_debug_events /*
3559 If non-zero, display debug information about Windows events that XEmacs sees.
3560 Information is displayed in a console window. Currently defined values are:
3561
3562 1 == non-verbose output
3563 2 == verbose output
3564
3565 #### Unfortunately, not yet implemented.
3566 */ );
3567 mswindows_debug_events = 0;
3568 #endif
3569
3570 DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu",
3571 &mswindows_alt_by_itself_activates_menu /*
3572 *Controls whether pressing and releasing the Alt key activates the menubar.
3573 This applies only if no intervening key was pressed. See also
3574 `menu-accelerator-enabled', which is probably the behavior you actually want.
3575 Default is t.
3576 */ );
3577
3578 DEFVAR_BOOL ("mswindows-dynamic-frame-resize",
3579 &mswindows_dynamic_frame_resize /*
3580 *Controls redrawing frame contents during mouse-drag or keyboard resize 2897 *Controls redrawing frame contents during mouse-drag or keyboard resize
3581 operation. When non-nil, the frame is redrawn while being resized. When 2898 operation. When non-nil, the frame is redrawn while being resized. When
3582 nil, frame is not redrawn, and exposed areas are filled with default 2899 nil, frame is not redrawn, and exposed areas are filled with default
3583 MDI application background color. Note that this option only has effect 2900 MDI application background color. Note that this option only has effect
3584 if "Show window contents while dragging" is on in system Display/Plus! 2901 if "Show window contents while dragging" is on in system Display/Plus!
3585 settings. 2902 settings.
3586 Default is t on fast machines, nil on slow. 2903 Default is t on fast machines, nil on slow.
3587 */ ); 2904 */ );
3588 2905
3589 DEFVAR_INT ("mswindows-mouse-button-tolerance", 2906 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */
3590 &mswindows_mouse_button_tolerance /* 2907 DEFVAR_INT ("mswindows-mouse-button-tolerance", &mswindows_mouse_button_tolerance /*
3591 *Analogue of double click interval for faking middle mouse events. 2908 *Analogue of double click interval for faking middle mouse events.
3592 The value is the minimum time in milliseconds that must elapse between 2909 The value is the minimum time in milliseconds that must elapse between
3593 left/right button down events before they are considered distinct events. 2910 left/right button down events before they are considered distinct events.
3594 If both mouse buttons are depressed within this interval, a middle mouse 2911 If both mouse buttons are depressed within this interval, a middle mouse
3595 button down event is generated instead. 2912 button down event is generated instead.
3596 If negative or zero, currently set system default is used instead. 2913 If negative or zero, currently set system default is used instead.
3597 */ ); 2914 */ );
3598 2915
2916 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */
3599 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /* 2917 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /*
3600 Number of physical mouse buttons. 2918 Number of physical mouse buttons.
3601 */ ); 2919 */ );
3602 2920
3603 DEFVAR_INT ("mswindows-mouse-button-max-skew-x", 2921 DEFVAR_INT ("mswindows-mouse-button-max-skew-x", &mswindows_mouse_button_max_skew_x /*
3604 &mswindows_mouse_button_max_skew_x /*
3605 *Maximum horizontal distance in pixels between points in which left and 2922 *Maximum horizontal distance in pixels between points in which left and
3606 right button clicks occurred for them to be translated into single 2923 right button clicks occurred for them to be translated into single
3607 middle button event. Clicks must occur in time not longer than defined 2924 middle button event. Clicks must occur in time not longer than defined
3608 by the variable `mswindows-mouse-button-tolerance'. 2925 by the variable `mswindows-mouse-button-tolerance'.
3609 If negative or zero, currently set system default is used instead. 2926 If negative or zero, currently set system default is used instead.
3610 */ ); 2927 */ );
3611 2928
3612 DEFVAR_INT ("mswindows-mouse-button-max-skew-y", 2929 DEFVAR_INT ("mswindows-mouse-button-max-skew-y", &mswindows_mouse_button_max_skew_y /*
3613 &mswindows_mouse_button_max_skew_y /*
3614 *Maximum vertical distance in pixels between points in which left and 2930 *Maximum vertical distance in pixels between points in which left and
3615 right button clicks occurred for them to be translated into single 2931 right button clicks occurred for them to be translated into single
3616 middle button event. Clicks must occur in time not longer than defined 2932 middle button event. Clicks must occur in time not longer than defined
3617 by the variable `mswindows-mouse-button-tolerance'. 2933 by the variable `mswindows-mouse-button-tolerance'.
3618 If negative or zero, currently set system default is used instead. 2934 If negative or zero, currently set system default is used instead.
3619 */ ); 2935 */ );
3620 2936
3621 mswindows_mouse_button_max_skew_x = 0; 2937 mswindows_mouse_button_max_skew_x = 0;
3622 mswindows_mouse_button_max_skew_y = 0; 2938 mswindows_mouse_button_max_skew_y = 0;
3623 mswindows_mouse_button_tolerance = 0; 2939 mswindows_mouse_button_tolerance = 0;
3624 mswindows_alt_by_itself_activates_menu = 1;
3625 } 2940 }
3626 2941
3627 void 2942 void
3628 syms_of_event_mswindows (void) 2943 syms_of_event_mswindows (void)
3629 { 2944 {