source: trunk/src/user32/oslibmsgtranslate.cpp@ 7212

Last change on this file since 7212 was 7212, checked in by phaller, 24 years ago

.

File size: 40.4 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.70 2001-10-26 10:03:34 phaller Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Daniela Engert (dani@ngrt.de)
8 * Copyright 1999 Rene Pronk (R.Pronk@twi.tudelft.nl)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 * TODO: Extra msgs: which messages must be put into the queue and which can be sent directly?
13 * (According to the docs TranslateMessage really inserts a msg in the queue)
14 * TODO: Filter translation isn't correct for posted messages
15 *
16 */
17#define INCL_WIN
18#define INCL_PM
19#define INCL_DOSPROCESS
20#include <os2wrap.h>
21#include <string.h>
22#include <misc.h>
23#include <winconst.h>
24#include <win32api.h>
25#include "oslibmsg.h"
26#include <winuser32.h>
27#include "win32wdesktop.h"
28#include "oslibutil.h"
29#include "timer.h"
30#include <thread.h>
31#include <wprocess.h>
32#include "pmwindow.h"
33#include "oslibwin.h"
34#include "winmouse.h"
35#include <pmkbdhk.h>
36#include <pmscan.h>
37#include <winscan.h>
38#include <winkeyboard.h>
39
40#define DBG_LOCALLOG DBG_oslibmsgtranslate
41#include "dbglocal.h"
42
43
44#if REDUNDANT_AND_BUGGY_DEFINITION
45// Formerly used method of translation based on OS/2 VKEY value didn't work
46// right. We need to take a look at the scan code we get from PM and derive
47// the Win32 VKEY and scancode from that because sometimes even the scancode
48// used in Win32 is different from the PM scancode!
49// The format is:
50// Win VKEY, Win scancode, (PM scancode) (key description)
51USHORT pmscan2winkey [][2] = {
52 0, 0, // 0x00
53 0x1B, 0x01, // 0x01 Esc
54 0x31, 0x02, // 0x02 1
55 0x32, 0x03, // 0x03 2
56 0x33, 0x04, // 0x04 3
57 0x34, 0x05, // 0x05 4
58 0x35, 0x06, // 0x06 5
59 0x36, 0x07, // 0x07 6
60 0x37, 0x08, // 0x08 7
61 0x38, 0x09, // 0x09 8
62 0x39, 0x0A, // 0x0A 9
63 0x30, 0x0B, // 0x0B 0
64 0xBD, 0x0C, // 0x0C -
65 0xBB, 0x0D, // 0x0D =
66 0x08, 0x0E, // 0x0E Bksp
67 0x09, 0x0F, // 0x0F Tab
68 0x51, 0x10, // 0x10 q
69 0x57, 0x11, // 0x11 w
70 0x45, 0x12, // 0x12 e
71 0x52, 0x13, // 0x13 r
72 0x54, 0x14, // 0x14 t
73 0x59, 0x15, // 0x15 y
74 0x55, 0x16, // 0x16 u
75 0x49, 0x17, // 0x17 i
76 0x4F, 0x18, // 0x18 o
77 0x50, 0x19, // 0x19 p
78 0xDB, 0x1A, // 0x1A [
79 0xDD, 0x1B, // 0x1B ]
80 0x0D, 0x1C, // 0x1C Enter
81 0x11, 0x1D, // 0x1D LCtrl
82 0x41, 0x1E, // 0x1E a
83 0x53, 0x1F, // 0x1F s
84 0x44, 0x20, // 0x20 d
85 0x46, 0x21, // 0x21 f
86 0x47, 0x22, // 0x22 g
87 0x48, 0x23, // 0x23 h
88 0x4A, 0x24, // 0x24 j
89 0x4B, 0x25, // 0x25 k
90 0x4C, 0x26, // 0x26 l
91 0xBA, 0x27, // 0x27 ;
92 0xDE, 0x28, // 0x28 '
93 0xC0, 0x29, // 0x29 `
94 VK_LSHIFT_W, 0x2A, // 0x2A LShift
95 0xDC, 0x2B, // 0x2B Bkslsh
96 0x5A, 0x2C, // 0x2C z
97 0x58, 0x2D, // 0x2D x
98 0x43, 0x2E, // 0x2E c
99 0x56, 0x2F, // 0x2F v
100 0x42, 0x30, // 0x30 b
101 0x4E, 0x31, // 0x31 n
102 0x4D, 0x32, // 0x32 m
103 0xBC, 0x33, // 0x33 ,
104 0xBE, 0x34, // 0x34 .
105 0xBF, 0x35, // 0x35 /
106 VK_RSHIFT_W, 0x36, // 0x36 RShift
107 0x6A, 0x37, // 0x37 * Pad
108// 0x12, 0x38, // 0x38 LAlt
109 VK_LMENU_W, 0x38, // 0x38 LAlt
110 0x20, 0x39, // 0x39 Space
111 0x14, 0x3A, // 0x3A CapsLk
112 0x70, 0x3B, // 0x3B F1
113 0x71, 0x3C, // 0x3C F2
114 0x72, 0x3D, // 0x3D F3
115 0x73, 0x3E, // 0x3E F4
116 0x74, 0x3F, // 0x3F F5
117 0x75, 0x40, // 0x40 F6
118 0x76, 0x41, // 0x41 F7
119 0x77, 0x42, // 0x42 F8
120 0x78, 0x43, // 0x43 F9
121 0x79, 0x44, // 0x44 F10 (?)
122 0x90, 0x145, // 0x45 NumLk
123 0x91, 0x46, // 0x46 ScrLk
124 0x24, 0x47, // 0x47 7 Pad
125 0x26, 0x48, // 0x48 8 Pad
126 0x21, 0x49, // 0x49 9 Pad
127 0x6D, 0x4A, // 0x4A - Pad
128 VK_LEFT_W, 0x4B, // 0x4B Left Arrow (depends on NumLock State)
129 0x0C, 0x4C, // 0x4C 5 Pad
130 0x27, 0x4D, // 0x4D 6 Pad
131 0x6B, 0x4E, // 0x4E + Pad
132 0x23, 0x4F, // 0x4F 1 Pad
133 0x28, 0x50, // 0x50 2 Pad
134 0x22, 0x51, // 0x51 3 Pad
135 0x2D, 0x52, // 0x52 0 Pad
136 0x2E, 0x53, // 0x53 . Pad
137 0, 0, // 0x54
138 0, 0, // 0x55
139 0xe2, 0x56, // 0x56 "<>|"
140 0x7A, 0x57, // 0x57 F11
141 0x7B, 0x58, // 0x58 F12
142 0, 0, // 0x59
143 0x0D, 0x11C, // 0x5A Enter Pad
144 0x11, 0x11D, // 0x5B RCtrl
145 0x6F, 0x135, // 0x5C / Pad
146 VK_SNAPSHOT_W, 0x137, // 0x5D PrtSc
147 0x12, 0x5E, // 0x5E RAlt
148 0x13, 0x45, // 0x5F Pause
149 VK_HOME_W, 0x60, // 0x60
150 VK_UP_W, 0x61, // 0x61
151 VK_PRIOR_W, 0x62, // 0x62
152 VK_LEFT_W, 0x63, // 0x63
153 VK_RIGHT_W, 0x64, // 0x64
154 VK_END_W, 0x65, // 0x65
155 VK_DOWN_W, 0x66, // 0x66
156 VK_NEXT_W, 0x67, // 0x67
157 VK_INSERT_W, 0x68, // 0x68
158 VK_DELETE_W, 0x69, // 0x69
159 VK_F23_W, 0x6A, // 0x6A
160 VK_F24_W, 0x6B, // 0x6B
161 0x5D, 0x15D, // 0x6C RWin (PM scan 0x7C)
162 0, 0, // 0x6D
163 0x5B, 0x15B, // 0x6E LWin (PM scan 0x7E)
164 0x5C, 0x15C // 0x6F RMenu? (PM scan 0x7F)
165};
166#endif
167
168static BOOL fGenerateDoubleClick = FALSE;
169static MSG doubleClickMsg = {0};
170
171
172// Note:
173// For a "lonekey"-press of AltGr, we only receive WM_KEYUP
174// messages. If the key is pressed longer and starts to repeat,
175// WM_KEYDOWN messages come in properly.
176static BOOL fKeyAltGrDown = FALSE;
177
178//******************************************************************************
179//******************************************************************************
180BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
181{
182 // check if the single slot is occupied already
183 if (teb->o.odin.fTranslated == TRUE)
184 // there's still an already translated message to be processed
185 return FALSE;
186
187 teb->o.odin.fTranslated = TRUE;
188 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
189 return TRUE;
190}
191
192//******************************************************************************
193//******************************************************************************
194ULONG GetMouseKeyState()
195{
196 ULONG keystate = 0;
197
198 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
199 keystate |= MK_LBUTTON_W;
200 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
201 keystate |= MK_RBUTTON_W;
202 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
203 keystate |= MK_MBUTTON_W;
204 if(WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000)
205 keystate |= MK_SHIFT_W;
206 if(WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
207 keystate |= MK_CONTROL_W;
208
209 return keystate;
210}
211//******************************************************************************
212//******************************************************************************
213LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
214{
215 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
216}
217//******************************************************************************
218//******************************************************************************
219void SetMenuDoubleClick(BOOL fSet)
220{
221 fGenerateDoubleClick = fSet;
222}
223//******************************************************************************
224//******************************************************************************
225BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
226{
227 Win32BaseWindow *win32wnd = 0;
228 OSLIBPOINT point, ClientPoint;
229 POSTMSG_PACKET *packet;
230 TEB *teb = (TEB *)pTeb;
231 BOOL fWasDisabled = FALSE;
232 BOOL fIsFrame = FALSE;
233 int i;
234
235 memset(winMsg, 0, sizeof(MSG));
236 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
237 if(!win32wnd) {
238 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
239 if(win32wnd) {
240 fIsFrame = TRUE;
241 }
242 }
243
244 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
245 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
246 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
247 {
248 goto dummymessage; //not a win32 client window
249 }
250 winMsg->time = os2Msg->time;
251 //CB: PM bug or undocumented feature? ptl.x highword is set!
252 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
253 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
254
255 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
256 winMsg->hwnd = win32wnd->getWindowHandle();
257
258 if(os2Msg->msg >= WIN32APP_POSTMSG) {
259 packet = (POSTMSG_PACKET *)os2Msg->mp2;
260 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
261 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
262 winMsg->wParam = packet->wParam;
263 winMsg->lParam = packet->lParam;
264 if(fMsgRemoved == MSG_REMOVE) free(packet); //free the shared memory here
265 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
266 return TRUE;
267 }
268 else {//broadcasted message (no packet present)
269 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
270 winMsg->wParam = (UINT)os2Msg->mp1;
271 winMsg->lParam = (DWORD)os2Msg->mp2;
272 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
273 return TRUE;
274 }
275 goto dummymessage;
276 }
277
278 switch(os2Msg->msg)
279 {
280 //OS/2 msgs
281 case WM_CREATE:
282 {
283 if(teb->o.odin.newWindow == 0) {
284 DebugInt3();
285 goto dummymessage;
286 }
287
288 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
289 win32wnd->addRef();
290
291 winMsg->message = WINWM_CREATE;
292 winMsg->hwnd = win32wnd->getWindowHandle();
293 winMsg->wParam = 0;
294 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
295 break;
296 }
297
298 case WM_QUIT:
299 winMsg->message = WINWM_QUIT;
300 break;
301
302 case WM_CLOSE:
303 winMsg->message = WINWM_CLOSE;
304 break;
305
306 case WM_DESTROY:
307 winMsg->message = WINWM_DESTROY;
308 break;
309
310 case WM_ENABLE:
311 winMsg->message = WINWM_ENABLE;
312 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
313 break;
314
315 case WM_SHOW:
316 winMsg->message = WINWM_SHOWWINDOW;
317 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
318 break;
319
320 case WM_WINDOWPOSCHANGED:
321 {
322 PSWP pswp = (PSWP)os2Msg->mp1;
323 SWP swpOld = *(pswp + 1);
324 HWND hParent = NULLHANDLE;
325 LONG yDelta = pswp->cy - swpOld.cy;
326 LONG xDelta = pswp->cx - swpOld.cx;
327
328 if(!fIsFrame) goto dummymessage;
329
330 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
331
332 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
333 if (win32wnd->isChild()) {
334 if(win32wnd->getParent()) {
335 hParent = win32wnd->getParent()->getOS2WindowHandle();
336 }
337 else goto dummymessage; //parent has just been destroyed
338 }
339 }
340 if(win32wnd->getParent()) {
341 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
342 win32wnd->getOS2WindowHandle());
343 }
344 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
345
346 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
347
348 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
349 {
350 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
351 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
352 {
353 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
354 if(wndAfter) {
355 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
356 RELEASE_WNDOBJ(wndAfter);
357 }
358 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
359 }
360 }
361 winMsg->message = WINWM_WINDOWPOSCHANGED;
362 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
363 break;
364 }
365
366 case WM_ACTIVATE:
367 {
368 HWND hwndActivate = (HWND)os2Msg->mp2;
369 BOOL fMinimized = FALSE;
370
371 hwndActivate = OS2ToWin32Handle(hwndActivate);
372 if(hwndActivate == 0) {
373 //another (non-win32) application's window
374 //set to desktop window handle
375 hwndActivate = windowDesktop->getWindowHandle();
376 }
377
378 if(win32wnd->getStyle() & WS_MINIMIZE_W)
379 {
380 fMinimized = TRUE;
381 }
382
383 winMsg->message = WINWM_ACTIVATE;
384 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
385 winMsg->lParam = (LPARAM)hwndActivate;
386 break;
387 }
388
389 case WM_SETFOCUS:
390 {
391 HWND hwndFocus = (HWND)os2Msg->mp1;
392
393 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
394 //another (non-win32) application's window
395 //set to NULL (allowed according to win32 SDK) to avoid problems
396 hwndFocus = NULL;
397 }
398 else hwndFocus = OS2ToWin32Handle(hwndFocus);
399
400 if((ULONG)os2Msg->mp2 == TRUE) {
401 winMsg->message = WINWM_SETFOCUS;
402 winMsg->wParam = (WPARAM)hwndFocus;
403 }
404 else {
405 winMsg->message = WINWM_KILLFOCUS;
406 winMsg->wParam = (WPARAM)hwndFocus;
407 }
408 break;
409 }
410
411 //**************************************************************************
412 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
413 //**************************************************************************
414 case WM_BUTTON1DOWN:
415 case WM_BUTTON1UP:
416 case WM_BUTTON1DBLCLK:
417 case WM_BUTTON2DOWN:
418 case WM_BUTTON2UP:
419 case WM_BUTTON2DBLCLK:
420 case WM_BUTTON3DOWN:
421 case WM_BUTTON3UP:
422 case WM_BUTTON3DBLCLK:
423 {
424 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
425
426 dprintf(("MsgButton %x (%x) %d at (%d,%d) time %x", winMsg->hwnd, os2Msg->hwnd, WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN), winMsg->pt.x, winMsg->pt.y, winMsg->time));
427
428 HWND hwnd;
429
430 DisableLogging();
431 if(GetCapture() != winMsg->hwnd)
432 {
433 hwnd = WindowFromPoint(winMsg->pt);
434 if(win32wnd->getWindowHandle() != hwnd) {
435 RELEASE_WNDOBJ(win32wnd);
436 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
437 if(win32wnd == NULL) {
438 DebugInt3();
439 EnableLogging();
440 goto dummymessage;
441 }
442 winMsg->hwnd = hwnd;
443 }
444 }
445
446 //if a window is disabled, it's parent receives the mouse messages
447 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
448 if(win32wnd->getParent()) {
449 Win32BaseWindow *parent = win32wnd->getParent();;
450 if(parent) parent->addRef();
451 RELEASE_WNDOBJ(win32wnd);
452 win32wnd = parent;
453 }
454 fWasDisabled = TRUE;
455 }
456
457 if(IsNCMouseMsg(win32wnd)) {
458 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
459 winMsg->wParam = win32wnd->getLastHitTestVal();
460 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
461 }
462 else {
463 ClientPoint.x = winMsg->pt.x;
464 ClientPoint.y = winMsg->pt.y;
465 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
466 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
467 winMsg->wParam = GetMouseKeyState();
468 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
469 }
470 EnableLogging();
471 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
472 {
473 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
474 goto dummymessage; //dinput swallowed message
475 }
476 }
477
478 if(fWasDisabled) {
479 if(win32wnd) {
480 winMsg->hwnd = win32wnd->getWindowHandle();
481 }
482 else goto dummymessage; //don't send mouse messages to disabled windows
483 }
484
485 DisableLogging();
486 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
487 (winMsg->message == WINWM_RBUTTONDOWN) ||
488 (winMsg->message == WINWM_MBUTTONDOWN) ||
489 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
490 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
491 (winMsg->message == WINWM_NCMBUTTONDOWN))
492 {
493 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
494 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
495 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
496 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
497 {
498 dprintf(("single -> double click"));
499 if(winMsg->message >= WINWM_LBUTTONDOWN) {
500 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
501 }
502 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
503 doubleClickMsg.message = 0;
504 }
505 else {
506 dprintf(("save for double click"));
507 doubleClickMsg = *winMsg;
508 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
509 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
510 }
511 }
512 }
513 EnableLogging();
514
515 break;
516 }
517
518 case WM_BUTTON2CLICK:
519 case WM_BUTTON1CLICK:
520 case WM_BUTTON3CLICK:
521 goto dummymessage;
522
523 case WM_BUTTON2MOTIONSTART:
524 case WM_BUTTON2MOTIONEND:
525 case WM_BUTTON1MOTIONSTART:
526 case WM_BUTTON1MOTIONEND:
527 case WM_BUTTON3MOTIONSTART:
528 case WM_BUTTON3MOTIONEND:
529 //no break; translate to WM_MOUSEMOVE
530 //Some applications (e.g. Unreal) retrieve all mouse messages
531 //when a mouse button is pressed and don't expect WM_NULL
532
533 case WM_MOUSEMOVE:
534 {
535 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
536
537 HWND hwnd;
538
539 dprintf2(("WM_NCMOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
540 DisableLogging();
541 if(GetCapture() != winMsg->hwnd)
542 {
543 hwnd = WindowFromPoint(winMsg->pt);
544 if(win32wnd->getWindowHandle() != hwnd) {
545 RELEASE_WNDOBJ(win32wnd);
546 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
547 if(win32wnd == NULL) {
548 DebugInt3();
549 EnableLogging();
550 goto dummymessage;
551 }
552 winMsg->hwnd = hwnd;
553 }
554 }
555
556 //if a window is disabled, it's parent receives the mouse messages
557 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
558 if(win32wnd->getParent()) {
559 Win32BaseWindow *parent = win32wnd->getParent();;
560 if(parent) parent->addRef();
561 RELEASE_WNDOBJ(win32wnd);
562 win32wnd = parent;
563 }
564 fWasDisabled = TRUE;
565 }
566 if(IsNCMouseMsg(win32wnd))
567 {
568 winMsg->message = WINWM_NCMOUSEMOVE;
569 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
570 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
571 }
572 else
573 {
574 ClientPoint.x = winMsg->pt.x;
575 ClientPoint.y = winMsg->pt.y;
576 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
577
578 winMsg->message = WINWM_MOUSEMOVE;
579 winMsg->wParam = GetMouseKeyState();
580 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
581 }
582 EnableLogging();
583 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
584 {
585 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
586 goto dummymessage; //dinput swallowed message
587 }
588 }
589 if(fWasDisabled) {
590 if(win32wnd) {
591 winMsg->hwnd = win32wnd->getWindowHandle();
592 }
593 else {
594 goto dummymessage; //don't send mouse messages to disabled windows
595 }
596 }
597 //OS/2 Window coordinates -> Win32 Window coordinates
598 break;
599 }
600
601 case WM_CONTROL:
602 goto dummymessage;
603
604 case WM_COMMAND:
605 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
606 winMsg->message = WINWM_COMMAND;
607 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
608 break;
609 }
610 //todo controls
611 goto dummymessage;
612
613 case WM_SYSCOMMAND:
614 {
615 ULONG x = 0, y = 0;
616 ULONG win32sc;
617
618 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
619 POINTL pointl;
620 WinQueryPointerPos(HWND_DESKTOP, &pointl);
621 x = pointl.x;
622 y = mapScreenY(y);
623 }
624 switch(SHORT1FROMMP(os2Msg->mp1)) {
625 case SC_MOVE:
626 win32sc = SC_MOVE_W;
627 break;
628 case SC_CLOSE:
629 {
630 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
631 //TRUE -> user clicked on close button -> close window
632 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
633 {
634 HWND hwnd = win32wnd->GetTopParent();
635 if(win32wnd->getWindowHandle() != hwnd) {
636 RELEASE_WNDOBJ(win32wnd);
637 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
638 if(win32wnd == NULL) {
639 DebugInt3();
640 goto dummymessage;
641 }
642 winMsg->hwnd = hwnd;
643 }
644 }
645 win32sc = SC_CLOSE_W;
646 break;
647 }
648 case SC_MAXIMIZE:
649 win32sc = SC_MAXIMIZE_W;
650 break;
651 case SC_MINIMIZE:
652 win32sc = SC_MINIMIZE_W;
653 break;
654 case SC_NEXTFRAME:
655 case SC_NEXTWINDOW:
656 win32sc = SC_NEXTWINDOW_W;
657 break;
658 case SC_RESTORE:
659 win32sc = SC_RESTORE_W;
660 break;
661 case SC_TASKMANAGER:
662 win32sc = SC_TASKLIST_W;
663 break;
664 default:
665 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
666 goto dummymessage;
667 }
668 winMsg->message= WINWM_SYSCOMMAND;
669 winMsg->wParam = (WPARAM)win32sc;
670 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
671 break;
672 }
673
674 case WM_CHAR_SPECIAL:
675 {
676 // @@@PH
677 // special char message from the keyboard hook
678 dprintf(("PM: WM_CHAR_SPECIAL\n"));
679
680 // NO BREAK! FALLTHRU CASE!
681 }
682
683 case WM_CHAR:
684 {
685 ULONG repeatCount=0, virtualKey=0, keyFlags=0, scanCode=0;
686 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
687 BOOL keyWasPressed, isExtended = FALSE;
688 char c;
689
690 teb->o.odin.fTranslated = FALSE;
691 repeatCount = CHAR3FROMMP(os2Msg->mp1);
692 scanCode = CHAR4FROMMP(os2Msg->mp1);
693 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
694
695 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode));
696 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
697
698 // vitali add begin
699 if ( ( SHORT1FROMMP(os2Msg->mp2) & 0x0FF ) == 0x0E0 )
700 {
701 // an extended key ( arrows, ins, del and so on )
702 // get "virtual" scancode from character code because
703 // for "regular" keys they are equal
704 if(!(flags & (KC_SHIFT|KC_ALT|KC_CTRL))) {
705 scanCode = ( SHORT1FROMMP(os2Msg->mp2) >> 8) & 0x0FF;
706 }
707 isExtended = TRUE;
708 }
709 // vitali add end
710
711 // both WM_KEYUP & WM_KEYDOWN want a virtual key, find the right Win32 virtual key
712 // given the OS/2 virtual key and OS/2 character
713
714 //if (((SHORT1FROMMP (mp1) & KC_CHAR) == KC_CHAR) ||
715 // ((SHORT1FROMMP (mp1) & KC_LONEKEY) == KC_LONEKEY))
716 c = 0;
717 if ((SHORT1FROMMP (os2Msg->mp1) & 0xFF) != 0)
718 {
719 c = SHORT1FROMMP (os2Msg->mp2);
720 if ((c >= 'A') && (c <= 'Z')) {
721 virtualKey = c;
722 goto VirtualKeyFound;
723 }
724 if ((c >='a') && (c <= 'z')) {
725 virtualKey = c - 32; // make it uppercase
726 goto VirtualKeyFound;
727 }
728 if ((c >= '0') && (c <= '9')) {
729 virtualKey = c;
730 goto VirtualKeyFound;
731 }
732 }
733
734VirtualKeyFound:
735// dprintf (("VIRTUALKEYFOUND:(%x)", virtualKey));
736
737 // @@@PH: what's this supposed to be?
738 // Adjust PM scancodes for Win* keys
739 if (scanCode >= 0x70)
740 scanCode -= 0x10;
741
742 // winMsg->wParam = pmscan2winkey[scanCode][0];
743 // wWinScan = pmscan2winkey[scanCode][1];
744 {
745 BOOL fWinExtended;
746 BYTE bWinVKey;
747 WORD wWinScan;
748
749 // Note: Numlock-state currently ignored, see below
750 KeyTranslatePMScanToWinVKey(scanCode,
751 FALSE,
752 &bWinVKey,
753 &wWinScan,
754 &fWinExtended);
755 winMsg->wParam = bWinVKey;
756 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
757 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
758 }
759
760 // Adjust VKEY value for pad digits if NumLock is on
761 if ((scanCode >= 0x47) && (scanCode <= 0x53) &&
762 (virtualKey >= 0x30) && (virtualKey >= 39))
763 winMsg->wParam = virtualKey + 0x30;
764
765 // Set the extended bit when appropriate
766 if (isExtended)
767 winMsg->lParam = winMsg->lParam | (1<<24);
768
769 if (!(flags & KC_ALT))
770 {
771 //
772 // the Alt key is not pressed
773 // or no more pressed
774 //
775 if (flags & KC_KEYUP)
776 {
777 // check for a lonesome ALT key ...
778 if ( (flags & KC_LONEKEY) &&
779 (winMsg->wParam == VK_LMENU_W) )
780 {
781 winMsg->message = WINWM_SYSKEYUP;
782
783 // held ALT-key when current key is released
784 // generates additional flag 0x2000000
785 // Note: PM seems to do this differently,
786 // KC_ALT is already reset
787 }
788 else
789 {
790 // send WM_KEYUP message
791 winMsg->message = WINWM_KEYUP;
792 }
793
794 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
795 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
796 }
797 else
798 {
799 // send WM_KEYDOWN message
800 winMsg->message = WINWM_KEYDOWN;
801 if (keyWasPressed)
802 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
803 }
804 }
805 else
806 {
807 //
808 // the Alt key is pressed
809 //
810 if (flags & KC_KEYUP)
811 {
812 // send WM_SYSKEYUP message
813 winMsg->message = WINWM_SYSKEYUP;
814 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
815 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
816 }
817 else
818 {
819 // send WM_SYSKEYDOWN message
820 winMsg->message = WINWM_SYSKEYDOWN;
821 if (keyWasPressed)
822 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
823
824 // pressed ALT-key generates additional flag 0x2000000
825 // if the current window has keyboard focus
826 winMsg->lParam |= 1 << 29;
827 }
828 }
829
830 // ------------------------------------------------
831 // check if additional messages have to be recorded
832 // ------------------------------------------------
833#if 0
834 {
835 MSG extramsg;
836 extramsg.hwnd = winMsg->hwnd;
837 extramsg.time = winMsg->time;
838 extramsg.pt = winMsg->pt;
839
840 switch (scanCode)
841 {
842 case PMSCAN_PRINT:
843 // Note: PRINT generates a WM_KEYUP under Windows
844 // also only call the standard kbd hook for the WM_KEYUP msg,
845 // the low-level hook is called twice
846 // mb->putWinMsg(hwndWin32, WM_CHAR, VK_PRINT_W, ... )
847 // WM_CHAR(0x0000002ch, c1370001h)
848 extramsg.message = WINWM_KEYUP;
849 extramsg.wParam = VK_PRINT_W;
850 extramsg.lParam = winMsg->lParam;
851 setThreadQueueExtraCharMessage(teb, &extramsg);
852 break;
853
854 #define WIN_KEY_EXTENDED 0x01000000
855 #define WIN_KEY_DONTCARE 0x02000000
856 #define WIN_KEY_ALTHELD 0x20000000
857 #define WIN_KEY_PREVSTATE 0x40000000
858 case PMSCAN_ALTRIGHT:
859 {
860 // we need very special treatment here for the
861 // poor, crippled AltGr key
862 // Note: see fKeyAltGrDown above!
863
864 if ( (keyWasPressed) || (fKeyAltGrDown == FALSE) )
865 {
866 fKeyAltGrDown = TRUE;
867
868 // 1 - generate a virtual LCONTROL-keypress
869 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-AltGr!)
870 // 0xfe000000: mask out extended-key, scancode, repeatcount
871 // Note: Win sends a WINWM_SYSKEYDOWN to the hooks,
872 // the queue gets a WM_KEYDOWN only! (wrong impl. here)
873 extramsg.message = WINWM_KEYDOWN;
874 extramsg.wParam = VK_RMENU_W;
875 extramsg.lParam = (winMsg->lParam & 0xfe000000)
876 | WIN_KEY_EXTENDED
877 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
878 | WIN_KEY_ALTHELD
879 | repeatCount
880 | (WINSCAN_ALTRIGHT << 16);
881 winMsg->message = WINWM_KEYDOWN;
882 winMsg->wParam = VK_LCONTROL_W;
883 winMsg->lParam = (winMsg->lParam & 0xfe000000)
884 | WIN_KEY_DONTCARE
885 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
886 | WIN_KEY_ALTHELD
887 | repeatCount
888 | (WINSCAN_CTRLLEFT << 16);
889 }
890 else
891 {
892 // OK, now we can release it!
893 fKeyAltGrDown = FALSE;
894
895 // key up
896 // 1 - generate a virtual LCONTROL-keypress
897 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-Alt!)
898 extramsg.message = WINWM_KEYUP;
899 extramsg.wParam = VK_RMENU_W;
900 extramsg.lParam = (winMsg->lParam & 0xfe000000)
901 | WIN_KEY_EXTENDED
902 | repeatCount
903 | (WINSCAN_ALTRIGHT << 16);
904 winMsg->message = WINWM_SYSKEYUP;
905 winMsg->wParam = VK_LCONTROL_W;
906 winMsg->lParam = (winMsg->lParam & 0xfe000000)
907 | WIN_KEY_ALTHELD
908 | repeatCount
909 | (WINSCAN_CTRLLEFT << 16);
910 }
911
912 // @@@PH
913 // unknown: this leads to an infinite loop
914 // because the OS/2 WM_CHAR_SPECIAL message is never
915 // removed from the queue?!
916 setThreadQueueExtraCharMessage(teb, &extramsg);
917
918 if ( (keyWasPressed) || (fKeyAltGrDown == FALSE) )
919 {
920 fKeyAltGrDown = TRUE;
921
922 // 1 - generate a virtual LCONTROL-keypress
923 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-AltGr!)
924 // 0xfe000000: mask out extended-key, scancode, repeatcount
925 // Note: Win sends a WINWM_SYSKEYDOWN to the hooks,
926 // the queue gets a WM_KEYDOWN only! (wrong impl. here)
927 winMsg->message = WINWM_KEYDOWN;
928 winMsg->wParam = VK_RMENU_W;
929 winMsg->lParam = (winMsg->lParam & 0xfe000000)
930 | WIN_KEY_EXTENDED
931 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
932 | WIN_KEY_ALTHELD
933 | repeatCount
934 | (WINSCAN_ALTRIGHT << 16);
935 }
936 else
937 {
938 // OK, now we can release it!
939 fKeyAltGrDown = FALSE;
940
941 // key up
942 // 1 - generate a virtual LCONTROL-keypress
943 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-Alt!)
944 winMsg->message = WINWM_KEYUP;
945 winMsg->wParam = VK_RMENU_W;
946 winMsg->lParam = (winMsg->lParam & 0xfe000000)
947 | WIN_KEY_EXTENDED
948 | repeatCount
949 | (WINSCAN_ALTRIGHT << 16);
950 }
951 }
952 break;
953 } /* switch */
954 }
955#endif
956
957 if (ISKDB_CAPTURED())
958 {
959 if (DInputKeyBoardHandler(winMsg)) {
960 goto dummymessage; //dinput swallowed message
961 }
962 }
963 break;
964 }
965
966 case WM_TIMER:
967//Why was this check here????
968// if (os2Msg->mp2)
969// {
970 BOOL sys;
971 ULONG id;
972
973 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id))
974 {
975 winMsg->wParam = (WPARAM)id;
976 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
977 break;
978 }
979// }
980 goto dummymessage; //for caret blinking
981
982 case WM_SETWINDOWPARAMS:
983 {
984 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
985
986 if(wndParams->fsStatus & WPM_TEXT) {
987 winMsg->message = WINWM_SETTEXT;
988 winMsg->lParam = (LPARAM)wndParams->pszText;
989 break;
990 }
991 goto dummymessage;
992 }
993
994#if 0
995 case WM_QUERYWINDOWPARAMS:
996 {
997 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
998 ULONG textlen;
999 PSZ wintext;
1000
1001 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
1002 {
1003 if(wndpars->fsStatus & WPM_CCHTEXT)
1004 wndpars->cchText = win32wnd->MsgGetTextLength();
1005 if(wndpars->fsStatus & WPM_TEXT)
1006 wndpars->pszText = win32wnd->MsgGetText();
1007
1008 wndpars->fsStatus = 0;
1009 wndpars->cbCtlData = 0;
1010 wndpars->cbPresParams = 0;
1011 goto dummymessage;
1012 }
1013 }
1014#endif
1015
1016 case WM_PAINT:
1017 {
1018 if(win32wnd->IsWindowIconic()) {
1019 winMsg->message = WINWM_PAINTICON;
1020 }
1021 else winMsg->message = WINWM_PAINT;
1022 break;
1023 }
1024
1025 case WM_CONTEXTMENU:
1026 winMsg->message = WINWM_CONTEXTMENU;
1027 winMsg->wParam = win32wnd->getWindowHandle();
1028 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
1029 break;
1030
1031 case WM_RENDERFMT:
1032 winMsg->message = WINWM_RENDERFORMAT;
1033 winMsg->wParam = (UINT) os2Msg->mp1;
1034 break;
1035
1036 case WM_RENDERALLFMTS:
1037 winMsg->message = WINWM_RENDERALLFORMATS;
1038 break;
1039
1040 case WM_DESTROYCLIPBOARD:
1041 winMsg->message = WINWM_DESTROYCLIPBOARD;
1042 break;
1043
1044 case WM_HSCROLL:
1045 case WM_VSCROLL:
1046 winMsg->message = (os2Msg->msg == WM_HSCROLL) ? WINWM_HSCROLL : WINWM_VSCROLL;
1047 winMsg->lParam = 0;
1048 winMsg->wParam = 0;
1049 switch(SHORT2FROMMP(os2Msg->mp2)) {
1050 case SB_LINERIGHT:
1051 winMsg->wParam = SB_LINERIGHT_W;
1052 break;
1053 case SB_LINELEFT:
1054 winMsg->wParam = SB_LINELEFT_W;
1055 break;
1056 case SB_PAGELEFT:
1057 winMsg->wParam = SB_PAGELEFT_W;
1058 break;
1059 case SB_PAGERIGHT:
1060 winMsg->wParam = SB_PAGERIGHT_W;
1061 break;
1062 default:
1063 dprintf(("Unsupported WM_H/VSCROLL message %x!!", SHORT2FROMMP(os2Msg->mp2)));
1064 goto dummymessage;
1065 }
1066 break;
1067
1068 case WM_INITMENU:
1069 case WM_MENUSELECT:
1070 case WM_MENUEND:
1071 case WM_NEXTMENU:
1072 case WM_SYSCOLORCHANGE:
1073 case WM_SYSVALUECHANGED:
1074 case WM_SETSELECTION:
1075 case WM_PPAINT:
1076 case WM_PSETFOCUS:
1077 case WM_PSYSCOLORCHANGE:
1078 case WM_PSIZE:
1079 case WM_PACTIVATE:
1080 case WM_PCONTROL:
1081 case WM_HELP:
1082 case WM_APPTERMINATENOTIFY:
1083 case WM_PRESPARAMCHANGED:
1084 case WM_DRAWITEM:
1085 case WM_MEASUREITEM:
1086 case WM_CONTROLPOINTER:
1087 case WM_QUERYDLGCODE:
1088 case WM_SUBSTITUTESTRING:
1089 case WM_MATCHMNEMONIC:
1090 case WM_SAVEAPPLICATION:
1091 case WM_SEMANTICEVENT:
1092 default:
1093dummymessage:
1094 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
1095 winMsg->message = 0;
1096 winMsg->wParam = 0;
1097 winMsg->lParam = 0;
1098 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1099 return FALSE;
1100 }
1101 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1102 return TRUE;
1103}
1104//******************************************************************************
1105//******************************************************************************
1106BOOL OSLibWinTranslateMessage(MSG *msg)
1107{
1108 TEB *teb;
1109
1110 teb = GetThreadTEB();
1111 if(!teb) {
1112 return FALSE;
1113 }
1114 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1115 // the newly generated WM_CHAR message.
1116 if(!teb->o.odin.fTranslated && teb->o.odin.os2msg.msg == WM_CHAR && !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
1117 {
1118 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
1119 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
1120 MSG extramsg;
1121
1122 memcpy(&extramsg, msg, sizeof(MSG));
1123 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1124 extramsg.lParam = 0;
1125
1126 // ESCAPE generates a WM_CHAR under windows, so take
1127 // special care for this here.
1128 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1129 switch (ucPMScanCode)
1130 {
1131 case PMSCAN_ESC:
1132 extramsg.wParam = VK_ESCAPE_W;
1133 fl |= KC_CHAR;
1134 break;
1135 }
1136
1137 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1138 {
1139 return FALSE;
1140 }
1141
1142 if(fl & KC_VIRTUALKEY)
1143 {
1144 if(msg->wParam)
1145 {
1146 if ((msg->wParam >= VK_NUMPAD0_W) &&
1147 (msg->wParam <= VK_NUMPAD9_W))
1148 extramsg.wParam = msg->wParam - 0x30;
1149 else
1150 extramsg.wParam = msg->wParam;
1151 }
1152 else
1153 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1154 }
1155
1156
1157 if(msg->message >= WINWM_SYSKEYDOWN)
1158 extramsg.message = WINWM_SYSCHAR;
1159 else
1160 extramsg.message = WINWM_CHAR;
1161
1162 if(fl & KC_DEADKEY)
1163 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1164
1165
1166 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1167 if(fl & KC_ALT)
1168 extramsg.lParam |= (1<<29);
1169 if(fl & KC_PREVDOWN)
1170 extramsg.lParam |= (1<<30);
1171 if(fl & KC_KEYUP)
1172 extramsg.lParam |= (1<<31);
1173
1174 // insert message into the queue
1175 setThreadQueueExtraCharMessage(teb, &extramsg);
1176 return TRUE;
1177 }
1178 return FALSE;
1179}
1180//******************************************************************************
1181//******************************************************************************
1182
Note: See TracBrowser for help on using the repository browser.