source: trunk/src/user32/dc.cpp@ 1267

Last change on this file since 1267 was 1267, checked in by phaller, 26 years ago

Fix: parameter checking in RedrawWindow and temp fix for MsgWaitForMultipleObjects

File size: 41.9 KB
Line 
1/* $Id: dc.cpp,v 1.12 1999-10-13 16:02:41 phaller Exp $ */
2
3/*
4 * DC functions for USER32
5 *
6 * Project Odin Software License can be found in LICENSE.TXT
7 *
8 */
9
10/*****************************************************************************
11 * Includes *
12 *****************************************************************************/
13
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2sel.h>
17
18#define INCL_WIN
19#define INCL_GPI
20#define INCL_GREALL
21#define INCL_DEV
22#include <os2.h>
23#include <pmddi.h>
24#include <stdlib.h>
25#include "win32type.h"
26#include <winconst.h>
27#include <wprocess.h>
28#include <misc.h>
29#include <win32wbase.h>
30#include <math.h>
31#include <limits.h>
32#include "oslibwin.h"
33#include "dcdata.h"
34
35
36ODINDEBUGCHANNEL(USER32-DC)
37
38
39#undef SEVERITY_ERROR
40#include <winerror.h>
41
42#ifndef OPEN32API
43#define OPEN32API _System
44#endif
45
46/*********************/
47typedef struct
48{
49 HDC hdc;
50 BOOL fErase;
51 RECT rcPaint;
52 BOOL fRestore;
53 BOOL IncUpdate;
54 BYTE rgbReserved[32];
55} PAINTSTRUCT_W, *PPAINTSTRUCT_W, *LPPAINTSTRUCT_W;
56
57#define PS_SOLID_W 0x00000000
58#define PS_DASH_W 0x00000001
59#define PS_DOT_W 0x00000002
60#define PS_DASHDOT_W 0x00000003
61#define PS_DASHDOTDOT_W 0x00000004
62#define PS_NULL_W 0x00000005
63#define PS_INSIDEFRAME_W 0x00000006
64#define PS_USERSTYLE_W 0x00000007
65#define PS_ALTERNATE_W 0x00000008
66#define PS_STYLE_MASK_W 0x0000000f
67
68typedef struct
69{
70 UINT lopnStyle;
71 POINT lopnWidth;
72 ULONG lopnColor;
73} LOGPEN_W, *LPLOGPEN_W;
74
75typedef struct tagEXTLOGPEN
76{
77 DWORD elpPenStyle;
78 DWORD elpWidth;
79 DWORD elpBrushStyle;
80 DWORD elpColor;
81 DWORD elpNumEntries;
82 DWORD elpStyleEntry[1];
83} EXTLOGPEN_W, *PEXTLOGPEN_W, *NPEXTLOGPEN_W, *LPEXTLOGPEN_W;
84
85typedef struct
86{
87 UINT lbStyle;
88 ULONG lbColor;
89 INT lbHatch;
90} LOGBRUSH_W, *LPLOGBRUSH_W;
91
92typedef struct _penobject
93{
94 ULONG filler[9];
95 union {
96 struct {
97 PEXTLOGPEN_W pExtLogPen;
98 LOGBRUSH_W logbrush;
99 LOGPEN_W logpen;
100 } ExtPen;
101 struct {
102 LOGPEN_W logpen;
103 } Pen;
104 };
105} tPenObject, *pPenObject;
106
107/* DC Graphics Mode */
108#define GM_COMPATIBLE_W 1
109#define GM_ADVANCED_W 2
110
111#define DCX_WINDOW_W 0x00000001L
112#define DCX_CACHE_W 0x00000002L
113#define DCX_NORESETATTRS_W 0x00000004L
114#define DCX_CLIPCHILDREN_W 0x00000008L
115#define DCX_CLIPSIBLINGS_W 0x00000010L
116#define DCX_PARENTCLIP_W 0x00000020L
117#define DCX_EXCLUDERGN_W 0x00000040L
118#define DCX_INTERSECTRGN_W 0x00000080L
119#define DCX_EXCLUDEUPDATE_W 0x00000100L
120#define DCX_INTERSECTUPDATE_W 0x00000200L
121#define DCX_LOCKWINDOWUPDATE_W 0x00000400L
122#define DCX_VALIDATE_W 0x00200000L
123
124#define RDW_INVALIDATE_W 0x0001
125#define RDW_INTERNALPAINT_W 0x0002
126#define RDW_ERASE_W 0x0004
127#define RDW_VALIDATE_W 0x0008
128#define RDW_NOINTERNALPAINT_W 0x0010
129#define RDW_NOERASE_W 0x0020
130#define RDW_NOCHILDREN_W 0x0040
131#define RDW_ALLCHILDREN_W 0x0080
132#define RDW_UPDATENOW_W 0x0100
133#define RDW_ERASENOW_W 0x0200
134#define RDW_FRAME_W 0x0400
135#define RDW_NOFRAME_W 0x0800
136
137typedef struct _RGNDATAHEADER_W {
138 DWORD dwSize;
139 DWORD iType;
140 DWORD nCount;
141 DWORD nRgnSize;
142 RECT rcBound;
143} RGNDATAHEADER_W, *LPRGNDATAHEADER_W;
144
145typedef struct _RGNDATA_W {
146 RGNDATAHEADER_W rdh;
147 char Buffer[1];
148} RGNDATA_W , *PRGNDATA_W , *LPRGNDATA_W ;
149
150
151/* Xform FLAGS */
152#define MWT_IDENTITY_W 1
153#define MWT_LEFTMULTIPLY_W 2
154#define MWT_RIGHTMULTIPLY_W 3
155
156/* Mapping Modes */
157#define MM_TEXT_W 1
158#define MM_LOMETRIC_W 2
159#define MM_HIMETRIC_W 3
160#define MM_LOENGLISH_W 4
161#define MM_HIENGLISH_W 5
162#define MM_TWIPS_W 6
163#define MM_ISOTROPIC_W 7
164#define MM_ANISOTROPIC_W 8
165
166#define RGN_OR_W 2
167
168/* Window scrolling */
169#define SW_SCROLLCHILDREN_W 0x0001
170#define SW_INVALIDATE_W 0x0002
171#define SW_ERASE_W 0x0004
172
173/*********************/
174
175BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight);
176LONG APIENTRY GpiQueryYInversion (HPS hps);
177PVOID APIENTRY GpiAllocateDCData (HPS GpiH, ULONG size);
178PVOID APIENTRY GpiQueryDCData (HPS hps);
179HDC OPEN32API HPSToHDC (HWND hwnd, HPS hps, HDC hdc, PVOID);
180void OPEN32API DeleteHDC (HDC hdc);
181BOOL OPEN32API _O32_EndPaint (HWND hwnd, const PAINTSTRUCT_W *lpps);
182int OPEN32API _O32_GetUpdateRgn (HWND hwnd, HRGN hrgn, BOOL erase);
183ULONG OPEN32API _O32_GetRegionData (HRGN hrgn, ULONG count, PRGNDATA_W pData);
184BOOL OPEN32API _O32_DeleteObject (LHANDLE hgdiobj);
185int OPEN32API _O32_ReleaseDC (HWND hwnd, HDC hdc);
186VOID OPEN32API _O32_SetLastError( DWORD );
187BOOL OPEN32API _O32_SetRectRgn (HRGN dest, int left, int top, int right, int bottom);
188int OPEN32API _O32_CombineRgn (HRGN dest, HRGN src1, HRGN src2, int mode);
189HRGN OPEN32API _O32_CreateRectRgn (int left, int top, int right, int bottom);
190
191#ifndef DEVESC_SETPS
192 #define DEVESC_SETPS 49149L
193#endif
194
195#define FLOAT_TO_FIXED(x) ((FIXED) ((x) * 65536.0))
196#define MICRO_HPS_TO_HDC(x) ((x) & 0xFFFFFFFE)
197
198#define PMRECT_FROM_WINRECT( pmRect, winRect ) \
199{ \
200 (pmRect).xLeft = (winRect).left; \
201 (pmRect).yBottom = (winRect).bottom; \
202 (pmRect).xRight = (winRect).right; \
203 (pmRect).yTop = (winRect).top; \
204}
205
206#define WINRECT_FROM_PMRECT( winRect, pmRect ) \
207{ \
208 (winRect).left = (pmRect).xLeft; \
209 (winRect).top = (pmRect).yTop; \
210 (winRect).right = (pmRect).xRight; \
211 (winRect).bottom = (pmRect).yBottom; \
212}
213
214#define MEM_HPS_MAX 768
215
216const XFORM_W XFORMIdentity = { 1.0, 0.0, 0.0, 1.0, 0, 0 };
217const MATRIXLF matrixlfIdentity = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0};
218
219BOOL setPageXForm(Win32BaseWindow *wnd, pDCData pHps);
220BOOL changePageXForm(Win32BaseWindow *wnd, pDCData pHps, PPOINTL pValue, int x, int y, PPOINTL pPrev);
221LONG clientHeight(Win32BaseWindow *wnd, HWND hwnd, pDCData pHps);
222
223void TestWideLine (pDCData pHps)
224{
225 const LOGPEN_W *pLogPen;
226
227 pHps->isWideLine = FALSE;
228 pLogPen = pHps->penIsExtPen ?
229 &(pHps->lastPenObject->ExtPen.logpen) :
230 &(pHps->lastPenObject->Pen.logpen);
231
232 if (((pLogPen->lopnStyle & PS_STYLE_MASK_W) != PS_NULL_W) &&
233 (pLogPen->lopnWidth.x > 0))
234 {
235 POINTL aptl[2] = { 0, 0, pLogPen->lopnWidth.x, pLogPen->lopnWidth.x };
236
237 GpiConvert(pHps->hps, CVTC_WORLD, CVTC_DEVICE, 2, aptl);
238
239 ULONG dx = abs(aptl[0].x - aptl[1].x);
240 ULONG dy = abs(aptl[0].y - aptl[1].y);
241
242 pHps->isWideLine = (dx > 1) || (dy > 1);
243 }
244}
245
246void Calculate1PixelDelta(pDCData pHps)
247{
248 POINTL aptl[2] = {0, 0, 1, 1};
249
250 GpiConvert(pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, aptl);
251 pHps->worldYDeltaFor1Pixel = (int)(aptl[1].y - aptl[0].y);
252 pHps->worldXDeltaFor1Pixel = (int)(aptl[1].x - aptl[0].x); // 171182
253}
254
255//******************************************************************************
256
257int setMapMode(Win32BaseWindow *wnd, pDCData pHps, int mode)
258{
259 int prevMode = 0;
260 ULONG flOptions;
261
262 switch (mode)
263 {
264 case MM_HIENGLISH_W : flOptions = PU_HIENGLISH; break;
265 case MM_LOENGLISH_W : flOptions = PU_LOENGLISH; break;
266 case MM_HIMETRIC_W : flOptions = PU_HIMETRIC ; break;
267 case MM_LOMETRIC_W : flOptions = PU_LOMETRIC ; break;
268 case MM_TEXT_W : flOptions = PU_PELS ; break;
269 case MM_TWIPS_W : flOptions = PU_TWIPS ; break;
270 case MM_ANISOTROPIC_W: flOptions = PU_PELS ; break;
271 case MM_ISOTROPIC_W : flOptions = PU_LOMETRIC ; break;
272 default:
273 _O32_SetLastError (ERROR_INVALID_PARAMETER);
274 return FALSE;
275 }
276
277 prevMode = pHps->MapMode; /* store previous mode */
278 pHps->MapMode = mode;
279
280 if (mode == MM_TEXT_W)
281 {
282 pHps->viewportXExt =
283 pHps->viewportYExt = 1.0;
284 pHps->windowExt.cx =
285 pHps->windowExt.cy = 1;
286 }
287 else if (mode != MM_ANISOTROPIC_W)
288 {
289 RECTL rectl;
290 SIZEL sizel;
291 ULONG data[3];
292
293 data[0] = flOptions;
294 data[1] = data[2] = 0;
295
296 if (DevEscape(pHps->hdc ? pHps->hdc : pHps->hps, DEVESC_SETPS, 12, (PBYTE)data, 0, 0) == DEVESC_ERROR)
297 {
298 _O32_SetLastError (ERROR_INVALID_PARAMETER);
299 return 0;
300 }
301
302 GpiQueryPageViewport(pHps->hps, &rectl);
303 pHps->viewportXExt = (double)rectl.xRight;
304 pHps->viewportYExt = -(double)rectl.yTop;
305
306 GreGetPageUnits(pHps->hdc? pHps->hdc : pHps->hps, &sizel);
307 pHps->windowExt.cx = sizel.cx;
308 pHps->windowExt.cy = sizel.cy;
309
310 data[0] = PU_PELS;
311 DevEscape(pHps->hdc ? pHps->hdc : pHps->hps, DEVESC_SETPS, 12, (PBYTE)data, 0, 0);
312 }
313
314 if (((prevMode != MM_ISOTROPIC_W) && (prevMode != MM_ANISOTROPIC_W)) &&
315 ((mode == MM_ISOTROPIC_W) || (mode == MM_ANISOTROPIC_W)))
316 {
317 if (pHps->lWndXExtSave && pHps->lWndYExtSave)
318 {
319 changePageXForm (wnd, pHps, (PPOINTL)&pHps->windowExt,
320 pHps->lWndXExtSave, pHps->lWndYExtSave, NULL );
321 pHps->lWndXExtSave = pHps->lWndYExtSave = 0;
322 }
323 if (pHps->lVwpXExtSave && pHps->lVwpYExtSave)
324 {
325 changePageXForm (wnd, pHps, NULL,
326 pHps->lVwpXExtSave, pHps->lVwpYExtSave, NULL );
327 pHps->lVwpXExtSave = pHps->lVwpYExtSave = 0;
328 }
329 }
330
331 setPageXForm(wnd, pHps);
332
333 return prevMode;
334}
335
336BOOL setPageXForm(Win32BaseWindow *wnd, pDCData pHps)
337{
338 MATRIXLF mlf;
339 BOOL rc = TRUE;
340
341 pHps->height = clientHeight(wnd, 0, pHps) - 1;
342
343 double xScale = pHps->viewportXExt / (double)pHps->windowExt.cx;
344 double yScale = pHps->viewportYExt / (double)pHps->windowExt.cy;
345
346 mlf.fxM11 = FLOAT_TO_FIXED(xScale);
347 mlf.fxM12 = 0;
348 mlf.lM13 = 0;
349 mlf.fxM21 = 0;
350 mlf.fxM22 = FLOAT_TO_FIXED(yScale);
351 mlf.lM23 = 0;
352 mlf.lM31 = pHps->viewportOrg.x - (LONG)(pHps->windowOrg.x * xScale);
353 mlf.lM32 = pHps->viewportOrg.y - (LONG)(pHps->windowOrg.y * yScale);
354
355 pHps->isLeftLeft = mlf.fxM11 >= 0;
356 pHps->isTopTop = mlf.fxM22 >= 0;
357
358 BOOL bEnableYInversion = FALSE;
359 if ((mlf.fxM22 > 0) ||
360 ((pHps->graphicsMode == GM_ADVANCED_W) &&
361 ((pHps->MapMode == MM_ANISOTROPIC_W) ||
362 (pHps->MapMode == MM_ISOTROPIC_W))))
363 {
364 bEnableYInversion = TRUE;
365 }
366 else
367 {
368 bEnableYInversion = FALSE;
369 mlf.lM32 = pHps->HPStoHDCInversionHeight + pHps->height - mlf.lM32;
370 mlf.fxM22 = -mlf.fxM22;
371 }
372
373 if (!pHps->isMetaPS)
374// if ((!pHps->isMetaPS) ||
375// (pHps->pMetaFileObject && pHps->pMetaFileObject->isEnhanced()))
376 rc = GpiSetDefaultViewMatrix(pHps->hps, 8, &mlf, TRANSFORM_REPLACE);
377
378 if (bEnableYInversion)
379 GpiEnableYInversion(pHps->hps, pHps->height + pHps->HPStoHDCInversionHeight);
380 else
381 GpiEnableYInversion(pHps->hps, 0);
382
383 TestWideLine(pHps);
384 Calculate1PixelDelta(pHps);
385 return rc;
386}
387
388BOOL changePageXForm(Win32BaseWindow *wnd, pDCData pHps, PPOINTL pValue, int x, int y, PPOINTL pPrev)
389{
390 BOOL result = FALSE;
391
392 if (pValue)
393 {
394 if (pPrev)
395 *pPrev = *pValue;
396
397 if ((pValue->x == x) && (pValue->y == y)) {
398 return TRUE;
399 }
400 pValue->x = x;
401 pValue->y = y;
402 }
403 else
404 {
405 if (pPrev)
406 {
407 pPrev->x = (int)pHps->viewportXExt;
408 pPrev->y = (int)pHps->viewportYExt;
409 }
410 pHps->viewportXExt = (double)x;
411 pHps->viewportYExt = (double)y;
412 }
413
414 if (pHps->MapMode == MM_ISOTROPIC_W)
415 {
416 double xExt = fabs(pHps->viewportXExt);
417 double yExt = fabs(pHps->viewportYExt);
418 double sf = fabs((double)pHps->windowExt.cx / pHps->windowExt.cy);
419
420 if (xExt > (yExt * sf))
421 {
422 xExt = yExt * sf;
423
424 if ((double)LONG_MAX <= xExt) return (result);
425
426 if (pHps->viewportXExt < 0.0)
427 pHps->viewportXExt = -xExt;
428 else
429 pHps->viewportXExt = xExt;
430 }
431 else
432 {
433 yExt = xExt / sf;
434
435 if ((double)LONG_MAX <= yExt) return (result);
436
437 if (pHps->viewportYExt < 0.0)
438 pHps->viewportYExt = -yExt;
439 else
440 pHps->viewportYExt = yExt;
441 }
442 }
443 result = setPageXForm(wnd, pHps);
444
445 return (result);
446}
447
448LONG clientHeight(Win32BaseWindow *wnd, HWND hwnd, pDCData pHps)
449{
450 if ((hwnd == 0) && (pHps != 0))
451 hwnd = pHps->hwnd;
452
453 if ((hwnd != 0) || (pHps == 0))
454 {
455 if (wnd)
456 return (wnd->getWindowHeight());
457 else
458 return OSLibQueryScreenHeight();
459 }
460 else if (pHps->bitmapHandle)
461 {
462 return pHps->bitmapHeight;
463 }
464 else if (pHps->isMetaPS)
465 {
466 return 0;
467 }
468 else if (pHps->isPrinter)
469 {
470 return pHps->printPageHeight;
471 }
472 else
473 {
474 return MEM_HPS_MAX;
475 }
476}
477
478BOOL isYup (pDCData pHps)
479{
480 if (((pHps->windowExt.cy < 0) && (pHps->viewportYExt > 0.0)) ||
481 ((pHps->windowExt.cy > 0) && (pHps->viewportYExt < 0.0)))
482 {
483 if ((pHps->graphicsMode == GM_COMPATIBLE_W) ||
484 ((pHps->graphicsMode == GM_ADVANCED_W) && (pHps->xform.eM22 >= 0.0)))
485 return TRUE;
486 }
487 else
488 {
489 if ((pHps->graphicsMode == GM_ADVANCED_W) && (pHps->xform.eM22 < 0.0))
490 return TRUE;
491 }
492 return FALSE;
493}
494
495INT revertDy (Win32BaseWindow *wnd, INT dy)
496{
497 if (wnd->isOwnDC())
498 {
499 pDCData pHps = (pDCData)GpiQueryDCData (wnd->getOwnDC());
500
501 if (pHps != NULLHANDLE)
502 if (!isYup (pHps))
503 dy = -dy;
504 }
505 else
506 {
507 dy = -dy;
508 }
509 return (dy);
510}
511
512VOID removeClientArea(pDCData pHps)
513{
514 pHps->isClient = FALSE;
515
516 if (pHps->isClientArea)
517 {
518 pHps->isClientArea = FALSE;
519 GreSetupDC(pHps->hps,
520 pHps->hrgnVis,
521 pHps->ptlOrigin.x,
522 pHps->ptlOrigin.y,
523 0,
524 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
525 }
526}
527
528BOOL selectClientArea(Win32BaseWindow *wnd, pDCData pHps, PRECTL prclPaint)
529{
530 RECTL rcl;
531 HRGN hrgnRect;
532 HWND hwnd;
533
534 if (!wnd) return (FALSE);
535
536 pHps->isClient = TRUE;
537 hwnd = pHps->hwnd;
538
539 rcl.xLeft = rcl.yBottom = 0;
540 rcl.xRight = wnd->getWindowWidth();
541 rcl.yTop = wnd->getWindowHeight();
542
543 WinMapWindowPoints(hwnd, HWND_DESKTOP, (PPOINTL) &rcl, 2);
544 pHps->ptlOrigin = *((PPOINTL) &rcl);
545
546 if (pHps->hrgnVis == 0)
547 pHps->hrgnVis = GreCreateRectRegion(pHps->hps, &rcl, 1);
548
549 hrgnRect = GreCreateRectRegion(pHps->hps, &rcl, 1);
550
551 if (!pHps->isClientArea)
552 GreCopyClipRegion(pHps->hps, pHps->hrgnVis, 0, COPYCRGN_VISRGN);
553
554 GreCombineRegion(pHps->hps, hrgnRect, pHps->hrgnVis, hrgnRect, CRGN_AND);
555 GreSetupDC(pHps->hps,
556 hrgnRect,
557 rcl.xLeft,
558 rcl.yBottom,
559 prclPaint,
560 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
561
562 pHps->isClientArea = TRUE;
563 GreDestroyRegion(pHps->hps, hrgnRect);
564
565 return (TRUE);
566}
567
568HDC sendEraseBkgnd (Win32BaseWindow *wnd)
569{
570 BOOL erased;
571 HWND hwnd;
572 HDC hdc;
573 HPS hps;
574 HRGN hrgnUpdate, hrgnOld, hrgnClip, hrgnCombined;
575 RECTL rectl = { 1, 1, 2, 2 };
576
577 hwnd = wnd->getOS2WindowHandle();
578 hps = WinGetPS(hwnd);
579
580 hrgnUpdate = GpiCreateRegion (hps, 1, &rectl);
581 WinQueryUpdateRegion (hwnd, hrgnUpdate);
582 hrgnClip = GpiQueryClipRegion (hps);
583
584 if (hrgnClip == NULLHANDLE)
585 {
586 GpiSetClipRegion (hps, hrgnUpdate, &hrgnOld);
587 }
588 else
589 {
590 hrgnCombined = GpiCreateRegion (hps, 1, &rectl);
591 GpiCombineRegion (hps, hrgnCombined, hrgnClip, hrgnUpdate, CRGN_AND);
592 GpiSetClipRegion (hps, hrgnCombined, &hrgnOld);
593 GpiDestroyRegion (hps, hrgnUpdate);
594 GpiDestroyRegion (hps, hrgnClip);
595 }
596 if (hrgnOld != NULLHANDLE)
597 GpiDestroyRegion (hps, hrgnOld);
598
599 hdc = HPSToHDC (hwnd, hps, NULL, NULL);
600
601 erased = wnd->MsgEraseBackGround (hdc);
602
603 DeleteHDC (hdc);
604 WinReleasePS (hps);
605
606 return erased;
607}
608
609void releaseOwnDC (HDC hps)
610{
611 pDCData pHps = (pDCData)GpiQueryDCData ((HPS)hps);
612
613 if (pHps) {
614 if (pHps->hrgnHDC)
615 GpiDestroyRegion (pHps->hps, pHps->hrgnHDC);
616
617 GpiSetBitmap (pHps->hps, NULL);
618 _O32_DeleteObject (pHps->nullBitmapHandle);
619 GpiDestroyPS(pHps->hps);
620
621 if (pHps->hdc)
622 DevCloseDC(pHps->hdc);
623
624// how can a memory chunk allocated by GpiAllocateDCData freed by delete?
625// delete pHps;
626 }
627}
628
629HDC WIN32API BeginPaint (HWND hWnd, PPAINTSTRUCT_W lpps)
630{
631 HWND hwnd = hWnd ? hWnd : HWND_DESKTOP;
632 pDCData pHps = NULLHANDLE;
633 RECTL rect;
634 HPS hPS_ownDC = NULLHANDLE;
635
636 dprintf (("USER32: BeginPaint(%x)", hWnd));
637
638 if ( !lpps )
639 {
640 _O32_SetLastError (ERROR_INVALID_PARAMETER);
641 return (HDC)NULLHANDLE;
642 }
643
644 USHORT sel = RestoreOS2FS();
645 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
646
647 if ((hwnd != HWND_DESKTOP) && wnd->isOwnDC())
648 {
649 hPS_ownDC = wnd->getOwnDC();
650 pHps = (pDCData)GpiQueryDCData(hPS_ownDC);
651 if (!pHps)
652 {
653 _O32_SetLastError (ERROR_INVALID_PARAMETER);
654 SetFS(sel);
655 return (HDC)NULLHANDLE;
656 }
657 }
658
659 HWND hwndClient = wnd->getOS2WindowHandle();
660 HPS hps = WinBeginPaint(hwndClient, hPS_ownDC, &rect);
661
662 if (!pHps)
663 {
664 HDC hdc = HPSToHDC (hwndClient, hps, NULL, NULL);
665 pHps = (pDCData)GpiQueryDCData(hps);
666 }
667
668 if (wnd->isFrameWindow())
669 {
670// WinSendMsg( hwnd, /* WM_DRAW */ 0x20D, (MPARAM)hps, MPVOID );
671 selectClientArea(wnd, pHps, &rect);
672 }
673
674 if (hPS_ownDC == 0)
675 setMapMode (wnd, pHps, MM_TEXT_W);
676 else
677 setPageXForm (wnd, pHps);
678
679 pHps->hdcType = TYPE_3;
680 lpps->hdc = (HDC)hps;
681
682 if (wnd->isEraseBkgnd())
683 wnd->setEraseBkgnd (FALSE, !wnd->MsgEraseBackGround(lpps->hdc));
684 wnd->setSupressErase (FALSE);
685 lpps->fErase = wnd->isPSErase();
686
687 if (!hPS_ownDC)
688 {
689 long height = wnd->getWindowHeight();
690 rect.yTop = height - rect.yTop;
691 rect.yBottom = height - rect.yBottom;
692 }
693 else
694 {
695 rect.yTop--;
696 rect.yBottom--;
697 GpiConvert(pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rect);
698 }
699
700 WINRECT_FROM_PMRECT(lpps->rcPaint, rect);
701
702 SetFS(sel);
703 _O32_SetLastError(0);
704 return (HDC)pHps->hps;
705}
706
707BOOL WIN32API EndPaint (HWND hwnd, const PAINTSTRUCT_W *pPaint)
708{
709dprintf (("USER32: EndPaint(%x)", hwnd));
710
711 if (!pPaint || !pPaint->hdc )
712 return TRUE;
713
714 USHORT sel = RestoreOS2FS();
715 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
716
717 if (!wnd) goto exit;
718
719 if (wnd->isOwnDC())
720 {
721 pDCData pHps = (pDCData)GpiQueryDCData((HPS)pPaint->hdc);
722 if (pHps && (pHps->hdcType == TYPE_3))
723 {
724 removeClientArea (pHps);
725 WinEndPaint (pHps->hps);
726 }
727 }
728 else
729 {
730 _O32_EndPaint (HWND_DESKTOP, pPaint);
731 }
732
733exit:
734 SetFS(sel);
735 _O32_SetLastError(0);
736 return TRUE;
737}
738
739BOOL WIN32API GetUpdateRect (HWND hwnd, LPRECT pRect, BOOL erase)
740{
741 if (hwnd)
742 {
743 _O32_SetLastError (ERROR_INVALID_HANDLE);
744 return FALSE;
745 }
746
747 RECTL rectl;
748 USHORT sel = RestoreOS2FS();
749 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
750
751 BOOL updateRegionExists = WinQueryUpdateRect (hwnd, pRect ? &rectl : NULL);
752 if (!pRect) {
753 SetFS(sel);
754 return (updateRegionExists);
755 }
756
757 if (updateRegionExists)
758 {
759 if (wnd->isOwnDC())
760 {
761 pDCData pHps = NULL;
762 pHps = (pDCData)GpiQueryDCData(wnd->getOwnDC());
763 if (!pHps)
764 {
765 _O32_SetLastError (ERROR_INVALID_HANDLE);
766 SetFS(sel);
767 return FALSE;
768 }
769 GpiConvert (pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rectl);
770 }
771 else
772 {
773 long height = wnd->getWindowHeight();
774 rectl.yTop = height - rectl.yTop;
775 rectl.yBottom = height - rectl.yBottom;
776 }
777
778 if (pRect)
779 WINRECT_FROM_PMRECT (*pRect, rectl);
780
781 if (erase)
782 sendEraseBkgnd (wnd);
783 }
784 else
785 {
786 if (pRect)
787 pRect->left = pRect->top = pRect->right = pRect->bottom = 0;
788 }
789
790 SetFS(sel);
791 return updateRegionExists;
792}
793
794int WIN32API GetUpdateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
795{
796 USHORT sel = RestoreOS2FS();
797 LONG Complexity;
798
799 Complexity = _O32_GetUpdateRgn (hwnd, hrgn, FALSE);
800 if (erase && (Complexity > NULLREGION_W)) {
801 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
802 sendEraseBkgnd (wnd);
803 }
804
805 SetFS(sel);
806 return Complexity;
807}
808
809// This implementation of GetDCEx supports
810// DCX_WINDOW
811// DCX_CACHE
812// DCX_EXCLUDERGN (complex regions allowed)
813// DCX_INTERSECTRGN (complex regions allowed)
814
815HDC WIN32API GetDCEx (HWND hwnd, HRGN hrgn, ULONG flags)
816{
817 USHORT sel = RestoreOS2FS();
818 Win32BaseWindow *wnd = NULL;
819 HWND hWindow;
820 BOOL success;
821 pDCData pHps = NULL;
822 HPS hps = NULLHANDLE;
823 BOOL drawingAllowed = TRUE;
824 BOOL isWindowOwnDC;
825 BOOL creatingOwnDC = FALSE;
826 PS_Type psType;
827
828 if (hwnd)
829 {
830 wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
831 if (flags & DCX_WINDOW_W)
832 hWindow = wnd->getOS2FrameWindowHandle();
833 else
834 hWindow = wnd->getOS2WindowHandle();
835 }
836 else
837 hWindow = HWND_DESKTOP;
838
839dprintf (("User32: GetDCEx hwnd %x (%x %x) -> wnd %x", hwnd, hrgn, flags, wnd));
840
841 isWindowOwnDC = (((hWindow == HWND_DESKTOP) ? FALSE : wnd->isOwnDC())
842 && !(flags & DCX_CACHE_W));
843 if (isWindowOwnDC)
844 {
845 hps = wnd->getOwnDC();
846 if (hps)
847 {
848 pDCData pHps = (pDCData)GpiQueryDCData (hps);
849 if (!pHps)
850 goto error;
851
852 if (flags & DCX_WINDOW_W)
853 removeClientArea (pHps);
854 else
855 selectClientArea (wnd, pHps, 0);
856
857 setPageXForm (wnd, pHps);
858
859 pHps->hdcType = TYPE_1;
860 SetFS(sel);
861 return (HDC)hps;
862 }
863 else
864 creatingOwnDC = TRUE;
865 }
866
867 if (isWindowOwnDC)
868 {
869 SIZEL sizel = {0,0};
870 hps = GpiCreatePS (WinQueryAnchorBlock (hWindow),
871 WinOpenWindowDC (hWindow),
872 &sizel, PU_PELS | GPIT_MICRO | GPIA_ASSOC );
873 psType = MICRO;
874 }
875 else
876 {
877 if (hWindow == HWND_DESKTOP)
878 hps = WinGetScreenPS (hWindow);
879 else
880 hps = WinGetPS (hWindow);
881
882 psType = MICRO_CACHED;
883 }
884
885 if (!hps)
886 goto error;
887
888 HPSToHDC (hWindow, hps, NULL, NULL);
889 pHps = (pDCData)GpiQueryDCData (hps);
890
891 if (!(flags & DCX_WINDOW_W)) {
892 if (selectClientArea (wnd, pHps, 0))
893 setMapMode (wnd, pHps, MM_TEXT_W);
894 }
895
896 if ((flags & DCX_EXCLUDERGN_W) || (flags & DCX_INTERSECTRGN_W))
897 {
898 ULONG BytesNeeded;
899 PRGNDATA_W RgnData;
900 PRECTL pr;
901 int i;
902 LONG height = OSLibQueryScreenHeight();
903
904 if (!hrgn)
905 goto error;
906
907 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
908 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
909 if (RgnData == NULL)
910 goto error;
911 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
912
913 i = RgnData->rdh.nCount;
914 pr = (PRECTL)(RgnData->Buffer);
915
916 success = TRUE;
917 if (flags & DCX_EXCLUDERGN_W)
918 for (; (i > 0) && success; i--, pr++) {
919 LONG y = pr->yBottom;
920
921 pr->yBottom = height - pr->yTop;
922 pr->yTop = height - y;
923 success &= GpiExcludeClipRectangle (pHps->hps, pr);
924 }
925 else
926 for (; (i > 0) && success; i--, pr++) {
927 LONG y = pr->yBottom;
928
929 pr->yBottom = height - pr->yTop;
930 pr->yTop = height - y;
931 success &= GpiIntersectClipRectangle (pHps->hps, pr);
932 }
933 if (!success)
934 goto error;
935 }
936
937 if (creatingOwnDC)
938 wnd->setOwnDC ((HDC)hps);
939
940 pHps->psType = psType;
941 pHps->hdcType = TYPE_1;
942 GpiSetDrawControl (hps, DCTL_DISPLAY, drawingAllowed ? DCTL_ON : DCTL_OFF);
943
944 SetFS(sel);
945 return (HDC)pHps->hps;
946
947error:
948 /* Something went wrong; clean up
949 */
950 if (pHps)
951 {
952 if (pHps->hps)
953 {
954 if(pHps->psType == MICRO_CACHED)
955 WinReleasePS(pHps->hps);
956 else
957 GpiDestroyPS(pHps->hps);
958 }
959
960 if (pHps->hdc) DevCloseDC(pHps->hdc);
961 if (pHps->hrgnHDC) GpiDestroyRegion(pHps->hps, pHps->hrgnHDC);
962
963 _O32_DeleteObject (pHps->nullBitmapHandle);
964 }
965 _O32_SetLastError (ERROR_INVALID_PARAMETER);
966 SetFS(sel);
967 return NULL;
968}
969
970HDC WIN32API GetDC (HWND hwnd)
971{
972 return GetDCEx (hwnd, NULL, 0);
973}
974
975HDC WIN32API GetWindowDC (HWND hwnd)
976{
977 return GetDCEx (hwnd, NULL, DCX_WINDOW_W);
978}
979
980int WIN32API ReleaseDC (HWND hwnd, HDC hdc)
981{
982 USHORT sel = RestoreOS2FS();
983 BOOL isOwnDC = FALSE;
984 int rc;
985
986 if (hwnd)
987 {
988 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
989 isOwnDC = wnd->isOwnDC();
990 }
991 if (isOwnDC)
992 rc = TRUE;
993 else
994 rc = _O32_ReleaseDC (0, hdc);
995
996 SetFS(sel);
997 dprintf(("ReleaseDC %x %x", hwnd, hdc));
998 return (rc);
999}
1000
1001BOOL WIN32API UpdateWindow (HWND hwnd)
1002{
1003 if (!hwnd)
1004 return FALSE;
1005
1006 USHORT sel = RestoreOS2FS();
1007 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1008
1009dprintf (("User32: UpdateWindow hwnd %x -> wnd %x", hwnd, wnd));
1010
1011 if (WinQueryUpdateRect (wnd->getOS2WindowHandle(), NULL))
1012 sendEraseBkgnd (wnd);
1013
1014 wnd->MsgPaint(0);
1015
1016 SetFS(sel);
1017 return (TRUE);
1018}
1019
1020// This implementation of RedrawWindow supports
1021// RDW_ERASE
1022// RDW_NOERASE
1023// RDW_INTERNALPAINT
1024// RDW_NOINTERNALPAINT
1025// RDW_INVALIDATE
1026// RDW_VALIDATE
1027// RDW_ERASENOW
1028// RDW_UPDATENOW
1029
1030ODINFUNCTION4(BOOL,RedrawWindow,HWND, hwnd,
1031 const RECT*, pRect,
1032 HRGN, hrgn,
1033 DWORD, redraw)
1034{
1035 Win32BaseWindow *wnd;
1036
1037 if (redraw & (RDW_FRAME_W | RDW_NOFRAME_W))
1038 {
1039 _O32_SetLastError (ERROR_NOT_SUPPORTED);
1040 return FALSE;
1041 }
1042
1043//@@@PH USHORT sel = RestoreOS2FS();
1044//@@@PH dprintf(("USER32: RedrawWindow %X, %X %X %X", hwnd, pRect, hrgn, redraw));
1045
1046 if (hwnd == NULLHANDLE)
1047 {
1048 hwnd = HWND_DESKTOP;
1049 wnd = Win32BaseWindow::GetWindowFromOS2Handle(OSLIB_HWND_DESKTOP);
1050
1051 if (!wnd)
1052 {
1053 dprintf(("USER32:dc: RedrawWindow can't find desktop window %08xh\n",
1054 hwnd));
1055 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1056//@@@PH SetFS(sel);
1057 return FALSE;
1058 }
1059
1060 }
1061 else
1062 {
1063 wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1064
1065 if (!wnd)
1066 {
1067 dprintf(("USER32:dc: RedrawWindow can't find window %08xh\n",
1068 hwnd));
1069 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1070//@@@PH SetFS(sel);
1071 return FALSE;
1072 }
1073 hwnd = wnd->getOS2WindowHandle();
1074 }
1075
1076 BOOL IncludeChildren = redraw & RDW_ALLCHILDREN_W ? TRUE : FALSE;
1077 BOOL success = TRUE;
1078 HPS hpsTemp = NULLHANDLE;
1079 HRGN hrgnTemp = NULLHANDLE;
1080 RECTL rectl;
1081
1082 if (redraw & RDW_UPDATENOW_W) redraw &= ~RDW_ERASENOW_W;
1083
1084 if (redraw & RDW_NOERASE_W)
1085 wnd->setEraseBkgnd (FALSE);
1086
1087 if (redraw & RDW_UPDATENOW_W)
1088 wnd->setSupressErase (FALSE);
1089 else if (redraw & RDW_ERASENOW_W)
1090 wnd->setSupressErase (FALSE);
1091#if 0
1092 else
1093 {
1094 QMSG qmsg;
1095 BOOL erase;
1096
1097 erase = (WinPeekMsg (HABX, &qmsg, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)
1098 && (redraw & RDW_NOERASE_W) == 0);
1099
1100 wnd->setSupressErase (!erase);
1101 }
1102
1103 if (redraw & (RDW_NOINTERNALPAINT_W | RDW_INTERNALPAINT_W))
1104 {
1105 QMSG qmsg;
1106
1107 WinPeekMsg( (HAB)0, &qmsg, hwnd, WM_VIRTUAL_INTERNALPAINT,
1108 WM_VIRTUAL_INTERNALPAINT, PM_REMOVE );
1109 }
1110#endif
1111
1112 if (hrgn)
1113 {
1114 ULONG BytesNeeded;
1115 PRGNDATA_W RgnData;
1116 PRECTL pr;
1117 int i;
1118 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1119
1120 if (!hrgn)
1121 goto error;
1122
1123 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
1124 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
1125 if (RgnData == NULL)
1126 goto error;
1127 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
1128
1129 pr = (PRECTL)(RgnData->Buffer);
1130 for (i = RgnData->rdh.nCount; i > 0; i--, pr++) {
1131 LONG temp = pr->yTop;
1132 pr->yTop = height - pr->yBottom;
1133 pr->yBottom = height - temp;
1134 }
1135
1136 hpsTemp = WinGetScreenPS (HWND_DESKTOP);
1137 hrgnTemp = GpiCreateRegion (hpsTemp, RgnData->rdh.nCount, (PRECTL)(RgnData->Buffer));
1138 if (!hrgnTemp) goto error;
1139 }
1140 else if (pRect)
1141 {
1142 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1143
1144 PMRECT_FROM_WINRECT (rectl, *pRect);
1145 rectl.yTop = height - rectl.yTop;
1146 rectl.yBottom = height - rectl.yBottom;
1147 }
1148
1149 if (redraw & RDW_INVALIDATE_W)
1150 {
1151 if (redraw & RDW_ERASE_W)
1152 wnd->setEraseBkgnd (TRUE, TRUE);
1153
1154 if (!pRect && !hrgn)
1155 success = WinInvalidateRect (hwnd, NULL, IncludeChildren);
1156 else if (hrgn)
1157 success = WinInvalidateRegion (hwnd, hrgnTemp, IncludeChildren);
1158 else
1159 success = WinInvalidateRect (hwnd, &rectl, IncludeChildren);
1160 if (!success) goto error;
1161 }
1162 else if (redraw & RDW_VALIDATE_W)
1163 {
1164 if (WinQueryUpdateRect (hwnd, NULL))
1165 {
1166 if (!pRect && !hrgn)
1167 success = WinValidateRect (hwnd, NULL, IncludeChildren);
1168 else if (hrgn)
1169 success = WinValidateRegion (hwnd, hrgnTemp, IncludeChildren);
1170 else
1171 success = WinValidateRect (hwnd, &rectl, IncludeChildren);
1172 if (!success) goto error;
1173 }
1174 }
1175
1176 if (WinQueryUpdateRect (hwnd, NULL))
1177 {
1178 if (redraw & RDW_UPDATENOW_W)
1179 wnd->MsgPaint (0, FALSE);
1180
1181 else if ((redraw & RDW_ERASE_W) && (redraw & RDW_ERASENOW_W))
1182 wnd->setEraseBkgnd (FALSE, !sendEraseBkgnd (wnd));
1183 }
1184 else if ((redraw & RDW_INTERNALPAINT_W) && !(redraw & RDW_INVALIDATE_W))
1185 {
1186 if (redraw & RDW_UPDATENOW_W)
1187 wnd->MsgPaint (0, FALSE);
1188// else
1189// WinPostMsg( hwnd, WM_VIRTUAL_INTERNALPAINT, MPVOID, MPVOID );
1190 }
1191
1192error:
1193 /* clean up */
1194 if (hrgnTemp)
1195 GpiDestroyRegion (hpsTemp, hrgnTemp);
1196
1197 if (hpsTemp)
1198 WinReleasePS (hpsTemp);
1199
1200 if ((redraw & RDW_INVALIDATE_W) == 0)
1201 wnd->setSupressErase (FALSE);
1202 else if ((redraw & RDW_ERASENOW_W) == RDW_ERASENOW_W)
1203 wnd->setSupressErase (TRUE);
1204
1205 if (!success)
1206 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1207
1208//@@@PH SetFS(sel);
1209 return (success);
1210}
1211
1212BOOL WIN32API InvalidateRect (HWND hwnd, const RECT *pRect, BOOL erase)
1213{
1214 USHORT sel = RestoreOS2FS();
1215// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1216 BOOL result;
1217
1218// todo !!
1219// if ( isFrame without client )
1220// erase = TRUE;
1221
1222 result = RedrawWindow (hwnd, pRect, NULLHANDLE,
1223 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1224 (erase ? RDW_ERASE_W : 0) |
1225 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1226 SetFS(sel);
1227 return (result);
1228}
1229
1230BOOL WIN32API InvalidateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
1231{
1232 USHORT sel = RestoreOS2FS();
1233// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1234 BOOL result;
1235
1236// todo !!
1237// if ( isFrame without client )
1238// erase = TRUE;
1239
1240 result = RedrawWindow (hwnd, NULL, hrgn,
1241 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1242 (erase ? RDW_ERASE_W : 0) |
1243 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1244 SetFS(sel);
1245 return (result);
1246}
1247
1248BOOL setPMRgnIntoWinRgn (HRGN hrgnPM, HRGN hrgnWin, LONG height)
1249{
1250 BOOL rc;
1251 HPS hps = WinGetScreenPS (HWND_DESKTOP);
1252 RGNRECT rgnRect;
1253 rgnRect.ircStart = 1;
1254 rgnRect.crc = 0;
1255 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference because we're getting them all
1256
1257 rc = GpiQueryRegionRects (hps, hrgnPM, NULL, &rgnRect, NULL);
1258
1259 if (rc && (rgnRect.crcReturned > 0))
1260 {
1261 PRECTL Rcls = new RECTL[rgnRect.crcReturned];
1262 PRECTL pRcl = Rcls;
1263
1264 if (Rcls != NULL)
1265 {
1266 rgnRect.crc = rgnRect.crcReturned;
1267 rc = GpiQueryRegionRects (hps, hrgnPM, NULL, &rgnRect, Rcls);
1268
1269 rc = _O32_SetRectRgn (hrgnWin, pRcl->xLeft,
1270 pRcl->xRight,
1271 height - pRcl->yTop,
1272 height - pRcl->yBottom);
1273
1274 if (rgnRect.crcReturned > 1)
1275 {
1276 int i;
1277 HRGN temp;
1278 temp = _O32_CreateRectRgn (0, 0, 1, 1);
1279
1280 for (i = 1, pRcl++; rc && (i < rgnRect.crcReturned); i++, pRcl++)
1281 {
1282 rc = _O32_SetRectRgn (temp, pRcl->xLeft,
1283 pRcl->xRight,
1284 height - pRcl->yTop,
1285 height - pRcl->yBottom);
1286 rc &= _O32_CombineRgn (hrgnWin, hrgnWin, temp, RGN_OR_W);
1287 }
1288 _O32_DeleteObject (temp);
1289 }
1290 delete[] Rcls;
1291 }
1292 else
1293 {
1294 rc = FALSE;
1295 }
1296 }
1297 else
1298 {
1299 rc = _O32_SetRectRgn (hrgnWin, 0, 0, 0, 0);
1300 }
1301
1302 WinReleasePS (hps);
1303 return (rc);
1304}
1305
1306BOOL WIN32API ScrollDC (HDC hDC, int dx, int dy, const RECT *pScroll,
1307 const RECT *pClip, HRGN hrgnUpdate, LPRECT pRectUpdate)
1308{
1309 USHORT sel = RestoreOS2FS();
1310 BOOL rc = TRUE;
1311
1312 dprintf (("USER32: ScrollDC"));
1313
1314 if (!hDC)
1315 {
1316 SetFS(sel);
1317 return (FALSE);
1318 }
1319
1320 pDCData pHps = (pDCData)GpiQueryDCData ((HPS)hDC);
1321 HWND hwnd = pHps->hwnd;
1322 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1323
1324 if ((hwnd == NULLHANDLE) || !wnd)
1325 {
1326 SetFS(sel);
1327 return (FALSE);
1328 }
1329
1330 POINTL ptl[2] = { 0, 0, dx, dy };
1331
1332 GpiConvert (pHps->hps, CVTC_WORLD, CVTC_DEVICE, 2, ptl);
1333 dx = (int)(ptl[1].x - ptl[0].x);
1334 dy = (int)(ptl[1].y - ptl[0].y);
1335
1336 RECTL scrollRect;
1337 RECTL clipRect;
1338
1339 if (pClip)
1340 {
1341 clipRect.xLeft = min (pClip->left, pClip->right);
1342 clipRect.xRight = max (pClip->left, pClip->right);
1343 clipRect.yTop = max (pClip->top, pClip->bottom);
1344 clipRect.yBottom = min (pClip->top, pClip->bottom);
1345
1346 if ((pHps->graphicsMode == GM_COMPATIBLE_W) &&
1347 (clipRect.xLeft != clipRect.xRight) &&
1348 (clipRect.yBottom != clipRect.yTop))
1349 {
1350 if (abs((int)pHps->viewportXExt) <= abs((int)pHps->windowExt.cx))
1351 clipRect.xRight -= abs(pHps->worldXDeltaFor1Pixel);
1352 else
1353 clipRect.xLeft += abs(pHps->worldXDeltaFor1Pixel);
1354
1355 if (abs((int)pHps->viewportYExt) <= abs((int)pHps->windowExt.cy))
1356 clipRect.yTop -= abs(pHps->worldYDeltaFor1Pixel);
1357 else
1358 clipRect.yBottom += abs(pHps->worldYDeltaFor1Pixel);
1359 }
1360 GpiConvert (pHps->hps, CVTC_WORLD, CVTC_DEVICE, 2, (PPOINTL)&clipRect);
1361 if (clipRect.xRight < clipRect.xLeft) {
1362 ULONG temp = clipRect.xLeft;
1363 clipRect.xLeft = clipRect.xRight;
1364 clipRect.xRight = temp;
1365 }
1366 if (clipRect.yTop < clipRect.yBottom) {
1367 ULONG temp = clipRect.yBottom;
1368 clipRect.yBottom = clipRect.yTop;
1369 clipRect.yTop = temp;
1370 }
1371 }
1372
1373 if (pScroll)
1374 {
1375 scrollRect.xLeft = min (pScroll->left, pScroll->right);
1376 scrollRect.xRight = max (pScroll->left, pScroll->right);
1377 scrollRect.yTop = max (pScroll->top, pScroll->bottom);
1378 scrollRect.yBottom = min (pScroll->top, pScroll->bottom);
1379
1380 if ((pHps->graphicsMode == GM_COMPATIBLE_W) &&
1381 (scrollRect.xLeft != scrollRect.xRight) &&
1382 (scrollRect.yBottom != scrollRect.yTop))
1383 {
1384 if (abs((int)pHps->viewportXExt) <= abs((int)pHps->windowExt.cx))
1385 scrollRect.xRight -= abs(pHps->worldXDeltaFor1Pixel);
1386 else
1387 scrollRect.xLeft += abs(pHps->worldXDeltaFor1Pixel);
1388
1389 if (abs((int)pHps->viewportYExt) <= abs((int)pHps->windowExt.cy))
1390 scrollRect.yTop -= abs(pHps->worldYDeltaFor1Pixel);
1391 else
1392 scrollRect.yBottom += abs(pHps->worldYDeltaFor1Pixel);
1393 }
1394 GpiConvert (pHps->hps, CVTC_WORLD, CVTC_DEVICE, 2, (PPOINTL)&scrollRect);
1395 if (scrollRect.xRight < scrollRect.xLeft) {
1396 ULONG temp = scrollRect.xLeft;
1397 scrollRect.xLeft = scrollRect.xRight;
1398 scrollRect.xRight = temp;
1399 }
1400 if (scrollRect.yTop < scrollRect.yBottom) {
1401 ULONG temp = scrollRect.yBottom;
1402 scrollRect.yBottom = scrollRect.yTop;
1403 scrollRect.yTop = temp;
1404 }
1405 }
1406 RECTL rectlUpdate;
1407 HRGN hrgn;
1408
1409 LONG lComplexity = WinScrollWindow (hwnd, dx, dy, (pScroll) ? &scrollRect : NULL, (pClip) ? &clipRect : NULL, hrgn, &rectlUpdate, 0);
1410 if (lComplexity == RGN_ERROR)
1411 {
1412 SetFS(sel);
1413 return (FALSE);
1414 }
1415
1416 RECT winRectUpdate;
1417 LONG height = wnd->getWindowHeight();
1418
1419 winRectUpdate.left = rectlUpdate.xLeft;
1420 winRectUpdate.right = rectlUpdate.xRight;
1421 winRectUpdate.top = height - rectlUpdate.yTop;
1422 winRectUpdate.bottom = height - rectlUpdate.yBottom;
1423
1424 if (pRectUpdate)
1425 *pRectUpdate = winRectUpdate;
1426
1427 if (hrgnUpdate)
1428 rc = setPMRgnIntoWinRgn (hrgn, hrgnUpdate, height);
1429
1430 SetFS(sel);
1431 return (rc);
1432}
1433
1434//******************************************************************************
1435//******************************************************************************
1436BOOL WIN32API ScrollWindow(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip)
1437{
1438 USHORT sel = RestoreOS2FS();
1439 Win32BaseWindow *window;
1440 APIRET rc;
1441 RECTL clientRect;
1442 RECTL scrollRect;
1443 RECTL clipRect;
1444 PRECTL pScrollRect = NULL;
1445 PRECTL pClipRect = NULL;
1446 ULONG scrollFlags = SW_INVALIDATERGN;
1447
1448 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1449 if(!window) {
1450 dprintf(("ScrollWindow, window %x not found", hwnd));
1451 SetFS(sel);
1452 return 0;
1453 }
1454 dprintf(("ScrollWindow %x %d %d\n", hwnd, dx, dy));
1455 MapWin32ToOS2Rectl(window->getClientRect(), (PRECTLOS2)&clientRect);
1456 //Rectangle could be relative to parent window, so fix this
1457 if(clientRect.yBottom != 0) {
1458 clientRect.yTop -= clientRect.yBottom;
1459 clientRect.yBottom = 0;
1460 }
1461 if(clientRect.xLeft != 0) {
1462 clientRect.xRight -= clientRect.xLeft;
1463 clientRect.xLeft = 0;
1464 }
1465 if(pScroll) {
1466 MapWin32ToOS2Rectl((RECT *)pScroll, (PRECTLOS2)&scrollRect);
1467 pScrollRect = &scrollRect;
1468
1469 //Scroll rectangle relative to client area
1470 pScrollRect->xLeft += clientRect.xLeft;
1471 pScrollRect->xRight += clientRect.xLeft;
1472 pScrollRect->yTop += clientRect.yBottom;
1473 pScrollRect->yBottom += clientRect.yBottom;
1474 WinIntersectRect ((HAB) 0, pScrollRect, pScrollRect, &clientRect);
1475 }
1476 else scrollFlags |= SW_SCROLLCHILDREN;
1477
1478 if(pClip) {
1479 MapWin32ToOS2Rectl((RECT *)pClip, (PRECTLOS2)&clipRect);
1480 pClipRect = &clipRect;
1481
1482 //Clip rectangle relative to client area
1483 pClipRect->xLeft += clientRect.xLeft;
1484 pClipRect->xRight += clientRect.xLeft;
1485 pClipRect->yTop += clientRect.yBottom;
1486 pClipRect->yBottom += clientRect.yBottom;
1487 WinIntersectRect ((HAB) 0, pClipRect, pClipRect, &clientRect);
1488 }
1489
1490 dy = revertDy (window, dy);
1491
1492 rc = WinScrollWindow(window->getOS2WindowHandle(), dx, dy,
1493 pScrollRect, pClipRect, NULLHANDLE,
1494 NULL, scrollFlags);
1495
1496 SetFS(sel);
1497 return (rc != RGN_ERROR);
1498}
1499//******************************************************************************
1500//******************************************************************************
1501INT WIN32API ScrollWindowEx(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip,
1502 HRGN hrgnUpdate, PRECT pRectUpdate, UINT scrollFlag)
1503{
1504 USHORT sel = RestoreOS2FS();
1505 Win32BaseWindow *window;
1506 APIRET rc;
1507 RECTL scrollRect;
1508 RECTL clipRect;
1509 ULONG scrollFlags = 0;
1510 int regionType = ERROR_W;
1511
1512 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1513 if(!window) {
1514 dprintf(("ScrollWindowEx, window %x not found", hwnd));
1515 SetFS(sel);
1516 return 0;
1517 }
1518
1519 dprintf(("ScrollWindowEx %x %d %d\n", hwnd, dx, dy));
1520
1521 dy = revertDy (window, dy);
1522
1523 if (scrollFlag & SW_INVALIDATE_W) scrollFlags |= SW_INVALIDATERGN;
1524 if (scrollFlag & SW_SCROLLCHILDREN_W) scrollFlags |= SW_SCROLLCHILDREN;
1525
1526 if(pScroll) MapWin32ToOS2Rectl((RECT *)pScroll, (PRECTLOS2)&scrollRect);
1527 if(pClip) MapWin32ToOS2Rectl((RECT *)pClip, (PRECTLOS2)&clipRect);
1528
1529 RECTL rectlUpdate;
1530 HRGN hrgn;
1531
1532 LONG lComplexity = WinScrollWindow (window->getOS2WindowHandle(), dx, dy,
1533 (pScroll) ? &scrollRect : NULL,
1534 (pClip) ? &clipRect : NULL,
1535 hrgn, &rectlUpdate, scrollFlags);
1536 if (lComplexity == RGN_ERROR)
1537 {
1538 SetFS(sel);
1539 return (0);
1540 }
1541
1542 RECT winRectUpdate;
1543 LONG height = window->getWindowHeight();
1544
1545 winRectUpdate.left = rectlUpdate.xLeft;
1546 winRectUpdate.right = rectlUpdate.xRight;
1547 winRectUpdate.top = height - rectlUpdate.yTop;
1548 winRectUpdate.bottom = height - rectlUpdate.yBottom;
1549
1550 if (pRectUpdate)
1551 *pRectUpdate = winRectUpdate;
1552
1553 if (hrgnUpdate)
1554 rc = setPMRgnIntoWinRgn (hrgn, hrgnUpdate, height);
1555
1556 if ((scrollFlag & SW_INVALIDATE_W) &&
1557 ((lComplexity == RGN_RECT) || (lComplexity == RGN_COMPLEX)))
1558 {
1559 rc = InvalidateRect (hwnd, &winRectUpdate, scrollFlag & SW_ERASE_W);
1560 if (rc == FALSE)
1561 {
1562 SetFS(sel);
1563 return (0);
1564 }
1565 }
1566
1567 switch (lComplexity)
1568 {
1569 case RGN_NULL:
1570 regionType = NULLREGION_W;
1571 break;
1572 case RGN_RECT:
1573 regionType = SIMPLEREGION_W;
1574 break;
1575 case RGN_COMPLEX:
1576 regionType = COMPLEXREGION_W;
1577 break;
1578 default:
1579 regionType = ERROR_W;
1580 break;
1581 }
1582
1583 SetFS(sel);
1584 return (regionType);
1585}
1586//******************************************************************************
1587//******************************************************************************
Note: See TracBrowser for help on using the repository browser.