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

Last change on this file since 2663 was 2663, checked in by sandervl, 26 years ago

WM_ERASEBKGND changes

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