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

Last change on this file since 9429 was 9429, checked in by sandervl, 23 years ago

Added debug wrappers for all exports

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