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