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

Last change on this file since 3721 was 3715, checked in by sandervl, 25 years ago

put back region code

File size: 49.7 KB
Line 
1/* $Id: region.cpp,v 1.9 2000-06-16 11:05:22 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>
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 <objhandle.h>
27#include <dcdata.h>
28#include <winuser32.h>
29#include <win32wnd.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//******************************************************************************
68static LONG clientHeight(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//******************************************************************************
113static LONG clientWidth(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 = clientHeight(hwnd, pHps);
178 wWidth = clientWidth(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//******************************************************************************
297BOOL setWinDeviceRegionFromPMDeviceRegion(HRGN winHrgn, HRGN pmHrgn, pDCData pHpsPmHrgn, HWND hwndPmHrgn)
298{
299 BOOL success;
300 int x;
301 BOOL mustReleaseScreenPS = FALSE;
302 HPS hps;
303
304 if(pHpsPmHrgn || hwndPmHrgn)
305 {
306 if(pHpsPmHrgn)
307 hps = pHpsPmHrgn->hps;
308 else
309 {
310 hps = WinGetScreenPS(HWND_DESKTOP);
311 mustReleaseScreenPS = TRUE;
312 }
313
314 RGNRECT rgnRect;
315 rgnRect.ircStart = 1;
316 rgnRect.crc = 0;
317 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
318 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, NULL);
319 if(success )
320 {
321 if(rgnRect.crcReturned > 0)
322 {
323 rgnRect.crc = rgnRect.crcReturned;
324 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
325 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, pRectl);
326 if(success)
327 {
328 if(pHpsPmHrgn)
329 convertPMDeviceRectToWinDeviceRect(pHpsPmHrgn, pRectl, rgnRect.crcReturned);
330 else
331 convertPMDeviceRectToWinDeviceRect(hwndPmHrgn, pRectl, rgnRect.crcReturned);
332
333 for(x=0; x < rgnRect.crcReturned; x++)
334 {
335 ULONG temp = pRectl[x].yBottom;
336 pRectl[x].yBottom = pRectl[x].yTop;
337 pRectl[x].yTop = temp;
338 }
339
340 success = GpiSetRegion(hpsRegion, winHrgn, rgnRect.crcReturned, pRectl);
341 }
342 delete[] pRectl;
343 }
344 else
345 {
346 success = GpiSetRegion(hpsRegion, winHrgn, 0, NULL);
347 }
348 }
349 }
350 else
351 success = FALSE;
352
353 if(mustReleaseScreenPS)
354 WinReleasePS(hps);
355
356 return success;
357}
358//******************************************************************************
359//******************************************************************************
360int WIN32API SelectClipRgn(HDC hdc, HRGN hrgn)
361{
362 LONG lComplexity = RGN_NULL;
363 HRGN hrgnNewClip;
364 HRGN hrgnOldClip;
365
366 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
367 if(!pHps)
368 {
369 dprintf(("WARNING: SelectClipRgn: invalid hdc!", hdc, hrgn));
370 SetLastError(ERROR_INVALID_HANDLE_W);
371 return ERROR_W;
372 }
373
374 if(hrgn)
375 {
376 hrgn = ObjGetHandleData(hrgn);
377 if(hrgn == HANDLE_OBJ_ERROR) {
378 dprintf(("WARNING: SelectClipRgn: invalid region!", hdc, hrgn));
379 SetLastError(ERROR_INVALID_HANDLE_W);
380 return ERROR_W;
381 }
382 }
383
384 if(hrgn)
385 {
386 RECTL rectl = {0,0,1,1};
387 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
388 if(interpretRegionAs(pHps, hrgnNewClip, hrgn, AS_DEVICE) == 0)
389 {
390 lComplexity = RGN_ERROR;
391 }
392 }
393 else
394 hrgnNewClip = 0;
395
396 if(lComplexity != RGN_ERROR)
397 {
398 if(hrgnNewClip == 0) {
399 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
400 }
401 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
402 if (lComplexity != RGN_ERROR )
403 {
404 dprintf(("SelectClipRgn: %x %x", hdc, hrgn));
405 if(hrgnOldClip)
406 GpiDestroyRegion(pHps->hps, hrgnOldClip);
407
408 //todo: metafile recording
409 SetLastError(ERROR_SUCCESS_W);
410 return lComplexity;
411 }
412 }
413
414 dprintf(("WARNING: SelectClipRgn: RGN_ERROR!", hdc, hrgn));
415 if(hrgnNewClip)
416 GpiDestroyRegion(pHps->hps, hrgnNewClip);
417
418 SetLastError(ERROR_SUCCESS_W);
419 return lComplexity;
420}
421//******************************************************************************
422//******************************************************************************
423int WIN32API ExtSelectClipRgn(HDC hdc, HRGN hrgn, int mode)
424{
425 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
426 if (!pHps)
427 {
428 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid hdc", hdc, hrgn, mode));
429 SetLastError(ERROR_INVALID_HANDLE_W);
430 return ERROR_W;
431 }
432
433 LONG lComplexity;
434 HRGN hrgnCurrent = NULLHANDLE;
435
436 if(!hrgn && mode != RGN_COPY_W)
437 {
438 SetLastError(ERROR_INVALID_PARAMETER_W);
439 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn, mode));
440 return ERROR_W;
441 }
442
443 LONG lMode;
444 switch (mode)
445 {
446 case RGN_AND_W : lMode = CRGN_AND ; break;
447 case RGN_COPY_W : lMode = CRGN_COPY; break;
448 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
449 case RGN_OR_W : lMode = CRGN_OR ; break;
450 case RGN_XOR_W : lMode = CRGN_XOR ; break;
451 default:
452 {
453 SetLastError(ERROR_INVALID_PARAMETER_W);
454 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn, mode));
455 return ERROR_W;
456 }
457 }
458
459 if(hrgn)
460 {
461 hrgn = ObjGetHandleData(hrgn);
462 if(hrgn == HANDLE_OBJ_ERROR) {
463 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid region handle", hdc, hrgn, mode));
464 SetLastError(ERROR_INVALID_HANDLE_W);
465 return 0;
466 }
467 }
468
469 dprintf(("WARNING: ExtSelectRgn %x %x %d", hdc, hrgn, mode));
470 //TODO: metafile recording
471 if(hrgn)
472 {
473 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
474 {
475 return ERROR_W;
476 }
477 }
478 else
479 {
480 //remove clip region
481 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
482 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
483
484 if(hrgnCurrent)
485 GpiDestroyRegion(pHps->hps, hrgnCurrent);
486
487 return NULLREGION_W;
488 }
489
490 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
491
492 if(hrgnCurrent == NULLHANDLE)
493 {
494 lMode = CRGN_COPY;
495 RECTL rectl = {0, 0, 1, 1};
496 hrgnCurrent = GpiCreateRegion(pHps->hps, 1, &rectl);
497 }
498
499 HRGN hrgnSrc1;
500 HRGN hrgnSrc2;
501 if(lMode != CRGN_COPY)
502 {
503 hrgnSrc1 = hrgnCurrent;
504 hrgnSrc2 = pHps->hrgnHDC;
505 }
506 else
507 {
508 hrgnSrc1 = pHps->hrgnHDC;
509 hrgnSrc2 = NULLHANDLE;
510 }
511
512 lComplexity = GpiCombineRegion(pHps->hps, hrgnCurrent, hrgnSrc1, hrgnSrc2, lMode);
513 if (lComplexity != RGN_ERROR)
514 {
515 HRGN hrgnOld;
516 lComplexity = GpiSetClipRegion(pHps->hps, hrgnCurrent, &hrgnOld);
517 SetLastError(ERROR_SUCCESS_W);
518 if (lComplexity != RGN_ERROR)
519 return lComplexity;
520 }
521 SetLastError(ERROR_SUCCESS_W);
522 return ERROR_W;
523}
524//******************************************************************************
525//******************************************************************************
526int WIN32API GetClipBox(HDC hdc, PRECT lpRect)
527{
528 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
529 RECTL rectl;
530 LONG lComplexity;
531 int rc;
532
533 if(!hdc || !lpRect || !pHps) {
534 dprintf(("GDI32: GetClipBox %x %x ERROR_INVALID_PARAMETER", hdc, lpRect));
535 SetLastError(ERROR_INVALID_PARAMETER_W);
536 return ERROR_W;
537 }
538 if(pHps->isPrinter)
539 {
540 lpRect->left = 0;
541 lpRect->top = 0;
542 lpRect->right = GetDeviceCaps( hdc, HORZRES_W);
543 lpRect->bottom = GetDeviceCaps( hdc, VERTRES_W);
544 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
545 convertPMDeviceRectToWinWorldRect(pHps, &rectl);
546
547 rc = SIMPLEREGION_W;
548 }
549 else {
550 lComplexity = GpiQueryClipBox(pHps->hps, &rectl);
551 if(lComplexity == RGN_ERROR)
552 {
553 rc = ERROR_W;
554 }
555 else
556 if(lComplexity == RGN_NULL)
557 {
558 memset(lpRect, 0, sizeof(*lpRect));
559 rc = NULLREGION_W;
560 }
561 else {
562 //Convert including/including to including/excluding
563 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
564
565 lpRect->left = rectl.xLeft;
566 lpRect->right = rectl.xRight;
567 //No conversion required as GpiQueryClipBox is affected by
568 //the y-inversion of the window
569 //NOTE: YINVERSION dependancy
570 if(rectl.yBottom > rectl.yTop) {
571 lpRect->top = rectl.yTop;
572 lpRect->bottom = rectl.yBottom;
573 }
574 else {
575 lpRect->top = rectl.yBottom;
576 lpRect->bottom = rectl.yTop;
577 }
578
579 rc = (lComplexity == RGN_RECT) ? SIMPLEREGION_W : COMPLEXREGION_W;
580 }
581 }
582 dprintf(("GDI32: GetClipBox of %X returned %d; (%d,%d)(%d,%d)", hdc, rc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
583 return rc;
584}
585//******************************************************************************
586//******************************************************************************
587int WIN32API GetClipRgn(HDC hdc, HRGN hrgn)
588{
589 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
590 BOOL success;
591 LONG lComplexity = RGN_RECT;
592 HRGN hrgnClip = NULL, hrgnTemp;
593
594 hrgn = ObjGetHandleData(hrgn);
595 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
596 dprintf(("WARNING: GetClipRgn %x %x invalid handle", hdc, hrgn));
597 SetLastError(ERROR_INVALID_HANDLE_W);
598 return 0;
599 }
600
601 if(GpiSetClipRegion(pHps->hps, NULL, &hrgnClip) == RGN_ERROR) {
602 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed! (%x)", WinGetLastError(0)));
603 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
604 return 0;
605 }
606 if(hrgnClip) {
607 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnClip, pHps, NULL)) {
608 dprintf(("WARNING: GetClipRgn setWinDeviceRegionFromPMDeviceRegion failed!"));
609 GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp);
610 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
611 return 0;
612 }
613 if(GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp) == RGN_ERROR )
614 {
615 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed %x!", WinGetLastError(0)));
616 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
617 return 0;
618 }
619 }
620 else lComplexity = RGN_NULL;
621
622 dprintf(("GetClipRgn %x %x returned %d", hdc, hrgn, lComplexity == RGN_NULL));
623 SetLastError(ERROR_SUCCESS_W);
624 if(lComplexity == RGN_NULL)
625 return 0;
626 else return 1;
627}
628//******************************************************************************
629//******************************************************************************
630int WIN32API ExcludeClipRect(HDC hdc, int left, int top, int right, int bottom)
631{
632 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
633 if(!pHps)
634 {
635 dprintf(("WARNING: ExcludeClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
636 SetLastError(ERROR_INVALID_HANDLE_W);
637 return ERROR_W;
638 }
639
640 LONG lComplexity;
641 RECTL rectl = { left, bottom, right, top };
642
643 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
644 if(rectl.yTop < rectl.yBottom) {
645 ULONG temp = rectl.yBottom;
646 rectl.yBottom = rectl.yTop;
647 rectl.yTop = temp;
648 }
649
650 dprintf(("ExcludeClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
651 lComplexity = GpiExcludeClipRectangle(pHps->hps, &rectl);
652 if (lComplexity == RGN_ERROR) {
653 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
654 return ERROR_W;
655 }
656
657 //todo metafile recording
658
659 SetLastError(ERROR_SUCCESS_W);
660 return lComplexity;
661}
662//******************************************************************************
663//******************************************************************************
664int WIN32API IntersectClipRect(HDC hdc, int left, int top, int right, int bottom)
665{
666 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
667 LONG lComplexity;
668 BOOL success;
669
670 if(!pHps) {
671 dprintf(("WARNING: IntersectClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
672 SetLastError(ERROR_INVALID_HANDLE_W);
673 return ERROR_W;
674 }
675 RECTL rectl = { left, bottom, right, top };
676
677 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
678 if(rectl.yTop < rectl.yBottom) {
679 ULONG temp = rectl.yBottom;
680 rectl.yBottom = rectl.yTop;
681 rectl.yTop = temp;
682 }
683
684 dprintf(("IntersectClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
685 lComplexity = GpiIntersectClipRectangle(pHps->hps, &rectl);
686
687 //todo metafile recording
688
689 SetLastError(ERROR_SUCCESS_W);
690 return lComplexity;
691}
692//******************************************************************************
693//******************************************************************************
694int WIN32API OffsetClipRgn(HDC hdc, int nXOffset, int nYOffset )
695{
696 BOOL success;
697 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
698 LONG lComplexity;
699
700 if(!pHps) {
701 dprintf(("OffsetClipRgn %x (%d,%d) invalid hdc", hdc, nXOffset, nYOffset));
702 SetLastError(ERROR_INVALID_HANDLE_W);
703 return ERROR_W;
704 }
705
706 dprintf(("OffsetClipRgn %x (%d,%d)", hdc, nXOffset, nYOffset));
707 POINTL pointl = { nXOffset, nYOffset };
708 lComplexity = GpiOffsetClipRegion(pHps->hps, &pointl);
709
710 //todo metafile recording
711
712 SetLastError(ERROR_SUCCESS_W);
713 return lComplexity;
714}
715//******************************************************************************
716//******************************************************************************
717HRGN WIN32API CreatePolyPolygonRgn(const POINT * lppt, const int *pPolyCount, int nCount, int fnPolyFillMode)
718{
719 LONG flMode;
720
721 switch(fnPolyFillMode)
722 {
723 case ALTERNATE_W:
724 flMode = POLYGON_ALTERNATE;
725 break;
726 case WINDING_W:
727 flMode = POLYGON_WINDING;
728 break;
729 default:
730 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
731 SetLastError(ERROR_INVALID_PARAMETER_W);
732 return 0;
733 }
734
735 if(nCount < 1)
736 {
737 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
738 SetLastError(ERROR_INVALID_PARAMETER_W);
739 return 0;
740 }
741
742 PPOLYGON pPolygon = new POLYGON[nCount];
743 if(!pPolygon) {
744 dprintf(("ERROR: CreatePolyPolygonRgn: out of memory!!"));
745 SetLastError(ERROR_OUTOFMEMORY_W);
746 return 0;
747 }
748 dprintf(("CreatePolyPolygonRgn %x %x %d %d", lppt, pPolyCount, nCount, fnPolyFillMode));
749
750 PPOINTL pPointl = (PPOINTL)lppt+1; // skip first point
751 for (int x=0; x < nCount; x++) {
752 pPolygon[x].ulPoints = (x == 0) ? pPolyCount[x] - 1 : pPolyCount[x];
753 pPolygon[x].aPointl = pPointl;
754 pPointl += pPolygon[x].ulPoints;
755 }
756 GpiMove(hpsRegion, (PPOINTL)lppt);
757 HRGN hrgn = GpiCreatePolygonRegion(hpsRegion, nCount, pPolygon, POLYGON_BOUNDARY | flMode);
758
759 delete[] pPolygon;
760
761 if(!hrgn) {
762 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
763 return 0;
764 }
765
766 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
767 SetLastError(ERROR_OUTOFMEMORY_W);
768 return 0;
769 }
770 SetLastError(ERROR_SUCCESS_W);
771 return hrgn;
772}
773//******************************************************************************
774//******************************************************************************
775HRGN WIN32API CreateRectRgn( int left, int top, int right, int bottom)
776{
777 HRGN hrgn;
778 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
779
780 hrgn = GpiCreateRegion(hpsRegion, 1, &rectl);
781 if(!hrgn) {
782 dprintf(("WARNING: CreateRectRgn: GpiCreateRectRegion failed! %x", WinGetLastError(0)));
783 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
784 return 0;
785 }
786
787 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
788 SetLastError(ERROR_OUTOFMEMORY_W);
789 return 0;
790 }
791 dprintf(("CreateRectRegion (%d,%d)(%d,%d) returned %x", left, top, right, bottom, hrgn));
792 SetLastError(ERROR_SUCCESS_W);
793 return hrgn;
794}
795//******************************************************************************
796//******************************************************************************
797HRGN WIN32API CreateRectRgnIndirect(const RECT *lprc)
798{
799 return CreateRectRgn(lprc->left, lprc->top, lprc->right, lprc->bottom);
800}
801//******************************************************************************
802//******************************************************************************
803HRGN WIN32API CreateRoundRectRgn(int left, int top, int right, int bottom, int nWidthEllipse, int nHeightEllipse)
804{
805 HRGN hrgn;
806 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
807
808 PPOINTL pPointl = (PPOINTL)&rectl;
809
810 GpiMove(hpsRegion, &pPointl[0]);
811 hrgn = GpiCreateRoundRectRegion(hpsRegion, &pPointl[1], labs(nWidthEllipse), labs(nHeightEllipse));
812
813 if(!hrgn) {
814 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
815 dprintf(("WARNING: CreateRoundRectRgn: GpiCreateRoundRectRegion failed! %x", WinGetLastError(0)));
816 return 0;
817 }
818
819 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
820 SetLastError(ERROR_OUTOFMEMORY_W);
821 return 0;
822 }
823 dprintf(("CreateRoundRectRegion (%d,%d)(%d,%d) (%d,%d) returned %x", left, top, right, bottom, nWidthEllipse, nHeightEllipse, hrgn));
824 SetLastError(ERROR_SUCCESS_W);
825 return hrgn;
826}
827//******************************************************************************
828//******************************************************************************
829HRGN WIN32API ExtCreateRegion(const XFORM_W *pXform, DWORD count, const RGNDATA *pData)
830{
831 HRGN hrgn;
832
833 if(!pData || count < (sizeof(RGNDATAHEADER) + pData->rdh.nCount * sizeof(RECT))) {
834 dprintf(("WARNING: ExtCreateRegion %x %d %x; invalid parameter", pXform, count, pData));
835 SetLastError(ERROR_INVALID_PARAMETER_W);
836 return 0;
837 }
838
839 PRECTL pRectl = new RECTL[pData->rdh.nCount];
840 PRECT pDataRects = (PRECT)pData->Buffer;
841 for(int i=0; i < pData->rdh.nCount; i++) {
842 MapWin32ToOS2Rect(pDataRects[i], pRectl[i]);
843 }
844
845 BOOL doShear = pXform && (pXform->eM12 || pXform->eM21);
846 HPS hpsTemp = NULLHANDLE;
847
848 dprintf(("ExtCreateRegion %x %d %x", pXform, count, pData));
849 if(doShear) {
850 hpsTemp = WinGetPS(HWND_DESKTOP);
851 GpiBeginPath(hpsTemp, 1);
852
853 MATRIXLF matrixlf;
854 matrixlf.fxM11 = pXform->eM11 * (float)0x10000;
855 matrixlf.fxM12 = pXform->eM12 * (float)0x10000;
856 matrixlf.lM13 = 0;
857 matrixlf.fxM21 = pXform->eM21 * (float)0x10000;
858 matrixlf.fxM22 = pXform->eM22 * (float)0x10000;
859 matrixlf.lM23 = 0;
860 matrixlf.lM31 = pXform->eDx;
861 matrixlf.lM32 = pXform->eDy;
862 matrixlf.lM33 = 1;
863
864 GpiSetModelTransformMatrix(hpsTemp, 9, &matrixlf, TRANSFORM_REPLACE);
865 }
866
867 for(i=0; i < pData->rdh.nCount; i++)
868 {
869 LONG temp = pRectl[i].yTop;
870 pRectl[i].yTop = pRectl[i].yBottom;
871 pRectl[i].yBottom = temp;
872
873 if(pXform)
874 {
875 PPOINTL pPointl = ((PPOINTL)&pRectl[i]);
876
877 if (doShear) {
878 GpiMove(hpsTemp, pPointl);
879 GpiBox(hpsTemp, DRO_OUTLINE, pPointl+1, 0, 0);
880 }
881 else
882 {
883 for(int j=0; j < 2; j++) {
884 pPointl[j].x = (pXform->eM11 * (float)pPointl[j].x) + (pXform->eM12 * (float)pPointl[j].y) + pXform->eDx;
885 pPointl[j].y = (pXform->eM21 * (float)pPointl[j].x) + (pXform->eM22 * (float)pPointl[j].y) + pXform->eDy;
886 }
887
888 PRECTL pRectlT = (PRECTL)pPointl;
889 if (pRectlT->xLeft > pRectlT->xRight) {
890 LONG temp = pRectlT->xLeft;
891 pRectlT->xLeft = pRectlT->xRight;
892 pRectlT->xRight = temp;
893 }
894 if (pRectlT->yBottom > pRectlT->yTop) {
895 LONG temp = pRectlT->yBottom;
896 pRectlT->yBottom = pRectlT->yTop;
897 pRectlT->yTop = temp;
898 }
899 }
900 }
901 }
902
903 if(doShear) {
904 GpiEndPath(hpsTemp);
905 hrgn = GpiPathToRegion(hpsTemp, 1, FPATH_WINDING);
906
907 if(pRectl)
908 delete[] pRectl;
909
910 if(hrgn == 0) {
911 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
912 SetLastError(ERROR_INVALID_PARAMETER_W);
913 return 0;
914 }
915 WinReleasePS(hpsTemp);
916 }
917 else {
918 hrgn = GpiCreateRegion(hpsRegion, pData->rdh.nCount, pRectl);
919 if(pRectl)
920 delete[] pRectl;
921
922 if(hrgn == 0) {
923 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
924 SetLastError(ERROR_INVALID_PARAMETER_W);
925 return 0;
926 }
927 }
928
929 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
930 SetLastError(ERROR_OUTOFMEMORY_W);
931 return 0;
932 }
933 SetLastError(ERROR_SUCCESS_W);
934 return hrgn;
935}
936//******************************************************************************
937//******************************************************************************
938HRGN WIN32API CreateEllipticRgn(int left, int top, int right, int bottom)
939{
940 HRGN hrgn;
941
942 RECTL rectl = { left,
943 top < bottom ? top : bottom,
944 right,
945 top < bottom ? bottom : top };
946
947 dprintf(("CreateEllipticRgn (%d,%d)(%d,%d)", left, top, right, bottom));
948 hrgn = GpiCreateEllipticRegion(hpsRegion, &rectl);
949
950 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
951 SetLastError(ERROR_OUTOFMEMORY_W);
952 return 0;
953 }
954 SetLastError(ERROR_SUCCESS_W);
955 return hrgn;
956}
957//******************************************************************************
958//******************************************************************************
959HRGN WIN32API CreateEllipticRgnIndirect(const RECT *pRect)
960{
961 return CreateEllipticRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
962}
963//******************************************************************************
964//******************************************************************************
965HRGN WIN32API CreatePolygonRgn(const POINT *lppt, int cPoints, int fnPolyFillMode)
966{
967 HRGN hrgn;
968 LONG flMode;
969
970 if(!lppt || cPoints < 2) {
971 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
972 SetLastError(ERROR_INVALID_PARAMETER_W);
973 return 0;
974 }
975
976 switch (fnPolyFillMode)
977 {
978 case ALTERNATE_W :
979 flMode = POLYGON_ALTERNATE;
980 break;
981 case WINDING_W :
982 flMode = POLYGON_WINDING;
983 break;
984 default:
985 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
986 SetLastError(ERROR_INVALID_PARAMETER_W);
987 return 0;
988 }
989
990 dprintf(("CreatePolygonRgn %x %d %d", lppt, cPoints, fnPolyFillMode));
991
992
993 POLYGON polygon;
994 polygon.ulPoints = cPoints - 1;
995 polygon.aPointl = (PPOINTL)(lppt + 1);
996
997 GpiMove(hpsRegion, (PPOINTL)lppt);
998 hrgn = GpiCreatePolygonRegion(hpsRegion, 1, &polygon, POLYGON_BOUNDARY | flMode);
999
1000 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
1001 SetLastError(ERROR_OUTOFMEMORY_W);
1002 return 0;
1003 }
1004 SetLastError(ERROR_SUCCESS_W);
1005 return hrgn;
1006}
1007//******************************************************************************
1008//******************************************************************************
1009int WIN32API CombineRgn(HRGN hrgnDest, HRGN hrgnSrc1, HRGN hrgnSrc2, int combineMode)
1010{
1011 ULONG lComplexity;
1012 LONG mode;
1013
1014 switch(combineMode) {
1015 case RGN_AND_W:
1016 mode = CRGN_AND;
1017 break;
1018 case RGN_COPY_W:
1019 mode = CRGN_COPY;
1020 break;
1021 case RGN_DIFF_W:
1022 mode = CRGN_DIFF;
1023 break;
1024 case RGN_OR_W:
1025 mode = CRGN_OR;
1026 break;
1027 case RGN_XOR_W:
1028 mode = CRGN_XOR;
1029 break;
1030 default:
1031 dprintf(("WARNING: CombineRgn %x %x %x %d; invalid mode!", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1032 SetLastError(ERROR_INVALID_PARAMETER_W);
1033 return ERROR_W;
1034 }
1035
1036 hrgnDest = ObjGetHandleData(hrgnDest);
1037 hrgnSrc1 = ObjGetHandleData(hrgnSrc1);
1038 hrgnSrc2 = ObjGetHandleData(hrgnSrc2);
1039 if(hrgnDest == HANDLE_OBJ_ERROR || hrgnSrc1 == HANDLE_OBJ_ERROR || (hrgnSrc2 == HANDLE_OBJ_ERROR && combineMode != RGN_COPY_W)) {
1040 dprintf(("WARNING: CombineRgn %x %x %x %d invalid region", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1041 SetLastError(ERROR_INVALID_HANDLE_W);
1042 return ERROR_W;
1043 }
1044
1045 lComplexity = GpiCombineRegion(hpsRegion, hrgnDest, hrgnSrc1, hrgnSrc2, mode);
1046 if(lComplexity == RGN_ERROR) {
1047 dprintf(("WARNING: CombineRgn %x %x %x %d GpiCombineRegion failed (%x)", hrgnDest, hrgnSrc1, hrgnSrc2, mode, WinGetLastError(0)));
1048 SetLastError(ERROR_INVALID_HANDLE_W);
1049 return ERROR_W;
1050 }
1051 SetLastError(ERROR_SUCCESS_W);
1052 return lComplexity;
1053}
1054//******************************************************************************
1055//******************************************************************************
1056BOOL WIN32API EqualRgn(HRGN hrgn1, HRGN hrgn2)
1057{
1058 LONG lEquality;
1059
1060 hrgn1 = ObjGetHandleData(hrgn1);
1061 hrgn2 = ObjGetHandleData(hrgn2);
1062 if(hrgn1 == HANDLE_OBJ_ERROR || hrgn2 == HANDLE_OBJ_ERROR) {
1063 dprintf(("WARNING: EqualRgn %x %x invalid region", hrgn1, hrgn2));
1064 SetLastError(ERROR_INVALID_HANDLE_W);
1065 return FALSE;
1066 }
1067 lEquality = GpiEqualRegion(hpsRegion, hrgn1, hrgn2);
1068
1069 dprintf(("EqualRgn %x %x = %d", hrgn1, hrgn2, lEquality));
1070 SetLastError(ERROR_SUCCESS_W);
1071
1072 if(lEquality == EQRGN_EQUAL)
1073 return TRUE;
1074 else
1075 if(lEquality == EQRGN_NOTEQUAL)
1076 return FALSE;
1077 else {
1078 return FALSE;
1079 }
1080}
1081//******************************************************************************
1082//******************************************************************************
1083BOOL WIN32API SetRectRgn(HRGN hrgn, int left, int top, int right, int bottom)
1084{
1085 BOOL result = FALSE;
1086
1087 hrgn = ObjGetHandleData(hrgn);
1088 if(hrgn == HANDLE_OBJ_ERROR) {
1089 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) invalid region handle", hrgn, left, top, right, bottom));
1090 SetLastError(ERROR_INVALID_HANDLE_W);
1091 return 0;
1092 }
1093 RECTL rectl = { left, top, right, bottom }; //reversed y coordinates
1094 if(GpiSetRegion(hpsRegion, hrgn, 1, &rectl)) {
1095 dprintf(("SetRectRgn %x (%d,%d)(%d,%d)", hrgn, left, top, right, bottom));
1096 return TRUE;
1097 }
1098 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) GpiSetRegion failed %x", hrgn, left, top, right, bottom, WinGetLastError(0)));
1099 return FALSE;
1100}
1101//******************************************************************************
1102//******************************************************************************
1103ULONG WIN32API GetRegionData(HRGN hrgn, ULONG count, PRGNDATA pData)
1104{
1105 if(!count && pData)
1106 {
1107 dprintf(("WARNING: GetRegionData %x %d %x; invalid parameter", hrgn, count, pData));
1108 SetLastError(ERROR_INVALID_PARAMETER_W);
1109 return 0;
1110 }
1111 hrgn = ObjGetHandleData(hrgn);
1112 if(hrgn == HANDLE_OBJ_ERROR) {
1113 dprintf(("WARNING: GetRegionData %x %d %x; invalid region handle", hrgn, count, pData));
1114 SetLastError(ERROR_INVALID_HANDLE_W);
1115 return 0;
1116 }
1117 RGNRECT rgnRect;
1118 rgnRect.ircStart = 1;
1119 rgnRect.crc = 0;
1120 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
1121 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1122 {
1123 dprintf(("WARNING: GetRegionData %x %d %x: GpiQueryRegionRects failed! (%x)", hrgn, count, pData, WinGetLastError(0)));
1124 return 0;
1125 }
1126
1127 dprintf(("GetRegionData %x %d %x", hrgn, count, pData));
1128
1129 ULONG bufSizeNeeded = rgnRect.crcReturned * sizeof(RECT) + sizeof (RGNDATAHEADER);
1130
1131 if(pData && (count >= (sizeof(RGNDATAHEADER) + rgnRect.crcReturned * sizeof(RECT))))
1132 {
1133 //we actually need to flip the top & bottom values, but as the layout of the PM RECTL and
1134 //Win32 RECT have exactly those two members reversed, we don't do this for the returned
1135 //rectangles (more efficient)
1136 PRECTL pRectl = (PRECTL)pData->Buffer;
1137 rgnRect.crc = rgnRect.crcReturned;
1138 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, pRectl))
1139 {
1140 dprintf(("WARNING: GetRegionData: GpiQueryRegionRects failed! (%x)", WinGetLastError(0)));
1141 return 0;
1142 }
1143
1144 RECTL boundRect;
1145 GpiQueryRegionBox(hpsRegion, hrgn, &boundRect); // no need to check rc
1146
1147 pData->rdh.dwSize = sizeof(pData->rdh);
1148 pData->rdh.iType = RDH_RECTANGLES_W; // one and only possible value
1149 pData->rdh.nCount = rgnRect.crcReturned;
1150 pData->rdh.nRgnSize = rgnRect.crcReturned * sizeof(RECTL);
1151
1152 //flip top & bottom for bounding rectangle (not really necessary; but cleaner coding)
1153 LONG temp = boundRect.yTop;
1154 boundRect.yTop = boundRect.yBottom;
1155 boundRect.yBottom = temp;
1156 MapOS2ToWin32Rect(boundRect, pData->rdh.rcBound);
1157 }
1158
1159 //return size needed
1160 return bufSizeNeeded;
1161}
1162//******************************************************************************
1163//******************************************************************************
1164int WIN32API GetRgnBox(HRGN hrgn, PRECT pRect)
1165{
1166 BOOL success;
1167 LONG lComplexity;
1168
1169 hrgn = ObjGetHandleData(hrgn);
1170 if(hrgn == HANDLE_OBJ_ERROR) {
1171 dprintf(("WARNING: GetRgnBox %x %x invalid region!", hrgn, pRect));
1172 SetLastError(ERROR_INVALID_HANDLE_W);
1173 return FALSE;
1174 }
1175
1176 dprintf(("GetRgnBox %x %x", hrgn, pRect));
1177
1178 RECTL rectl;
1179 lComplexity = GpiQueryRegionBox(hpsRegion, hrgn, &rectl);
1180 if(lComplexity != RGN_ERROR)
1181 {
1182 //no conversion required, just flip top & bottom
1183 ULONG temp = rectl.yBottom;
1184 rectl.yBottom = rectl.yTop;
1185 rectl.yTop = temp;
1186
1187 MapOS2ToWin32Rect(rectl, *pRect);
1188 }
1189 else {
1190 lComplexity = ERROR_W;
1191 dprintf(("WARNING: GetRgnBox error in region!"));
1192 }
1193
1194 SetLastError(ERROR_SUCCESS_W);
1195 return lComplexity;
1196}
1197//******************************************************************************
1198//******************************************************************************
1199BOOL WIN32API InvertRgn(HDC hdc, HRGN hrgn)
1200{
1201 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1202
1203 hrgn = ObjGetHandleData(hrgn);
1204 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1205 dprintf(("WARNING: InvertRgn %x %x invalid handle!", hdc, hrgn));
1206 SetLastError(ERROR_INVALID_HANDLE_W);
1207 return FALSE;
1208 }
1209 //todo metafile recording
1210
1211 dprintf(("InvertRgn %x %x", hdc, hrgn));
1212
1213 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1214
1215 LONG lHits = GPI_ERROR;
1216 HRGN hrgnOld;
1217 LONG lComplexity ;
1218 RECTL boundingRect; // this gets a rectangle in world cordinates!
1219
1220 lComplexity = GpiQueryRegionBox(pHps->hps, pHps->hrgnHDC, &boundingRect);
1221 if(lComplexity != RGN_ERROR)
1222 {
1223 lComplexity = GpiSetClipRegion(pHps->hps, pHps->hrgnHDC, &hrgnOld);
1224 if(lComplexity != RGN_ERROR)
1225 {
1226 RECTL rectls[2];
1227 rectls[0] = boundingRect;
1228 rectls[1] = boundingRect;
1229 lHits = GpiBitBlt(pHps->hps, NULL, 3, (PPOINTL)rectls,
1230 ROP_DSTINVERT, 0);
1231
1232 /* Restore the old region */
1233 GpiSetClipRegion(pHps->hps, hrgnOld, &hrgnOld);
1234 }
1235 }
1236
1237 if(lHits == GPI_ERROR || lComplexity == RGN_ERROR)
1238 {
1239 dprintf(("WARNING: InvertRgn error during Gpi operation (%x) (%d,%d)", WinGetLastError(0), lHits, lComplexity));
1240 return FALSE;
1241 }
1242
1243 return TRUE;
1244}
1245//******************************************************************************
1246//******************************************************************************
1247int WIN32API OffsetRgn(HRGN hrgn, int xOffset, int yOffset)
1248{
1249 LONG lComplexity;
1250
1251 hrgn = ObjGetHandleData(hrgn);
1252 if(hrgn == HANDLE_OBJ_ERROR) {
1253 dprintf(("WARNING: OffsetRgn %x %d %d invalid handle!", hrgn, xOffset, yOffset));
1254 SetLastError(ERROR_INVALID_HANDLE_W);
1255 return ERROR_W;
1256 }
1257 dprintf(("OffsetRgn %x %d %d", hrgn, xOffset, yOffset));
1258
1259 POINTL ptlOffset = {xOffset, yOffset};
1260 GpiOffsetRegion(hpsRegion, hrgn, &ptlOffset);
1261
1262 RGNRECT rgnRect;
1263 rgnRect.ircStart = 1;
1264 rgnRect.crc = 0;
1265 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference
1266 if(GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1267 {
1268 switch (rgnRect.crcReturned) {
1269 case 0:
1270 lComplexity = NULLREGION_W;
1271 break;
1272 case 1:
1273 lComplexity = SIMPLEREGION_W;
1274 break;
1275 default:
1276 lComplexity = COMPLEXREGION_W;
1277 break;
1278 }
1279 }
1280 else {
1281 lComplexity = ERROR_W;
1282 dprintf(("WARNING: OffsetRgn error in region! (%x)", WinGetLastError(0)));
1283 }
1284
1285 SetLastError(ERROR_SUCCESS_W);
1286
1287 return lComplexity;
1288}
1289//******************************************************************************
1290//******************************************************************************
1291BOOL WIN32API FrameRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush, int width, int height)
1292{
1293 HBRUSH hbrushRestore = 0;
1294 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1295
1296 hrgn = ObjGetHandleData(hrgn);
1297 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1298 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid handle!", hdc, hrgn, hBrush, width, height));
1299 SetLastError(ERROR_INVALID_HANDLE_W);
1300 return FALSE;
1301 }
1302
1303 width = abs(width);
1304 height = abs(height);
1305
1306 if(pHps->lastBrushHandle != (UINT)hBrush)
1307 {
1308 hbrushRestore = SelectObject(hdc, hBrush);
1309 if(!hbrushRestore)
1310 {
1311 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid brush!", hdc, hrgn, hBrush, width, height));
1312 SetLastError(ERROR_INVALID_HANDLE_W);
1313 return FALSE;
1314 }
1315 }
1316 dprintf(("FrameRgn %x %x %x (%d,%d)", hdc, hrgn, hBrush, width, height));
1317 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1318
1319 SIZEL thickness = { width, height };
1320 LONG lHits = GpiFrameRegion(pHps->hps, pHps->hrgnHDC, &thickness);
1321
1322 SetLastError(ERROR_SUCCESS_W);
1323
1324 // Restore the brush if necessary
1325 if(hbrushRestore)
1326 SelectObject(hdc, hbrushRestore);
1327
1328 //todo metafile recording
1329 return (lHits != GPI_ERROR);
1330}
1331//******************************************************************************
1332//******************************************************************************
1333BOOL WIN32API FillRgn(HDC hdc, HRGN hrgn, HBRUSH hBrush)
1334{
1335 BOOL success;
1336 HBRUSH hbrushRestore = 0;
1337
1338 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1339
1340 hrgn = ObjGetHandleData(hrgn);
1341 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1342 dprintf(("WARNING: FillRgn %x %x %x invalid handle!", hdc, hrgn, hBrush));
1343 SetLastError(ERROR_INVALID_HANDLE_W);
1344 return FALSE;
1345 }
1346
1347 if(pHps->lastBrushHandle != (UINT)hBrush)
1348 {
1349 hbrushRestore = SelectObject(hdc, hBrush);
1350 if (!hbrushRestore)
1351 {
1352 dprintf(("WARNING: FillRgn %x %x %x invalid brush!", hdc, hrgn, hBrush));
1353 SetLastError(ERROR_INVALID_HANDLE_W);
1354 return FALSE;
1355 }
1356 }
1357 dprintf(("FillRgn %x %x %x", hdc, hrgn, hBrush));
1358
1359 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1360
1361 success = GpiPaintRegion(pHps->hps, pHps->hrgnHDC);
1362
1363 //todo metafile recording
1364
1365 /* Restore the brush if necessary */
1366 if(hbrushRestore)
1367 SelectObject(hdc, hbrushRestore);
1368
1369 return(success);
1370}
1371//******************************************************************************
1372//******************************************************************************
1373BOOL WIN32API PaintRgn(HDC hdc, HRGN hrgn)
1374{
1375 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1376 if(!pHps)
1377 {
1378 SetLastError(ERROR_INVALID_HANDLE_W);
1379 return FALSE;
1380 }
1381
1382 return FillRgn(hdc, hrgn, (HBRUSH) pHps->lastBrushHandle);
1383}
1384//******************************************************************************
1385//******************************************************************************
1386BOOL WIN32API PtInRegion( HRGN hrgn, int x, int y)
1387{
1388 BOOL success;
1389 LONG lInside;
1390
1391 hrgn = ObjGetHandleData(hrgn);
1392 if(hrgn == HANDLE_OBJ_ERROR) {
1393 dprintf(("WARNING: PtInRgn %x (%d,%d) invalid region!", hrgn, x, y));
1394 SetLastError(ERROR_INVALID_HANDLE_W);
1395 return FALSE;
1396 }
1397
1398 POINTL pointl = {x,y};
1399 lInside = GpiPtInRegion(hpsRegion, hrgn, &pointl);
1400 if(lInside == PRGN_ERROR) {
1401 success = FALSE;
1402 }
1403 else success = TRUE;
1404
1405 SetLastError(ERROR_SUCCESS_W);
1406
1407 dprintf(("WARNING: PtInRgn %x (%d,%d) returned %d", hrgn, x, y, (success && lInside == PRGN_INSIDE) ? 1 : 0));
1408
1409 if(success && lInside == PRGN_INSIDE)
1410 return TRUE;
1411 else
1412 return FALSE;
1413}
1414//******************************************************************************
1415//******************************************************************************
1416BOOL WIN32API RectInRegion(HRGN hrgn, const RECT *pRect)
1417{
1418 BOOL success;
1419 LONG lInside;
1420
1421 if(!pRect) {
1422 dprintf(("WARNING: RectInRgn %x %x invalid parameter!", hrgn, pRect));
1423 SetLastError(ERROR_INVALID_PARAMETER_W);
1424 return FALSE;
1425 }
1426 hrgn = ObjGetHandleData(hrgn);
1427 if(hrgn == HANDLE_OBJ_ERROR) {
1428 dprintf(("WARNING: RectInRgn %x %x invalid region", hrgn, pRect));
1429 SetLastError(ERROR_INVALID_HANDLE_W);
1430 return FALSE;
1431 }
1432
1433 RECTL rectl;
1434 MapWin32ToOS2Rect(*pRect, rectl);
1435 //switch bottom & top
1436 UINT temp = rectl.yBottom;
1437 rectl.yBottom = rectl.yTop;
1438 rectl.yTop = temp;
1439
1440 lInside = GpiRectInRegion(hpsRegion, hrgn, &rectl);
1441 if(lInside == RRGN_ERROR) {
1442 success = FALSE;
1443 }
1444 else success = TRUE;
1445
1446 SetLastError(ERROR_SUCCESS_W);
1447
1448 dprintf(("WARNING: RectInRgn %x %x returned %d", hrgn, pRect, (success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL)) ? 1 : 0));
1449
1450 if(success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL))
1451 return TRUE;
1452 else
1453 return FALSE;
1454}
1455//******************************************************************************
1456//Returned region in device coordinates (undocumented behaviour)
1457//******************************************************************************
1458HRGN WIN32API PathToRegion(HDC hdc)
1459{
1460 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1461 if(!pHps)
1462 {
1463 dprintf(("WARNING: PathToRegion %x; invalid hdc!", hdc));
1464 SetLastError(ERROR_INVALID_HANDLE_W);
1465 return NULLHANDLE;
1466 }
1467
1468 HRGN hrgn, hrgnTemp, hrgnwin;
1469
1470 dprintf(("GDI32: PathToRegion %x", hdc));
1471
1472 hrgnTemp = GpiPathToRegion(pHps->hps, 1, (pHps->polyFillMode == ALTERNATE_W) ? FPATH_ALTERNATE : FPATH_WINDING);
1473 if(hrgnTemp == NULLHANDLE)
1474 goto error;
1475
1476 hrgnwin = CreateRectRgn(1, 1, 2, 2);
1477 hrgn = ObjGetHandleData(hrgnwin);
1478 if(hrgn == HANDLE_OBJ_ERROR) {
1479 dprintf(("WARNING: PathToRegion invalid region", hrgnwin));
1480 SetLastError(ERROR_INVALID_HANDLE_W);
1481 return NULLHANDLE;
1482 }
1483
1484 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnTemp, pHps, NULL))
1485 goto error;
1486
1487 GpiDestroyRegion(pHps->hps, hrgnTemp);
1488
1489 return hrgnwin;
1490
1491error:
1492 if(hrgnwin)
1493 DeleteObject(hrgnwin);
1494
1495 SetLastError(ERROR_INVALID_HANDLE_W); //todo right error
1496 return NULLHANDLE;
1497}
1498//******************************************************************************
1499//******************************************************************************
1500void OSLibDeleteRegion(HANDLE hRegion)
1501{
1502 if(GpiDestroyRegion(hpsRegion, hRegion) == FALSE) {
1503 dprintf(("WARNING: OSLibDeleteRegion %x; GpiDestroyRegion failed (%x)", hRegion, WinGetLastError(0)));
1504 }
1505}
1506/*****************************************************************************
1507 * Name : int GetMetaRgn
1508 * Purpose : The GetMetaRgn function retrieves the current metaregion for
1509 * the specified device context.
1510 * Parameters: HDC hdc handle of device context
1511 * HRGN hrgn handle of region
1512 * Variables :
1513 * Result : 0 / 1
1514 * Remark :
1515 * Status : UNTESTED STUB
1516 *
1517 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1518 *****************************************************************************/
1519
1520int WIN32API GetMetaRgn(HDC hdc,
1521 HRGN hrgn)
1522{
1523 dprintf(("GDI32: GetMetaRgn(%08xh, %08xh) not implemented.\n",
1524 hdc,
1525 hrgn));
1526
1527 SetLastError(ERROR_SUCCESS_W);
1528 return (0);
1529}
1530/*****************************************************************************
1531 * Name : int SetMetaRgn
1532 * Purpose : The SetMetaRgn function intersects the current clipping region
1533 * for the specified device context with the current metaregion
1534 * and saves the combined region as the new metaregion for the
1535 * specified device context. The clipping region is reset to a null region.
1536 * Parameters: HDC hdc handle of device context
1537 * Variables :
1538 * Result : TRUE / FALSE
1539 * Remark :
1540 * Status : UNTESTED STUB
1541 *
1542 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1543 *****************************************************************************/
1544
1545BOOL WIN32API SetMetaRgn(HDC hdc)
1546{
1547 dprintf(("GDI32: SetMetaRgn(%08xh) not implemented.\n",
1548 hdc));
1549
1550 SetLastError(ERROR_SUCCESS_W);
1551 return (NULLREGION_W);
1552}
1553//******************************************************************************
1554//******************************************************************************
Note: See TracBrowser for help on using the repository browser.