Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

oslibmsgtranslate.cpp

Go to the documentation of this file.
00001 /* $Id: oslibmsgtranslate.cpp,v 1.79 2001/12/12 16:40:43 sandervl Exp $ */
00002 /*
00003  * Window message translation functions for OS/2
00004  *
00005  *
00006  * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
00007  * Copyright 1999      Daniela Engert (dani@ngrt.de)
00008  * Copyright 1999      Rene Pronk (R.Pronk@twi.tudelft.nl)
00009  *
00010  * Project Odin Software License can be found in LICENSE.TXT
00011  *
00012  * TODO: Extra msgs: which messages must be put into the queue and which can be sent directly?
00013  *       (According to the docs TranslateMessage really inserts a msg in the queue)
00014  * TODO: Filter translation isn't correct for posted messages
00015  *
00016  */
00017 #define  INCL_WIN
00018 #define  INCL_PM
00019 #define  INCL_DOSPROCESS
00020 #include <os2wrap.h>
00021 #include <string.h>
00022 #include <misc.h>
00023 #include <winconst.h>
00024 #include <win32api.h>
00025 #include "oslibmsg.h"
00026 #include <winuser32.h>
00027 #include "win32wdesktop.h"
00028 #include "oslibutil.h"
00029 #include "timer.h"
00030 #include <thread.h>
00031 #include <wprocess.h>
00032 #include "pmwindow.h"
00033 #include "oslibwin.h"
00034 #include "winmouse.h"
00035 #include <pmkbdhk.h>
00036 #include <pmscan.h>
00037 #include <winscan.h>
00038 #include <winkeyboard.h>
00039 
00040 #define DBG_LOCALLOG    DBG_oslibmsgtranslate
00041 #include "dbglocal.h"
00042 
00043 
00044 static BOOL fGenerateDoubleClick = FALSE;
00045 static MSG  doubleClickMsg = {0};
00046 
00047 //******************************************************************************
00048 //******************************************************************************
00049 BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
00050 {
00051   // check if the single slot is occupied already
00052   if (teb->o.odin.fTranslated == TRUE)
00053     // there's still an already translated message to be processed
00054     return FALSE;
00055   
00056   teb->o.odin.fTranslated = TRUE;
00057   memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
00058   return TRUE;
00059 }
00060 
00061 //******************************************************************************
00062 //******************************************************************************
00063 ULONG GetMouseKeyState()
00064 {
00065   ULONG keystate = 0;
00066 
00067   if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
00068     keystate |= MK_LBUTTON_W;
00069   if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
00070     keystate |= MK_RBUTTON_W;
00071   if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
00072     keystate |= MK_MBUTTON_W;
00073   if(WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000)
00074     keystate |= MK_SHIFT_W;
00075   if(WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
00076     keystate |= MK_CONTROL_W;
00077 
00078   return keystate;
00079 }
00080 //******************************************************************************
00081 //******************************************************************************
00082 LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
00083 {
00084   return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
00085 }
00086 //******************************************************************************
00087 //******************************************************************************
00088 void SetMenuDoubleClick(BOOL fSet)
00089 {
00090   fGenerateDoubleClick = fSet;
00091 }
00092 //******************************************************************************
00093 //******************************************************************************
00094 BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
00095 {
00096   Win32BaseWindow *win32wnd = 0;
00097   OSLIBPOINT       point, ClientPoint;
00098   POSTMSG_PACKET  *packet;
00099   TEB             *teb = (TEB *)pTeb;
00100   BOOL             fWasDisabled = FALSE;
00101   BOOL             fIsFrame = FALSE;
00102   int i;
00103 
00104     memset(winMsg, 0, sizeof(MSG));
00105     win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
00106     if(!win32wnd) {
00107         win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
00108         if(win32wnd) {
00109             fIsFrame = TRUE;
00110         }
00111     }
00112 
00113     //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
00114     //Realplayer starts a timer with hwnd 0 & proc 0; check this here
00115     if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
00116     {
00117         goto dummymessage; //not a win32 client window
00118     }
00119     winMsg->time = os2Msg->time;
00120     //CB: PM bug or undocumented feature? ptl.x highword is set!
00121     winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
00122     winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
00123 
00124     if(win32wnd) //==0 for WM_CREATE/WM_QUIT
00125         winMsg->hwnd = win32wnd->getWindowHandle();
00126 
00127     if(os2Msg->msg >= WIN32APP_POSTMSG) {
00128         packet = (POSTMSG_PACKET *)os2Msg->mp2;
00129         if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
00130             winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
00131             winMsg->wParam  = packet->wParam;
00132             winMsg->lParam  = packet->lParam;
00133             if(fMsgRemoved == MSG_REMOVE) free(packet); //free the shared memory here
00134             if(win32wnd) RELEASE_WNDOBJ(win32wnd);
00135             return TRUE;
00136         }
00137         else {//broadcasted message (no packet present)
00138             winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
00139             winMsg->wParam  = (UINT)os2Msg->mp1;
00140             winMsg->lParam  = (DWORD)os2Msg->mp2;
00141             if(win32wnd) RELEASE_WNDOBJ(win32wnd);
00142             return TRUE;
00143         }
00144         goto dummymessage;
00145     }
00146 
00147     switch(os2Msg->msg)
00148     {
00149     //OS/2 msgs
00150     case WM_CREATE:
00151     {
00152         if(teb->o.odin.newWindow == 0) {
00153             DebugInt3();
00154             goto dummymessage;
00155         }
00156 
00157         win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
00158         win32wnd->addRef();
00159 
00160         winMsg->message = WINWM_CREATE;
00161         winMsg->hwnd    = win32wnd->getWindowHandle();
00162         winMsg->wParam  = 0;
00163         winMsg->lParam  = (LPARAM)win32wnd->tmpcs;
00164         break;
00165     }
00166 
00167     case WM_QUIT:
00168         winMsg->message = WINWM_QUIT;
00169         break;
00170 
00171     case WM_CLOSE:
00172         winMsg->message = WINWM_CLOSE;
00173         break;
00174 
00175     case WM_DESTROY:
00176         winMsg->message = WINWM_DESTROY;
00177         break;
00178 
00179     case WM_ENABLE:
00180         winMsg->message = WINWM_ENABLE;
00181         winMsg->wParam  = SHORT1FROMMP(os2Msg->mp1);
00182         break;
00183 
00184     case WM_SHOW:
00185         winMsg->message = WINWM_SHOWWINDOW;
00186         winMsg->wParam  = SHORT1FROMMP(os2Msg->mp1);
00187         break;
00188 
00189     case WM_WINDOWPOSCHANGED:
00190     {
00191       PSWP      pswp  = (PSWP)os2Msg->mp1;
00192       SWP       swpOld = *(pswp + 1);
00193       HWND      hParent = NULLHANDLE;
00194       LONG      yDelta = pswp->cy - swpOld.cy;
00195       LONG      xDelta = pswp->cx - swpOld.cx;
00196 
00197         if(!fIsFrame) goto dummymessage;
00198 
00199         if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
00200 
00201         if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
00202             if (win32wnd->isChild()) {
00203                 if(win32wnd->getParent()) {
00204                         hParent = win32wnd->getParent()->getOS2WindowHandle();
00205                 }
00206                 else    goto dummymessage; //parent has just been destroyed
00207             }
00208         }
00209         if(win32wnd->getParent()) {
00210               OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
00211                                      win32wnd->getOS2WindowHandle());
00212         }
00213         else  OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
00214 
00215         if (!win32wnd->CanReceiveSizeMsgs())    goto dummymessage;
00216 
00217         if(pswp->fl & (SWP_MOVE | SWP_SIZE))
00218         {
00219                 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
00220                 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
00221                 {
00222                         Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
00223                         if(wndAfter) {
00224                               teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
00225                               RELEASE_WNDOBJ(wndAfter);
00226                         }
00227                         else  teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
00228                 }
00229         }
00230         winMsg->message = WINWM_WINDOWPOSCHANGED;
00231         winMsg->lParam  = (LPARAM)&teb->o.odin.wp;
00232         break;
00233     }
00234 
00235     case WM_ACTIVATE:
00236     {
00237       HWND hwndActivate = (HWND)os2Msg->mp2;
00238       BOOL fMinimized = FALSE;
00239 
00240         hwndActivate = OS2ToWin32Handle(hwndActivate);
00241         if(hwndActivate == 0) {
00242             //another (non-win32) application's window
00243             //set to desktop window handle
00244             hwndActivate = windowDesktop->getWindowHandle();
00245         }
00246 
00247         if(win32wnd->getStyle() & WS_MINIMIZE_W)
00248         {
00249            fMinimized = TRUE;
00250         }
00251 
00252         winMsg->message = WINWM_ACTIVATE;
00253         winMsg->wParam  = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
00254         winMsg->lParam  = (LPARAM)hwndActivate;
00255         break;
00256     }
00257 
00258     case WM_SETFOCUS:
00259     {
00260       HWND hwndFocus = (HWND)os2Msg->mp1;
00261 
00262         if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
00263                 //another (non-win32) application's window
00264                 //set to NULL (allowed according to win32 SDK) to avoid problems
00265                 hwndFocus = NULL;
00266         }
00267         else    hwndFocus = OS2ToWin32Handle(hwndFocus);
00268 
00269         if((ULONG)os2Msg->mp2 == TRUE) {
00270                 winMsg->message = WINWM_SETFOCUS;
00271                 winMsg->wParam  = (WPARAM)hwndFocus;
00272         }
00273         else {
00274                 winMsg->message = WINWM_KILLFOCUS;
00275                 winMsg->wParam  = (WPARAM)hwndFocus;
00276         }
00277         break;
00278     }
00279 
00280     //**************************************************************************
00281     //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
00282     //**************************************************************************
00283     case WM_BUTTON1DOWN:
00284     case WM_BUTTON1UP:
00285     case WM_BUTTON1DBLCLK:
00286     case WM_BUTTON2DOWN:
00287     case WM_BUTTON2UP:
00288     case WM_BUTTON2DBLCLK:
00289     case WM_BUTTON3DOWN:
00290     case WM_BUTTON3UP:
00291     case WM_BUTTON3DBLCLK:
00292     {
00293         //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
00294 
00295         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));
00296 
00297         HWND hwnd;
00298 
00299         DisableLogging();
00300         if(GetCapture() != winMsg->hwnd)
00301         {
00302             hwnd = WindowFromPoint(winMsg->pt);
00303             if(win32wnd->getWindowHandle() != hwnd) {
00304                 RELEASE_WNDOBJ(win32wnd);
00305                 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00306                 if(win32wnd == NULL) {
00307                     DebugInt3();
00308                     EnableLogging();
00309                     goto dummymessage;
00310                 }
00311                 winMsg->hwnd = hwnd;
00312             }
00313         }
00314 
00315         //if a window is disabled, it's parent receives the mouse messages
00316         if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
00317             if(win32wnd->getParent()) {
00318                 Win32BaseWindow *parent = win32wnd->getParent();;
00319                 if(parent) parent->addRef();
00320                 RELEASE_WNDOBJ(win32wnd);
00321                 win32wnd = parent;
00322             }
00323             fWasDisabled = TRUE;
00324         }
00325 
00326         if(IsNCMouseMsg(win32wnd)) {
00327             winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
00328             winMsg->wParam  = win32wnd->getLastHitTestVal();
00329             winMsg->lParam  = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
00330         }
00331         else {
00332             ClientPoint.x = winMsg->pt.x;
00333             ClientPoint.y = winMsg->pt.y;
00334             MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
00335             winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
00336             winMsg->wParam  = GetMouseKeyState();
00337             winMsg->lParam  = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
00338         }
00339         EnableLogging();
00340         if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
00341         {
00342             if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
00343                 goto dummymessage; //dinput swallowed message
00344             }
00345         }
00346 
00347         if(fWasDisabled) {
00348             if(win32wnd) {
00349                 winMsg->hwnd = win32wnd->getWindowHandle();
00350             }
00351             else goto dummymessage; //don't send mouse messages to disabled windows
00352         }
00353 
00354         DisableLogging();
00355         if ((winMsg->message == WINWM_LBUTTONDOWN) ||
00356             (winMsg->message == WINWM_RBUTTONDOWN) ||
00357             (winMsg->message == WINWM_MBUTTONDOWN) ||
00358             (winMsg->message == WINWM_NCLBUTTONDOWN) ||
00359             (winMsg->message == WINWM_NCRBUTTONDOWN) ||
00360             (winMsg->message == WINWM_NCMBUTTONDOWN))
00361         {
00362             if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message && 
00363                winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
00364                (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
00365                (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2)) 
00366             {
00367                  dprintf(("single -> double click"));
00368                  if(winMsg->message >= WINWM_LBUTTONDOWN) {
00369                       winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
00370                  }
00371                  else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
00372                  doubleClickMsg.message = 0;
00373             }
00374             else {
00375                  dprintf(("save for double click"));
00376                  doubleClickMsg = *winMsg;
00377                  if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
00378                       doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
00379                  }
00380             }
00381         }
00382         EnableLogging();
00383 
00384         break;
00385     }
00386 
00387     case WM_BUTTON2CLICK:
00388     case WM_BUTTON1CLICK:
00389     case WM_BUTTON3CLICK:
00390         goto dummymessage;
00391 
00392     case WM_BUTTON2MOTIONSTART:
00393     case WM_BUTTON2MOTIONEND:
00394     case WM_BUTTON1MOTIONSTART:
00395     case WM_BUTTON1MOTIONEND:
00396     case WM_BUTTON3MOTIONSTART:
00397     case WM_BUTTON3MOTIONEND:
00398         //no break; translate to WM_MOUSEMOVE
00399         //Some applications (e.g. Unreal) retrieve all mouse messages
00400         //when a mouse button is pressed and don't expect WM_NULL
00401 
00402     case WM_MOUSEMOVE:
00403     {
00404         //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
00405 
00406         HWND hwnd;
00407 
00408         dprintf2(("WM_NCMOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
00409         DisableLogging();
00410         if(GetCapture() != winMsg->hwnd)
00411         {
00412             hwnd = WindowFromPoint(winMsg->pt);
00413             if(win32wnd->getWindowHandle() != hwnd) {
00414                 RELEASE_WNDOBJ(win32wnd);
00415                 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00416                 if(win32wnd == NULL) {
00417                     DebugInt3();
00418                     EnableLogging();
00419                     goto dummymessage;
00420                 }
00421                 winMsg->hwnd = hwnd;
00422             }
00423         }
00424 
00425         //if a window is disabled, it's parent receives the mouse messages
00426         if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
00427             if(win32wnd->getParent()) {
00428                 Win32BaseWindow *parent = win32wnd->getParent();;
00429                 if(parent) parent->addRef();
00430                 RELEASE_WNDOBJ(win32wnd);
00431                 win32wnd = parent;
00432             }
00433             fWasDisabled = TRUE;
00434         }
00435         if(IsNCMouseMsg(win32wnd))
00436         {
00437             winMsg->message = WINWM_NCMOUSEMOVE;
00438             winMsg->wParam  = (WPARAM)win32wnd->getLastHitTestVal();
00439             winMsg->lParam  = MAKELONG(winMsg->pt.x,winMsg->pt.y);
00440         }
00441         else
00442         {
00443             ClientPoint.x = winMsg->pt.x;
00444             ClientPoint.y = winMsg->pt.y;
00445             MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
00446 
00447             winMsg->message = WINWM_MOUSEMOVE;
00448             winMsg->wParam  = GetMouseKeyState();
00449             winMsg->lParam  = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
00450         }
00451         EnableLogging();
00452         if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
00453         {
00454             if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
00455                 goto dummymessage; //dinput swallowed message
00456             }
00457         }
00458         if(fWasDisabled) {
00459                 if(win32wnd) {
00460                     winMsg->hwnd = win32wnd->getWindowHandle();
00461                 }
00462                 else {
00463                     goto dummymessage; //don't send mouse messages to disabled windows
00464                 }
00465         }
00466         //OS/2 Window coordinates -> Win32 Window coordinates
00467         break;
00468     }
00469 
00470     case WM_CONTROL:
00471       goto dummymessage;
00472 
00473     case WM_COMMAND:
00474         if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
00475             winMsg->message = WINWM_COMMAND;
00476             winMsg->wParam  = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
00477             break;
00478         }
00479         //todo controls
00480         goto dummymessage;
00481 
00482     case WM_SYSCOMMAND:
00483     {
00484       ULONG x = 0, y = 0;
00485       ULONG win32sc;
00486 
00487         if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
00488             POINTL pointl;
00489             WinQueryPointerPos(HWND_DESKTOP, &pointl);
00490             x = pointl.x;
00491             y = mapScreenY(y);
00492         }
00493         switch(SHORT1FROMMP(os2Msg->mp1)) {
00494         case SC_MOVE:
00495             win32sc = SC_MOVE_W;
00496             break;
00497         case SC_CLOSE:
00498         {
00499             //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
00500             //TRUE  -> user clicked on close button -> close window
00501             if(SHORT2FROMMP(os2Msg->mp2) == FALSE) 
00502             {
00503                 HWND hwnd = win32wnd->GetTopParent();
00504                 if(win32wnd->getWindowHandle() != hwnd) {
00505                     RELEASE_WNDOBJ(win32wnd);
00506                     win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00507                     if(win32wnd == NULL) {
00508                         DebugInt3();
00509                         goto dummymessage;
00510                     }
00511                     winMsg->hwnd = hwnd;
00512                 }
00513             }
00514             win32sc = SC_CLOSE_W;
00515             break;
00516         }
00517         case SC_MAXIMIZE:
00518             win32sc = SC_MAXIMIZE_W;
00519             break;
00520         case SC_MINIMIZE:
00521             win32sc = SC_MINIMIZE_W;
00522             break;
00523         case SC_NEXTFRAME:
00524         case SC_NEXTWINDOW:
00525             win32sc = SC_NEXTWINDOW_W;
00526             break;
00527         case SC_RESTORE:
00528             win32sc = SC_RESTORE_W;
00529             break;
00530         case SC_TASKMANAGER:
00531             win32sc = SC_TASKLIST_W;
00532             break;
00533         default:
00534             dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
00535             goto dummymessage;
00536         }
00537         winMsg->message= WINWM_SYSCOMMAND;
00538         winMsg->wParam = (WPARAM)win32sc;
00539         winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
00540         break;
00541     }
00542       
00543     case WM_CHAR_SPECIAL:
00544     {
00545         // @@@PH
00546         // special char message from the keyboard hook
00547         dprintf(("PM: WM_CHAR_SPECIAL\n"));
00548         
00549       // NO BREAK! FALLTHRU CASE!
00550     }
00551       
00552     case WM_CHAR:
00553     {
00554       ULONG  repeatCount=0;
00555       ULONG  virtualKey=0;
00556       ULONG  keyFlags=0;
00557       USHORT scanCode=0;
00558       ULONG  flags = SHORT1FROMMP(os2Msg->mp1);
00559       BOOL   keyWasPressed;
00560       char   c;
00561       USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
00562 
00563         teb->o.odin.fTranslated = FALSE;
00564         repeatCount = CHAR3FROMMP(os2Msg->mp1);
00565         scanCode = CHAR4FROMMP(os2Msg->mp1);
00566         keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
00567 
00568         dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode));
00569         dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
00570 
00571         BOOL  fWinExtended;
00572         BYTE  bWinVKey;
00573         WORD  wWinScan;
00574 
00575         // Note: Numlock-state currently ignored, see below
00576         KeyTranslatePMScanToWinVKey(usPMScanCode,
00577                                     FALSE, 
00578                                     &bWinVKey,
00579                                     &wWinScan,
00580                                     &fWinExtended);
00581         winMsg->wParam = bWinVKey;
00582         winMsg->lParam  = repeatCount & 0x0FFFF;                 // bit 0-15, repeatcount
00583         winMsg->lParam |= (wWinScan & 0x1FF) << 16;  // bit 16-23, scancode + bit 15 extended
00584       
00585         // Set the extended bit when appropriate
00586         if (fWinExtended)
00587             winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
00588 
00589 #if 0
00590 //TODO
00591         // Adjust VKEY value for pad digits if NumLock is on
00592         if ((scanCode >= 0x47) && (scanCode <= 0x53) &&
00593             (virtualKey >= 0x30) && (virtualKey >= 39))
00594             winMsg->wParam = virtualKey + 0x30;
00595 #endif
00596 
00597 #ifdef ALTGR_HACK
00598      
00599         if (usPMScanCode == PMSCAN_ALTRIGHT)
00600         {
00601           // Turn message into CTRL-event
00602           // The original PM message is still saved inside
00603           // the TEB, the next call to TranslateMessage()
00604           // will then generate the required additional message
00605           // for the ALTGR-event.
00606           winMsg->wParam = VK_LCONTROL_W;
00607           winMsg->lParam = repeatCount & 0x0FFFF;
00608           winMsg->lParam |= WINSCAN_CTRLLEFT << 16
00609                             |  WIN_KEY_DONTCARE;
00610           
00611           if (flags & KC_KEYUP)
00612           {
00613             winMsg->message = WINWM_SYSKEYUP;
00614             winMsg->lParam |= WIN_KEY_ALTHELD;                      // bit 29, alt was pressed
00615             winMsg->lParam |= WIN_KEY_PREVSTATE;                    // bit 30, previous state, always 1 for a WM_KEYUP message
00616             winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP
00617             
00618             // Note: altgr affects the alt-key state in windows!
00619             // The overlay causes GetKeyState/GetAsyncKeyState to return
00620             // the correct states
00621             KeySetOverlayKeyState(VK_LCONTROL_W, KEYOVERLAYSTATE_DONTCARE);
00622             KeySetOverlayKeyState(VK_CONTROL_W, KEYOVERLAYSTATE_DONTCARE);
00623           }
00624           else
00625           {
00626             winMsg->lParam |= WIN_KEY_ALTHELD;
00627             if (keyWasPressed)
00628               winMsg->lParam |= WIN_KEY_PREVSTATE;     // bit 30, previous state, 1 means key was pressed
00629             winMsg->message = WINWM_KEYDOWN;
00630             
00631             // Note: altgr affects the alt-key state in windows!
00632             // The overlay causes GetKeyState/GetAsyncKeyState to return
00633             // the correct states
00634             KeySetOverlayKeyState(VK_LCONTROL_W, KEYOVERLAYSTATE_DOWN);
00635             KeySetOverlayKeyState(VK_CONTROL_W, KEYOVERLAYSTATE_DOWN);
00636             KeySetOverlayKeyState(VK_RMENU_W, KEYOVERLAYSTATE_DOWN);
00637             KeySetOverlayKeyState(VK_MENU_W, KEYOVERLAYSTATE_DOWN);
00638             
00639             // Note: when CTRL comes up, windows keeps ALTGR still down!
00640             // KeySetOverlayKeyState(VK_RMENU_W, KEYOVERLAYSTATE_DOWN);
00641           }
00642         }     
00643 #endif
00644       
00645         if (!(flags & KC_ALT))
00646         {
00647           //
00648           // the Alt key is not pressed
00649           // or no more pressed
00650           //
00651           if (flags & KC_KEYUP)
00652           {
00653             // check for a lonesome ALT key ...
00654             if ( (flags & KC_LONEKEY) &&
00655                 (winMsg->wParam == VK_LMENU_W) )
00656             {
00657               winMsg->message = WINWM_SYSKEYUP;
00658               
00659               // held ALT-key when current key is released
00660               // generates additional flag 0x2000000
00661               // Note: PM seems to do this differently, 
00662               // KC_ALT is already reset
00663             }
00664             else
00665             {
00666               // send WM_KEYUP message
00667               winMsg->message = WINWM_KEYUP;
00668             }
00669             
00670             winMsg->lParam |= WIN_KEY_PREVSTATE;                    // bit 30, previous state, always 1 for a WM_KEYUP message
00671             winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP
00672           }
00673           else 
00674           {
00675             // send WM_KEYDOWN message
00676             winMsg->message = WINWM_KEYDOWN;
00677             if (keyWasPressed)
00678               winMsg->lParam |= WIN_KEY_PREVSTATE;                  // bit 30, previous state, 1 means key was pressed
00679           }
00680         }
00681         else 
00682         {
00683           //
00684           // the Alt key is pressed
00685           //
00686           if (flags & KC_KEYUP)
00687           {
00688             // send WM_SYSKEYUP message
00689             winMsg->message = WINWM_SYSKEYUP;
00690             winMsg->lParam |= WIN_KEY_PREVSTATE;                    // bit 30, previous state, always 1 for a WM_KEYUP message
00691             winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP
00692           }
00693           else 
00694           {
00695             // send WM_SYSKEYDOWN message
00696             winMsg->message = WINWM_SYSKEYDOWN;
00697             if (keyWasPressed)
00698               winMsg->lParam |= WIN_KEY_PREVSTATE;                  // bit 30, previous state, 1 means key was pressed
00699 
00700             // pressed ALT-key generates additional flag 0x2000000
00701             // if the current window has keyboard focus
00702             winMsg->lParam |= WIN_KEY_ALTHELD;
00703           }
00704         }
00705 
00706         if (ISKDB_CAPTURED())
00707         {
00708             if (DInputKeyBoardHandler(winMsg)) {
00709                 goto dummymessage; //dinput swallowed message
00710             }
00711         }
00712 
00713 #ifdef ALTGR_HACK
00714         // it's a PMSCAN_ALTRIGHT WM_CHAR message?
00715         // and not previously translated?
00716         if(fMsgRemoved && usPMScanCode == PMSCAN_ALTRIGHT && !(teb->o.odin.fTranslated))
00717         {
00718             dprintf(("Queue ALTRIGHT message"));
00719             // special ALTRIGHT treatment:
00720             // we try to insert another WM_KEYDOWN or WM_KEYUP instead of
00721             // the usual WM_CHAR which is expected here.
00722             // -> experimental
00723             // it's really an OS/2-style WM_CHAR message?
00724             MSG extramsg;
00725             memcpy(&extramsg, winMsg, sizeof(MSG));
00726     
00727             // AltGr is not released with WINWM_SYSKEYUP, but WINWM_KEYUP
00728             if(flags & KC_KEYUP)
00729             {
00730                 extramsg.message = WINWM_KEYUP;
00731             }
00732             extramsg.wParam = VK_RMENU_W;
00733     
00734             // mask out message bits and scan code
00735             extramsg.lParam &= (0xDC00FFFF);
00736             extramsg.lParam |= (WINSCAN_ALTRIGHT & 0x1FF) << 16;
00737 ////            extramsg.lParam |= WIN_KEY_EXTENDED;
00738             if (!(flags & KC_KEYUP))
00739                 extramsg.lParam |= WIN_KEY_ALTHELD;
00740   
00741             // insert message into the queue
00742             setThreadQueueExtraCharMessage(teb, &extramsg);
00743         }
00744 #endif
00745         break;
00746     }
00747 
00748     case WM_TIMER:
00749 //Why was this check here????
00750 //        if (os2Msg->mp2)
00751 //        {
00752           BOOL sys;
00753           ULONG id;
00754 
00755           if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id))
00756           {
00757                 winMsg->wParam = (WPARAM)id;
00758                 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
00759                 break;
00760           }
00761 //        }
00762         goto dummymessage; //for caret blinking
00763 
00764     case WM_SETWINDOWPARAMS:
00765     {
00766       WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
00767 
00768         if(wndParams->fsStatus & WPM_TEXT) {
00769             winMsg->message = WINWM_SETTEXT;
00770             winMsg->lParam  = (LPARAM)wndParams->pszText;
00771             break;
00772         }
00773         goto dummymessage;
00774     }
00775 
00776 #if 0
00777     case WM_QUERYWINDOWPARAMS:
00778     {
00779      PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
00780      ULONG textlen;
00781      PSZ   wintext;
00782 
00783         if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
00784         {
00785             if(wndpars->fsStatus & WPM_CCHTEXT)
00786                 wndpars->cchText = win32wnd->MsgGetTextLength();
00787             if(wndpars->fsStatus & WPM_TEXT)
00788                 wndpars->pszText = win32wnd->MsgGetText();
00789 
00790             wndpars->fsStatus = 0;
00791             wndpars->cbCtlData = 0;
00792             wndpars->cbPresParams = 0;
00793             goto dummymessage;
00794       }
00795     }
00796 #endif
00797 
00798     case WM_PAINT:
00799     {
00800         if(win32wnd->IsWindowIconic()) {
00801                 winMsg->message = WINWM_PAINTICON;
00802         }
00803         else    winMsg->message = WINWM_PAINT;
00804         break;
00805     }
00806 
00807     case WM_CONTEXTMENU:
00808         winMsg->message = WINWM_CONTEXTMENU;
00809         winMsg->wParam  = win32wnd->getWindowHandle();
00810         winMsg->lParam  = MAKELONG(winMsg->pt.x,winMsg->pt.y);
00811         break;
00812 
00813     case WM_RENDERFMT:
00814         winMsg->message = WINWM_RENDERFORMAT;
00815         winMsg->wParam  = (UINT) os2Msg->mp1;
00816         break;
00817 
00818     case WM_RENDERALLFMTS:
00819         winMsg->message = WINWM_RENDERALLFORMATS;
00820         break;
00821 
00822     case WM_DESTROYCLIPBOARD:
00823         winMsg->message = WINWM_DESTROYCLIPBOARD;
00824         break;
00825 
00826     case WM_HSCROLL:
00827     case WM_VSCROLL:
00828         winMsg->message = (os2Msg->msg == WM_HSCROLL) ? WINWM_HSCROLL : WINWM_VSCROLL;
00829         winMsg->lParam  = 0;
00830         winMsg->wParam  = 0;
00831         switch(SHORT2FROMMP(os2Msg->mp2)) {
00832         case SB_LINERIGHT:
00833             winMsg->wParam = SB_LINERIGHT_W;
00834             break;
00835         case SB_LINELEFT:
00836             winMsg->wParam = SB_LINELEFT_W;
00837             break;
00838         case SB_PAGELEFT:
00839             winMsg->wParam = SB_PAGELEFT_W;
00840             break;
00841         case SB_PAGERIGHT:
00842             winMsg->wParam = SB_PAGERIGHT_W;
00843             break;
00844         default:
00845             dprintf(("Unsupported WM_H/VSCROLL message %x!!", SHORT2FROMMP(os2Msg->mp2)));
00846             goto dummymessage;
00847         }
00848         break;
00849 
00850     case WM_INITMENU:
00851     case WM_MENUSELECT:
00852     case WM_MENUEND:
00853     case WM_NEXTMENU:
00854     case WM_SYSCOLORCHANGE:
00855     case WM_SYSVALUECHANGED:
00856     case WM_SETSELECTION:
00857     case WM_PPAINT:
00858     case WM_PSETFOCUS:
00859     case WM_PSYSCOLORCHANGE:
00860     case WM_PSIZE:
00861     case WM_PACTIVATE:
00862     case WM_PCONTROL:
00863     case WM_HELP:
00864     case WM_APPTERMINATENOTIFY:
00865     case WM_PRESPARAMCHANGED:
00866     case WM_DRAWITEM:
00867     case WM_MEASUREITEM:
00868     case WM_CONTROLPOINTER:
00869     case WM_QUERYDLGCODE:
00870     case WM_SUBSTITUTESTRING:
00871     case WM_MATCHMNEMONIC:
00872     case WM_SAVEAPPLICATION:
00873     case WM_SEMANTICEVENT:
00874     default:
00875 dummymessage:
00876         dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
00877         winMsg->message = 0;
00878         winMsg->wParam  = 0;
00879         winMsg->lParam  = 0;
00880         if(win32wnd) RELEASE_WNDOBJ(win32wnd);
00881         return FALSE;
00882     }
00883     if(win32wnd) RELEASE_WNDOBJ(win32wnd);
00884     return TRUE;
00885 }
00886 //******************************************************************************
00887 //******************************************************************************
00888 BOOL OSLibWinTranslateMessage(MSG *msg)
00889 {
00890   TEB *teb;
00891   MSG extramsg;
00892 
00893   teb = GetThreadTEB();
00894   if(!teb)
00895     return FALSE;
00896 
00897   UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
00898   ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
00899  
00900   
00901     //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
00902     //      the newly generated WM_CHAR message.
00903     if(!teb->o.odin.fTranslated &&
00904        teb->o.odin.os2msg.msg == WM_CHAR && 
00905        !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
00906     {
00907       //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
00908       memcpy(&extramsg, msg, sizeof(MSG));
00909       extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
00910       extramsg.lParam = 0;
00911 
00912       // ESCAPE generates a WM_CHAR under windows, so take
00913       // special care for this here.
00914       switch (ucPMScanCode)
00915       {
00916         case PMSCAN_ESC:
00917           extramsg.wParam  = VK_ESCAPE_W;
00918           fl |= KC_CHAR;
00919         break;
00920       }
00921 
00922       if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN) 
00923       {
00924         return FALSE;
00925       }
00926 
00927       if(fl & KC_VIRTUALKEY)
00928       {
00929         if(msg->wParam)
00930         {
00931           if ((msg->wParam >= VK_NUMPAD0_W) && 
00932               (msg->wParam <= VK_NUMPAD9_W))
00933             extramsg.wParam = msg->wParam - 0x30;
00934           else
00935             extramsg.wParam = msg->wParam;
00936         }
00937         else    
00938           extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
00939       }
00940 
00941 
00942       if(msg->message >= WINWM_SYSKEYDOWN) 
00943         extramsg.message = WINWM_SYSCHAR;
00944       else    
00945         extramsg.message = WINWM_CHAR;
00946 
00947       if(fl & KC_DEADKEY)
00948         extramsg.message++;  //WM_DEADCHAR/WM_SYSDEADCHAR
00949 
00950 
00951       extramsg.lParam = msg->lParam & 0x00FFFFFF;
00952       if(fl & KC_ALT)
00953         extramsg.lParam |= WIN_KEY_ALTHELD;
00954       if(fl & KC_PREVDOWN)
00955         extramsg.lParam |= WIN_KEY_PREVSTATE;
00956       if(fl & KC_KEYUP)
00957         extramsg.lParam |= (1<<31);
00958 
00959       // insert message into the queue
00960       setThreadQueueExtraCharMessage(teb, &extramsg);
00961       return TRUE;
00962     }
00963     return FALSE;
00964 }
00965 //******************************************************************************
00966 //******************************************************************************
00967 

Generated on Wed Jan 23 23:17:39 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001