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

Last change on this file since 10189 was 10189, checked in by sandervl, 22 years ago

Convert WM_CHAR characters to UTF-16 for unicode windows

File size: 41.0 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.112 2003-07-31 12:25:57 sandervl 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#include <winnls.h>
40#include "hook.h"
41#include "user32api.h"
42
43
44#define DBG_LOCALLOG DBG_oslibmsgtranslate
45#include "dbglocal.h"
46
47static BOOL fGenerateDoubleClick = FALSE;
48static MSG doubleClickMsg = {0};
49
50//For wheel mouse translation
51#define WHEEL_DELTA 120
52#define OS2_WHEEL_CORRECTION 1
53//PF Correction is different for different mouse drivers. For now no correction
54//is ok because lots of Odin controls rely on minimum delta. However in future
55//we will possibly detect mouse driver and use correction if speed will be
56//too high or too low.
57
58//******************************************************************************
59//
60// setThreadQueueExtraCharMessage: queues WM_CHAR message so it is retrieved
61// by GetMessage & PeekMessage
62//
63// NOTE: Automatically converts ascii character code to UTF-16 if the target
64// window is unicode.
65//
66//******************************************************************************
67BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
68{
69 // check if the single slot is occupied already
70 if (teb->o.odin.fTranslated == TRUE)
71 // there's still an already translated message to be processed
72 return FALSE;
73
74 //Unicode windows expect the character code in UTF-16
75 if(IsWindowUnicode(pExtraMsg->hwnd))
76 {
77 CHAR charA;
78 WCHAR charW;
79
80 charA = pExtraMsg->wParam;
81 MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
82 pExtraMsg->wParam= charW;
83 dprintf(("setThreadQueueExtraCharMessage: Convert to Unicode src=%x res=%x", charA, charW ));
84 }
85
86 teb->o.odin.fTranslated = TRUE;
87 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
88 return TRUE;
89}
90
91//******************************************************************************
92//******************************************************************************
93ULONG ConvertNumPadKey(ULONG pmScan)
94{
95 ULONG ret;
96 BYTE winKey;
97
98 switch (pmScan)
99 {
100 case PMSCAN_PAD7: ret = PMSCAN_HOME; break;
101 case PMSCAN_PAD8: ret = PMSCAN_UP; break;
102 case PMSCAN_PAD9: ret = PMSCAN_PAGEUP; break;
103 case PMSCAN_PAD4: ret = PMSCAN_LEFT; break;
104 case PMSCAN_PAD6: ret = PMSCAN_RIGHT; break;
105 case PMSCAN_PAD1: ret = PMSCAN_END; break;
106 case PMSCAN_PAD2: ret = PMSCAN_DOWN; break;
107 case PMSCAN_PAD3: ret = PMSCAN_PAGEDOWN; break;
108 case PMSCAN_PAD0: ret = PMSCAN_INSERT; break;
109 case PMSCAN_PADPERIOD: ret = PMSCAN_DELETE; break;
110 default:
111 ret = pmScan;
112 }
113
114 KeyTranslatePMScanToWinVKey(ret, FALSE, (PBYTE)&winKey, NULL, NULL);
115 return winKey;
116
117}
118//******************************************************************************
119//******************************************************************************
120LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
121{
122 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
123}
124//******************************************************************************
125//******************************************************************************
126void OSLibSetMenuDoubleClick(BOOL fSet)
127{
128 fGenerateDoubleClick = fSet;
129}
130//******************************************************************************
131
132
133/**
134 * Inter process/thread packet cleanup.
135 * See OSLibPackMessage() for details on the packing.
136 *
137 * @param pTeb Pointer to the thread environment block for the current thread.
138 * @param pPacket Pointer to the packet in question.
139 * @param pWinMsg Pointer to the window message corresponding to the packet.
140 */
141inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
142{
143 switch (pWinMsg->message)
144 {
145 /*
146 * Place this in the TEB freeing any previous WM_COPYDATA packet.
147 * Note! Nested WM_COPYDATA isn't working.
148 */
149 case WINWM_COPYDATA:
150 {
151 dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
152 if (pTeb->o.odin.pWM_COPYDATA)
153 _sfree(pTeb->o.odin.pWM_COPYDATA);
154 pTeb->o.odin.pWM_COPYDATA = pPacket;
155 break;
156 }
157
158 /*
159 * Default packing - free the shared memory here.
160 */
161 default:
162 _sfree(pPacket);
163 break;
164 }
165}
166
167//******************************************************************************
168BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
169{
170 Win32BaseWindow *win32wnd = 0;
171 OSLIBPOINT point, ClientPoint;
172 POSTMSG_PACKET *packet;
173 TEB *teb = (TEB *)pTeb;
174 BOOL fWasDisabled = FALSE;
175 BOOL fIsFrame = FALSE;
176 int i;
177
178 memset(winMsg, 0, sizeof(MSG));
179 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
180 if(!win32wnd) {
181 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
182 if(win32wnd) {
183 fIsFrame = TRUE;
184 }
185 }
186
187 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
188 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
189 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
190 {
191 goto dummymessage; //not a win32 client window
192 }
193 winMsg->time = os2Msg->time;
194 //CB: PM bug or undocumented feature? ptl.x highword is set!
195 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
196 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
197
198 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
199 winMsg->hwnd = win32wnd->getWindowHandle();
200
201 if(os2Msg->msg >= WIN32APP_POSTMSG) {
202 packet = (POSTMSG_PACKET *)os2Msg->mp2;
203 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
204 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
205 winMsg->wParam = packet->wParam;
206 winMsg->lParam = packet->lParam;
207 if (fMsgRemoved == MSG_REMOVE)
208 OSLibCleanupPacket(teb, packet, winMsg);
209 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
210 return TRUE;
211 }
212 else {//broadcasted message (no packet present)
213 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
214 winMsg->wParam = (UINT)os2Msg->mp1;
215 winMsg->lParam = (DWORD)os2Msg->mp2;
216 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
217 return TRUE;
218 }
219 goto dummymessage;
220 }
221
222 switch(os2Msg->msg)
223 {
224 //OS/2 msgs
225 case WM_CREATE:
226 {
227 if(teb->o.odin.newWindow == 0) {
228 DebugInt3();
229 goto dummymessage;
230 }
231
232 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
233 win32wnd->addRef();
234
235 winMsg->message = WINWM_CREATE;
236 winMsg->hwnd = win32wnd->getWindowHandle();
237 winMsg->wParam = 0;
238 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
239 break;
240 }
241
242 case WM_QUIT:
243 winMsg->message = WINWM_QUIT;
244 if (fMsgRemoved && win32wnd && (ULONG)os2Msg->mp2 != 0) {
245 // mp2 != 0 -> sent by window list; be nice and close
246 // the window first
247 win32wnd->MsgClose();
248 }
249 break;
250
251 case WM_CLOSE:
252 winMsg->message = WINWM_CLOSE;
253 break;
254
255 case WM_DESTROY:
256 winMsg->message = WINWM_DESTROY;
257 break;
258
259 case WM_ENABLE:
260 winMsg->message = WINWM_ENABLE;
261 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
262 break;
263
264 case WM_SHOW:
265 winMsg->message = WINWM_SHOWWINDOW;
266 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
267 break;
268
269 case WM_REALIZEPALETTE:
270 winMsg->message = WINWM_PALETTECHANGED;
271 break;
272
273 case WM_WINDOWPOSCHANGED:
274 {
275 PSWP pswp = (PSWP)os2Msg->mp1;
276 SWP swpOld = *(pswp + 1);
277 HWND hParent = NULLHANDLE;
278 LONG yDelta = pswp->cy - swpOld.cy;
279 LONG xDelta = pswp->cx - swpOld.cx;
280
281 if(!fIsFrame) goto dummymessage;
282
283 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
284
285 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
286 if (win32wnd->isChild()) {
287 if(win32wnd->getParent()) {
288 hParent = win32wnd->getParent()->getOS2WindowHandle();
289 }
290 else goto dummymessage; //parent has just been destroyed
291 }
292 }
293 if(win32wnd->getParent()) {
294 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
295 win32wnd->getOS2WindowHandle());
296 }
297 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
298
299 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
300
301 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
302 {
303 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
304 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
305 {
306 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
307 if(wndAfter) {
308 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
309 RELEASE_WNDOBJ(wndAfter);
310 }
311 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
312 }
313 }
314 winMsg->message = WINWM_WINDOWPOSCHANGED;
315 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
316 break;
317 }
318
319 case WM_ACTIVATE:
320 {
321 HWND hwndActivate = (HWND)os2Msg->mp2;
322 BOOL fMinimized = FALSE;
323
324 hwndActivate = OS2ToWin32Handle(hwndActivate);
325 if(hwndActivate == 0) {
326 //another (non-win32) application's window
327 //set to desktop window handle
328 hwndActivate = windowDesktop->getWindowHandle();
329 }
330
331 if(win32wnd->getStyle() & WS_MINIMIZE_W)
332 {
333 fMinimized = TRUE;
334 }
335
336 winMsg->message = WINWM_ACTIVATE;
337 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
338 winMsg->lParam = (LPARAM)hwndActivate;
339 break;
340 }
341
342 case WM_SETFOCUS:
343 {
344 HWND hwndFocus = (HWND)os2Msg->mp1;
345
346 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
347 //another (non-win32) application's window
348 //set to NULL (allowed according to win32 SDK) to avoid problems
349 hwndFocus = NULL;
350 }
351 else hwndFocus = OS2ToWin32Handle(hwndFocus);
352
353 if((ULONG)os2Msg->mp2 == TRUE) {
354 winMsg->message = WINWM_SETFOCUS;
355 winMsg->wParam = (WPARAM)hwndFocus;
356 }
357 else {
358 //If SetFocus(0) was called, then the window has already received
359 //a WM_KILLFOCUS; don't send another one
360 if(!fIgnoreKeystrokes) {
361 winMsg->message = WINWM_KILLFOCUS;
362 winMsg->wParam = (WPARAM)hwndFocus;
363 }
364 else {
365 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
366 goto dummymessage;
367 }
368 }
369 break;
370 }
371
372 //**************************************************************************
373 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
374 //**************************************************************************
375 case WM_BUTTON1DOWN:
376 case WM_BUTTON1UP:
377 case WM_BUTTON1DBLCLK:
378 case WM_BUTTON2DOWN:
379 case WM_BUTTON2UP:
380 case WM_BUTTON2DBLCLK:
381 case WM_BUTTON3DOWN:
382 case WM_BUTTON3UP:
383 case WM_BUTTON3DBLCLK:
384 {
385 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
386
387 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));
388
389 HWND hwnd;
390
391 DisableLogging();
392 if(GetCapture() != winMsg->hwnd)
393 {
394 hwnd = WindowFromPoint(winMsg->pt);
395 if(win32wnd->getWindowHandle() != hwnd) {
396 RELEASE_WNDOBJ(win32wnd);
397 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
398 if(win32wnd == NULL) {
399 DebugInt3();
400 EnableLogging();
401 goto dummymessage;
402 }
403 winMsg->hwnd = hwnd;
404 }
405 }
406
407 //if a window is disabled, its parent receives the mouse messages
408 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
409 if(win32wnd->getParent()) {
410 Win32BaseWindow *parent = win32wnd->getParent();;
411 if(parent) parent->addRef();
412 RELEASE_WNDOBJ(win32wnd);
413 win32wnd = parent;
414 }
415 fWasDisabled = TRUE;
416 }
417
418 if(IsNCMouseMsg(win32wnd)) {
419 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
420 winMsg->wParam = win32wnd->getLastHitTestVal();
421 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
422 }
423 else {
424 ClientPoint.x = winMsg->pt.x;
425 ClientPoint.y = winMsg->pt.y;
426 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
427 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
428 winMsg->wParam = GetMouseKeyState();
429 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
430 }
431 EnableLogging();
432
433 if(fWasDisabled) {
434 if(win32wnd) {
435 winMsg->hwnd = win32wnd->getWindowHandle();
436 }
437 else goto dummymessage; //don't send mouse messages to disabled windows
438 }
439
440 DisableLogging();
441 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
442 (winMsg->message == WINWM_RBUTTONDOWN) ||
443 (winMsg->message == WINWM_MBUTTONDOWN) ||
444 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
445 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
446 (winMsg->message == WINWM_NCMBUTTONDOWN))
447 {
448 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
449 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
450 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
451 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
452 {
453 dprintf(("single -> double click"));
454 if(winMsg->message >= WINWM_LBUTTONDOWN) {
455 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
456 }
457 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
458 if(fMsgRemoved) doubleClickMsg.message = 0;
459 }
460 else {
461 dprintf(("save for double click"));
462 if(fMsgRemoved) {
463 doubleClickMsg = *winMsg;
464 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
465 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
466 }
467 }
468 }
469 }
470 EnableLogging();
471
472 if(fMsgRemoved == MSG_REMOVE)
473 {
474 MSLLHOOKSTRUCT hook;
475 ULONG msg;
476
477 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
478 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
479 }
480 else msg = winMsg->message;
481
482 if(msg == WINWM_LBUTTONDBLCLK) {
483 msg = WINWM_LBUTTONDOWN;
484 }
485 else
486 if(msg == WINWM_RBUTTONDBLCLK) {
487 msg = WINWM_RBUTTONDOWN;
488 }
489 else
490 if(msg == WINWM_MBUTTONDBLCLK) {
491 msg = WINWM_MBUTTONDOWN;
492 }
493
494 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
495 hook.pt.y = mapScreenY(os2Msg->ptl.y);
496 hook.mouseData = 0; //todo: XBUTTON1/2 (XP feature) or wheel data
497 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
498 hook.time = winMsg->time;
499 hook.dwExtraInfo = 0;
500
501 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
502 goto dummymessage; //hook swallowed message
503 }
504 }
505 break;
506 }
507
508 case WM_BUTTON2CLICK:
509 case WM_BUTTON1CLICK:
510 case WM_BUTTON3CLICK:
511 goto dummymessage;
512
513 case WM_BUTTON2MOTIONSTART:
514 case WM_BUTTON2MOTIONEND:
515 case WM_BUTTON1MOTIONSTART:
516 case WM_BUTTON1MOTIONEND:
517 case WM_BUTTON3MOTIONSTART:
518 case WM_BUTTON3MOTIONEND:
519 //no break; translate to WM_MOUSEMOVE
520 //Some applications (e.g. Unreal) retrieve all mouse messages
521 //when a mouse button is pressed and don't expect WM_NULL
522
523 case WM_MOUSEMOVE:
524 {
525 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
526
527 HWND hwnd;
528
529 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
530 DisableLogging();
531 if(GetCapture() != winMsg->hwnd)
532 {
533 hwnd = WindowFromPoint(winMsg->pt);
534 if(win32wnd->getWindowHandle() != hwnd) {
535 RELEASE_WNDOBJ(win32wnd);
536 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
537 if(win32wnd == NULL) {
538 DebugInt3();
539 EnableLogging();
540 goto dummymessage;
541 }
542 winMsg->hwnd = hwnd;
543 }
544 }
545
546 //if a window is disabled, its parent receives the mouse messages
547 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
548 if(win32wnd->getParent()) {
549 Win32BaseWindow *parent = win32wnd->getParent();;
550 if(parent) parent->addRef();
551 RELEASE_WNDOBJ(win32wnd);
552 win32wnd = parent;
553 }
554 fWasDisabled = TRUE;
555 }
556 if(IsNCMouseMsg(win32wnd))
557 {
558 winMsg->message = WINWM_NCMOUSEMOVE;
559 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
560 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
561 }
562 else
563 {
564 ClientPoint.x = winMsg->pt.x;
565 ClientPoint.y = winMsg->pt.y;
566 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
567
568 winMsg->message = WINWM_MOUSEMOVE;
569 winMsg->wParam = GetMouseKeyState();
570 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
571 }
572 EnableLogging();
573 if(fWasDisabled) {
574 if(win32wnd) {
575 winMsg->hwnd = win32wnd->getWindowHandle();
576 }
577 else {
578 goto dummymessage; //don't send mouse messages to disabled windows
579 }
580 }
581 if(fMsgRemoved == MSG_REMOVE)
582 {
583 MSLLHOOKSTRUCT hook;
584
585 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
586 hook.pt.y = mapScreenY(os2Msg->ptl.y);
587 hook.mouseData = 0;
588 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
589 hook.time = winMsg->time;
590 hook.dwExtraInfo = 0;
591
592 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, winMsg->message, (LPARAM)&hook)) {
593 goto dummymessage; //hook swallowed message
594 }
595 }
596 break;
597 }
598
599 case WM_CONTROL:
600 goto dummymessage;
601
602 case WM_COMMAND:
603 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
604 winMsg->message = WINWM_COMMAND;
605 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
606 break;
607 }
608 //todo controls
609 goto dummymessage;
610
611 case WM_SYSCOMMAND:
612 {
613 ULONG x = 0, y = 0;
614 ULONG win32sc;
615
616 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
617 POINTL pointl;
618 WinQueryPointerPos(HWND_DESKTOP, &pointl);
619 x = pointl.x;
620 y = mapScreenY(y);
621 }
622 switch(SHORT1FROMMP(os2Msg->mp1)) {
623 case SC_MOVE:
624 win32sc = SC_MOVE_W;
625 break;
626 case SC_CLOSE:
627 {
628 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
629 //TRUE -> user clicked on close button -> close window
630 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
631 {
632 HWND hwnd = win32wnd->GetTopParent();
633 if(win32wnd->getWindowHandle() != hwnd) {
634 RELEASE_WNDOBJ(win32wnd);
635 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
636 if(win32wnd == NULL) {
637 DebugInt3();
638 goto dummymessage;
639 }
640 winMsg->hwnd = hwnd;
641 }
642 }
643 win32sc = SC_CLOSE_W;
644 break;
645 }
646 case SC_MAXIMIZE:
647 win32sc = SC_MAXIMIZE_W;
648 break;
649 case SC_MINIMIZE:
650 win32sc = SC_MINIMIZE_W;
651 break;
652 case SC_NEXTFRAME:
653 case SC_NEXTWINDOW:
654 win32sc = SC_NEXTWINDOW_W;
655 break;
656 case SC_RESTORE:
657 win32sc = SC_RESTORE_W;
658 break;
659 case SC_TASKMANAGER:
660 win32sc = SC_TASKLIST_W;
661 break;
662 case SC_SYSMENU:
663 win32sc = SC_KEYMENU_W; //??
664 break;
665 default:
666 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
667 goto dummymessage;
668 }
669 winMsg->message= WINWM_SYSCOMMAND;
670 winMsg->wParam = (WPARAM)win32sc;
671 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
672 break;
673 }
674
675 case WM_CHAR_SPECIAL_CONSOLE_BREAK:
676 {
677 dprintf(("PM: WM_CHAR_SPECIAL_CONSOLE_BREAK for %x", winMsg->hwnd));
678 if(fMsgRemoved)
679 {
680 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT_W,0);
681 // It is our internal message, do not work with it more, its function
682 // is over, otherwise it will return FALSE and will be dispatched,
683 // and retranslated once again.
684
685 winMsg->message = 0;
686 winMsg->wParam = 0;
687 winMsg->lParam = 0;
688 goto msgdone;
689 }
690 goto dummymessage;
691 }
692
693 case WM_CHAR_SPECIAL_ALTGRCONTROL:
694 {
695 // special char message from the keyboard hook
696 dprintf(("PM: WM_CHAR_SPECIAL_ALTGRCONTROL"));
697 // NO BREAK! FALLTHRU CASE!
698 }
699
700 case WM_CHAR_SPECIAL:
701 {
702 // @@@PH
703 // special char message from the keyboard hook
704 if(os2Msg->msg == WM_CHAR_SPECIAL) {
705 dprintf(("PM: WM_CHAR_SPECIAL"));
706 }
707 // NO BREAK! FALLTHRU CASE!
708 }
709
710 case WM_CHAR:
711 {
712 ULONG repeatCount=0;
713 ULONG virtualKey=0;
714 ULONG keyFlags=0;
715 USHORT scanCode=0;
716 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
717 BOOL keyWasPressed;
718 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
719 char c;
720 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
721
722 teb->o.odin.fTranslated = FALSE;
723 repeatCount = CHAR3FROMMP(os2Msg->mp1);
724 scanCode = CHAR4FROMMP(os2Msg->mp1);
725 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
726
727 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
728 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
729
730 BOOL fWinExtended;
731 BYTE bWinVKey;
732 WORD wWinScan;
733
734 if (scanCode==0) goto dummymessage;
735
736 KeyTranslatePMScanToWinVKey(usPMScanCode,
737 FALSE,
738 &bWinVKey,
739 &wWinScan,
740 &fWinExtended);
741 winMsg->wParam = bWinVKey;
742 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
743 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
744
745 // Set the extended bit when appropriate
746 if (fWinExtended)
747 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
748
749 //PF When we press shift we enable non-numeric functions of Numpad
750 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
751 winMsg->wParam = ConvertNumPadKey(scanCode);
752
753 //@PF This looks ugly but this is just what we have in win32 both in win98/win2k
754 //what happens is that lParam is tweaked in win32 to contain some illegal codes
755 //I simply reproduce here all situation. Absolute values can be kept because
756 //Break scancode can be acheived only by pressing Ctrl-Break combination
757 if ((usPMScanCode == PMSCAN_BREAK) && !(flags & KC_KEYUP) && (flags & KC_CTRL)
758 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
759 {
760 MSG extramsg;
761 memcpy(&extramsg, winMsg, sizeof(MSG));
762 // adjust our WM_CHAR code
763 extramsg.lParam = 0x01460001;
764
765 //After SetFocus(0), all keystrokes are converted in WM_SYS*
766 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
767
768 setThreadQueueExtraCharMessage(teb, &extramsg);
769 // and finally adjust our WM_KEYDOWN code
770 winMsg->lParam = 0x01460001;
771 }
772
773 if (!(flags & KC_ALT))
774 {
775 //
776 // the Alt key is not pressed
777 // or no more pressed
778 //
779 if (flags & KC_KEYUP)
780 {
781 // check for a lonesome ALT key ...
782 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
783 if ( (flags & KC_LONEKEY) &&
784 (winMsg->wParam == VK_LMENU_W) )
785 {
786 winMsg->message = WINWM_SYSKEYUP;
787 // held ALT-key when current key is released
788 // generates additional flag 0x2000000
789 // Note: PM seems to do this differently,
790 // KC_ALT is already reset
791 }
792 else
793 {
794 // send WM_KEYUP message
795 winMsg->message = WINWM_KEYUP;
796 }
797 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
798 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
799 }
800 else
801 { // send WM_KEYDOWN message
802 winMsg->message = WINWM_KEYDOWN;
803
804 if (keyWasPressed)
805 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
806
807 //Shift-Enter and possibly others need to have special handling
808 if (flags & KC_SHIFT)
809 {
810 if(fMsgRemoved && !(teb->o.odin.fTranslated))
811 {
812 dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
813 if (winMsg->wParam == VK_RETURN_W)
814 {
815 MSG extramsg;
816 memcpy(&extramsg, winMsg, sizeof(MSG));
817
818 //After SetFocus(0), all keystrokes are converted in WM_SYS*
819 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
820
821 // insert message into the queue
822 setThreadQueueExtraCharMessage(teb, &extramsg);
823 winMsg->lParam &= 0x3FFFFFFF;
824 }
825 } // else ???
826 } // KC_SHIFT
827 else
828 {
829 // in case we handle Enter directly through PMKBDHOOK
830 if ((os2Msg->msg == WM_CHAR_SPECIAL) && (winMsg->wParam == VK_RETURN_W)
831 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
832 {
833 MSG extramsg;
834 memcpy(&extramsg, winMsg, sizeof(MSG));
835
836 //After SetFocus(0), all keystrokes are converted in WM_SYS*
837 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
838
839 // insert message into the queue
840 setThreadQueueExtraCharMessage(teb, &extramsg);
841 }
842 }
843 }
844 // if right alt is down, then we need to set the alt down bit too
845 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
846 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
847 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
848 {
849 winMsg->lParam |= WIN_KEY_ALTHELD;
850 }
851 }
852 else
853 {
854 //
855 // the Alt key is pressed
856 //
857 if (flags & KC_KEYUP)
858 {
859 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
860 winMsg->message = WINWM_SYSKEYUP;
861 winMsg->lParam |= WIN_KEY_PREVSTATE;
862 // No ALTHELD for Alt itself ;)
863 winMsg->lParam |= WIN_KEY_ALTHELD;
864 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
865 }
866 else
867 {
868 // send WM_SYSKEYDOWN message
869 winMsg->message = WINWM_SYSKEYDOWN;
870 if (keyWasPressed)
871 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
872
873 // pressed ALT-key generates additional flag 0x2000000
874 // if the current window has keyboard focus
875 winMsg->lParam |= WIN_KEY_ALTHELD;
876 }
877 }
878#if 0
879 //
880 // AltGr needs special handling
881 //
882 // AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
883 // WM_SYSKEYUP (VK_CONTROL)
884 // WM_KEYUP (VK_MENU)
885 //
886 // Ctrl+AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYUP (VK_CONTROL)
887 // WM_KEYDOWN (VK_MENU)
888 // WM_KEYUP (VK_MENU)
889 // WM_KEYUP (VK_CONTROL)
890 //
891 // AltGr+Ctrl -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
892 // WM_KEYDOWN (VK_CONTROL)
893 // WM_SYSKEYUP (VK_CONTROL)
894 // WM_SYSKEYUP (VK_CONTROL)
895 // WM_KEYUP (VK_MENU)
896 //
897 // AltGr down -> if Ctrl down, send WM_KEYUP (VK_CONTROL)
898 // endif
899 // Send WM_KEYDOWN (VK_CONTROL)
900 // Send WM_KEYDOWN (VK_MENU)
901 // AltGr up -> if !(Ctrl down before AltGr was pressed || Ctrl up)
902 // Send WM_SYSKEYUP (VK_CONTROL)
903 // endif
904 // Send WM_KEYDOWN (VK_MENU)
905 //
906 if(winMsg->wParam == VK_MENU_W && (winMsg->lParam & WIN_KEY_EXTENDED))
907 {//AltGr
908 if(GetKeyState(VK_CONTROL_W) & 0x8000)
909 {//Ctrl key pressed, send WM_KEYUP
910
911 }
912 }
913#endif
914
915 //After SetFocus(0), all keystrokes are converted in WM_SYS*
916 if(fIgnoreKeystrokes) {
917 if(winMsg->message == WINWM_KEYDOWN) {
918 winMsg->message = WINWM_SYSKEYDOWN;
919 }
920 else
921 if(winMsg->message == WINWM_KEYUP) {
922 winMsg->message = WINWM_SYSKEYUP;
923 }
924 }
925 break;
926 }
927
928 case WM_TIMER:
929//Why was this check here????
930// if (os2Msg->mp2)
931// {
932 BOOL sys;
933 ULONG id, proc;
934
935 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
936 {
937 winMsg->wParam = (WPARAM)id;
938 winMsg->lParam = (LPARAM)proc;
939 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
940 break;
941 }
942// }
943 goto dummymessage; //for caret blinking
944
945 case WM_SETWINDOWPARAMS:
946 {
947 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
948
949 if(wndParams->fsStatus & WPM_TEXT) {
950 winMsg->message = WINWM_SETTEXT;
951 winMsg->lParam = (LPARAM)wndParams->pszText;
952 break;
953 }
954 goto dummymessage;
955 }
956
957#if 0
958 case WM_QUERYWINDOWPARAMS:
959 {
960 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
961 ULONG textlen;
962 PSZ wintext;
963
964 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
965 {
966 if(wndpars->fsStatus & WPM_CCHTEXT)
967 wndpars->cchText = win32wnd->MsgGetTextLength();
968 if(wndpars->fsStatus & WPM_TEXT)
969 wndpars->pszText = win32wnd->MsgGetText();
970
971 wndpars->fsStatus = 0;
972 wndpars->cbCtlData = 0;
973 wndpars->cbPresParams = 0;
974 goto dummymessage;
975 }
976 }
977#endif
978
979 case WM_PAINT:
980 {
981 if(win32wnd->IsWindowIconic()) {
982 winMsg->message = WINWM_PAINTICON;
983 }
984 else winMsg->message = WINWM_PAINT;
985 break;
986 }
987
988 case WM_CONTEXTMENU:
989 winMsg->message = WINWM_CONTEXTMENU;
990 winMsg->wParam = win32wnd->getWindowHandle();
991 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
992 break;
993
994 case WM_RENDERFMT:
995 winMsg->message = WINWM_RENDERFORMAT;
996 winMsg->wParam = (UINT) os2Msg->mp1;
997 break;
998
999 case WM_RENDERALLFMTS:
1000 winMsg->message = WINWM_RENDERALLFORMATS;
1001 break;
1002
1003 case WM_DESTROYCLIPBOARD:
1004 winMsg->message = WINWM_DESTROYCLIPBOARD;
1005 break;
1006
1007 case WM_DRAWCLIPBOARD:
1008 winMsg->message = WINWM_DRAWCLIPBOARD;
1009 break;
1010
1011 case WM_HSCROLL:
1012 case WM_VSCROLL:
1013 //PF For win32 we support only vertical scrolling for WM_MOUSEWHEEL
1014 if (os2Msg->msg == WM_VSCROLL)
1015 {
1016 POINT CursorPoint;
1017 winMsg->message = WINWM_MOUSEWHEEL;
1018 if (OSLibWinQueryPointerPos(&CursorPoint))
1019 mapScreenPoint((OSLIBPOINT*)&CursorPoint);
1020
1021 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1022 winMsg->wParam = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1023 else
1024 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1025 winMsg->wParam = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1026 else
1027 winMsg->wParam = MAKELONG(GetMouseKeyState(), 0);
1028
1029 winMsg->lParam = MAKELONG(CursorPoint.x, CursorPoint.y);
1030
1031 dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
1032 if (fMsgRemoved == MSG_REMOVE)
1033 {
1034 MSLLHOOKSTRUCT hook;
1035
1036 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
1037 hook.pt.y = mapScreenY(os2Msg->ptl.y);
1038 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1039 hook.mouseData = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1040 else
1041 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1042 hook.mouseData = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1043 else goto dummymessage; // IBM driver produces other messages as well sometimes
1044
1045 hook.flags = LLMHF_INJECTED;
1046 hook.time = winMsg->time;
1047 hook.dwExtraInfo = 0;
1048 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
1049 goto dummymessage; //hook swallowed message
1050 }
1051 break;
1052 }
1053 goto dummymessage; //eat this message
1054 break;
1055
1056 case WM_INITMENU:
1057 case WM_MENUSELECT:
1058 case WM_MENUEND:
1059 case WM_NEXTMENU:
1060 case WM_SYSCOLORCHANGE:
1061 case WM_SYSVALUECHANGED:
1062 case WM_SETSELECTION:
1063 case WM_PPAINT:
1064 case WM_PSETFOCUS:
1065 case WM_PSYSCOLORCHANGE:
1066 case WM_PSIZE:
1067 case WM_PACTIVATE:
1068 case WM_PCONTROL:
1069 case WM_HELP:
1070 case WM_APPTERMINATENOTIFY:
1071 case WM_PRESPARAMCHANGED:
1072 case WM_DRAWITEM:
1073 case WM_MEASUREITEM:
1074 case WM_CONTROLPOINTER:
1075 case WM_QUERYDLGCODE:
1076 case WM_SUBSTITUTESTRING:
1077 case WM_MATCHMNEMONIC:
1078 case WM_SAVEAPPLICATION:
1079 case WM_SEMANTICEVENT:
1080 default:
1081dummymessage:
1082 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
1083 winMsg->message = 0;
1084 winMsg->wParam = 0;
1085 winMsg->lParam = 0;
1086 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1087 return FALSE;
1088 }
1089msgdone:
1090 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1091 return TRUE;
1092}
1093//******************************************************************************
1094//******************************************************************************
1095BOOL OSLibWinTranslateMessage(MSG *msg)
1096{
1097 TEB *teb;
1098 MSG extramsg;
1099 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
1100 teb = GetThreadTEB();
1101 if(!teb)
1102 return FALSE;
1103
1104 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1105 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
1106
1107
1108 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1109 // the newly generated WM_CHAR message.
1110 if(!teb->o.odin.fTranslated &&
1111 teb->o.odin.os2msg.msg == WM_CHAR &&
1112 !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
1113 {
1114 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
1115 memcpy(&extramsg, msg, sizeof(MSG));
1116 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1117 extramsg.lParam = 0;
1118
1119 // ESCAPE generates a WM_CHAR under windows, so take
1120 // special care for this here.
1121 switch (ucPMScanCode)
1122 {
1123 case PMSCAN_ESC:
1124 extramsg.wParam = VK_ESCAPE_W;
1125 fl |= KC_CHAR;
1126 break;
1127 }
1128
1129 // PF With NumLock off do not generate any WM_CHAR messages at all
1130 // PADMINUS,PADPLUS fall in range of PAD7..PADPERIOD but they should generate WM_CHAR
1131 // other PAD(X) buttons miss that range at all and thus generate WM_CHAR
1132 if (!numPressed && (ucPMScanCode != PMSCAN_PADMINUS) && (ucPMScanCode != PMSCAN_PADPLUS) &&
1133 (ucPMScanCode >= PMSCAN_PAD7) && (ucPMScanCode <= PMSCAN_PADPERIOD))
1134 return FALSE;
1135
1136 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1137 {
1138 return FALSE;
1139 }
1140
1141 //the KC_COMPOSITE flag might be set; in that case this key will
1142 //be combined with the previous dead key, so we must use the scancode
1143 //(e.g. ^ on german keyboards)
1144 if((fl & (KC_VIRTUALKEY|KC_COMPOSITE)) == KC_VIRTUALKEY)
1145 {
1146 if(msg->wParam)
1147 {
1148 if ((msg->wParam >= VK_NUMPAD0_W) &&
1149 (msg->wParam <= VK_NUMPAD9_W))
1150 extramsg.wParam = msg->wParam - 0x30;
1151 else
1152 if (msg->wParam == VK_DECIMAL_W)
1153 extramsg.wParam = VK_DELETE_W;
1154 else
1155 /* PM Sends Bogus Things when pressing Shift+NUMAsterisk */
1156 if (msg->wParam != VK_MULTIPLY_W)
1157 extramsg.wParam = msg->wParam;
1158 }
1159 else
1160 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1161 }
1162
1163
1164 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1165 if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
1166 extramsg.message = WINWM_SYSCHAR;
1167 else
1168 extramsg.message = WINWM_CHAR;
1169
1170 if(fl & KC_DEADKEY)
1171 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1172
1173
1174 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1175 if ((fl & KC_ALT) || (msg->lParam & WIN_KEY_ALTHELD))
1176 extramsg.lParam |= WIN_KEY_ALTHELD;
1177 if(fl & KC_PREVDOWN)
1178 extramsg.lParam |= WIN_KEY_PREVSTATE;
1179 if(fl & KC_KEYUP)
1180 extramsg.lParam |= (1<<31);
1181
1182 // insert message into the queue
1183 setThreadQueueExtraCharMessage(teb, &extramsg);
1184
1185 return TRUE;
1186 }
1187 return FALSE;
1188}
1189//******************************************************************************
1190//******************************************************************************
1191
Note: See TracBrowser for help on using the repository browser.