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

Last change on this file since 5087 was 4848, checked in by sandervl, 25 years ago

Win32ToOS2Handle & OS2ToWin32Handle exported with stdcall calling convention

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