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

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

extra logging

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