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

Last change on this file since 4802 was 4755, checked in by sandervl, 25 years ago

handle management update

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