From 7c1ad31f47a9d229d1f877d2ca45b93be805a47c Mon Sep 17 00:00:00 2001 From: Jon Griffiths Date: Tue, 23 Nov 2004 12:19:24 +0000 Subject: [PATCH] Set the miter limit in the DC state. Only SetLastError() in object functions where native does. Test the error comditions of the gdiobj functions. Minor documentation updates. --- dlls/gdi/dc.c | 49 +++++++++++++++++++ dlls/gdi/gdi_private.h | 1 + dlls/gdi/gdiobj.c | 104 ++++++++++++++++++++++++++-------------- dlls/gdi/tests/gdiobj.c | 68 ++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 36 deletions(-) diff --git a/dlls/gdi/dc.c b/dlls/gdi/dc.c index 3cd121a7129..972d3d49e58 100644 --- a/dlls/gdi/dc.c +++ b/dlls/gdi/dc.c @@ -75,6 +75,7 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs, WORD magic ) dc->vportOrgY = 0; dc->vportExtX = 1; dc->vportExtY = 1; + dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */ dc->flags = 0; dc->hClipRgn = 0; dc->hVisRgn = 0; @@ -2034,3 +2035,51 @@ DWORD WINAPI SetVirtualResolution(HDC hdc, DWORD dw2, DWORD dw3, DWORD dw4, DWOR FIXME("(%p %08lx %08lx %08lx %08lx): stub!\n", hdc, dw2, dw3, dw4, dw5); return FALSE; } + +/******************************************************************* + * GetMiterLimit [GDI32.@] + * + * + */ +BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit) +{ + BOOL bRet = FALSE; + DC *dc; + + TRACE("(%p,%p)\n", hdc, peLimit); + + dc = DC_GetDCPtr( hdc ); + if (dc) + { + if (peLimit) + *peLimit = dc->miterLimit; + + GDI_ReleaseObj( hdc ); + bRet = TRUE; + } + return bRet; +} + +/******************************************************************* + * SetMiterLimit [GDI32.@] + * + * + */ +BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit) +{ + BOOL bRet = FALSE; + DC *dc; + + TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit); + + dc = DC_GetDCPtr( hdc ); + if (dc) + { + if (peOldLimit) + *peOldLimit = dc->miterLimit; + dc->miterLimit = eNewLimit; + GDI_ReleaseObj( hdc ); + bRet = TRUE; + } + return bRet; +} diff --git a/dlls/gdi/gdi_private.h b/dlls/gdi/gdi_private.h index f5aa6821be6..f598534c0b1 100644 --- a/dlls/gdi/gdi_private.h +++ b/dlls/gdi/gdi_private.h @@ -215,6 +215,7 @@ typedef struct tagDC INT vportOrgY; INT vportExtX; /* Viewport extent */ INT vportExtY; + FLOAT miterLimit; int flags; HRGN hClipRgn; /* Clip region (may be 0) */ diff --git a/dlls/gdi/gdiobj.c b/dlls/gdi/gdiobj.c index 7e370d45b71..eea174c1f36 100644 --- a/dlls/gdi/gdiobj.c +++ b/dlls/gdi/gdiobj.c @@ -875,7 +875,6 @@ void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic ) if (!ptr) { _LeaveSysLevel( &GDI_level ); - SetLastError( ERROR_INVALID_HANDLE ); WARN( "Invalid handle %p\n", handle ); } else TRACE_SEC( handle, "enter" ); @@ -907,6 +906,17 @@ void GDI_CheckNotLock(void) /*********************************************************************** * DeleteObject (GDI32.@) + * + * Delete a Gdi object. + * + * PARAMS + * obj [I] Gdi object to delete + * + * RETURNS + * Success: TRUE. If obj was not returned from GetStockObject(), any resources + * it consumed are released. + * Failure: FALSE, if obj is not a valid Gdi object, or is currently selected + * into a DC. */ BOOL WINAPI DeleteObject( HGDIOBJ obj ) { @@ -1120,7 +1130,11 @@ DWORD WINAPI GetObjectType( HGDIOBJ handle ) INT result = 0; TRACE("%p\n", handle ); - if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0; + if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) + { + SetLastError( ERROR_INVALID_HANDLE ); + return 0; + } switch(GDIMAGIC(ptr->wMagic)) { @@ -1173,6 +1187,24 @@ DWORD WINAPI GetObjectType( HGDIOBJ handle ) /*********************************************************************** * GetCurrentObject (GDI32.@) + * + * Get the currently selected object of a given type in a device context. + * + * PARAMS + * hdc [I] Device context to get the current object from + * type [I] Type of current object to get (OBJ_* defines from "wingdi.h") + * + * RETURNS + * Success: The current object of the given type selected in hdc. + * Failure: A NULL handle. + * + * NOTES + * - only the following object types are supported: + *| OBJ_PEN + *| OBJ_BRUSH + *| OBJ_PAL + *| OBJ_FONT + *| OBJ_BITMAP */ HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type) { @@ -1200,25 +1232,49 @@ HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type) /*********************************************************************** * SelectObject (GDI32.@) + * + * Select a Gdi object into a device context. + * + * PARAMS + * hdc [I] Device context to associate the object with + * hObj [I] Gdi object to associate with hdc + * + * RETURNS + * Success: A non-NULL handle representing the previously selected object of + * the same type as hObj. + * Failure: A NULL object. If hdc is invalid, GetLastError() returns ERROR_INVALID_HANDLE. + * if hObj is not a valid object handle, no last error is set. In either + * case, hdc is unaffected by the call. */ -HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle ) +HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj ) { HGDIOBJ ret = 0; - GDIOBJHDR *header = GDI_GetObjPtr( handle, MAGIC_DONTCARE ); - if (!header) return 0; + GDIOBJHDR *header; + DC *dc; - TRACE("hdc=%p %p\n", hdc, handle ); + TRACE( "(%p,%p)\n", hdc, hObj ); - if (header->funcs && header->funcs->pSelectObject) + if (!(dc = DC_GetDCPtr( hdc ))) + SetLastError( ERROR_INVALID_HANDLE ); + else { - ret = header->funcs->pSelectObject( handle, header, hdc ); - if (ret && ret != handle && (INT)ret > COMPLEXREGION) + GDI_ReleaseObj( (GDIOBJHDR *)dc ); + + header = GDI_GetObjPtr( hObj, MAGIC_DONTCARE ); + if (header) { - inc_ref_count( handle ); - dec_ref_count( ret ); + if (header->funcs && header->funcs->pSelectObject) + { + ret = header->funcs->pSelectObject( hObj, header, hdc ); + if (ret && ret != hObj && (INT)ret > COMPLEXREGION) + { + inc_ref_count( hObj ); + dec_ref_count( ret ); + } + } + GDI_ReleaseObj( hObj ); } } - GDI_ReleaseObj( handle ); return ret; } @@ -1478,30 +1534,6 @@ BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca) return 0; } -/******************************************************************* - * GetMiterLimit [GDI32.@] - * - * - */ -BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit) -{ - FIXME("GetMiterLimit, stub\n"); - return 0; -} - -/******************************************************************* - * SetMiterLimit [GDI32.@] - * - * - */ -BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit) -{ - FIXME("(%p,%f,%p) stub\n", hdc, eNewLimit, peOldLimit); - if (peOldLimit) - *peOldLimit = 10.0; /* Default miter is 10, see msdn */ - return TRUE; -} - /******************************************************************* * GdiComment [GDI32.@] * diff --git a/dlls/gdi/tests/gdiobj.c b/dlls/gdi/tests/gdiobj.c index 0dd1db14182..0edacdca25c 100644 --- a/dlls/gdi/tests/gdiobj.c +++ b/dlls/gdi/tests/gdiobj.c @@ -205,8 +205,76 @@ todo_wine ReleaseDC(0, hdc); } +static void test_gdi_objects(void) +{ + BYTE buff[256]; + HDC hdc = GetDC(NULL); + HPEN hp; + int i; + + /* SelectObject() with a NULL DC returns 0 and sets ERROR_INVALID_HANDLE. + * Note: Under XP at least invalid ptrs can also be passed, not just NULL; + * Don't test that here in case it crashes earlier win versions. + */ + SetLastError(0); + hp = SelectObject(NULL, GetStockObject(BLACK_PEN)); + ok(!hp && GetLastError() == ERROR_INVALID_HANDLE, + "SelectObject(NULL DC) expected 0, ERROR_INVALID_HANDLE, got %p, 0x%08lx\n", + hp, GetLastError()); + + /* With a valid DC and a NULL object, the call returns 0 but does not SetLastError() */ + SetLastError(0); + hp = SelectObject(hdc, NULL); + ok(!hp && !GetLastError(), + "SelectObject(NULL obj) expected 0, NO_ERROR, got %p, 0x%08lx\n", + hp, GetLastError()); + + /* The DC is unaffected by the NULL SelectObject */ + SetLastError(0); + hp = SelectObject(hdc, GetStockObject(BLACK_PEN)); + ok(hp && !GetLastError(), + "SelectObject(post NULL) expected non-null, NO_ERROR, got %p, 0x%08lx\n", + hp, GetLastError()); + + /* GetCurrentObject does not SetLastError() on a null object */ + SetLastError(0); + hp = GetCurrentObject(NULL, OBJ_PEN); + ok(!hp && !GetLastError(), + "GetCurrentObject(NULL DC) expected 0, NO_ERROR, got %p, 0x%08lx\n", + hp, GetLastError()); + + /* DeleteObject does not SetLastError() on a null object */ + ok(!DeleteObject(NULL) && !GetLastError(), + "DeleteObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n", + DeleteObject(NULL), GetLastError()); + + /* GetObject does not SetLastError() on a null object */ + SetLastError(0); + i = GetObjectA(NULL, sizeof(buff), buff); + ok (!i && !GetLastError(), + "GetObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n", + i, GetLastError()); + + /* GetObjectType does SetLastError() on a null object */ + SetLastError(0); + i = GetObjectType(NULL); + ok (!i && GetLastError() == ERROR_INVALID_HANDLE, + "GetObjectType(NULL obj), expected 0, ERROR_INVALID_HANDLE, got %d, 0x%08lx\n", + i, GetLastError()); + + /* UnrealizeObject does not SetLastError() on a null object */ + SetLastError(0); + i = UnrealizeObject(NULL); + ok (!i && !GetLastError(), + "UnrealizeObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n", + i, GetLastError()); + + ReleaseDC(NULL, hdc); +} + START_TEST(gdiobj) { test_logfont(); test_bitmap_font(); + test_gdi_objects(); }