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

Last change on this file since 22012 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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