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

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

Update

File size: 68.2 KB
Line 
1/* $Id: region.cpp,v 1.36 2004-01-11 11:42:21 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
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 already NULL, so nothing to do.
649
650 pHps->hrgnWin32Clip = hrgn;
651 return NULLREGION_W;
652 }
653
654 LONG lMode;
655 switch (operation)
656 {
657 case RGN_AND_W : lMode = CRGN_AND ; break; //intersect clip & visible region
658 default:
659 dprintf(("ERROR: GdiCombineVisRgnClipRgn %d invalid parameter", operation));
660 DebugInt3();
661 goto failure;
662 }
663 // If there's no visible region (meaning entire DC is visible), then just set
664 // the GPI clip region to the win32 clip region
665 if (pHps->hrgnWinVis == NULLHANDLE)
666 {
667 lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, hrgn, NULLHANDLE, CRGN_COPY);
668 }
669 else lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, pHps->hrgnWinVis, hrgn, lMode);
670
671 if (lComplexity != RGN_ERROR)
672 {
673 dprintfRegion(pHps->hps, hrgnNewClip);
674 //And activate the new clip region
675 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
676 if (lComplexity == RGN_ERROR )
677 {
678 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiSetClipRegion failed"));
679 DebugInt3();
680 goto failure;
681 }
682 //SvL: Must check if origin changed here. Sometimes happens when
683 // window looses focus. (don't know why....)
684 checkOrigin(pHps);
685
686 if(hrgnOldClip) GpiDestroyRegion(pHps->hps, hrgnOldClip);
687
688 pHps->hrgnWin32Clip = hrgn;
689
690 return GPI_TO_WIN_COMPLEXITY(lComplexity);
691 }
692 dprintf(("ERROR: GdiCombineVisRgnClipRgn: GpiCombineRegion failed"));
693 DebugInt3();
694
695failure:
696 if(hrgnNewClip) GpiDestroyRegion(pHps->hps, hrgnNewClip);
697
698 return ERROR_W;
699}
700//******************************************************************************
701// GdiCopyClipRgn
702//
703// Duplicate the GPI region
704//
705// Parameters:
706//
707// pDCData pHps - presentation space structure
708//
709// Returns: - NULL -> failure
710// - <> NULL -> GPI handle of copied region
711//
712//******************************************************************************
713HRGN GdiCopyClipRgn(pDCData pHps)
714{
715 HRGN hrgnNewClip;
716 LONG lComplexity;
717 RECTL rectl = {0, 0, 1, 1};
718
719 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
720 if(hrgnNewClip == NULLHANDLE) {
721 dprintf(("ERROR: GdiCopyClipRgn: GpiCreateRegion failed!!"));
722 DebugInt3();
723 return 0;
724 }
725 lComplexity = GpiCombineRegion(pHps->hps, hrgnNewClip, pHps->hrgnWin32Clip, NULLHANDLE, CRGN_COPY);
726 if (lComplexity != RGN_ERROR)
727 {
728 return TRUE;
729 }
730 DebugInt3();
731 return FALSE;
732}
733//******************************************************************************
734// GdiDestroyRgn
735//
736// Destroy the GPI region
737//
738// Parameters:
739//
740// pDCData pHps - presentation space structure
741// HRGN hrgn - region handle (GPI)
742//
743// Returns: - FALSE -> failure
744// - TRUE -> success
745//
746//******************************************************************************
747BOOL GdiDestroyRgn(pDCData pHps, HRGN hrgn)
748{
749 return GpiDestroyRegion(pHps->hps, hrgn);
750}
751//******************************************************************************
752//******************************************************************************
753int WIN32API ExtSelectClipRgn(HDC hdc, HRGN hrgn, int mode)
754{
755#ifdef DEBUG
756 HRGN hrgn1 = hrgn;
757#endif
758
759 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
760 if (!pHps)
761 {
762 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid hdc", hdc, hrgn, mode));
763 SetLastError(ERROR_INVALID_HANDLE_W);
764 return ERROR_W;
765 }
766
767 LONG lComplexity;
768 HRGN hrgnCurrent = NULLHANDLE, hrgnOld = NULLHANDLE;
769
770 if(!hrgn && mode != RGN_COPY_W)
771 {
772 SetLastError(ERROR_INVALID_PARAMETER_W);
773 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
774 return ERROR_W;
775 }
776
777 LONG lMode;
778 switch (mode)
779 {
780 case RGN_AND_W : lMode = CRGN_AND ; break;
781 case RGN_COPY_W : lMode = CRGN_COPY; break;
782 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
783 case RGN_OR_W : lMode = CRGN_OR ; break;
784 case RGN_XOR_W : lMode = CRGN_XOR ; break;
785 default:
786 {
787 SetLastError(ERROR_INVALID_PARAMETER_W);
788 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
789 return ERROR_W;
790 }
791 }
792
793 if(hrgn)
794 {
795 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
796 if(hrgn == HANDLE_OBJ_ERROR) {
797 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid region handle", hdc, hrgn1, mode));
798 SetLastError(ERROR_INVALID_HANDLE_W);
799 return 0;
800 }
801 dprintfRegion(hdc, hrgn);
802 }
803
804 //TODO: metafile recording
805 if(hrgn)
806 {
807 //interpretRegionAs converts the region and saves it in pHps->hrgnHDC
808 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
809 {
810 return ERROR_W;
811 }
812 }
813 else
814 {
815 //Intersect the Windows clip region with the current visible region
816 lComplexity = GdiCombineVisRgnClipRgn(pHps, NULLHANDLE, RGN_AND_W);
817
818 return NULLREGION_W;
819 }
820
821 // get current clipping region
822 hrgnOld = pHps->hrgnWin32Clip;
823 hrgnCurrent = hrgnOld;
824
825 if(hrgnCurrent == NULLHANDLE)
826 {//if none, then create one
827 lMode = CRGN_COPY;
828 RECTL rectl = {0, 0, 1, 1};
829 hrgnCurrent = GpiCreateRegion(pHps->hps, 1, &rectl);
830 }
831
832 HRGN hrgnSrc1;
833 HRGN hrgnSrc2;
834 if(lMode != CRGN_COPY)
835 {
836 hrgnSrc1 = hrgnCurrent;
837 hrgnSrc2 = pHps->hrgnHDC;
838 }
839 else
840 {
841 hrgnSrc1 = pHps->hrgnHDC;
842 hrgnSrc2 = NULLHANDLE;
843 }
844
845 lComplexity = GpiCombineRegion(pHps->hps, hrgnCurrent, hrgnSrc1, hrgnSrc2, lMode);
846 if (lComplexity != RGN_ERROR)
847 {
848 HRGN hrgnOld;
849
850 //Intersect the Windows clip region with the current visible region
851 lComplexity = GdiCombineVisRgnClipRgn(pHps, hrgnCurrent, RGN_AND_W);
852
853 SetLastError(ERROR_SUCCESS_W);
854
855 if (lComplexity != RGN_ERROR) {
856 return lComplexity;
857 }
858 }
859 GpiDestroyRegion(pHps->hps, hrgnCurrent); //delete newly created region
860
861 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO
862 return ERROR_W;
863}
864//******************************************************************************
865//******************************************************************************
866int WIN32API SelectClipRgn(HDC hdc, HRGN hrgn)
867{
868 return ExtSelectClipRgn(hdc, hrgn, RGN_COPY_W);
869}
870//******************************************************************************
871// The GetClipBox function retrieves the dimensions of the tightest bounding
872// rectangle that can be drawn around the current visible area on the device.
873// The visible area is defined by the current clipping region or clip path, as well
874// as any overlapping windows.
875//
876// NOTE: We simply call GpiQueryClipBox as it behaves just like GetClipBox
877//
878//******************************************************************************
879int WIN32API GetClipBox(HDC hdc, PRECT lpRect)
880{
881 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
882 RECTL rectl;
883 LONG lComplexity;
884 int rc;
885
886 if(!hdc || !lpRect || !pHps) {
887 dprintf(("GDI32: GetClipBox %x %x ERROR_INVALID_PARAMETER", hdc, lpRect));
888 SetLastError(ERROR_INVALID_PARAMETER_W);
889 return ERROR_W;
890 }
891 if(pHps->isPrinter)
892 {
893 //Some printers return the wrong clip box. Return the full page instead.
894 //(TODO: which is incorrect!)
895 lpRect->left = 0;
896 lpRect->top = 0;
897 lpRect->right = GetDeviceCaps( hdc, HORZRES_W);
898 lpRect->bottom = GetDeviceCaps( hdc, VERTRES_W);
899 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
900 convertPMDeviceRectToWinWorldRect(pHps, &rectl);
901
902 rc = SIMPLEREGION_W;
903 }
904 else {
905 lComplexity = GpiQueryClipBox(pHps->hps, &rectl);
906 if(lComplexity == RGN_ERROR)
907 {
908 rc = ERROR_W;
909 }
910 else
911 if(lComplexity == RGN_NULL)
912 {
913 memset(lpRect, 0, sizeof(*lpRect));
914 rc = NULLREGION_W;
915 }
916 else {
917#ifndef INVERT
918 //Convert coordinates from PM to win32
919 if (pHps->yInvert > 0) {
920 LONG temp = pHps->yInvert - rectl.yBottom;
921 rectl.yBottom = pHps->yInvert - rectl.yTop;
922 rectl.yTop = temp;
923 }
924#endif
925 //Convert including/including to including/excluding
926 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
927
928 lpRect->left = rectl.xLeft;
929 lpRect->right = rectl.xRight;
930
931 if(rectl.yBottom > rectl.yTop) {
932 lpRect->top = rectl.yTop;
933 lpRect->bottom = rectl.yBottom;
934 }
935 else {
936 lpRect->top = rectl.yBottom;
937 lpRect->bottom = rectl.yTop;
938 }
939
940 rc = GPI_TO_WIN_COMPLEXITY(lComplexity);
941 }
942 }
943// if(lpRect->left == 0 && lpRect->top == 0 && lpRect->right == 0 && lpRect->bottom == 0)
944// DebugInt3();
945 dprintf(("GDI32: GetClipBox of %X returned %d; (%d,%d)(%d,%d)", hdc, rc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
946 return rc;
947}
948//******************************************************************************
949//******************************************************************************
950int WIN32API GetClipRgn(HDC hdc, HRGN hrgn)
951{
952 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
953 BOOL success;
954 LONG lComplexity = RGN_RECT;
955 HRGN hrgnClip = NULL, hrgnTemp;
956#ifdef DEBUG
957 HRGN hrgn1 = hrgn;
958#endif
959
960 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
961 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
962 dprintf(("WARNING: GetClipRgn %x %x invalid handle", hdc, hrgn1));
963 SetLastError(ERROR_INVALID_HANDLE_W);
964 return 0;
965 }
966
967 if(pHps->hrgnWin32Clip) {
968 dprintfRegion(hdc, pHps->hrgnWin32Clip);
969 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, pHps->hrgnWin32Clip, pHps, NULL)) {
970 dprintf(("WARNING: GetClipRgn setWinDeviceRegionFromPMDeviceRegion failed!"));
971 GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp);
972 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
973 return 0;
974 }
975 }
976 else {
977 //no clip region; return NULL
978 lComplexity = RGN_NULL;
979 }
980
981 SetLastError(ERROR_SUCCESS_W);
982 if(lComplexity == RGN_NULL)
983 return 0;
984 else return 1;
985}
986//******************************************************************************
987// The GetRandomRgn function copies the system clipping region of a specified
988// device context to a specific region.
989// It returns the visible region of the specified device context in screen
990// coordinates (if it belongs to a window).
991//
992// VALUE = 1: This undocumented value will return the current Clip Region contained in the DC.
993// VALUE = 2: This undocumented value will return the current Meta Region contained in the DC.
994// VALUE = 3: This undocumented value will return the intersection of the Clip Region and Meta Region.
995// VALUE = 4, SYSRGN: The only value that is documented and defined for this function.
996// This value returns the System Region
997//******************************************************************************
998INT WIN32API GetRandomRgn(HDC hdc, HRGN hrgn, INT iNum)
999{
1000 HWND hwnd;
1001 INT ret;
1002
1003 if(iNum != SYSRGN_W) {
1004 dprintf(("WARNING: GetRandomRgn: invalid parameter %x", iNum));
1005 SetLastError(ERROR_INVALID_PARAMETER_W);
1006 return ERROR_W;
1007 }
1008 ret = GetClipRgn(hdc, hrgn);
1009
1010 hwnd = WindowFromDC(hdc);
1011 if(hwnd) {
1012 POINT pt = {0,0};
1013 //map from client to desktop coordinates
1014 MapWindowPoints(hwnd, 0, &pt, 1);
1015
1016 OffsetRgn(hrgn, pt.x, pt.y);
1017 }
1018 return ret;
1019}
1020//******************************************************************************
1021//******************************************************************************
1022int WIN32API ExcludeClipRect(HDC hdc, int left, int top, int right, int bottom)
1023{
1024 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1025 if(!pHps)
1026 {
1027 dprintf(("ERROR: ExcludeClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
1028 SetLastError(ERROR_INVALID_HANDLE_W);
1029 return ERROR_W;
1030 }
1031
1032 LONG lComplexity;
1033 RECTL rectl = { left, bottom, right, top };
1034
1035 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
1036 if(rectl.yTop < rectl.yBottom) {
1037 ULONG temp = rectl.yBottom;
1038 rectl.yBottom = rectl.yTop;
1039 rectl.yTop = temp;
1040 }
1041
1042#ifndef INVERT
1043 if (pHps->yInvert > 0) {
1044 LONG temp = pHps->yInvert - rectl.yBottom;
1045 rectl.yBottom = pHps->yInvert - rectl.yTop;
1046 rectl.yTop = temp;
1047 }
1048#endif
1049
1050 dprintf(("ExcludeClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
1051
1052 lComplexity = GpiExcludeClipRectangle(pHps->hps, &rectl);
1053 if (lComplexity == RGN_ERROR) {
1054 dprintf(("ERROR: ExcludeClipRgn: GpiExcludeClipRectangle failed!!"));
1055 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1056 return ERROR_W;
1057 }
1058
1059 //Ok, success. Now update the cached win32 clip region
1060 if(pHps->hrgnWin32Clip != NULLHANDLE)
1061 {
1062 HRGN hrgnClipRect = GpiCreateRegion(pHps->hps, 1, &rectl);
1063 if(hrgnClipRect == NULLHANDLE) {
1064 dprintf(("ERROR: ExcludeClipRgn GpiCreateRegion failed!!"));
1065 DebugInt3();
1066 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1067 return ERROR_W;
1068 }
1069 //subtract rect region from clip region
1070 lComplexity = GpiCombineRegion(pHps->hps, pHps->hrgnWin32Clip, pHps->hrgnWin32Clip, hrgnClipRect, CRGN_DIFF);
1071 GpiDestroyRegion(pHps->hps, hrgnClipRect);
1072
1073 if (lComplexity == RGN_ERROR) {
1074 dprintf(("ERROR: ExcludeClipRgn GpiCombineRegion failed!!"));
1075 DebugInt3();
1076 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1077 return ERROR_W;
1078 }
1079 }
1080
1081 //todo metafile recording
1082
1083 SetLastError(ERROR_SUCCESS_W);
1084 return lComplexity;
1085}
1086//******************************************************************************
1087//******************************************************************************
1088int WIN32API IntersectClipRect(HDC hdc, int left, int top, int right, int bottom)
1089{
1090 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1091 LONG lComplexity;
1092 BOOL success;
1093
1094 if(!pHps) {
1095 dprintf(("WARNING: IntersectClipRect %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
1096 SetLastError(ERROR_INVALID_HANDLE_W);
1097 return ERROR_W;
1098 }
1099 RECTL rectl = { left, bottom, right, top };
1100
1101 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
1102 if(rectl.yTop < rectl.yBottom) {
1103 ULONG temp = rectl.yBottom;
1104 rectl.yBottom = rectl.yTop;
1105 rectl.yTop = temp;
1106 }
1107
1108#ifndef INVERT
1109 //Convert coordinates from PM to win32
1110 if (pHps->yInvert > 0) {
1111 LONG temp = pHps->yInvert - rectl.yBottom;
1112 rectl.yBottom = pHps->yInvert - rectl.yTop;
1113 rectl.yTop = temp;
1114 }
1115#endif
1116
1117 dprintf(("IntersectClipRect %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
1118 lComplexity = GpiIntersectClipRectangle(pHps->hps, &rectl);
1119 if (lComplexity == RGN_ERROR) {
1120 dprintf(("ERROR: IntersectClipRect: GpiIntersectClipRectangle failed!!"));
1121 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1122 return ERROR_W;
1123 }
1124
1125 //Ok, success. Now update the cached win32 clip region
1126 if(pHps->hrgnWin32Clip != NULLHANDLE)
1127 {
1128 HRGN hrgnClipRect = GpiCreateRegion(pHps->hps, 1, &rectl);
1129 if(hrgnClipRect == NULLHANDLE) {
1130 dprintf(("ERROR: IntersectClipRect GpiCreateRegion failed!!"));
1131 DebugInt3();
1132 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1133 return ERROR_W;
1134 }
1135 //intersect rect region with clip region
1136 lComplexity = GpiCombineRegion(pHps->hps, pHps->hrgnWin32Clip, pHps->hrgnWin32Clip, hrgnClipRect, CRGN_AND);
1137 GpiDestroyRegion(pHps->hps, hrgnClipRect);
1138
1139 if (lComplexity == RGN_ERROR) {
1140 dprintf(("ERROR: IntersectClipRect GpiCombineRegion failed!!"));
1141 DebugInt3();
1142 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1143 return ERROR_W;
1144 }
1145 }
1146
1147 //todo metafile recording
1148
1149 SetLastError(ERROR_SUCCESS_W);
1150 return lComplexity;
1151}
1152//******************************************************************************
1153//******************************************************************************
1154int WIN32API OffsetClipRgn(HDC hdc, int nXOffset, int nYOffset )
1155{
1156 BOOL success;
1157 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1158 LONG lComplexity;
1159
1160 if(!pHps) {
1161 dprintf(("OffsetClipRgn %x (%d,%d) invalid hdc", hdc, nXOffset, nYOffset));
1162 SetLastError(ERROR_INVALID_HANDLE_W);
1163 return ERROR_W;
1164 }
1165
1166 dprintf(("OffsetClipRgn %x (%d,%d)", hdc, nXOffset, nYOffset));
1167 POINTL pointl = { nXOffset, nYOffset };
1168#ifndef INVERT
1169 if (pHps->yInvert > 0) {
1170 pointl.y = pHps->yInvert - pointl.y;
1171 }
1172#endif
1173
1174 if(pHps->hrgnWin32Clip == NULLHANDLE) {
1175 lComplexity = NULLREGION_W;
1176 }
1177 else {
1178 lComplexity = GpiOffsetRegion(pHps->hps, pHps->hrgnWin32Clip, &pointl);
1179 if (lComplexity == RGN_ERROR) {
1180 dprintf(("ERROR: OffsetClipRgn: GpiOffsetRegion failed!!"));
1181 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
1182 return ERROR_W;
1183 }
1184
1185 //Intersect the Windows clip region with the current visible region
1186 lComplexity = GdiCombineVisRgnClipRgn(pHps, pHps->hrgnWin32Clip, RGN_AND_W);
1187
1188 lComplexity = GPI_TO_WIN_COMPLEXITY(lComplexity);
1189 }
1190
1191 //todo metafile recording
1192
1193 SetLastError(ERROR_SUCCESS_W);
1194 return lComplexity;
1195}
1196//******************************************************************************
1197//******************************************************************************
1198HRGN WIN32API CreatePolyPolygonRgn(const POINT *lppt, const int *pPolyCount,
1199 int nCount, int fnPolyFillMode)
1200{
1201 LONG flMode;
1202
1203 switch(fnPolyFillMode)
1204 {
1205 case ALTERNATE_W:
1206 flMode = POLYGON_ALTERNATE;
1207 break;
1208 case WINDING_W:
1209 flMode = POLYGON_WINDING;
1210 break;
1211 default:
1212 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
1213 SetLastError(ERROR_INVALID_PARAMETER_W);
1214 return 0;
1215 }
1216
1217 if(nCount < 1)
1218 {
1219 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
1220 SetLastError(ERROR_INVALID_PARAMETER_W);
1221 return 0;
1222 }
1223
1224 PPOLYGON pPolygon = new POLYGON[nCount];
1225 if(!pPolygon) {
1226 dprintf(("ERROR: CreatePolyPolygonRgn: out of memory!!"));
1227 SetLastError(ERROR_OUTOFMEMORY_W);
1228 return 0;
1229 }
1230 dprintf(("CreatePolyPolygonRgn %x %x %d %d", lppt, pPolyCount, nCount, fnPolyFillMode));
1231
1232 PPOINTL pPointl = (PPOINTL)lppt+1; // skip first point
1233 for (int x=0; x < nCount; x++) {
1234 pPolygon[x].ulPoints = (x == 0) ? pPolyCount[x] - 1 : pPolyCount[x];
1235 pPolygon[x].aPointl = pPointl;
1236 pPointl += pPolygon[x].ulPoints;
1237 }
1238 GpiMove(hpsRegion, (PPOINTL)lppt);
1239 HRGN hrgn = GpiCreatePolygonRegion(hpsRegion, nCount, pPolygon, POLYGON_BOUNDARY | flMode);
1240
1241 delete[] pPolygon;
1242
1243 if(!hrgn) {
1244 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1245 return 0;
1246 }
1247
1248 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1249 GpiDestroyRegion(hpsRegion, hrgn);
1250 SetLastError(ERROR_OUTOFMEMORY_W);
1251 return 0;
1252 }
1253 STATS_CreatePolyPolygonRgn(hrgn, lppt, pPolyCount, nCount, fnPolyFillMode);
1254
1255 SetLastError(ERROR_SUCCESS_W);
1256 return hrgn;
1257}
1258//******************************************************************************
1259//******************************************************************************
1260HRGN WIN32API CreateRectRgn(int left, int top, int right, int bottom)
1261{
1262 HRGN hrgn;
1263 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
1264
1265 hrgn = GpiCreateRegion(hpsRegion, 1, &rectl);
1266 if(!hrgn) {
1267 dprintf(("WARNING: CreateRectRgn: GpiCreateRectRegion failed! %x", WinGetLastError(0)));
1268 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1269 return 0;
1270 }
1271
1272 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1273 GpiDestroyRegion(hpsRegion, hrgn);
1274 SetLastError(ERROR_OUTOFMEMORY_W);
1275 return 0;
1276 }
1277 STATS_CreateRectRgn(hrgn, left, top, right, bottom);
1278
1279 dprintf(("CreateRectRegion (%d,%d)(%d,%d) returned %x", left, top, right, bottom, hrgn));
1280 SetLastError(ERROR_SUCCESS_W);
1281 return hrgn;
1282}
1283//******************************************************************************
1284//******************************************************************************
1285HRGN WIN32API CreateRectRgnIndirect( const RECT * lprc)
1286{
1287 return CreateRectRgn(lprc->left, lprc->top, lprc->right, lprc->bottom);
1288}
1289//******************************************************************************
1290//******************************************************************************
1291HRGN WIN32API CreateRoundRectRgn(int left, int top, int right, int bottom, int nWidthEllipse, int nHeightEllipse)
1292{
1293 HRGN hrgn;
1294 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
1295
1296 PPOINTL pPointl = (PPOINTL)&rectl;
1297
1298 GpiMove(hpsRegion, &pPointl[0]);
1299 hrgn = GpiCreateRoundRectRegion(hpsRegion, &pPointl[1], labs(nWidthEllipse), labs(nHeightEllipse));
1300
1301 if(!hrgn) {
1302 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1303 dprintf(("WARNING: CreateRoundRectRgn: GpiCreateRoundRectRegion failed! %x", WinGetLastError(0)));
1304 return 0;
1305 }
1306
1307 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1308 GpiDestroyRegion(hpsRegion, hrgn);
1309 SetLastError(ERROR_OUTOFMEMORY_W);
1310 return 0;
1311 }
1312 STATS_CreateRoundRectRgn(hrgn, left, top, right, bottom, nWidthEllipse, nHeightEllipse);
1313
1314 dprintf(("CreateRoundRectRegion (%d,%d)(%d,%d) (%d,%d) returned %x", left, top, right, bottom, nWidthEllipse, nHeightEllipse, hrgn));
1315 SetLastError(ERROR_SUCCESS_W);
1316 return hrgn;
1317}
1318//******************************************************************************
1319//******************************************************************************
1320HRGN WIN32API ExtCreateRegion(const XFORM_W * pXform, DWORD count,
1321 const RGNDATA * pData)
1322{
1323 HRGN hrgn;
1324
1325 if(!pData || count < (sizeof(RGNDATAHEADER) + pData->rdh.nCount * sizeof(RECT))) {
1326 dprintf(("WARNING: ExtCreateRegion %x %d %x; invalid parameter", pXform, count, pData));
1327 SetLastError(ERROR_INVALID_PARAMETER_W);
1328 return 0;
1329 }
1330
1331 PRECTL pRectl = new RECTL[pData->rdh.nCount];
1332 PRECT pDataRects = (PRECT)pData->Buffer;
1333 for(int i=0; i < pData->rdh.nCount; i++) {
1334 MapWin32ToOS2Rect(pDataRects[i], pRectl[i]);
1335 }
1336
1337 BOOL doShear = pXform && (pXform->eM12 || pXform->eM21);
1338 HPS hpsTemp = NULLHANDLE;
1339
1340 dprintf(("ExtCreateRegion %x %d %x", pXform, count, pData));
1341 if(doShear) {
1342 hpsTemp = WinGetPS(HWND_DESKTOP);
1343 GpiBeginPath(hpsTemp, 1);
1344
1345 MATRIXLF matrixlf;
1346 matrixlf.fxM11 = pXform->eM11 * (float)0x10000;
1347 matrixlf.fxM12 = pXform->eM12 * (float)0x10000;
1348 matrixlf.lM13 = 0;
1349 matrixlf.fxM21 = pXform->eM21 * (float)0x10000;
1350 matrixlf.fxM22 = pXform->eM22 * (float)0x10000;
1351 matrixlf.lM23 = 0;
1352 matrixlf.lM31 = pXform->eDx;
1353 matrixlf.lM32 = pXform->eDy;
1354 matrixlf.lM33 = 1;
1355
1356 GpiSetModelTransformMatrix(hpsTemp, 9, &matrixlf, TRANSFORM_REPLACE);
1357 }
1358
1359 for(i=0; i < pData->rdh.nCount; i++)
1360 {
1361 LONG temp = pRectl[i].yTop;
1362 pRectl[i].yTop = pRectl[i].yBottom;
1363 pRectl[i].yBottom = temp;
1364
1365 if(pXform)
1366 {
1367 PPOINTL pPointl = ((PPOINTL)&pRectl[i]);
1368
1369 if (doShear) {
1370 GpiMove(hpsTemp, pPointl);
1371 GpiBox(hpsTemp, DRO_OUTLINE, pPointl+1, 0, 0);
1372 }
1373 else
1374 {
1375 for(int j=0; j < 2; j++) {
1376 pPointl[j].x = (pXform->eM11 * (float)pPointl[j].x) + (pXform->eM12 * (float)pPointl[j].y) + pXform->eDx;
1377 pPointl[j].y = (pXform->eM21 * (float)pPointl[j].x) + (pXform->eM22 * (float)pPointl[j].y) + pXform->eDy;
1378 }
1379
1380 PRECTL pRectlT = (PRECTL)pPointl;
1381 if (pRectlT->xLeft > pRectlT->xRight) {
1382 LONG temp = pRectlT->xLeft;
1383 pRectlT->xLeft = pRectlT->xRight;
1384 pRectlT->xRight = temp;
1385 }
1386 if (pRectlT->yBottom > pRectlT->yTop) {
1387 LONG temp = pRectlT->yBottom;
1388 pRectlT->yBottom = pRectlT->yTop;
1389 pRectlT->yTop = temp;
1390 }
1391 }
1392 }
1393 }
1394
1395 if(doShear) {
1396 GpiEndPath(hpsTemp);
1397 hrgn = GpiPathToRegion(hpsTemp, 1, FPATH_WINDING);
1398
1399 if(pRectl)
1400 delete[] pRectl;
1401
1402 if(hrgn == 0) {
1403 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
1404 SetLastError(ERROR_INVALID_PARAMETER_W);
1405 return 0;
1406 }
1407 WinReleasePS(hpsTemp);
1408 }
1409 else {
1410 hrgn = GpiCreateRegion(hpsRegion, pData->rdh.nCount, pRectl);
1411 if(pRectl)
1412 delete[] pRectl;
1413
1414 if(hrgn == 0) {
1415 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
1416 SetLastError(ERROR_INVALID_PARAMETER_W);
1417 return 0;
1418 }
1419 }
1420
1421 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1422 GpiDestroyRegion(hpsRegion, hrgn);
1423 SetLastError(ERROR_OUTOFMEMORY_W);
1424 return 0;
1425 }
1426 STATS_ExtCreateRegion(hrgn, (PVOID)pXform, count, pData);
1427 SetLastError(ERROR_SUCCESS_W);
1428 return hrgn;
1429}
1430//******************************************************************************
1431//******************************************************************************
1432HRGN WIN32API CreateEllipticRgn(int left, int top, int right, int bottom)
1433{
1434 HRGN hrgn;
1435
1436 RECTL rectl = { left,
1437 top < bottom ? top : bottom,
1438 right,
1439 top < bottom ? bottom : top };
1440
1441 dprintf(("CreateEllipticRgn (%d,%d)(%d,%d)", left, top, right, bottom));
1442 hrgn = GpiCreateEllipticRegion(hpsRegion, &rectl);
1443 if(hrgn == RGN_ERROR) {
1444 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1445 dprintf(("WARNING: CreateEllipticRgn: GpiCreateEllipticRegion failed! %x", WinGetLastError(0)));
1446 return 0;
1447 }
1448
1449 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1450 GpiDestroyRegion(hpsRegion, hrgn);
1451 SetLastError(ERROR_OUTOFMEMORY_W);
1452 return 0;
1453 }
1454 STATS_CreateEllipticRgn(hrgn, left, top, right, bottom);
1455 SetLastError(ERROR_SUCCESS_W);
1456 return hrgn;
1457}
1458//******************************************************************************
1459//******************************************************************************
1460HRGN WIN32API CreateEllipticRgnIndirect(const RECT *pRect)
1461{
1462 return CreateEllipticRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
1463}
1464//******************************************************************************
1465//******************************************************************************
1466HRGN WIN32API CreatePolygonRgn(const POINT * lppt, int cPoints, int fnPolyFillMode)
1467{
1468 HRGN hrgn;
1469 LONG flMode;
1470
1471 if(!lppt || cPoints < 2) {
1472 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1473 SetLastError(ERROR_INVALID_PARAMETER_W);
1474 return 0;
1475 }
1476
1477 switch (fnPolyFillMode)
1478 {
1479 case ALTERNATE_W :
1480 flMode = POLYGON_ALTERNATE;
1481 break;
1482 case WINDING_W :
1483 flMode = POLYGON_WINDING;
1484 break;
1485 default:
1486 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1487 SetLastError(ERROR_INVALID_PARAMETER_W);
1488 return 0;
1489 }
1490 dprintf(("CreatePolygonRgn %x %d %d", lppt, cPoints, fnPolyFillMode));
1491
1492 POLYGON polygon;
1493 polygon.ulPoints = cPoints - 1;
1494 polygon.aPointl = (PPOINTL)(lppt + 1);
1495
1496#ifdef DEBUG
1497 for(int i=0;i<cPoints;i++) {
1498 dprintf(("Point %d: (%d,%d)", i, lppt[i].x, lppt[i].y));
1499 }
1500#endif
1501 GpiMove(hpsRegion, (PPOINTL)lppt);
1502 hrgn = GpiCreatePolygonRegion(hpsRegion, 1, &polygon, POLYGON_BOUNDARY | flMode);
1503 if(hrgn == RGN_ERROR) {
1504 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
1505 dprintf(("WARNING: CreatePolygonRgn: GpiCreatePolygonRegion failed! %x", WinGetLastError(0)));
1506 return 0;
1507 }
1508
1509 if(ObjAllocateHandle(&hrgn, hrgn, HNDL_REGION) == FALSE) {
1510 GpiDestroyRegion(hpsRegion, hrgn);
1511 SetLastError(ERROR_OUTOFMEMORY_W);
1512 return 0;
1513 }
1514 STATS_CreatePolygonRgn(hrgn, lppt, cPoints, fnPolyFillMode);
1515 SetLastError(ERROR_SUCCESS_W);
1516 return hrgn;
1517}
1518//******************************************************************************
1519//******************************************************************************
1520int WIN32API CombineRgn(HRGN hrgnDest, HRGN hrgnSrc1, HRGN hrgnSrc2, int combineMode)
1521{
1522 ULONG lComplexity;
1523 LONG mode;
1524#ifdef DEBUG
1525 HRGN hrgn1 = hrgnDest;
1526 HRGN hrgn2 = hrgnSrc1;
1527 HRGN hrgn3 = hrgnSrc2;
1528#endif
1529
1530 switch(combineMode) {
1531 case RGN_AND_W:
1532 mode = CRGN_AND;
1533 break;
1534 case RGN_COPY_W:
1535 mode = CRGN_COPY;
1536 break;
1537 case RGN_DIFF_W:
1538 mode = CRGN_DIFF;
1539 break;
1540 case RGN_OR_W:
1541 mode = CRGN_OR;
1542 break;
1543 case RGN_XOR_W:
1544 mode = CRGN_XOR;
1545 break;
1546 default:
1547 dprintf(("WARNING: CombineRgn %x %x %x %d; invalid mode!", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1548 SetLastError(ERROR_INVALID_PARAMETER_W);
1549 return ERROR_W;
1550 }
1551
1552 hrgnDest = ObjQueryHandleData(hrgnDest, HNDL_REGION);
1553 hrgnSrc1 = ObjQueryHandleData(hrgnSrc1, HNDL_REGION);
1554 hrgnSrc2 = ObjQueryHandleData(hrgnSrc2, HNDL_REGION);
1555 if(hrgnDest == HANDLE_OBJ_ERROR || hrgnSrc1 == HANDLE_OBJ_ERROR || (hrgnSrc2 == HANDLE_OBJ_ERROR && combineMode != RGN_COPY_W)) {
1556 dprintf(("WARNING: CombineRgn %x %x %x %d invalid region", hrgn1, hrgn2, hrgn3, combineMode));
1557 SetLastError(ERROR_INVALID_HANDLE_W);
1558 return ERROR_W;
1559 }
1560
1561 lComplexity = GpiCombineRegion(hpsRegion, hrgnDest, hrgnSrc1, hrgnSrc2, mode);
1562 if(lComplexity == RGN_ERROR) {
1563 dprintf(("WARNING: CombineRgn %x %x %x %d GpiCombineRegion failed (%x)", hrgn1, hrgn2, hrgn3, mode, WinGetLastError(0)));
1564 SetLastError(ERROR_INVALID_HANDLE_W);
1565 return ERROR_W;
1566 }
1567 SetLastError(ERROR_SUCCESS_W);
1568 return lComplexity;
1569}
1570//******************************************************************************
1571//******************************************************************************
1572BOOL WIN32API EqualRgn(HRGN hrgn1, HRGN hrgn2)
1573{
1574 LONG lEquality;
1575#ifdef DEBUG
1576 HRGN hrgnt1 = hrgn1;
1577 HRGN hrgnt2 = hrgn2;
1578#endif
1579
1580 hrgn1 = ObjQueryHandleData(hrgn1, HNDL_REGION);
1581 hrgn2 = ObjQueryHandleData(hrgn2, HNDL_REGION);
1582 if(hrgn1 == HANDLE_OBJ_ERROR || hrgn2 == HANDLE_OBJ_ERROR) {
1583 dprintf(("WARNING: EqualRgn %x %x invalid region", hrgnt1, hrgnt2));
1584 SetLastError(ERROR_INVALID_HANDLE_W);
1585 return FALSE;
1586 }
1587 lEquality = GpiEqualRegion(hpsRegion, hrgn1, hrgn2);
1588
1589 dprintf(("EqualRgn %x %x = %d", hrgnt1, hrgnt2, lEquality));
1590 SetLastError(ERROR_SUCCESS_W);
1591
1592 if(lEquality == EQRGN_EQUAL)
1593 return TRUE;
1594 else
1595 if(lEquality == EQRGN_NOTEQUAL)
1596 return FALSE;
1597 else {
1598 return FALSE;
1599 }
1600}
1601//******************************************************************************
1602//******************************************************************************
1603BOOL WIN32API SetRectRgn(HRGN hrgn, int left, int top, int right, int bottom)
1604{
1605 BOOL result = FALSE;
1606#ifdef DEBUG
1607 HRGN hrgn1 = hrgn;
1608#endif
1609
1610 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1611 if(hrgn == HANDLE_OBJ_ERROR) {
1612 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) invalid region handle", hrgn1, left, top, right, bottom));
1613 SetLastError(ERROR_INVALID_HANDLE_W);
1614 return 0;
1615 }
1616 RECTL rectl = { left, top, right, bottom }; //reversed y coordinates
1617 if(GpiSetRegion(hpsRegion, hrgn, 1, &rectl)) {
1618 dprintf(("SetRectRgn %x (%d,%d)(%d,%d)", hrgn1, left, top, right, bottom));
1619 return TRUE;
1620 }
1621 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) GpiSetRegion failed %x", hrgn1, left, top, right, bottom, WinGetLastError(0)));
1622 return FALSE;
1623}
1624//******************************************************************************
1625//NOTE: depends on hps inversion
1626//******************************************************************************
1627ULONG WIN32API GetRegionData( HRGN hrgn, ULONG count, PRGNDATA pData)
1628{
1629#ifdef DEBUG
1630 HRGN hrgn1 = hrgn;
1631#endif
1632
1633 if(!count && pData)
1634 {
1635 dprintf(("WARNING: GetRegionData %x %d %x; invalid parameter", hrgn1, count, pData));
1636 SetLastError(ERROR_INVALID_PARAMETER_W);
1637 return 0;
1638 }
1639 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1640 if(hrgn == HANDLE_OBJ_ERROR) {
1641 dprintf(("WARNING: GetRegionData %x %d %x; invalid region handle", hrgn1, count, pData));
1642 SetLastError(ERROR_INVALID_HANDLE_W);
1643 return 0;
1644 }
1645 RGNRECT rgnRect;
1646 rgnRect.ircStart = 1;
1647 rgnRect.crc = 0;
1648 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
1649 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1650 {
1651 dprintf(("WARNING: GetRegionData %x %d %x: GpiQueryRegionRects failed! (%x)", hrgn1, count, pData, WinGetLastError(0)));
1652 return 0;
1653 }
1654
1655 dprintf(("GetRegionData %x %d %x", hrgn1, count, pData));
1656
1657 ULONG bufSizeNeeded = rgnRect.crcReturned * sizeof(RECT) + sizeof (RGNDATAHEADER);
1658
1659 if(pData && (count >= (sizeof(RGNDATAHEADER) + rgnRect.crcReturned * sizeof(RECT))))
1660 {
1661 //we actually need to flip the top & bottom values, but as the layout of the PM RECTL and
1662 //Win32 RECT have exactly those two members reversed, we don't do this for the returned
1663 //rectangles (more efficient)
1664 PRECTL pRectl = (PRECTL)pData->Buffer;
1665 rgnRect.crc = rgnRect.crcReturned;
1666 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, pRectl))
1667 {
1668 dprintf(("WARNING: GetRegionData: GpiQueryRegionRects failed! (%x)", WinGetLastError(0)));
1669 return 0;
1670 }
1671
1672 RECTL boundRect;
1673 GpiQueryRegionBox(hpsRegion, hrgn, &boundRect); // no need to check rc
1674
1675 pData->rdh.dwSize = sizeof(pData->rdh);
1676 pData->rdh.iType = RDH_RECTANGLES_W; // one and only possible value
1677 pData->rdh.nCount = rgnRect.crcReturned;
1678 pData->rdh.nRgnSize = rgnRect.crcReturned * sizeof(RECT);
1679
1680 //flip top & bottom for bounding rectangle (not really necessary; but cleaner coding)
1681 LONG temp = boundRect.yTop;
1682 boundRect.yTop = boundRect.yBottom;
1683 boundRect.yBottom = temp;
1684 MapOS2ToWin32Rect(boundRect, pData->rdh.rcBound);
1685 }
1686
1687 //return size needed
1688 return bufSizeNeeded;
1689}
1690//******************************************************************************
1691//******************************************************************************
1692int WIN32API GetRgnBox( HRGN hrgn, PRECT pRect)
1693{
1694 BOOL success;
1695 LONG lComplexity;
1696#ifdef DEBUG
1697 HRGN hrgn1 = hrgn;
1698#endif
1699
1700 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1701 if(hrgn == HANDLE_OBJ_ERROR) {
1702 dprintf(("WARNING: GetRgnBox %x %x invalid region!", hrgn1, pRect));
1703 SetLastError(ERROR_INVALID_HANDLE_W);
1704 return ERROR_W;
1705 }
1706
1707 RECTL rectl;
1708 lComplexity = GpiQueryRegionBox(hpsRegion, hrgn, &rectl);
1709 if(lComplexity != RGN_ERROR)
1710 {
1711 //no conversion required, just flip top & bottom
1712 ULONG temp = rectl.yBottom;
1713 rectl.yBottom = rectl.yTop;
1714 rectl.yTop = temp;
1715
1716 MapOS2ToWin32Rect(rectl, *pRect);
1717 }
1718 else {
1719 lComplexity = ERROR_W;
1720 dprintf(("WARNING: GetRgnBox error in region!"));
1721 }
1722 dprintf(("GetRgnBox %x (%d,%d)(%d,%d)", hrgn1, pRect->left, pRect->top, pRect->right, pRect->bottom));
1723
1724 SetLastError(ERROR_SUCCESS_W);
1725 return lComplexity;
1726}
1727//******************************************************************************
1728//******************************************************************************
1729BOOL WIN32API InvertRgn( HDC hdc, HRGN hrgn)
1730{
1731#ifdef DEBUG
1732 HRGN hrgn1 = hrgn;
1733#endif
1734 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1735
1736 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1737 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1738 dprintf(("WARNING: InvertRgn %x %x invalid handle!", hdc, hrgn));
1739 SetLastError(ERROR_INVALID_HANDLE_W);
1740 return FALSE;
1741 }
1742 //todo metafile recording
1743
1744 dprintf(("InvertRgn %x %x", hdc, hrgn1));
1745
1746 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1747
1748 LONG lHits = GPI_ERROR;
1749 HRGN hrgnOld;
1750 LONG lComplexity ;
1751 RECTL boundingRect; // this gets a rectangle in world cordinates!
1752
1753 lComplexity = GpiQueryRegionBox(pHps->hps, pHps->hrgnHDC, &boundingRect);
1754 if(lComplexity != RGN_ERROR)
1755 {
1756 lComplexity = GpiSetClipRegion(pHps->hps, pHps->hrgnHDC, &hrgnOld);
1757 if(lComplexity != RGN_ERROR)
1758 {
1759 RECTL rectls[2];
1760 rectls[0] = boundingRect;
1761 rectls[1] = boundingRect;
1762 lHits = GpiBitBlt(pHps->hps, NULL, 3, (PPOINTL)rectls,
1763 ROP_DSTINVERT, 0);
1764
1765 /* Restore the old region */
1766 GpiSetClipRegion(pHps->hps, hrgnOld, &hrgnOld);
1767 }
1768 }
1769
1770 if(lHits == GPI_ERROR || lComplexity == RGN_ERROR)
1771 {
1772 dprintf(("WARNING: InvertRgn error during Gpi operation (%x) (%d,%d)", WinGetLastError(0), lHits, lComplexity));
1773 return FALSE;
1774 }
1775
1776 DIBSECTION_MARK_INVALID(hdc);
1777 return TRUE;
1778}
1779//******************************************************************************
1780//******************************************************************************
1781int WIN32API OffsetRgn( HRGN hrgn, int xOffset, int yOffset)
1782{
1783 LONG lComplexity;
1784#ifdef DEBUG
1785 HRGN hrgn1 = hrgn;
1786#endif
1787
1788 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1789 if(hrgn == HANDLE_OBJ_ERROR) {
1790 dprintf(("WARNING: OffsetRgn %x %d %d invalid handle!", hrgn, xOffset, yOffset));
1791 SetLastError(ERROR_INVALID_HANDLE_W);
1792 return ERROR_W;
1793 }
1794 dprintf(("OffsetRgn %x %d %d", hrgn1, xOffset, yOffset));
1795
1796 POINTL ptlOffset = {xOffset, yOffset};
1797 GpiOffsetRegion(hpsRegion, hrgn, &ptlOffset);
1798
1799 RECTL rectl[8];
1800 RGNRECT rgnRect;
1801 rgnRect.ircStart = 1;
1802 rgnRect.crc = 8;
1803 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference
1804 if(GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, &rectl[0]))
1805 {
1806 switch (rgnRect.crcReturned) {
1807 case 0:
1808 lComplexity = NULLREGION_W;
1809 break;
1810 case 1:
1811 lComplexity = SIMPLEREGION_W;
1812 break;
1813 default:
1814 lComplexity = COMPLEXREGION_W;
1815 break;
1816 }
1817 }
1818 else {
1819 lComplexity = ERROR_W;
1820 dprintf(("WARNING: OffsetRgn error in region! (%x)", WinGetLastError(0)));
1821 }
1822
1823 SetLastError(ERROR_SUCCESS_W);
1824
1825 return lComplexity;
1826}
1827//******************************************************************************
1828//******************************************************************************
1829BOOL WIN32API FrameRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush, int width, int height)
1830{
1831 HBRUSH hbrushRestore = 0;
1832#ifdef DEBUG
1833 HRGN hrgn1 = hrgn;
1834#endif
1835 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1836
1837 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1838 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1839 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid handle!", hdc, hrgn, hBrush, width, height));
1840 SetLastError(ERROR_INVALID_HANDLE_W);
1841 return FALSE;
1842 }
1843
1844 width = abs(width);
1845 height = abs(height);
1846
1847 if(pHps->lastBrushKey != (UINT)hBrush)
1848 {
1849 hbrushRestore = SelectObject(hdc, hBrush);
1850 if(!hbrushRestore)
1851 {
1852 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid brush!", hdc, hrgn, hBrush, width, height));
1853 SetLastError(ERROR_INVALID_HANDLE_W);
1854 return FALSE;
1855 }
1856 }
1857 dprintf(("FrameRgn %x %x %x (%d,%d)", hdc, hrgn1, hBrush, width, height));
1858 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1859
1860 SIZEL thickness = { width, height };
1861 LONG lHits = GpiFrameRegion(pHps->hps, pHps->hrgnHDC, &thickness);
1862
1863 SetLastError(ERROR_SUCCESS_W);
1864
1865 // Restore the brush if necessary
1866 if(hbrushRestore)
1867 SelectObject(hdc, hbrushRestore);
1868
1869 if(lHits != GPI_ERROR)
1870 DIBSECTION_MARK_INVALID(hdc);
1871
1872 //todo metafile recording
1873 return (lHits != GPI_ERROR);
1874}
1875//******************************************************************************
1876//******************************************************************************
1877BOOL WIN32API FillRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush)
1878{
1879 BOOL success;
1880 HBRUSH hbrushRestore = 0;
1881#ifdef DEBUG
1882 HRGN hrgn1 = hrgn;
1883#endif
1884
1885 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1886
1887 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1888 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1889 dprintf(("WARNING: FillRgn %x %x %x invalid handle!", hdc, hrgn1, hBrush));
1890 SetLastError(ERROR_INVALID_HANDLE_W);
1891 return FALSE;
1892 }
1893
1894 if(pHps->lastBrushKey != (UINT)hBrush)
1895 {
1896 hbrushRestore = SelectObject(hdc, hBrush);
1897 if (!hbrushRestore)
1898 {
1899 dprintf(("WARNING: FillRgn %x %x %x invalid brush!", hdc, hrgn1, hBrush));
1900 SetLastError(ERROR_INVALID_HANDLE_W);
1901 return FALSE;
1902 }
1903 }
1904 dprintf(("FillRgn %x %x %x", hdc, hrgn1, hBrush));
1905
1906 DIBSECTION_CHECK_IF_DIRTY(hdc);
1907 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1908
1909 dprintfRegion(pHps->hps, pHps->hrgnHDC);
1910
1911 success = GpiPaintRegion(pHps->hps, pHps->hrgnHDC);
1912
1913 //todo metafile recording
1914
1915 /* Restore the brush if necessary */
1916 if(hbrushRestore)
1917 SelectObject(hdc, hbrushRestore);
1918
1919 if(success)
1920 DIBSECTION_MARK_INVALID(hdc);
1921
1922 return(success);
1923}
1924//******************************************************************************
1925//******************************************************************************
1926BOOL WIN32API PaintRgn( HDC hdc, HRGN hrgn)
1927{
1928 return FillRgn(hdc, hrgn, (HBRUSH) GetCurrentObject(hdc, OBJ_BRUSH_W));
1929}
1930//******************************************************************************
1931//******************************************************************************
1932BOOL WIN32API PtInRegion( HRGN hrgn, int x, int y)
1933{
1934 BOOL success;
1935 LONG lInside;
1936#ifdef DEBUG
1937 HRGN hrgn1 = hrgn;
1938#endif
1939
1940 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1941 if(hrgn == HANDLE_OBJ_ERROR) {
1942 dprintf(("WARNING: PtInRgn %x (%d,%d) invalid region!", hrgn1, x, y));
1943 SetLastError(ERROR_INVALID_HANDLE_W);
1944 return FALSE;
1945 }
1946
1947 POINTL pointl = {x,y};
1948 lInside = GpiPtInRegion(hpsRegion, hrgn, &pointl);
1949 if(lInside == PRGN_ERROR) {
1950 success = FALSE;
1951 }
1952 else success = TRUE;
1953
1954 SetLastError(ERROR_SUCCESS_W);
1955
1956 dprintf(("PtInRgn %x (%d,%d) returned %d", hrgn1, x, y, (success && lInside == PRGN_INSIDE) ? 1 : 0));
1957
1958 if(success && lInside == PRGN_INSIDE)
1959 return TRUE;
1960 else
1961 return FALSE;
1962}
1963//******************************************************************************
1964//******************************************************************************
1965BOOL WIN32API RectInRegion( HRGN hrgn, const RECT * pRect)
1966{
1967 BOOL success;
1968 LONG lInside;
1969#ifdef DEBUG
1970 HRGN hrgn1 = hrgn;
1971#endif
1972
1973 if(!pRect) {
1974 dprintf(("WARNING: RectInRgn %x %x invalid parameter!", hrgn1, pRect));
1975 SetLastError(ERROR_INVALID_PARAMETER_W);
1976 return FALSE;
1977 }
1978 hrgn = ObjQueryHandleData(hrgn, HNDL_REGION);
1979 if(hrgn == HANDLE_OBJ_ERROR) {
1980 dprintf(("WARNING: RectInRgn %x %x invalid region", hrgn1, pRect));
1981 SetLastError(ERROR_INVALID_HANDLE_W);
1982 return FALSE;
1983 }
1984
1985 RECTL rectl;
1986 MapWin32ToOS2Rect(*pRect, rectl);
1987 //switch bottom & top
1988 UINT temp = rectl.yBottom;
1989 rectl.yBottom = rectl.yTop;
1990 rectl.yTop = temp;
1991
1992 lInside = GpiRectInRegion(hpsRegion, hrgn, &rectl);
1993 if(lInside == RRGN_ERROR) {
1994 success = FALSE;
1995 }
1996 else success = TRUE;
1997
1998 SetLastError(ERROR_SUCCESS_W);
1999
2000 dprintf(("RectInRgn %x %x returned %d", hrgn1, pRect, (success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL)) ? 1 : 0));
2001
2002 if(success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL))
2003 return TRUE;
2004 else
2005 return FALSE;
2006}
2007//******************************************************************************
2008//Returned region in device coordinates (undocumented behaviour)
2009//******************************************************************************
2010HRGN WIN32API PathToRegion( HDC hdc)
2011{
2012 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
2013 if(!pHps)
2014 {
2015 dprintf(("WARNING: PathToRegion %x; invalid hdc!", hdc));
2016 SetLastError(ERROR_INVALID_HANDLE_W);
2017 return NULLHANDLE;
2018 }
2019
2020 HRGN hrgn, hrgnTemp, hrgnwin;
2021
2022 dprintf(("GDI32: PathToRegion %x", hdc));
2023
2024 hrgnTemp = GpiPathToRegion(pHps->hps, 1, (pHps->polyFillMode == ALTERNATE_W) ? FPATH_ALTERNATE : FPATH_WINDING);
2025 if(hrgnTemp == NULLHANDLE)
2026 goto error;
2027
2028 hrgnwin = CreateRectRgn(1, 1, 2, 2);
2029 hrgn = ObjQueryHandleData(hrgnwin, HNDL_REGION);
2030 if(hrgn == HANDLE_OBJ_ERROR) {
2031 dprintf(("WARNING: PathToRegion invalid region", hrgnwin));
2032 SetLastError(ERROR_INVALID_HANDLE_W);
2033 return NULLHANDLE;
2034 }
2035
2036 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnTemp, pHps, NULL))
2037 goto error;
2038
2039 GpiDestroyRegion(pHps->hps, hrgnTemp);
2040
2041 return hrgnwin;
2042
2043error:
2044 if(hrgnwin)
2045 DeleteObject(hrgnwin);
2046
2047 SetLastError(ERROR_INVALID_HANDLE_W); //todo right error
2048 return NULLHANDLE;
2049}
2050//******************************************************************************
2051//Needs wrapper as this file includes os2.h!!
2052//******************************************************************************
2053BOOL WIN32API OSLibDeleteRegion(HANDLE hRegion)
2054{
2055 if(GpiDestroyRegion(hpsRegion, hRegion) == FALSE) {
2056 dprintf(("WARNING: OSLibDeleteRegion %x; GpiDestroyRegion failed (%x)", hRegion, WinGetLastError(0)));
2057 }
2058 return (0);
2059}
2060/*****************************************************************************
2061 * Name : int GetMetaRgn
2062 * Purpose : The GetMetaRgn function retrieves the current metaregion for
2063 * the specified device context.
2064 * Parameters: HDC hdc handle of device context
2065 * HRGN hrgn handle of region
2066 * Variables :
2067 * Result : 0 / 1
2068 * Remark :
2069 * Status : UNTESTED STUB
2070 *
2071 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
2072 *****************************************************************************/
2073
2074int WIN32API GetMetaRgn( HDC hdc, HRGN hrgn)
2075{
2076 dprintf(("GDI32: GetMetaRgn(%08xh, %08xh) not implemented.\n",
2077 hdc,
2078 hrgn));
2079
2080 SetLastError(ERROR_SUCCESS_W);
2081 return (0);
2082}
2083/*****************************************************************************
2084 * Name : int SetMetaRgn
2085 * Purpose : The SetMetaRgn function intersects the current clipping region
2086 * for the specified device context with the current metaregion
2087 * and saves the combined region as the new metaregion for the
2088 * specified device context. The clipping region is reset to a null region.
2089 * Parameters: HDC hdc handle of device context
2090 * Variables :
2091 * Result : TRUE / FALSE
2092 * Remark :
2093 * Status : UNTESTED STUB
2094 *
2095 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
2096 *****************************************************************************/
2097
2098BOOL WIN32API SetMetaRgn( HDC hdc)
2099{
2100 dprintf(("GDI32: SetMetaRgn(%08xh) not implemented.\n",
2101 hdc));
2102
2103 SetLastError(ERROR_SUCCESS_W);
2104 return (NULLREGION_W);
2105}
2106//******************************************************************************
2107//******************************************************************************
Note: See TracBrowser for help on using the repository browser.