From 78bfde8ac086e4009edf0aadfee959f60a165df3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 26 May 2016 23:34:58 +0200 Subject: [PATCH 1/2] Fix link errors with older MinGW due to use of GetLayout() This function is not present in older MinGW import libraries, up to at least MinGW 4.8.1, so we can't use it directly as it was done in 22f0801378674ccf815434389d3ec9faeb766af5 and we need to load it dynamically. This was already done in wxDC code, so just reuse the same wrapper function after extracting it (and a few others, for consistency) into a new header. --- include/wx/msw/private/dcdynwrap.h | 39 ++++++++++++++++++++++++++++++ src/msw/checklst.cpp | 3 ++- src/msw/dc.cpp | 11 --------- 3 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 include/wx/msw/private/dcdynwrap.h diff --git a/include/wx/msw/private/dcdynwrap.h b/include/wx/msw/private/dcdynwrap.h new file mode 100644 index 0000000000..fe41430c30 --- /dev/null +++ b/include/wx/msw/private/dcdynwrap.h @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/private/dcdynwrap.h +// Purpose: Private dynamically loaded HDC-related functions +// Author: Vadim Zeitlin +// Created: 2016-05-26 (extracted from src/msw/dc.cpp) +// Copyright: (c) 2016 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_PRIVATE_DCDYNWRAP_H_ +#define _WX_MSW_PRIVATE_DCDYNWRAP_H_ + +#include "wx/msw/wrapwin.h" + +// Namespace for the wrapper functions, hopefully one day we'll be able to get +// rid of all of them and then it will be easy to find all occurrences of their +// use by just searching for this namespace name. +// +// All of the functions in this namespace must work *exactly* like the standard +// functions with the same name and just return an error if dynamically loading +// them failed. +// +// And they're all implemented in src/msw/dc.cpp. +namespace wxDynLoadWrappers +{ + +DWORD GetLayout(HDC hdc); +DWORD SetLayout(HDC hdc, DWORD dwLayout); + +BOOL AlphaBlend(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, + HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, + BLENDFUNCTION bf); + +BOOL GradientFill(HDC hdc, PTRIVERTEX pVert, ULONG numVert, + PVOID pMesh, ULONG numMesh, ULONG mode); + +} // namespace wxDynLoadWrappers + +#endif // _WX_MSW_PRIVATE_DCDYNWRAP_H_ diff --git a/src/msw/checklst.cpp b/src/msw/checklst.cpp index c47e6c3e09..ec084c3175 100644 --- a/src/msw/checklst.cpp +++ b/src/msw/checklst.cpp @@ -47,6 +47,7 @@ #include "wx/renderer.h" #include "wx/msw/private.h" #include "wx/msw/dc.h" +#include "wx/msw/private/dcdynwrap.h" // ---------------------------------------------------------------------------- // private functions @@ -159,7 +160,7 @@ bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc, UINT uState = stat & wxOwnerDrawn::wxODSelected ? wxDSB_SELECTED : wxDSB_NORMAL; // checkmarks should not be mirrored in RTL layout - DWORD oldLayout = ::GetLayout(hdc); + DWORD oldLayout = wxDynLoadWrappers::GetLayout(hdc); if ( oldLayout & LAYOUT_RTL ) ::SetLayout(hdc, oldLayout | LAYOUT_BITMAPORIENTATIONPRESERVED); wxDrawStateBitmap(hdc, hBmpCheck, x, y, uState); diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 03f96e6955..acf9cc1f22 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -240,13 +240,6 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxGDIDLLsCleanupModule, wxModule); #endif // USE_DYNAMIC_GDI_FUNCS -// Namespace for the wrapper functions, hopefully one day we'll be able to get -// rid of all of them and then it will be easy to find all occurrences of their -// use by just searching for this namespace name. -// -// All of the functions in this namespace must work *exactly* like the standard -// functions with the same name and just return an error if dynamically loading -// them failed. namespace wxDynLoadWrappers { @@ -317,19 +310,16 @@ BOOL GradientFill(HDC hdc, PTRIVERTEX pVert, ULONG numVert, #elif defined(USE_STATIC_GDI_FUNCS) -inline DWORD GetLayout(HDC hdc) { return ::GetLayout(hdc); } -inline DWORD SetLayout(HDC hdc, DWORD dwLayout) { return ::SetLayout(hdc, dwLayout); } -inline BOOL AlphaBlend(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, BLENDFUNCTION bf) @@ -339,7 +329,6 @@ BOOL AlphaBlend(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, bf); } -inline BOOL GradientFill(HDC hdc, PTRIVERTEX pVert, ULONG numVert, PVOID pMesh, ULONG numMesh, ULONG mode) { From 6d54c49b2a672ab503ddfaae4174cbd5dfec2ce0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 26 May 2016 23:37:28 +0200 Subject: [PATCH 2/2] Fix build with classic MinGW in strict ANSI mode when using PCH The hack used in cc774bb3016813e67591c019d716f8e0861f8bb9 to include some standard headers after undefining __STRICT_ANSI__ doesn't work when precompiled headers are used because the headers had been already included from wx/wxprec.h then. So instead bite the bullet and just reproduce MinGW stdlib.h declarations to define "environ" ourselves, it's not that bad and hopefully won't need much maintenance as later versions won't need the strict ANSI workarounds at all. As for tzset(), wxDECL_FOR_STRICT_MINGW32() can be used for it without any problems at all, not sure why hasn't it been done like this since the beginning. See #16984. --- src/common/time.cpp | 18 +----------------- src/common/utilscmn.cpp | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/common/time.cpp b/src/common/time.cpp index b9ccf39b43..6c42da537a 100644 --- a/src/common/time.cpp +++ b/src/common/time.cpp @@ -22,23 +22,6 @@ #pragma hdrstop #endif -// This is a horrible hack which only works because we don't currently include -// from wx/wxprec.h. It is needed because we need timezone-related -// stuff from MinGW time.h, but it is not compiled in strict ANSI mode and it -// is too complicated to be dealt with using wxDECL_FOR_STRICT_MINGW32(). So we -// just include the header after undefining __STRICT_ANSI__ to get all the -// declarations we need -- and then define it back to avoid inconsistencies in -// all our other headers. -// -// Note that the same hack is used for "environ" in utilscmn.cpp, so if the -// code here is modified because this hack becomes unnecessary or a better -// solution is found, the code there should be updated as well. -#ifdef wxNEEDS_STRICT_ANSI_WORKAROUNDS - #undef __STRICT_ANSI__ - #include - #define __STRICT_ANSI__ -#endif - #include "wx/time.h" #ifndef WX_PRECOMP @@ -59,6 +42,7 @@ #include +wxDECL_FOR_STRICT_MINGW32(void, tzset, (void)); #if !defined(__WXMAC__) #include // for time_t diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index fbf933fa94..7394fe3c85 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -23,12 +23,27 @@ #pragma hdrstop #endif -// See comment about this hack in time.cpp: here we do it for environ external -// variable which can't be easily declared when using MinGW in strict ANSI mode. +// This is a needed to get the declaration of the global "environ" variable +// from MinGW headers which don't declare it there when in strict ANSI mode. We +// can't use the usual wxDECL_FOR_STRICT_MINGW32() hack for it because it's not +// even a variable, but a macro expanding to a function or a variable depending +// on the build and this is horribly brittle but there just doesn't seem to be +// any other alternative. #ifdef wxNEEDS_STRICT_ANSI_WORKAROUNDS - #undef __STRICT_ANSI__ + // Notice that undefining __STRICT_ANSI__ and including it here doesn't + // work because it could have been already included, e.g. when using PCH. #include - #define __STRICT_ANSI__ + + #ifndef environ + // This just reproduces what stdlib.h does in MinGW 4.8.1. + #ifdef __MSVCRT__ + wxDECL_FOR_STRICT_MINGW32(char ***, __p__environ, (void)); + #define environ (*__p__environ()) + #else + extern char *** _imp___environ_dll; + #define environ (*_imp___environ_dll) + #endif + #endif // defined(environ) #endif #ifndef WX_PRECOMP