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

Last change on this file since 6502 was 5760, checked in by sandervl, 24 years ago

LPtoDP/DPtoLP: check input because GpiConvert doesn't like illegal values

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