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

Last change on this file since 7178 was 7074, checked in by sandervl, 24 years ago

destroy region presentation space during unload

File size: 52.8 KB
Line 
1/* $Id: region.cpp,v 1.24 2001-10-16 11:40: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 *
9 * TODO: Metafile recording
10 * TODO: Do we need to translate & set the last error for Gpi operations?
11 *
12 * Project Odin Software License can be found in LICENSE.TXT
13 *
14 */
15
16// Note: profiling currently not supported for this file
17#undef PROFILE
18#include <odinwrap.h>
19
20#define INCL_GPI
21#define INCL_WIN
22#include <os2wrap.h> //need odin wrappers
23
24#include <win32type.h>
25#include <win32api.h>
26#include <winconst.h>
27#include <stdlib.h>
28#include <stdarg.h>
29#include <string.h>
30#include <misc.h>
31#include <objhandle.h>
32#include <dcdata.h>
33#include <winuser32.h>
34#include "oslibgpi.h"
35
36#define DBG_LOCALLOG DBG_region
37#include "dbglocal.h"
38
39
40ODINDEBUGCHANNEL(GDI32-REGION)
41
42
43typedef enum
44{
45 AS_DEVICE,
46 AS_WORLD
47} InterpMode;
48
49#define MEM_HPS_MAX 768
50
51static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count);
52
53#define convertWinDeviceRectToPMDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
54#define convertPMDeviceRectToWinDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
55
56inline void convertDeviceRect(pDCData pHps, PRECTL pRectl, ULONG count)
57{
58 convertDeviceRect(0, pHps, pRectl, count);
59}
60inline void convertDeviceRect(HWND hwnd, PRECTL pRectl, ULONG count)
61{
62 convertDeviceRect(hwnd, 0, pRectl, count);
63}
64
65HPS hpsRegion = 0;
66
67//******************************************************************************
68//******************************************************************************
69BOOL InitRegionSpace()
70{
71 hpsRegion = WinGetScreenPS(HWND_DESKTOP);
72 return hpsRegion != 0;
73}
74//******************************************************************************
75//******************************************************************************
76void DestroyRegionSpace()
77{
78 if(hpsRegion) WinReleasePS(hpsRegion);
79 hpsRegion = 0;
80}
81//******************************************************************************
82//******************************************************************************
83LONG hdcHeight(HWND hwnd, pDCData pHps)
84{
85 if(hwnd == 0 && pHps != 0)
86 hwnd = pHps->hwnd;
87
88 if(hwnd != 0 || pHps == 0)
89 {
90 RECT rect;
91 RECTL rectl;
92 LONG y = 0;
93
94 if(pHps == 0 || pHps->isClient) //client area
95 {
96 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
97 y = rect.bottom - rect.top;
98 }
99 }
100 else
101 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
102 y = rectl.yTop;
103
104 return y;
105 }
106 else
107 if(pHps->bitmapHandle)
108 {
109 return pHps->bitmapHeight;
110 }
111 else
112 if(pHps->isMetaPS)
113 {
114 return 0;
115 }
116 else
117 if(pHps->isPrinter)
118 {
119 return pHps->printPageHeight;
120 }
121 else
122 {
123 return MEM_HPS_MAX;
124 }
125}
126//******************************************************************************
127//******************************************************************************
128LONG hdcWidth(HWND hwnd, pDCData pHps)
129{
130 if(hwnd == 0 && pHps != 0)
131 hwnd = pHps->hwnd;
132
133 if(hwnd != 0 || pHps == 0)
134 {
135 RECT rect;
136 RECTL rectl;
137 LONG x = 0;
138
139 if(pHps == 0 || pHps->isClient) //client area
140 {
141 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
142 x = rect.right - rect.left;
143 }
144 }
145 else
146 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
147 x = rectl.xRight;
148
149 return x;
150 }
151// else
152// DebugInt3();
153 return 0;
154}
155//******************************************************************************
156//******************************************************************************
157static void convertWinWorldRectToPMDeviceRect(pDCData pHps_Hdc, PRECTL pRects, UINT count = 1)
158{
159 PRECTL pRectl;
160 for (int x=0; x < count; x++)
161 {
162 pRectl = &pRects[x];
163
164 if(pRectl->yTop < pRectl->yBottom) {
165 ULONG temp = pRectl->yBottom;
166 pRectl->yBottom = pRectl->yTop;
167 pRectl->yTop = temp;
168 }
169 BOOL success = GpiConvert( pHps_Hdc->hps, CVTC_WORLD, CVTC_DEVICE, 2, (PPOINTL)pRectl);
170 if(!success)
171 {
172 break;
173 }
174 if(pRectl->yTop < pRectl->yBottom) {
175 ULONG temp = pRectl->yBottom;
176 pRectl->yBottom = pRectl->yTop;
177 pRectl->yTop = temp;
178 }
179 }
180}
181//******************************************************************************
182//******************************************************************************
183static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count)
184{
185 long wHeight, wWidth;
186
187 if(hwnd == HWND_DESKTOP) {
188 wHeight = OSLibGetScreenHeight();
189 wWidth = OSLibGetScreenWidth();
190 }
191 else {
192 wHeight = hdcHeight(hwnd, pHps);
193 wWidth = hdcWidth(hwnd, pHps);
194 }
195
196 if(pHps)
197 {
198 wHeight += pHps->HPStoHDCInversionHeight;
199 }
200
201 if(hwnd || (pHps && pHps->hwnd)) {
202 for(int x=0; x < count; x++)
203 {
204 if(pRectl[x].xRight > wWidth) {
205 pRectl[x].xRight = wWidth;
206 }
207 if(pRectl[x].yTop > wHeight) {
208 pRectl[x].yTop = 0;
209 }
210 else pRectl[x].yTop = wHeight - pRectl[x].yTop;
211
212 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
213 }
214 }
215 else {
216 for(int x=0; x < count; x++)
217 {
218 pRectl[x].yTop = wHeight - pRectl[x].yTop;
219 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
220 }
221 }
222}
223//******************************************************************************
224//******************************************************************************
225static void convertPMDeviceRectToWinWorldRect(pDCData pHps_Hdc, PRECTL pRectl)
226{
227 GpiConvert(pHps_Hdc->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)pRectl );
228}
229//******************************************************************************
230//******************************************************************************
231BOOL interpretRegionAs(pDCData pHps, HRGN hrgnDest, HRGN hrgnSrc, InterpMode mode)
232{
233 BOOL success = FALSE;
234 int x, i;
235 HPS hpsDest;
236
237 if(pHps)
238 {
239 if(!hrgnDest) {
240 hrgnDest = pHps->hrgnHDC;
241#ifdef DEBUG
242 if(hrgnDest == 0) {
243 DebugInt3();
244 }
245#endif
246 }
247 hpsDest = pHps->hps;
248 }
249 else {
250 DebugInt3();
251 return FALSE;
252 }
253
254 RGNRECT rgnRect;
255 rgnRect.ircStart = 1;
256 rgnRect.crc = 0;
257 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
258 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, NULL);
259 if(success)
260 {
261 if(rgnRect.crcReturned > 0)
262 {
263 rgnRect.crc = rgnRect.crcReturned;
264 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
265 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, pRectl);
266 if(success)
267 {
268 if(mode == AS_DEVICE)
269 {
270 ULONG temp;
271 for(x=0; x < rgnRect.crcReturned; x++)
272 {
273 temp = pRectl[x].yBottom;
274 pRectl[x].yBottom = pRectl[x].yTop;
275 pRectl[x].yTop = temp;
276 }
277 convertWinDeviceRectToPMDeviceRect(pHps, pRectl, rgnRect.crcReturned);
278 }
279 else
280 {
281 GpiConvert(pHps->hps, CVTC_WORLD, CVTC_DEVICE, rgnRect.crcReturned<<1, (PPOINTL)pRectl);
282
283 ULONG temp;
284 for(i=0; i < rgnRect.crcReturned; i++)
285 {
286 if(pRectl[i].yTop < pRectl[i].yBottom)
287 {
288 temp = pRectl[i].yBottom + 1;
289 pRectl[i].yBottom = pRectl[i].yTop + 1;
290 pRectl[i].yTop = temp;
291 }
292 else
293 {
294 pRectl[i].yTop++;
295 pRectl[i].yBottom++;
296 }
297 }
298 }
299 success = GpiSetRegion(hpsDest, hrgnDest, rgnRect.crcReturned, pRectl);
300 }
301 delete[] pRectl;
302 }
303 else
304 {
305 success = GpiSetRegion(hpsDest, hrgnDest, 0, NULL);
306 }
307 }
308 return success;
309}
310//******************************************************************************
311//exported (used by user32)
312//******************************************************************************
313BOOL WIN32API setWinDeviceRegionFromPMDeviceRegion(HRGN winHrgn, HRGN pmHrgn, pDCData pHpsPmHrgn, HWND hwndPmHrgn)
314{
315 BOOL success;
316 int x;
317 BOOL mustReleaseScreenPS = FALSE;
318 HPS hps;
319
320 if(pHpsPmHrgn || hwndPmHrgn)
321 {
322 if(pHpsPmHrgn)
323 hps = pHpsPmHrgn->hps;
324 else
325 {
326 hps = WinGetScreenPS(HWND_DESKTOP);
327 mustReleaseScreenPS = TRUE;
328 }
329
330 RGNRECT rgnRect;
331 rgnRect.ircStart = 1;
332 rgnRect.crc = 0;
333 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
334 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, NULL);
335 if(success )
336 {
337 if(rgnRect.crcReturned > 0)
338 {
339 rgnRect.crc = rgnRect.crcReturned;
340 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
341 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, pRectl);
342 if(success)
343 {
344 if(pHpsPmHrgn)
345 convertPMDeviceRectToWinDeviceRect(pHpsPmHrgn, pRectl, rgnRect.crcReturned);
346 else
347 convertPMDeviceRectToWinDeviceRect(hwndPmHrgn, pRectl, rgnRect.crcReturned);
348
349 for(x=0; x < rgnRect.crcReturned; x++)
350 {
351 ULONG temp = pRectl[x].yBottom;
352 pRectl[x].yBottom = pRectl[x].yTop;
353 pRectl[x].yTop = temp;
354 }
355
356 success = GpiSetRegion(hpsRegion, winHrgn, rgnRect.crcReturned, pRectl);
357 }
358 delete[] pRectl;
359 }
360 else
361 {
362 success = GpiSetRegion(hpsRegion, winHrgn, 0, NULL);
363 }
364 }
365 }
366 else
367 success = FALSE;
368
369 if(mustReleaseScreenPS)
370 WinReleasePS(hps);
371
372 return success;
373}
374//******************************************************************************
375int WIN32API GetRgnBox( HRGN hrgn, PRECT pRect);
376//******************************************************************************
377ODINFUNCTIONNODBG2(int, SelectClipRgn, HDC, hdc, HRGN, hrgn)
378{
379 LONG lComplexity = RGN_NULL;
380 HRGN hrgnNewClip;
381 HRGN hrgnOldClip;
382#ifdef DEBUG
383 HRGN hrgn1 = hrgn;
384#endif
385
386 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
387 if(!pHps)
388 {
389 dprintf(("WARNING: SelectClipRgn: invalid hdc!", hdc, hrgn));
390 SetLastError(ERROR_INVALID_HANDLE_W);
391 return ERROR_W;
392 }
393
394 dprintf(("SelectClipRgn: %x %x", hdc, hrgn));
395 if(hrgn)
396 {
397 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
398 if(hrgn == HANDLE_OBJ_ERROR) {
399 dprintf(("WARNING: SelectClipRgn: invalid region!", hdc, hrgn1));
400 SetLastError(ERROR_INVALID_HANDLE_W);
401 return ERROR_W;
402 }
403 }
404
405 if(hrgn)
406 {
407 RECTL rectl = {0,0,1,1};
408 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
409 if(interpretRegionAs(pHps, hrgnNewClip, hrgn, AS_DEVICE) == 0)
410 {
411 lComplexity = RGN_ERROR;
412 }
413 }
414 else
415 hrgnNewClip = 0;
416
417 if(lComplexity != RGN_ERROR)
418 {
419 if(hrgnNewClip == 0) {
420 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
421 }
422 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
423 if (lComplexity != RGN_ERROR )
424 {
425 if(hrgnOldClip)
426 GpiDestroyRegion(pHps->hps, hrgnOldClip);
427
428 //todo: metafile recording
429 SetLastError(ERROR_SUCCESS_W);
430
431 //SvL: Must check if origin changed here. Sometimes happens when
432 // window looses focus. (don't know why....)
433 checkOrigin(pHps);
434 return lComplexity;
435 }
436 }
437
438 dprintf(("WARNING: SelectClipRgn: RGN_ERROR!", hdc, hrgn1));
439 if(hrgnNewClip)
440 GpiDestroyRegion(pHps->hps, hrgnNewClip);
441
442 SetLastError(ERROR_SUCCESS_W);
443 return lComplexity;
444}
445//******************************************************************************
446//******************************************************************************
447ODINFUNCTIONNODBG3(int, ExtSelectClipRgn, HDC, hdc, HRGN, hrgn, int, mode)
448{
449#ifdef DEBUG
450 HRGN hrgn1 = hrgn;
451#endif
452
453 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
454 if (!pHps)
455 {
456 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid hdc", hdc, hrgn, mode));
457 SetLastError(ERROR_INVALID_HANDLE_W);
458 return ERROR_W;
459 }
460
461 LONG lComplexity;
462 HRGN hrgnCurrent = NULLHANDLE;
463
464 if(!hrgn && mode != RGN_COPY_W)
465 {
466 SetLastError(ERROR_INVALID_PARAMETER_W);
467 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
468 return ERROR_W;
469 }
470
471 LONG lMode;
472 switch (mode)
473 {
474 case RGN_AND_W : lMode = CRGN_AND ; break;
475 case RGN_COPY_W : lMode = CRGN_COPY; break;
476 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
477 case RGN_OR_W : lMode = CRGN_OR ; break;
478 case RGN_XOR_W : lMode = CRGN_XOR ; break;
479 default:
480 {
481 SetLastError(ERROR_INVALID_PARAMETER_W);
482 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
483 return ERROR_W;
484 }
485 }
486
487 if(hrgn)
488 {
489 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
490 if(hrgn == HANDLE_OBJ_ERROR) {
491 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid region handle", hdc, hrgn1, mode));
492 SetLastError(ERROR_INVALID_HANDLE_W);
493 return 0;
494 }
495 }
496
497 dprintf(("ExtSelectRgn %x %x %d", hdc, hrgn1, mode));
498 //TODO: metafile recording
499 if(hrgn)
500 {
501 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
502 {
503 return ERROR_W;
504 }
505 }
506 else
507 {
508 //remove clip region
509 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
510 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
511
512 if(hrgnCurrent)
513 GpiDestroyRegion(pHps->hps, hrgnCurrent);
514
515 return NULLREGION_W;
516 }
517
518 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
519
520 if(hrgnCurrent == NULLHANDLE)
521 {
522 lMode = CRGN_COPY;
523 RECTL rectl = {0, 0, 1, 1};
524 hrgnCurrent = GpiCreateRegion(pHps->hps, 1, &rectl);
525 }
526
527 HRGN hrgnSrc1;
528 HRGN hrgnSrc2;
529 if(lMode != CRGN_COPY)
530 {
531 hrgnSrc1 = hrgnCurrent;
532 hrgnSrc2 = pHps->hrgnHDC;
533 }
534 else
535 {
536 hrgnSrc1 = pHps->hrgnHDC;
537 hrgnSrc2 = NULLHANDLE;
538 }
539
540 lComplexity = GpiCombineRegion(pHps->hps, hrgnCurrent, hrgnSrc1, hrgnSrc2, lMode);
541 if (lComplexity != RGN_ERROR)
542 {
543 HRGN hrgnOld;
544 lComplexity = GpiSetClipRegion(pHps->hps, hrgnCurrent, &hrgnOld);
545 SetLastError(ERROR_SUCCESS_W);
546
547 //SvL: Must check if origin changed here. Sometimes happens when
548 // window looses focus. (don't know why....)
549 checkOrigin(pHps);
550
551 if (lComplexity != RGN_ERROR)
552 return lComplexity;
553 }
554 SetLastError(ERROR_SUCCESS_W);
555 return ERROR_W;
556}
557//******************************************************************************
558//******************************************************************************
559ODINFUNCTIONNODBG2(int, GetClipBox, HDC, hdc, PRECT, lpRect)
560{
561 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
562 RECTL rectl;
563 LONG lComplexity;
564 int rc;
565
566 if(!hdc || !lpRect || !pHps) {
567 dprintf(("GDI32: GetClipBox %x %x ERROR_INVALID_PARAMETER", hdc, lpRect));
568 SetLastError(ERROR_INVALID_PARAMETER_W);
569 return ERROR_W;
570 }
571 if(pHps->isPrinter)
572 {
573 lpRect->left = 0;
574 lpRect->top = 0;
575 lpRect->right = GetDeviceCaps( hdc, HORZRES_W);
576 lpRect->bottom = GetDeviceCaps( hdc, VERTRES_W);
577 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
578 convertPMDeviceRectToWinWorldRect(pHps, &rectl);
579
580 rc = SIMPLEREGION_W;
581 }
582 else {
583 lComplexity = GpiQueryClipBox(pHps->hps, &rectl);
584 if(lComplexity == RGN_ERROR)
585 {
586 rc = ERROR_W;
587 }
588 else
589 if(lComplexity == RGN_NULL)
590 {
591 memset(lpRect, 0, sizeof(*lpRect));
592 rc = NULLREGION_W;
593 }
594 else {
595#ifndef INVERT
596 //Convert coordinates from PM to win32
597 if (pHps->yInvert > 0) {
598 LONG temp = pHps->yInvert - rectl.yBottom;
599 rectl.yBottom = pHps->yInvert - rectl.yTop;
600 rectl.yTop = temp;
601 }
602#endif
603 //Convert including/including to including/excluding
604 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
605
606 lpRect->left = rectl.xLeft;
607 lpRect->right = rectl.xRight;
608
609 if(rectl.yBottom > rectl.yTop) {
610 lpRect->top = rectl.yTop;
611 lpRect->bottom = rectl.yBottom;
612 }
613 else {
614 lpRect->top = rectl.yBottom;
615 lpRect->bottom = rectl.yTop;
616 }
617
618 rc = (lComplexity == RGN_RECT) ? SIMPLEREGION_W : COMPLEXREGION_W;
619 }
620 }
621// if(lpRect->left == 0 && lpRect->top == 0 && lpRect->right == 0 && lpRect->bottom == 0)
622// DebugInt3();
623 dprintf(("GDI32: GetClipBox of %X returned %d; (%d,%d)(%d,%d)", hdc, rc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
624 return rc;
625}
626//******************************************************************************
627//******************************************************************************
628ODINFUNCTIONNODBG2(int, GetClipRgn, HDC, hdc, HRGN, hrgn)
629{
630 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
631 BOOL success;
632 LONG lComplexity = RGN_RECT;
633 HRGN hrgnClip = NULL, hrgnTemp;
634#ifdef DEBUG
635 HRGN hrgn1 = hrgn;
636#endif
637
638 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
639 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
640 dprintf(("WARNING: GetClipRgn %x %x invalid handle", hdc, hrgn1));
641 SetLastError(ERROR_INVALID_HANDLE_W);
642 return 0;
643 }
644
645 if(GpiSetClipRegion(pHps->hps, NULL, &hrgnClip) == RGN_ERROR) {
646 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed! (%x)", WinGetLastError(0)));
647 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
648 return 0;
649 }
650 if(hrgnClip) {
651 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnClip, pHps, NULL)) {
652 dprintf(("WARNING: GetClipRgn setWinDeviceRegionFromPMDeviceRegion failed!"));
653 GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp);
654 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
655 return 0;
656 }
657 if(GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp) == RGN_ERROR )
658 {
659 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed %x!", WinGetLastError(0)));
660 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
661 return 0;
662 }
663 }
664 else lComplexity = RGN_NULL;
665
666 dprintf(("GetClipRgn %x %x returned %d", hdc, hrgn1, lComplexity != RGN_NULL));
667 SetLastError(ERROR_SUCCESS_W);
668 if(lComplexity == RGN_NULL)
669 return 0;
670 else return 1;
671}
672//******************************************************************************
673//******************************************************************************
674ODINFUNCTIONNODBG5(int, ExcludeClipRect, HDC, hdc, int, left, int, top, int, right, int, bottom)
675{
676 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
677 if(!pHps)
678 {
679 dprintf(("WARNING: ExcludeClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
680 SetLastError(ERROR_INVALID_HANDLE_W);
681 return ERROR_W;
682 }
683
684 LONG lComplexity;
685 RECTL rectl = { left, bottom, right, top };
686
687 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
688 if(rectl.yTop < rectl.yBottom) {
689 ULONG temp = rectl.yBottom;
690 rectl.yBottom = rectl.yTop;
691 rectl.yTop = temp;
692 }
693
694#ifndef INVERT
695 if (pHps->yInvert > 0) {
696 LONG temp = pHps->yInvert - rectl.yBottom;
697 rectl.yBottom = pHps->yInvert - rectl.yTop;
698 rectl.yTop = temp;
699 }
700#endif
701
702 dprintf(("ExcludeClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
703 lComplexity = GpiExcludeClipRectangle(pHps->hps, &rectl);
704 if (lComplexity == RGN_ERROR) {
705 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
706 return ERROR_W;
707 }
708
709 //todo metafile recording
710
711 SetLastError(ERROR_SUCCESS_W);
712 return lComplexity;
713}
714//******************************************************************************
715//******************************************************************************
716ODINFUNCTIONNODBG5(int, IntersectClipRect, HDC, hdc, int, left, int, top, int, right, int, bottom)
717{
718 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
719 LONG lComplexity;
720 BOOL success;
721
722 if(!pHps) {
723 dprintf(("WARNING: IntersectClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
724 SetLastError(ERROR_INVALID_HANDLE_W);
725 return ERROR_W;
726 }
727 RECTL rectl = { left, bottom, right, top };
728
729 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
730 if(rectl.yTop < rectl.yBottom) {
731 ULONG temp = rectl.yBottom;
732 rectl.yBottom = rectl.yTop;
733 rectl.yTop = temp;
734 }
735
736#ifndef INVERT
737 //Convert coordinates from PM to win32
738 if (pHps->yInvert > 0) {
739 LONG temp = pHps->yInvert - rectl.yBottom;
740 rectl.yBottom = pHps->yInvert - rectl.yTop;
741 rectl.yTop = temp;
742 }
743#endif
744
745 dprintf(("IntersectClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
746 lComplexity = GpiIntersectClipRectangle(pHps->hps, &rectl);
747
748 //todo metafile recording
749
750 SetLastError(ERROR_SUCCESS_W);
751 return lComplexity;
752}
753//******************************************************************************
754//******************************************************************************
755ODINFUNCTIONNODBG3(int, OffsetClipRgn, HDC, hdc, int, nXOffset, int, nYOffset )
756{
757 BOOL success;
758 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
759 LONG lComplexity;
760
761 if(!pHps) {
762 dprintf(("OffsetClipRgn %x (%d,%d) invalid hdc", hdc, nXOffset, nYOffset));
763 SetLastError(ERROR_INVALID_HANDLE_W);
764 return ERROR_W;
765 }
766
767 dprintf(("OffsetClipRgn %x (%d,%d)", hdc, nXOffset, nYOffset));
768 POINTL pointl = { nXOffset, nYOffset };
769#ifndef INVERT
770 if (pHps->yInvert > 0) {
771 pointl.y = pHps->yInvert - pointl.y;
772 }
773#endif
774
775 lComplexity = GpiOffsetClipRegion(pHps->hps, &pointl);
776
777 //todo metafile recording
778
779 SetLastError(ERROR_SUCCESS_W);
780 return lComplexity;
781}
782//******************************************************************************
783//******************************************************************************
784ODINFUNCTIONNODBG4(HRGN, CreatePolyPolygonRgn, const POINT * , lppt, const int *, pPolyCount, int, nCount, int, fnPolyFillMode)
785{
786 LONG flMode;
787
788 switch(fnPolyFillMode)
789 {
790 case ALTERNATE_W:
791 flMode = POLYGON_ALTERNATE;
792 break;
793 case WINDING_W:
794 flMode = POLYGON_WINDING;
795 break;
796 default:
797 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
798 SetLastError(ERROR_INVALID_PARAMETER_W);
799 return 0;
800 }
801
802 if(nCount < 1)
803 {
804 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
805 SetLastError(ERROR_INVALID_PARAMETER_W);
806 return 0;
807 }
808
809 PPOLYGON pPolygon = new POLYGON[nCount];
810 if(!pPolygon) {
811 dprintf(("ERROR: CreatePolyPolygonRgn: out of memory!!"));
812 SetLastError(ERROR_OUTOFMEMORY_W);
813 return 0;
814 }
815 dprintf(("CreatePolyPolygonRgn %x %x %d %d", lppt, pPolyCount, nCount, fnPolyFillMode));
816
817 PPOINTL pPointl = (PPOINTL)lppt+1; // skip first point
818 for (int x=0; x < nCount; x++) {
819 pPolygon[x].ulPoints = (x == 0) ? pPolyCount[x] - 1 : pPolyCount[x];
820 pPolygon[x].aPointl = pPointl;
821 pPointl += pPolygon[x].ulPoints;
822 }
823 GpiMove(hpsRegion, (PPOINTL)lppt);
824 HRGN hrgn = GpiCreatePolygonRegion(hpsRegion, nCount, pPolygon, POLYGON_BOUNDARY | flMode);
825
826 delete[] pPolygon;
827
828 if(!hrgn) {
829 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
830 return 0;
831 }
832
833 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
834 SetLastError(ERROR_OUTOFMEMORY_W);
835 return 0;
836 }
837 SetLastError(ERROR_SUCCESS_W);
838 return hrgn;
839}
840//******************************************************************************
841//******************************************************************************
842ODINFUNCTIONNODBG4(HRGN, CreateRectRgn, int, left, int, top, int, right, int, bottom)
843{
844 HRGN hrgn;
845 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
846
847 hrgn = GpiCreateRegion(hpsRegion, 1, &rectl);
848 if(!hrgn) {
849 dprintf(("WARNING: CreateRectRgn: GpiCreateRectRegion failed! %x", WinGetLastError(0)));
850 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
851 return 0;
852 }
853
854 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
855 SetLastError(ERROR_OUTOFMEMORY_W);
856 return 0;
857 }
858 dprintf(("CreateRectRegion (%d,%d)(%d,%d) returned %x", left, top, right, bottom, hrgn));
859 SetLastError(ERROR_SUCCESS_W);
860 return hrgn;
861}
862//******************************************************************************
863//******************************************************************************
864ODINFUNCTIONNODBG1(HRGN, CreateRectRgnIndirect, const RECT *, lprc)
865{
866 return CreateRectRgn(lprc->left, lprc->top, lprc->right, lprc->bottom);
867}
868//******************************************************************************
869//******************************************************************************
870ODINFUNCTIONNODBG6(HRGN, CreateRoundRectRgn, int, left, int, top, int, right, int, bottom, int, nWidthEllipse, int, nHeightEllipse)
871{
872 HRGN hrgn;
873 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
874
875 PPOINTL pPointl = (PPOINTL)&rectl;
876
877 GpiMove(hpsRegion, &pPointl[0]);
878 hrgn = GpiCreateRoundRectRegion(hpsRegion, &pPointl[1], labs(nWidthEllipse), labs(nHeightEllipse));
879
880 if(!hrgn) {
881 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
882 dprintf(("WARNING: CreateRoundRectRgn: GpiCreateRoundRectRegion failed! %x", WinGetLastError(0)));
883 return 0;
884 }
885
886 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
887 SetLastError(ERROR_OUTOFMEMORY_W);
888 return 0;
889 }
890 dprintf(("CreateRoundRectRegion (%d,%d)(%d,%d) (%d,%d) returned %x", left, top, right, bottom, nWidthEllipse, nHeightEllipse, hrgn));
891 SetLastError(ERROR_SUCCESS_W);
892 return hrgn;
893}
894//******************************************************************************
895//******************************************************************************
896ODINFUNCTIONNODBG3(HRGN, ExtCreateRegion, const XFORM_W *, pXform, DWORD, count, const RGNDATA *, pData)
897{
898 HRGN hrgn;
899
900 if(!pData || count < (sizeof(RGNDATAHEADER) + pData->rdh.nCount * sizeof(RECT))) {
901 dprintf(("WARNING: ExtCreateRegion %x %d %x; invalid parameter", pXform, count, pData));
902 SetLastError(ERROR_INVALID_PARAMETER_W);
903 return 0;
904 }
905
906 PRECTL pRectl = new RECTL[pData->rdh.nCount];
907 PRECT pDataRects = (PRECT)pData->Buffer;
908 for(int i=0; i < pData->rdh.nCount; i++) {
909 MapWin32ToOS2Rect(pDataRects[i], pRectl[i]);
910 }
911
912 BOOL doShear = pXform && (pXform->eM12 || pXform->eM21);
913 HPS hpsTemp = NULLHANDLE;
914
915 dprintf(("ExtCreateRegion %x %d %x", pXform, count, pData));
916 if(doShear) {
917 hpsTemp = WinGetPS(HWND_DESKTOP);
918 GpiBeginPath(hpsTemp, 1);
919
920 MATRIXLF matrixlf;
921 matrixlf.fxM11 = pXform->eM11 * (float)0x10000;
922 matrixlf.fxM12 = pXform->eM12 * (float)0x10000;
923 matrixlf.lM13 = 0;
924 matrixlf.fxM21 = pXform->eM21 * (float)0x10000;
925 matrixlf.fxM22 = pXform->eM22 * (float)0x10000;
926 matrixlf.lM23 = 0;
927 matrixlf.lM31 = pXform->eDx;
928 matrixlf.lM32 = pXform->eDy;
929 matrixlf.lM33 = 1;
930
931 GpiSetModelTransformMatrix(hpsTemp, 9, &matrixlf, TRANSFORM_REPLACE);
932 }
933
934 for(i=0; i < pData->rdh.nCount; i++)
935 {
936 LONG temp = pRectl[i].yTop;
937 pRectl[i].yTop = pRectl[i].yBottom;
938 pRectl[i].yBottom = temp;
939
940 if(pXform)
941 {
942 PPOINTL pPointl = ((PPOINTL)&pRectl[i]);
943
944 if (doShear) {
945 GpiMove(hpsTemp, pPointl);
946 GpiBox(hpsTemp, DRO_OUTLINE, pPointl+1, 0, 0);
947 }
948 else
949 {
950 for(int j=0; j < 2; j++) {
951 pPointl[j].x = (pXform->eM11 * (float)pPointl[j].x) + (pXform->eM12 * (float)pPointl[j].y) + pXform->eDx;
952 pPointl[j].y = (pXform->eM21 * (float)pPointl[j].x) + (pXform->eM22 * (float)pPointl[j].y) + pXform->eDy;
953 }
954
955 PRECTL pRectlT = (PRECTL)pPointl;
956 if (pRectlT->xLeft > pRectlT->xRight) {
957 LONG temp = pRectlT->xLeft;
958 pRectlT->xLeft = pRectlT->xRight;
959 pRectlT->xRight = temp;
960 }
961 if (pRectlT->yBottom > pRectlT->yTop) {
962 LONG temp = pRectlT->yBottom;
963 pRectlT->yBottom = pRectlT->yTop;
964 pRectlT->yTop = temp;
965 }
966 }
967 }
968 }
969
970 if(doShear) {
971 GpiEndPath(hpsTemp);
972 hrgn = GpiPathToRegion(hpsTemp, 1, FPATH_WINDING);
973
974 if(pRectl)
975 delete[] pRectl;
976
977 if(hrgn == 0) {
978 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
979 SetLastError(ERROR_INVALID_PARAMETER_W);
980 return 0;
981 }
982 WinReleasePS(hpsTemp);
983 }
984 else {
985 hrgn = GpiCreateRegion(hpsRegion, pData->rdh.nCount, pRectl);
986 if(pRectl)
987 delete[] pRectl;
988
989 if(hrgn == 0) {
990 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
991 SetLastError(ERROR_INVALID_PARAMETER_W);
992 return 0;
993 }
994 }
995
996 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
997 SetLastError(ERROR_OUTOFMEMORY_W);
998 return 0;
999 }
1000 SetLastError(ERROR_SUCCESS_W);
1001 return hrgn;
1002}
1003//******************************************************************************
1004//******************************************************************************
1005ODINFUNCTIONNODBG4(HRGN, CreateEllipticRgn, int, left, int, top, int, right, int, bottom)
1006{
1007 HRGN hrgn;
1008
1009 RECTL rectl = { left,
1010 top < bottom ? top : bottom,
1011 right,
1012 top < bottom ? bottom : top };
1013
1014 dprintf(("CreateEllipticRgn (%d,%d)(%d,%d)", left, top, right, bottom));
1015 hrgn = GpiCreateEllipticRegion(hpsRegion, &rectl);
1016
1017 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
1018 SetLastError(ERROR_OUTOFMEMORY_W);
1019 return 0;
1020 }
1021 SetLastError(ERROR_SUCCESS_W);
1022 return hrgn;
1023}
1024//******************************************************************************
1025//******************************************************************************
1026ODINFUNCTIONNODBG1(HRGN, CreateEllipticRgnIndirect, const RECT *, pRect)
1027{
1028 return CreateEllipticRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
1029}
1030//******************************************************************************
1031//******************************************************************************
1032ODINFUNCTIONNODBG3(HRGN, CreatePolygonRgn, const POINT *, lppt, int, cPoints, int, fnPolyFillMode)
1033{
1034 HRGN hrgn;
1035 LONG flMode;
1036
1037 if(!lppt || cPoints < 2) {
1038 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1039 SetLastError(ERROR_INVALID_PARAMETER_W);
1040 return 0;
1041 }
1042
1043 switch (fnPolyFillMode)
1044 {
1045 case ALTERNATE_W :
1046 flMode = POLYGON_ALTERNATE;
1047 break;
1048 case WINDING_W :
1049 flMode = POLYGON_WINDING;
1050 break;
1051 default:
1052 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1053 SetLastError(ERROR_INVALID_PARAMETER_W);
1054 return 0;
1055 }
1056
1057 dprintf(("CreatePolygonRgn %x %d %d", lppt, cPoints, fnPolyFillMode));
1058
1059
1060 POLYGON polygon;
1061 polygon.ulPoints = cPoints - 1;
1062 polygon.aPointl = (PPOINTL)(lppt + 1);
1063
1064 GpiMove(hpsRegion, (PPOINTL)lppt);
1065 hrgn = GpiCreatePolygonRegion(hpsRegion, 1, &polygon, POLYGON_BOUNDARY | flMode);
1066
1067 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
1068 SetLastError(ERROR_OUTOFMEMORY_W);
1069 return 0;
1070 }
1071 SetLastError(ERROR_SUCCESS_W);
1072 return hrgn;
1073}
1074//******************************************************************************
1075//******************************************************************************
1076ODINFUNCTIONNODBG4(int, CombineRgn, HRGN, hrgnDest, HRGN, hrgnSrc1, HRGN, hrgnSrc2, int, combineMode)
1077{
1078 ULONG lComplexity;
1079 LONG mode;
1080#ifdef DEBUG
1081 HRGN hrgn1 = hrgnDest;
1082 HRGN hrgn2 = hrgnSrc1;
1083 HRGN hrgn3 = hrgnSrc2;
1084#endif
1085
1086 switch(combineMode) {
1087 case RGN_AND_W:
1088 mode = CRGN_AND;
1089 break;
1090 case RGN_COPY_W:
1091 mode = CRGN_COPY;
1092 break;
1093 case RGN_DIFF_W:
1094 mode = CRGN_DIFF;
1095 break;
1096 case RGN_OR_W:
1097 mode = CRGN_OR;
1098 break;
1099 case RGN_XOR_W:
1100 mode = CRGN_XOR;
1101 break;
1102 default:
1103 dprintf(("WARNING: CombineRgn %x %x %x %d; invalid mode!", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1104 SetLastError(ERROR_INVALID_PARAMETER_W);
1105 return ERROR_W;
1106 }
1107
1108 hrgnDest = ObjGetHandleData(hrgnDest, GDIOBJ_REGION);
1109 hrgnSrc1 = ObjGetHandleData(hrgnSrc1, GDIOBJ_REGION);
1110 hrgnSrc2 = ObjGetHandleData(hrgnSrc2, GDIOBJ_REGION);
1111 if(hrgnDest == HANDLE_OBJ_ERROR || hrgnSrc1 == HANDLE_OBJ_ERROR || (hrgnSrc2 == HANDLE_OBJ_ERROR && combineMode != RGN_COPY_W)) {
1112 dprintf(("WARNING: CombineRgn %x %x %x %d invalid region", hrgn1, hrgn2, hrgn3, combineMode));
1113 SetLastError(ERROR_INVALID_HANDLE_W);
1114 return ERROR_W;
1115 }
1116
1117 lComplexity = GpiCombineRegion(hpsRegion, hrgnDest, hrgnSrc1, hrgnSrc2, mode);
1118 if(lComplexity == RGN_ERROR) {
1119 dprintf(("WARNING: CombineRgn %x %x %x %d GpiCombineRegion failed (%x)", hrgn1, hrgn2, hrgn3, mode, WinGetLastError(0)));
1120 SetLastError(ERROR_INVALID_HANDLE_W);
1121 return ERROR_W;
1122 }
1123 dprintf(("CombineRgn %x %x %x %d", hrgn1, hrgn2, hrgn3, mode));
1124 SetLastError(ERROR_SUCCESS_W);
1125 return lComplexity;
1126}
1127//******************************************************************************
1128//******************************************************************************
1129ODINFUNCTIONNODBG2(BOOL, EqualRgn, HRGN, hrgn1, HRGN, hrgn2)
1130{
1131 LONG lEquality;
1132#ifdef DEBUG
1133 HRGN hrgnt1 = hrgn1;
1134 HRGN hrgnt2 = hrgn2;
1135#endif
1136
1137 hrgn1 = ObjGetHandleData(hrgn1, GDIOBJ_REGION);
1138 hrgn2 = ObjGetHandleData(hrgn2, GDIOBJ_REGION);
1139 if(hrgn1 == HANDLE_OBJ_ERROR || hrgn2 == HANDLE_OBJ_ERROR) {
1140 dprintf(("WARNING: EqualRgn %x %x invalid region", hrgnt1, hrgnt2));
1141 SetLastError(ERROR_INVALID_HANDLE_W);
1142 return FALSE;
1143 }
1144 lEquality = GpiEqualRegion(hpsRegion, hrgn1, hrgn2);
1145
1146 dprintf(("EqualRgn %x %x = %d", hrgnt1, hrgnt2, lEquality));
1147 SetLastError(ERROR_SUCCESS_W);
1148
1149 if(lEquality == EQRGN_EQUAL)
1150 return TRUE;
1151 else
1152 if(lEquality == EQRGN_NOTEQUAL)
1153 return FALSE;
1154 else {
1155 return FALSE;
1156 }
1157}
1158//******************************************************************************
1159//******************************************************************************
1160ODINFUNCTIONNODBG5(BOOL, SetRectRgn, HRGN, hrgn, int, left, int, top, int, right, int, bottom)
1161{
1162 BOOL result = FALSE;
1163#ifdef DEBUG
1164 HRGN hrgn1 = hrgn;
1165#endif
1166
1167 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1168 if(hrgn == HANDLE_OBJ_ERROR) {
1169 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) invalid region handle", hrgn1, left, top, right, bottom));
1170 SetLastError(ERROR_INVALID_HANDLE_W);
1171 return 0;
1172 }
1173 RECTL rectl = { left, top, right, bottom }; //reversed y coordinates
1174 if(GpiSetRegion(hpsRegion, hrgn, 1, &rectl)) {
1175 dprintf(("SetRectRgn %x (%d,%d)(%d,%d)", hrgn1, left, top, right, bottom));
1176 return TRUE;
1177 }
1178 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) GpiSetRegion failed %x", hrgn1, left, top, right, bottom, WinGetLastError(0)));
1179 return FALSE;
1180}
1181//******************************************************************************
1182//NOTE: depends on hps inversion
1183//******************************************************************************
1184ODINFUNCTIONNODBG3(ULONG, GetRegionData, HRGN, hrgn, ULONG, count, PRGNDATA, pData)
1185{
1186#ifdef DEBUG
1187 HRGN hrgn1 = hrgn;
1188#endif
1189
1190 if(!count && pData)
1191 {
1192 dprintf(("WARNING: GetRegionData %x %d %x; invalid parameter", hrgn1, count, pData));
1193 SetLastError(ERROR_INVALID_PARAMETER_W);
1194 return 0;
1195 }
1196 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1197 if(hrgn == HANDLE_OBJ_ERROR) {
1198 dprintf(("WARNING: GetRegionData %x %d %x; invalid region handle", hrgn1, count, pData));
1199 SetLastError(ERROR_INVALID_HANDLE_W);
1200 return 0;
1201 }
1202 RGNRECT rgnRect;
1203 rgnRect.ircStart = 1;
1204 rgnRect.crc = 0;
1205 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
1206 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1207 {
1208 dprintf(("WARNING: GetRegionData %x %d %x: GpiQueryRegionRects failed! (%x)", hrgn1, count, pData, WinGetLastError(0)));
1209 return 0;
1210 }
1211
1212 dprintf(("GetRegionData %x %d %x", hrgn1, count, pData));
1213
1214 ULONG bufSizeNeeded = rgnRect.crcReturned * sizeof(RECT) + sizeof (RGNDATAHEADER);
1215
1216 if(pData && (count >= (sizeof(RGNDATAHEADER) + rgnRect.crcReturned * sizeof(RECT))))
1217 {
1218 //we actually need to flip the top & bottom values, but as the layout of the PM RECTL and
1219 //Win32 RECT have exactly those two members reversed, we don't do this for the returned
1220 //rectangles (more efficient)
1221 PRECTL pRectl = (PRECTL)pData->Buffer;
1222 rgnRect.crc = rgnRect.crcReturned;
1223 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, pRectl))
1224 {
1225 dprintf(("WARNING: GetRegionData: GpiQueryRegionRects failed! (%x)", WinGetLastError(0)));
1226 return 0;
1227 }
1228
1229 RECTL boundRect;
1230 GpiQueryRegionBox(hpsRegion, hrgn, &boundRect); // no need to check rc
1231
1232 pData->rdh.dwSize = sizeof(pData->rdh);
1233 pData->rdh.iType = RDH_RECTANGLES_W; // one and only possible value
1234 pData->rdh.nCount = rgnRect.crcReturned;
1235 pData->rdh.nRgnSize = rgnRect.crcReturned * sizeof(RECT);
1236
1237 //flip top & bottom for bounding rectangle (not really necessary; but cleaner coding)
1238 LONG temp = boundRect.yTop;
1239 boundRect.yTop = boundRect.yBottom;
1240 boundRect.yBottom = temp;
1241 MapOS2ToWin32Rect(boundRect, pData->rdh.rcBound);
1242 }
1243
1244 //return size needed
1245 return bufSizeNeeded;
1246}
1247//******************************************************************************
1248//******************************************************************************
1249ODINFUNCTIONNODBG2(int, GetRgnBox, HRGN, hrgn, PRECT, pRect)
1250{
1251 BOOL success;
1252 LONG lComplexity;
1253#ifdef DEBUG
1254 HRGN hrgn1 = hrgn;
1255#endif
1256
1257 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1258 if(hrgn == HANDLE_OBJ_ERROR) {
1259 dprintf(("WARNING: GetRgnBox %x %x invalid region!", hrgn1, pRect));
1260 SetLastError(ERROR_INVALID_HANDLE_W);
1261 return FALSE;
1262 }
1263
1264 RECTL rectl;
1265 lComplexity = GpiQueryRegionBox(hpsRegion, hrgn, &rectl);
1266 if(lComplexity != RGN_ERROR)
1267 {
1268 //no conversion required, just flip top & bottom
1269 ULONG temp = rectl.yBottom;
1270 rectl.yBottom = rectl.yTop;
1271 rectl.yTop = temp;
1272
1273 MapOS2ToWin32Rect(rectl, *pRect);
1274 }
1275 else {
1276 lComplexity = ERROR_W;
1277 dprintf(("WARNING: GetRgnBox error in region!"));
1278 }
1279 dprintf(("GetRgnBox %x (%d,%d)(%d,%d)", hrgn1, pRect->left, pRect->bottom, pRect->right, pRect->top));
1280
1281 SetLastError(ERROR_SUCCESS_W);
1282 return lComplexity;
1283}
1284//******************************************************************************
1285//******************************************************************************
1286ODINFUNCTIONNODBG2(BOOL, InvertRgn, HDC, hdc, HRGN, hrgn)
1287{
1288#ifdef DEBUG
1289 HRGN hrgn1 = hrgn;
1290#endif
1291 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1292
1293 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1294 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1295 dprintf(("WARNING: InvertRgn %x %x invalid handle!", hdc, hrgn));
1296 SetLastError(ERROR_INVALID_HANDLE_W);
1297 return FALSE;
1298 }
1299 //todo metafile recording
1300
1301 dprintf(("InvertRgn %x %x", hdc, hrgn1));
1302
1303 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1304
1305 LONG lHits = GPI_ERROR;
1306 HRGN hrgnOld;
1307 LONG lComplexity ;
1308 RECTL boundingRect; // this gets a rectangle in world cordinates!
1309
1310 lComplexity = GpiQueryRegionBox(pHps->hps, pHps->hrgnHDC, &boundingRect);
1311 if(lComplexity != RGN_ERROR)
1312 {
1313 lComplexity = GpiSetClipRegion(pHps->hps, pHps->hrgnHDC, &hrgnOld);
1314 if(lComplexity != RGN_ERROR)
1315 {
1316 RECTL rectls[2];
1317 rectls[0] = boundingRect;
1318 rectls[1] = boundingRect;
1319 lHits = GpiBitBlt(pHps->hps, NULL, 3, (PPOINTL)rectls,
1320 ROP_DSTINVERT, 0);
1321
1322 /* Restore the old region */
1323 GpiSetClipRegion(pHps->hps, hrgnOld, &hrgnOld);
1324 }
1325 }
1326
1327 if(lHits == GPI_ERROR || lComplexity == RGN_ERROR)
1328 {
1329 dprintf(("WARNING: InvertRgn error during Gpi operation (%x) (%d,%d)", WinGetLastError(0), lHits, lComplexity));
1330 return FALSE;
1331 }
1332
1333 return TRUE;
1334}
1335//******************************************************************************
1336//******************************************************************************
1337ODINFUNCTIONNODBG3(int, OffsetRgn, HRGN, hrgn, int, xOffset, int, yOffset)
1338{
1339 LONG lComplexity;
1340#ifdef DEBUG
1341 HRGN hrgn1 = hrgn;
1342#endif
1343
1344 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1345 if(hrgn == HANDLE_OBJ_ERROR) {
1346 dprintf(("WARNING: OffsetRgn %x %d %d invalid handle!", hrgn, xOffset, yOffset));
1347 SetLastError(ERROR_INVALID_HANDLE_W);
1348 return ERROR_W;
1349 }
1350 dprintf(("OffsetRgn %x %d %d", hrgn1, xOffset, yOffset));
1351
1352 POINTL ptlOffset = {xOffset, yOffset};
1353 GpiOffsetRegion(hpsRegion, hrgn, &ptlOffset);
1354
1355 RECTL rectl[8];
1356 RGNRECT rgnRect;
1357 rgnRect.ircStart = 1;
1358 rgnRect.crc = 8;
1359 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference
1360 if(GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, &rectl[0]))
1361 {
1362 switch (rgnRect.crcReturned) {
1363 case 0:
1364 lComplexity = NULLREGION_W;
1365 break;
1366 case 1:
1367 lComplexity = SIMPLEREGION_W;
1368 break;
1369 default:
1370 lComplexity = COMPLEXREGION_W;
1371 break;
1372 }
1373 }
1374 else {
1375 lComplexity = ERROR_W;
1376 dprintf(("WARNING: OffsetRgn error in region! (%x)", WinGetLastError(0)));
1377 }
1378
1379 SetLastError(ERROR_SUCCESS_W);
1380
1381 return lComplexity;
1382}
1383//******************************************************************************
1384//******************************************************************************
1385ODINFUNCTIONNODBG5(BOOL, FrameRgn, HDC, hdc, HRGN, hrgn, HBRUSH, hBrush, int, width, int, height)
1386{
1387 HBRUSH hbrushRestore = 0;
1388#ifdef DEBUG
1389 HRGN hrgn1 = hrgn;
1390#endif
1391 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1392
1393 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1394 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1395 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid handle!", hdc, hrgn, hBrush, width, height));
1396 SetLastError(ERROR_INVALID_HANDLE_W);
1397 return FALSE;
1398 }
1399
1400 width = abs(width);
1401 height = abs(height);
1402
1403 if(pHps->lastBrushKey != (UINT)hBrush)
1404 {
1405 hbrushRestore = SelectObject(hdc, hBrush);
1406 if(!hbrushRestore)
1407 {
1408 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid brush!", hdc, hrgn, hBrush, width, height));
1409 SetLastError(ERROR_INVALID_HANDLE_W);
1410 return FALSE;
1411 }
1412 }
1413 dprintf(("FrameRgn %x %x %x (%d,%d)", hdc, hrgn1, hBrush, width, height));
1414 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1415
1416 SIZEL thickness = { width, height };
1417 LONG lHits = GpiFrameRegion(pHps->hps, pHps->hrgnHDC, &thickness);
1418
1419 SetLastError(ERROR_SUCCESS_W);
1420
1421 // Restore the brush if necessary
1422 if(hbrushRestore)
1423 SelectObject(hdc, hbrushRestore);
1424
1425 //todo metafile recording
1426 return (lHits != GPI_ERROR);
1427}
1428//******************************************************************************
1429//******************************************************************************
1430ODINFUNCTIONNODBG3(BOOL, FillRgn, HDC, hdc, HRGN, hrgn, HBRUSH, hBrush)
1431{
1432 BOOL success;
1433 HBRUSH hbrushRestore = 0;
1434#ifdef DEBUG
1435 HRGN hrgn1 = hrgn;
1436#endif
1437
1438 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1439
1440 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1441 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1442 dprintf(("WARNING: FillRgn %x %x %x invalid handle!", hdc, hrgn1, hBrush));
1443 SetLastError(ERROR_INVALID_HANDLE_W);
1444 return FALSE;
1445 }
1446
1447 if(pHps->lastBrushKey != (UINT)hBrush)
1448 {
1449 hbrushRestore = SelectObject(hdc, hBrush);
1450 if (!hbrushRestore)
1451 {
1452 dprintf(("WARNING: FillRgn %x %x %x invalid brush!", hdc, hrgn1, hBrush));
1453 SetLastError(ERROR_INVALID_HANDLE_W);
1454 return FALSE;
1455 }
1456 }
1457 dprintf(("FillRgn %x %x %x", hdc, hrgn1, hBrush));
1458
1459 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1460
1461 success = GpiPaintRegion(pHps->hps, pHps->hrgnHDC);
1462
1463 //todo metafile recording
1464
1465 /* Restore the brush if necessary */
1466 if(hbrushRestore)
1467 SelectObject(hdc, hbrushRestore);
1468
1469 return(success);
1470}
1471//******************************************************************************
1472//******************************************************************************
1473ODINFUNCTIONNODBG2(BOOL, PaintRgn, HDC, hdc, HRGN, hrgn)
1474{
1475 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1476 if(!pHps)
1477 {
1478 SetLastError(ERROR_INVALID_HANDLE_W);
1479 return FALSE;
1480 }
1481
1482 return FillRgn(hdc, hrgn, (HBRUSH) pHps->lastBrushKey);
1483}
1484//******************************************************************************
1485//******************************************************************************
1486ODINFUNCTIONNODBG3(BOOL, PtInRegion, HRGN, hrgn, int, x, int, y)
1487{
1488 BOOL success;
1489 LONG lInside;
1490#ifdef DEBUG
1491 HRGN hrgn1 = hrgn;
1492#endif
1493
1494 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1495 if(hrgn == HANDLE_OBJ_ERROR) {
1496 dprintf(("WARNING: PtInRgn %x (%d,%d) invalid region!", hrgn1, x, y));
1497 SetLastError(ERROR_INVALID_HANDLE_W);
1498 return FALSE;
1499 }
1500
1501 POINTL pointl = {x,y};
1502 lInside = GpiPtInRegion(hpsRegion, hrgn, &pointl);
1503 if(lInside == PRGN_ERROR) {
1504 success = FALSE;
1505 }
1506 else success = TRUE;
1507
1508 SetLastError(ERROR_SUCCESS_W);
1509
1510 dprintf(("PtInRgn %x (%d,%d) returned %d", hrgn1, x, y, (success && lInside == PRGN_INSIDE) ? 1 : 0));
1511
1512 if(success && lInside == PRGN_INSIDE)
1513 return TRUE;
1514 else
1515 return FALSE;
1516}
1517//******************************************************************************
1518//******************************************************************************
1519ODINFUNCTIONNODBG2(BOOL, RectInRegion, HRGN, hrgn, const RECT *, pRect)
1520{
1521 BOOL success;
1522 LONG lInside;
1523#ifdef DEBUG
1524 HRGN hrgn1 = hrgn;
1525#endif
1526
1527 if(!pRect) {
1528 dprintf(("WARNING: RectInRgn %x %x invalid parameter!", hrgn1, pRect));
1529 SetLastError(ERROR_INVALID_PARAMETER_W);
1530 return FALSE;
1531 }
1532 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1533 if(hrgn == HANDLE_OBJ_ERROR) {
1534 dprintf(("WARNING: RectInRgn %x %x invalid region", hrgn1, pRect));
1535 SetLastError(ERROR_INVALID_HANDLE_W);
1536 return FALSE;
1537 }
1538
1539 RECTL rectl;
1540 MapWin32ToOS2Rect(*pRect, rectl);
1541 //switch bottom & top
1542 UINT temp = rectl.yBottom;
1543 rectl.yBottom = rectl.yTop;
1544 rectl.yTop = temp;
1545
1546 lInside = GpiRectInRegion(hpsRegion, hrgn, &rectl);
1547 if(lInside == RRGN_ERROR) {
1548 success = FALSE;
1549 }
1550 else success = TRUE;
1551
1552 SetLastError(ERROR_SUCCESS_W);
1553
1554 dprintf(("RectInRgn %x %x returned %d", hrgn1, pRect, (success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL)) ? 1 : 0));
1555
1556 if(success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL))
1557 return TRUE;
1558 else
1559 return FALSE;
1560}
1561//******************************************************************************
1562//Returned region in device coordinates (undocumented behaviour)
1563//******************************************************************************
1564ODINFUNCTIONNODBG1(HRGN, PathToRegion, HDC, hdc)
1565{
1566 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1567 if(!pHps)
1568 {
1569 dprintf(("WARNING: PathToRegion %x; invalid hdc!", hdc));
1570 SetLastError(ERROR_INVALID_HANDLE_W);
1571 return NULLHANDLE;
1572 }
1573
1574 HRGN hrgn, hrgnTemp, hrgnwin;
1575
1576 dprintf(("GDI32: PathToRegion %x", hdc));
1577
1578 hrgnTemp = GpiPathToRegion(pHps->hps, 1, (pHps->polyFillMode == ALTERNATE_W) ? FPATH_ALTERNATE : FPATH_WINDING);
1579 if(hrgnTemp == NULLHANDLE)
1580 goto error;
1581
1582 hrgnwin = CreateRectRgn(1, 1, 2, 2);
1583 hrgn = ObjGetHandleData(hrgnwin, GDIOBJ_REGION);
1584 if(hrgn == HANDLE_OBJ_ERROR) {
1585 dprintf(("WARNING: PathToRegion invalid region", hrgnwin));
1586 SetLastError(ERROR_INVALID_HANDLE_W);
1587 return NULLHANDLE;
1588 }
1589
1590 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnTemp, pHps, NULL))
1591 goto error;
1592
1593 GpiDestroyRegion(pHps->hps, hrgnTemp);
1594
1595 return hrgnwin;
1596
1597error:
1598 if(hrgnwin)
1599 DeleteObject(hrgnwin);
1600
1601 SetLastError(ERROR_INVALID_HANDLE_W); //todo right error
1602 return NULLHANDLE;
1603}
1604//******************************************************************************
1605//Needs wrapper as this file includes os2.h!!
1606//******************************************************************************
1607ODINFUNCTIONNODBG1(BOOL, OSLibDeleteRegion, HANDLE, hRegion)
1608{
1609 if(GpiDestroyRegion(hpsRegion, hRegion) == FALSE) {
1610 dprintf(("WARNING: OSLibDeleteRegion %x; GpiDestroyRegion failed (%x)", hRegion, WinGetLastError(0)));
1611 }
1612 return (0);
1613}
1614/*****************************************************************************
1615 * Name : int GetMetaRgn
1616 * Purpose : The GetMetaRgn function retrieves the current metaregion for
1617 * the specified device context.
1618 * Parameters: HDC hdc handle of device context
1619 * HRGN hrgn handle of region
1620 * Variables :
1621 * Result : 0 / 1
1622 * Remark :
1623 * Status : UNTESTED STUB
1624 *
1625 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1626 *****************************************************************************/
1627
1628ODINFUNCTIONNODBG2(int, GetMetaRgn, HDC, hdc, HRGN, hrgn)
1629{
1630 dprintf(("GDI32: GetMetaRgn(%08xh, %08xh) not implemented.\n",
1631 hdc,
1632 hrgn));
1633
1634 SetLastError(ERROR_SUCCESS_W);
1635 return (0);
1636}
1637/*****************************************************************************
1638 * Name : int SetMetaRgn
1639 * Purpose : The SetMetaRgn function intersects the current clipping region
1640 * for the specified device context with the current metaregion
1641 * and saves the combined region as the new metaregion for the
1642 * specified device context. The clipping region is reset to a null region.
1643 * Parameters: HDC hdc handle of device context
1644 * Variables :
1645 * Result : TRUE / FALSE
1646 * Remark :
1647 * Status : UNTESTED STUB
1648 *
1649 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1650 *****************************************************************************/
1651
1652ODINFUNCTIONNODBG1(BOOL, SetMetaRgn, HDC, hdc)
1653{
1654 dprintf(("GDI32: SetMetaRgn(%08xh) not implemented.\n",
1655 hdc));
1656
1657 SetLastError(ERROR_SUCCESS_W);
1658 return (NULLREGION_W);
1659}
1660//******************************************************************************
1661//******************************************************************************
Note: See TracBrowser for help on using the repository browser.