*** empty log message ***
[dana/urxvt.git] / W11 / w32 / event.c
1
2 #include <X11/Xlib.h>
3 #include <X11/Xatom.h>
4 #include <X11/keysymdef.h>
5 #include "ntdef.h"
6
7 /* a crude method to avoid losing the selection when
8    calling EmptyClipboard, which is necessary to do
9    every time the selection content changes, otherwise
10    windows apps use a cached copy of the selection */
11 static volatile int destroyClipboardCatcher = 0;
12 static NT_window *NT_CWIN = NULL;
13 void
14 catchNextDestroyClipboard()
15 {
16     destroyClipboardCatcher=1;
17 }
18
19 typedef struct WinEvent_
20 {
21     NT_window *window;
22     UINT message;
23     UINT wParam;
24     LONG lParam;
25 } WinEvent;
26
27 #define W11_QSIZE 100
28 typedef struct WinEventQ_
29 {
30     int num;
31     int avail;
32     int next;
33     int count;
34     int dispatch;
35     proto_W11EventHandler *handler;
36     WinEvent list[W11_QSIZE];
37 } WinEventQ;
38
39 static WinEventQ *wineventq = NULL;
40
41 void
42 initQ() {
43     int i;
44     WinEventQ *q = (WinEventQ *)allocateMemory(sizeof(WinEventQ));
45     q->num=W11_QSIZE-1;
46     q->avail=0;
47     q->next=0;
48     q->count=0;
49     q->dispatch=0;
50     q->handler=NULL;
51     for (i=0; i<W11_QSIZE; i++) {
52         q->list[i].message=0;
53         q->list[i].window = NULL;
54     }
55     wineventq = q;
56 }
57
58 static int
59 getQdEvent(WinEventQ *q, XEvent *ev)
60 {
61     WinEvent we;
62     if (q->count<=0) {
63         cjh_printf("Queue is empty\n");
64         return 0;
65     }
66     we = q->list[q->next];
67     WinEventToXEvent(&we,ev);
68     q->next++;
69     q->count--;
70     if (q->next>q->num) q->next=0;      
71     return 1;
72 }
73
74 static void
75 QSendEvent(WinEventQ *q) 
76 {
77     XEvent e;
78     if (q->handler != NULL) {
79         if (getQdEvent(q,&e)) (q->handler)(&e);
80     }
81 }
82
83 static int
84 QEvent(WinEventQ *q, NT_window *window,UINT message,UINT wParam,LONG lParam)
85 {
86     q->list[q->avail].window=window;
87     q->list[q->avail].message=message;
88     q->list[q->avail].wParam=wParam;
89     q->list[q->avail].lParam=lParam;
90     q->avail++; q->count++;
91     if (q->avail>q->num) q->avail=0;
92     if (q->dispatch) QSendEvent(q);
93     return 1;
94 }
95
96
97 /* Allow application to install an event handler call back.
98    This will make some actions such as moving the window work
99    better.
100
101    The event handler should look like:
102    void process_xevent(XEvent *ev) { }
103
104    To install it:
105    W11AddEventHandler(display,process_xevent);
106
107    The specific problem is that calling DefWindowProc()
108    in response to a WM_SYSCOMMAND will cause windows to run its
109    own event loop waiting for the mouse up event.  The application
110    therefore cannot rely on it's main event loop to get run for
111    each event.  Without running multiple threads, or setjmp, there
112    is little recourse for alerting the application in the
113    traditional X manner to Expose events while the window is
114    being moved.
115 */
116
117 void W11AddEventHandler(Display *d, proto_W11EventHandler *ev) 
118 {
119     wineventq->handler = ev;
120 }
121
122
123 static void
124 doTranslateMessage(MSG *m)
125 {
126         if ((m->message == WM_KEYDOWN) && 
127             ((m->wParam == VK_BACK) ||
128              (((m->wParam == VK_ADD) || (m->wParam == VK_SUBTRACT)) &&
129               (GetKeyState(VK_SHIFT) & 0x8000)))) return;
130         if ((m->message == WM_SYSKEYDOWN) && (m->wParam == VK_F10))
131         {
132             m->message = WM_KEYDOWN;
133             return;
134         }
135         TranslateMessage(m);
136 }
137
138 static LONG
139 NT_default(HWND hWnd,UINT message,UINT wParam,LONG lParam)
140 {
141     return DefWindowProc(hWnd, message, wParam, lParam);
142 }
143
144 static void
145 NT_wakeup(HWND hWnd) 
146 {
147     PostMessage(hWnd,USR_WakeUp,0,0L);
148 }
149
150 /*****************************************************************\
151
152         Function: MainWndProc
153         Inputs:   Window handle, message, message parameters.
154
155         Comments: This is called when messages are sent to the application
156                   but not to the application's message queue.  If an
157                   event can be processed, it is done here.  The equivalent
158                   XEvent is filled out in l_event, which is picked up
159                   in the X event routines.  Some events are not received
160                   from Windows, eg Enter/LeaveNotify, so these are made
161                   up as required.
162
163         Caution:  The application does not see HWND, but Window.
164
165 \*****************************************************************/
166
167 /* queued messages
168    WM_KEYDOWN
169    WM_KEYUP
170    WM_CHAR
171    WM_MOUSEMOVE
172    WM_BUTTONxx
173    WM_TIMER
174    WM_PAINT
175    WM_QUIT
176    */
177
178 LONG NT_handleMsg(
179     HWND hWnd,            /* window handle                   */
180     UINT message,                 /* type of message                 */
181     UINT wParam,                  /* additional information          */
182     LONG lParam)                  /* additional information          */
183 {
184     RECT rect;
185     WINDOWPOS *posStruct;
186     unsigned long int st=0L;
187     NT_window *window;
188     long mask;
189     PAINTSTRUCT paintStruct;
190
191     /*  if (message == WM_CLOSE) exit(0); */
192         
193     window = NT_find_window_from_id(hWnd);
194     if (window == NULL) return  (NT_default(hWnd, message, wParam, lParam));
195
196     mask = window->mask;
197         
198     switch (message) {
199         /* we'll handle these, later */
200         case WM_KILLFOCUS:
201             QEvent(wineventq,window,message,wParam,lParam);
202             NT_wakeup(hWnd);
203             break;
204         case WM_SETFOCUS:
205         case WM_QUIT:
206         case WM_CLOSE:
207         case WM_DESTROY:
208         case WM_SYSCHAR: /* alt-keys go here */
209         case WM_CHAR:
210         case WM_LBUTTONDBLCLK:
211         case WM_MBUTTONDBLCLK:
212         case WM_RBUTTONDBLCLK:
213         case USR_MapNotify:
214         case USR_EnterNotify:
215         case WM_MOVE:
216 #if defined(WIN9X)
217         case WM_SIZING:
218 #endif                  
219         case WM_SIZE:                   
220             QEvent(wineventq,window,message,wParam,lParam);
221             break;
222         case WM_DESTROYCLIPBOARD:
223             if (destroyClipboardCatcher)
224                 destroyClipboardCatcher=0;
225             else {
226                 QEvent(wineventq,window,message,wParam,lParam);
227                 NT_wakeup(hWnd);
228             }
229             break;
230         case WM_PAINT:
231             BeginPaint(hWnd,&paintStruct);
232             FillRect(paintStruct.hdc, &paintStruct.rcPaint,window->bg);
233             QEvent(wineventq,window,message,
234                    (((paintStruct.rcPaint.right-paintStruct.rcPaint.left)&0xffff) |
235                     (((paintStruct.rcPaint.bottom-paintStruct.rcPaint.top)&0xffff)<<16)),
236                    (((paintStruct.rcPaint.left)&0xffff) | (((paintStruct.rcPaint.top)&0xffff)<<16)));
237
238             EndPaint(hWnd,&paintStruct);
239             break;
240             /* capture the mouse on button down to emulate x */
241         case WM_LBUTTONDOWN:
242         case WM_MBUTTONDOWN:
243         case WM_RBUTTONDOWN:
244             SetCapture(hWnd);
245             QEvent(wineventq,window,message,wParam,lParam);
246             break;
247         case WM_MBUTTONUP:
248         case WM_LBUTTONUP:
249         case WM_RBUTTONUP:
250             ReleaseCapture();
251             QEvent(wineventq,window,message,wParam,lParam);
252             break;
253         case WM_MOUSEMOVE:
254             if ((mask&PointerMotionMask) ||
255                 ((mask&Button1MotionMask)&& (wParam&MK_LBUTTON)) ||
256                 ((mask&Button2MotionMask)&& (wParam&MK_MBUTTON)) ||
257                 ((mask&Button3MotionMask)&& (wParam&MK_RBUTTON)) ||
258                 ((mask&ButtonMotionMask)&&((wParam&(MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))))
259                 )
260                 QEvent(wineventq,window,message,wParam,lParam);
261             else
262                 return (NT_default(hWnd, message, wParam, lParam));
263             break;
264         case WM_MOUSEWHEEL:
265             /* this event only seems to go to the top most window.
266                see if child windows accept it. */
267             window = NT_find_child(window,ButtonPressMask|Button2MotionMask|Button3MotionMask,
268                                    ButtonPressMask|Button3MotionMask );
269             if (window && ((window->mask)&ButtonPressMask)) 
270                 QEvent(wineventq,window,message,wParam,lParam);
271             else
272                 return (NT_default(hWnd, message, wParam, lParam));
273             break;
274         case WM_ERASEBKGND:
275             /* don't erase the background */
276             return 1;
277             break;
278         case WM_SYSCOMMAND:
279             wineventq->dispatch++;
280             NT_default(hWnd, message, wParam, lParam);
281             wineventq->dispatch--;
282             break;
283         case WM_KEYDOWN:
284             switch (wParam)
285             {
286                 case VK_CANCEL:
287                 case VK_CLEAR:
288                 case VK_PAUSE:
289                 case VK_PRIOR:
290                 case VK_NEXT:
291                 case VK_END:
292                 case VK_HOME:
293                 case VK_LEFT:
294                 case VK_UP:
295                 case VK_RIGHT:
296                 case VK_DOWN:
297                 case VK_SELECT:
298                 case VK_PRINT:
299                 case VK_EXECUTE:
300                 case VK_INSERT:
301                 case VK_DELETE:
302                 case VK_HELP:
303                 case VK_NUMLOCK:
304                 case VK_SCROLL:
305                 case VK_BACK:
306                 case VK_F1:
307                 case VK_F2:
308                 case VK_F3:
309                 case VK_F4:
310                 case VK_F5:
311                 case VK_F6:
312                 case VK_F7:
313                 case VK_F8:
314                 case VK_F9:
315                 case VK_F10:
316                 case VK_F11:
317                 case VK_F12:
318                 case VK_ADD:
319                 case VK_SUBTRACT:
320                     QEvent(wineventq,window,message,wParam,lParam);
321                     break;
322                 default:
323                     return  (NT_default(hWnd, message, wParam, lParam));
324                     break;
325                                         
326             }
327             break;
328         default:                          /* Passes it on if unproccessed    */
329             return (NT_default(hWnd, message, wParam, lParam));
330     }
331     return 0L;
332 }
333
334 /*****************************************************************\
335
336         Function: NT_get_state
337         Inputs: 
338
339         Comments: Get the keyboard state
340
341 \*****************************************************************/
342
343 static unsigned int
344 NT_get_state()
345 {
346         unsigned int state = 0;
347         if (GetKeyState(VK_SHIFT)   & 0x8000) state |= ShiftMask;
348         if (GetKeyState(VK_CONTROL) & 0x8000)
349         {
350                 if (!(GetKeyState(VK_MENU) & 0x8000)) 
351                         state |= ControlMask;
352         }
353         else if (GetKeyState(VK_MENU)    & 0x8000)
354                 state |= Mod1Mask;
355         if (GetKeyState(VK_CAPITAL) & 0x0001) state |= LockMask;
356         if (GetKeyState(VK_NUMLOCK) & 0x0001) state |= Mod5Mask;
357         if (GetKeyState(VK_SCROLL)  & 0x0001) state |= Mod3Mask;
358         if (GetKeyState(VK_LBUTTON) & 0x8000) state |= Button1Mask;
359         if (GetKeyState(VK_MBUTTON) & 0x8000) state |= Button2Mask;
360         if (GetKeyState(VK_RBUTTON) & 0x8000) state |= Button3Mask;
361         return state;
362 }
363
364 int
365 WinEventToXEvent(
366     WinEvent *we,
367     XEvent *event)
368 {
369     POINT pt;
370     RECT rect;
371     unsigned long int st=0L;
372     UINT key;
373     HWND hWnd;
374     UINT wParam;
375     LONG lParam;
376     NT_window *window;
377         
378     do {                
379         if (event==NULL) break;
380         if (we == NULL) break;
381
382         window = we->window;
383         wParam = we->wParam;
384         lParam = we->lParam;
385                 
386         event->type=-1;
387         event->xbutton.subwindow = None;
388         hWnd = window->w;
389                 
390         switch (we->message) {
391             case WM_SETFOCUS:
392                 event->type=FocusIn;
393                 event->xfocus.window=(Window)window;
394                 break;
395             case WM_KILLFOCUS:
396                 event->type=FocusOut;
397                 event->xfocus.window=(Window)window;
398                 break;  
399                                 /*      case WM_ERASEBKGND: */
400             case WM_PAINT:
401                 event->type=Expose;
402                 event->xexpose.x=LOWORD(lParam); /* right */
403                 event->xexpose.y=HIWORD(lParam); /* top */
404                 event->xexpose.width=LOWORD(wParam);
405                 event->xexpose.height=HIWORD(wParam);
406                 event->xexpose.count=0;
407                 event->xexpose.window=(Window)window;
408                 break;
409             case WM_LBUTTONDOWN:
410             case WM_LBUTTONDBLCLK:
411                 event->type = ButtonPress;
412                 event->xbutton.x = LOWORD (lParam);
413                 event->xbutton.y = HIWORD (lParam);
414                 if ( wParam & MK_SHIFT )
415                     event->xbutton.button=Button2;
416                 else
417                     event->xbutton.button=Button1;
418                 event->xbutton.window = (Window)window;
419                 event->xbutton.time=GetTickCount();
420                 break;
421             case WM_LBUTTONUP:
422                 event->type=ButtonRelease;
423                 event->xbutton.x=LOWORD(lParam);
424                 event->xbutton.y=HIWORD (lParam);
425                 if ( wParam & MK_SHIFT )
426                     event->xbutton.button=Button2;
427                 else
428                     event->xbutton.button=Button1;
429                 event->xbutton.window=(Window)window;
430                 event->xbutton.time=GetTickCount();
431                 break;
432             case WM_MBUTTONDOWN:
433             case WM_MBUTTONDBLCLK:
434                 event->type=ButtonPress;
435                 event->xbutton.x=LOWORD(lParam);
436                 event->xbutton.y=HIWORD (lParam);
437                 event->xbutton.button=Button2;
438                 event->xbutton.window=(Window)window;
439                 event->xbutton.time=GetTickCount();
440                 break;
441             case WM_MBUTTONUP:
442                 event->type=ButtonRelease;
443                 event->xbutton.x=LOWORD(lParam);
444                 event->xbutton.y=HIWORD (lParam);
445                 event->xbutton.button=Button2;
446                 event->xbutton.window=(Window)window;
447                 event->xbutton.time=GetTickCount();
448                 break;
449             case WM_RBUTTONDOWN:
450             case WM_RBUTTONDBLCLK:
451                 event->type=ButtonPress;
452                 event->xbutton.x=LOWORD(lParam);
453                 event->xbutton.y=HIWORD (lParam);
454                 event->xbutton.button=Button3;
455                 event->xbutton.window=(Window)window;
456                 event->xbutton.time=GetTickCount();
457                 break;
458             case WM_RBUTTONUP:
459                 event->type=ButtonRelease;
460                 event->xbutton.x=LOWORD(lParam);
461                 event->xbutton.y=HIWORD (lParam);
462                 event->xbutton.button=Button3;
463                 event->xbutton.window=(Window)window;
464                 event->xbutton.time=GetTickCount();
465                 break;
466             case WM_MOUSEMOVE:
467                 if (hWnd!=(HWND)NT_CWIN)  /* Mouse in different window? */
468                 {
469                     if (NT_CWIN==NULL) /* No previous window */
470                     {
471                         event->type = EnterNotify;
472                         event->xcrossing.x = LOWORD(lParam);
473                         event->xcrossing.y = HIWORD(lParam);
474                         event->xcrossing.window = (Window)window;
475                     }
476                     else
477                     {
478                         event->type=LeaveNotify;
479                         event->xcrossing.x=LOWORD(lParam);
480                         event->xcrossing.y=HIWORD(lParam);
481                         event->xcrossing.window = (Window)NT_find_window_from_id(NT_CWIN);
482                     }
483                 }
484                 else
485                 {
486                     event->type=MotionNotify;    /* Fill out mouse event */
487                     event->xmotion.window=(Window)window;
488                     event->xmotion.x=pt.x=LOWORD(lParam);
489                     event->xmotion.y=pt.y=HIWORD(lParam);
490                     event->xmotion.time=GetTickCount();
491                     ClientToScreen(hWnd,&pt);     /* Translate coordinates */
492                     event->xmotion.x_root=pt.x;
493                     event->xmotion.y_root=pt.y;
494                     if (wParam&MK_CONTROL)
495                         st|=ControlMask;
496                     if (wParam&MK_SHIFT)
497                         st|=ShiftMask;
498                     if (wParam&MK_LBUTTON)
499                         st|=Button1Mask;
500                     if (wParam&MK_MBUTTON)
501                         st|=Button2Mask;
502                     if (wParam&MK_RBUTTON)
503                         st|=Button3Mask;
504                     event->xmotion.state=st;
505                 }
506                 NT_CWIN=(NT_window *)hWnd;
507                 break;
508             case WM_MOUSEWHEEL:
509                 event->type=ButtonRelease;
510                 event->xbutton.x=LOWORD(lParam);
511                 event->xbutton.y=HIWORD (lParam);
512                 event->xbutton.button=HIWORD(wParam)>32768?Button5:Button4;
513                 event->xbutton.window=(Window)window;
514                 event->xbutton.time=GetTickCount();
515                 if (wParam&MK_CONTROL)
516                     st|=ControlMask;
517                 if (wParam&MK_SHIFT)
518                     st|=ShiftMask;
519                 if (wParam&MK_LBUTTON)
520                     st|=Button1Mask;
521                 if (wParam&MK_MBUTTON)
522                     st|=Button2Mask;
523                 if (wParam&MK_RBUTTON)
524                     st|=Button3Mask;
525                 event->xbutton.state=st;
526                 break;
527             case WM_SYSCHAR:
528             case WM_CHAR:
529                 event->type=KeyPress;
530                 event->xkey.state=NT_get_state();
531                 event->xkey.x=event->xkey.y=0; /* Inside the window */
532                 event->xkey.keycode=LOWORD(wParam);
533                 if (GetKeyState(VK_CONTROL) & 0x8000) {
534                     if (event->xkey.keycode == 32) { event->xkey.keycode=0; }
535                     if (event->xkey.keycode >255 ) { event->xkey.keycode=0; }
536                 }
537                 event->xkey.window=(Window)window;
538                 break;
539             case WM_KEYDOWN:
540                 event->type=KeyPress;
541                 switch (wParam)
542                 {
543                     case VK_CANCEL:  key=XK_Cancel;      break;
544                     case VK_CLEAR:   key=XK_Clear;       break;
545                 /*  causes AltGr to create a keypress */
546                 /*  case VK_MENU:    key=XK_Alt_L;       break;*/
547                     case VK_PAUSE:   key=XK_Pause;       break;
548                     case VK_PRIOR:   key=XK_Prior;       break;
549                     case VK_NEXT:    key=XK_Next;        break;
550                     case VK_END:     key=XK_End;         break;
551                     case VK_HOME:    key=XK_Home;        break;
552                     case VK_LEFT:    key=XK_Left;        break;
553                     case VK_UP:      key=XK_Up;          break;
554                     case VK_RIGHT:   key=XK_Right;       break;
555                     case VK_DOWN:    key=XK_Down;        break;
556                     case VK_SELECT:  key=XK_Select;      break;
557                     case VK_PRINT:   key=XK_Print;       break;
558                     case VK_EXECUTE: key=XK_Execute;     break;
559                     case VK_INSERT:  key=XK_Insert;      break;
560                     case VK_DELETE:  key=XK_Delete;      break;
561                     case VK_HELP:    key=XK_Help;        break;
562                     case VK_NUMLOCK: key=XK_Num_Lock;    break;
563                     case VK_SCROLL:  key=XK_Scroll_Lock; break;
564                     case VK_BACK:    key=XK_BackSpace; break;
565                     case VK_F1:      key=XK_F1;          break;
566                     case VK_F2:      key=XK_F2;          break;
567                     case VK_F3:      key=XK_F3;          break;
568                     case VK_F4:      key=XK_F4;          break;
569                     case VK_F5:      key=XK_F5;          break;
570                     case VK_F6:      key=XK_F6;          break;
571                     case VK_F7:      key=XK_F7;          break;
572                     case VK_F8:      key=XK_F8;          break;
573                     case VK_F9:      key=XK_F9;          break;
574                     case VK_F10:     key=XK_F10;         break;
575                     case VK_F11:     key=XK_F11;         break;
576                     case VK_F12:     key=XK_F12;         break;
577                     case VK_ADD:     key=XK_KP_Add;      break;
578                     case VK_SUBTRACT:key=XK_KP_Subtract; break;
579                     default:         key=0;              break;
580                 }
581                 if (key == 0) {
582                     event->type = -1;
583                 }
584                 else
585                 {
586                     event->xkey.keycode=key;
587                     event->xkey.window=(Window)window;
588                     event->xkey.state=NT_get_state();
589                     event->xkey.x=event->xkey.y=0; /* Inside the window */
590                 }
591                 break;
592             case WM_DESTROY:
593             case WM_QUIT:
594             case WM_CLOSE:
595                 event->type = ClientMessage;
596                 event->xclient.format = 32;
597                 event->xclient.data.l[0] = XInternAtom(NULL,"WM_DELETE_WINDOW", FALSE);
598                 break;
599             case USR_EnterNotify:
600                 event->type = EnterNotify;
601                 event->xcrossing.x = LOWORD(lParam);
602                 event->xcrossing.y = HIWORD(lParam);
603                 event->xcrossing.window = (Window)window;
604                 break;
605             case WM_MOVE:
606                 if (window->min==0)
607                 {
608                     window->x =  LOWORD(lParam);
609                     window->y =  HIWORD(lParam);
610                     NT_configureNotify(window,window->x,window->y);
611                     event->type = ConfigureNotify;
612                     event->xconfigure.window = (Window)window;
613                     event->xconfigure.x = 0;  /* client area is always @ 0 */
614                     event->xconfigure.y = 0;
615                     event->xconfigure.width = window->wdth;
616                     event->xconfigure.height = window->hght;
617                     event->xconfigure.above = Above;
618                 }
619                 break;
620             case WM_SIZING:
621                 event->type = ConfigureNotify;
622                 window->wdth =  LOWORD(lParam);
623                 if (window->wdth<window->minx)
624                     window->wdth = window->minx;
625                 window->hght =  HIWORD(lParam);
626                 if (window->hght<window->minx)
627                     window->hght = window->miny;
628                 NT_configureNotify(window,window->x,window->y);
629                 event->xconfigure.window = (Window)window;
630                 event->xconfigure.x = 0;
631                 event->xconfigure.y = 0;
632                 event->xconfigure.width = window->wdth;
633                 event->xconfigure.height = window->hght;
634                 event->xconfigure.above = Above;
635                 break;
636             case WM_SIZE:
637                 switch(wParam)
638                 {
639                     case SIZE_MINIMIZED:
640                         event->type=UnmapNotify;
641                         window->min=1;
642                         break;
643                     default:
644                         event->type = ConfigureNotify;
645                         window->wdth =  LOWORD(lParam);
646                         if (window->wdth<window->minx)
647                             window->wdth = window->minx;
648                         window->hght =  HIWORD(lParam);
649                         if (window->hght<window->minx)
650                             window->hght = window->miny;
651                         event->xconfigure.window = (Window)window;
652                         event->xconfigure.x = 0;
653                         event->xconfigure.y = 0;
654                         event->xconfigure.width = window->wdth;
655                         event->xconfigure.height = window->hght;
656                         event->xconfigure.above = Above;
657 #if !defined(WIN9X)                                             
658                         if (window->min) event->type=MapNotify;
659 #endif                                          
660                         window->min=0;
661                         break;
662                 }
663                 break;
664             case WM_DESTROYCLIPBOARD:
665                 event->type = SelectionClear;
666                 event->xselectionclear.time = GetTickCount();
667                 break;
668             case USR_MapNotify:
669                 event->type=MapNotify;
670                 break;
671             case USR_ConvertSelection:
672                 event->type=SelectionNotify;
673                 event->xselection.requestor = (Window)window;
674                 event->xselection.property = XA_CUT_BUFFER0;                    
675                 break;
676             default:
677                 break;
678         }
679     } while(0);
680     return (event==NULL?0: (event->type==-1?0:1));
681 }
682 /*****************************************************************\
683
684
685         Function: XCheckWindowEvent
686         Inputs:   display, window, event mask.
687         Returned: pointer to filled in event structure, status.
688
689         Comments: This is fudged at the moment to work with the toolkit.
690                   The event system needs rewriting to account properly for
691                   event masks.
692
693 \*****************************************************************/
694
695 BoolDef
696 XCheckTypedEvent(display,ev,rep)
697 Display *display;
698 int ev;
699 XEvent *rep;
700 {
701         xtrace("XCheckTypedEvent\n");
702         return (False);
703 }
704
705 BoolDef
706 XCheckWindowEvent(display,w,emask,ev)
707 Display *display;
708 Window w;
709 long emask;
710 XEvent *ev;
711 {
712         NT_window *ntw=(NT_window *)w;
713         MSG msg;
714         BoolDef status = 0;
715
716         xtrace("XCheckWindowEvent\n");
717         if (emask&0)
718                 if (PeekMessage(&msg,ntw->w,USR_MapNotify,
719                                                 USR_MapNotify,PM_REMOVE)||
720                     PeekMessage(&msg,ntw->w,WM_PAINT,WM_PAINT,PM_REMOVE))
721                 {
722                         cjh_printf("removed message\n");
723                         ev->type=ConfigureNotify;
724                         status = 1;
725                 }
726         return(status);
727 }
728
729 /*
730   XPending checks for x events pending.
731   We don't know if we have x events until we process
732   the win events.
733   */
734 int
735 XPending (display)
736 Display *display;
737 {
738         MSG msg;
739         /*      xtrace("XPending\n"); */
740         while(wineventq->count<=0 && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
741         {
742                 doTranslateMessage(&msg);
743                 DispatchMessage(&msg);
744         }
745         return wineventq->count;
746 }
747
748 int
749 XPutBackEvent(display,event)
750 Display *display;
751 XEvent *event;
752 {
753         xtrace("XPutBackEvent\n");
754         return 0;
755 }
756
757
758 StatusDef
759 XSendEvent(display,w,prop,emask,event)
760 Display *display;
761 Window w;
762 BoolDef prop;
763 long emask;
764 XEvent *event;
765 {
766         xtrace("XSendEvent\n");
767         return 0;
768 }
769
770 /* I'm tempted to flush the windows queue
771 **   before checking, but I think that would
772 **   break the assumtion that most of the WM_PAINT
773 **   messges are only going to be dispatched when
774 **   the app is directly calling us.
775 */
776
777 BoolDef
778 XCheckTypedWindowEvent(
779         Display* display,
780         Window w,
781         int event_type,
782         XEvent* event_return)
783 {
784         int i,j;
785         xtrace("XCheckTypedWindowEvent\n");
786         if (w==0) return 0;
787         /*
788         i = wineventq->next;
789         while(i != wineventq->avail)
790         {
791                 if (wineventq->list[i].window==(NT_window*)w)
792                 {
793                         WinEventToXEvent(&wineventq->list[i],event_return);
794                         if (event_return->type == event_type)
795                         {
796                                 break;
797                         }
798                 }
799                 i++;
800                 if (i>wineventq->num) i=0;
801         }
802         if (i != wineventq->avail)
803         {
804                 while(i != wineventq->next)
805                 {
806                         j =i-1;
807                         if (j<0) j= wineventq->num;
808                         copyWinEvent(&wineventq->list[i],&wineventq->list[j]);
809                         i = j;
810                 }
811                 wineventq->next++;
812                 wineventq->count--;
813                 cjh_printf("removed an event\n");
814                 return 1;
815         }
816         */
817         return 0;
818 }
819
820 /*****************************************************************\
821
822
823         Function: XWindowEvent
824         Inputs:   display, window, event mask.
825         Returned: pointer to filled in event structure.
826
827         Comments: This is fudged at the moment to work with the toolkit.
828                   The event system needs rewriting to account properly for
829                   event masks.
830
831 \*****************************************************************/
832
833 int
834 XWindowEvent(display,w,emask,rep)
835 Display *display;
836 Window w;
837 long emask;
838 XEvent *rep;
839 {
840         NT_window *ntw=(NT_window *)w;
841         MSG msg;
842
843         xtrace("XWindowEvent\n");
844         if (emask&ExposureMask)
845         {
846                 GetMessage(&msg,ntw->w,USR_MapNotify,USR_MapNotify);
847                 rep->type=ConfigureNotify;
848         }
849         return 0;
850 }
851
852
853
854 /*****************************************************************\
855
856         Function: XNextEvent
857         Inputs:   display, event structure pointer.
858
859         Comments: Windows routines receive messages (events) in two ways:
860                   firstly by GetMessage, which takes messages from the
861                   calling thread's message queue, and secondly by the
862                   window function being called with events as arguments.
863                   To simulate the X system, we get messages from the queue
864                   and pass them to the window function anyway, which
865                   processes them and fills out the local XEvent structure.
866                   DispatchMessage calls the window procedure and waits until
867                   it returns. Translate message turns WM_KEYUP/DOWN messages
868                   into WM_CHAR.
869
870 \*****************************************************************/
871
872 int
873 XNextEvent(Display *display,XEvent  *event)
874 {
875     MSG msg;
876         
877     xtrace("XNextEvent\n");
878
879     /* if there isn't already an event in the pipe, this will block */
880     while(wineventq->count <= 0 && GetMessage(&msg, NULL, 0, 0)>0)
881     {           
882         doTranslateMessage(&msg);
883         DispatchMessage(&msg);
884     }
885     if (wineventq->count>0)
886     {
887         getQdEvent(wineventq,event);
888     }
889     else
890     {
891         /* hmm, GetMessage failed, maybe we're supposed to quit */
892         event->type=ClientMessage;
893         event->xclient.format = 32;
894         event->xclient.data.l[0] = XInternAtom(NULL,"WM_DELETE_WINDOW", FALSE);
895         return 1;
896     }
897     return 1;
898 }
899
900 BoolDef
901 XFilterEvent(XEvent* event,Window window)
902 {
903         xtrace("XFilterEvent\n");
904         return 0;
905 }
906
907 BoolDef
908 XQueryPointer(
909         Display* display,
910         Window w,
911         Window* root_return,
912         Window* child_return,
913         int* root_x_return,
914         int* root_y_return,
915         int* win_x_return,
916         int* win_y_return,
917         unsigned int* mask_return)
918 {
919     POINT point;
920         RECT rect;
921         xtrace("XQueryPointer\n");
922     GetCursorPos(&point);
923     *root_x_return = point.x;
924     *root_y_return = point.y;
925         GetWindowRect(((NT_window*)w)->w,&rect);
926         *win_x_return= point.x - rect.left;
927         *win_y_return= point.y - rect.top;
928         *mask_return = NT_get_state();
929     return True;
930 }
931
932 int
933 XConvertSelection(
934     Display *display,
935     Atom sel, Atom target, Atom prop,
936     Window req, 
937     Time time)
938 {
939     xtrace("XConvertSelection\n");
940     QEvent(wineventq,(NT_window*)req,USR_ConvertSelection,0,0L);
941     NT_wakeup(((NT_window*)req)->w);
942     return 0;
943 }
944