Ignore:
Timestamp:
Jun 14, 2000, 3:17:51 PM (25 years ago)
Author:
sandervl
Message:

region changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gdi32/region.cpp

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