Mercurial > hg > xemacs-beta
comparison src/event-msw.c @ 771:943eaba38521
[xemacs-hg @ 2002-03-13 08:51:24 by ben]
The big ben-mule-21-5 check-in!
Various files were added and deleted. See CHANGES-ben-mule.
There are still some test suite failures. No crashes, though.
Many of the failures have to do with problems in the test suite itself
rather than in the actual code. I'll be addressing these in the next
day or so -- none of the test suite failures are at all critical.
Meanwhile I'll be trying to address the biggest issues -- i.e. build
or run failures, which will almost certainly happen on various platforms.
All comments should be sent to ben@xemacs.org -- use a Cc: if necessary
when sending to mailing lists. There will be pre- and post- tags,
something like
pre-ben-mule-21-5-merge-in, and
post-ben-mule-21-5-merge-in.
author | ben |
---|---|
date | Wed, 13 Mar 2002 08:54:06 +0000 |
parents | 46d76bae9921 |
children | 026c5bf9c134 |
comparison
equal
deleted
inserted
replaced
770:336a418893b5 | 771:943eaba38521 |
---|---|
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, 2001 Ben Wing. | 4 Copyright (C) 1996, 2000, 2001, 2002 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 |
20 along with XEmacs; see the file COPYING. If not, write to | 20 along with XEmacs; see the file COPYING. If not, write to |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
22 Boston, MA 02111-1307, USA. */ | 22 Boston, MA 02111-1307, USA. */ |
23 | 23 |
24 /* Synched up with: Not in FSF. */ | 24 /* Synched up with: Not in FSF. */ |
25 | |
26 /* This file essentially Mule-ized (except perhaps some Unicode splitting). | |
27 5-2000. */ | |
25 | 28 |
26 /* Authorship: | 29 /* Authorship: |
27 | 30 |
28 Ultimately based on FSF. | 31 Ultimately based on FSF. |
29 Rewritten by Ben Wing. | 32 Rewritten by Ben Wing. |
30 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0. | 33 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0. |
31 Subprocess and modal loop support by Kirill M. Katsnelson. | 34 Subprocess and modal loop support by Kirill M. Katsnelson. |
32 */ | 35 */ |
36 | |
37 #define NEED_MSWINDOWS_SHLOBJ /* for IShellLink */ | |
33 | 38 |
34 #include <config.h> | 39 #include <config.h> |
35 #include "lisp.h" | 40 #include "lisp.h" |
36 | 41 |
37 #include "console-msw.h" | 42 #include "console-msw.h" |
56 #include "frame.h" | 61 #include "frame.h" |
57 #include "lstream.h" | 62 #include "lstream.h" |
58 #include "objects-msw.h" | 63 #include "objects-msw.h" |
59 #include "process.h" | 64 #include "process.h" |
60 #include "redisplay.h" | 65 #include "redisplay.h" |
61 #include "select.h" | |
62 #include "sysdep.h" | 66 #include "sysdep.h" |
63 #include "window.h" | 67 #include "window.h" |
64 | 68 |
65 #include "sysfile.h" | 69 #include "sysfile.h" |
66 #include "sysproc.h" | 70 #include "sysproc.h" |
67 #include "systime.h" | 71 #include "systime.h" |
68 #include "syswait.h" | 72 #include "syswait.h" |
69 | 73 |
70 #ifdef HAVE_MSG_SELECT | 74 #ifdef HAVE_MSG_SELECT |
71 #include "console-tty.h" | 75 #include "console-tty.h" |
72 #elif defined(CYGWIN) | 76 #elif defined (CYGWIN) |
73 typedef unsigned int SOCKET; | 77 typedef unsigned int SOCKET; |
74 #endif | |
75 | |
76 #if !(defined(CYGWIN) || defined(MINGW)) | |
77 # include <shlobj.h> /* For IShellLink */ | |
78 #endif | 78 #endif |
79 | 79 |
80 #ifdef HAVE_MENUBARS | 80 #ifdef HAVE_MENUBARS |
81 #define ADJR_MENUFLAG TRUE | 81 #define ADJR_MENUFLAG TRUE |
82 #else | 82 #else |
92 #define BUTTON_2_TIMER_ID 1 | 92 #define BUTTON_2_TIMER_ID 1 |
93 | 93 |
94 static Lisp_Object mswindows_find_console (HWND hwnd); | 94 static Lisp_Object mswindows_find_console (HWND hwnd); |
95 static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, | 95 static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, |
96 int extendedp); | 96 int extendedp); |
97 static int mswindows_modifier_state (BYTE* keymap, DWORD fwKeys, | 97 static int mswindows_modifier_state (BYTE *keymap, DWORD fwKeys, |
98 int has_AltGr); | 98 int has_AltGr); |
99 static void mswindows_set_chord_timer (HWND hwnd); | 99 static void mswindows_set_chord_timer (HWND hwnd); |
100 static int mswindows_button2_near_enough (POINTS p1, POINTS p2); | 100 static int mswindows_button2_near_enough (POINTS p1, POINTS p2); |
101 static int mswindows_current_layout_has_AltGr (void); | 101 static int mswindows_current_layout_has_AltGr (void); |
102 static int mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam, | 102 static int mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam, |
210 shared_data_block[MAX_SLURP_STREAMS]={{0}}; | 210 shared_data_block[MAX_SLURP_STREAMS]={{0}}; |
211 | 211 |
212 struct ntpipe_slurp_stream | 212 struct ntpipe_slurp_stream |
213 { | 213 { |
214 LPARAM user_data; /* Any user data stored in the stream object */ | 214 LPARAM user_data; /* Any user data stored in the stream object */ |
215 struct ntpipe_slurp_stream_shared_data* thread_data; | 215 struct ntpipe_slurp_stream_shared_data *thread_data; |
216 }; | 216 }; |
217 | 217 |
218 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-input", lstream_ntpipe_slurp, | 218 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-input", ntpipe_slurp); |
219 sizeof (struct ntpipe_slurp_stream)); | |
220 | 219 |
221 /* This function is thread-safe, and is called from either thread | 220 /* This function is thread-safe, and is called from either thread |
222 context. It serializes freeing shared data structure */ | 221 context. It serializes freeing shared data structure */ |
223 static void | 222 static void |
224 slurper_free_shared_data_maybe (struct ntpipe_slurp_stream_shared_data* s) | 223 slurper_free_shared_data_maybe (struct ntpipe_slurp_stream_shared_data *s) |
225 { | 224 { |
226 if (InterlockedDecrement (&s->lock_count) == 0) | 225 if (InterlockedDecrement (&s->lock_count) == 0) |
227 { | 226 { |
228 /* Destroy events */ | 227 /* Destroy events */ |
229 CloseHandle (s->hev_thread); | 228 CloseHandle (s->hev_thread); |
232 CloseHandle (s->hpipe); | 231 CloseHandle (s->hpipe); |
233 s->inuse_p = 0; | 232 s->inuse_p = 0; |
234 } | 233 } |
235 } | 234 } |
236 | 235 |
237 static struct ntpipe_slurp_stream_shared_data* | 236 static struct ntpipe_slurp_stream_shared_data * |
238 slurper_allocate_shared_data (void) | 237 slurper_allocate_shared_data (void) |
239 { | 238 { |
240 int i=0; | 239 int i=0; |
241 for (i=0; i<MAX_SLURP_STREAMS; i++) | 240 for (i = 0; i < MAX_SLURP_STREAMS; i++) |
242 { | 241 { |
243 if (!shared_data_block[i].inuse_p) | 242 if (!shared_data_block[i].inuse_p) |
244 { | 243 { |
245 shared_data_block[i].inuse_p=1; | 244 shared_data_block[i].inuse_p = 1; |
246 return &shared_data_block[i]; | 245 return &shared_data_block[i]; |
247 } | 246 } |
248 } | 247 } |
249 return (struct ntpipe_slurp_stream_shared_data*)0; | 248 return (struct ntpipe_slurp_stream_shared_data *)0; |
250 } | 249 } |
251 | 250 |
252 static DWORD WINAPI | 251 static DWORD WINAPI |
253 slurp_thread (LPVOID vparam) | 252 slurp_thread (LPVOID vparam) |
254 { | 253 { |
255 struct ntpipe_slurp_stream_shared_data *s = | 254 struct ntpipe_slurp_stream_shared_data *s = |
256 (struct ntpipe_slurp_stream_shared_data*)vparam; | 255 (struct ntpipe_slurp_stream_shared_data *)vparam; |
257 | 256 |
258 for (;;) | 257 for (;;) |
259 { | 258 { |
260 /* Read one byte from the pipe */ | 259 /* Read one byte from the pipe */ |
261 DWORD actually_read; | 260 DWORD actually_read; |
307 static Lisp_Object | 306 static Lisp_Object |
308 make_ntpipe_input_stream (HANDLE hpipe, LPARAM param) | 307 make_ntpipe_input_stream (HANDLE hpipe, LPARAM param) |
309 { | 308 { |
310 Lisp_Object obj; | 309 Lisp_Object obj; |
311 Lstream *lstr = Lstream_new (lstream_ntpipe_slurp, "r"); | 310 Lstream *lstr = Lstream_new (lstream_ntpipe_slurp, "r"); |
312 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA (lstr); | 311 struct ntpipe_slurp_stream *s = NTPIPE_SLURP_STREAM_DATA (lstr); |
313 DWORD thread_id_unused; | 312 DWORD thread_id_unused; |
314 HANDLE hthread; | 313 HANDLE hthread; |
315 | 314 |
316 /* We deal only with pipes, for we're using PeekNamedPipe api */ | 315 /* We deal only with pipes, for we're using PeekNamedPipe api */ |
317 assert (GetFileType (hpipe) == FILE_TYPE_PIPE); | 316 assert (GetFileType (hpipe) == FILE_TYPE_PIPE); |
337 s->thread_data->error_p = FALSE; | 336 s->thread_data->error_p = FALSE; |
338 s->thread_data->hpipe = hpipe; | 337 s->thread_data->hpipe = hpipe; |
339 s->user_data = param; | 338 s->user_data = param; |
340 | 339 |
341 /* hev_thread is a manual-reset event, initially signaled */ | 340 /* hev_thread is a manual-reset event, initially signaled */ |
342 s->thread_data->hev_thread = CreateEvent (NULL, TRUE, TRUE, NULL); | 341 s->thread_data->hev_thread = qxeCreateEvent (NULL, TRUE, TRUE, NULL); |
343 /* hev_caller is a manual-reset event, initially nonsignaled */ | 342 /* hev_caller is a manual-reset event, initially nonsignaled */ |
344 s->thread_data->hev_caller = CreateEvent (NULL, TRUE, FALSE, NULL); | 343 s->thread_data->hev_caller = qxeCreateEvent (NULL, TRUE, FALSE, NULL); |
345 /* hev_unsleep is a manual-reset event, initially nonsignaled */ | 344 /* hev_unsleep is a manual-reset event, initially nonsignaled */ |
346 s->thread_data->hev_unsleep = CreateEvent (NULL, TRUE, FALSE, NULL); | 345 s->thread_data->hev_unsleep = qxeCreateEvent (NULL, TRUE, FALSE, NULL); |
347 | 346 |
348 /* Now let it go */ | 347 /* Now let it go */ |
349 ResumeThread (hthread); | 348 ResumeThread (hthread); |
350 CloseHandle (hthread); | 349 CloseHandle (hthread); |
351 | 350 |
355 } | 354 } |
356 | 355 |
357 static LPARAM | 356 static LPARAM |
358 get_ntpipe_input_stream_param (Lstream *stream) | 357 get_ntpipe_input_stream_param (Lstream *stream) |
359 { | 358 { |
360 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream); | 359 struct ntpipe_slurp_stream *s = NTPIPE_SLURP_STREAM_DATA(stream); |
361 return s->user_data; | 360 return s->user_data; |
362 } | 361 } |
363 | 362 |
364 static HANDLE | 363 static HANDLE |
365 get_ntpipe_input_stream_waitable (Lstream *stream) | 364 get_ntpipe_input_stream_waitable (Lstream *stream) |
366 { | 365 { |
367 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream); | 366 struct ntpipe_slurp_stream *s = NTPIPE_SLURP_STREAM_DATA(stream); |
368 return s->thread_data->hev_caller; | 367 return s->thread_data->hev_caller; |
369 } | 368 } |
370 | 369 |
371 static Bytecount | 370 static Bytecount |
372 ntpipe_slurp_reader (Lstream *stream, unsigned char *data, | 371 ntpipe_slurp_reader (Lstream *stream, unsigned char *data, |
373 Bytecount size) | 372 Bytecount size) |
374 { | 373 { |
375 /* This function must be called from the main thread only */ | 374 /* This function must be called from the main thread only */ |
376 struct ntpipe_slurp_stream_shared_data* s = | 375 struct ntpipe_slurp_stream_shared_data *s = |
377 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; | 376 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; |
378 | 377 |
379 if (!s->die_p) | 378 if (!s->die_p) |
380 { | 379 { |
381 DWORD wait_result; | 380 DWORD wait_result; |
382 /* Disallow pipe read delay for the thread: we need a character | 381 /* Disallow pipe read delay for the thread: we need a character |
383 ASAP */ | 382 ASAP */ |
384 SetEvent (s->hev_unsleep); | 383 SetEvent (s->hev_unsleep); |
385 | 384 |
386 /* Check if we have a character ready. Give it a short delay, | 385 /* Check if we have a character ready. Give it a short delay, |
387 for the thread to awake from pipe delay, just ion case*/ | 386 for the thread to awake from pipe delay, just ion case */ |
388 wait_result = WaitForSingleObject (s->hev_caller, 2); | 387 wait_result = WaitForSingleObject (s->hev_caller, 2); |
389 | 388 |
390 /* Revert to the normal sleep behavior. */ | 389 /* Revert to the normal sleep behavior. */ |
391 ResetEvent (s->hev_unsleep); | 390 ResetEvent (s->hev_unsleep); |
392 | 391 |
444 | 443 |
445 static int | 444 static int |
446 ntpipe_slurp_closer (Lstream *stream) | 445 ntpipe_slurp_closer (Lstream *stream) |
447 { | 446 { |
448 /* This function must be called from the main thread only */ | 447 /* This function must be called from the main thread only */ |
449 struct ntpipe_slurp_stream_shared_data* s = | 448 struct ntpipe_slurp_stream_shared_data *s = |
450 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; | 449 NTPIPE_SLURP_STREAM_DATA(stream)->thread_data; |
451 | 450 |
452 /* Force thread to stop */ | 451 /* Force thread to stop */ |
453 InterlockedIncrement (&s->die_p); | 452 InterlockedIncrement (&s->die_p); |
454 | 453 |
492 LONG idle_p; /* Non-zero if thread is waiting for job */ | 491 LONG idle_p; /* Non-zero if thread is waiting for job */ |
493 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ | 492 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ |
494 BOOL blocking_p : 1;/* Last write attempt would cause blocking */ | 493 BOOL blocking_p : 1;/* Last write attempt would cause blocking */ |
495 }; | 494 }; |
496 | 495 |
497 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove, | 496 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", ntpipe_shove); |
498 sizeof (struct ntpipe_shove_stream)); | |
499 | 497 |
500 #ifndef HAVE_MSG_SELECT | 498 #ifndef HAVE_MSG_SELECT |
501 static DWORD WINAPI | 499 static DWORD WINAPI |
502 shove_thread (LPVOID vparam) | 500 shove_thread (LPVOID vparam) |
503 { | 501 { |
504 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam; | 502 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream *) vparam; |
505 | 503 |
506 for (;;) | 504 for (;;) |
507 { | 505 { |
508 DWORD bytes_written; | 506 DWORD bytes_written; |
509 | 507 |
510 /* Block on event and wait for a job */ | 508 /* Block on event and wait for a job */ |
511 InterlockedIncrement (&s->idle_p); | 509 InterlockedIncrement (&s->idle_p); |
512 WaitForSingleObject (s->hev_thread, INFINITE); | 510 WaitForSingleObject (s->hev_thread, INFINITE); |
511 | |
512 if (s->die_p) | |
513 break; | |
513 | 514 |
514 /* Write passed buffer if any */ | 515 /* Write passed buffer if any */ |
515 if (s->size > 0) | 516 if (s->size > 0) |
516 { | 517 { |
517 if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL) | 518 if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL) |
535 static Lisp_Object | 536 static Lisp_Object |
536 make_ntpipe_output_stream (HANDLE hpipe, LPARAM param) | 537 make_ntpipe_output_stream (HANDLE hpipe, LPARAM param) |
537 { | 538 { |
538 Lisp_Object obj; | 539 Lisp_Object obj; |
539 Lstream *lstr = Lstream_new (lstream_ntpipe_shove, "w"); | 540 Lstream *lstr = Lstream_new (lstream_ntpipe_shove, "w"); |
540 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA (lstr); | 541 struct ntpipe_shove_stream *s = NTPIPE_SHOVE_STREAM_DATA (lstr); |
541 DWORD thread_id_unused; | 542 DWORD thread_id_unused; |
542 | 543 |
543 s->die_p = 0; | 544 s->die_p = 0; |
544 s->error_p = FALSE; | 545 s->error_p = FALSE; |
545 s->hpipe = hpipe; | 546 s->hpipe = hpipe; |
563 Lstream_delete (lstr); | 564 Lstream_delete (lstr); |
564 return Qnil; | 565 return Qnil; |
565 } | 566 } |
566 | 567 |
567 /* hev_thread is an auto-reset event, initially nonsignaled */ | 568 /* hev_thread is an auto-reset event, initially nonsignaled */ |
568 s->hev_thread = CreateEvent (NULL, FALSE, FALSE, NULL); | 569 s->hev_thread = qxeCreateEvent (NULL, FALSE, FALSE, NULL); |
569 | 570 |
570 /* Now let it go */ | 571 /* Now let it go */ |
571 ResumeThread (s->hthread); | 572 ResumeThread (s->hthread); |
572 | 573 |
573 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE; | 574 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE; |
576 } | 577 } |
577 | 578 |
578 static LPARAM | 579 static LPARAM |
579 get_ntpipe_output_stream_param (Lstream *stream) | 580 get_ntpipe_output_stream_param (Lstream *stream) |
580 { | 581 { |
581 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); | 582 struct ntpipe_shove_stream *s = NTPIPE_SHOVE_STREAM_DATA(stream); |
582 return s->user_data; | 583 return s->user_data; |
583 } | 584 } |
584 #endif | 585 #endif |
585 | 586 |
586 static Bytecount | 587 static Bytecount |
587 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, | 588 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, |
588 Bytecount size) | 589 Bytecount size) |
589 { | 590 { |
590 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); | 591 struct ntpipe_shove_stream *s = NTPIPE_SHOVE_STREAM_DATA(stream); |
591 | 592 |
592 if (s->error_p) | 593 if (s->error_p) |
593 return -1; | 594 return -1; |
594 | 595 |
595 s->blocking_p = !s->idle_p; | 596 s->blocking_p = !s->idle_p; |
605 /* Start output */ | 606 /* Start output */ |
606 InterlockedDecrement (&s->idle_p); | 607 InterlockedDecrement (&s->idle_p); |
607 SetEvent (s->hev_thread); | 608 SetEvent (s->hev_thread); |
608 /* Give it a chance to run -- this dramatically improves performance | 609 /* Give it a chance to run -- this dramatically improves performance |
609 of things like crypt. */ | 610 of things like crypt. */ |
610 if (xSwitchToThread) /* not in Win9x or NT 3.51 */ | 611 if (xSwitchToThread) /* not in Win9x */ |
611 (void) xSwitchToThread (); | 612 (void) xSwitchToThread (); |
612 return size; | 613 return size; |
613 } | 614 } |
614 | 615 |
615 static int | 616 static int |
616 ntpipe_shove_was_blocked_p (Lstream *stream) | 617 ntpipe_shove_was_blocked_p (Lstream *stream) |
617 { | 618 { |
618 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); | 619 struct ntpipe_shove_stream *s = NTPIPE_SHOVE_STREAM_DATA(stream); |
619 return s->blocking_p; | 620 return s->blocking_p; |
620 } | 621 } |
621 | 622 |
622 static int | 623 static int |
623 ntpipe_shove_closer (Lstream *stream) | 624 ntpipe_shove_closer (Lstream *stream) |
624 { | 625 { |
625 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); | 626 struct ntpipe_shove_stream *s = NTPIPE_SHOVE_STREAM_DATA(stream); |
626 | 627 |
627 /* Force thread stop */ | 628 /* Force thread stop */ |
628 InterlockedIncrement (&s->die_p); | 629 InterlockedIncrement (&s->die_p); |
630 | |
631 /* Close pipe handle, possibly breaking it */ | |
632 CloseHandle (s->hpipe); | |
629 | 633 |
630 /* Thread will end upon unblocking. If it's already unblocked this will | 634 /* Thread will end upon unblocking. If it's already unblocked this will |
631 do nothing, but the thread won't look at die_p until it's written any | 635 do nothing, but the thread won't look at die_p until it's written any |
632 pending output. */ | 636 pending output. */ |
633 SetEvent (s->hev_thread); | 637 SetEvent (s->hev_thread); |
634 | 638 |
635 /* Wait while thread terminates */ | 639 /* Wait while thread terminates */ |
636 WaitForSingleObject (s->hthread, INFINITE); | 640 WaitForSingleObject (s->hthread, INFINITE); |
637 | |
638 /* Close pipe handle, possibly breaking it */ | |
639 CloseHandle (s->hpipe); | |
640 | 641 |
641 /* Close the thread handle */ | 642 /* Close the thread handle */ |
642 CloseHandle (s->hthread); | 643 CloseHandle (s->hthread); |
643 | 644 |
644 /* Destroy the event */ | 645 /* Destroy the event */ |
676 unsigned int blocking_p :1; /* Last write attempt would block */ | 677 unsigned int blocking_p :1; /* Last write attempt would block */ |
677 }; | 678 }; |
678 | 679 |
679 #define WINSOCK_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, winsock) | 680 #define WINSOCK_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, winsock) |
680 | 681 |
681 DEFINE_LSTREAM_IMPLEMENTATION ("winsock", lstream_winsock, | 682 DEFINE_LSTREAM_IMPLEMENTATION ("winsock", winsock); |
682 sizeof (struct winsock_stream)); | |
683 | 683 |
684 static void | 684 static void |
685 winsock_initiate_read (struct winsock_stream *str) | 685 winsock_initiate_read (struct winsock_stream *str) |
686 { | 686 { |
687 ResetEvent (str->ov.hEvent); | 687 ResetEvent (str->ov.hEvent); |
735 if (str->error_p) | 735 if (str->error_p) |
736 return -1; | 736 return -1; |
737 | 737 |
738 /* Return as much of buffer as we have */ | 738 /* Return as much of buffer as we have */ |
739 size = min (size, (Bytecount) (str->bufsize - str->charbpos)); | 739 size = min (size, (Bytecount) (str->bufsize - str->charbpos)); |
740 memcpy (data, (void*)((BYTE*)str->buffer + str->charbpos), size); | 740 memcpy (data, (void *) ((BYTE *) str->buffer + str->charbpos), size); |
741 str->charbpos += size; | 741 str->charbpos += size; |
742 | 742 |
743 /* Read more if buffer is exhausted */ | 743 /* Read more if buffer is exhausted */ |
744 if (str->bufsize == str->charbpos) | 744 if (str->bufsize == str->charbpos) |
745 winsock_initiate_read (str); | 745 winsock_initiate_read (str); |
839 | 839 |
840 xzero (*str); | 840 xzero (*str); |
841 str->s = s; | 841 str->s = s; |
842 str->user_data = param; | 842 str->user_data = param; |
843 | 843 |
844 str->ov.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); | 844 str->ov.hEvent = qxeCreateEvent (NULL, TRUE, FALSE, NULL); |
845 | 845 |
846 if (lstr->flags & LSTREAM_FL_READ) | 846 if (lstr->flags & LSTREAM_FL_READ) |
847 { | 847 { |
848 str->buffer = xmalloc (WINSOCK_READ_BUFFER_SIZE); | 848 str->buffer = xmalloc (WINSOCK_READ_BUFFER_SIZE); |
849 winsock_initiate_read (str); | 849 winsock_initiate_read (str); |
893 /************************************************************************/ | 893 /************************************************************************/ |
894 /* Dispatch queue management */ | 894 /* Dispatch queue management */ |
895 /************************************************************************/ | 895 /************************************************************************/ |
896 | 896 |
897 static int | 897 static int |
898 mswindows_user_event_p (Lisp_Event* sevt) | 898 mswindows_user_event_p (Lisp_Event *sevt) |
899 { | 899 { |
900 return (sevt->event_type == key_press_event | 900 return (sevt->event_type == key_press_event |
901 || sevt->event_type == button_press_event | 901 || sevt->event_type == button_press_event |
902 || sevt->event_type == button_release_event | 902 || sevt->event_type == button_release_event |
903 || sevt->event_type == misc_user_event); | 903 || sevt->event_type == misc_user_event); |
915 &mswindows_s_dispatch_event_queue, | 915 &mswindows_s_dispatch_event_queue, |
916 user_p ? &mswindows_u_dispatch_event_queue_tail : | 916 user_p ? &mswindows_u_dispatch_event_queue_tail : |
917 &mswindows_s_dispatch_event_queue_tail); | 917 &mswindows_s_dispatch_event_queue_tail); |
918 | 918 |
919 /* Avoid blocking on WaitMessage */ | 919 /* Avoid blocking on WaitMessage */ |
920 PostMessage (NULL, XM_BUMPQUEUE, 0, 0); | 920 qxePostMessage (NULL, XM_BUMPQUEUE, 0, 0); |
921 } | 921 } |
922 | 922 |
923 /* | 923 /* |
924 * Add a misc-user event to the dispatch queue. | 924 * Add a misc-user event to the dispatch queue. |
925 * | 925 * |
929 void | 929 void |
930 mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function, | 930 mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function, |
931 Lisp_Object object) | 931 Lisp_Object object) |
932 { | 932 { |
933 Lisp_Object event = Fmake_event (Qnil, Qnil); | 933 Lisp_Object event = Fmake_event (Qnil, Qnil); |
934 Lisp_Event* e = XEVENT (event); | 934 Lisp_Event *e = XEVENT (event); |
935 | 935 |
936 e->event_type = misc_user_event; | 936 e->event_type = misc_user_event; |
937 e->channel = channel; | 937 e->channel = channel; |
938 e->timestamp = GetTickCount (); | 938 e->timestamp = GetTickCount (); |
939 e->event.misc.function = function; | 939 e->event.misc.function = function; |
944 | 944 |
945 void | 945 void |
946 mswindows_enqueue_magic_event (HWND hwnd, UINT msg) | 946 mswindows_enqueue_magic_event (HWND hwnd, UINT msg) |
947 { | 947 { |
948 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 948 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
949 Lisp_Event* event = XEVENT (emacs_event); | 949 Lisp_Event *event = XEVENT (emacs_event); |
950 | 950 |
951 event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil; | 951 event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil; |
952 event->timestamp = GetMessageTime(); | 952 event->timestamp = GetMessageTime(); |
953 event->event_type = magic_event; | 953 event->event_type = magic_event; |
954 EVENT_MSWINDOWS_MAGIC_TYPE (event) = msg; | 954 EVENT_MSWINDOWS_MAGIC_TYPE (event) = msg; |
955 | 955 |
956 mswindows_enqueue_dispatch_event (emacs_event); | 956 mswindows_enqueue_dispatch_event (emacs_event); |
957 } | 957 } |
958 | 958 |
959 static void | 959 static void |
960 mswindows_enqueue_process_event (Lisp_Process* p) | 960 mswindows_enqueue_process_event (Lisp_Process *p) |
961 { | 961 { |
962 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 962 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
963 Lisp_Event* event = XEVENT (emacs_event); | 963 Lisp_Event *event = XEVENT (emacs_event); |
964 Lisp_Object process; | 964 Lisp_Object process; |
965 XSETPROCESS (process, p); | 965 XSETPROCESS (process, p); |
966 | 966 |
967 event->event_type = process_event; | 967 event->event_type = process_event; |
968 event->timestamp = GetTickCount (); | 968 event->timestamp = GetTickCount (); |
981 /* We always use last message time, because mouse button | 981 /* We always use last message time, because mouse button |
982 events may get delayed, and XEmacs double click | 982 events may get delayed, and XEmacs double click |
983 recognition will fail */ | 983 recognition will fail */ |
984 | 984 |
985 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 985 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
986 Lisp_Event* event = XEVENT (emacs_event); | 986 Lisp_Event *event = XEVENT (emacs_event); |
987 | 987 |
988 mswindows_handle_sticky_modifiers (0, 0, downp, 0); | 988 mswindows_handle_sticky_modifiers (0, 0, downp, 0); |
989 event->channel = mswindows_find_frame (hwnd); | 989 event->channel = mswindows_find_frame (hwnd); |
990 event->timestamp = when; | 990 event->timestamp = when; |
991 event->event.button.button = | 991 event->event.button.button = |
1014 } | 1014 } |
1015 | 1015 |
1016 mswindows_enqueue_dispatch_event (emacs_event); | 1016 mswindows_enqueue_dispatch_event (emacs_event); |
1017 } | 1017 } |
1018 | 1018 |
1019 static void | 1019 static Lisp_Object |
1020 mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods) | 1020 mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods) |
1021 { | 1021 { |
1022 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 1022 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
1023 Lisp_Event* event = XEVENT(emacs_event); | 1023 Lisp_Event *event = XEVENT(emacs_event); |
1024 | 1024 |
1025 event->channel = mswindows_find_console(hwnd); | 1025 event->channel = mswindows_find_console(hwnd); |
1026 event->timestamp = GetMessageTime(); | 1026 event->timestamp = GetMessageTime(); |
1027 event->event_type = key_press_event; | 1027 event->event_type = key_press_event; |
1028 event->event.key.keysym = keysym; | 1028 event->event.key.keysym = keysym; |
1029 event->event.key.modifiers = mods; | 1029 event->event.key.modifiers = mods; |
1030 mswindows_enqueue_dispatch_event (emacs_event); | 1030 mswindows_enqueue_dispatch_event (emacs_event); |
1031 return emacs_event; | |
1031 } | 1032 } |
1032 | 1033 |
1033 /* | 1034 /* |
1034 * Remove and return the first emacs event on the dispatch queue. | 1035 * Remove and return the first emacs event on the dispatch queue. |
1035 * Give a preference to user events over non-user ones. | 1036 * Give a preference to user events over non-user ones. |
1036 */ | 1037 */ |
1037 static Lisp_Object | 1038 static Lisp_Object |
1038 mswindows_dequeue_dispatch_event (void) | 1039 mswindows_dequeue_dispatch_event (void) |
1039 { | 1040 { |
1040 Lisp_Object event; | 1041 Lisp_Object event; |
1041 Lisp_Event* sevt; | 1042 Lisp_Event *sevt; |
1042 | 1043 |
1043 assert (!NILP(mswindows_u_dispatch_event_queue) || | 1044 assert (!NILP(mswindows_u_dispatch_event_queue) || |
1044 !NILP(mswindows_s_dispatch_event_queue)); | 1045 !NILP(mswindows_s_dispatch_event_queue)); |
1045 | 1046 |
1046 event = dequeue_event ( | 1047 event = dequeue_event ( |
1073 mswindows_cancel_dispatch_event (Lisp_Event *match) | 1074 mswindows_cancel_dispatch_event (Lisp_Event *match) |
1074 { | 1075 { |
1075 Lisp_Object event; | 1076 Lisp_Object event; |
1076 Lisp_Object previous_event = Qnil; | 1077 Lisp_Object previous_event = Qnil; |
1077 int user_p = mswindows_user_event_p (match); | 1078 int user_p = mswindows_user_event_p (match); |
1078 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : | 1079 Lisp_Object *head = user_p ? &mswindows_u_dispatch_event_queue : |
1079 &mswindows_s_dispatch_event_queue; | 1080 &mswindows_s_dispatch_event_queue; |
1080 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : | 1081 Lisp_Object *tail = user_p ? &mswindows_u_dispatch_event_queue_tail : |
1081 &mswindows_s_dispatch_event_queue_tail; | 1082 &mswindows_s_dispatch_event_queue_tail; |
1082 | 1083 |
1083 assert (match->event_type == timeout_event | 1084 assert (match->event_type == timeout_event |
1084 || match->event_type == key_press_event); | 1085 || match->event_type == key_press_event); |
1085 | 1086 |
1148 | 1149 |
1149 | 1150 |
1150 /************************************************************************/ | 1151 /************************************************************************/ |
1151 /* Event pump */ | 1152 /* Event pump */ |
1152 /************************************************************************/ | 1153 /************************************************************************/ |
1154 | |
1155 int | |
1156 mswindows_window_is_xemacs (HWND hwnd) | |
1157 { | |
1158 /* GetClassName will truncate a longer class name. By adding one | |
1159 extra character, we are forcing textual comparison to fail | |
1160 if the name is longer than XEMACS_CLASS */ | |
1161 Extbyte class_name_buf[sizeof (XEMACS_CLASS) + 2]; | |
1162 | |
1163 /* Use GetClassNameA because XEMACS_CLASS is not in Unicode format. */ | |
1164 if (!GetClassNameA (hwnd, class_name_buf, sizeof (class_name_buf) - 1)) | |
1165 return 0; | |
1166 | |
1167 return !ascii_strcasecmp (class_name_buf, XEMACS_CLASS); | |
1168 } | |
1153 | 1169 |
1154 static Lisp_Object | 1170 static Lisp_Object |
1155 mswindows_modal_loop_error_handler (Lisp_Object cons_sig_data, | 1171 mswindows_modal_loop_error_handler (Lisp_Object cons_sig_data, |
1156 Lisp_Object u_n_u_s_e_d) | 1172 Lisp_Object u_n_u_s_e_d) |
1157 { | 1173 { |
1278 MSG msg; | 1294 MSG msg; |
1279 | 1295 |
1280 /* should call mswindows_need_event_in_modal_loop() if in modal loop */ | 1296 /* should call mswindows_need_event_in_modal_loop() if in modal loop */ |
1281 assert (!mswindows_in_modal_loop); | 1297 assert (!mswindows_in_modal_loop); |
1282 | 1298 |
1283 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) | 1299 while (qxePeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) |
1284 { | 1300 { |
1285 char class_name_buf [sizeof (XEMACS_CLASS) + 2] = ""; | 1301 #ifdef HAVE_DIALOGS |
1286 | |
1287 /* Don't translate messages destined for a dialog box, this | 1302 /* Don't translate messages destined for a dialog box, this |
1288 makes keyboard traversal work. I think?? */ | 1303 makes keyboard traversal work. I think?? */ |
1289 if (mswindows_is_dialog_msg (&msg)) | 1304 if (mswindows_is_dialog_msg (&msg)) |
1290 { | 1305 { |
1291 mswindows_unmodalize_signal_maybe (); | 1306 mswindows_unmodalize_signal_maybe (); |
1292 continue; | 1307 continue; |
1293 } | 1308 } |
1309 #endif /* HAVE_DIALOGS */ | |
1294 | 1310 |
1295 /* We have to translate messages that are not sent to an XEmacs | 1311 /* We have to translate messages that are not sent to an XEmacs |
1296 frame. This is so that key presses work ok in things like | 1312 frame. This is so that key presses work ok in things like |
1297 edit fields. However, we *musn't* translate message for XEmacs | 1313 edit fields. However, we *musn't* translate message for XEmacs |
1298 frames as this is handled in the wnd proc. | 1314 frames as this is handled in the wnd proc. |
1299 We also have to avoid generating paint magic events for windows | 1315 We also have to avoid generating paint magic events for windows |
1300 that aren't XEmacs frames */ | 1316 that aren't XEmacs frames */ |
1301 /* GetClassName will truncate a longer class name. By adding one | 1317 |
1302 extra character, we are forcing textual comparison to fail | 1318 if (!mswindows_window_is_xemacs (msg.hwnd)) |
1303 if the name is longer than XEMACS_CLASS */ | 1319 TranslateMessage (&msg); |
1304 | |
1305 GetClassName (msg.hwnd, class_name_buf, sizeof (class_name_buf) - 1); | |
1306 if (stricmp (class_name_buf, XEMACS_CLASS) != 0) | |
1307 { | |
1308 /* Not an XEmacs frame */ | |
1309 TranslateMessage (&msg); | |
1310 } | |
1311 else if (msg.message == WM_PAINT) | 1320 else if (msg.message == WM_PAINT) |
1312 { | 1321 { |
1313 struct mswindows_frame* msframe; | 1322 struct mswindows_frame *msframe; |
1314 | 1323 |
1315 /* hdc will be NULL unless this is a subwindow - in which case we | 1324 /* hdc will be NULL unless this is a subwindow - in which case we |
1316 shouldn't have received a paint message for it here. */ | 1325 shouldn't have received a paint message for it here. */ |
1317 assert (msg.wParam == 0); | 1326 assert (msg.wParam == 0); |
1318 | 1327 |
1319 /* Queue a magic event for handling when safe */ | 1328 /* Queue a magic event for handling when safe */ |
1326 } | 1335 } |
1327 /* Don't dispatch. WM_PAINT is always the last message in the | 1336 /* Don't dispatch. WM_PAINT is always the last message in the |
1328 queue so it's OK to just return. */ | 1337 queue so it's OK to just return. */ |
1329 return; | 1338 return; |
1330 } | 1339 } |
1331 DispatchMessage (&msg); | 1340 qxeDispatchMessage (&msg); |
1332 mswindows_unmodalize_signal_maybe (); | 1341 mswindows_unmodalize_signal_maybe (); |
1333 } | 1342 } |
1334 } | 1343 } |
1335 | 1344 |
1336 /* | 1345 /* |
1370 /* We'll deadlock if go waiting */ | 1379 /* We'll deadlock if go waiting */ |
1371 if (mswindows_pending_timers_count == 0) | 1380 if (mswindows_pending_timers_count == 0) |
1372 invalid_operation ("Deadlock due to an attempt to call next-event in a wrong context", Qunbound); | 1381 invalid_operation ("Deadlock due to an attempt to call next-event in a wrong context", Qunbound); |
1373 | 1382 |
1374 /* Fetch and dispatch any pending timers */ | 1383 /* Fetch and dispatch any pending timers */ |
1375 if (GetMessage (&msg, NULL, WM_TIMER, WM_TIMER) > 0) | 1384 if (qxeGetMessage (&msg, NULL, WM_TIMER, WM_TIMER) > 0) |
1376 DispatchMessage (&msg); | 1385 qxeDispatchMessage (&msg); |
1377 } | 1386 } |
1378 } | 1387 } |
1379 | 1388 |
1380 /* | 1389 /* |
1381 * This drains the event queue and fills up two internal queues until | 1390 * This drains the event queue and fills up two internal queues until |
1437 user events ahead of process events. */ | 1446 user events ahead of process events. */ |
1438 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) | 1447 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) |
1439 { | 1448 { |
1440 struct console *c = tty_find_console_from_fd (i); | 1449 struct console *c = tty_find_console_from_fd (i); |
1441 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 1450 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
1442 Lisp_Event* event = XEVENT (emacs_event); | 1451 Lisp_Event *event = XEVENT (emacs_event); |
1443 | 1452 |
1444 assert (c); | 1453 assert (c); |
1445 if (read_event_from_tty_or_stream_desc (event, c, i)) | 1454 if (read_event_from_tty_or_stream_desc (event, c)) |
1446 { | 1455 { |
1447 mswindows_enqueue_dispatch_event (emacs_event); | 1456 mswindows_enqueue_dispatch_event (emacs_event); |
1448 return; | 1457 return; |
1449 } | 1458 } |
1450 } | 1459 } |
1473 } | 1482 } |
1474 } | 1483 } |
1475 } | 1484 } |
1476 } | 1485 } |
1477 } | 1486 } |
1478 else if (active==-1) | 1487 else if (active == -1) |
1479 { | 1488 { |
1480 if (errno != EINTR) | 1489 if (errno != EINTR) |
1481 { | 1490 { |
1482 /* something bad happened */ | 1491 /* something bad happened */ |
1483 assert(0); | 1492 assert(0); |
1502 } | 1511 } |
1503 else | 1512 else |
1504 /* Look for any event */ | 1513 /* Look for any event */ |
1505 what_events = QS_ALLINPUT; | 1514 what_events = QS_ALLINPUT; |
1506 | 1515 |
1516 /* | |
1517 #### YUCK YUCK YUCK!!!! | |
1518 | |
1519 When running under a debugger, every time I hit F12 (which for me | |
1520 is mapped to right-brace) I hit a breakpoint inside of Windows! | |
1521 | |
1522 NTDLL! DbgBreakPoint@0 address 0x77f9eea9 | |
1523 KERNEL32! BaseAttachComplete@4 + 41 bytes | |
1524 KERNEL32! BaseAttachCompleteThunk@0 + 19 bytes | |
1525 USER32! MsgWaitForMultipleObjectsEx@20 + 224 bytes | |
1526 USER32! MsgWaitForMultipleObjects@20 + 30 bytes | |
1527 | |
1528 Microsoft says: | |
1529 | |
1530 (Knowledge Base Q130667, PRB: F12 Causes Hard-Coded Breakpoint | |
1531 Exception When Debugging) | |
1532 | |
1533 CAUSE | |
1534 | |
1535 When the F12 key is pressed and the application in focus is being | |
1536 debugged, Windows NT calls a function similar to DebugBreak(), | |
1537 which executes a hard coded breakpoint instruction. The integrated | |
1538 debugger then traps the exception generated by this instruction. | |
1539 | |
1540 This behavior is intentional and occurs with other debuggers such | |
1541 as WinDbg from the Windows 32-bit SDK. | |
1542 | |
1543 RESOLUTION | |
1544 | |
1545 While there is no way to disable this functionality, it doesn't | |
1546 affect the application that's being debugged other than to pause | |
1547 debugging and change focus. You can continue debugging by pressing | |
1548 the F5 key. | |
1549 | |
1550 This can be annoying if you have an application that heavily uses | |
1551 the F12 key, so you may want to temporarily assign another key to | |
1552 handle the F12 key functionality in your program when debugging. | |
1553 | |
1554 STATUS | |
1555 | |
1556 This behavior is by design. | |
1557 | |
1558 | |
1559 However, elsewhere I found this: | |
1560 | |
1561 UserDebuggerHotKey | |
1562 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug | |
1563 | |
1564 Data type Range Default value | |
1565 REG_DWORD 0x0 - 0xFF 0x0 | |
1566 | |
1567 Description | |
1568 | |
1569 Specifies the key that, when pressed, establishes a breakpoint in | |
1570 code being debugged. | |
1571 | |
1572 The debugger interrupts code processing at the breakpoint so the | |
1573 programmer can examine a suspected problem. | |
1574 | |
1575 The key specified in this value only sets a breakpoint. It does | |
1576 not invoke the debugger (the debugger must be running before the | |
1577 key is pressed) and it does not switch the debugger to single-step | |
1578 mode. | |
1579 | |
1580 The value of this entry is a keyboard scan code. The default | |
1581 value, 0x0, represents the F12 key on a 101-key keyboard or the - | |
1582 (hyphen, VK_SUBTRACT) key on an 82-key keyboard. | |
1583 */ | |
1584 | |
1585 __try | |
1586 { | |
1507 active = MsgWaitForMultipleObjects (mswindows_waitable_count, | 1587 active = MsgWaitForMultipleObjects (mswindows_waitable_count, |
1508 mswindows_waitable_handles, | 1588 mswindows_waitable_handles, |
1509 FALSE, badly_p ? INFINITE : 0, | 1589 FALSE, badly_p ? INFINITE : 0, |
1510 what_events); | 1590 what_events); |
1591 } | |
1592 __except (GetExceptionCode () == EXCEPTION_BREAKPOINT ? | |
1593 EXCEPTION_CONTINUE_EXECUTION : | |
1594 EXCEPTION_CONTINUE_SEARCH) | |
1595 { | |
1596 } | |
1511 | 1597 |
1512 /* This will assert if handle being waited for becomes abandoned. | 1598 /* This will assert if handle being waited for becomes abandoned. |
1513 Not the case currently tho */ | 1599 Not the case currently tho */ |
1514 assert ((!badly_p && active == WAIT_TIMEOUT) || | 1600 assert ((!badly_p && active == WAIT_TIMEOUT) || |
1515 (active >= WAIT_OBJECT_0 && | 1601 (active >= WAIT_OBJECT_0 && |
1623 return (HDDEDATA)FALSE; | 1709 return (HDDEDATA)FALSE; |
1624 | 1710 |
1625 case XTYP_WILDCONNECT: | 1711 case XTYP_WILDCONNECT: |
1626 { | 1712 { |
1627 /* We only support one {service,topic} pair */ | 1713 /* We only support one {service,topic} pair */ |
1628 HSZPAIR pairs[2] = { | 1714 HSZPAIR pairs[2] = |
1715 { | |
1629 { mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } }; | 1716 { mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } }; |
1630 | 1717 |
1631 if (!(hszItem || DdeCmpStringHandles (hszItem, mswindows_dde_service)) && | 1718 if (!(hszItem |
1632 !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))) | 1719 || DdeCmpStringHandles (hszItem, mswindows_dde_service)) && |
1720 !(hszTopic | |
1721 || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))) | |
1633 return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs, | 1722 return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs, |
1634 sizeof (pairs), 0L, 0, uFmt, 0)); | 1723 sizeof (pairs), 0L, 0, uFmt, 0)); |
1635 } | 1724 } |
1636 return (HDDEDATA)NULL; | 1725 return (HDDEDATA)NULL; |
1637 | 1726 |
1640 return (HDDEDATA) DDE_FBUSY; | 1729 return (HDDEDATA) DDE_FBUSY; |
1641 | 1730 |
1642 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)) | 1731 if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)) |
1643 { | 1732 { |
1644 DWORD len = DdeGetData (hdata, NULL, 0, 0); | 1733 DWORD len = DdeGetData (hdata, NULL, 0, 0); |
1645 LPBYTE cmd = (LPBYTE) alloca (len+1); | 1734 LPBYTE extcmd = (LPBYTE) alloca (len+1); |
1646 char *end; | 1735 Intbyte *cmd; |
1647 char *filename; | 1736 Intbyte *end; |
1648 struct gcpro gcpro1, gcpro2; | 1737 struct gcpro gcpro1, gcpro2; |
1649 Lisp_Object l_dndlist = Qnil; | 1738 Lisp_Object l_dndlist = Qnil; |
1650 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 1739 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
1651 Lisp_Object frmcons, devcons, concons; | 1740 Lisp_Object frmcons, devcons, concons; |
1652 Lisp_Event *event = XEVENT (emacs_event); | 1741 Lisp_Event *event = XEVENT (emacs_event); |
1653 | 1742 |
1654 DdeGetData (hdata, cmd, len, 0); | 1743 DdeGetData (hdata, extcmd, len, 0); |
1655 cmd[len] = '\0'; | |
1656 DdeFreeDataHandle (hdata); | 1744 DdeFreeDataHandle (hdata); |
1745 | |
1746 TO_INTERNAL_FORMAT (DATA, (extcmd, len), | |
1747 C_STRING_ALLOCA, cmd, | |
1748 Qmswindows_tstr); | |
1657 | 1749 |
1658 /* Check syntax & that it's an [Open("foo")] command, which we | 1750 /* Check syntax & that it's an [Open("foo")] command, which we |
1659 * treat like a file drop */ | 1751 * treat like a file drop */ |
1660 /* #### Ought to be generalised and accept some other commands */ | 1752 /* #### Ought to be generalised and accept some other commands */ |
1661 if (*cmd == '[') | 1753 if (*cmd == '[') |
1662 cmd++; | 1754 cmd++; |
1663 if (strnicmp (cmd, MSWINDOWS_DDE_ITEM_OPEN, | 1755 if (qxestrncasecmp_c (cmd, MSWINDOWS_DDE_ITEM_OPEN, |
1664 strlen (MSWINDOWS_DDE_ITEM_OPEN))) | 1756 strlen (MSWINDOWS_DDE_ITEM_OPEN))) |
1665 return DDE_FNOTPROCESSED; | 1757 return DDE_FNOTPROCESSED; |
1666 cmd += strlen (MSWINDOWS_DDE_ITEM_OPEN); | 1758 cmd += strlen (MSWINDOWS_DDE_ITEM_OPEN); |
1667 while (*cmd==' ') | 1759 while (*cmd == ' ') |
1668 cmd++; | 1760 cmd++; |
1669 if (*cmd!='(' || *(cmd+1)!='\"') | 1761 if (*cmd != '(' || *(cmd + 1) != '\"') |
1670 return DDE_FNOTPROCESSED; | 1762 return DDE_FNOTPROCESSED; |
1671 end = (cmd+=2); | 1763 end = (cmd += 2); |
1672 while (*end && *end!='\"') | 1764 while (*end && *end != '\"') |
1673 end++; | 1765 end++; |
1674 if (!*end) | 1766 if (!*end) |
1675 return DDE_FNOTPROCESSED; | 1767 return DDE_FNOTPROCESSED; |
1676 *end = '\0'; | 1768 *end = '\0'; |
1677 if (*(++end)!=')') | 1769 if (*++end != ')') |
1678 return DDE_FNOTPROCESSED; | 1770 return DDE_FNOTPROCESSED; |
1679 if (*(++end)==']') | 1771 if (*++end == ']') |
1680 end++; | 1772 end++; |
1681 if (*end) | 1773 if (*end) |
1682 return DDE_FNOTPROCESSED; | 1774 return DDE_FNOTPROCESSED; |
1683 | 1775 |
1684 #ifdef CYGWIN | 1776 { |
1685 filename = alloca (cygwin_win32_to_posix_path_list_buf_size (cmd) + 5); | 1777 /* The drag-n-drop code in dragdrop.el expects pseudo-URL's, |
1686 strcpy (filename, "file:"); | 1778 consisting of just file: followed by the filename. This |
1687 cygwin_win32_to_posix_path_list (cmd, filename+5); | 1779 should maybe work, but both Netscape and IE complain |
1688 #else | 1780 whenever they're not given the full file spec, like |
1689 dostounix_filename (cmd); | 1781 |
1690 filename = alloca (strlen (cmd)+6); | 1782 file:///C|/foo/bar/ or equivalently |
1691 strcpy (filename, "file:"); | 1783 file:///C:/foo/bar/ (less portably) |
1692 strcat (filename, cmd); | 1784 |
1693 #endif | 1785 they don't allow relative paths at all! this is way bogus. */ |
1786 cmd = urlify_filename (cmd); | |
1787 l_dndlist = build_intstring (cmd); | |
1788 xfree (cmd); | |
1789 } | |
1694 GCPRO2 (emacs_event, l_dndlist); | 1790 GCPRO2 (emacs_event, l_dndlist); |
1695 l_dndlist = make_string (filename, strlen (filename)); | |
1696 | 1791 |
1697 /* Find a mswindows frame */ | 1792 /* Find a mswindows frame */ |
1698 event->channel = Qnil; | 1793 event->channel = Qnil; |
1699 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | 1794 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
1700 { | 1795 { |
2074 #ifdef DEBUG_XEMACS | 2169 #ifdef DEBUG_XEMACS |
2075 if (debug_mswindows_events) | 2170 if (debug_mswindows_events) |
2076 debug_output_mswin_message (hwnd, message_, wParam, lParam); | 2171 debug_output_mswin_message (hwnd, message_, wParam, lParam); |
2077 #endif /* DEBUG_XEMACS */ | 2172 #endif /* DEBUG_XEMACS */ |
2078 | 2173 |
2079 assert (!GetWindowLong (hwnd, GWL_USERDATA)); | 2174 assert (!qxeGetWindowLong (hwnd, GWL_USERDATA)); |
2080 switch (message_) | 2175 switch (message_) |
2081 { | 2176 { |
2082 case WM_DESTROYCLIPBOARD: | 2177 case WM_DESTROYCLIPBOARD: |
2083 /* We own the clipboard and someone else wants it. Delete our | 2178 mswindows_handle_destroyclipboard (); |
2084 cached copy of the clipboard contents so we'll ask for it from | |
2085 Windows again when someone does a paste, and destroy any memory | |
2086 objects we hold on the clipboard that are not in the list of types | |
2087 that Windows will delete itself. */ | |
2088 mswindows_destroy_selection (QCLIPBOARD); | |
2089 handle_selection_clear (QCLIPBOARD); | |
2090 break; | 2179 break; |
2091 | 2180 |
2092 case WM_ERASEBKGND: | 2181 case WM_ERASEBKGND: |
2093 /* Erase background only during non-dynamic sizing */ | 2182 /* Erase background only during non-dynamic sizing */ |
2094 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2183 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2095 if (msframe->sizing && !mswindows_dynamic_frame_resize) | 2184 if (msframe->sizing && !mswindows_dynamic_frame_resize) |
2096 goto defproc; | 2185 goto defproc; |
2097 return 1; | 2186 return 1; |
2098 | 2187 |
2099 case WM_CLOSE: | 2188 case WM_CLOSE: |
2153 * calling TranslateMessage() unless AltGr is *really* down. */ | 2242 * calling TranslateMessage() unless AltGr is *really* down. */ |
2154 { | 2243 { |
2155 BYTE keymap_trans[256]; | 2244 BYTE keymap_trans[256]; |
2156 BYTE keymap_orig[256]; | 2245 BYTE keymap_orig[256]; |
2157 BYTE keymap_sticky[256]; | 2246 BYTE keymap_sticky[256]; |
2247 /* WARNING: XEmacs code paths are far more subtle than you | |
2248 think. In particular, QUIT checking will query and remove | |
2249 events, including keyboard events, from the queue. (QUIT is | |
2250 definitely invoked from TO_INTERNAL_FORMAT().) If we do | |
2251 this recursively anywhere in the following code, it will | |
2252 mess certain things up -- in particular, the OS-provided | |
2253 sticky modifier code available as part of the accessibility | |
2254 package. | |
2255 | |
2256 (Academic question: If QUIT checking is supposed to be | |
2257 triggered only every 1/4 second, why is it getting | |
2258 consistently triggered here? I saw the problem | |
2259 consistently. Answer: It appears that, currently, | |
2260 sometimes the code to pump messages is wrapped with | |
2261 begin_dont_check_for_quit() and sometimes it isn't. (#### | |
2262 FIX THIS SHIT!) cmdloop.c, for example, has it, but not | |
2263 everywhere. The current games with avoiding QUIT mean that | |
2264 the 1/4-second timer consistently fires while | |
2265 dont_check_for_quit is set [which causes the quit check to | |
2266 get deferred but the flag is still on], and so the next | |
2267 time it's unset and we call QUIT is *right here*. | |
2268 | |
2269 In my stderr-proc ws I majorly cleaned up the whole shit by | |
2270 just wrapping all the entry points in dont_check_for_quit. | |
2271 This fixed the remaining bugs with C-g getting interpreted | |
2272 wrong.) | |
2273 | |
2274 #### We should probably wrap this whole function in | |
2275 begin_dont_check_for_quit(); but then we should set this | |
2276 back to 0 when handling a menu callback, which gets invoked | |
2277 from within this function, specifically from | |
2278 DefWindowProc(). (We already do the latter in my new | |
2279 stderr-proc ws, because in that ws next_event_internal() | |
2280 calls begin_dont_check_for_quit(). */ | |
2281 | |
2282 int count = begin_dont_check_for_quit (); | |
2158 int has_AltGr = mswindows_current_layout_has_AltGr (); | 2283 int has_AltGr = mswindows_current_layout_has_AltGr (); |
2159 int mods = 0, mods_with_shift = 0; | 2284 int mods = 0, mods_with_shift = 0; |
2160 int extendedp = lParam & 0x1000000; | 2285 int extendedp = lParam & 0x1000000; |
2161 Lisp_Object keysym; | 2286 Lisp_Object keysym; |
2162 int sticky_changed; | 2287 int sticky_changed; |
2202 CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); | 2327 CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); |
2203 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; | 2328 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; |
2204 MSG msg, tranmsg; | 2329 MSG msg, tranmsg; |
2205 int potential_accelerator = 0; | 2330 int potential_accelerator = 0; |
2206 int got_accelerator = 0; | 2331 int got_accelerator = 0; |
2332 /* No need to gcpro because the event is already on a | |
2333 queue when we retrieve it. */ | |
2334 Lisp_Object lastev = Qnil; | |
2207 | 2335 |
2208 msg.hwnd = hwnd; | 2336 msg.hwnd = hwnd; |
2209 msg.message = message_; | 2337 msg.message = message_; |
2210 msg.wParam = wParam; | 2338 msg.wParam = wParam; |
2211 msg.lParam = lParam; | 2339 msg.lParam = lParam; |
2249 SetKeyboardState (keymap_trans); | 2377 SetKeyboardState (keymap_trans); |
2250 | 2378 |
2251 /* Maybe generate some WM_[SYS]CHARs in the queue */ | 2379 /* Maybe generate some WM_[SYS]CHARs in the queue */ |
2252 TranslateMessage (&msg); | 2380 TranslateMessage (&msg); |
2253 | 2381 |
2254 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) | 2382 while (qxePeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) |
2255 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, | 2383 || qxePeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, |
2256 PM_REMOVE)) | 2384 PM_REMOVE)) |
2257 { | 2385 { |
2258 int mods_with_quit = mods; | 2386 int mods_with_quit = mods; |
2259 Emchar ch = (Emchar) tranmsg.wParam; | 2387 int length; |
2388 Extbyte extchar[4]; | |
2389 Intbyte *intchar; | |
2390 Emchar ch; | |
2391 | |
2392 if (XEUNICODE_P) | |
2393 { | |
2394 length = unicode_char_to_text (tranmsg.wParam, extchar); | |
2395 TO_INTERNAL_FORMAT (DATA, (extchar, length), | |
2396 C_STRING_ALLOCA, (intchar), | |
2397 Qmswindows_unicode); | |
2398 ch = charptr_emchar (intchar); | |
2399 } | |
2400 else | |
2401 { | |
2402 length = ansi_char_to_text (tranmsg.wParam, extchar); | |
2403 intchar = (convert_multibyte_to_internal_malloc | |
2404 (extchar, length, | |
2405 mswindows_locale_to_code_page | |
2406 /* See intl-win32.c for an explanation of | |
2407 the following */ | |
2408 ((LCID) GetKeyboardLayout (0) & 0xFFFF), | |
2409 NULL)); | |
2410 ch = charptr_emchar (intchar); | |
2411 xfree (intchar); | |
2412 } | |
2260 | 2413 |
2261 #ifdef DEBUG_XEMACS | 2414 #ifdef DEBUG_XEMACS |
2262 if (debug_mswindows_events) | 2415 if (debug_mswindows_events) |
2263 { | 2416 { |
2264 stderr_out ("-> "); | 2417 stderr_out ("-> "); |
2269 #endif /* DEBUG_XEMACS */ | 2422 #endif /* DEBUG_XEMACS */ |
2270 | 2423 |
2271 /* If a quit char with no modifiers other than control and | 2424 /* If a quit char with no modifiers other than control and |
2272 shift, then mark it with a fake modifier, which is removed | 2425 shift, then mark it with a fake modifier, which is removed |
2273 upon dequeueing the event */ | 2426 upon dequeueing the event */ |
2274 /* !!#### Fix this in my mule ws -- replace current_buffer | |
2275 with 0 */ | |
2276 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) | 2427 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) |
2277 && DOWNCASE (current_buffer, quit_ch + 'a' - 1) == | 2428 && DOWNCASE (0, quit_ch + 'a' - 1) == |
2278 DOWNCASE (current_buffer, ch)) | 2429 DOWNCASE (0, ch)) |
2279 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) | 2430 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) |
2280 && DOWNCASE (current_buffer, quit_ch) == | 2431 && DOWNCASE (0, quit_ch) == |
2281 DOWNCASE (current_buffer, ch))) | 2432 DOWNCASE (0, ch))) |
2282 && ((mods_with_shift & | 2433 && ((mods_with_shift & |
2283 ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) | 2434 ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) |
2284 == 0)) | 2435 == 0)) |
2285 { | 2436 { |
2286 mods_with_quit |= FAKE_MOD_QUIT; | 2437 mods_with_quit |= FAKE_MOD_QUIT; |
2292 mswindows_char_is_accelerator (frame, ch)) | 2443 mswindows_char_is_accelerator (frame, ch)) |
2293 { | 2444 { |
2294 got_accelerator = 1; | 2445 got_accelerator = 1; |
2295 break; | 2446 break; |
2296 } | 2447 } |
2297 mswindows_enqueue_keypress_event (hwnd, make_char (ch), | 2448 lastev = mswindows_enqueue_keypress_event (hwnd, |
2298 mods_with_quit); | 2449 make_char (ch), |
2450 mods_with_quit); | |
2299 } /* while */ | 2451 } /* while */ |
2452 | |
2453 #ifdef MULE | |
2454 /* Also figure out what the character would be in other | |
2455 possible keyboard layouts, in this order: | |
2456 | |
2457 -- current language environment | |
2458 -- user default language environment | |
2459 -- system default language environment | |
2460 -- same three, but checking the underlying virtual key, | |
2461 and only paying attention if it's alphabetic | |
2462 -- US ASCII | |
2463 | |
2464 See events.h, struct key_data, for why we do this. | |
2465 */ | |
2466 | |
2467 if (!NILP (lastev)) | |
2468 { | |
2469 int i; | |
2470 int scan = (lParam >> 16) && 0xFF; | |
2471 | |
2472 for (i = 0; i < KEYCHAR_LAST; i++) | |
2473 { | |
2474 int vk_only = 0; | |
2475 LCID lcid; | |
2476 int virtual_key; | |
2477 | |
2478 switch (i) | |
2479 { | |
2480 case KEYCHAR_UNDERLYING_VIRTUAL_KEY_CURRENT_LANGENV: | |
2481 vk_only = 1; | |
2482 case KEYCHAR_CURRENT_LANGENV: | |
2483 lcid = mswindows_current_locale (); | |
2484 break; | |
2485 | |
2486 case KEYCHAR_UNDERLYING_VIRTUAL_KEY_DEFAULT_USER: | |
2487 vk_only = 1; | |
2488 case KEYCHAR_DEFAULT_USER: | |
2489 lcid = GetUserDefaultLCID (); | |
2490 break; | |
2491 | |
2492 case KEYCHAR_UNDERLYING_VIRTUAL_KEY_DEFAULT_SYSTEM: | |
2493 vk_only = 1; | |
2494 case KEYCHAR_DEFAULT_SYSTEM: | |
2495 lcid = GetSystemDefaultLCID (); | |
2496 break; | |
2497 | |
2498 case KEYCHAR_QWERTY: | |
2499 lcid = MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US); | |
2500 break; | |
2501 | |
2502 default: abort (); lcid = 0; | |
2503 } | |
2504 | |
2505 /* VERY CONFUSING! See intl-win32.c. */ | |
2506 lcid = lcid & 0xFFFF; | |
2507 | |
2508 virtual_key = MapVirtualKeyEx (scan, 1, (HKL) lcid); | |
2509 if (!vk_only) | |
2510 { | |
2511 if (XEUNICODE_P) | |
2512 { | |
2513 Extbyte received_keys[32]; | |
2514 int tounret = | |
2515 ToUnicodeEx | |
2516 (virtual_key, scan, keymap_trans, | |
2517 (LPWSTR) received_keys, | |
2518 sizeof (received_keys) / XETCHAR_SIZE, | |
2519 0, /* #### what about this flag? "if | |
2520 bit 0 is set, a menu is | |
2521 active???" */ | |
2522 (HKL) lcid); | |
2523 if (tounret > 0) | |
2524 { | |
2525 Intbyte *intchar; | |
2526 | |
2527 TO_INTERNAL_FORMAT | |
2528 (DATA, | |
2529 (received_keys + (tounret - 1) * 2, 2), | |
2530 C_STRING_ALLOCA, intchar, | |
2531 Qmswindows_unicode); | |
2532 XEVENT (lastev)->event.key.alt_keychars[i] = | |
2533 charptr_emchar (intchar); | |
2534 } | |
2535 } | |
2536 else | |
2537 { | |
2538 WORD received_keys[32]; | |
2539 int tounret = | |
2540 ToAsciiEx (virtual_key, scan, keymap_trans, | |
2541 received_keys, | |
2542 0, /* #### what about this | |
2543 flag? "if bit 0 is set, a | |
2544 menu is active???" */ | |
2545 (HKL) lcid); | |
2546 if (tounret > 0) | |
2547 { | |
2548 /* #### I cannot find proper | |
2549 documentation on what format the | |
2550 return value is in. I'm assuming | |
2551 it's like WM_IME_CHAR: DBCS chars | |
2552 have the lead byte in bits 8-15 of | |
2553 the short. */ | |
2554 Intbyte *intchar; | |
2555 Extbyte mbstuff[2]; | |
2556 Bytecount mblength = 0; | |
2557 WORD thechar = received_keys[tounret - 1]; | |
2558 | |
2559 mbstuff[mblength++] = | |
2560 (Extbyte) (thechar & 0xFF); | |
2561 if (thechar > 0xFF) | |
2562 mbstuff[mblength++] = | |
2563 (Extbyte) ((thechar >> 8) & 0xFF); | |
2564 | |
2565 intchar = convert_multibyte_to_internal_malloc | |
2566 (mbstuff, mblength, | |
2567 mswindows_locale_to_code_page (lcid), | |
2568 NULL); | |
2569 | |
2570 XEVENT (lastev)->event.key.alt_keychars[i] = | |
2571 charptr_emchar (intchar); | |
2572 xfree (intchar); | |
2573 } | |
2574 } | |
2575 } | |
2576 else | |
2577 { | |
2578 Emchar altch; | |
2579 | |
2580 if (virtual_key >= 'A' && virtual_key <= 'Z') | |
2581 altch = | |
2582 virtual_key + (mods_with_shift & XEMACS_MOD_SHIFT ? | |
2583 'a' - 'A' : 0); | |
2584 else | |
2585 altch = 0; | |
2586 | |
2587 XEVENT (lastev)->event.key.alt_keychars[i] = altch; | |
2588 } | |
2589 } | |
2590 } | |
2591 #endif /* MULE */ | |
2300 | 2592 |
2301 /* This generates WM_SYSCHAR messages, which are interpreted | 2593 /* This generates WM_SYSCHAR messages, which are interpreted |
2302 by DefWindowProc as the menu selections. */ | 2594 by DefWindowProc as the menu selections. */ |
2303 if (got_accelerator) | 2595 if (got_accelerator) |
2304 { | 2596 { |
2305 SetKeyboardState (keymap_sticky); | 2597 SetKeyboardState (keymap_sticky); |
2306 TranslateMessage (&msg); | 2598 TranslateMessage (&msg); |
2307 SetKeyboardState (keymap_orig); | 2599 SetKeyboardState (keymap_orig); |
2600 unbind_to (count); | |
2308 goto defproc; | 2601 goto defproc; |
2309 } | 2602 } |
2310 | 2603 |
2311 SetKeyboardState (keymap_orig); | 2604 SetKeyboardState (keymap_orig); |
2312 } /* else */ | 2605 } /* else */ |
2606 | |
2607 if (key_needs_default_processing_p (wParam)) | |
2608 { | |
2609 unbind_to (count); | |
2610 goto defproc; | |
2611 } | |
2612 else | |
2613 { | |
2614 unbind_to (count); | |
2615 break; | |
2616 } | |
2313 } | 2617 } |
2314 | |
2315 if (key_needs_default_processing_p (wParam)) | |
2316 goto defproc; | |
2317 else | |
2318 break; | |
2319 | 2618 |
2320 case WM_MBUTTONDOWN: | 2619 case WM_MBUTTONDOWN: |
2321 case WM_MBUTTONUP: | 2620 case WM_MBUTTONUP: |
2322 /* Real middle mouse button has nothing to do with emulated one: | 2621 /* Real middle mouse button has nothing to do with emulated one: |
2323 if one wants to exercise fingers playing chords on the mouse, | 2622 if one wants to exercise fingers playing chords on the mouse, |
2327 wParam &~ MK_MBUTTON, | 2626 wParam &~ MK_MBUTTON, |
2328 GetMessageTime()); | 2627 GetMessageTime()); |
2329 break; | 2628 break; |
2330 | 2629 |
2331 case WM_LBUTTONUP: | 2630 case WM_LBUTTONUP: |
2332 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2631 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2333 msframe->last_click_time = GetMessageTime(); | 2632 msframe->last_click_time = GetMessageTime(); |
2334 | 2633 |
2335 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2634 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2336 msframe->button2_need_lbutton = 0; | 2635 msframe->button2_need_lbutton = 0; |
2337 if (msframe->ignore_next_lbutton_up) | 2636 if (msframe->ignore_next_lbutton_up) |
2338 { | 2637 { |
2365 GetMessageTime()); | 2664 GetMessageTime()); |
2366 } | 2665 } |
2367 break; | 2666 break; |
2368 | 2667 |
2369 case WM_RBUTTONUP: | 2668 case WM_RBUTTONUP: |
2370 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2669 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2371 msframe->last_click_time = GetMessageTime(); | 2670 msframe->last_click_time = GetMessageTime(); |
2372 | 2671 |
2373 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2672 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2374 msframe->button2_need_rbutton = 0; | 2673 msframe->button2_need_rbutton = 0; |
2375 if (msframe->ignore_next_rbutton_up) | 2674 if (msframe->ignore_next_rbutton_up) |
2376 { | 2675 { |
2403 GetMessageTime()); | 2702 GetMessageTime()); |
2404 } | 2703 } |
2405 break; | 2704 break; |
2406 | 2705 |
2407 case WM_LBUTTONDOWN: | 2706 case WM_LBUTTONDOWN: |
2408 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2707 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2409 | 2708 |
2410 if (msframe->button2_need_lbutton) | 2709 if (msframe->button2_need_lbutton) |
2411 { | 2710 { |
2412 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2711 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2413 msframe->button2_need_lbutton = 0; | 2712 msframe->button2_need_lbutton = 0; |
2441 mswindows_set_chord_timer (hwnd); | 2740 mswindows_set_chord_timer (hwnd); |
2442 msframe->button2_need_rbutton = 1; | 2741 msframe->button2_need_rbutton = 1; |
2443 msframe->last_click_point = MAKEPOINTS (lParam); | 2742 msframe->last_click_point = MAKEPOINTS (lParam); |
2444 msframe->last_click_mods = wParam; | 2743 msframe->last_click_mods = wParam; |
2445 } | 2744 } |
2446 msframe->last_click_time = GetMessageTime(); | 2745 msframe->last_click_time = GetMessageTime(); |
2447 break; | 2746 break; |
2448 | 2747 |
2449 case WM_RBUTTONDOWN: | 2748 case WM_RBUTTONDOWN: |
2450 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2749 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2451 | 2750 |
2452 if (msframe->button2_need_rbutton) | 2751 if (msframe->button2_need_rbutton) |
2453 { | 2752 { |
2454 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2753 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2455 msframe->button2_need_lbutton = 0; | 2754 msframe->button2_need_lbutton = 0; |
2483 mswindows_set_chord_timer (hwnd); | 2782 mswindows_set_chord_timer (hwnd); |
2484 msframe->button2_need_lbutton = 1; | 2783 msframe->button2_need_lbutton = 1; |
2485 msframe->last_click_point = MAKEPOINTS (lParam); | 2784 msframe->last_click_point = MAKEPOINTS (lParam); |
2486 msframe->last_click_mods = wParam; | 2785 msframe->last_click_mods = wParam; |
2487 } | 2786 } |
2488 msframe->last_click_time = GetMessageTime(); | 2787 msframe->last_click_time = GetMessageTime(); |
2489 break; | 2788 break; |
2490 | 2789 |
2491 case WM_TIMER: | 2790 case WM_TIMER: |
2492 if (wParam == BUTTON_2_TIMER_ID) | 2791 if (wParam == BUTTON_2_TIMER_ID) |
2493 { | 2792 { |
2494 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2793 msframe = |
2794 FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2495 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2795 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2496 | 2796 |
2497 if (msframe->button2_need_lbutton) | 2797 if (msframe->button2_need_lbutton) |
2498 { | 2798 { |
2499 msframe->button2_need_lbutton = 0; | 2799 msframe->button2_need_lbutton = 0; |
2517 assert ("Spurious timer fired" == 0); | 2817 assert ("Spurious timer fired" == 0); |
2518 break; | 2818 break; |
2519 | 2819 |
2520 case WM_MOUSEMOVE: | 2820 case WM_MOUSEMOVE: |
2521 /* Optimization: don't report mouse movement while size is changing */ | 2821 /* Optimization: don't report mouse movement while size is changing */ |
2522 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 2822 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2523 if (!msframe->sizing) | 2823 if (!msframe->sizing) |
2524 { | 2824 { |
2525 /* When waiting for the second mouse button to finish | 2825 /* When waiting for the second mouse button to finish |
2526 button2 emulation, and have moved too far, just pretend | 2826 button2 emulation, and have moved too far, just pretend |
2527 as if timer has expired. This improves drag-select feedback */ | 2827 as if timer has expired. This improves drag-select feedback */ |
2528 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton) | 2828 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton) |
2529 && !mswindows_button2_near_enough (msframe->last_click_point, | 2829 && !mswindows_button2_near_enough (msframe->last_click_point, |
2530 MAKEPOINTS (lParam))) | 2830 MAKEPOINTS (lParam))) |
2531 { | 2831 { |
2532 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 2832 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
2533 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); | 2833 qxeSendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); |
2534 } | 2834 } |
2535 | 2835 |
2536 emacs_event = Fmake_event (Qnil, Qnil); | 2836 emacs_event = Fmake_event (Qnil, Qnil); |
2537 event = XEVENT(emacs_event); | 2837 event = XEVENT(emacs_event); |
2538 | 2838 |
2539 event->channel = mswindows_find_frame(hwnd); | 2839 event->channel = mswindows_find_frame (hwnd); |
2540 event->timestamp = GetMessageTime(); | 2840 event->timestamp = GetMessageTime (); |
2541 event->event_type = pointer_motion_event; | 2841 event->event_type = pointer_motion_event; |
2542 event->event.motion.x = MAKEPOINTS(lParam).x; | 2842 event->event.motion.x = MAKEPOINTS (lParam).x; |
2543 event->event.motion.y = MAKEPOINTS(lParam).y; | 2843 event->event.motion.y = MAKEPOINTS (lParam).y; |
2544 event->event.motion.modifiers = | 2844 event->event.motion.modifiers = |
2545 mswindows_modifier_state (NULL, wParam, 0); | 2845 mswindows_modifier_state (NULL, wParam, 0); |
2546 | 2846 |
2547 mswindows_enqueue_dispatch_event (emacs_event); | 2847 mswindows_enqueue_dispatch_event (emacs_event); |
2548 } | 2848 } |
2561 LPNMHDR nmhdr = (LPNMHDR) lParam; | 2861 LPNMHDR nmhdr = (LPNMHDR) lParam; |
2562 | 2862 |
2563 if ((int) nmhdr->code == TTN_NEEDTEXT) | 2863 if ((int) nmhdr->code == TTN_NEEDTEXT) |
2564 { | 2864 { |
2565 #ifdef HAVE_TOOLBARS | 2865 #ifdef HAVE_TOOLBARS |
2566 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT) lParam; | 2866 LPTOOLTIPTEXTW tttextw = (LPTOOLTIPTEXTW) lParam; |
2567 Lisp_Object btext; | 2867 Lisp_Object btext; |
2868 Extbyte *btextext = 0; | |
2568 | 2869 |
2569 /* find out which toolbar */ | 2870 /* find out which toolbar */ |
2570 frame = XFRAME (mswindows_find_frame (hwnd)); | 2871 frame = XFRAME (mswindows_find_frame (hwnd)); |
2571 btext = mswindows_get_toolbar_button_text (frame, nmhdr->idFrom); | 2872 btext = mswindows_get_toolbar_button_text (frame, nmhdr->idFrom); |
2572 | 2873 |
2573 tttext->lpszText = NULL; | 2874 tttextw->hinst = NULL; |
2574 tttext->hinst = NULL; | 2875 |
2575 | 2876 if (!NILP (btext)) |
2576 if (!NILP(btext)) | 2877 LISP_STRING_TO_TSTR (btext, btextext); |
2878 | |
2879 if (btextext) | |
2577 { | 2880 { |
2578 /* I think this is safe since the text will only go away | 2881 /* WARNING: We can't just write a '\0' into the 79th |
2579 when the toolbar does...*/ | 2882 "character" because tttextw->szText is in WCHAR's but we |
2580 LISP_STRING_TO_EXTERNAL (btext, tttext->lpszText, Qnative); | 2883 may be copying an ANSI string into it. Easiest to just |
2884 zero the whole thing. */ | |
2885 xzero (*tttextw->szText); | |
2886 xetcsncpy ((Extbyte *) tttextw->szText, btextext, 79); | |
2581 } | 2887 } |
2888 else | |
2889 tttextw->lpszText = NULL; | |
2582 #endif | 2890 #endif |
2583 } | 2891 } |
2584 /* handle tree view callbacks */ | 2892 /* handle tree view callbacks */ |
2585 else if ((int) nmhdr->code == TVN_SELCHANGED) | 2893 else if ((int) nmhdr->code == TVN_SELCHANGED) |
2586 { | 2894 { |
2590 } | 2898 } |
2591 /* handle tab control callbacks */ | 2899 /* handle tab control callbacks */ |
2592 else if ((int) nmhdr->code == TCN_SELCHANGE) | 2900 else if ((int) nmhdr->code == TCN_SELCHANGE) |
2593 { | 2901 { |
2594 TC_ITEM item; | 2902 TC_ITEM item; |
2595 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0); | 2903 int idx = qxeSendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0); |
2596 frame = XFRAME (mswindows_find_frame (hwnd)); | 2904 frame = XFRAME (mswindows_find_frame (hwnd)); |
2597 | 2905 |
2598 item.mask = TCIF_PARAM; | 2906 item.mask = TCIF_PARAM; |
2599 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx, | 2907 qxeSendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM) idx, |
2600 (LPARAM)&item); | 2908 (LPARAM) &item); |
2601 | 2909 |
2602 mswindows_handle_gui_wm_command (frame, 0, item.lParam); | 2910 mswindows_handle_gui_wm_command (frame, 0, item.lParam); |
2603 } | 2911 } |
2604 } | 2912 } |
2605 break; | 2913 break; |
2641 { | 2949 { |
2642 FRAME_VISIBLE_P (frame) = 0; | 2950 FRAME_VISIBLE_P (frame) = 0; |
2643 FRAME_ICONIFIED_P (frame) = 0; | 2951 FRAME_ICONIFIED_P (frame) = 0; |
2644 } | 2952 } |
2645 | 2953 |
2646 return DefWindowProc (hwnd, message_, wParam, lParam); | 2954 goto defproc; |
2647 } | 2955 } |
2648 | 2956 |
2649 case WM_SHOWWINDOW: | 2957 case WM_SHOWWINDOW: |
2650 /* | 2958 /* |
2651 The WM_SHOWWINDOW message is sent to a window when the window | 2959 The WM_SHOWWINDOW message is sent to a window when the window |
2670 } | 2978 } |
2671 break; | 2979 break; |
2672 | 2980 |
2673 case WM_SIZE: | 2981 case WM_SIZE: |
2674 /* We only care about this message if our size has really changed */ | 2982 /* We only care about this message if our size has really changed */ |
2675 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED) | 2983 if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || |
2984 wParam == SIZE_MINIMIZED) | |
2676 { | 2985 { |
2677 RECT rect; | 2986 RECT rect; |
2678 int columns, rows; | 2987 int columns, rows; |
2679 | 2988 |
2680 fobj = mswindows_find_frame (hwnd); | 2989 fobj = mswindows_find_frame (hwnd); |
2681 frame = XFRAME (fobj); | 2990 frame = XFRAME (fobj); |
2682 msframe = FRAME_MSWINDOWS_DATA (frame); | 2991 msframe = FRAME_MSWINDOWS_DATA (frame); |
2683 | 2992 |
2684 /* We cannot handle frame map and unmap hooks right in | 2993 /* We cannot handle frame map and unmap hooks right in |
2685 this routine, because these may throw. We queue | 2994 this routine, because these may throw. We queue |
2686 magic events to run these hooks instead - kkm */ | 2995 magic events to run these hooks instead - kkm */ |
2687 | 2996 |
2688 if (wParam==SIZE_MINIMIZED) | 2997 if (wParam == SIZE_MINIMIZED) |
2689 { | 2998 { |
2690 /* Iconified */ | 2999 /* Iconified */ |
2691 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME); | 3000 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME); |
2692 } | 3001 } |
2693 else | 3002 else |
2698 | 3007 |
2699 pixel_to_real_char_size (frame, rect.right, rect.bottom, | 3008 pixel_to_real_char_size (frame, rect.right, rect.bottom, |
2700 &FRAME_MSWINDOWS_CHARWIDTH (frame), | 3009 &FRAME_MSWINDOWS_CHARWIDTH (frame), |
2701 &FRAME_MSWINDOWS_CHARHEIGHT (frame)); | 3010 &FRAME_MSWINDOWS_CHARHEIGHT (frame)); |
2702 | 3011 |
2703 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows); | 3012 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, |
3013 &rows); | |
2704 change_frame_size (frame, rows, columns, 1); | 3014 change_frame_size (frame, rows, columns, 1); |
2705 | 3015 |
2706 /* If we are inside frame creation, we have to apply geometric | 3016 /* If we are inside frame creation, we have to apply geometric |
2707 properties now. */ | 3017 properties now. */ |
2708 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | 3018 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) |
2709 { | 3019 { |
2710 /* Yes, we have to size again */ | 3020 /* Yes, we have to size again */ |
2711 mswindows_size_frame_internal ( frame, | 3021 mswindows_size_frame_internal (frame, |
2712 FRAME_MSWINDOWS_TARGET_RECT | 3022 FRAME_MSWINDOWS_TARGET_RECT |
2713 (frame)); | 3023 (frame)); |
2714 /* Reset so we do not get here again. The SetWindowPos call in | 3024 /* Reset so we do not get here again. The SetWindowPos |
2715 * mswindows_size_frame_internal can cause recursion here. */ | 3025 * call in mswindows_size_frame_internal can cause |
3026 * recursion here. */ | |
2716 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | 3027 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) |
2717 { | 3028 { |
2718 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame)); | 3029 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame)); |
2719 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0; | 3030 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0; |
2720 } | 3031 } |
2776 && wpl.showCmd != SW_SHOWMAXIMIZED | 3087 && wpl.showCmd != SW_SHOWMAXIMIZED |
2777 && !(wp->flags & SWP_NOSIZE)) | 3088 && !(wp->flags & SWP_NOSIZE)) |
2778 { | 3089 { |
2779 RECT ncsize = { 0, 0, 0, 0 }; | 3090 RECT ncsize = { 0, 0, 0, 0 }; |
2780 int pixwidth, pixheight; | 3091 int pixwidth, pixheight; |
2781 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE), | 3092 AdjustWindowRectEx (&ncsize, qxeGetWindowLong (hwnd, GWL_STYLE), |
2782 GetMenu(hwnd) != NULL, | 3093 GetMenu(hwnd) != NULL, |
2783 GetWindowLong (hwnd, GWL_EXSTYLE)); | 3094 qxeGetWindowLong (hwnd, GWL_EXSTYLE)); |
2784 | 3095 |
2785 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)), | 3096 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)), |
2786 wp->cx - (ncsize.right - ncsize.left), | 3097 wp->cx - (ncsize.right - ncsize.left), |
2787 wp->cy - (ncsize.bottom - ncsize.top), | 3098 wp->cy - (ncsize.bottom - ncsize.top), |
2788 &pixwidth, &pixheight); | 3099 &pixwidth, &pixheight); |
2811 window position if the user tries to track window too small */ | 3122 window position if the user tries to track window too small */ |
2812 } | 3123 } |
2813 goto defproc; | 3124 goto defproc; |
2814 | 3125 |
2815 case WM_ENTERSIZEMOVE: | 3126 case WM_ENTERSIZEMOVE: |
2816 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 3127 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2817 msframe->sizing = 1; | 3128 msframe->sizing = 1; |
2818 return 0; | 3129 return 0; |
2819 | 3130 |
2820 case WM_EXITSIZEMOVE: | 3131 case WM_EXITSIZEMOVE: |
2821 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 3132 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
2822 msframe->sizing = 0; | 3133 msframe->sizing = 0; |
2823 /* Queue noop event */ | 3134 /* Queue noop event */ |
2824 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | 3135 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); |
2825 return 0; | 3136 return 0; |
2826 | 3137 |
2834 HWND hwndScrollBar = (HWND) lParam; | 3145 HWND hwndScrollBar = (HWND) lParam; |
2835 struct gcpro gcpro1, gcpro2; | 3146 struct gcpro gcpro1, gcpro2; |
2836 | 3147 |
2837 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos); | 3148 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos); |
2838 GCPRO2 (emacs_event, fobj); | 3149 GCPRO2 (emacs_event, fobj); |
2839 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */ | 3150 if (UNBOUNDP (mswindows_pump_outstanding_events())) /* Can GC */ |
2840 { | 3151 { |
2841 /* Error during event pumping - cancel scroll */ | 3152 /* Error during event pumping - cancel scroll */ |
2842 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0); | 3153 qxeSendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0); |
2843 } | 3154 } |
2844 UNGCPRO; | 3155 UNGCPRO; |
2845 break; | 3156 break; |
2846 } | 3157 } |
2847 | 3158 |
2860 } | 3171 } |
2861 #endif | 3172 #endif |
2862 | 3173 |
2863 #ifdef HAVE_MENUBARS | 3174 #ifdef HAVE_MENUBARS |
2864 case WM_INITMENU: | 3175 case WM_INITMENU: |
2865 if (UNBOUNDP (mswindows_handle_wm_initmenu ( | 3176 if (UNBOUNDP (mswindows_handle_wm_initmenu |
2866 (HMENU) wParam, | 3177 ((HMENU) wParam, |
2867 XFRAME (mswindows_find_frame (hwnd))))) | 3178 XFRAME (mswindows_find_frame (hwnd))))) |
2868 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | 3179 qxeSendMessage (hwnd, WM_CANCELMODE, 0, 0); |
2869 break; | 3180 break; |
2870 | 3181 |
2871 case WM_INITMENUPOPUP: | 3182 case WM_INITMENUPOPUP: |
2872 if (!HIWORD(lParam)) | 3183 if (!HIWORD(lParam)) |
2873 { | 3184 { |
2874 if (UNBOUNDP (mswindows_handle_wm_initmenupopup ( | 3185 if (UNBOUNDP (mswindows_handle_wm_initmenupopup |
2875 (HMENU) wParam, | 3186 ((HMENU) wParam, |
2876 XFRAME (mswindows_find_frame (hwnd))))) | 3187 XFRAME (mswindows_find_frame (hwnd))))) |
2877 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | 3188 qxeSendMessage (hwnd, WM_CANCELMODE, 0, 0); |
2878 } | 3189 } |
2879 break; | 3190 break; |
2880 | 3191 |
2881 #endif /* HAVE_MENUBARS */ | 3192 #endif /* HAVE_MENUBARS */ |
2882 | 3193 |
2889 | 3200 |
2890 #ifdef HAVE_TOOLBARS | 3201 #ifdef HAVE_TOOLBARS |
2891 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id))) | 3202 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id))) |
2892 break; | 3203 break; |
2893 #endif | 3204 #endif |
2894 /* widgets in a buffer only eval a callback for suitable events.*/ | 3205 /* widgets in a buffer only eval a callback for suitable events. */ |
2895 switch (nid) | 3206 switch (nid) |
2896 { | 3207 { |
2897 case BN_CLICKED: | 3208 case BN_CLICKED: |
2898 case EN_CHANGE: | 3209 case EN_CHANGE: |
2899 case CBN_EDITCHANGE: | 3210 case CBN_EDITCHANGE: |
2900 case CBN_SELCHANGE: | 3211 case CBN_SELCHANGE: |
2901 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id))) | 3212 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id))) |
2902 return 0; | 3213 return 0; |
2903 } | 3214 } |
2904 /* menubars always must come last since the hashtables do not | 3215 /* menubars always must come last since the hashtables do not |
2905 always exist*/ | 3216 always exist */ |
2906 #ifdef HAVE_MENUBARS | 3217 #ifdef HAVE_MENUBARS |
2907 if (!NILP (mswindows_handle_wm_command (frame, id))) | 3218 if (!NILP (mswindows_handle_wm_command (frame, id))) |
2908 break; | 3219 break; |
2909 #endif | 3220 #endif |
2910 | 3221 |
2911 return DefWindowProc (hwnd, message_, wParam, lParam); | 3222 goto defproc; |
2912 /* Bite me - a spurious command. This used to not be able to | 3223 /* Bite me - a spurious command. This used to not be able to |
2913 happen but with the introduction of widgets its now | 3224 happen but with the introduction of widgets it's now |
2914 possible. */ | 3225 possible. #### Andy, fix the god-damn widget code! It has |
3226 more bugs than a termite's nest! */ | |
2915 } | 3227 } |
2916 break; | 3228 break; |
2917 | 3229 |
2918 case WM_CTLCOLORBTN: | 3230 case WM_CTLCOLORBTN: |
2919 case WM_CTLCOLORLISTBOX: | 3231 case WM_CTLCOLORLISTBOX: |
2921 case WM_CTLCOLORSTATIC: | 3233 case WM_CTLCOLORSTATIC: |
2922 case WM_CTLCOLORSCROLLBAR: | 3234 case WM_CTLCOLORSCROLLBAR: |
2923 { | 3235 { |
2924 /* if we get an opportunity to paint a widget then do so if | 3236 /* if we get an opportunity to paint a widget then do so if |
2925 there is an appropriate face */ | 3237 there is an appropriate face */ |
2926 HWND crtlwnd = (HWND)lParam; | 3238 HWND crtlwnd = (HWND) lParam; |
2927 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA); | 3239 LONG ii = qxeGetWindowLong (crtlwnd, GWL_USERDATA); |
2928 if (ii) | 3240 if (ii) |
2929 { | 3241 { |
2930 Lisp_Object image_instance; | 3242 Lisp_Object image_instance; |
2931 VOID_TO_LISP (image_instance, ii); | 3243 VOID_TO_LISP (image_instance, ii); |
2932 if (IMAGE_INSTANCEP (image_instance) | 3244 if (IMAGE_INSTANCEP (image_instance) |
2933 && | 3245 && |
2934 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)) | 3246 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)) |
2935 { | 3247 { |
2936 /* set colors for the buttons */ | 3248 /* set colors for the buttons */ |
2937 HDC hdc = (HDC)wParam; | 3249 HDC hdc = (HDC) wParam; |
2938 if (last_widget_brushed != ii) | 3250 if (last_widget_brushed != ii) |
2939 { | 3251 { |
2940 if (widget_brush) | 3252 if (widget_brush) |
2941 DeleteObject (widget_brush); | 3253 DeleteObject (widget_brush); |
2942 widget_brush = CreateSolidBrush | 3254 widget_brush = CreateSolidBrush |
2969 goto defproc; | 3281 goto defproc; |
2970 | 3282 |
2971 #ifdef HAVE_DRAGNDROP | 3283 #ifdef HAVE_DRAGNDROP |
2972 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */ | 3284 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */ |
2973 { | 3285 { |
2974 UINT filecount, i, len; | 3286 UINT filecount, i; |
2975 POINT point; | 3287 POINT point; |
2976 char* filename; | |
2977 char* fname; | |
2978 | 3288 |
2979 Lisp_Object l_dndlist = Qnil, l_item = Qnil; | 3289 Lisp_Object l_dndlist = Qnil, l_item = Qnil; |
2980 struct gcpro gcpro1, gcpro2, gcpro3; | 3290 struct gcpro gcpro1, gcpro2, gcpro3; |
2981 | 3291 |
2982 emacs_event = Fmake_event (Qnil, Qnil); | 3292 emacs_event = Fmake_event (Qnil, Qnil); |
2983 event = XEVENT(emacs_event); | 3293 event = XEVENT (emacs_event); |
2984 | 3294 |
2985 GCPRO3 (emacs_event, l_dndlist, l_item); | 3295 GCPRO3 (emacs_event, l_dndlist, l_item); |
2986 | 3296 |
2987 if (!DragQueryPoint ((HDROP) wParam, &point)) | 3297 if (!DragQueryPoint ((HDROP) wParam, &point)) |
2988 point.x = point.y = -1; /* outside client area */ | 3298 point.x = point.y = -1; /* outside client area */ |
2989 | 3299 |
2990 event->event_type = misc_user_event; | 3300 event->event_type = misc_user_event; |
2991 event->channel = mswindows_find_frame(hwnd); | 3301 event->channel = mswindows_find_frame (hwnd); |
2992 event->timestamp = GetMessageTime(); | 3302 event->timestamp = GetMessageTime(); |
2993 event->event.misc.button = 1; /* #### Should try harder */ | 3303 event->event.misc.button = 1; /* #### Should try harder */ |
2994 event->event.misc.modifiers = mswindows_modifier_state (NULL, | 3304 event->event.misc.modifiers = mswindows_modifier_state (NULL, |
2995 (DWORD) -1, 0); | 3305 (DWORD) -1, 0); |
2996 event->event.misc.x = point.x; | 3306 event->event.misc.x = point.x; |
2997 event->event.misc.y = point.y; | 3307 event->event.misc.y = point.y; |
2998 event->event.misc.function = Qdragdrop_drop_dispatch; | 3308 event->event.misc.function = Qdragdrop_drop_dispatch; |
2999 | 3309 |
3000 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0); | 3310 filecount = qxeDragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0); |
3001 for (i=0; i<filecount; i++) | 3311 for (i = 0; i < filecount; i++) |
3002 { | 3312 { |
3003 len = DragQueryFile ((HDROP) wParam, i, NULL, 0); | 3313 Intbyte *fname; |
3314 Extbyte *fname_ext; | |
3315 Bytecount fnamelen; | |
3316 Charcount len = qxeDragQueryFile ((HDROP) wParam, i, NULL, 0); | |
3004 /* The URLs that we make here aren't correct according to section | 3317 /* The URLs that we make here aren't correct according to section |
3005 * 3.10 of rfc1738 because they're missing the //<host>/ part and | 3318 * 3.10 of rfc1738 because they're missing the //<host>/ part and |
3006 * because they may contain reserved characters. But that's OK - | 3319 * because they may contain reserved characters. But that's OK - |
3007 * they just need to be good enough to keep dragdrop.el happy. */ | 3320 * they just need to be good enough to keep dragdrop.el happy. */ |
3008 fname = (char *)xmalloc (len+1); | 3321 fname_ext = (Extbyte *) alloca ((len + 1) * XETCHAR_SIZE); |
3009 DragQueryFile ((HANDLE) wParam, i, fname, len+1); | 3322 qxeDragQueryFile ((HDROP) wParam, i, fname_ext, len + 1); |
3323 | |
3324 TO_INTERNAL_FORMAT (DATA, (fname_ext, len * XETCHAR_SIZE), | |
3325 ALLOCA, (fname, fnamelen), | |
3326 Qmswindows_tstr); | |
3010 | 3327 |
3011 /* May be a shell link aka "shortcut" - replace fname if so */ | 3328 /* May be a shell link aka "shortcut" - replace fname if so */ |
3012 #if !(defined(CYGWIN) || defined(MINGW)) | 3329 #if !defined (NO_CYGWIN_COM_SUPPORT) |
3013 /* cygwin doesn't define this COM stuff */ | 3330 if (!qxestrcasecmp_c (fname + fnamelen - 4, ".LNK")) |
3014 if (!stricmp (fname + strlen (fname) - 4, ".LNK")) | |
3015 { | 3331 { |
3016 IShellLink* psl; | 3332 /* #### |
3017 | 3333 |
3018 if (CoCreateInstance (&CLSID_ShellLink, NULL, | 3334 Note the following in the docs: |
3019 CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl) == S_OK) | 3335 |
3336 Note: The IShellLink interface has an ANSI version | |
3337 (IShellLinkA) and a Unicode version (IShellLinkW). The | |
3338 version that will be used depends on whether you compile | |
3339 for ANSI or Unicode. However, Microsoft® Windows 95 and | |
3340 Microsoft® Windows 98 only support IShellLinkA. | |
3341 | |
3342 We haven't yet implemented COM support in the | |
3343 Unicode-splitting library. I don't quite understand how | |
3344 COM works yet, but it looks like what's happening is | |
3345 that the ShellLink class implements both the IShellLinkA | |
3346 and IShellLinkW interfaces. To make this work at | |
3347 run-time, we have to do something like this: | |
3348 | |
3349 -- define a new interface qxeIShellLink that uses | |
3350 Extbyte * instead of LPSTR or LPWSTR. (not totally | |
3351 necessary since Extbyte * == LPSTR). | |
3352 | |
3353 -- define a new class qxeShellLink that implements | |
3354 qxeIShellLink. the methods on this class need to create | |
3355 a shadow ShellLink object to do all the real work, and | |
3356 call the corresponding function from either the | |
3357 IShellLinkA or IShellLinkW interfaces on this object, | |
3358 depending on whether XEUNICODE_P is defined. | |
3359 | |
3360 -- with appropriate preprocessor magic, of course, we | |
3361 could make things appear transparent; but we've decided | |
3362 not to do preprocessor magic for the moment. | |
3363 */ | |
3364 | |
3365 /* #### Not Unicode-split for the moment; we have to do it | |
3366 ourselves. */ | |
3367 if (XEUNICODE_P) | |
3020 { | 3368 { |
3021 IPersistFile* ppf; | 3369 IShellLinkW *psl; |
3022 | 3370 |
3023 if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, | 3371 if (CoCreateInstance ( |
3024 &ppf) == S_OK) | 3372 XECOMID (CLSID_ShellLink), |
3373 NULL, | |
3374 CLSCTX_INPROC_SERVER, | |
3375 XECOMID (IID_IShellLinkW), | |
3376 (void **) &psl) == S_OK) | |
3025 { | 3377 { |
3026 OLECHAR wsz[PATH_MAX]; | 3378 IPersistFile *ppf; |
3027 WIN32_FIND_DATA wfd; | 3379 |
3028 LPSTR resolved = (char *) xmalloc (PATH_MAX+1); | 3380 if (XECOMCALL2 (psl, QueryInterface, |
3029 | 3381 XECOMID (IID_IPersistFile), |
3030 MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, PATH_MAX); | 3382 (void **) &ppf) == |
3031 | 3383 S_OK) |
3032 if ((ppf->lpVtbl->Load (ppf, wsz, STGM_READ) == S_OK) && | |
3033 (psl->lpVtbl->GetPath (psl, resolved, PATH_MAX, | |
3034 &wfd, 0)==S_OK)) | |
3035 { | 3384 { |
3036 xfree (fname); | 3385 Extbyte *fname_unicode; |
3037 fname = resolved; | 3386 WIN32_FIND_DATAW wfd; |
3038 len = strlen (fname); | 3387 LPWSTR resolved = |
3388 alloca_array (WCHAR, PATH_MAX + 1); | |
3389 | |
3390 TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen), | |
3391 C_STRING_ALLOCA, | |
3392 fname_unicode, | |
3393 Qmswindows_unicode); | |
3394 | |
3395 if (XECOMCALL2 (ppf, Load, | |
3396 (LPWSTR) fname_unicode, | |
3397 STGM_READ) == S_OK && | |
3398 /* #### YUCK! Docs read | |
3399 | |
3400 cchMaxPath | |
3401 | |
3402 Maximum number of bytes to copy to the buffer pointed to by the | |
3403 pszFile parameter. | |
3404 | |
3405 But "cch" means "count of characters", not bytes. I'll assume the doc | |
3406 writers messed up and the programmer was correct. Also, this approach | |
3407 is safe even if it's actually the other way around. */ | |
3408 #ifdef CYGWIN_HEADERS /* Another Cygwin prototype error */ | |
3409 XECOMCALL4 (psl, GetPath, (LPSTR) resolved, | |
3410 PATH_MAX, &wfd, 0) | |
3411 #else | |
3412 XECOMCALL4 (psl, GetPath, resolved, | |
3413 PATH_MAX, &wfd, 0) | |
3414 #endif | |
3415 == S_OK) | |
3416 TO_INTERNAL_FORMAT (C_STRING, resolved, | |
3417 ALLOCA, (fname, fnamelen), | |
3418 Qmswindows_tstr); | |
3419 | |
3420 XECOMCALL0 (ppf, Release); | |
3039 } | 3421 } |
3040 | 3422 |
3041 ppf->lpVtbl->Release (ppf); | 3423 XECOMCALL0 (psl, Release); |
3042 } | 3424 } |
3043 | 3425 } |
3044 psl->lpVtbl->Release (psl); | 3426 else |
3427 { | |
3428 IShellLinkA *psl; | |
3429 | |
3430 if (CoCreateInstance ( | |
3431 XECOMID (CLSID_ShellLink), | |
3432 NULL, | |
3433 CLSCTX_INPROC_SERVER, | |
3434 XECOMID (IID_IShellLinkA), | |
3435 (void **) &psl) == S_OK) | |
3436 { | |
3437 IPersistFile *ppf; | |
3438 | |
3439 if (XECOMCALL2 (psl, QueryInterface, | |
3440 XECOMID (IID_IPersistFile), | |
3441 (void **) &ppf) == | |
3442 S_OK) | |
3443 { | |
3444 Extbyte *fname_unicode; | |
3445 WIN32_FIND_DATAA wfd; | |
3446 LPSTR resolved = | |
3447 alloca_array (CHAR, PATH_MAX + 1); | |
3448 | |
3449 /* Always Unicode. Not obvious from the | |
3450 IPersistFile documentation, but look under | |
3451 "Shell Link" for example code. */ | |
3452 TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen), | |
3453 C_STRING_ALLOCA, | |
3454 fname_unicode, | |
3455 Qmswindows_unicode); | |
3456 | |
3457 if (XECOMCALL2 (ppf, Load, | |
3458 (LPWSTR) fname_unicode, | |
3459 STGM_READ) == S_OK | |
3460 && XECOMCALL4 (psl, GetPath, resolved, | |
3461 PATH_MAX, &wfd, 0) == S_OK) | |
3462 TO_INTERNAL_FORMAT (C_STRING, resolved, | |
3463 ALLOCA, (fname, fnamelen), | |
3464 Qmswindows_tstr); | |
3465 | |
3466 XECOMCALL0 (ppf, Release); | |
3467 } | |
3468 | |
3469 XECOMCALL0 (psl, Release); | |
3470 } | |
3045 } | 3471 } |
3046 } | 3472 } |
3047 #endif | 3473 #endif /* !defined (NO_CYGWIN_COM_SUPPORT) */ |
3048 | 3474 { |
3049 #ifdef CYGWIN | 3475 fname = urlify_filename (fname); |
3050 filename = xmalloc (cygwin_win32_to_posix_path_list_buf_size (fname) + 5); | 3476 l_item = build_intstring (fname); |
3051 strcpy (filename, "file:"); | 3477 xfree (fname); |
3052 cygwin_win32_to_posix_path_list (fname, filename+5); | 3478 l_dndlist = Fcons (l_item, l_dndlist); |
3053 #else | 3479 } |
3054 filename = (char *)xmalloc (len+6); | |
3055 strcat (strcpy (filename, "file:"), fname); | |
3056 dostounix_filename (filename+5); | |
3057 #endif | |
3058 xfree (fname); | |
3059 l_item = make_string (filename, strlen (filename)); | |
3060 l_dndlist = Fcons (l_item, l_dndlist); | |
3061 xfree (filename); | |
3062 } | 3480 } |
3481 | |
3063 DragFinish ((HDROP) wParam); | 3482 DragFinish ((HDROP) wParam); |
3064 | 3483 |
3065 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist); | 3484 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist); |
3066 mswindows_enqueue_dispatch_event (emacs_event); | 3485 mswindows_enqueue_dispatch_event (emacs_event); |
3067 UNGCPRO; | 3486 UNGCPRO; |
3068 } | 3487 } |
3069 break; | 3488 break; |
3070 #endif | 3489 #endif /* HAVE_DRAGNDROP */ |
3490 | |
3491 #ifdef MULE | |
3492 case WM_IME_CHAR: | |
3493 | |
3494 case WM_IME_STARTCOMPOSITION: | |
3495 mswindows_start_ime_composition (XFRAME (mswindows_find_frame (hwnd))); | |
3496 goto defproc; | |
3497 | |
3498 case WM_IME_COMPOSITION: | |
3499 if (lParam & GCS_RESULTSTR) | |
3500 { | |
3501 HIMC imc = ImmGetContext (hwnd); | |
3502 Extbyte *result; | |
3503 Bytecount len; | |
3504 Intbyte *resultint, *endptr; | |
3505 Bytecount lenint; | |
3506 int speccount; | |
3507 | |
3508 if (!imc) | |
3509 break; | |
3510 | |
3511 /* See WM_KEYDOWN above. */ | |
3512 speccount = begin_dont_check_for_quit (); | |
3513 | |
3514 /* Sizes always in bytes, even for unicode. | |
3515 ImmGetCompositionStringW is supported even on Windows 9x, and | |
3516 allows us to handle multiple languages. */ | |
3517 len = ImmGetCompositionStringW (imc, GCS_RESULTSTR, NULL, 0); | |
3518 result = alloca_array (Extbyte, len); | |
3519 ImmGetCompositionStringW (imc, GCS_RESULTSTR, (WCHAR *) result, len); | |
3520 ImmReleaseContext (hwnd, imc); | |
3521 | |
3522 TO_INTERNAL_FORMAT (DATA, (result, len), | |
3523 ALLOCA, (resultint, lenint), | |
3524 Qmswindows_tstr); | |
3525 | |
3526 endptr = resultint + lenint; | |
3527 | |
3528 while (resultint < endptr) | |
3529 { | |
3530 Emchar ch = charptr_emchar (resultint); | |
3531 if (ch == ' ') | |
3532 mswindows_enqueue_keypress_event (hwnd, QKspace, 0); | |
3533 else | |
3534 mswindows_enqueue_keypress_event (hwnd, make_char (ch), 0); | |
3535 INC_CHARPTR (resultint); | |
3536 } | |
3537 | |
3538 unbind_to (speccount); | |
3539 } | |
3540 goto defproc; | |
3541 #endif /* MULE */ | |
3071 | 3542 |
3072 defproc: | 3543 defproc: |
3073 default: | 3544 default: |
3074 return DefWindowProc (hwnd, message_, wParam, lParam); | 3545 return qxeDefWindowProc (hwnd, message_, wParam, lParam); |
3075 } | 3546 } |
3076 return (0); | 3547 return (0); |
3077 } | 3548 } |
3078 | 3549 |
3079 | 3550 |
3116 { | 3587 { |
3117 /* This simple caching mechanism saves 10% of CPU | 3588 /* This simple caching mechanism saves 10% of CPU |
3118 time when a key typed at autorepeat rate of 30 cps! */ | 3589 time when a key typed at autorepeat rate of 30 cps! */ |
3119 static HKL last_hkl = 0; | 3590 static HKL last_hkl = 0; |
3120 static int last_hkl_has_AltGr; | 3591 static int last_hkl_has_AltGr; |
3121 HKL current_hkl = (HKL) -1; | 3592 HKL current_hkl = GetKeyboardLayout (0); |
3122 | 3593 |
3123 if (xGetKeyboardLayout) /* not in NT 3.5 */ | |
3124 current_hkl = xGetKeyboardLayout (0); | |
3125 if (current_hkl != last_hkl) | 3594 if (current_hkl != last_hkl) |
3126 { | 3595 { |
3127 int c; | 3596 int c; |
3128 last_hkl_has_AltGr = 0; | 3597 last_hkl_has_AltGr = 0; |
3129 /* In this loop, we query whether a character requires | 3598 /* In this loop, we query whether a character requires |
3143 | 3612 |
3144 | 3613 |
3145 /* Returns the state of the modifier keys in the format expected by the | 3614 /* Returns the state of the modifier keys in the format expected by the |
3146 * Lisp_Event key_data, button_data and motion_data modifiers member */ | 3615 * Lisp_Event key_data, button_data and motion_data modifiers member */ |
3147 static int | 3616 static int |
3148 mswindows_modifier_state (BYTE* keymap, DWORD fwKeys, int has_AltGr) | 3617 mswindows_modifier_state (BYTE *keymap, DWORD fwKeys, int has_AltGr) |
3149 { | 3618 { |
3150 int mods = 0; | 3619 int mods = 0; |
3151 int keys_is_real = 0; | 3620 int keys_is_real = 0; |
3152 BYTE keymap2[256]; | 3621 BYTE keymap2[256]; |
3153 | 3622 |
3221 } | 3690 } |
3222 else | 3691 else |
3223 { | 3692 { |
3224 switch (mswindows_key) | 3693 switch (mswindows_key) |
3225 { | 3694 { |
3695 | |
3696 #if 0 | |
3697 VK_LBUTTON: | |
3698 VK_RBUTTON: | |
3699 VK_CANCEL: | |
3700 VK_MBUTTON: | |
3701 VK_XBUTTON1: | |
3702 VK_XBUTTON2: | |
3703 #endif /* 0 */ | |
3704 | |
3226 case VK_BACK: return QKbackspace; | 3705 case VK_BACK: return QKbackspace; |
3227 case VK_TAB: return QKtab; | 3706 case VK_TAB: return QKtab; |
3707 /* #### Officially 0A (and 0B too) are "reserved". */ | |
3228 case '\n': return QKlinefeed; | 3708 case '\n': return QKlinefeed; |
3229 case VK_CLEAR: return KEYSYM ("clear"); | 3709 case VK_CLEAR: return KEYSYM ("clear"); |
3230 case VK_RETURN: return QKreturn; | 3710 case VK_RETURN: return QKreturn; |
3711 | |
3712 #if 0 | |
3713 VK_SHIFT: "shift" | |
3714 VK_CONTROL: "control" | |
3715 VK_MENU: "alt" | |
3716 #endif /* 0 */ | |
3717 | |
3231 case VK_PAUSE: return KEYSYM ("pause"); | 3718 case VK_PAUSE: return KEYSYM ("pause"); |
3719 | |
3720 #if 0 | |
3721 VK_CAPITAL: "caps-lock" | |
3722 VK_KANA: IME Kana mode | |
3723 VK_HANGUEL: IME Hanguel mode (maintained for compatibility; use VK_HANGUL) | |
3724 VK_HANGUL: IME Hangul mode | |
3725 VK_JUNJA: IME Junja mode | |
3726 VK_FINAL: IME final mode | |
3727 VK_HANJA: IME Hanja mode | |
3728 VK_KANJI: IME Kanji mode | |
3729 #endif /* 0 */ | |
3730 | |
3232 case VK_ESCAPE: return QKescape; | 3731 case VK_ESCAPE: return QKescape; |
3732 | |
3733 #if 0 | |
3734 VK_CONVERT: IME convert | |
3735 VK_NONCONVERT: IME nonconvert | |
3736 VK_ACCEPT: IME accept | |
3737 VK_MODECHANGE: IME mode change request | |
3738 #endif /* 0 */ | |
3739 | |
3233 case VK_SPACE: return QKspace; | 3740 case VK_SPACE: return QKspace; |
3234 case VK_PRIOR: return KEYSYM ("kp-prior"); | 3741 case VK_PRIOR: return KEYSYM ("kp-prior"); |
3235 case VK_NEXT: return KEYSYM ("kp-next"); | 3742 case VK_NEXT: return KEYSYM ("kp-next"); |
3236 case VK_END: return KEYSYM ("kp-end"); | 3743 case VK_END: return KEYSYM ("kp-end"); |
3237 case VK_HOME: return KEYSYM ("kp-home"); | 3744 case VK_HOME: return KEYSYM ("kp-home"); |
3244 case VK_EXECUTE: return KEYSYM ("execute"); | 3751 case VK_EXECUTE: return KEYSYM ("execute"); |
3245 case VK_SNAPSHOT: return KEYSYM ("print"); | 3752 case VK_SNAPSHOT: return KEYSYM ("print"); |
3246 case VK_INSERT: return KEYSYM ("kp-insert"); | 3753 case VK_INSERT: return KEYSYM ("kp-insert"); |
3247 case VK_DELETE: return KEYSYM ("kp-delete"); | 3754 case VK_DELETE: return KEYSYM ("kp-delete"); |
3248 case VK_HELP: return KEYSYM ("help"); | 3755 case VK_HELP: return KEYSYM ("help"); |
3756 #if 0 | |
3757 '0' through '9': numeric keys | |
3758 'A' through 'Z': alphabetic keys | |
3759 VK_LWIN: "lwin" | |
3760 VK_RWIN: "rwin" | |
3761 VK_APPS: "apps" | |
3762 VK_SLEEP: "sleep" | |
3763 #endif /* 0 */ | |
3249 case VK_NUMPAD0: return KEYSYM ("kp-0"); | 3764 case VK_NUMPAD0: return KEYSYM ("kp-0"); |
3250 case VK_NUMPAD1: return KEYSYM ("kp-1"); | 3765 case VK_NUMPAD1: return KEYSYM ("kp-1"); |
3251 case VK_NUMPAD2: return KEYSYM ("kp-2"); | 3766 case VK_NUMPAD2: return KEYSYM ("kp-2"); |
3252 case VK_NUMPAD3: return KEYSYM ("kp-3"); | 3767 case VK_NUMPAD3: return KEYSYM ("kp-3"); |
3253 case VK_NUMPAD4: return KEYSYM ("kp-4"); | 3768 case VK_NUMPAD4: return KEYSYM ("kp-4"); |
3284 case VK_F20: return KEYSYM ("f20"); | 3799 case VK_F20: return KEYSYM ("f20"); |
3285 case VK_F21: return KEYSYM ("f21"); | 3800 case VK_F21: return KEYSYM ("f21"); |
3286 case VK_F22: return KEYSYM ("f22"); | 3801 case VK_F22: return KEYSYM ("f22"); |
3287 case VK_F23: return KEYSYM ("f23"); | 3802 case VK_F23: return KEYSYM ("f23"); |
3288 case VK_F24: return KEYSYM ("f24"); | 3803 case VK_F24: return KEYSYM ("f24"); |
3804 | |
3805 #if 0 | |
3806 VK_NUMLOCK: 90 NUM LOCK key | |
3807 VK_SCROLL: 91 SCROLL LOCK key | |
3808 92~96 OEM specific; | |
3809 VK_LSHIFT: | |
3810 VK_RSHIFT: | |
3811 VK_LCONTROL: | |
3812 VK_RCONTROL: | |
3813 VK_LMENU: | |
3814 VK_RMENU: | |
3815 | |
3816 #ifdef VK_BROWSER_BACK /* Windows 2000 only */ | |
3817 VK_BROWSER_BACK: Browser Back key | |
3818 VK_BROWSER_FORWARD: Browser Forward key | |
3819 VK_BROWSER_REFRESH: Browser Refresh key | |
3820 VK_BROWSER_STOP: Browser Stop key | |
3821 VK_BROWSER_SEARCH: Browser Search key | |
3822 VK_BROWSER_FAVORITES: Browser Favorites key | |
3823 VK_BROWSER_HOME: Browser Start and Home key | |
3824 VK_VOLUME_MUTE: Volume Mute key | |
3825 VK_VOLUME_DOWN: Volume Down key | |
3826 VK_VOLUME_UP: Volume Up key | |
3827 VK_MEDIA_NEXT_TRACK: Next Track key | |
3828 VK_MEDIA_PREV_TRACK: Previous Track key | |
3829 VK_MEDIA_STOP: Stop Media key | |
3830 VK_MEDIA_PLAY_PAUSE: Play/Pause Media key | |
3831 VK_LAUNCH_MAIL: Start Mail key | |
3832 VK_LAUNCH_MEDIA_SELECT: Select Media key | |
3833 VK_LAUNCH_APP1: Start Application 1 key | |
3834 VK_LAUNCH_APP2: Start Application 2 key | |
3835 B8-B9 Reserved; | |
3836 VK_OEM_1: For the US standard keyboard, the ';:' key | |
3837 VK_OEM_PLUS: For any country/region, the '+' key | |
3838 VK_OEM_COMMA: For any country/region, the ',' key | |
3839 VK_OEM_MINUS: For any country/region, the '-' key | |
3840 VK_OEM_PERIOD: For any country/region, the '.' key | |
3841 VK_OEM_2: For the US standard keyboard, the '/?' key | |
3842 VK_OEM_3: For the US standard keyboard, the '`~' key | |
3843 C1~D7 Reserved; | |
3844 D8~DA Unassigned; | |
3845 VK_OEM_4: For the US standard keyboard, the '[{' key | |
3846 VK_OEM_5: For the US standard keyboard, the '\|' key | |
3847 VK_OEM_6: For the US standard keyboard, the ']}' key | |
3848 VK_OEM_7: For the US standard keyboard, the 'single-quote/double-quote' key | |
3849 VK_OEM_8: | |
3850 E0 Reserved; | |
3851 E1 OEM specific; | |
3852 VK_OEM_102: Either the angle bracket key or the backslash key on the RT 102-key keyboard | |
3853 E3~E4 OEM specific; | |
3854 #endif /* VK_BROWSER_BACK */ | |
3855 VK_PROCESSKEY: E5 Windows 95/98, Windows NT 4.0, Windows 2000: IME PROCESS key | |
3856 E6 OEM specific; | |
3857 VK_PACKET: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP | |
3858 E8 Unassigned; | |
3859 E9~F5 OEM specific; | |
3860 VK_ATTN: Attn key | |
3861 VK_CRSEL: CrSel key | |
3862 VK_EXSEL: ExSel key | |
3863 VK_EREOF: Erase EOF key | |
3864 VK_PLAY: Play key | |
3865 VK_ZOOM: Zoom key | |
3866 VK_NONAME: Reserved for future use | |
3867 VK_PA1: PA1 key | |
3868 VK_OEM_CLEAR: Clear key | |
3869 #endif /* 0 */ | |
3870 | |
3289 } | 3871 } |
3290 } | 3872 } |
3291 return Qnil; | 3873 return Qnil; |
3292 } | 3874 } |
3293 | 3875 |
3305 * Find the frame that matches the supplied mswindows window handle | 3887 * Find the frame that matches the supplied mswindows window handle |
3306 */ | 3888 */ |
3307 Lisp_Object | 3889 Lisp_Object |
3308 mswindows_find_frame (HWND hwnd) | 3890 mswindows_find_frame (HWND hwnd) |
3309 { | 3891 { |
3310 LONG l = GetWindowLong (hwnd, XWL_FRAMEOBJ); | 3892 LONG l = qxeGetWindowLong (hwnd, XWL_FRAMEOBJ); |
3311 Lisp_Object f; | 3893 Lisp_Object f; |
3312 if (l == 0) | 3894 if (l == 0) |
3313 { | 3895 { |
3314 /* We are in progress of frame creation. Return the frame | 3896 /* We are in progress of frame creation. Return the frame |
3315 being created, as it still not remembered in the window | 3897 being created, as it still not remembered in the window |
3397 * Handle a magic event off the dispatch queue. | 3979 * Handle a magic event off the dispatch queue. |
3398 */ | 3980 */ |
3399 static void | 3981 static void |
3400 emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event) | 3982 emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event) |
3401 { | 3983 { |
3402 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)) | 3984 switch (EVENT_MSWINDOWS_MAGIC_TYPE (emacs_event)) |
3403 { | 3985 { |
3404 case XM_BUMPQUEUE: | 3986 case XM_BUMPQUEUE: |
3405 break; | 3987 break; |
3406 | 3988 |
3407 case WM_PAINT: | 3989 case WM_PAINT: |
3415 case WM_SETFOCUS: | 3997 case WM_SETFOCUS: |
3416 case WM_KILLFOCUS: | 3998 case WM_KILLFOCUS: |
3417 { | 3999 { |
3418 Lisp_Object frame = EVENT_CHANNEL (emacs_event); | 4000 Lisp_Object frame = EVENT_CHANNEL (emacs_event); |
3419 struct frame *f = XFRAME (frame); | 4001 struct frame *f = XFRAME (frame); |
3420 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS); | 4002 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE (emacs_event) == WM_SETFOCUS); |
3421 Lisp_Object conser; | 4003 Lisp_Object conser; |
3422 struct gcpro gcpro1; | 4004 struct gcpro gcpro1; |
3423 | 4005 |
3424 /* On focus change, clear all memory of sticky modifiers | 4006 /* On focus change, clear all memory of sticky modifiers |
3425 to avoid non-intuitive behavior. */ | 4007 to avoid non-intuitive behavior. */ |
3438 | 4020 |
3439 case XM_MAPFRAME: | 4021 case XM_MAPFRAME: |
3440 case XM_UNMAPFRAME: | 4022 case XM_UNMAPFRAME: |
3441 { | 4023 { |
3442 Lisp_Object frame = EVENT_CHANNEL (emacs_event); | 4024 Lisp_Object frame = EVENT_CHANNEL (emacs_event); |
3443 va_run_hook_with_args (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) | 4025 va_run_hook_with_args (EVENT_MSWINDOWS_MAGIC_TYPE (emacs_event) |
3444 == XM_MAPFRAME ? | 4026 == XM_MAPFRAME ? |
3445 Qmap_frame_hook : Qunmap_frame_hook, | 4027 Qmap_frame_hook : Qunmap_frame_hook, |
3446 1, frame); | 4028 1, frame); |
3447 } | 4029 } |
3448 break; | 4030 break; |
3571 Vquit_flag = critical_p ? Qcritical : Qt; | 4153 Vquit_flag = critical_p ? Qcritical : Qt; |
3572 } | 4154 } |
3573 } | 4155 } |
3574 | 4156 |
3575 USID | 4157 USID |
3576 emacs_mswindows_create_stream_pair (void* inhandle, void* outhandle, | 4158 emacs_mswindows_create_stream_pair (void *inhandle, void *outhandle, |
3577 Lisp_Object* instream, | 4159 Lisp_Object *instream, |
3578 Lisp_Object* outstream, | 4160 Lisp_Object *outstream, |
3579 int flags) | 4161 int flags) |
3580 { | 4162 { |
3581 /* Handles for streams */ | 4163 /* Handles for streams */ |
3582 HANDLE hin, hout; | 4164 HANDLE hin, hout; |
3583 /* fds. These just stored along with the streams, and are closed in | 4165 /* fds. These just stored along with the streams, and are closed in |
3659 : get_ntpipe_input_stream_param (XLSTREAM (instream))); | 4241 : get_ntpipe_input_stream_param (XLSTREAM (instream))); |
3660 int out = (NILP(outstream) ? -1 | 4242 int out = (NILP(outstream) ? -1 |
3661 : filedesc_stream_fd (XLSTREAM (outstream))); | 4243 : filedesc_stream_fd (XLSTREAM (outstream))); |
3662 | 4244 |
3663 if (in >= 0) | 4245 if (in >= 0) |
3664 close (in); | 4246 retry_close (in); |
3665 if (out != in && out >= 0) | 4247 if (out != in && out >= 0) |
3666 close (out); | 4248 retry_close (out); |
3667 #endif | 4249 #endif |
3668 | 4250 |
3669 return (NILP (instream) | 4251 return (NILP (instream) |
3670 ? USID_DONTHASH | 4252 ? USID_DONTHASH |
3671 #if defined(HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) | 4253 #if defined(HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) |
3691 #if 0 /* #### */ | 4273 #if 0 /* #### */ |
3692 Lisp_Object instr, outstr; | 4274 Lisp_Object instr, outstr; |
3693 | 4275 |
3694 get_process_streams (p, &instr, &outstr); | 4276 get_process_streams (p, &instr, &outstr); |
3695 /* if it still has fds, then it hasn't been killed yet. */ | 4277 /* if it still has fds, then it hasn't been killed yet. */ |
3696 assert (NILP(instr)); | 4278 assert (NILP (instr)); |
3697 assert (NILP(outstr)); | 4279 assert (NILP (outstr)); |
3698 | 4280 |
3699 /* #### More checks here */ | 4281 /* #### More checks here */ |
3700 #endif | 4282 #endif |
3701 } | 4283 } |
3702 #endif | 4284 #endif |
4039 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; | 4621 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; |
4040 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; | 4622 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; |
4041 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; | 4623 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; |
4042 #ifdef HAVE_MSG_SELECT | 4624 #ifdef HAVE_MSG_SELECT |
4043 mswindows_event_stream->select_process_cb = | 4625 mswindows_event_stream->select_process_cb = |
4044 (void (*)(Lisp_Process*))event_stream_unixoid_select_process; | 4626 (void (*)(Lisp_Process *)) event_stream_unixoid_select_process; |
4045 mswindows_event_stream->unselect_process_cb = | 4627 mswindows_event_stream->unselect_process_cb = |
4046 (void (*)(Lisp_Process*))event_stream_unixoid_unselect_process; | 4628 (void (*)(Lisp_Process *)) event_stream_unixoid_unselect_process; |
4047 mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair; | 4629 mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair; |
4048 mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair; | 4630 mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair; |
4049 #else | 4631 #else |
4050 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; | 4632 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; |
4051 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; | 4633 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; |
4161 | 4743 |
4162 void | 4744 void |
4163 init_event_mswindows_late (void) | 4745 init_event_mswindows_late (void) |
4164 { | 4746 { |
4165 #ifdef HAVE_MSG_SELECT | 4747 #ifdef HAVE_MSG_SELECT |
4166 windows_fd = open("/dev/windows", O_RDONLY | O_NONBLOCK, 0); | 4748 windows_fd = retry_open ("/dev/windows", O_RDONLY | O_NONBLOCK, 0); |
4167 assert (windows_fd>=0); | 4749 assert (windows_fd>=0); |
4168 FD_SET (windows_fd, &input_wait_mask); | 4750 FD_SET (windows_fd, &input_wait_mask); |
4169 FD_ZERO(&zero_mask); | 4751 FD_ZERO(&zero_mask); |
4170 #endif | 4752 #endif |
4171 | 4753 |