source: trunk/src/user32/pmwindow.cpp@ 21347

Last change on this file since 21347 was 21347, checked in by vladest, 16 years ago
  1. Remove setting up Windows codepage for ODIN PM session. This is incorrect. Fixed umlaut problem
  2. Textinput improves. Attempt to add deadchars support
File size: 93.7 KB
Line 
1/* $Id: pmwindow.cpp,v 1.230 2004-05-24 09:01:59 sandervl Exp $ */
2/*
3 * Win32 Window Managment Code for OS/2
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_WIN
13#define INCL_GPI
14#define INCL_DEV /* Device Function definitions */
15#define INCL_GPICONTROL /* GPI control Functions */
16#define INCL_DOSPROCESS
17#define INCL_DOSMODULEMGR
18#define INCL_DOSDEVICES
19#define INCL_DOSDEVIOCTL
20#define INCL_WINTRACKRECT
21#define INCL_BASE
22
23#include <os2wrap.h>
24#include <odinwrap.h>
25#include <stdlib.h>
26#include <string.h>
27#include <win32type.h>
28#include <win32api.h>
29#include <winconst.h>
30#include <winuser32.h>
31#include <wprocess.h>
32#include <dbglog.h>
33#include <win32wbase.h>
34#include <win32wfake.h>
35#include <win32dlg.h>
36#include "win32wdesktop.h"
37#include "pmwindow.h"
38#include "oslibwin.h"
39#include "oslibutil.h"
40#include "oslibgdi.h"
41#include "oslibmsg.h"
42#define INCLUDED_BY_DC
43#include "dc.h"
44#include <thread.h>
45#include <wprocess.h>
46#include <objhandle.h>
47#include "caret.h"
48#include "timer.h"
49#include <codepage.h>
50#include "syscolor.h"
51#include "options.h"
52#include "menu.h"
53#include <pmkbdhk.h>
54#include <pmscan.h>
55#include <winscan.h>
56#include <oslibdnd.h>
57#include <custombuild.h>
58#include <win\dbt.h>
59#include "dragdrop.h"
60#include "menu.h"
61#include "user32api.h"
62#include <kbdhook.h>
63#include <heapstring.h>
64
65#include <os2im.h>
66#include <im32.h>
67
68#define DBG_LOCALLOG DBG_pmwindow
69#include "dbglocal.h"
70
71
72// Notification that focus change has completed (UNDOCUMENTED)
73#define WM_FOCUSCHANGED 0x000e
74
75//define this to use the new code for WM_CALCVALIDRECT handling
76//#define USE_CALCVALIDRECT
77
78HMQ hmq = 0; /* Message queue handle */
79HAB hab = 0;
80RECTL desktopRectl = {0};
81ULONG ScreenWidth = 0;
82ULONG ScreenHeight = 0;
83ULONG ScreenBitsPerPel = 0;
84BOOL fOS2Look = FALSE;
85BOOL fForceMonoCursor = FALSE;
86BOOL fDragDropActive = FALSE;
87BOOL fDragDropDisabled = FALSE;
88
89const char WIN32_CDCLASS[] = ODIN_WIN32_CDCLASS;
90 char WIN32_STDCLASS[255] = ODIN_WIN32_STDCLASS;
91
92#define PMMENU_MINBUTTON 0
93#define PMMENU_MAXBUTTON 1
94#define PMMENU_RESTOREBUTTON 2
95#define PMMENU_CLOSEBUTTON 3
96#define PMMENU_MINBUTTONDOWN 4
97#define PMMENU_MAXBUTTONDOWN 5
98#define PMMENU_RESTOREBUTTONDOWN 6
99#define PMMENU_CLOSEBUTTONDOWN 7
100
101HBITMAP hbmFrameMenu[8] = {0};
102
103//Win32 bitmap handles of the OS/2 min, max and restore buttons
104HBITMAP hBmpMinButton = 0;
105HBITMAP hBmpMaxButton = 0;
106HBITMAP hBmpRestoreButton = 0;
107HBITMAP hBmpCloseButton = 0;
108HBITMAP hBmpMinButtonDown = 0;
109HBITMAP hBmpMaxButtonDown = 0;
110HBITMAP hBmpRestoreButtonDown = 0;
111HBITMAP hBmpCloseButtonDown = 0;
112
113 PFNWP pfnFrameWndProc = NULL;
114static HWND hwndFocusChange = 0;
115 HWND hwndCD = 0;
116
117// this holds the font height that the display driver returns using DevQueryCaps
118// 13 would be small fonts, 16 medium fonts and 20 large fonts
119LONG CapsCharHeight = 0;
120
121// Note:
122// For a "lonekey"-press of AltGr, we only receive WM_KEYUP
123// messages. If the key is pressed longer and starts to repeat,
124// WM_KEYDOWN messages come in properly.
125static BOOL fKeyAltGrDown = FALSE;
126static BOOL fEnableCDPolling = FALSE;
127
128static char *PMDragExtractFiles(PDRAGINFO pDragInfo, ULONG *pcItems, ULONG *pulBytes);
129static BOOL PMDragValidate(PDRAGINFO pDragInfo);
130static void QueryPMMenuBitmaps();
131
132MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
133MRESULT EXPENTRY Win32CDWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
134MRESULT EXPENTRY Win32FrameWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
135void FrameReplaceMenuItem(HWND hwndMenu, ULONG nIndex, ULONG idOld, ULONG idNew,
136 HBITMAP hbmNew);
137void FrameSetFocus(HWND hwnd);
138
139VOID APIENTRY DspInitSystemDriverName(PSZ pszDriverName, ULONG lenDriverName);
140
141#ifdef DEBUG_LOGGING
142static char *DbgGetStringSWPFlags(ULONG flags);
143static char *DbgPrintQFCFlags(ULONG flags);
144#endif
145
146extern "C" ULONG OSLibImSetMsgQueueProperty( ULONG, ULONG );
147
148//******************************************************************************
149// Initialize PM; create hab, message queue and register special Win32 window classes
150//
151// This is called from the initterm, so we call it only once for each process.
152// We make sure PM is up and running for our purposes and init the existing
153// thread 0.
154//******************************************************************************
155BOOL InitPM()
156{
157 hab = WinInitialize(0);
158 dprintf(("Winitialize returned %x", hab));
159 hmq = WinCreateMsgQueue(hab, 0);
160
161 if(!hab || !hmq)
162 {
163 UINT error;
164 //CB: only fail on real error
165 error = WinGetLastError(hab) & 0xFFFF; //error code
166 if (!hab || (error != PMERR_MSG_QUEUE_ALREADY_EXISTS))
167 {
168 dprintf(("WinInitialize or WinCreateMsgQueue failed %x %x", hab, hmq));
169 dprintf((" Error = %x",error));
170 if(error == PMERR_NOT_IN_A_PM_SESSION) return TRUE;
171
172 return(FALSE);
173 }
174 else
175 {
176 if(!hab) {
177 hab = WinQueryAnchorBlock(HWND_DESKTOP);
178 dprintf(("WinQueryAnchorBlock returned %x", hab));
179 }
180 if(!hmq) {
181 PTIB ptib;
182 PPIB ppib;
183
184 DosGetInfoBlocks(&ptib, &ppib);
185
186 hmq = WinQueueFromID(hab, ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
187 }
188 }
189 }
190
191 // store our HAB and HMQ in the TEB - we need it quite often
192 // and they don't map 1:1 to Windows entities
193 SetThreadHAB(hab);
194 dprintf(("InitPM: hmq = %x", hmq));
195 SetThreadMessageQueue(hmq);
196
197 //initialize keyboard hook for first thread
198 hookInit(hab);
199
200 //BOOL rc = WinSetCp(hmq, GetDisplayCodepage());
201 //dprintf(("InitPM: WinSetCP was %s OK", rc ? " " : "not "));
202
203 /* IM instace is created per message queue, that is, thread */
204 if( IsDBCSEnv())
205 OSLibImSetMsgQueueProperty( hmq, MQP_INSTANCE_PERMQ );
206
207 //CD polling window class
208 if(!WinRegisterClass( /* Register window class */
209 hab, /* Anchor block handle */
210 (PSZ)WIN32_CDCLASS, /* Window class name */
211 (PFNWP)Win32CDWindowProc, /* Address of window procedure */
212 0,
213 0))
214 {
215 dprintf(("WinRegisterClass Win32BaseWindow failed"));
216 return(FALSE);
217 }
218
219 //Standard Odin window class
220 if(!WinRegisterClass( /* Register window class */
221 hab, /* Anchor block handle */
222 (PSZ)WIN32_STDCLASS, /* Window class name */
223 (PFNWP)Win32WindowProc, /* Address of window procedure */
224 0,
225 NROF_WIN32WNDBYTES))
226 {
227 dprintf(("WinRegisterClass Win32BaseWindow failed"));
228 return(FALSE);
229 }
230
231 //We no longer register our own frame window class as there is code in PM
232 //that makes assumptions about frame window class names.
233 //Instead we subclass the frame window right after creating it.
234 CLASSINFO FrameClassInfo;
235 if(!WinQueryClassInfo (hab, WC_FRAME, &FrameClassInfo)) {
236 dprintf (("WinQueryClassInfo WC_FRAME failed"));
237 return (FALSE);
238 }
239 pfnFrameWndProc = FrameClassInfo.pfnWindowProc;
240
241 dprintf(("WC_FRAME style %x", FrameClassInfo.flClassStyle));
242
243 // get the screen dimensions and store them
244 WinQueryWindowRect(HWND_DESKTOP, &desktopRectl);
245 ScreenWidth = desktopRectl.xRight;
246 ScreenHeight = desktopRectl.yTop;
247
248 HDC hdc; /* Device-context handle */
249 /* context data structure */
250 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL,
251 NULL, NULL, NULL};
252
253 /* create memory device context - it's temporary to query some information */
254 hdc = DevOpenDC(hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
255
256 // check if we have the OS/2 Look and Feel enabled
257 fOS2Look = PROFILE_GetOdinIniBool(ODINSYSTEM_SECTION, "OS2Look", TRUE);
258 if(fOS2Look)
259 {
260 SYSCOLOR_Init(FALSE); //use OS/2 colors
261 QueryPMMenuBitmaps();
262 }
263
264 // find out which colordepth we're running
265 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, (PLONG)&ScreenBitsPerPel);
266
267 // query the font height to find out whether we have small or large fonts
268 DevQueryCaps(hdc, CAPS_GRAPHICS_CHAR_HEIGHT, 1, (PLONG)&CapsCharHeight);
269 dprintf(("CAPS_GRAPHICS_CHAR_HEIGHT = %d", CapsCharHeight));
270 if(CapsCharHeight > 16) {
271 CapsCharHeight = 16;
272 }
273
274#ifdef DEBUG
275 ULONG temp;
276 DevQueryCaps(hdc, CAPS_GRAPHICS_CHAR_WIDTH, 1, (PLONG)&temp);
277 dprintf(("CAPS_GRAPHICS_CHAR_WIDTH = %d", temp));
278 DevQueryCaps(hdc, CAPS_CHAR_HEIGHT, 1, (PLONG)&temp);
279 dprintf(("CAPS_CHAR_HEIGTH = %d", temp));
280 DevQueryCaps(hdc, CAPS_CHAR_WIDTH, 1, (PLONG)&temp);
281 dprintf(("CAPS_CHAR_WIDTH = %d", temp));
282 DevQueryCaps(hdc, CAPS_SMALL_CHAR_HEIGHT, 1, (PLONG)&temp);
283 dprintf(("CAPS_SMALL_CHAR_HEIGTH = %d", temp));
284 DevQueryCaps(hdc, CAPS_SMALL_CHAR_WIDTH, 1, (PLONG)&temp);
285 dprintf(("CAPS_SMALL_CHAR_WIDTH = %d", temp));
286 DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES, 1,(PLONG)&temp);
287 dprintf(("CAPS_VERTICAL_FONT_RES = %d", temp));
288 DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1,(PLONG)&temp);
289 dprintf(("CAPS_HORIZONTAL_FONT_RES = %d", temp));
290#endif
291
292 DevCloseDC(hdc);
293
294 dprintf(("InitPM: Desktop (%d,%d) bpp %d font size %d", ScreenWidth, ScreenHeight, ScreenBitsPerPel, CapsCharHeight));
295 return TRUE;
296} /* End of main */
297//******************************************************************************
298HBITMAP OPEN32API _O32_CreateBitmapFromPMHandle(HBITMAP hPMBitmap);
299
300inline HBITMAP O32_CreateBitmapFromPMHandle(HBITMAP hPMBitmap)
301{
302 HBITMAP yyrc;
303 USHORT sel = RestoreOS2FS();
304
305 yyrc = _O32_CreateBitmapFromPMHandle(hPMBitmap);
306 SetFS(sel);
307
308 return yyrc;
309}
310//******************************************************************************
311static void QueryPMMenuBitmaps()
312{
313 CHAR szDisplay[30];
314 HMODULE hModDisplay;
315
316 if(hbmFrameMenu[0] == 0)
317 {
318 CHAR szDisplay[30];
319 HMODULE hModDisplay;
320 HDC hdc; /* Device-context handle */
321 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL,
322 NULL, NULL, NULL};
323
324 /* create memory device context */
325 hdc = DevOpenDC(hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
326
327 DspInitSystemDriverName(szDisplay, sizeof(szDisplay));
328 DosQueryModuleHandle(szDisplay, &hModDisplay);
329
330 hbmFrameMenu[PMMENU_MINBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MINBUTTON, 0, 0);
331 hbmFrameMenu[PMMENU_MINBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MINBUTTONDEP, 0, 0);
332 hbmFrameMenu[PMMENU_MAXBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MAXBUTTON, 0, 0);
333 hbmFrameMenu[PMMENU_MAXBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MAXBUTTONDEP, 0, 0);
334 hbmFrameMenu[PMMENU_RESTOREBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_RESTOREBUTTON, 0, 0);
335 hbmFrameMenu[PMMENU_RESTOREBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_RESTOREBUTTONDEP, 0, 0);
336 hbmFrameMenu[PMMENU_CLOSEBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_CLOSE, 0, 0);
337 hbmFrameMenu[PMMENU_CLOSEBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_CLOSEDEP, 0, 0);
338
339 //Create win32 bitmap handles of the OS/2 min, max and restore buttons
340 hBmpMinButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MINBUTTON]);
341 ObjSetHandleFlag(hBmpMinButton, OBJHANDLE_FLAG_NODELETE, 1);
342 hBmpMinButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MINBUTTONDOWN]);
343 ObjSetHandleFlag(hBmpMinButtonDown, OBJHANDLE_FLAG_NODELETE, 1);
344 hBmpMaxButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MAXBUTTON]);
345 ObjSetHandleFlag(hBmpMaxButton, OBJHANDLE_FLAG_NODELETE, 1);
346 hBmpMaxButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MAXBUTTONDOWN]);
347 ObjSetHandleFlag(hBmpMaxButtonDown, OBJHANDLE_FLAG_NODELETE, 1);
348 hBmpRestoreButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_RESTOREBUTTON]);
349 ObjSetHandleFlag(hBmpRestoreButton, OBJHANDLE_FLAG_NODELETE, 1);
350 hBmpRestoreButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_RESTOREBUTTONDOWN]);
351 ObjSetHandleFlag(hBmpRestoreButtonDown, OBJHANDLE_FLAG_NODELETE, 1);
352 hBmpCloseButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_CLOSEBUTTON]);
353 ObjSetHandleFlag(hBmpCloseButton, OBJHANDLE_FLAG_NODELETE, 1);
354 hBmpCloseButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_CLOSEBUTTONDOWN]);
355 ObjSetHandleFlag(hBmpCloseButtonDown, OBJHANDLE_FLAG_NODELETE, 1);
356 DevCloseDC(hdc);
357 }
358}
359//******************************************************************************
360//******************************************************************************
361void WIN32API SetWindowAppearance(int fLooks)
362{
363 if(fLooks == OS2_APPEARANCE || fLooks == OS2_APPEARANCE_SYSMENU)
364 {
365 SYSCOLOR_Init(FALSE); //use OS/2 colors
366 QueryPMMenuBitmaps();
367 }
368 fOS2Look = fLooks;
369 MENU_Init();
370}
371//******************************************************************************
372//******************************************************************************
373void WIN32API CustForceMonoCursor()
374{
375 fForceMonoCursor = TRUE;
376}
377//******************************************************************************
378//******************************************************************************
379void WIN32API DisableDragDrop(BOOL fDisabled)
380{
381 fDragDropDisabled = fDisabled;
382}
383//******************************************************************************
384// Turn on CD Polling (window with 2 second timer to check CD disk presence)
385//
386// NOTE: This can cause PM hangs when executing a program for a very long time
387// (block in IOCtl)
388//******************************************************************************
389void WIN32API CustEnableCDPolling()
390{
391 fEnableCDPolling = TRUE;
392}
393//******************************************************************************
394//CD notification window class
395//******************************************************************************
396MRESULT EXPENTRY Win32CDWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
397{
398#pragma pack(1)
399 typedef struct
400 {
401 BYTE ucCommandInfo;
402 WORD usDriveUnit;
403 } ParameterBlock;
404#pragma pack()
405
406 MRESULT rc = 0;
407 static ULONG drives[26] = {0};
408 static int drivestatus[26] = {0};
409
410 switch( msg )
411 {
412 //OS/2 msgs
413 case WM_CREATE:
414 {
415 char drive[4];
416
417 //skip floppy drives
418 drive[0] = 'C';
419 drive[1] = ':';
420 drive[2] = '\0';
421
422 for(int i=2;i<26;i++) {
423 drives[i] = GetDriveTypeA(drive);
424 if(drives[i] == DRIVE_CDROM_W)
425 {
426 DWORD parsize = sizeof(ParameterBlock);
427 DWORD datasize = 2;
428 WORD status = 0;
429 DWORD rc;
430 ParameterBlock parm;
431
432 parm.ucCommandInfo = 0;
433 parm.usDriveUnit = i;
434 rc = DosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
435 &status, sizeof(status), &datasize);
436 if(rc != NO_ERROR) {
437 dprintf(("DosDevIOCtl failed with rc %d", rc));
438 drives[i] = 0;
439 continue;
440 }
441 //if no disk present, return FALSE
442 if(status & 4) {
443 drivestatus[i] = status & 4;
444 }
445 }
446 drive[0]++;
447 }
448 WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 32*60);
449//// WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 32*3);
450//// WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 5000);
451 rc = (MRESULT)FALSE;
452 break;
453 }
454 case WM_TIMER:
455 {
456 for(int i=0;i<26;i++)
457 {
458 //for now only cdrom/dvd drives
459 if(drives[i] == DRIVE_CDROM_W)
460 {
461 DWORD parsize = sizeof(ParameterBlock);
462 DWORD datasize = 2;
463 WORD status = 0;
464 DWORD rc;
465 ParameterBlock parm;
466
467 parm.ucCommandInfo = 0;
468 parm.usDriveUnit = i;
469 rc = DosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
470 &status, sizeof(status), &datasize);
471 if(rc != NO_ERROR) {
472 dprintf(("DosDevIOCtl failed with rc %d", rc));
473 return FALSE;
474 }
475 //Send WM_DEVICECHANGE message when CD status changes
476 if((status & 4) != drivestatus[i])
477 {
478 PID pidThis, pidTemp;
479 HENUM henum;
480 HWND hwndEnum;
481 DEV_BROADCAST_VOLUME volchange;
482
483 dprintf(("Disk status 0x%x", status));
484
485 volchange.dbcv_size = sizeof(volchange);
486 volchange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
487 volchange.dbcv_reserved = 0;
488 volchange.dbcv_unitmask = (1 << i);
489 volchange.dbcv_flags = DBTF_MEDIA;
490
491 WinQueryWindowProcess(hwnd, &pidThis, NULL);
492
493 //Iterate over all child windows of the desktop
494 henum = WinBeginEnumWindows(HWND_DESKTOP);
495
496 SetWin32TIB();
497 while(hwndEnum = WinGetNextWindow(henum))
498 {
499 WinQueryWindowProcess(hwndEnum, &pidTemp, NULL);
500 if(pidTemp == pidThis)
501 {
502 HWND hwndWin32 = OS2ToWin32Handle(hwndEnum);
503 if(hwndWin32) {
504 SendMessageA(hwndWin32,
505 WM_DEVICECHANGE_W,
506 (status & 4) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
507 (LPARAM)&volchange);
508 }
509 }
510 }
511 RestoreOS2TIB();
512 WinEndEnumWindows(henum);
513
514 drivestatus[i] = (status & 4);
515 }
516 }
517 }
518 break;
519 }
520
521 case WM_DESTROY:
522 dprintf(("WM_DESTROY for CD notification window"));
523 WinStopTimer(hab, hwnd, TIMERID_DRIVEPOLL);
524 break;
525
526 default:
527 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
528 }
529 return (MRESULT)rc;
530}
531//******************************************************************************
532// Win32 window message handler
533// The PM window procedure for our client window class (non frame)
534//******************************************************************************
535MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
536{
537 Win32BaseWindow *win32wnd;
538 TEB *teb;
539 MSG winMsg, *pWinMsg;
540 MRESULT rc = 0;
541 POSTMSG_PACKET *postmsg;
542 OSLIBPOINT point, ClientPoint;
543 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
544
545 ODIN_SetExceptionHandler(&exceptRegRec);
546 // restore our FS selector
547 SetWin32TIB();
548
549#ifdef DEBUG
550 dbg_ThreadPushCall("Win32WindowProc");
551#endif
552
553 // BEGIN NOTE-------------->>>>>> If this is changed, also change Win32FrameWindowProc!! <<<<<<<<<<<-------------------- BEGIN
554 teb = GetThreadTEB();
555 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
556
557//// dprintf(("window %x msg %x", (win32wnd) ? win32wnd->getWindowHandle() : 0, msg));
558
559 // do some sanity checking here:
560 // - we need to have a TEB handle
561 // - unless this is WM_CREATE (the very first message), there has to be
562 // a USER32 window object for this window handle
563 // - thread must not be suspended in WaitMessage
564 if(!teb || (msg != WM_CREATE && win32wnd == NULL) || teb->o.odin.fWaitMessageSuspend) {
565 if(teb && teb->o.odin.fWaitMessageSuspend)
566 dprintf(("OS2: fWaitMessageSuspend window %x msg %x -> run default frame proc", hwnd, msg));
567 else dprintf(("OS2: Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
568 goto RunDefWndProc;
569 }
570//// if(teb->o.odin.fIgnoreMsgs) {
571//// goto RunDefWndProc;
572//// }
573
574 // check if the message state counter in the TEB is odd
575 // This means the message has been sent directly from PM to our message
576 // handler (so it is the first time we know about this PM message).
577 // If this is the case, we have to translate it here to a Win32
578 // message first. The other case is that the message is the result of a
579 // WinDispatchMsg call and therefore has already been translated.
580 if((teb->o.odin.msgstate & 1) == 0)
581 {
582 // message that was sent directly to our window proc handler; translate it here
583 QMSG qmsg;
584
585 qmsg.msg = msg;
586 qmsg.hwnd = hwnd;
587 qmsg.mp1 = mp1;
588 qmsg.mp2 = mp2;
589 qmsg.time = WinQueryMsgTime(teb->o.odin.hab);
590 WinQueryMsgPos(teb->o.odin.hab, &qmsg.ptl);
591 qmsg.reserved = 0;
592
593 /* sometimes MSG_REMOVE here caused to double free of the message */
594 if(OS2ToWinMsgTranslate((PVOID)teb, &qmsg, &winMsg, FALSE, MSG_REMOVE) == FALSE)
595 {//message was not translated
596 memset(&winMsg, 0, sizeof(MSG));
597 }
598 pWinMsg = &winMsg;
599 }
600 else {
601 // message has already been translated before (GetMessage/PeekMessage).
602 // Use the translated information. Flip the translation flag.
603 pWinMsg = &teb->o.odin.msg;
604 teb->o.odin.msgstate++;
605 }
606 // END NOTE-------------->>>>>> If this is changed, also change Win32FrameWindowProc!! <<<<<<<<<<<-------------------- END
607
608 if(msg >= WIN32APP_POSTMSG) {
609 //probably win32 app user message
610 dprintf2(("Posted message %x->%x", msg, msg-WIN32APP_POSTMSG));
611 if((ULONG)mp1 == WIN32MSG_MAGICA) {
612 rc = (MRESULT)win32wnd->DispatchMsgA(pWinMsg);
613 }
614 else
615 if((ULONG)mp1 == WIN32MSG_MAGICW) {
616 rc = (MRESULT)win32wnd->DispatchMsgW(pWinMsg);
617 }
618 else {//broadcasted message
619 rc = (MRESULT)win32wnd->DispatchMsgA(pWinMsg);
620 }
621 RELEASE_WNDOBJ(win32wnd);
622 RestoreOS2TIB();
623 ODIN_UnsetExceptionHandler(&exceptRegRec);
624
625#ifdef DEBUG
626 dbg_ThreadPopCall();
627#endif
628 return rc;
629 }
630
631 switch( msg )
632 {
633 //OS/2 msgs
634 case WM_CREATE:
635 {
636 if(teb->o.odin.newWindow == 0)
637 goto createfail;
638
639 //Processing is done in after WinCreateWindow returns
640 dprintf(("OS2: WM_CREATE %x", hwnd));
641 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
642 win32wnd->addRef();
643 teb->o.odin.newWindow = 0;
644 if(win32wnd->MsgCreate(hwnd) == FALSE)
645 {
646 rc = (MRESULT)TRUE; //discontinue window creation
647 break;
648 }
649
650 //Create CD notification window
651 if(hwndCD == 0 && fEnableCDPolling) {
652 hwndCD = WinCreateWindow(HWND_DESKTOP, WIN32_CDCLASS,
653 NULL, 0, 0, 0, 0, 0,
654 HWND_DESKTOP, HWND_TOP, 0, NULL, NULL);
655 }
656
657 createfail:
658 rc = (MRESULT)FALSE;
659 break;
660 }
661
662 case WM_QUIT:
663 dprintf(("OS2: WM_QUIT %x", hwnd));
664 win32wnd->MsgQuit();
665 break;
666
667 case WM_CLOSE:
668 dprintf(("OS2: WM_CLOSE %x", hwnd));
669 win32wnd->MsgClose();
670 break;
671
672 case WM_DESTROY:
673 dprintf(("OS2: WM_DESTROY %x", hwnd));
674 win32wnd->MsgDestroy();
675 WinSetVisibleRegionNotify(hwnd, FALSE);
676 goto RunDefWndProc;
677
678 case WM_ENABLE:
679 dprintf(("OS2: WM_ENABLE %x", hwnd));
680 break;
681
682 case WM_SHOW:
683 {
684 dprintf(("OS2: WM_SHOW %x %d", hwnd, mp1));
685 win32wnd->MsgShow((ULONG)mp1);
686
687 //if a child window is hidden, then the update region of the
688 //parent changes and a WM_ERASEBKGND is required during the next
689 //BeginPaint call.
690 if((ULONG)mp1 == FALSE)
691 {
692 Win32BaseWindow *parent = win32wnd->getParent();
693 if(parent) {
694 dprintf(("PM Update region changed for parent %x", win32wnd->getWindowHandle()));
695 parent->SetPMUpdateRegionChanged(TRUE);
696 }
697 }
698 break;
699 }
700
701 case WM_ACTIVATE:
702 {
703 ULONG flags = WinQueryWindowULong(hwnd, OFFSET_WIN32FLAGS);
704
705 dprintf(("OS2: WM_ACTIVATE %x %x %x", hwnd, mp1, mp2));
706 WinSetWindowULong(hwnd, OFFSET_WIN32FLAGS, SHORT1FROMMP(mp1) ? (flags | WINDOWFLAG_ACTIVE):(flags & ~WINDOWFLAG_ACTIVE));
707 if(win32wnd->IsWindowCreated())
708 {
709 win32wnd->MsgActivate((LOWORD(pWinMsg->wParam) == WA_ACTIVE_W) ? 1 : 0, HIWORD(pWinMsg->wParam), pWinMsg->lParam, (HWND)mp2);
710 }
711 break;
712 }
713
714 case WM_SIZE:
715 {
716 dprintf(("OS2: WM_SIZE (%d,%d) (%d,%d)", SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), SHORT1FROMMP(mp1), SHORT2FROMMP(mp1)));
717 win32wnd->SetPMUpdateRegionChanged(TRUE);
718
719 goto RunDefWndProc;
720 }
721
722
723 case WM_VRNENABLED:
724 {
725 dprintf(("OS2: WM_VRNENABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
726 //Always call handler; even if mp1 is 0. If we don't do this, the
727 //DivX 4 player will never be allowed to draw after putting another window
728 //on top of it.
729
730 win32wnd->callVisibleRgnNotifyProc(TRUE);
731
732 //Workaround for PM/GPI bug when moving/sizing a window with open DCs
733 //
734 //Windows applictions often get a DC and keep it open for the duration
735 //of the application. When the DC's window is moved (full window dragging on)
736 //PM/GPI doesn't seem to update the DC properly/in time.
737 //This can result is visible distortions on the screen.
738 //Debugging showed that querying the visible region of a DC will cure
739 //this problem (GPI probably recalculates the visible region). (#334)
740
741 int nrdcs = 0;
742 HDC hdcWindow[MAX_OPENDCS];
743
744 if(win32wnd->queryOpenDCs(hdcWindow, MAX_OPENDCS, &nrdcs))
745 {
746 RECTL rcl = {0,0,1,1};
747 HRGN hrgnRect;
748
749 for(int i=0;i<nrdcs;i++) {
750 dprintf(("Recalc visible region of DC %x for window %x", hdcWindow[i], win32wnd->getWindowHandle()));
751
752 hrgnRect = GreCreateRectRegion(hdcWindow[i], &rcl, 1);
753 GreCopyClipRegion(hdcWindow[i], hrgnRect, 0, COPYCRGN_VISRGN);
754 GreDestroyRegion(hdcWindow[i], hrgnRect);
755 }
756 }
757 //Workaround END
758
759 if(!win32wnd->isComingToTop() && ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == WS_EX_TOPMOST_W))
760 {
761 HWND hwndrelated;
762 Win32BaseWindow *topwindow;
763
764 win32wnd->setComingToTop(TRUE);
765
766 hwndrelated = WinQueryWindow(hwnd, QW_PREV);
767 dprintf(("WM_VRNENABLED hwndrelated = %x (hwnd=%x)", hwndrelated, hwnd));
768 topwindow = Win32BaseWindow::GetWindowFromOS2Handle(hwndrelated);
769 if(topwindow == NULL || ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == 0)) {
770 //put window at the top of z order
771 WinSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
772 }
773 if(topwindow) RELEASE_WNDOBJ(topwindow);
774
775 win32wnd->setComingToTop(FALSE);
776 break;
777 }
778 goto RunDefWndProc;
779 }
780
781 case WM_VRNDISABLED:
782 {
783 dprintf(("OS2: WM_VRNDISABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
784 //visible region is about to change or WinLockWindowUpdate called
785 //suspend window drawing
786
787 win32wnd->callVisibleRgnNotifyProc(FALSE);
788 goto RunDefWndProc;
789 }
790
791 case WIN32APP_DDRAWFULLSCREEN:
792 //Changing the size of the win32 window in SetCooperativeLevel can
793 //fail if this happens during WM_ADJUSTWINDOWPOS
794 //NOTE: This is not a good solution, but a proper fix is more difficult
795 // with the current window mess
796 dprintf(("WIN32APP_DDRAWFULLSCREEN %x (%d,%d)", win32wnd->getWindowHandle(), mp1, mp2));
797 SetWindowPos(win32wnd->getWindowHandle(), HWND_TOP_W, 0, 0, (DWORD)mp1, (DWORD)mp2, 0);
798 ShowWindow(win32wnd->getWindowHandle(), SW_SHOW_W);
799 break;
800
801 case WIN32APP_CHNGEFRAMECTRLS:
802 {
803 dprintf(("OS2: WIN32APP_CHANGEFRAMECTRLS"));
804 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), (ULONG)mp1, win32wnd->getExStyle(), (ULONG)mp2);
805 break;
806 }
807
808#ifdef DEBUG
809 case WM_SETFOCUS:
810 {
811 HWND hwndFocus = (HWND)mp1;
812 dprintf(("OS2: WM_SETFOCUS %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
813 if(WinQueryFocus(HWND_DESKTOP) == win32wnd->getOS2FrameWindowHandle()) {
814 dprintf(("WARNING: Focus set to frame window"));
815 }
816 break;
817 }
818#endif
819
820 //Handle all focus processed during WM_FOCUSCHANGED; PM doesn't like focus
821 //changes during focus processing (WM_SETFOCUS). This message is sent
822 //after all focus work has been completed.
823 case WM_FOCUSCHANGED:
824 {
825 HWND hwndFocus = (HWND)mp1;
826 HWND hwndFocusWin32 = OS2ToWin32Handle(hwndFocus);
827
828 dprintf(("OS2: WM_FOCUSCHANGED %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
829
830 //PM doesn't allow SetFocus calls during WM_SETFOCUS message processing;
831 //must delay this function call
832
833 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC)
834 {
835 //another (non-win32) application's window
836 //set to NULL (allowed according to win32 SDK) to avoid problems
837 hwndFocus = 0;
838 hwndFocusWin32 = 0;
839 }
840 if((ULONG)mp2 == TRUE) {
841 recreateCaret(hwndFocusWin32);
842 win32wnd->MsgSetFocus(hwndFocusWin32);
843 }
844 else {
845 //If SetFocus(0) was called, then the window has already received
846 //a WM_KILLFOCUS; don't send another one
847 if(!fIgnoreKeystrokes) {
848 win32wnd->MsgKillFocus(OS2ToWin32Handle(hwndFocus));
849 }
850 else dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
851 }
852 break;
853 }
854
855 //**************************************************************************
856 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
857 //**************************************************************************
858
859 case WM_BUTTON1DOWN:
860 case WM_BUTTON1UP:
861 case WM_BUTTON1DBLCLK:
862 case WM_BUTTON2DOWN:
863 case WM_BUTTON2UP:
864 case WM_BUTTON2DBLCLK:
865 case WM_BUTTON3DOWN:
866 case WM_BUTTON3UP:
867 case WM_BUTTON3DBLCLK:
868 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
869 RELEASE_WNDOBJ(win32wnd);
870 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
871 }
872 if(win32wnd)
873 win32wnd->MsgButton(pWinMsg);
874
875 rc = (MRESULT)TRUE;
876 break;
877
878 case WM_BUTTON2MOTIONSTART:
879 case WM_BUTTON2MOTIONEND:
880 case WM_BUTTON2CLICK:
881 case WM_BUTTON1MOTIONSTART:
882 case WM_BUTTON1MOTIONEND:
883 case WM_BUTTON1CLICK:
884 case WM_BUTTON3MOTIONSTART:
885 case WM_BUTTON3MOTIONEND:
886 case WM_BUTTON3CLICK:
887 rc = (MRESULT)TRUE;
888 break;
889
890 case WM_MOUSEMOVE:
891 {
892 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
893 RELEASE_WNDOBJ(win32wnd);
894 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
895 }
896 if(win32wnd)
897 win32wnd->MsgMouseMove(pWinMsg);
898 break;
899 }
900
901 case WM_CONTROL:
902 goto RunDefWndProc;
903
904 case WM_COMMAND:
905 dprintf(("OS2: WM_COMMAND %x %x %x", hwnd, mp1, mp2));
906 win32wnd->DispatchMsgA(pWinMsg);
907 break;
908
909 case WM_SYSCOMMAND:
910 dprintf(("OS2: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
911 win32wnd->DispatchMsgA(pWinMsg);
912 break;
913
914 case WM_RENDERFMT:
915 case WM_RENDERALLFMTS:
916 case WM_DESTROYCLIPBOARD:
917 case WM_DRAWCLIPBOARD:
918 win32wnd->DispatchMsgA(pWinMsg);
919 break;
920
921 case WM_CHAR_SPECIAL:
922 /* NO BREAK! FALLTHRU CASE! */
923
924 case WM_CHAR:
925 dprintf(("OS2: WM_CHAR %x %x %x, %x %x msg: %x focus wnd %x", win32wnd->getWindowHandle(), mp1, mp2, pWinMsg->wParam, pWinMsg->lParam, pWinMsg->message, WinQueryFocus(HWND_DESKTOP)));
926 win32wnd->MsgChar(pWinMsg);
927 /*
928 * now, we need to send WM_CHAR message
929 * to inform Win32 window that an char was input
930 * We ignoring wm_char sending in case of Ctrl or Alt pressed
931 * Also we
932 */
933 /* sending only after WINWM_KEYDOWN */
934 /* checking for alphanum chars and number. did I miss something?
935 */
936 if (WINWM_KEYDOWN == pWinMsg->message &&
937 (((SHORT1FROMMP(mp1) & KC_CHAR) &&
938 !(SHORT1FROMMP(mp1) & KC_VIRTUALKEY)) ||
939 (SHORT1FROMMP(mp1) & KC_DEADKEY)))
940 {
941 MSG extramsg;
942 memcpy(&extramsg, pWinMsg, sizeof(MSG));
943 extramsg.message = WINWM_CHAR;
944 extramsg.wParam = (ULONG)mp2;
945 if(SHORT1FROMMP(mp1) & KC_DEADKEY)
946 {
947 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
948 }
949
950 win32wnd->MsgChar(&extramsg);
951 }
952
953 break;
954
955 case WM_TIMER:
956 dprintf(("OS2: WM_TIMER %x %x time %x", win32wnd->getWindowHandle(), pWinMsg->wParam, GetTickCount()));
957 win32wnd->DispatchMsgA(pWinMsg);
958 goto RunDefWndProc;
959
960 case WM_SETWINDOWPARAMS:
961 {
962 WNDPARAMS *wndParams = (WNDPARAMS *)mp1;
963
964 dprintf(("OS2: WM_SETWINDOWPARAMS %x", hwnd));
965 if(wndParams->fsStatus & WPM_TEXT) {
966 win32wnd->MsgSetText(wndParams->pszText, wndParams->cchText);
967 }
968 goto RunDefWndProc;
969 }
970
971 case WM_QUERYWINDOWPARAMS:
972 {
973 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
974 ULONG textlen;
975 PSZ wintext;
976
977 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
978 {
979 if(wndpars->fsStatus & WPM_TEXT)
980 win32wnd->MsgGetText(wndpars->pszText, wndpars->cchText);
981 if(wndpars->fsStatus & WPM_CCHTEXT)
982 wndpars->cchText = win32wnd->MsgGetTextLength();
983
984 wndpars->fsStatus = 0;
985 wndpars->cbCtlData = 0;
986 wndpars->cbPresParams = 0;
987 rc = (MRESULT)TRUE;
988 break;
989 }
990 goto RunDefWndProc;
991 }
992
993 case WM_PAINT:
994 {
995 RECTL rectl;
996 BOOL rc;
997
998 win32wnd->checkForDirtyUpdateRegion();
999
1000 rc = WinQueryUpdateRect(hwnd, &rectl);
1001 dprintf(("OS2: WM_PAINT %x (%d,%d) (%d,%d) rc=%d", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop, rc));
1002
1003 if(rc && win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
1004 rectl.yBottom != rectl.yTop) && !IsIconic(win32wnd->GetTopParent()))
1005 {
1006 win32wnd->DispatchMsgA(pWinMsg);
1007 if(WinQueryUpdateRect(hwnd, NULL) == TRUE)
1008 {//the application didn't validate the update region; Windows
1009 //will only send a WM_PAINT once until another part of the
1010 //window is invalidated. Unfortunately PM keeps on sending
1011 //WM_PAINT messages until we validate the update region.
1012
1013 win32wnd->saveAndValidateUpdateRegion();
1014 }
1015 }
1016 else goto RunDefWndProc;
1017 break;
1018 }
1019
1020 case WM_ERASEBACKGROUND:
1021 {
1022 dprintf(("OS2: WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
1023 rc = (MRESULT)FALSE;
1024 break;
1025 }
1026
1027 case WM_CALCVALIDRECTS:
1028 dprintf(("OS2: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1029 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
1030 break;
1031
1032 case WM_REALIZEPALETTE:
1033 {
1034 dprintf(("OS2: WM_REALIZEPALETTE %x", win32wnd->getWindowHandle()));
1035 win32wnd->DispatchMsgA(pWinMsg);
1036 break;
1037 }
1038
1039 case WM_HSCROLL:
1040 case WM_VSCROLL:
1041 dprintf(("OS2: %s %x %x %x", (msg == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL", win32wnd->getWindowHandle(), mp1, mp2));
1042 win32wnd->DispatchMsgA(pWinMsg);
1043 break;
1044
1045 case WM_IMEREQUEST:
1046 case WM_IMECONTROL:
1047 case WM_IMENOTIFY:
1048 if( pWinMsg->message )
1049 {
1050 win32wnd->DispatchMsgA( pWinMsg );
1051
1052 if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
1053 ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
1054 {
1055 MSG m;
1056
1057 m.message = WM_IME_NOTIFY_W;
1058 m.wParam = IMN_SETCONVERSIONMODE_W;
1059 m.lParam = 0;
1060
1061 win32wnd->DispatchMsgA( &m );
1062 }
1063 }
1064 else
1065 goto RunDefWndProc;
1066 break;
1067
1068 case DM_DRAGOVER:
1069 {
1070 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
1071 PDRAGITEM pDragItem;
1072 USHORT sxDrop = SHORT1FROMMP(mp2);
1073 USHORT syDrop = SHORT2FROMMP(mp2);
1074
1075 dprintf(("OS2: DM_DRAGOVER %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
1076
1077 if(fDragDropDisabled) {
1078 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1079 break;
1080 }
1081
1082 //does this window accept dropped files?
1083 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1084 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1085 break;
1086 }
1087
1088 if(PMDragValidate(pDragInfo) == FALSE) {
1089 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1090 break;
1091 }
1092 if(win32wnd->isDragDropActive() == FALSE) {
1093 ULONG ulBytes, cItems;
1094 char *pszFiles;
1095
1096 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
1097 if(pszFiles) {
1098 POINT point = {sxDrop, syDrop};
1099 if(DragDropDragEnter(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes, DROPEFFECT_COPY_W) == FALSE) {
1100 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1101 }
1102 else {
1103 fDragDropActive = TRUE;
1104 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1105 win32wnd->setDragDropActive(TRUE);
1106 }
1107 free(pszFiles);
1108 }
1109 else {
1110 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1111 }
1112 }
1113 else {
1114 if(DragDropDragOver(win32wnd->getWindowHandle(), DROPEFFECT_COPY_W) == FALSE) {
1115 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1116 }
1117 else rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1118 }
1119 break;
1120 }
1121
1122 case DM_DRAGLEAVE:
1123 {
1124 dprintf(("OS2: DM_DRAGLEAVE %x", win32wnd->getWindowHandle()));
1125
1126 if(fDragDropDisabled) {
1127 break;
1128 }
1129
1130 fDragDropActive = FALSE;
1131
1132 //does this window accept dropped files?
1133 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1134 break;
1135 }
1136
1137 DragDropDragLeave(win32wnd->getWindowHandle());
1138 win32wnd->setDragDropActive(FALSE);
1139 break;
1140 }
1141
1142 case DM_DROP:
1143 {
1144 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
1145 PDRAGITEM pDragItem;
1146 USHORT sxDrop = SHORT1FROMMP(mp2);
1147 USHORT syDrop = SHORT2FROMMP(mp2);
1148 USHORT usIndicator, usOp;
1149
1150 dprintf(("OS2: DM_DROP %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
1151
1152 fDragDropActive = FALSE;
1153 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1154
1155 if(fDragDropDisabled) {
1156 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1157 break;
1158 }
1159
1160 //does this window accept dropped files?
1161 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1162 break;
1163 }
1164
1165 ULONG ulBytes, cItems;
1166 char *pszFiles;
1167
1168 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
1169 if(pszFiles) {
1170 POINT point = {sxDrop, syDrop};
1171 if(DragDropFiles(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes) == FALSE) {
1172 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1173 }
1174 else {
1175 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1176 win32wnd->setDragDropActive(FALSE);
1177 }
1178 free(pszFiles);
1179 }
1180 else {
1181 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1182 }
1183 break;
1184 }
1185
1186 case DM_RENDER:
1187 {
1188 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1189
1190 dprintf(("OS2: DM_RENDER %x", pDragTransfer));
1191
1192 rc = (MRESULT)OSLibRenderFormat(pDragTransfer);
1193 break;
1194 }
1195
1196 case DM_RENDERPREPARE:
1197 {
1198 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1199
1200 dprintf(("OS2: DM_RENDERPREPARE %x", pDragTransfer));
1201 break;
1202 }
1203
1204 case DM_ENDCONVERSATION:
1205 {
1206 dprintf(("OS2: DM_ENDCONVERSATION"));
1207 rc = (MRESULT)OSLibEndConversation();
1208 break;
1209 }
1210
1211 case DM_RENDERFILE:
1212 {
1213 dprintf(("OS2: DM_ENDCONVERSATION"));
1214 rc = FALSE;
1215 break;
1216 }
1217
1218 case WM_DDE_INITIATE:
1219 case WM_DDE_INITIATEACK:
1220 case WM_DDE_REQUEST:
1221 case WM_DDE_ACK:
1222 case WM_DDE_DATA:
1223 case WM_DDE_ADVISE:
1224 case WM_DDE_UNADVISE:
1225 case WM_DDE_POKE:
1226 case WM_DDE_EXECUTE:
1227 case WM_DDE_TERMINATE:
1228 dprintf(("OS2: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
1229 goto RunDefWndProc;
1230
1231 case WM_INITMENU:
1232 case WM_MENUSELECT:
1233 case WM_MENUEND:
1234 case WM_NEXTMENU:
1235 case WM_SYSCOLORCHANGE:
1236 case WM_SYSVALUECHANGED:
1237 case WM_SETSELECTION:
1238 case WM_PPAINT:
1239 case WM_PSETFOCUS:
1240 case WM_PSYSCOLORCHANGE:
1241 case WM_PSIZE:
1242 case WM_PACTIVATE:
1243 case WM_PCONTROL:
1244 case WM_HELP:
1245 case WM_APPTERMINATENOTIFY:
1246 case WM_PRESPARAMCHANGED:
1247 case WM_DRAWITEM:
1248 case WM_MEASUREITEM:
1249 case WM_CONTROLPOINTER:
1250 case WM_QUERYDLGCODE:
1251 case WM_SUBSTITUTESTRING:
1252 case WM_MATCHMNEMONIC:
1253 case WM_SAVEAPPLICATION:
1254 case WM_SEMANTICEVENT:
1255 default:
1256 dprintf2(("OS2: RunDefWndProc hwnd %x msg %x mp1 %x mp2 %x", hwnd, msg, mp1, mp2));
1257 goto RunDefWndProc;
1258 }
1259 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1260 RestoreOS2TIB();
1261 ODIN_UnsetExceptionHandler(&exceptRegRec);
1262
1263#ifdef DEBUG
1264 dbg_ThreadPopCall();
1265#endif
1266 return (MRESULT)rc;
1267
1268RunDefWndProc:
1269// dprintf(("OS2: RunDefWndProc msg %x for %x", msg, hwnd));
1270 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1271
1272 RestoreOS2TIB();
1273 ODIN_UnsetExceptionHandler(&exceptRegRec);
1274
1275#ifdef DEBUG
1276 dbg_ThreadPopCall();
1277#endif
1278 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1279} /* End of Win32WindowProc */
1280//******************************************************************************
1281//******************************************************************************
1282MRESULT EXPENTRY Win32FrameWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1283{
1284 POSTMSG_PACKET *postmsg;
1285 OSLIBPOINT point, ClientPoint;
1286 Win32BaseWindow *win32wnd;
1287 TEB *teb;
1288 MRESULT rc = 0;
1289 MSG winMsg, *pWinMsg;
1290 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
1291
1292#ifdef DEBUG
1293 dbg_ThreadPushCall("Win32FrameWindowProc");
1294#endif
1295
1296 ODIN_SetExceptionHandler(&exceptRegRec);
1297 //Restore our FS selector
1298 SetWin32TIB();
1299
1300 // BEGIN NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- BEGIN
1301 teb = GetThreadTEB();
1302 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
1303
1304 // do some sanity checking here:
1305 // - we need to have a TEB handle
1306 // - unless this is WM_CREATE (the very first message), there has to be
1307 // a USER32 window object for this window handle
1308 // - thread must not be suspended in WaitMessage
1309 if(!teb || (msg != WM_CREATE && win32wnd == NULL) || teb->o.odin.fWaitMessageSuspend) {
1310 if(teb && teb->o.odin.fWaitMessageSuspend)
1311 dprintf(("PMFRAME: fWaitMessageSuspend window %x msg %x -> run default frame proc", hwnd, msg));
1312 else dprintf(("PMFRAME: Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
1313 goto RunDefFrameWndProc;
1314 }
1315//// if(teb->o.odin.fIgnoreMsgs) {
1316//// goto RunDefWndProc;
1317//// }
1318
1319 // check if the message state counter in the TEB is odd
1320 // This means the message has been sent directly from PM to our message
1321 // handler (so it is the first time we know about this PM message).
1322 // If this is the case, we have to translate it here to a Win32
1323 // message first. The other case is that the message is the result of a
1324 // WinDispatchMsg call and therefore has already been translated.
1325 if((teb->o.odin.msgstate & 1) == 0)
1326 {//message that was sent directly to our window proc handler; translate it here
1327 QMSG qmsg;
1328
1329 qmsg.msg = msg;
1330 qmsg.hwnd = hwnd;
1331 qmsg.mp1 = mp1;
1332 qmsg.mp2 = mp2;
1333 qmsg.time = WinQueryMsgTime(teb->o.odin.hab);
1334 WinQueryMsgPos(teb->o.odin.hab, &qmsg.ptl);
1335 qmsg.reserved = 0;
1336
1337 if(OS2ToWinMsgTranslate((PVOID)teb, &qmsg, &winMsg, FALSE, MSG_REMOVE) == FALSE)
1338 {//message was not translated
1339 memset(&winMsg, 0, sizeof(MSG));
1340 }
1341 pWinMsg = &winMsg;
1342 }
1343 else {
1344 // message has already been translated before (GetMessage/PeekMessage).
1345 // Use the translated information. Flip the translation flag.
1346 pWinMsg = &teb->o.odin.msg;
1347 teb->o.odin.msgstate++;
1348 }
1349 // END NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- END
1350
1351 switch( msg )
1352 {
1353 case WM_CREATE:
1354 {
1355 //WM_CREATE handled during client window creation
1356 dprintf(("PMFRAME: WM_CREATE %x", hwnd));
1357 goto RunDefFrameWndProc;
1358 }
1359
1360//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
1361// handler; must postpone it, so do it here
1362 case WIN32APP_POSTPONEDESTROY:
1363 OSLibWinDestroyWindow(hwnd);
1364 break;
1365//hack end
1366
1367#ifdef DEBUG
1368 case WM_CLOSE:
1369 {
1370 dprintf(("PMFRAME: WM_CLOSE %x", hwnd));
1371 goto RunDefFrameWndProc;
1372 }
1373#endif
1374
1375 case WM_PAINT:
1376 {
1377 RECTL rectl;
1378 HRGN hrgn;
1379
1380 hrgn = CreateRectRgn(0, 0, 0, 0);
1381 GetUpdateRgnFrame(win32wnd->getWindowHandle(), hrgn);
1382
1383 HPS hps = WinBeginPaint(hwnd, NULL, &rectl);
1384 dprintf(("PMFRAME: WM_PAINT %x (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop));
1385
1386 if(win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
1387 rectl.yBottom != rectl.yTop))
1388 {
1389 PRECT pClient = win32wnd->getClientRectPtr();
1390 PRECT pWindow = win32wnd->getWindowRect();
1391
1392 if(!(pClient->left == 0 && pClient->top == 0 &&
1393 win32wnd->getClientHeight() == win32wnd->getWindowHeight() &&
1394 win32wnd->getClientWidth() == win32wnd->getWindowWidth()))
1395 {
1396 RECT rectUpdate;
1397
1398 mapOS2ToWin32Rect(win32wnd->getWindowHeight(), (PRECTLOS2)&rectl, &rectUpdate);
1399 win32wnd->MsgNCPaint(&rectUpdate, hrgn);
1400 }
1401 }
1402 WinEndPaint(hps);
1403
1404 DeleteObject(hrgn);
1405 break;
1406 }
1407
1408 case WM_ERASEBACKGROUND:
1409 {
1410 dprintf(("PMFRAME:WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
1411 rc = (MRESULT)FALSE;
1412 break;
1413 }
1414
1415 //**************************************************************************
1416 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
1417 //**************************************************************************
1418
1419 case WM_BUTTON1DOWN:
1420 case WM_BUTTON1UP:
1421 case WM_BUTTON1DBLCLK:
1422 case WM_BUTTON2DOWN:
1423 case WM_BUTTON2UP:
1424 case WM_BUTTON2DBLCLK:
1425 case WM_BUTTON3DOWN:
1426 case WM_BUTTON3UP:
1427 case WM_BUTTON3DBLCLK:
1428 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1429 RELEASE_WNDOBJ(win32wnd);
1430 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1431 }
1432 if(win32wnd)
1433 win32wnd->MsgButton(pWinMsg);
1434
1435 rc = (MRESULT)TRUE;
1436 break;
1437
1438 case WM_BUTTON2MOTIONSTART:
1439 case WM_BUTTON2MOTIONEND:
1440 case WM_BUTTON2CLICK:
1441 case WM_BUTTON1MOTIONSTART:
1442 case WM_BUTTON1MOTIONEND:
1443 case WM_BUTTON1CLICK:
1444 case WM_BUTTON3MOTIONSTART:
1445 case WM_BUTTON3MOTIONEND:
1446 case WM_BUTTON3CLICK:
1447 rc = (MRESULT)TRUE;
1448 break;
1449
1450 case WM_MOUSEMOVE:
1451 {
1452 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1453 RELEASE_WNDOBJ(win32wnd);
1454 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1455 }
1456 if(win32wnd)
1457 win32wnd->MsgMouseMove(pWinMsg);
1458 break;
1459 }
1460
1461 case WM_CHAR_SPECIAL_CONSOLE_BREAK:
1462 {
1463 //ignore this message. don't forward it to the default PM frame window handler
1464 //as that one sends it to the client. as a result we end up translating
1465 //it twice
1466 break;
1467 }
1468
1469 case WM_CHAR:
1470 {
1471 dprintf(("PMFRAME:WM_CHAR"));
1472 break;
1473 }
1474
1475 case WM_ADJUSTWINDOWPOS:
1476 {
1477 PSWP pswp = (PSWP)mp1;
1478 SWP swpOld;
1479 WINDOWPOS wp,wpOld;
1480 ULONG ulFlags;
1481 ULONG ret = 0;
1482 HWND hParent = NULLHANDLE, hwndAfter;
1483
1484 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1485
1486 ulFlags = pswp->fl;
1487
1488 if(win32wnd->IsParentChanging()) {
1489 rc = 0;
1490 break;
1491 }
1492
1493 //@@PF all commands from minimized window viewer or from Ctrl-Esc
1494 //are 'pure' and should be handled only by DeFrameProc - this is weird
1495 //but without them we will not have results. Pure = plain flag of restore/minimize/maximize
1496 if((pswp->fl == SWP_MINIMIZE) || (pswp->fl & SWP_RESTORE)) {
1497 // note the purity of SWP no other SWP_FLAGS allowed
1498 goto RunDefFrameWndProc;
1499 }
1500
1501 if(pswp->fl & SWP_NOADJUST) {
1502 //ignore weird messages (TODO: why are they sent?)
1503 dprintf(("WARNING: WM_ADJUSTWINDOWPOS with SWP_NOADJUST flag!!"));
1504 break;
1505
1506 }
1507
1508 //PF Pure flags should not cause any subsequent messages to win32 windows
1509 //we should route them to DefFrameWndProc and check highlight.
1510
1511 if ((pswp->fl == SWP_FOCUSACTIVATE) || (pswp->fl == SWP_FOCUSDEACTIVATE))
1512 {
1513 if (fOS2Look)
1514 {
1515 if(pswp->fl == SWP_FOCUSACTIVATE)
1516 {
1517 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1518 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1519 }
1520 else
1521 {
1522 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1523 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1524 }
1525 }
1526 goto RunDefFrameWndProc;
1527 }
1528
1529 //CB: show dialog in front of owner
1530 if (win32wnd->IsModalDialogOwner())
1531 {
1532 dprintf(("win32wnd->IsModalDialogOwner %x", win32wnd->getWindowHandle()));
1533 pswp->fl |= SWP_ZORDER;
1534 pswp->hwndInsertBehind = win32wnd->getOS2HwndModalDialog();
1535 if (pswp->fl & SWP_ACTIVATE)
1536 {
1537 pswp->fl &= ~SWP_ACTIVATE;
1538 WinSetWindowPos(win32wnd->getOS2HwndModalDialog(),0,0,0,0,0,SWP_ACTIVATE);
1539 }
1540 }
1541
1542 if(!win32wnd->CanReceiveSizeMsgs())
1543 break;
1544
1545 WinQueryWindowPos(hwnd, &swpOld);
1546 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
1547 if (win32wnd->isChild()) {
1548 if(win32wnd->getParent()) {
1549 hParent = win32wnd->getParent()->getOS2WindowHandle();
1550 }
1551 else goto RunDefFrameWndProc;
1552 }
1553 }
1554 hwndAfter = pswp->hwndInsertBehind;
1555 if(win32wnd->getParent()) {
1556 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(), hwnd);
1557 }
1558 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1559
1560 wp.hwnd = win32wnd->getWindowHandle();
1561 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1562 {
1563 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1564 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1565 if(wndAfter) {
1566 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1567 RELEASE_WNDOBJ(wndAfter);
1568 }
1569 else wp.hwndInsertAfter = HWND_TOP_W;
1570 }
1571
1572 wpOld = wp;
1573 win32wnd->MsgPosChanging((LPARAM)&wp);
1574
1575 if(win32wnd->getOldStyle() != win32wnd->getStyle())
1576 {
1577 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), win32wnd->getStyle(), win32wnd->getExStyle(), win32wnd->getStyle());
1578 if(fOS2Look) {
1579 DWORD dwOldStyle = win32wnd->getOldStyle();
1580 DWORD dwStyle = win32wnd->getStyle();
1581
1582 win32wnd->setOldStyle(dwStyle);
1583 if((dwOldStyle & WS_MINIMIZE_W) && !(dwStyle & WS_MINIMIZE_W)) {
1584 //SC_RESTORE -> SC_MINIMIZE
1585 dprintf(("%x -> SC_RESTORE -> SC_MINIMIZE", win32wnd->getWindowHandle()));
1586 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_RESTORE, SC_MINIMIZE, hbmFrameMenu[PMMENU_MINBUTTON]);
1587 if(dwStyle & WS_MAXIMIZE_W) {
1588 //SC_MAXIMIZE -> SC_RESTORE
1589 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (1)", win32wnd->getWindowHandle()));
1590 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1591 }
1592 }
1593 else
1594 if((dwOldStyle & WS_MAXIMIZE_W) && !(dwStyle & WS_MAXIMIZE_W)) {
1595 //SC_RESTORE -> SC_MAXIMIZE
1596 dprintf(("%x -> SC_RESTORE -> SC_MAXIMIZE", win32wnd->getWindowHandle()));
1597 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_RESTORE, SC_MAXIMIZE, hbmFrameMenu[PMMENU_MAXBUTTON]);
1598 }
1599 else
1600 if(!(dwOldStyle & WS_MINIMIZE_W) && (dwStyle & WS_MINIMIZE_W)) {
1601 //SC_MINIMIZE -> SC_RESTORE
1602 dprintf(("%x -> SC_MINIMIZE -> SC_RESTORE", win32wnd->getWindowHandle()));
1603 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_MINIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1604 }
1605 else
1606 if(!(dwOldStyle & WS_MAXIMIZE_W) && (dwStyle & WS_MAXIMIZE_W)) {
1607 //SC_MAXIMIZE -> SC_RESTORE
1608 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (2)", win32wnd->getWindowHandle()));
1609 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1610 }
1611 }
1612 }
1613
1614 if ((wp.hwndInsertAfter != wpOld.hwndInsertAfter) ||
1615 (wp.x != wpOld.x) || (wp.y != wpOld.y) || (wp.cx != wpOld.cx) || (wp.cy != wpOld.cy) || (wp.flags != wpOld.flags))
1616 {
1617 ULONG flags = pswp->fl; //make a backup copy; OSLibMapWINDOWPOStoSWP will modify it
1618
1619 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1620 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1621
1622 if(win32wnd->getParent()) {
1623 OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, win32wnd->getParent()->getClientHeight(),
1624 hwnd);
1625 }
1626 else OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1627
1628 dprintf(("%x (%d,%d), (%d,%d)", pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
1629
1630 //OSLibMapWINDOWPOStoSWP can add flags, but we must not let it remove flags!
1631 if(pswp->fl & SWP_SIZE)
1632 flags |= SWP_SIZE;
1633
1634 if(pswp->fl & SWP_MOVE)
1635 flags |= SWP_MOVE;
1636
1637 pswp->fl = flags; //restore flags
1638
1639 pswp->fl |= SWP_NOADJUST;
1640 pswp->hwndInsertBehind = hwndAfter;
1641 pswp->hwnd = hwnd;
1642
1643 ret = 0xf;
1644 }
1645adjustend:
1646 //The next part needs to be done for top-level windows only
1647 if(!((win32wnd->getStyle() & (WS_POPUP_W|WS_CHILD_W)) == WS_CHILD_W))
1648 {
1649 //Setting these flags is necessary to avoid activation/focus problems
1650 if(ulFlags & SWP_DEACTIVATE) {
1651 ret |= AWP_DEACTIVATE;
1652 }
1653 if(ulFlags & SWP_ACTIVATE)
1654 {
1655 if(ulFlags & SWP_ZORDER) {
1656 dprintf(("Set FF_NOACTIVATESWP"));
1657 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
1658 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags | FF_NOACTIVATESWP);
1659 }
1660
1661 if(!(ulFlags & SWP_SHOW))
1662 {
1663 ret |= AWP_ACTIVATE;
1664 }
1665 else
1666 {
1667 FrameSetFocus(hwnd);
1668 }
1669 }
1670 }
1671 else {
1672 if(ulFlags & (SWP_ACTIVATE|SWP_FOCUSACTIVATE))
1673 {
1674 win32wnd->MsgChildActivate(TRUE);
1675 if(fOS2Look) {
1676 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1677 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1678 }
1679 }
1680 else
1681 if(ulFlags & (SWP_DEACTIVATE|SWP_FOCUSDEACTIVATE))
1682 {
1683 win32wnd->MsgChildActivate(FALSE);
1684 if(fOS2Look) {
1685 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1686 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1687 }
1688 }
1689 }
1690#ifdef DEBUG
1691 dprintf(("WM_ADJUSTWINDOWPOS ret %x flags %x", ret, WinQueryWindowUShort(hwnd, QWS_FLAGS)));
1692 if(ret == 0x0f) {
1693 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1694 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1695 }
1696#endif
1697 rc = (MRESULT)ret;
1698 break;
1699 }
1700
1701 case WM_WINDOWPOSCHANGED:
1702 {
1703 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
1704 SWP swpOld = *(pswp + 1);
1705 WINDOWPOS wp;
1706 ULONG flAfp = (ULONG)mp2;
1707 HWND hParent = NULLHANDLE;
1708 RECTL rect;
1709
1710 dprintf(("PMFRAME:WM_WINDOWPOSCHANGED (%x) %x %x (%s) (%d,%d) (%d,%d) z %x", mp2, win32wnd->getWindowHandle(), pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy, Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind)));
1711 if(win32wnd->IsParentChanging()) {
1712 goto PosChangedEnd;
1713 }
1714
1715 // PF: MDI window is not a common OS/2 frame window so we just skipped all
1716 // PM default processing for it that basicly moved this window to 0,0 point
1717 // and changed frame controls. Now do our own processing.
1718
1719 if ((pswp->fl & SWP_MAXIMIZE) && (win32wnd->getExStyle() & WS_EX_MDICHILD_W))
1720 {
1721 SendMessageA(win32wnd->getWindowHandle(), WM_SYSCOMMAND_W, SC_MAXIMIZE_W, 0);
1722 goto PosChangedEnd;
1723 }
1724
1725 //SvL: When a window is made visible, then we don't receive a
1726 // WM_VRNENABLED message (for some weird reason)
1727 if(pswp->fl & SWP_SHOW) {
1728 win32wnd->callVisibleRgnNotifyProc(TRUE);
1729 }
1730 else
1731 if(pswp->fl & SWP_HIDE) {
1732 win32wnd->callVisibleRgnNotifyProc(FALSE);
1733 }
1734
1735 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
1736 {
1737 if(win32wnd->isChild())
1738 {
1739 if(win32wnd->getParent()) {
1740 hParent = win32wnd->getParent()->getOS2WindowHandle();
1741 }
1742 else goto PosChangedEnd; //parent has just been destroyed
1743 }
1744 }
1745
1746
1747 if(win32wnd->getParent()) {
1748 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1749 hwnd);
1750 }
1751 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1752
1753 wp.hwnd = win32wnd->getWindowHandle();
1754 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1755 {
1756 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1757 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1758 if(wndAfter) {
1759 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1760 RELEASE_WNDOBJ(wndAfter);
1761 }
1762 else wp.hwndInsertAfter = HWND_TOP_W;
1763 }
1764
1765 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0)
1766 {
1767 if(pswp->fl & SWP_RESTORE && win32wnd->getStyle() & WS_MINIMIZE_W) {
1768 dprintf(("Restoring minimized window %x", win32wnd->getWindowHandle()));
1769 win32wnd->ShowWindow(SW_RESTORE_W);
1770 }
1771 if(pswp->fl & SWP_SHOW) {
1772 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1773 }
1774 else
1775 if(pswp->fl & SWP_HIDE) {
1776 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1777 }
1778 if(pswp->fl & (SWP_SHOW|SWP_HIDE))
1779 {//TODO: necessary for more options? (activate?)
1780 if(win32wnd->CanReceiveSizeMsgs())
1781 win32wnd->MsgPosChanged((LPARAM)&wp);
1782 }
1783
1784 //MUST call the old frame window proc!
1785 goto RunDefFrameWndProc;
1786 }
1787
1788 if(pswp->fl & SWP_SHOW) {
1789 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1790 }
1791 else
1792 if(pswp->fl & SWP_HIDE) {
1793 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1794 }
1795
1796 if(flAfp & AWP_ACTIVATE)
1797 {
1798 FrameSetFocus(hwnd);
1799 }
1800
1801#ifndef USE_CALCVALIDRECT
1802 if((pswp->fl & (SWP_MOVE | SWP_SIZE)))
1803 {
1804 //CB: todo: use result for WM_CALCVALIDRECTS
1805 //Get old client rectangle (for invalidation of frame window parts later on)
1806 //Use new window height to calculate the client area
1807 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&rect);
1808
1809 //Note: Also updates the new window rectangle
1810 win32wnd->MsgFormatFrame(&wp);
1811
1812 if(win32wnd->isOwnDC()) {
1813 setPageXForm(win32wnd, (pDCData)GpiQueryDCData(win32wnd->getOwnDC()));
1814 }
1815
1816 if(win32wnd->CanReceiveSizeMsgs())
1817 win32wnd->MsgPosChanged((LPARAM)&wp);
1818
1819 if((pswp->fl & SWP_SIZE) && ((pswp->cx != pswpOld->cx) || (pswp->cy != pswpOld->cy)))
1820 {
1821 //redraw the frame (to prevent unnecessary client updates)
1822 BOOL redrawAll = FALSE;
1823
1824 dprintf2(("WM_WINDOWPOSCHANGED: redraw frame"));
1825 if (win32wnd->getWindowClass())
1826 {
1827 DWORD dwStyle = win32wnd->getWindowClass()->getClassLongA(GCL_STYLE_W);
1828
1829 if ((dwStyle & CS_HREDRAW_W) && (pswp->cx != pswpOld->cx))
1830 redrawAll = TRUE;
1831 else
1832 if ((dwStyle & CS_VREDRAW_W) && (pswp->cy != pswpOld->cy))
1833 redrawAll = TRUE;
1834 }
1835 else redrawAll = TRUE;
1836
1837 if(win32wnd->IsMixMaxStateChanging()) {
1838 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1839 redrawAll = TRUE;
1840 }
1841
1842 if (redrawAll)
1843 {
1844 //CB: redraw all children for now
1845 // -> problems with update region if we don't do it
1846 // todo: rewrite whole handling
1847 dprintf(("PMFRAME: WM_WINDOWPOSCHANGED invalidate all"));
1848 WinInvalidateRect(hwnd,NULL,TRUE);
1849 }
1850 else
1851 {
1852 HPS hps = WinGetPS(hwnd);
1853 RECTL frame,client,arcl[4];
1854
1855 WinQueryWindowRect(hwnd,&frame);
1856
1857 //top
1858 arcl[0].xLeft = 0;
1859 arcl[0].xRight = frame.xRight;
1860 arcl[0].yBottom = rect.yTop;
1861 arcl[0].yTop = frame.yTop;
1862 //right
1863 arcl[1].xLeft = rect.xRight;
1864 arcl[1].xRight = frame.xRight;
1865 arcl[1].yBottom = 0;
1866 arcl[1].yTop = frame.yTop;
1867 //left
1868 arcl[2].xLeft = 0;
1869 arcl[2].xRight = rect.xLeft;
1870 arcl[2].yBottom = 0;
1871 arcl[2].yTop = frame.yTop;
1872 //bottom
1873 arcl[3].xLeft = 0;
1874 arcl[3].xRight = frame.xRight;
1875 arcl[3].yBottom = 0;
1876 arcl[3].yTop = rect.yBottom;
1877
1878 HRGN hrgn = GpiCreateRegion(hps,4,(PRECTL)&arcl);
1879
1880 WinInvalidateRegion(hwnd,hrgn,FALSE);
1881 GpiDestroyRegion(hps,hrgn);
1882 WinReleasePS(hps);
1883 }
1884 }
1885 }
1886 else
1887 {
1888#endif //USE_CALCVALIDRECT
1889 if(win32wnd->CanReceiveSizeMsgs())
1890 win32wnd->MsgPosChanged((LPARAM)&wp);
1891#ifndef USE_CALCVALIDRECT
1892 }
1893#endif
1894 //PF This is the final step of PM restoration - should end up
1895 //in default handler.
1896 if (win32wnd->getOldStyle() & WS_MINIMIZE_W && pswp->fl & SWP_RESTORE)
1897 goto RunDefFrameWndProc;
1898
1899 //PF This is the final step of PM minimization - shoukd end up
1900 //in default handler
1901 if (win32wnd->getStyle() & WS_MINIMIZE_W && pswp->fl & SWP_MINIMIZE)
1902 goto RunDefFrameWndProc;
1903
1904PosChangedEnd:
1905 rc = (MRESULT)FALSE;
1906 break;
1907 }
1908
1909 case WM_CALCVALIDRECTS:
1910#ifdef USE_CALCVALIDRECT
1911 {
1912 PRECTL oldRect = (PRECTL)mp1, newRect = oldRect+1;
1913 PSWP pswp = (PSWP)mp2;
1914 SWP swpOld;
1915 WINDOWPOS wp;
1916 RECTL newClientRect, oldClientRect;
1917 ULONG nccalcret;
1918// UINT res = CVR_ALIGNLEFT | CVR_ALIGNTOP;
1919 UINT res = 0;
1920
1921 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1922
1923 //Get old position info
1924 WinQueryWindowPos(hwnd, &swpOld);
1925
1926 if(win32wnd->getParent()) {
1927 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1928 win32wnd->getParent()->getClientRectPtr()->left,
1929 win32wnd->getParent()->getClientRectPtr()->top,
1930 hwnd);
1931 }
1932 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), 0, 0, hwnd);
1933
1934 wp.hwnd = win32wnd->getWindowHandle();
1935 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1936 {
1937 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1938 if(wndAfter) {
1939 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1940 RELEASE_WNDOBJ(wndAfter);
1941 }
1942 else wp.hwndInsertAfter = HWND_TOP_W;
1943 }
1944
1945 //Get old client rectangle
1946 mapWin32ToOS2Rect(oldRect->yTop - oldRect->yBottom, win32wnd->getClientRectPtr(), (PRECTLOS2)&oldClientRect);
1947
1948 //Note: Also updates the new window rectangle
1949 nccalcret = win32wnd->MsgFormatFrame(&wp);
1950
1951 //Get new client rectangle
1952 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&newClientRect);
1953
1954 if(nccalcret == 0) {
1955 res = CVR_ALIGNTOP | CVR_ALIGNLEFT;
1956 }
1957 else {
1958 if(nccalcret & WVR_ALIGNTOP_W) {
1959 res |= CVR_ALIGNTOP;
1960 }
1961 else
1962 if(nccalcret & WVR_ALIGNBOTTOM_W) {
1963 res |= CVR_ALIGNBOTTOM;
1964 }
1965
1966 if(nccalcret & WVR_ALIGNLEFT_W) {
1967 res |= CVR_ALIGNLEFT;
1968 }
1969 else
1970 if(nccalcret & WVR_ALIGNRIGHT_W) {
1971 res |= CVR_ALIGNRIGHT;
1972 }
1973
1974 if(nccalcret & WVR_REDRAW_W) {//WVR_REDRAW_W = (WVR_HREDRAW | WVR_VREDRAW)
1975 res |= CVR_REDRAW;
1976 }
1977 else
1978 if(nccalcret & WVR_VALIDRECTS_W) {
1979 //TODO:
1980 //res = 0;
1981 }
1982 }
1983 if(win32wnd->IsMixMaxStateChanging()) {
1984 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1985 res |= CVR_REDRAW;
1986 }
1987 if(res == (CVR_ALIGNTOP|CVR_ALIGNLEFT)) {
1988 oldRect->xRight -= oldClientRect.xLeft;
1989 oldRect->yBottom += oldClientRect.yBottom;
1990 newRect->xRight -= newClientRect.xLeft;
1991 newRect->yBottom += newClientRect.yBottom;
1992 }
1993 rc = res;
1994 break;
1995 }
1996#else
1997 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1998 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
1999 break;
2000#endif
2001
2002 case WM_CALCFRAMERECT:
2003 dprintf(("PMFRAME:WM_CALCFRAMERECT %x", win32wnd->getWindowHandle()));
2004 rc = (MRESULT)TRUE;
2005 break;
2006
2007 case WM_QUERYCTLTYPE:
2008 // This is a frame window
2009 dprintf(("PMFRAME:WM_QUERYCTLTYPE %x", win32wnd->getWindowHandle()));
2010 rc = (MRESULT)CCT_FRAME;
2011 break;
2012
2013#ifdef DEBUG
2014 case WM_QUERYFOCUSCHAIN:
2015 dprintf2(("PMFRAME:WM_QUERYFOCUSCHAIN %x fsCmd %x (%s) parent %x", win32wnd->getWindowHandle(), SHORT1FROMMP(mp1), DbgPrintQFCFlags(SHORT1FROMMP(mp1)), (mp2) ? OS2ToWin32Handle((DWORD)mp2) : 0));
2016
2017 RestoreOS2TIB();
2018 rc = pfnFrameWndProc(hwnd, msg, mp1, mp2);
2019 SetWin32TIB();
2020 dprintf2(("PMFRAME:WM_QUERYFOCUSCHAIN %x fsCmd %x parent %x returned %x (%x)", win32wnd->getWindowHandle(), SHORT1FROMMP(mp1), (mp2) ? OS2ToWin32Handle((DWORD)mp2) : 0, (rc) ? OS2ToWin32Handle((DWORD)rc) : 0, rc));
2021 break;
2022// goto RunDefFrameWndProc;
2023#endif
2024
2025 case WM_FOCUSCHANGE:
2026 {
2027 HWND hwndFocus = (HWND)mp1;
2028 HWND hwndLoseFocus, hwndGainFocus;
2029 USHORT usSetFocus = SHORT1FROMMP(mp2);
2030 USHORT fsFocusChange = SHORT2FROMMP(mp2);
2031
2032 //Save window that gains focus so we can determine which
2033 //process we lose activation to
2034 hwndFocusChange = (HWND)mp1;
2035
2036 dprintf(("PMFRAME:WM_FOCUSCHANGE %x %x (%x) %x %x", win32wnd->getWindowHandle(), OS2ToWin32Handle(hwndFocus), hwndFocus, usSetFocus, fsFocusChange));
2037 goto RunDefFrameWndProc;
2038 }
2039
2040#ifdef DEBUG
2041 case WM_SETFOCUS:
2042 {
2043 dprintf(("PMFRAME: WM_SETFOCUS %x %x %d -> %x", win32wnd->getWindowHandle(), hwnd, mp2, mp1));
2044 goto RunDefFrameWndProc;
2045 }
2046#endif
2047
2048 case WM_ACTIVATE:
2049 {
2050 HWND hwndTitle;
2051 USHORT flags = WinQueryWindowUShort(hwnd,QWS_FLAGS);
2052
2053 dprintf(("PMFRAME: WM_ACTIVATE %x %x %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle((DWORD)mp2)));
2054 if (win32wnd->IsWindowCreated())
2055 {
2056 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
2057 if(fOS2Look) {
2058 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
2059 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, mp1, 0);
2060 }
2061 if(SHORT1FROMMP(mp1) == 0) {
2062 //deactivate
2063 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
2064 }
2065 PID pidThis, pidPartner, pidTemp;
2066 TID tidPartner;
2067 HENUM henum;
2068 HWND hwndEnum;
2069
2070 WinQueryWindowProcess(hwnd, &pidThis, NULL);
2071 WinQueryWindowProcess(hwndFocusChange, &pidPartner, &tidPartner);
2072
2073 if(pidThis != pidPartner) {
2074 //Gain or lose activation to window in other process
2075 //must send WM_ACTIVATEAPP to top-level windows
2076
2077 //Iterate over all child windows of the desktop
2078 henum = WinBeginEnumWindows(HWND_DESKTOP);
2079
2080 while(hwndEnum = WinGetNextWindow(henum))
2081 {
2082 WinQueryWindowProcess(hwndEnum, &pidTemp, NULL);
2083 if(pidTemp == pidThis)
2084 {
2085 SendMessageA(OS2ToWin32Handle(hwndEnum), WM_ACTIVATEAPP_W, (WPARAM)SHORT1FROMMP(mp1), (LPARAM)tidPartner);
2086 }
2087 }
2088 WinEndEnumWindows(henum);
2089 }
2090 if(SHORT1FROMMP(mp1)) {
2091 //activate
2092 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
2093 }
2094
2095 //CB: show owner behind the dialog
2096 if (win32wnd->IsModalDialog())
2097 {
2098 if(win32wnd->getOwner()) {
2099 Win32BaseWindow *topOwner = Win32BaseWindow::GetWindowFromHandle(win32wnd->getOwner()->GetTopParent());
2100
2101 if (topOwner) {
2102 WinSetWindowPos(topOwner->getOS2FrameWindowHandle(),hwnd,0,0,0,0,SWP_ZORDER);
2103 RELEASE_WNDOBJ(topOwner);
2104 }
2105 }
2106 }
2107 }
2108 else
2109 {
2110 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
2111 }
2112 rc = 0;
2113 break;
2114 }
2115
2116 case WM_ENABLE:
2117 dprintf(("PMFRAME: WM_ENABLE %x", hwnd));
2118 win32wnd->MsgEnable(SHORT1FROMMP(mp1));
2119 break;
2120
2121 case WM_SHOW:
2122 dprintf(("PMFRAME: WM_SHOW %x %d", hwnd, mp1));
2123 //show client window
2124 WinShowWindow(win32wnd->getOS2WindowHandle(), (BOOL)mp1);
2125 break;
2126
2127 case WM_QUERYTRACKINFO:
2128 {
2129 PTRACKINFO trackInfo = (PTRACKINFO)mp2;
2130
2131 dprintf(("PMFRAME:WM_QUERYTRACKINFO %x", win32wnd->getWindowHandle()));
2132 trackInfo->cxBorder = 4;
2133 trackInfo->cyBorder = 4;
2134 win32wnd->AdjustTrackInfo((PPOINT)&trackInfo->ptlMinTrackSize,(PPOINT)&trackInfo->ptlMaxTrackSize);
2135 rc = (MRESULT)TRUE;
2136 break;
2137 }
2138
2139 case WM_QUERYBORDERSIZE:
2140 {
2141 PWPOINT size = (PWPOINT)mp1;
2142
2143 dprintf(("PMFRAME:WM_QUERYBORDERSIZE %x", win32wnd->getWindowHandle()));
2144
2145 size->x = 0;
2146 size->y = 0;
2147 rc = (MRESULT)TRUE;
2148 break;
2149 }
2150
2151#ifdef DEBUG
2152 case WM_QUERYFRAMEINFO:
2153 dprintf(("PMFRAME:WM_QUERYFRAMEINFO %x", win32wnd->getWindowHandle()));
2154 goto RunDefFrameWndProc;
2155#endif
2156
2157 case WM_FORMATFRAME:
2158 dprintf(("PMFRAME:WM_FORMATFRAME %x", win32wnd->getWindowHandle()));
2159 break;
2160
2161 case WM_ADJUSTFRAMEPOS:
2162 {
2163 PSWP pswp = (PSWP)mp1;
2164
2165 dprintf(("PMFRAME:WM_ADJUSTFRAMEPOS %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
2166 //hack alert: the PM frame control changes the z-order of a child window
2167 // if it receives focus after a window has been destroyed
2168 // We can't let this happen as this messes up assumptions
2169 // elsewhere (e.g. GetNextDlgGroupItem)
2170 // By returning 0 here, we prevent the default frame handler
2171 // from messing things up. (one example is a group of radio buttons)
2172 //NOTE: We really need to get rid of frame & client windows for each
2173 // win32 window
2174 if(pswp->fl == SWP_FOCUSACTIVATE && win32wnd->isChild()) {
2175 rc = 0;
2176 break;
2177 }
2178 //hack alert: as we return zero as border size (check handler) we need
2179 //to do adjustments here as well or PM will calculate it for us and
2180 //result will be illegal. Btw we do not honour PM border size settings
2181 //and never will. I was unable to figure out why only X coordinate
2182 //is being broken but not Y as well.
2183
2184 if ((pswp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2185 {
2186 RECT rect;
2187 rect.left = rect.top = rect.right = rect.bottom = 0;
2188 win32wnd->AdjustMaximizedRect(&rect);
2189
2190 pswp->x += rect.left;
2191 }
2192 goto RunDefFrameWndProc;
2193 }
2194
2195#ifdef DEBUG
2196 case WM_OWNERPOSCHANGE:
2197 {
2198 PSWP pswp = (PSWP)mp1;
2199
2200 dprintf(("PMFRAME:WM_OWNERPOSCHANGE %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
2201 RestoreOS2TIB();
2202 rc = pfnFrameWndProc(hwnd, msg, mp1, mp2);
2203 SetWin32TIB();
2204 dprintf(("PMFRAME: DEF WM_OWNERPOSCHANGE %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
2205 break;
2206 }
2207#endif
2208
2209 case WM_MINMAXFRAME:
2210 {
2211 PSWP swp = (PSWP)mp1;
2212
2213 if (!win32wnd->IsWindowCreated()) goto RunDefWndProc;
2214
2215 dprintf(("PMFRAME:WM_MINMAXFRAME %x",hwnd));
2216 if ((swp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2217 {
2218 // MDI frame windows are not common PM windows so we need to
2219 // drop-out WHOLE chain of WM_X commands with SWP_MAXIMIZE flag
2220 // finally last WM_WINDOWPOSCHANGED will take care of maximization
2221
2222 if (win32wnd->getExStyle() & WS_EX_MDICHILD_W) {
2223 rc = 0;
2224 break;
2225 }
2226
2227 RECT rect;
2228 rect.left = rect.top = rect.right = rect.bottom = 0;
2229 win32wnd->AdjustMaximizedRect(&rect);
2230
2231 swp->x += rect.left;
2232 swp->cx += rect.right-rect.left;
2233 swp->y -= rect.bottom;
2234 swp->cy += rect.bottom-rect.top;
2235
2236 win32wnd->ShowWindow(SW_RESTORE_W);
2237 }
2238 else
2239 if ((swp->fl & SWP_MINIMIZE) == SWP_MINIMIZE)
2240 {
2241 win32wnd->setStyle((win32wnd->getStyle() & ~WS_MAXIMIZE_W) | WS_MINIMIZE_W);
2242 }
2243 else
2244 if ((swp->fl & SWP_RESTORE) == SWP_RESTORE)
2245 {
2246 win32wnd->setStyle(win32wnd->getStyle() & ~(WS_MINIMIZE_W | WS_MAXIMIZE_W));
2247 }
2248 goto RunDefWndProc;
2249 }
2250
2251#ifdef DEBUG
2252 case WM_UPDATEFRAME:
2253 dprintf(("PMFRAME:WM_UPDATEFRAME %x", win32wnd->getWindowHandle()));
2254 goto RunDefFrameWndProc;
2255#endif
2256
2257 case WM_TRACKFRAME:
2258 dprintf(("PMFRAME: WM_TRACKFRAME %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2259 if(fOS2Look) {//sent by titlebar control
2260 Frame_SysCommandSizeMove(win32wnd, SC_MOVE_W+HTCAPTION_W);
2261 }
2262 rc = 0;
2263 break;
2264
2265 case WM_SYSCOMMAND:
2266 dprintf(("PMFRAME: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2267 if (fOS2Look == OS2_APPEARANCE_SYSMENU && mp1 == (MPARAM)OSSC_SYSMENU)
2268 goto RunDefFrameWndProc;
2269
2270 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
2271 RELEASE_WNDOBJ(win32wnd);
2272 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
2273 }
2274 if(win32wnd)
2275 win32wnd->DispatchMsgA(pWinMsg);
2276 break;
2277
2278 case WM_IMEREQUEST:
2279 case WM_IMECONTROL:
2280 case WM_IMENOTIFY:
2281 if( pWinMsg->message )
2282 {
2283 dprintf(("Frame window received IME message"));
2284 win32wnd->DispatchMsgA( pWinMsg );
2285
2286 if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
2287 ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
2288 {
2289 MSG m;
2290
2291 m.message = WM_IME_NOTIFY_W;
2292 m.wParam = IMN_SETCONVERSIONMODE_W;
2293 m.lParam = 0;
2294
2295 win32wnd->DispatchMsgA( &m );
2296 }
2297 }
2298 else
2299 goto RunDefWndProc;
2300 break;
2301
2302#ifdef DEBUG
2303 case WM_DDE_INITIATE:
2304 case WM_DDE_INITIATEACK:
2305 case WM_DDE_REQUEST:
2306 case WM_DDE_ACK:
2307 case WM_DDE_DATA:
2308 case WM_DDE_ADVISE:
2309 case WM_DDE_UNADVISE:
2310 case WM_DDE_POKE:
2311 case WM_DDE_EXECUTE:
2312 case WM_DDE_TERMINATE:
2313 dprintf(("PMFRAME: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
2314 break;
2315#endif
2316
2317 default:
2318 goto RunDefFrameWndProc;
2319 }
2320 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2321 RestoreOS2TIB();
2322 ODIN_UnsetExceptionHandler(&exceptRegRec);
2323
2324#ifdef DEBUG
2325 dbg_ThreadPopCall();
2326#endif
2327 return (MRESULT)rc;
2328
2329RunDefFrameWndProc:
2330 dprintf2(("RunDefFrameWndProc"));
2331 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2332 RestoreOS2TIB();
2333 ODIN_UnsetExceptionHandler(&exceptRegRec);
2334
2335#ifdef DEBUG
2336 dbg_ThreadPopCall();
2337#endif
2338 return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2339
2340RunDefWndProc:
2341 dprintf2(("RunDefWndProc"));
2342 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2343 RestoreOS2TIB();
2344 ODIN_UnsetExceptionHandler(&exceptRegRec);
2345
2346 //calling WinDefWindowProc here breaks Opera hotlist window (WM_ADJUSTWINDOWPOS)
2347// return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2348
2349#ifdef DEBUG
2350 dbg_ThreadPopCall();
2351#endif
2352 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2353}
2354//******************************************************************************
2355//******************************************************************************
2356MRESULT EXPENTRY Win32FakeWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2357{
2358 PFNWP pfnOldWindowProc;
2359 Win32BaseWindow *win32wnd, *win32wndchild;
2360 TEB *teb;
2361 MRESULT rc = 0;
2362 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
2363
2364 //Restore our FS selector
2365 SetWin32TIB();
2366
2367 win32wnd = Win32FakeWindow::GetWindowFromOS2Handle(hwnd);
2368 if(win32wnd == NULL) {
2369 DebugInt3();
2370 goto RunDefWndProc;
2371 }
2372
2373 pfnOldWindowProc = (PFNWP)win32wnd->getOldPMWindowProc();
2374 if(pfnOldWindowProc == NULL) {
2375 DebugInt3();
2376 goto RunDefWndProc;
2377 }
2378
2379 RestoreOS2TIB();
2380 rc = pfnOldWindowProc(hwnd, msg, mp1, mp2);
2381
2382 ODIN_SetExceptionHandler(&exceptRegRec);
2383 SetWin32TIB();
2384 switch(msg) {
2385 case WM_WINDOWPOSCHANGED:
2386 {
2387 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
2388 SWP swpOld = *(pswp + 1);
2389 WINDOWPOS wp;
2390
2391 if(win32wnd->getParent()) {
2392 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
2393 hwnd);
2394 }
2395 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
2396
2397 win32wnd->SetWindowPos(wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
2398 break;
2399 }
2400
2401 }
2402 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2403 RestoreOS2TIB();
2404 ODIN_UnsetExceptionHandler(&exceptRegRec);
2405 return rc;
2406
2407RunDefWndProc:
2408 RestoreOS2TIB();
2409 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2410}
2411//******************************************************************************
2412// PMWinSubclassFakeWindow
2413//
2414// Subclass a fake window (converted PM window)
2415//
2416// Parameters
2417//
2418// HWND hwndOS2 - PM handle of fake window
2419//
2420// Returns
2421// NULL - Failure
2422// else - Old PM window procedure
2423//
2424//******************************************************************************
2425PVOID PMWinSubclassFakeWindow(HWND hwndOS2)
2426{
2427 return WinSubclassWindow(hwndOS2, Win32FakeWindowProc);
2428}
2429//******************************************************************************
2430//******************************************************************************
2431void FrameSetFocus(HWND hwnd)
2432{
2433 HWND hwndFocusSave = WinQueryWindowULong(hwnd, QWL_HWNDFOCUSSAVE);
2434 if(!WinIsWindow(hab, hwndFocusSave)) {
2435 hwndFocusSave = WinWindowFromID(hwnd, FID_CLIENT);
2436 WinSetWindowULong(hwnd, QWL_HWNDFOCUSSAVE, hwndFocusSave);
2437 }
2438 dprintf(("FrameSetFocus: hwndFocusSave %x %x", OS2ToWin32Handle(hwndFocusSave), hwndFocusSave));
2439 dprintf(("FrameSetFocus: cur focus=%x (%x) cur active=%x (%x)\n",
2440 WinQueryFocus(HWND_DESKTOP), OS2ToWin32Handle(WinQueryFocus(HWND_DESKTOP)),
2441 WinQueryActiveWindow(HWND_DESKTOP), OS2ToWin32Handle(WinQueryActiveWindow(HWND_DESKTOP))));
2442 WinSetFocus(HWND_DESKTOP, hwndFocusSave);
2443
2444 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
2445 ulFrameFlags &= ~FF_NOACTIVATESWP;
2446 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags);
2447}
2448//******************************************************************************
2449//******************************************************************************
2450void FrameReplaceMenuItem(HWND hwndMenu, ULONG nIndex, ULONG idOld, ULONG idNew,
2451 HBITMAP hbmNew)
2452{
2453 MENUITEM mi;
2454
2455 if (!hwndMenu)
2456 return;
2457
2458 WinEnableWindowUpdate(hwndMenu, FALSE);
2459
2460 if (WinSendMsg(hwndMenu, MM_QUERYITEM, MPFROM2SHORT(idOld, TRUE), MPFROMP(&mi)))
2461 {
2462 WinSendMsg(hwndMenu, MM_REMOVEITEM, (MPARAM)idOld, 0);
2463 mi.afStyle = MIS_BITMAP | MIS_SYSCOMMAND;
2464 mi.afAttribute = 0;
2465 mi.hwndSubMenu = 0;
2466 mi.id = idNew;
2467 mi.hItem = (ULONG)hbmNew;
2468 WinSendMsg(hwndMenu, MM_INSERTITEM, (MPARAM)&mi, 0);
2469 }
2470 else
2471 dprintf(("WARNING: FrameReplaceMenuItem control %x not found",idOld));
2472
2473 WinEnableWindowUpdate(hwndMenu, TRUE);
2474
2475 WinInvalidateRect(hwndMenu, NULL, TRUE);
2476}
2477//******************************************************************************
2478//******************************************************************************
2479void RecalcVisibleRegion(Win32BaseWindow *win32wnd)
2480{
2481 //Workaround for PM/GPI bug when moving/sizing a window with open DCs
2482 //
2483 //Windows applictions often get a DC and keep it open for the duration
2484 //of the application. When the DC's window is moved (full window dragging on)
2485 //PM/GPI doesn't seem to update the DC properly/in time.
2486 //This can result is visible distortions on the screen.
2487
2488 //We need to reset our DC (transformation & y-inversion) (#945)
2489 //Debugging showed that querying the visible region of a DC will cure
2490 //this problem (GPI probably recalculates the visible region). (#334)
2491
2492 int nrdcs = 0;
2493 HDC hdcWindow[MAX_OPENDCS];
2494
2495 if(win32wnd->queryOpenDCs(hdcWindow, MAX_OPENDCS, &nrdcs))
2496 {
2497 for(int i=0;i<nrdcs;i++)
2498 {
2499 dprintf(("Recalc visible region of DC %x for window %x", hdcWindow[i], win32wnd->getWindowHandle()));
2500
2501 pDCData pHps = (pDCData)GpiQueryDCData (hdcWindow[i]);
2502
2503 if(pHps) setPageXForm (win32wnd, pHps);
2504 else DebugInt3();
2505 }
2506 }
2507 //Workaround END
2508}
2509//******************************************************************************
2510//******************************************************************************
2511static char *PMDragExtractFiles(PDRAGINFO pDragInfo, ULONG *pcItems, ULONG *pulBytes)
2512{
2513 PDRAGITEM pDragItem;
2514 int i, cItems;
2515 BOOL ret;
2516 char szFileName[CCHMAXPATH];
2517 char szContainerName[CCHMAXPATH];
2518 ULONG ulBytes;
2519 char *pszCurFile = NULL;
2520
2521 /* Get access to the DRAGINFO data structure */
2522 if(!DrgAccessDraginfo(pDragInfo)) {
2523 return NULL;
2524 }
2525
2526 cItems = DrgQueryDragitemCount(pDragInfo);
2527
2528 //compute memory required to hold all filenames
2529 int bufsize = 0;
2530 for (i = 0; i < cItems; i++) {
2531 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2532
2533 bufsize += DrgQueryStrNameLen(pDragItem->hstrContainerName) + DrgQueryStrNameLen(pDragItem->hstrSourceName);
2534 bufsize++; //0 terminator
2535 bufsize++; //+ potential missing backslash
2536 }
2537 bufsize++; //extra 0 terminator
2538 char *pszFiles = (char *)malloc(bufsize);
2539 if(pszFiles == NULL) {
2540 dprintf(("Out of memory!!"));
2541 DebugInt3();
2542 goto failure;
2543 }
2544 memset(pszFiles, 0, bufsize);
2545
2546 pszCurFile = pszFiles;
2547
2548 //copy all filenames
2549 for (i = 0; i < cItems; i++) {
2550 char *pszTemp = pszCurFile;
2551
2552 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2553
2554 ulBytes = DrgQueryStrNameLen(pDragItem->hstrContainerName);
2555 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2556 ulBytes, pszCurFile);
2557 if(pszCurFile[ulBytes-1] != '\\') {
2558 pszCurFile[ulBytes] = '\\';
2559 pszCurFile++;
2560 }
2561 pszCurFile += ulBytes;
2562
2563 ulBytes = DrgQueryStrNameLen(pDragItem->hstrSourceName);
2564 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2565 ulBytes+1, pszCurFile);
2566 pszCurFile += ulBytes + 1; //+ terminator
2567
2568 dprintf(("dropped file %s", pszTemp));
2569 }
2570
2571 /* Release the draginfo data structure */
2572 DrgFreeDraginfo(pDragInfo);
2573
2574 *pulBytes = bufsize;
2575 *pcItems = cItems;
2576
2577 return pszFiles;
2578
2579failure:
2580 /* Release the draginfo data structure */
2581 DrgFreeDraginfo(pDragInfo);
2582 if(pszFiles) {
2583 free(pszFiles);
2584 }
2585 return NULL;
2586}
2587//******************************************************************************
2588//******************************************************************************
2589static BOOL PMDragValidate(PDRAGINFO pDragInfo)
2590{
2591 PDRAGITEM pDragItem;
2592 ULONG ulBytes;
2593 int i, cItems;
2594 BOOL ret;
2595 char szFileName[CCHMAXPATH];
2596 char szContainerName[CCHMAXPATH];
2597 USHORT usOp = DO_MOVE;
2598
2599 /* Get access to the DRAGINFO data structure */
2600 if(!DrgAccessDraginfo(pDragInfo)) {
2601 return FALSE;
2602 }
2603
2604 /* Can we accept this drop? */
2605 switch (pDragInfo->usOperation) {
2606 /* Return DOR_NODROPOP if current operation */
2607 /* is link or unknown */
2608 case DO_LINK:
2609 case DO_COPY:
2610 case DO_UNKNOWN:
2611 goto failure;
2612
2613 /* Our default operation is Move */
2614 case DO_MOVE:
2615 case DO_DEFAULT:
2616 pDragItem = DrgQueryDragitemPtr(pDragInfo, 0);
2617 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2618 sizeof(szContainerName),
2619 szContainerName);
2620 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2621 sizeof(szFileName),
2622 szFileName);
2623 if (!ulBytes) {
2624 goto failure;
2625 }
2626
2627 dprintf(("dropped file %s%s", szContainerName, szFileName));
2628 break;
2629 }
2630
2631 cItems = DrgQueryDragitemCount(pDragInfo);
2632
2633 /* Now, we need to look at each item in turn */
2634 for (i = 0; i < cItems; i++) {
2635 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2636
2637 /* Make sure we can move for a Move request */
2638 if (!((pDragItem->fsSupportedOps & DO_MOVEABLE) &&
2639 (usOp == (USHORT)DO_MOVE)))
2640 {
2641 dprintf(("item %d not accepted", i));
2642 goto failure;
2643 }
2644 }
2645 /* Release the draginfo data structure */
2646 DrgFreeDraginfo(pDragInfo);
2647 return TRUE;
2648
2649failure:
2650 DrgFreeDraginfo(pDragInfo);
2651 return FALSE;
2652}
2653
2654//******************************************************************************
2655// Override std class names we use in Odin (necessary for keyboard hook)
2656//******************************************************************************
2657void WIN32API SetCustomStdClassName(LPSTR pszStdClassName)
2658{
2659 strcpy(WIN32_STDCLASS, pszStdClassName);
2660}
2661//******************************************************************************
2662//******************************************************************************
2663char *WIN32API QueryCustomStdClassName()
2664{
2665 return WIN32_STDCLASS;
2666}
2667//******************************************************************************
2668//******************************************************************************
2669
2670#ifdef DEBUG_LOGGING
2671static char *DbgGetStringSWPFlags(ULONG flags)
2672{
2673 static char szSWPFlags[512];
2674
2675 szSWPFlags[0] = 0;
2676
2677 if(flags & SWP_SIZE) {
2678 strcat(szSWPFlags, "SWP_SIZE ");
2679 }
2680 if(flags & SWP_MOVE) {
2681 strcat(szSWPFlags, "SWP_MOVE ");
2682 }
2683 if(flags & SWP_ZORDER) {
2684 strcat(szSWPFlags, "SWP_ZORDER ");
2685 }
2686 if(flags & SWP_SHOW) {
2687 strcat(szSWPFlags, "SWP_SHOW ");
2688 }
2689 if(flags & SWP_HIDE) {
2690 strcat(szSWPFlags, "SWP_HIDE ");
2691 }
2692 if(flags & SWP_NOREDRAW) {
2693 strcat(szSWPFlags, "SWP_NOREDRAW ");
2694 }
2695 if(flags & SWP_NOADJUST) {
2696 strcat(szSWPFlags, "SWP_NOADJUST ");
2697 }
2698 if(flags & SWP_ACTIVATE) {
2699 strcat(szSWPFlags, "SWP_ACTIVATE ");
2700 }
2701 if(flags & SWP_DEACTIVATE) {
2702 strcat(szSWPFlags, "SWP_DEACTIVATE ");
2703 }
2704 if(flags & SWP_EXTSTATECHANGE) {
2705 strcat(szSWPFlags, "SWP_EXTSTATECHANGE ");
2706 }
2707 if(flags & SWP_MINIMIZE) {
2708 strcat(szSWPFlags, "SWP_MINIMIZE ");
2709 }
2710 if(flags & SWP_MAXIMIZE) {
2711 strcat(szSWPFlags, "SWP_MAXIMIZE ");
2712 }
2713 if(flags & SWP_RESTORE) {
2714 strcat(szSWPFlags, "SWP_RESTORE ");
2715 }
2716 if(flags & SWP_FOCUSACTIVATE) {
2717 strcat(szSWPFlags, "SWP_FOCUSACTIVATE ");
2718 }
2719 if(flags & SWP_FOCUSDEACTIVATE) {
2720 strcat(szSWPFlags, "SWP_FOCUSDEACTIVATE ");
2721 }
2722 if(flags & SWP_NOAUTOCLOSE) {
2723 strcat(szSWPFlags, "SWP_NOAUTOCLOSE ");
2724 }
2725 return szSWPFlags;
2726}
2727static char *DbgPrintQFCFlags(ULONG flags)
2728{
2729 static char szQFCFlags[64];
2730
2731 szQFCFlags[0] = 0;
2732
2733 if(flags & QFC_NEXTINCHAIN) {
2734 strcat(szQFCFlags, "QFC_NEXTINCHAIN");
2735 }
2736 else
2737 if(flags & QFC_ACTIVE) {
2738 strcat(szQFCFlags, "QFC_ACTIVE");
2739 }
2740 else
2741 if(flags & QFC_FRAME) {
2742 strcat(szQFCFlags, "QFC_FRAME");
2743 }
2744 else
2745 if(flags & QFC_SELECTACTIVE) {
2746 strcat(szQFCFlags, "QFC_SELECTACTIVE");
2747 }
2748 else
2749 if(flags & QFC_PARTOFCHAIN) {
2750 strcat(szQFCFlags, "QFC_PARTOFCHAIN");
2751 }
2752
2753 return szQFCFlags;
2754}
2755#endif
2756
Note: See TracBrowser for help on using the repository browser.