source: trunk/src/gdi32/region.cpp@ 10321

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

compile fix

File size: 66.9 KB
Line 
1/* $Id: region.cpp,v 1.34 2003-11-14 17:30:47 sandervl Exp $ */
2
3/*
4 * GDI32 region code
5 *
6 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 * Copyright 2002-2003 Innotek Systemberatung GmbH (sandervl@innotek.de)
9 *
10 * TODO: Metafile recording
11 * TODO: Do we need to translate & set the last error for Gpi operations?
12 *
13 *
14 * NOTE: In windows there is a clip and a visible region (just like in PM)
15 * We do not map the Win32 visible region to the PM visible region
16 * as that's rather annoying.
17 * Instead we use the intersection of the win32 visible and win32 clip
18 * region for the PM clip region.
19 * The original Win32 clip region is saved in pHps->hrgnWin32Clip.
20 * The Win32 visible region is saved in pHps->hrgnWinVis.
21 *
22 *
23 *
24 * Project Odin Software License can be found in LICENSE.TXT
25 *
26 */
27
28#define INCL_GPI
29#define INCL_WIN
30#include <os2wrap.h> //need odin wrappers
31
32#include <win32type.h>
33#include <win32api.h>
34#include <winconst.h>
35#include <stdlib.h>
36#include <stdarg.h>
37#include <string.h>
38#include <misc.h>
39#include <objhandle.h>
40#include <dcdata.h>
41#include <winuser32.h>
42#include "oslibgpi.h"
43#include <stats.h>
44#include "dibsect.h"
45#include <wingdi32.h>
46
47#define DBG_LOCALLOG DBG_region
48#include "dbglocal.h"
49
50#define DIBSECTION_MARK_INVALID(a)
51#define DIBSECTION_CHECK_IF_DIRTY(a)
52
53//GPI and Windows use the same values
54#define GPI_TO_WIN_COMPLEXITY(a) a
55
56typedef enum
57{
58 AS_DEVICE,
59 AS_WORLD
60} InterpMode;
61
62#define MEM_HPS_MAX 768
63
64int WIN32API OffsetRgn( HRGN hrgn, int xOffset, int yOffset);
65
66static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count);
67
68#define convertWinDeviceRectToPMDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
69#define convertPMDeviceRectToWinDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
70
71inline void convertDeviceRect(pDCData pHps, PRECTL pRectl, ULONG count)
72{
73 convertDeviceRect(0, pHps, pRectl, count);
74}
75inline void convertDeviceRect(HWND hwnd, PRECTL pRectl, ULONG count)
76{
77 convertDeviceRect(hwnd, 0, pRectl, count);
78}
79
80HPS hpsRegion = 0;
81
82
83#ifdef DEBUG
84//#define dprintfRegion(a,b,c) if(DbgEnabledLvl2GDI32[DBG_LOCALLOG] == 1) dprintfRegion1(a,b,c)
85//#define dprintfRegion(a,b,c) dprintfRegion1(a,b,c)
86
87void dprintfRegion(HPS hps, HRGN hrgnClip)
88{
89 RGNRECT rgnRect = {0, 16, 0, RECTDIR_LFRT_TOPBOT};
90 RECTL rectRegion[16];
91 APIRET rc;
92
93 dprintf(("dprintfRegion %x", hps));
94 rc = GpiQueryRegionRects(hps, hrgnClip, NULL, &rgnRect, &rectRegion[0]);
95 for(int i=0;i<rgnRect.crcReturned;i++) {
96 dprintf(("(%d,%d)(%d,%d)", rectRegion[i].xLeft, rectRegion[i].yBottom, rectRegion[i].xRight, rectRegion[i].yTop));
97 }
98}
99#else
100#define dprintfRegion(a,c)
101#endif
102
103//******************************************************************************
104//******************************************************************************
105BOOL InitRegionSpace()
106{
107 hpsRegion = WinGetScreenPS(HWND_DESKTOP);
108 return hpsRegion != 0;
109}
110//******************************************************************************
111//******************************************************************************
112void DestroyRegionSpace()
113{
114 if(hpsRegion) WinReleasePS(hpsRegion);
115 hpsRegion = 0;
116}
117//******************************************************************************
118//******************************************************************************
119LONG hdcHeight(HWND hwnd, pDCData pHps)
120{
121 if(hwnd == 0 && pHps != 0)
122 hwnd = pHps->hwnd;
123
124 if(hwnd != 0 || pHps == 0)
125 {
126 RECT rect;
127 RECTL rectl;
128 LONG y = 0;
129
130 if(pHps && pHps->isClient) //client area
131 {
132 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
133 y = rect.bottom - rect.top;
134 }
135 }
136 else
137 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
138 y = rectl.yTop;
139
140 return y;
141 }
142 else
143 if(pHps->bitmapHandle)
144 {
145 return pHps->bitmapHeight;
146 }
147 else
148 if(pHps->isMetaPS)
149 {
150 return 0;
151 }
152 else
153 if(pHps->isPrinter)
154 {
155 return GetDeviceCaps(pHps->hps, VERTRES_W);
156 }
157 else
158 {
159 return MEM_HPS_MAX;
160 }
161}
162//******************************************************************************
163//******************************************************************************
164LONG hdcWidth(HWND hwnd, pDCData pHps)
165{
166 if(hwnd == 0 && pHps != 0)
167 hwnd = pHps->hwnd;
168
169 if(hwnd != 0 || pHps == 0)
170 {
171 RECT rect;
172 RECTL rectl;
173 LONG x = 0;
174
175 if(pHps && pHps->isClient) //client area
176 {
177 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
178 x = rect.right - rect.left;
179 }
180 }
181 else
182 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
183 x = rectl.xRight;
184
185 return x;
186 }
187 else
188 if(pHps->bitmapHandle)
189 {
190 return pHps->bitmapWidth;
191 }
192 else
193 if(pHps->isMetaPS)
194 {
195 return 0;
196 }
197 else
198 if(pHps->isPrinter)
199 {
200 return GetDeviceCaps(pHps->hps, HORZRES_W);
201 }
202// else
203// DebugInt3();
204 return 0;
205}
206//******************************************************************************
207//******************************************************************************
208static void convertWinWorldRectToPMDeviceRect(pDCData pHps_Hdc, PRECTL pRects, UINT count = 1)
209{
210 PRECTL pRectl;
211 for (int x=0; x < count; x++)
212 {
213 pRectl = &pRects[x];
214
215 if(pRectl->yTop < pRectl->yBottom) {
216 ULONG temp = pRectl->yBottom;
217 pRectl->yBottom = pRectl->yTop;
218 pRectl->yTop = temp;
219 }
220 BOOL success = GpiConvert( pHps_Hdc->hps, CVTC_WORLD, CVTC_DEVICE, 2, (PPOINTL)pRectl);
221 if(!success)
222 {
223 break;
224 }
225 if(pRectl->yTop < pRectl->yBottom) {
226 ULONG temp = pRectl->yBottom;
227 pRectl->yBottom = pRectl->yTop;
228 pRectl->yTop = temp;
229 }
230 }
231}
232//******************************************************************************
233//******************************************************************************
234static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count)
235{
236 long wHeight, wWidth;
237
238 if(hwnd == HWND_DESKTOP) {
239 wHeight = OSLibGetScreenHeight();
240 wWidth = OSLibGetScreenWidth();
241 }
242 else {
243 wHeight = hdcHeight(hwnd, pHps);
244 wWidth = hdcWidth(hwnd, pHps);
245 }
246
247 if(pHps)
248 {
249 wHeight += pHps->HPStoHDCInversionHeight;
250 }
251
252 if(hwnd || (pHps && pHps->hwnd)) {
253 for(int x=0; x < count; x++)
254 {
255 if(pRectl[x].xRight > wWidth) {
256 pRectl[x].xRight = wWidth;
257 }
258 if(pRectl[x].yTop > wHeight) {
259 pRectl[x].yTop = 0;
260 }
261 else pRectl[x].yTop = wHeight - pRectl[x].yTop;
262
263 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
264 }
265 }
266 else {
267 for(int x=0; x < count; x++)
268 {
269 pRectl[x].yTop = wHeight - pRectl[x].yTop;
270 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
271 }
272 }
273}
274//******************************************************************************
275//******************************************************************************
276static void convertPMDeviceRectToWinWorldRect(pDCData pHps_Hdc, PRECTL pRectl)
277{
278 GpiConvert(pHps_Hdc->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)pRectl );
279}
280//******************************************************************************
281//******************************************************************************
282BOOL interpretRegionAs(pDCData pHps, HRGN hrgnDest, HRGN hrgnSrc, InterpMode mode)
283{
284 BOOL success = FALSE;
285 int x, i;
286 HPS hpsDest;
287
288 if(pHps)
289 {
290 if(!hrgnDest) {
291 hrgnDest = pHps->hrgnHDC;
292#ifdef DEBUG
293 if(hrgnDest == 0) {
294 DebugInt3();
295 }
296#endif
297 }
298 hpsDest = pHps->hps;
299 }
300 else {
301 DebugInt3();
302 return FALSE;
303 }
304
305 RGNRECT rgnRect;
306 rgnRect.ircStart = 1;
307 rgnRect.crc = 0;
308 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
309 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, NULL);
310 if(success)
311 {
312 if(rgnRect.crcReturned > 0)
313 {
314 rgnRect.crc = rgnRect.crcReturned;
315 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
316 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, pRectl);
317 if(success)
318 {
319 if(mode == AS_DEVICE)
320 {
321 ULONG temp;
322 for(x=0; x < rgnRect.crcReturned; x++)
323 {
324 temp = pRectl[x].yBottom;
325 pRectl[x].yBottom = pRectl[x].yTop;
326 pRectl[x].yTop = temp;
327 }
328 convertWinDeviceRectToPMDeviceRect(pHps, pRectl, rgnRect.crcReturned);
329 }
330 else
331 {
332 GpiConvert(pHps->hps, CVTC_WORLD, CVTC_DEVICE, rgnRect.crcReturned<<1, (PPOINTL)pRectl);
333
334 ULONG temp;
335 for(i=0; i < rgnRect.crcReturned; i++)
336 {
337 if(pRectl[i].yTop < pRectl[i].yBottom)
338 {
339 temp = pRectl[i].yBottom + 1;
340 pRectl[i].yBottom = pRectl[i].yTop + 1;
341 pRectl[i].yTop = temp;
342 }
343 else
344 {
345 pRectl[i].yTop++;
346 pRectl[i].yBottom++;
347 }
348 }
349 }
350 success = GpiSetRegion(hpsDest, hrgnDest, rgnRect.crcReturned, pRectl);
351 }
352 delete[] pRectl;
353 }
354 else
355 {
356 success = GpiSetRegion(hpsDest, hrgnDest, 0, NULL);
357 }
358 }
359 return success;
360}
361//******************************************************************************
362//exported (used by user32)
363//******************************************************************************
364BOOL WIN32API setWinDeviceRegionFromPMDeviceRegion(HRGN winHrgn, HRGN pmHrgn, pDCData pHpsPmHrgn, HWND hwndPmHrgn)
365{
366 BOOL success;
367 int x;
368 BOOL mustReleaseScreenPS = FALSE;
369 HPS hps;
370
371 if(pHpsPmHrgn || hwndPmHrgn)
372 {
373 if(pHpsPmHrgn)
374 hps = pHpsPmHrgn->hps;
375 else
376 {
377 hps = WinGetScreenPS(HWND_DESKTOP);
378 mustReleaseScreenPS = TRUE;
379 }
380
381 RGNRECT rgnRect;
382 rgnRect.ircStart = 1;
383 rgnRect.crc = 0;
384 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
385 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, NULL);
386 if(success )
387 {
388 if(rgnRect.crcReturned > 0)
389 {
390 rgnRect.crc = rgnRect.crcReturned;
391 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
392 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, pRectl);
393 if(success)
394 {
395 if(pHpsPmHrgn)
396 convertPMDeviceRectToWinDeviceRect(pHpsPmHrgn, pRectl, rgnRect.crcReturned);
397 else
398 convertPMDeviceRectToWinDeviceRect(hwndPmHrgn, pRectl, rgnRect.crcReturned);
399
400 for(x=0; x < rgnRect.crcReturned; x++)
401 {
402 ULONG temp = pRectl[x].yBottom;
403 pRectl[x].yBottom = pRectl[x].yTop;
404 pRectl[x].yTop = temp;
405 }
406
407 success = GpiSetRegion(hpsRegion, winHrgn, rgnRect.crcReturned, pRectl);
408 }
409 delete[] pRectl;
410 }
411 else
412 {
413 success = GpiSetRegion(hpsRegion, winHrgn, 0, NULL);
414 }
415 }
416 }
417 else
418 success = FALSE;
419
420 if(mustReleaseScreenPS)
421 WinReleasePS(hps);
422
423 return success;
424}
425//******************************************************************************
426// GdiSetVisRgn
427//
428// Change the Win32 visible region to the specified region
429//
430// Parameters:
431//
432// pDCData pHps - presentation space structure
433// HRGN hrgn - region handle (GPI)
434//
435//
436// Returns: - ERROR_W -> failure
437// - NULLREGION_W -> empty region
438// - SIMPLEREGION_W -> rectangular region
439// - COMPLEXREGION_W -> complex region
440//
441// NOTE: In windows there is a clip and a visible region (just like in PM)
442// We do not map the Win32 visible region to the PM visible region
443// as that's rather annoying.
444// Instead we use the intersection of the win32 visible and win32 clip
445// region for the PM clip region.
446// The Win32 clip region is saved in pHps->hrgnWin32Clip.
447// The Win32 visible region is saved in pHps->hrgnWinVis.
448//
449//******************************************************************************
450INT WIN32API GdiSetVisRgn(pDCData pHps, HRGN hrgn)
451{
452 HRGN hrgnNewClip = NULLHANDLE, hrgnOldClip = NULLHANDLE;
453 LONG lComplexity = RGN_NULL;
454 RECTL rectl = {0, 0, 1, 1};
455
456 if(pHps == NULL) {
457 DebugInt3();
458 return ERROR_W;
459 }
460
461 if(hrgn != NULLHANDLE)
462 {
463 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
464 if(hrgnNewClip == NULLHANDLE) {
465 dprintf(("ERROR: GdiCombineVisRgn: GpiCreateRegion failed!!"));
466 DebugInt3();
467 goto failure;
468 }
469 //make a copy of the new visible region
470 lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, hrgn, NULLHANDLE, CRGN_COPY);
471 }
472 else {
473 hrgnNewClip = NULLHANDLE;
474 }
475
476 //and set that as the GPI clip region
477 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
478 if (lComplexity != RGN_ERROR)
479 {
480 //SvL: Must check if origin changed here. Sometimes happens when
481 // window looses focus. (don't know why....)
482 checkOrigin(pHps);
483
484 if(hrgnOldClip) GpiDestroyRegion(pHps->hps, hrgnOldClip);
485
486 dprintf(("New visible region %x", hrgn));
487 pHps->hrgnWinVis = hrgn;
488 return GPI_TO_WIN_COMPLEXITY(lComplexity);
489 }
490failure:
491 if(hrgnNewClip) GpiDestroyRegion(pHps->hps, hrgnNewClip);
492
493 return ERROR_W;
494}
495//******************************************************************************
496// GdiCombineVisRgn
497//
498// Combine the specified region with the visible region according to the operation
499//
500// Parameters:
501//
502// pDCData pHps - presentation space structure
503// HRGN hrgn - region handle (Win32)
504// INT operation - combine operation (RGN_*)
505//
506//
507// Returns: - ERROR_W -> failure
508// - NULLREGION_W -> empty region
509// - SIMPLEREGION_W -> rectangular region
510// - COMPLEXREGION_W -> complex region
511//
512// NOTE: In windows there is a clip and a visible region (just like in PM)
513// We do not map the Win32 visible region to the PM visible region
514// as that's rather annoying.
515// Instead we use the intersection of the win32 visible and win32 clip
516// region for the PM clip region.
517// The Win32 clip region is saved in pHps->hrgnWin32Clip.
518// The Win32 visible region is saved in pHps->hrgnWinVis.
519//
520//******************************************************************************
521INT WIN32API GdiCombineVisRgn(pDCData pHps, HRGN hrgn, INT operation)
522{
523#ifdef DEBUG
524 HRGN hrgn1 = hrgn;
525#endif
526 LONG lComplexity = RGN_NULL;
527
528 if(pHps == NULL) {
529 DebugInt3();
530 return ERROR_W;
531 }
532
533 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
534 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
535 dprintf(("ERROR: GdiCombineVisRgn %x invalid handle", hrgn1));
536 return ERROR_W;
537 }
538 //interpretRegionAs converts the region and saves it in pHps->hrgnHDC
539 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
540 {
541 dprintf(("ERROR: interpretRegionAs failed!!"));
542 return ERROR_W;
543 }
544
545 //If there is no visible region, then create one that covers the whole DC
546 if(pHps->hrgnWinVis == NULLHANDLE)
547 {
548 RECTL rectl = {0, 0, hdcWidth(0, pHps), hdcHeight(0, pHps)};
549 dprintf(("No visible region: create one (0,0)(%d,%d)", rectl.xRight, rectl.yTop));
550 pHps->hrgnWinVis = GpiCreateRegion(pHps->hps, 1, &rectl);
551 if(pHps->hrgnWinVis == NULLHANDLE) {
552 dprintf(("ERROR: GdiCombineVisRgn: GpiCreateRegion failed!!"));
553 DebugInt3();
554 goto failure;
555 }
556 }
557
558 LONG lMode;
559 switch (operation)
560 {
561 case RGN_AND_W : lMode = CRGN_AND ; break;
562 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
563 default:
564 dprintf(("ERROR: GdiCombineVisRgn %d invalid parameter", operation));
565 DebugInt3();
566 goto failure;
567 }
568 lComplexity = GpiCombineRegion(pHps->hps, pHps->hrgnWinVis, pHps->hrgnWinVis, pHps->hrgnHDC, lMode);
569 if (lComplexity != RGN_ERROR)
570 {
571 return GdiSetVisRgn(pHps, pHps->hrgnWinVis);
572 }
573 dprintf(("ERROR: GdiCombineVisRgn: GpiCombineRegion failed"));
574 DebugInt3();
575
576failure:
577 return ERROR_W;
578}
579//******************************************************************************
580// GdiCombineVisRgnClipRgn
581//
582// Combine the specified clip region with the visible region according to the operation
583//
584// Parameters:
585//
586// pDCData pHps - presentation space structure
587// HRGN hrgn - region handle (GPI)
588// INT operation - combine operation (RGN_*)
589//
590//
591// Returns: - ERROR_W -> failure
592// - NULLREGION_W -> empty region
593// - SIMPLEREGION_W -> rectangular region
594// - COMPLEXREGION_W -> complex region
595//
596// NOTE: In windows there is a clip and a visible region (just like in PM)
597// We do not map the Win32 visible region to the PM visible region
598// as that's rather annoying.
599// Instead we use the intersection of the win32 visible and win32 clip
600// region for the PM clip region.
601// The Win32 clip region is saved in pHps->hrgnWin32Clip.
602// The Win32 visible region is saved in pHps->hrgnWinVis.
603//
604//******************************************************************************
605INT WIN32API GdiCombineVisRgnClipRgn(pDCData pHps, HRGN hrgn, INT operation)
606{
607 HRGN hrgnClip = NULL, hrgnOldClip, hrgnNewClip;
608 LONG lComplexity = RGN_NULL;
609
610 //Create a region that will be used for the new GPI clip region
611 RECTL rectl = {0, 0, 1, 1};
612 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
613 if(hrgnNewClip == NULLHANDLE) {
614 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiCreateRegion failed!!"));
615 DebugInt3();
616 return ERROR_W;
617 }
618
619 if(hrgn == NULLHANDLE)
620 {
621 if(pHps->hrgnWin32Clip != NULL)
622 {
623 //Only reset the path if both the visible and clip regions are zero
624 if(!pHps->hrgnWinVis) {
625 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
626
627 GpiDestroyRegion(pHps->hps, hrgnNewClip);
628 hrgnNewClip = NULLHANDLE;
629 }
630 else
631 {//set PM clip region to Win32 visible region
632 lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, pHps->hrgnWinVis, NULLHANDLE, CRGN_COPY);
633 if(lComplexity == RGN_ERROR) {
634 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiSetClipRegion failed!!"));
635 DebugInt3();
636 goto failure;
637 }
638 }
639 dprintfRegion(pHps->hps, hrgnNewClip);
640 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
641 if(lComplexity == RGN_ERROR) {
642 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiSetClipRegion failed!!"));
643 DebugInt3();
644 }
645
646 //SvL: Must check if origin changed here. Sometimes happens when
647 // window looses focus. (don't know why....)
648 checkOrigin(pHps);
649 if(hrgnOldClip) GpiDestroyRegion(pHps->hps, hrgnOldClip);
650 }
651 //else already NULL, so nothing to do.
652
653 pHps->hrgnWin32Clip = hrgn;
654 return NULLREGION_W;
655 }
656
657 LONG lMode;
658 switch (operation)
659 {
660 case RGN_AND_W : lMode = CRGN_AND ; break; //intersect clip & visible region
661 default:
662 dprintf(("ERROR: GdiCombineVisRgnClipRgn %d invalid parameter", operation));
663 DebugInt3();
664 goto failure;
665 }
666 // If there's no visible region (meaning entire DC is visible), then just set
667 // the GPI clip region to the win32 clip region
668 if (pHps->hrgnWinVis == NULLHANDLE)
669 {
670 lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, hrgn, NULLHANDLE, CRGN_COPY);
671 }
672 else lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, pHps->hrgnWinVis, hrgn, lMode);
673
674 if (lComplexity != RGN_ERROR)
675 {
676 dprintfRegion(pHps->hps, hrgnNewClip);
677 //And activate the new clip region
678 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
679 if (lComplexity == RGN_ERROR )
680 {
681 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiSetClipRegion failed"));
682 DebugInt3();
683 goto failure;
684 }
685 //SvL: Must check if origin changed here. Sometimes happens when
686 // window looses focus. (don't know why....)
687 checkOrigin(pHps);
688
689 if(hrgnOldClip) GpiDestroyRegion(pHps->hps, hrgnOldClip);
690
691 pHps->hrgnWin32Clip = hrgn;
692
693 return GPI_TO_WIN_COMPLEXITY(lComplexity);
694 }
695 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiCombineRegion failed"));
696 DebugInt3();
697
698failure:
699 if(hrgnNewClip) GpiDestroyRegion(pHps->hps, hrgnNewClip);
700
701 return ERROR_W;
702}
703//******************************************************************************
704//******************************************************************************
705int WIN32API ExtSelectClipRgn(HDC hdc, HRGN hrgn, int mode)
706{
707#ifdef DEBUG
708 HRGN hrgn1 = hrgn;
709#endif
710
711 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
712 if (!pHps)
713 {
714 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid hdc", hdc, hrgn, mode));
715 SetLastError(ERROR_INVALID_HANDLE_W);
716 return ERROR_W;
717 }
718
719 LONG lComplexity;
720 HRGN hrgnCurrent = NULLHANDLE, hrgnOld = NULLHANDLE;
721
722 if(!hrgn && mode != RGN_COPY_W)
723 {
724 SetLastError(ERROR_INVALID_PARAMETER_W);
725 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
726 return ERROR_W;
727 }
728
729 LONG lMode;
730 switch (mode)
731 {
732 case RGN_AND_W : lMode = CRGN_AND ; break;
733 case RGN_COPY_W : lMode = CRGN_COPY; break;
734 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
735 case RGN_OR_W : lMode = CRGN_OR ; break;
736 case RGN_XOR_W : lMode = CRGN_XOR ; break;
737 default:
738 {
739 SetLastError(ERROR_INVALID_PARAMETER_W);
740 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
741 return ERROR_W;
742 }
743 }
744
745 if(hrgn)
746 {
747 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
748 if(hrgn == HANDLE_OBJ_ERROR) {
749 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid region handle", hdc, hrgn1, mode));
750 SetLastError(ERROR_INVALID_HANDLE_W);
751 return 0;
752 }
753 dprintfRegion(hdc, hrgn);
754 }
755
756 //TODO: metafile recording
757 if(hrgn)
758 {
759 //interpretRegionAs converts the region and saves it in pHps->hrgnHDC
760 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
761 {
762 return ERROR_W;
763 }
764 }
765 else
766 {
767 //Intersect the Windows clip region with the current visible region
768 lComplexity = GdiCombineVisRgnClipRgn(pHps, NULLHANDLE, RGN_AND_W);
769
770 return NULLREGION_W;
771 }
772
773 // get current clipping region
774 hrgnOld = pHps->hrgnWin32Clip;
775 hrgnCurrent = hrgnOld;
776
777 if(hrgnCurrent == NULLHANDLE)
778 {//if none, then create one
779 lMode = CRGN_COPY;
780 RECTL rectl = {0, 0, 1, 1};
781 hrgnCurrent = GpiCreateRegion(pHps->hps, 1, &rectl);
782 }
783
784 HRGN hrgnSrc1;
785 HRGN hrgnSrc2;
786 if(lMode != CRGN_COPY)
787 {
788 hrgnSrc1 = hrgnCurrent;
789 hrgnSrc2 = pHps->hrgnHDC;
790 }
791 else
792 {
793 hrgnSrc1 = pHps->hrgnHDC;
794 hrgnSrc2 = NULLHANDLE;
795 }
796
797 lComplexity = GpiCombineRegion(pHps->hps, hrgnCurrent, hrgnSrc1, hrgnSrc2, lMode);
798 if (lComplexity != RGN_ERROR)
799 {
800 HRGN hrgnOld;
801
802 //Intersect the Windows clip region with the current visible region
803 lComplexity = GdiCombineVisRgnClipRgn(pHps, hrgnCurrent, RGN_AND_W);
804
805 SetLastError(ERROR_SUCCESS_W);
806
807 if (lComplexity != RGN_ERROR) {
808 return lComplexity;
809 }
810 }
811 GpiDestroyRegion(pHps->hps, hrgnCurrent); //delete newly created region
812
813 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO
814 return ERROR_W;
815}
816//******************************************************************************
817//******************************************************************************
818int WIN32API SelectClipRgn(HDC hdc, HRGN hrgn)
819{
820 return ExtSelectClipRgn(hdc, hrgn, RGN_COPY_W);
821}
822//******************************************************************************
823// The GetClipBox function retrieves the dimensions of the tightest bounding
824// rectangle that can be drawn around the current visible area on the device.
825// The visible area is defined by the current clipping region or clip path, as well
826// as any overlapping windows.
827//
828// NOTE: We simply call GpiQueryClipBox as it behaves just like GetClipBox
829//
830//******************************************************************************
831int WIN32API GetClipBox(HDC hdc, PRECT lpRect)
832{
833 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
834 RECTL rectl;
835 LONG lComplexity;
836 int rc;
837
838 if(!hdc || !lpRect || !pHps) {
839 dprintf(("GDI32: GetClipBox %x %x ERROR_INVALID_PARAMETER", hdc, lpRect));
840 SetLastError(ERROR_INVALID_PARAMETER_W);
841 return ERROR_W;
842 }
843 if(pHps->isPrinter)
844 {
845 //Some printers return the wrong clip box. Return the full page instead.
846 //(TODO: which is incorrect!)
847 lpRect->left = 0;
848 lpRect->top = 0;
849 lpRect->right = GetDeviceCaps( hdc, HORZRES_W);
850 lpRect->bottom = GetDeviceCaps( hdc, VERTRES_W);
851 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
852 convertPMDeviceRectToWinWorldRect(pHps, &rectl);
853
854 rc = SIMPLEREGION_W;
855 }
856 else {
857 lComplexity = GpiQueryClipBox(pHps->hps, &rectl);
858 if(lComplexity == RGN_ERROR)
859 {
860 rc = ERROR_W;
861 }
862 else
863 if(lComplexity == RGN_NULL)
864 {
865 memset(lpRect, 0, sizeof(*lpRect));
866 rc = NULLREGION_W;
867 }
868 else {
869#ifndef INVERT
870 //Convert coordinates from PM to win32
871 if (pHps->yInvert > 0) {
872 LONG temp = pHps->yInvert - rectl.yBottom;
873 rectl.yBottom = pHps->yInvert - rectl.yTop;
874 rectl.yTop = temp;
875 }
876#endif
877 //Convert including/including to including/excluding
878 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
879
880 lpRect->left = rectl.xLeft;
881 lpRect->right = rectl.xRight;
882
883 if(rectl.yBottom > rectl.yTop) {
884 lpRect->top = rectl.yTop;
885 lpRect->bottom = rectl.yBottom;
886 }
887 else {
888 lpRect->top = rectl.yBottom;
889 lpRect->bottom = rectl.yTop;
890 }
891
892 rc = GPI_TO_WIN_COMPLEXITY(lComplexity);
893 }
894 }
895// if(lpRect->left == 0 && lpRect->top == 0 && lpRect->right == 0 && lpRect->bottom == 0)
896// DebugInt3();
897 dprintf(("GDI32: GetClipBox of %X returned %d; (%d,%d)(%d,%d)", hdc, rc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
898 return rc;
899}
900//******************************************************************************
901//******************************************************************************
902int WIN32API GetClipRgn(HDC hdc, HRGN hrgn)
903{
904 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
905 BOOL success;
906 LONG lComplexity = RGN_RECT;
907 HRGN hrgnClip = NULL, hrgnTemp;
908#ifdef DEBUG
909 HRGN hrgn1 = hrgn;
910#endif
911
912 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
913 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
914 dprintf(("WARNING: GetClipRgn %x %x invalid handle", hdc, hrgn1));
915 SetLastError(ERROR_INVALID_HANDLE_W);
916 return 0;
917 }
918
919 if(pHps->hrgnWin32Clip) {
920 dprintfRegion(hdc, pHps->hrgnWin32Clip);
921 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, pHps->hrgnWin32Clip, pHps, NULL)) {
922 dprintf(("WARNING: GetClipRgn setWinDeviceRegionFromPMDeviceRegion failed!"));
923 GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp);
924 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
925 return 0;
926 }
927 }
928 else {
929 //no clip region; return NULL
930 lComplexity = RGN_NULL;
931 }
932
933 SetLastError(ERROR_SUCCESS_W);
934 if(lComplexity == RGN_NULL)
935 return 0;
936 else return 1;
937}
938//******************************************************************************
939// The GetRandomRgn function copies the system clipping region of a specified
940// device context to a specific region.
941// It returns the visible region of the specified device context in screen
942// coordinates (if it belongs to a window).
943//
944// VALUE = 1: This undocumented value will return the current Clip Region contained in the DC.
945// VALUE = 2: This undocumented value will return the current Meta Region contained in the DC.
946// VALUE = 3: This undocumented value will return the intersection of the Clip Region and Meta Region.
947// VALUE = 4, SYSRGN: The only value that is documented and defined for this function.
948// This value returns the System Region
949//******************************************************************************
950INT WIN32API GetRandomRgn(HDC hdc, HRGN hrgn, INT iNum)
951{
952 HWND hwnd;
953 INT ret;
954
955 if(iNum != SYSRGN_W) {
956 dprintf(("WARNING: GetRandomRgn: invalid parameter %x", iNum));
957 SetLastError(ERROR_INVALID_PARAMETER_W);
958 return ERROR_W;
959 }
960 ret = GetClipRgn(hdc, hrgn);
961
962 hwnd = WindowFromDC(hdc);
963 if(hwnd) {
964 POINT pt = {0,0};
965 //map from client to desktop coordinates
966 MapWindowPoints(hwnd, 0, &pt, 1);
967
968 OffsetRgn(hrgn, pt.x, pt.y);
969 }
970 return ret;
971}
972//******************************************************************************
973//******************************************************************************
974int WIN32API ExcludeClipRect(HDC hdc, int left, int top, int right, int bottom)
975{
976 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
977 if(!pHps)
978 {
979 dprintf(("ERROR: ExcludeClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
980 SetLastError(ERROR_INVALID_HANDLE_W);
981 return ERROR_W;
982 }
983
984 LONG lComplexity;
985 RECTL rectl = { left, bottom, right, top };
986
987 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
988 if(rectl.yTop < rectl.yBottom) {
989 ULONG temp = rectl.yBottom;
990 rectl.yBottom = rectl.yTop;
991 rectl.yTop = temp;
992 }
993
994#ifndef INVERT
995 if (pHps->yInvert > 0) {
996 LONG temp = pHps->yInvert - rectl.yBottom;
997 rectl.yBottom = pHps->yInvert - rectl.yTop;
998 rectl.yTop = temp;
999 }
1000#endif
1001
1002 dprintf(("ExcludeClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
1003
1004 lComplexity = GpiExcludeClipRectangle(pHps->hps, &rectl);
1005 if (lComplexity == RGN_ERROR) {
1006 dprintf(("ERROR: ExcludeClipRgn: GpiExcludeClipRectangle failed!!"));
1007 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1008 return ERROR_W;
1009 }
1010
1011 //Ok, success. Now update the cached win32 clip region
1012 if(pHps->hrgnWin32Clip != NULLHANDLE)
1013 {
1014 HRGN hrgnClipRect = GpiCreateRegion(pHps->hps, 1, &rectl);
1015 if(hrgnClipRect == NULLHANDLE) {
1016 dprintf(("ERROR: ExcludeClipRgn GpiCreateRegion failed!!"));
1017 DebugInt3();
1018 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1019 return ERROR_W;
1020 }
1021 //subtract rect region from clip region
1022 lComplexity = GpiCombineRegion(pHps->hps, pHps->hrgnWin32Clip, pHps->hrgnWin32Clip, hrgnClipRect, CRGN_DIFF);
1023 GpiDestroyRegion(pHps->hps, hrgnClipRect);
1024
1025 if (lComplexity == RGN_ERROR) {
1026 dprintf(("ERROR: ExcludeClipRgn GpiCombineRegion failed!!"));
1027 DebugInt3();
1028 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1029 return ERROR_W;
1030 }
1031 }
1032
1033 //todo metafile recording
1034
1035 SetLastError(ERROR_SUCCESS_W);
1036 return lComplexity;
1037}
1038//******************************************************************************
1039//******************************************************************************
1040int WIN32API IntersectClipRect(HDC hdc, int left, int top, int right, int bottom)
1041{
1042 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1043 LONG lComplexity;
1044 BOOL success;
1045
1046 if(!pHps) {
1047 dprintf(("WARNING: IntersectClipRect %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
1048 SetLastError(ERROR_INVALID_HANDLE_W);
1049 return ERROR_W;
1050 }
1051 RECTL rectl = { left, bottom, right, top };
1052
1053 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
1054 if(rectl.yTop < rectl.yBottom) {
1055 ULONG temp = rectl.yBottom;
1056 rectl.yBottom = rectl.yTop;
1057 rectl.yTop = temp;
1058 }
1059
1060#ifndef INVERT
1061 //Convert coordinates from PM to win32
1062 if (pHps->yInvert > 0) {
1063 LONG temp = pHps->yInvert - rectl.yBottom;
1064 rectl.yBottom = pHps->yInvert - rectl.yTop;
1065 rectl.yTop = temp;
1066 }
1067#endif
1068
1069 dprintf(("IntersectClipRect %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
1070 lComplexity = GpiIntersectClipRectangle(pHps->hps, &rectl);
1071 if (lComplexity == RGN_ERROR) {
1072 dprintf(("ERROR: IntersectClipRect: GpiIntersectClipRectangle failed!!"));
1073 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1074 return ERROR_W;
1075 }
1076
1077 //Ok, success. Now update the cached win32 clip region
1078 if(pHps->hrgnWin32Clip != NULLHANDLE)
1079 {
1080 HRGN hrgnClipRect = GpiCreateRegion(pHps->hps, 1, &rectl);
1081 if(hrgnClipRect == NULLHANDLE) {
1082 dprintf(("ERROR: IntersectClipRect GpiCreateRegion failed!!"));
1083 DebugInt3();
1084 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1085 return ERROR_W;
1086 }
1087 //intersect rect region with clip region
1088 lComplexity = GpiCombineRegion(pHps->hps, pHps->hrgnWin32Clip, pHps->hrgnWin32Clip, hrgnClipRect, CRGN_AND);
1089 GpiDestroyRegion(pHps->hps, hrgnClipRect);
1090
1091 if (lComplexity == RGN_ERROR) {
1092 dprintf(("ERROR: IntersectClipRect GpiCombineRegion failed!!"));
1093 DebugInt3();
1094 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1095 return ERROR_W;
1096 }
1097 }
1098
1099 //todo metafile recording
1100
1101 SetLastError(ERROR_SUCCESS_W);
1102 return lComplexity;
1103}
1104//******************************************************************************
1105//******************************************************************************
1106int WIN32API OffsetClipRgn(HDC hdc, int nXOffset, int nYOffset )
1107{
1108 BOOL success;
1109 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1110 LONG lComplexity;
1111
1112 if(!pHps) {
1113 dprintf(("OffsetClipRgn %x (%d,%d) invalid hdc", hdc, nXOffset, nYOffset));
1114 SetLastError(ERROR_INVALID_HANDLE_W);
1115 return ERROR_W;
1116 }
1117
1118 dprintf(("OffsetClipRgn %x (%d,%d)", hdc, nXOffset, nYOffset));
1119 POINTL pointl = { nXOffset, nYOffset };
1120#ifndef INVERT
1121 if (pHps->yInvert > 0) {
1122 pointl.y = pHps->yInvert - pointl.y;
1123 }
1124#endif
1125
1126 if(pHps->hrgnWin32Clip == NULLHANDLE) {
1127 lComplexity = NULLREGION_W;
1128 }
1129 else {
1130 lComplexity = GpiOffsetRegion(pHps->hps, pHps->hrgnWin32Clip, &pointl);
1131 if (lComplexity == RGN_ERROR) {
1132 dprintf(("ERROR: OffsetClipRgn: GpiOffsetRegion failed!!"));
1133 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1134 return ERROR_W;
1135 }
1136
1137 //Intersect the Windows clip region with the current visible region
1138 lComplexity = GdiCombineVisRgnClipRgn(pHps, pHps->hrgnWin32Clip, RGN_AND_W);
1139
1140 lComplexity = GPI_TO_WIN_COMPLEXITY(lComplexity);
1141 }
1142
1143 //todo metafile recording
1144
1145 SetLastError(ERROR_SUCCESS_W);
1146 return lComplexity;
1147}
1148//******************************************************************************
1149//******************************************************************************
1150HRGN WIN32API CreatePolyPolygonRgn(const POINT *lppt, const int *pPolyCount,
1151 int nCount, int fnPolyFillMode)
1152{
1153 LONG flMode;
1154
1155 switch(fnPolyFillMode)
1156 {
1157 case ALTERNATE_W:
1158 flMode = POLYGON_ALTERNATE;
1159 break;
1160 case WINDING_W:
1161 flMode = POLYGON_WINDING;
1162 break;
1163 default:
1164 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
1165 SetLastError(ERROR_INVALID_PARAMETER_W);
1166 return 0;
1167 }
1168
1169 if(nCount < 1)
1170 {
1171 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
1172 SetLastError(ERROR_INVALID_PARAMETER_W);
1173 return 0;
1174 }
1175
1176 PPOLYGON pPolygon = new POLYGON[nCount];
1177 if(!pPolygon) {
1178 dprintf(("ERROR: CreatePolyPolygonRgn: out of memory!!"));
1179 SetLastError(ERROR_OUTOFMEMORY_W);
1180 return 0;
1181 }
1182 dprintf(("CreatePolyPolygonRgn %x %x %d %d", lppt, pPolyCount, nCount, fnPolyFillMode));
1183
1184 PPOINTL pPointl = (PPOINTL)lppt+1; // skip first point
1185 for (int x=0; x < nCount; x++) {
1186 pPolygon[x].ulPoints = (x == 0) ? pPolyCount[x] - 1 : pPolyCount[x];
1187 pPolygon[x].aPointl = pPointl;
1188 pPointl += pPolygon[x].ulPoints;
1189 }
1190 GpiMove(hpsRegion, (PPOINTL)lppt);
1191 HRGN hrgn = GpiCreatePolygonRegion(hpsRegion, nCount, pPolygon, POLYGON_BOUNDARY | flMode);
1192
1193 delete[] pPolygon;
1194
1195 if(!hrgn) {
1196 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1197 return 0;
1198 }
1199
1200 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1201 GpiDestroyRegion(hpsRegion, hrgn);
1202 SetLastError(ERROR_OUTOFMEMORY_W);
1203 return 0;
1204 }
1205 STATS_CreatePolyPolygonRgn(hrgn, lppt, pPolyCount, nCount, fnPolyFillMode);
1206
1207 SetLastError(ERROR_SUCCESS_W);
1208 return hrgn;
1209}
1210//******************************************************************************
1211//******************************************************************************
1212HRGN WIN32API CreateRectRgn(int left, int top, int right, int bottom)
1213{
1214 HRGN hrgn;
1215 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
1216
1217 hrgn = GpiCreateRegion(hpsRegion, 1, &rectl);
1218 if(!hrgn) {
1219 dprintf(("WARNING: CreateRectRgn: GpiCreateRectRegion failed! %x", WinGetLastError(0)));
1220 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1221 return 0;
1222 }
1223
1224 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1225 GpiDestroyRegion(hpsRegion, hrgn);
1226 SetLastError(ERROR_OUTOFMEMORY_W);
1227 return 0;
1228 }
1229 STATS_CreateRectRgn(hrgn, left, top, right, bottom);
1230
1231 dprintf(("CreateRectRegion (%d,%d)(%d,%d) returned %x", left, top, right, bottom, hrgn));
1232 SetLastError(ERROR_SUCCESS_W);
1233 return hrgn;
1234}
1235//******************************************************************************
1236//******************************************************************************
1237HRGN WIN32API CreateRectRgnIndirect( const RECT * lprc)
1238{
1239 return CreateRectRgn(lprc->left, lprc->top, lprc->right, lprc->bottom);
1240}
1241//******************************************************************************
1242//******************************************************************************
1243HRGN WIN32API CreateRoundRectRgn(int left, int top, int right, int bottom, int nWidthEllipse, int nHeightEllipse)
1244{
1245 HRGN hrgn;
1246 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
1247
1248 PPOINTL pPointl = (PPOINTL)&rectl;
1249
1250 GpiMove(hpsRegion, &pPointl[0]);
1251 hrgn = GpiCreateRoundRectRegion(hpsRegion, &pPointl[1], labs(nWidthEllipse), labs(nHeightEllipse));
1252
1253 if(!hrgn) {
1254 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1255 dprintf(("WARNING: CreateRoundRectRgn: GpiCreateRoundRectRegion failed! %x", WinGetLastError(0)));
1256 return 0;
1257 }
1258
1259 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1260 GpiDestroyRegion(hpsRegion, hrgn);
1261 SetLastError(ERROR_OUTOFMEMORY_W);
1262 return 0;
1263 }
1264 STATS_CreateRoundRectRgn(hrgn, left, top, right, bottom, nWidthEllipse, nHeightEllipse);
1265
1266 dprintf(("CreateRoundRectRegion (%d,%d)(%d,%d) (%d,%d) returned %x", left, top, right, bottom, nWidthEllipse, nHeightEllipse, hrgn));
1267 SetLastError(ERROR_SUCCESS_W);
1268 return hrgn;
1269}
1270//******************************************************************************
1271//******************************************************************************
1272HRGN WIN32API ExtCreateRegion(const XFORM_W * pXform, DWORD count,
1273 const RGNDATA * pData)
1274{
1275 HRGN hrgn;
1276
1277 if(!pData || count < (sizeof(RGNDATAHEADER) + pData->rdh.nCount * sizeof(RECT))) {
1278 dprintf(("WARNING: ExtCreateRegion %x %d %x; invalid parameter", pXform, count, pData));
1279 SetLastError(ERROR_INVALID_PARAMETER_W);
1280 return 0;
1281 }
1282
1283 PRECTL pRectl = new RECTL[pData->rdh.nCount];
1284 PRECT pDataRects = (PRECT)pData->Buffer;
1285 for(int i=0; i < pData->rdh.nCount; i++) {
1286 MapWin32ToOS2Rect(pDataRects[i], pRectl[i]);
1287 }
1288
1289 BOOL doShear = pXform && (pXform->eM12 || pXform->eM21);
1290 HPS hpsTemp = NULLHANDLE;
1291
1292 dprintf(("ExtCreateRegion %x %d %x", pXform, count, pData));
1293 if(doShear) {
1294 hpsTemp = WinGetPS(HWND_DESKTOP);
1295 GpiBeginPath(hpsTemp, 1);
1296
1297 MATRIXLF matrixlf;
1298 matrixlf.fxM11 = pXform->eM11 * (float)0x10000;
1299 matrixlf.fxM12 = pXform->eM12 * (float)0x10000;
1300 matrixlf.lM13 = 0;
1301 matrixlf.fxM21 = pXform->eM21 * (float)0x10000;
1302 matrixlf.fxM22 = pXform->eM22 * (float)0x10000;
1303 matrixlf.lM23 = 0;
1304 matrixlf.lM31 = pXform->eDx;
1305 matrixlf.lM32 = pXform->eDy;
1306 matrixlf.lM33 = 1;
1307
1308 GpiSetModelTransformMatrix(hpsTemp, 9, &matrixlf, TRANSFORM_REPLACE);
1309 }
1310
1311 for(i=0; i < pData->rdh.nCount; i++)
1312 {
1313 LONG temp = pRectl[i].yTop;
1314 pRectl[i].yTop = pRectl[i].yBottom;
1315 pRectl[i].yBottom = temp;
1316
1317 if(pXform)
1318 {
1319 PPOINTL pPointl = ((PPOINTL)&pRectl[i]);
1320
1321 if (doShear) {
1322 GpiMove(hpsTemp, pPointl);
1323 GpiBox(hpsTemp, DRO_OUTLINE, pPointl+1, 0, 0);
1324 }
1325 else
1326 {
1327 for(int j=0; j < 2; j++) {
1328 pPointl[j].x = (pXform->eM11 * (float)pPointl[j].x) + (pXform->eM12 * (float)pPointl[j].y) + pXform->eDx;
1329 pPointl[j].y = (pXform->eM21 * (float)pPointl[j].x) + (pXform->eM22 * (float)pPointl[j].y) + pXform->eDy;
1330 }
1331
1332 PRECTL pRectlT = (PRECTL)pPointl;
1333 if (pRectlT->xLeft > pRectlT->xRight) {
1334 LONG temp = pRectlT->xLeft;
1335 pRectlT->xLeft = pRectlT->xRight;
1336 pRectlT->xRight = temp;
1337 }
1338 if (pRectlT->yBottom > pRectlT->yTop) {
1339 LONG temp = pRectlT->yBottom;
1340 pRectlT->yBottom = pRectlT->yTop;
1341 pRectlT->yTop = temp;
1342 }
1343 }
1344 }
1345 }
1346
1347 if(doShear) {
1348 GpiEndPath(hpsTemp);
1349 hrgn = GpiPathToRegion(hpsTemp, 1, FPATH_WINDING);
1350
1351 if(pRectl)
1352 delete[] pRectl;
1353
1354 if(hrgn == 0) {
1355 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
1356 SetLastError(ERROR_INVALID_PARAMETER_W);
1357 return 0;
1358 }
1359 WinReleasePS(hpsTemp);
1360 }
1361 else {
1362 hrgn = GpiCreateRegion(hpsRegion, pData->rdh.nCount, pRectl);
1363 if(pRectl)
1364 delete[] pRectl;
1365
1366 if(hrgn == 0) {
1367 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
1368 SetLastError(ERROR_INVALID_PARAMETER_W);
1369 return 0;
1370 }
1371 }
1372
1373 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1374 GpiDestroyRegion(hpsRegion, hrgn);
1375 SetLastError(ERROR_OUTOFMEMORY_W);
1376 return 0;
1377 }
1378 STATS_ExtCreateRegion(hrgn, (PVOID)pXform, count, pData);
1379 SetLastError(ERROR_SUCCESS_W);
1380 return hrgn;
1381}
1382//******************************************************************************
1383//******************************************************************************
1384HRGN WIN32API CreateEllipticRgn(int left, int top, int right, int bottom)
1385{
1386 HRGN hrgn;
1387
1388 RECTL rectl = { left,
1389 top < bottom ? top : bottom,
1390 right,
1391 top < bottom ? bottom : top };
1392
1393 dprintf(("CreateEllipticRgn (%d,%d)(%d,%d)", left, top, right, bottom));
1394 hrgn = GpiCreateEllipticRegion(hpsRegion, &rectl);
1395 if(hrgn == RGN_ERROR) {
1396 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1397 dprintf(("WARNING: CreateEllipticRgn: GpiCreateEllipticRegion failed! %x", WinGetLastError(0)));
1398 return 0;
1399 }
1400
1401 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1402 GpiDestroyRegion(hpsRegion, hrgn);
1403 SetLastError(ERROR_OUTOFMEMORY_W);
1404 return 0;
1405 }
1406 STATS_CreateEllipticRgn(hrgn, left, top, right, bottom);
1407 SetLastError(ERROR_SUCCESS_W);
1408 return hrgn;
1409}
1410//******************************************************************************
1411//******************************************************************************
1412HRGN WIN32API CreateEllipticRgnIndirect(const RECT *pRect)
1413{
1414 return CreateEllipticRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
1415}
1416//******************************************************************************
1417//******************************************************************************
1418HRGN WIN32API CreatePolygonRgn(const POINT * lppt, int cPoints, int fnPolyFillMode)
1419{
1420 HRGN hrgn;
1421 LONG flMode;
1422
1423 if(!lppt || cPoints < 2) {
1424 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1425 SetLastError(ERROR_INVALID_PARAMETER_W);
1426 return 0;
1427 }
1428
1429 switch (fnPolyFillMode)
1430 {
1431 case ALTERNATE_W :
1432 flMode = POLYGON_ALTERNATE;
1433 break;
1434 case WINDING_W :
1435 flMode = POLYGON_WINDING;
1436 break;
1437 default:
1438 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1439 SetLastError(ERROR_INVALID_PARAMETER_W);
1440 return 0;
1441 }
1442 dprintf(("CreatePolygonRgn %x %d %d", lppt, cPoints, fnPolyFillMode));
1443
1444 POLYGON polygon;
1445 polygon.ulPoints = cPoints - 1;
1446 polygon.aPointl = (PPOINTL)(lppt + 1);
1447
1448#ifdef DEBUG
1449 for(int i=0;i<cPoints;i++) {
1450 dprintf(("Point %d: (%d,%d)", i, lppt[i].x, lppt[i].y));
1451 }
1452#endif
1453 GpiMove(hpsRegion, (PPOINTL)lppt);
1454 hrgn = GpiCreatePolygonRegion(hpsRegion, 1, &polygon, POLYGON_BOUNDARY | flMode);
1455 if(hrgn == RGN_ERROR) {
1456 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1457 dprintf(("WARNING: CreatePolygonRgn: GpiCreatePolygonRegion failed! %x", WinGetLastError(0)));
1458 return 0;
1459 }
1460
1461 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1462 GpiDestroyRegion(hpsRegion, hrgn);
1463 SetLastError(ERROR_OUTOFMEMORY_W);
1464 return 0;
1465 }
1466 STATS_CreatePolygonRgn(hrgn, lppt, cPoints, fnPolyFillMode);
1467 SetLastError(ERROR_SUCCESS_W);
1468 return hrgn;
1469}
1470//******************************************************************************
1471//******************************************************************************
1472int WIN32API CombineRgn(HRGN hrgnDest, HRGN hrgnSrc1, HRGN hrgnSrc2, int combineMode)
1473{
1474 ULONG lComplexity;
1475 LONG mode;
1476#ifdef DEBUG
1477 HRGN hrgn1 = hrgnDest;
1478 HRGN hrgn2 = hrgnSrc1;
1479 HRGN hrgn3 = hrgnSrc2;
1480#endif
1481
1482 switch(combineMode) {
1483 case RGN_AND_W:
1484 mode = CRGN_AND;
1485 break;
1486 case RGN_COPY_W:
1487 mode = CRGN_COPY;
1488 break;
1489 case RGN_DIFF_W:
1490 mode = CRGN_DIFF;
1491 break;
1492 case RGN_OR_W:
1493 mode = CRGN_OR;
1494 break;
1495 case RGN_XOR_W:
1496 mode = CRGN_XOR;
1497 break;
1498 default:
1499 dprintf(("WARNING: CombineRgn %x %x %x %d; invalid mode!", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1500 SetLastError(ERROR_INVALID_PARAMETER_W);
1501 return ERROR_W;
1502 }
1503
1504 hrgnDest = ObjQueryHandleData(hrgnDest, HNDL_REGION);
1505 hrgnSrc1 = ObjQueryHandleData(hrgnSrc1, HNDL_REGION);
1506 hrgnSrc2 = ObjQueryHandleData(hrgnSrc2, HNDL_REGION);
1507 if(hrgnDest == HANDLE_OBJ_ERROR || hrgnSrc1 == HANDLE_OBJ_ERROR || (hrgnSrc2 == HANDLE_OBJ_ERROR && combineMode != RGN_COPY_W)) {
1508 dprintf(("WARNING: CombineRgn %x %x %x %d invalid region", hrgn1, hrgn2, hrgn3, combineMode));
1509 SetLastError(ERROR_INVALID_HANDLE_W);
1510 return ERROR_W;
1511 }
1512
1513 lComplexity = GpiCombineRegion(hpsRegion, hrgnDest, hrgnSrc1, hrgnSrc2, mode);
1514 if(lComplexity == RGN_ERROR) {
1515 dprintf(("WARNING: CombineRgn %x %x %x %d GpiCombineRegion failed (%x)", hrgn1, hrgn2, hrgn3, mode, WinGetLastError(0)));
1516 SetLastError(ERROR_INVALID_HANDLE_W);
1517 return ERROR_W;
1518 }
1519 SetLastError(ERROR_SUCCESS_W);
1520 return lComplexity;
1521}
1522//******************************************************************************
1523//******************************************************************************
1524BOOL WIN32API EqualRgn(HRGN hrgn1, HRGN hrgn2)
1525{
1526 LONG lEquality;
1527#ifdef DEBUG
1528 HRGN hrgnt1 = hrgn1;
1529 HRGN hrgnt2 = hrgn2;
1530#endif
1531
1532 hrgn1 = ObjQueryHandleData(hrgn1, HNDL_REGION);
1533 hrgn2 = ObjQueryHandleData(hrgn2, HNDL_REGION);
1534 if(hrgn1 == HANDLE_OBJ_ERROR || hrgn2 == HANDLE_OBJ_ERROR) {
1535 dprintf(("WARNING: EqualRgn %x %x invalid region", hrgnt1, hrgnt2));
1536 SetLastError(ERROR_INVALID_HANDLE_W);
1537 return FALSE;
1538 }
1539 lEquality = GpiEqualRegion(hpsRegion, hrgn1, hrgn2);
1540
1541 dprintf(("EqualRgn %x %x = %d", hrgnt1, hrgnt2, lEquality));
1542 SetLastError(ERROR_SUCCESS_W);
1543
1544 if(lEquality == EQRGN_EQUAL)
1545 return TRUE;
1546 else
1547 if(lEquality == EQRGN_NOTEQUAL)
1548 return FALSE;
1549 else {
1550 return FALSE;
1551 }
1552}
1553//******************************************************************************
1554//******************************************************************************
1555BOOL WIN32API SetRectRgn(HRGN hrgn, int left, int top, int right, int bottom)
1556{
1557 BOOL result = FALSE;
1558#ifdef DEBUG
1559 HRGN hrgn1 = hrgn;
1560#endif
1561
1562 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1563 if(hrgn == HANDLE_OBJ_ERROR) {
1564 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) invalid region handle", hrgn1, left, top, right, bottom));
1565 SetLastError(ERROR_INVALID_HANDLE_W);
1566 return 0;
1567 }
1568 RECTL rectl = { left, top, right, bottom }; //reversed y coordinates
1569 if(GpiSetRegion(hpsRegion, hrgn, 1, &rectl)) {
1570 dprintf(("SetRectRgn %x (%d,%d)(%d,%d)", hrgn1, left, top, right, bottom));
1571 return TRUE;
1572 }
1573 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) GpiSetRegion failed %x", hrgn1, left, top, right, bottom, WinGetLastError(0)));
1574 return FALSE;
1575}
1576//******************************************************************************
1577//NOTE: depends on hps inversion
1578//******************************************************************************
1579ULONG WIN32API GetRegionData( HRGN hrgn, ULONG count, PRGNDATA pData)
1580{
1581#ifdef DEBUG
1582 HRGN hrgn1 = hrgn;
1583#endif
1584
1585 if(!count && pData)
1586 {
1587 dprintf(("WARNING: GetRegionData %x %d %x; invalid parameter", hrgn1, count, pData));
1588 SetLastError(ERROR_INVALID_PARAMETER_W);
1589 return 0;
1590 }
1591 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1592 if(hrgn == HANDLE_OBJ_ERROR) {
1593 dprintf(("WARNING: GetRegionData %x %d %x; invalid region handle", hrgn1, count, pData));
1594 SetLastError(ERROR_INVALID_HANDLE_W);
1595 return 0;
1596 }
1597 RGNRECT rgnRect;
1598 rgnRect.ircStart = 1;
1599 rgnRect.crc = 0;
1600 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
1601 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1602 {
1603 dprintf(("WARNING: GetRegionData %x %d %x: GpiQueryRegionRects failed! (%x)", hrgn1, count, pData, WinGetLastError(0)));
1604 return 0;
1605 }
1606
1607 dprintf(("GetRegionData %x %d %x", hrgn1, count, pData));
1608
1609 ULONG bufSizeNeeded = rgnRect.crcReturned * sizeof(RECT) + sizeof (RGNDATAHEADER);
1610
1611 if(pData && (count >= (sizeof(RGNDATAHEADER) + rgnRect.crcReturned * sizeof(RECT))))
1612 {
1613 //we actually need to flip the top & bottom values, but as the layout of the PM RECTL and
1614 //Win32 RECT have exactly those two members reversed, we don't do this for the returned
1615 //rectangles (more efficient)
1616 PRECTL pRectl = (PRECTL)pData->Buffer;
1617 rgnRect.crc = rgnRect.crcReturned;
1618 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, pRectl))
1619 {
1620 dprintf(("WARNING: GetRegionData: GpiQueryRegionRects failed! (%x)", WinGetLastError(0)));
1621 return 0;
1622 }
1623
1624 RECTL boundRect;
1625 GpiQueryRegionBox(hpsRegion, hrgn, &boundRect); // no need to check rc
1626
1627 pData->rdh.dwSize = sizeof(pData->rdh);
1628 pData->rdh.iType = RDH_RECTANGLES_W; // one and only possible value
1629 pData->rdh.nCount = rgnRect.crcReturned;
1630 pData->rdh.nRgnSize = rgnRect.crcReturned * sizeof(RECT);
1631
1632 //flip top & bottom for bounding rectangle (not really necessary; but cleaner coding)
1633 LONG temp = boundRect.yTop;
1634 boundRect.yTop = boundRect.yBottom;
1635 boundRect.yBottom = temp;
1636 MapOS2ToWin32Rect(boundRect, pData->rdh.rcBound);
1637 }
1638
1639 //return size needed
1640 return bufSizeNeeded;
1641}
1642//******************************************************************************
1643//******************************************************************************
1644int WIN32API GetRgnBox( HRGN hrgn, PRECT pRect)
1645{
1646 BOOL success;
1647 LONG lComplexity;
1648#ifdef DEBUG
1649 HRGN hrgn1 = hrgn;
1650#endif
1651
1652 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1653 if(hrgn == HANDLE_OBJ_ERROR) {
1654 dprintf(("WARNING: GetRgnBox %x %x invalid region!", hrgn1, pRect));
1655 SetLastError(ERROR_INVALID_HANDLE_W);
1656 return ERROR_W;
1657 }
1658
1659 RECTL rectl;
1660 lComplexity = GpiQueryRegionBox(hpsRegion, hrgn, &rectl);
1661 if(lComplexity != RGN_ERROR)
1662 {
1663 //no conversion required, just flip top & bottom
1664 ULONG temp = rectl.yBottom;
1665 rectl.yBottom = rectl.yTop;
1666 rectl.yTop = temp;
1667
1668 MapOS2ToWin32Rect(rectl, *pRect);
1669 }
1670 else {
1671 lComplexity = ERROR_W;
1672 dprintf(("WARNING: GetRgnBox error in region!"));
1673 }
1674 dprintf(("GetRgnBox %x (%d,%d)(%d,%d)", hrgn1, pRect->left, pRect->top, pRect->right, pRect->bottom));
1675
1676 SetLastError(ERROR_SUCCESS_W);
1677 return lComplexity;
1678}
1679//******************************************************************************
1680//******************************************************************************
1681BOOL WIN32API InvertRgn( HDC hdc, HRGN hrgn)
1682{
1683#ifdef DEBUG
1684 HRGN hrgn1 = hrgn;
1685#endif
1686 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1687
1688 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1689 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1690 dprintf(("WARNING: InvertRgn %x %x invalid handle!", hdc, hrgn));
1691 SetLastError(ERROR_INVALID_HANDLE_W);
1692 return FALSE;
1693 }
1694 //todo metafile recording
1695
1696 dprintf(("InvertRgn %x %x", hdc, hrgn1));
1697
1698 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1699
1700 LONG lHits = GPI_ERROR;
1701 HRGN hrgnOld;
1702 LONG lComplexity ;
1703 RECTL boundingRect; // this gets a rectangle in world cordinates!
1704
1705 lComplexity = GpiQueryRegionBox(pHps->hps, pHps->hrgnHDC, &boundingRect);
1706 if(lComplexity != RGN_ERROR)
1707 {
1708 lComplexity = GpiSetClipRegion(pHps->hps, pHps->hrgnHDC, &hrgnOld);
1709 if(lComplexity != RGN_ERROR)
1710 {
1711 RECTL rectls[2];
1712 rectls[0] = boundingRect;
1713 rectls[1] = boundingRect;
1714 lHits = GpiBitBlt(pHps->hps, NULL, 3, (PPOINTL)rectls,
1715 ROP_DSTINVERT, 0);
1716
1717 /* Restore the old region */
1718 GpiSetClipRegion(pHps->hps, hrgnOld, &hrgnOld);
1719 }
1720 }
1721
1722 if(lHits == GPI_ERROR || lComplexity == RGN_ERROR)
1723 {
1724 dprintf(("WARNING: InvertRgn error during Gpi operation (%x) (%d,%d)", WinGetLastError(0), lHits, lComplexity));
1725 return FALSE;
1726 }
1727
1728 DIBSECTION_MARK_INVALID(hdc);
1729 return TRUE;
1730}
1731//******************************************************************************
1732//******************************************************************************
1733int WIN32API OffsetRgn( HRGN hrgn, int xOffset, int yOffset)
1734{
1735 LONG lComplexity;
1736#ifdef DEBUG
1737 HRGN hrgn1 = hrgn;
1738#endif
1739
1740 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1741 if(hrgn == HANDLE_OBJ_ERROR) {
1742 dprintf(("WARNING: OffsetRgn %x %d %d invalid handle!", hrgn, xOffset, yOffset));
1743 SetLastError(ERROR_INVALID_HANDLE_W);
1744 return ERROR_W;
1745 }
1746 dprintf(("OffsetRgn %x %d %d", hrgn1, xOffset, yOffset));
1747
1748 POINTL ptlOffset = {xOffset, yOffset};
1749 GpiOffsetRegion(hpsRegion, hrgn, &ptlOffset);
1750
1751 RECTL rectl[8];
1752 RGNRECT rgnRect;
1753 rgnRect.ircStart = 1;
1754 rgnRect.crc = 8;
1755 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference
1756 if(GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, &rectl[0]))
1757 {
1758 switch (rgnRect.crcReturned) {
1759 case 0:
1760 lComplexity = NULLREGION_W;
1761 break;
1762 case 1:
1763 lComplexity = SIMPLEREGION_W;
1764 break;
1765 default:
1766 lComplexity = COMPLEXREGION_W;
1767 break;
1768 }
1769 }
1770 else {
1771 lComplexity = ERROR_W;
1772 dprintf(("WARNING: OffsetRgn error in region! (%x)", WinGetLastError(0)));
1773 }
1774
1775 SetLastError(ERROR_SUCCESS_W);
1776
1777 return lComplexity;
1778}
1779//******************************************************************************
1780//******************************************************************************
1781BOOL WIN32API FrameRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush, int width, int height)
1782{
1783 HBRUSH hbrushRestore = 0;
1784#ifdef DEBUG
1785 HRGN hrgn1 = hrgn;
1786#endif
1787 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1788
1789 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1790 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1791 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid handle!", hdc, hrgn, hBrush, width, height));
1792 SetLastError(ERROR_INVALID_HANDLE_W);
1793 return FALSE;
1794 }
1795
1796 width = abs(width);
1797 height = abs(height);
1798
1799 if(pHps->lastBrushKey != (UINT)hBrush)
1800 {
1801 hbrushRestore = SelectObject(hdc, hBrush);
1802 if(!hbrushRestore)
1803 {
1804 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid brush!", hdc, hrgn, hBrush, width, height));
1805 SetLastError(ERROR_INVALID_HANDLE_W);
1806 return FALSE;
1807 }
1808 }
1809 dprintf(("FrameRgn %x %x %x (%d,%d)", hdc, hrgn1, hBrush, width, height));
1810 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1811
1812 SIZEL thickness = { width, height };
1813 LONG lHits = GpiFrameRegion(pHps->hps, pHps->hrgnHDC, &thickness);
1814
1815 SetLastError(ERROR_SUCCESS_W);
1816
1817 // Restore the brush if necessary
1818 if(hbrushRestore)
1819 SelectObject(hdc, hbrushRestore);
1820
1821 if(lHits != GPI_ERROR)
1822 DIBSECTION_MARK_INVALID(hdc);
1823
1824 //todo metafile recording
1825 return (lHits != GPI_ERROR);
1826}
1827//******************************************************************************
1828//******************************************************************************
1829BOOL WIN32API FillRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush)
1830{
1831 BOOL success;
1832 HBRUSH hbrushRestore = 0;
1833#ifdef DEBUG
1834 HRGN hrgn1 = hrgn;
1835#endif
1836
1837 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1838
1839 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1840 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1841 dprintf(("WARNING: FillRgn %x %x %x invalid handle!", hdc, hrgn1, hBrush));
1842 SetLastError(ERROR_INVALID_HANDLE_W);
1843 return FALSE;
1844 }
1845
1846 if(pHps->lastBrushKey != (UINT)hBrush)
1847 {
1848 hbrushRestore = SelectObject(hdc, hBrush);
1849 if (!hbrushRestore)
1850 {
1851 dprintf(("WARNING: FillRgn %x %x %x invalid brush!", hdc, hrgn1, hBrush));
1852 SetLastError(ERROR_INVALID_HANDLE_W);
1853 return FALSE;
1854 }
1855 }
1856 dprintf(("FillRgn %x %x %x", hdc, hrgn1, hBrush));
1857
1858 DIBSECTION_CHECK_IF_DIRTY(hdc);
1859 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1860
1861 dprintfRegion(pHps->hps, pHps->hrgnHDC);
1862
1863 success = GpiPaintRegion(pHps->hps, pHps->hrgnHDC);
1864
1865 //todo metafile recording
1866
1867 /* Restore the brush if necessary */
1868 if(hbrushRestore)
1869 SelectObject(hdc, hbrushRestore);
1870
1871 if(success)
1872 DIBSECTION_MARK_INVALID(hdc);
1873
1874 return(success);
1875}
1876//******************************************************************************
1877//******************************************************************************
1878BOOL WIN32API PaintRgn( HDC hdc, HRGN hrgn)
1879{
1880 return FillRgn(hdc, hrgn, (HBRUSH) GetCurrentObject(hdc, OBJ_BRUSH_W));
1881}
1882//******************************************************************************
1883//******************************************************************************
1884BOOL WIN32API PtInRegion( HRGN hrgn, int x, int y)
1885{
1886 BOOL success;
1887 LONG lInside;
1888#ifdef DEBUG
1889 HRGN hrgn1 = hrgn;
1890#endif
1891
1892 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1893 if(hrgn == HANDLE_OBJ_ERROR) {
1894 dprintf(("WARNING: PtInRgn %x (%d,%d) invalid region!", hrgn1, x, y));
1895 SetLastError(ERROR_INVALID_HANDLE_W);
1896 return FALSE;
1897 }
1898
1899 POINTL pointl = {x,y};
1900 lInside = GpiPtInRegion(hpsRegion, hrgn, &pointl);
1901 if(lInside == PRGN_ERROR) {
1902 success = FALSE;
1903 }
1904 else success = TRUE;
1905
1906 SetLastError(ERROR_SUCCESS_W);
1907
1908 dprintf(("PtInRgn %x (%d,%d) returned %d", hrgn1, x, y, (success && lInside == PRGN_INSIDE) ? 1 : 0));
1909
1910 if(success && lInside == PRGN_INSIDE)
1911 return TRUE;
1912 else
1913 return FALSE;
1914}
1915//******************************************************************************
1916//******************************************************************************
1917BOOL WIN32API RectInRegion( HRGN hrgn, const RECT * pRect)
1918{
1919 BOOL success;
1920 LONG lInside;
1921#ifdef DEBUG
1922 HRGN hrgn1 = hrgn;
1923#endif
1924
1925 if(!pRect) {
1926 dprintf(("WARNING: RectInRgn %x %x invalid parameter!", hrgn1, pRect));
1927 SetLastError(ERROR_INVALID_PARAMETER_W);
1928 return FALSE;
1929 }
1930 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1931 if(hrgn == HANDLE_OBJ_ERROR) {
1932 dprintf(("WARNING: RectInRgn %x %x invalid region", hrgn1, pRect));
1933 SetLastError(ERROR_INVALID_HANDLE_W);
1934 return FALSE;
1935 }
1936
1937 RECTL rectl;
1938 MapWin32ToOS2Rect(*pRect, rectl);
1939 //switch bottom & top
1940 UINT temp = rectl.yBottom;
1941 rectl.yBottom = rectl.yTop;
1942 rectl.yTop = temp;
1943
1944 lInside = GpiRectInRegion(hpsRegion, hrgn, &rectl);
1945 if(lInside == RRGN_ERROR) {
1946 success = FALSE;
1947 }
1948 else success = TRUE;
1949
1950 SetLastError(ERROR_SUCCESS_W);
1951
1952 dprintf(("RectInRgn %x %x returned %d", hrgn1, pRect, (success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL)) ? 1 : 0));
1953
1954 if(success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL))
1955 return TRUE;
1956 else
1957 return FALSE;
1958}
1959//******************************************************************************
1960//Returned region in device coordinates (undocumented behaviour)
1961//******************************************************************************
1962HRGN WIN32API PathToRegion( HDC hdc)
1963{
1964 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1965 if(!pHps)
1966 {
1967 dprintf(("WARNING: PathToRegion %x; invalid hdc!", hdc));
1968 SetLastError(ERROR_INVALID_HANDLE_W);
1969 return NULLHANDLE;
1970 }
1971
1972 HRGN hrgn, hrgnTemp, hrgnwin;
1973
1974 dprintf(("GDI32: PathToRegion %x", hdc));
1975
1976 hrgnTemp = GpiPathToRegion(pHps->hps, 1, (pHps->polyFillMode == ALTERNATE_W) ? FPATH_ALTERNATE : FPATH_WINDING);
1977 if(hrgnTemp == NULLHANDLE)
1978 goto error;
1979
1980 hrgnwin = CreateRectRgn(1, 1, 2, 2);
1981 hrgn = ObjQueryHandleData(hrgnwin, HNDL_REGION);
1982 if(hrgn == HANDLE_OBJ_ERROR) {
1983 dprintf(("WARNING: PathToRegion invalid region", hrgnwin));
1984 SetLastError(ERROR_INVALID_HANDLE_W);
1985 return NULLHANDLE;
1986 }
1987
1988 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnTemp, pHps, NULL))
1989 goto error;
1990
1991 GpiDestroyRegion(pHps->hps, hrgnTemp);
1992
1993 return hrgnwin;
1994
1995error:
1996 if(hrgnwin)
1997 DeleteObject(hrgnwin);
1998
1999 SetLastError(ERROR_INVALID_HANDLE_W); //todo right error
2000 return NULLHANDLE;
2001}
2002//******************************************************************************
2003//Needs wrapper as this file includes os2.h!!
2004//******************************************************************************
2005BOOL WIN32API OSLibDeleteRegion(HANDLE hRegion)
2006{
2007 if(GpiDestroyRegion(hpsRegion, hRegion) == FALSE) {
2008 dprintf(("WARNING: OSLibDeleteRegion %x; GpiDestroyRegion failed (%x)", hRegion, WinGetLastError(0)));
2009 }
2010 return (0);
2011}
2012/*****************************************************************************
2013 * Name : int GetMetaRgn
2014 * Purpose : The GetMetaRgn function retrieves the current metaregion for
2015 * the specified device context.
2016 * Parameters: HDC hdc handle of device context
2017 * HRGN hrgn handle of region
2018 * Variables :
2019 * Result : 0 / 1
2020 * Remark :
2021 * Status : UNTESTED STUB
2022 *
2023 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
2024 *****************************************************************************/
2025
2026int WIN32API GetMetaRgn( HDC hdc, HRGN hrgn)
2027{
2028 dprintf(("GDI32: GetMetaRgn(%08xh, %08xh) not implemented.\n",
2029 hdc,
2030 hrgn));
2031
2032 SetLastError(ERROR_SUCCESS_W);
2033 return (0);
2034}
2035/*****************************************************************************
2036 * Name : int SetMetaRgn
2037 * Purpose : The SetMetaRgn function intersects the current clipping region
2038 * for the specified device context with the current metaregion
2039 * and saves the combined region as the new metaregion for the
2040 * specified device context. The clipping region is reset to a null region.
2041 * Parameters: HDC hdc handle of device context
2042 * Variables :
2043 * Result : TRUE / FALSE
2044 * Remark :
2045 * Status : UNTESTED STUB
2046 *
2047 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
2048 *****************************************************************************/
2049
2050BOOL WIN32API SetMetaRgn( HDC hdc)
2051{
2052 dprintf(("GDI32: SetMetaRgn(%08xh) not implemented.\n",
2053 hdc));
2054
2055 SetLastError(ERROR_SUCCESS_W);
2056 return (NULLREGION_W);
2057}
2058//******************************************************************************
2059//******************************************************************************
Note: See TracBrowser for help on using the repository browser.