Enlist `wx/string.h` header in `wx/colour.h`
The full `wxString` class definition is needed, not just the forward
declaration. Otherwise the `const char*`- and `const wchar_t*`-based
`wxColour` constructors attempt to call the `Set()` overload that takes
a `unsigned long`, causing the following error:
```
$WXWIN/build-debug/bk-deps g++ -c -o corelib_msw_colour.o -I$WXWIN/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/msw/colour.cpp
In file included from ../src/msw/colour.cpp:14:
../include/wx/msw/colour.h: In constructor 'wxColour::wxColour(const char*)':
../include/wx/colour.h:26:52: error: invalid conversion from 'const char*' to 'long unsigned int' [-fpermissive]
26 | wxColour(const char *colourName) { Init(); Set(colourName); }
| ^~~~~~~~~~
| |
| const char*
../include/wx/colour.h:39:5: note: in expansion of macro 'wxWXCOLOUR_CTOR_FROM_CHAR'
39 | wxWXCOLOUR_CTOR_FROM_CHAR \
| ^~~~~~~~~~~~~~~~~~~~~~~~~
../include/wx/msw/colour.h:24:5: note: in expansion of macro 'DEFINE_STD_WXCOLOUR_CONSTRUCTORS'
24 | DEFINE_STD_WXCOLOUR_CONSTRUCTORS
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../include/wx/colour.h:100:28: note: initializing argument 1 of 'void wxColourBase::Set(long unsigned int)'
100 | void Set(unsigned long colRGB)
| ~~~~~~~~~~~~~~^~~~~~
../include/wx/msw/colour.h: In constructor 'wxColour::wxColour(const wchar_t*)':
../include/wx/colour.h:40:55: error: invalid conversion from 'const wchar_t*' to 'long unsigned int' [-fpermissive]
40 | wxColour(const wchar_t *colourName) { Init(); Set(colourName); }
| ^~~~~~~~~~
| |
| const wchar_t*
../include/wx/msw/colour.h:24:5: note: in expansion of macro 'DEFINE_STD_WXCOLOUR_CONSTRUCTORS'
24 | DEFINE_STD_WXCOLOUR_CONSTRUCTORS
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../include/wx/colour.h:100:28: note: initializing argument 1 of 'void wxColourBase::Set(long unsigned int)'
100 | void Set(unsigned long colRGB)
| ~~~~~~~~~~~~~~^~~~~~
make: *** [Makefile:30649: corelib_msw_colour.o] Error 1
```
Enlist `wx/control.h` header in `src/msw/window.cpp`
The use of `wxDynamicCast` with `wxControl` needs its full definition.
Without this patch we get the following error:
```
$WXWIN/build-debug/bk-deps g++ -c -o corelib_msw_window.o -I$WXWIN/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/msw/window.cpp
In file included from ../include/wx/event.h:15,
from ../include/wx/window.h:18,
from ../src/msw/window.cpp:23:
../src/msw/window.cpp: In member function 'wxWindow* wxWindow::FindItemByHWND(WXHWND, bool) const':
../include/wx/object.h:121:21: error: incomplete type 'wxControl' used in nested name specifier
121 | &className::ms_classInfo)))
| ^~~~~~~~~~~~
../src/msw/window.cpp:353:20: note: in expansion of macro 'wxDynamicCast'
353 | || wxDynamicCast(parent, wxControl)
| ^~~~~~~~~~~~~
../src/msw/window.cpp: In static member function 'static wxButton* wxWindow::MSWGetDefaultButtonFor(wxWindow*)':
../src/msw/window.cpp:2892:57: warning: unused parameter 'win' [-Wunused-parameter]
2892 | wxButton* wxWindowMSW::MSWGetDefaultButtonFor(wxWindow* win)
| ~~~~~~~~~~^~~
../src/msw/window.cpp: In member function 'virtual bool wxWindow::MSWOnDrawItem(int, void**)':
../src/msw/window.cpp:4793:20: error: invalid use of incomplete type 'class wxControl'
4793 | return item->MSWOnDraw(itemStruct);
| ^~
../include/wx/window.h:57:28: note: forward declaration of 'class wxControl'
57 | class WXDLLIMPEXP_FWD_CORE wxControl;
| ^~~~~~~~~
../src/msw/window.cpp:4737:55: warning: unused parameter 'id' [-Wunused-parameter]
4737 | wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
| ^
../src/msw/window.cpp:4731:43: note: in definition of macro 'WXUNUSED_UNLESS_ODRAWN'
4731 | #define WXUNUSED_UNLESS_ODRAWN(param) param
| ^~~~~
../src/msw/window.cpp: In member function 'bool wxWindow::HandleCtlColor(HBRUSH__**, WXHDC, WXHWND)':
../include/wx/object.h:121:21: error: incomplete type 'wxControl' used in nested name specifier
121 | &className::ms_classInfo)))
| ^~~~~~~~~~~~
../src/msw/window.cpp:5126:23: note: in expansion of macro 'wxDynamicCast'
5126 | wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
| ^~~~~~~~~~~~~
../src/msw/window.cpp:5129:22: error: invalid use of incomplete type 'class wxControl'
5129 | *brush = item->MSWControlColor(hDC, hWnd);
| ^~
../include/wx/window.h:57:28: note: forward declaration of 'class wxControl'
57 | class WXDLLIMPEXP_FWD_CORE wxControl;
| ^~~~~~~~~
../src/msw/window.cpp: In member function 'bool wxWindow::HandleMouseWheel(wxMouseWheelAxis, WXWPARAM, WXLPARAM)':
../src/msw/window.cpp:6091:48: warning: unused parameter 'axis' [-Wunused-parameter]
6091 | wxWindowMSW::HandleMouseWheel(wxMouseWheelAxis axis,
| ~~~~~~~~~~~~~~~~~^~~~
make: *** [Makefile:30751: corelib_msw_window.o] Error 1
```
Add `wxUSE_STATTEXT` and `wxUSE_BUTTON` guards to `src/generic/msgdlgg.cpp`
Without this patch these compilation errors were encountered:
```
$WXWIN/build-debug/bk-deps g++ -c -o corelib_msgdlgg.o -I$WXWIN/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/generic/msgdlgg.cpp
../src/generic/msgdlgg.cpp:46:35: error: invalid use of incomplete type 'class wxTextSizerWrapper'
46 | class wxTitleTextWrapper : public wxTextSizerWrapper
| ^~~~~~~~~~~~~~~~~~
In file included from ../src/generic/msgdlgg.cpp:17:
../include/wx/dialog.h:24:7: note: forward declaration of 'class wxTextSizerWrapper'
24 | class wxTextSizerWrapper;
| ^~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:55:23: error: 'virtual wxWindow* wxTitleTextWrapper::OnCreateLine(const wxString&)' marked 'override', but does not override
55 | virtual wxWindow *OnCreateLine(const wxString& s) override
| ^~~~~~~~~~~~
../src/generic/msgdlgg.cpp: In constructor 'wxTitleTextWrapper::wxTitleTextWrapper(wxWindow*)':
../src/generic/msgdlgg.cpp:50:11: error: type 'wxTextSizerWrapper' is not a direct base of 'wxTitleTextWrapper'
50 | : wxTextSizerWrapper(win)
| ^~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp: In member function 'virtual wxWindow* wxTitleTextWrapper::OnCreateLine(const wxString&)':
../src/generic/msgdlgg.cpp:57:52: error: incomplete type 'wxTextSizerWrapper' used in nested name specifier
57 | wxWindow * const win = wxTextSizerWrapper::OnCreateLine(s);
| ^~~~~~~~~~~~
../src/generic/msgdlgg.cpp: In member function 'wxSizer* wxGenericMessageDialog::CreateMsgDlgButtonSizer()':
../src/generic/msgdlgg.cpp:96:55: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
96 | wxStdDialogButtonSizer * const sizerStd = new wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:102:68: error: invalid use of incomplete type 'class wxButton'
102 | btnDef = new wxButton(this, wxID_OK, GetCustomOKLabel());
| ^
In file included from ../include/wx/window.h:2034,
from ../include/wx/nonownedwnd.h:13,
from ../include/wx/toplevel.h:19,
from ../include/wx/dialog.h:13:
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:103:21: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
103 | sizerStd->AddButton(btnDef);
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:109:80: error: invalid use of incomplete type 'class wxButton'
109 | cancel = new wxButton(this, wxID_CANCEL, GetCustomCancelLabel());
| ^
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:110:21: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
110 | sizerStd->AddButton(cancel);
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:119:71: error: invalid use of incomplete type 'class wxButton'
119 | yes = new wxButton(this, wxID_YES, GetCustomYesLabel());
| ^
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:120:21: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
120 | sizerStd->AddButton(yes);
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:123:68: error: invalid use of incomplete type 'class wxButton'
123 | no = new wxButton(this, wxID_NO, GetCustomNoLabel());
| ^
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:124:21: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
124 | sizerStd->AddButton(no);
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:134:74: error: invalid use of incomplete type 'class wxButton'
134 | help = new wxButton(this, wxID_HELP, GetCustomHelpLabel());
| ^
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:135:21: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
135 | sizerStd->AddButton(help);
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:140:19: error: invalid use of incomplete type 'class wxButton'
140 | btnDef->SetDefault();
| ^~
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:141:19: error: invalid use of incomplete type 'class wxButton'
141 | btnDef->SetFocus();
| ^~
../include/wx/msw/window.h:17:28: note: forward declaration of 'class wxButton'
17 | class WXDLLIMPEXP_FWD_CORE wxButton;
| ^~~~~~~~
../src/generic/msgdlgg.cpp:144:17: error: invalid use of incomplete type 'class wxStdDialogButtonSizer'
144 | sizerStd->Realize();
| ^~
../include/wx/dialog.h:18:28: note: forward declaration of 'class wxStdDialogButtonSizer'
18 | class WXDLLIMPEXP_FWD_CORE wxStdDialogButtonSizer;
| ^~~~~~~~~~~~~~~~~~~~~~
../src/generic/msgdlgg.cpp:146:37: error: cannot convert 'wxStdDialogButtonSizer* const' to 'wxSizer*'
146 | return CreateSeparatedSizer(sizerStd);
| ^~~~~~~~
| |
| wxStdDialogButtonSizer* const
../include/wx/dialog.h:151:44: note: initializing argument 1 of 'wxSizer* wxDialogBase::CreateSeparatedSizer(wxSizer* '
151 | wxSizer *CreateSeparatedSizer(wxSizer *sizer);
| ~~~~~~~~~^~~~~
../src/generic/msgdlgg.cpp: In member function 'void wxGenericMessageDialog::DoCreateMsgdialog()':
../src/generic/msgdlgg.cpp:163:17: warning: unused variable 'icon_text' [-Wunused-variable]
163 | wxBoxSizer *icon_text = new wxBoxSizer( wxHORIZONTAL );
| ^~~~~~~~~
make: *** [Makefile:32587: corelib_msgdlgg.o] Error 1
```
Add `wxUSE_MENUS` guards in src/msw/toplevel.cpp
Without this patch a minimal MSW build fails with:
```
$WXWIN/build-debug/bk-deps g++ -c -o corelib_msw_toplevel.o -I$WXWIN/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/msw/toplevel.cpp
../src/msw/toplevel.cpp: In member function 'virtual WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM)':
../src/msw/toplevel.cpp:316:38: error: invalid use of incomplete type 'class wxMenu'
316 | if ( m_menuSystem->MSWCommand(0 /* unused anyhow */, id) )
| ^~
In file included from ../include/wx/window.h:18,
from ../include/wx/nonownedwnd.h:13,
from ../include/wx/toplevel.h:19,
from ../src/msw/toplevel.cpp:22:
../include/wx/event.h:49:32: note: forward declaration of 'class wxMenu'
49 | class WXDLLIMPEXP_FWD_CORE wxMenu;
| ^~~~~~
../src/msw/toplevel.cpp: In destructor 'virtual wxTopLevelWindowMSW::~wxTopLevelWindowMSW()':
../src/msw/toplevel.cpp:520:5: warning: possible problem detected in invocation of 'operator delete' [-Wdelete-incomplete]
520 | delete m_menuSystem;
| ^~~~~~~~~~~~~~~~~~~
/home/t_17_/source/repos/wxWidgets/build-debug/bk-deps g++ -c -o corelib_uxtheme.o -IC:/Users/t_17_/source/repos/wxWidgets/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/msw/uxtheme.cpp
../src/msw/toplevel.cpp:520:12: warning: invalid use of incomplete type 'class wxMenu'
520 | delete m_menuSystem;
| ^~~~~~~~~~~~
../include/wx/event.h:49:32: note: forward declaration of 'class wxMenu'
49 | class WXDLLIMPEXP_FWD_CORE wxMenu;
| ^~~~~~
../src/msw/toplevel.cpp:520:5: note: neither the destructor nor the class-specific 'operator delete' will be called, even if they are declared when the class is defined
520 | delete m_menuSystem;
| ^~~~~~~~~~~~~~~~~~~
../src/msw/toplevel.cpp: In member function 'wxMenu* wxTopLevelWindowMSW::MSWGetSystemMenu() const':
../src/msw/toplevel.cpp:1230:38: error: incomplete type 'wxMenu' used in nested name specifier
1230 | self->m_menuSystem = wxMenu::MSWNewFromHMENU(hmenu);
| ^~~~~~~~~~~~~~~
../src/msw/toplevel.cpp:1241:21: error: invalid use of incomplete type 'class wxMenu'
1241 | m_menuSystem->SetInvokingWindow(self);
| ^~
../include/wx/event.h:49:32: note: forward declaration of 'class wxMenu'
49 | class WXDLLIMPEXP_FWD_CORE wxMenu;
| ^~~~~~
make: *** [Makefile:30739: corelib_msw_toplevel.o] Error 1
```
Add `wxUSE_MENUBAR` guards to src/msw/frame.cpp
Without this patch the minimal MSW build fails with the following error:
```
$WXWIN/build-debug/bk-deps g++ -c -o corelib_msw_frame.o -I$WXWIN/build-debug/lib/wx/include/msw-unicode-static-3.3 -I../include -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -DWXBUILDING -DwxUSE_BASE=0 -Wall -Wundef -Wunused-parameter -Wno-ctor-dtor-privacy -Woverloaded-virtual -g -O0 ../src/msw/frame.cpp
../src/msw/frame.cpp: In member function 'virtual WXLRESULT wxFrame::MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM)':
../src/msw/frame.cpp:907:10: error: 'GetMenuBar' was not declared in this scope; did you mean 'GetMenu'?
907 | if ( GetMenuBar() &&
| ^~~~~~~~~~
| GetMenu
../src/msw/frame.cpp:947:18: error: 'wxMenuBar' was not declared in this scope; did you mean 'wxMenu'?
947 | if ( wxMenuBar* mbar = GetMenuBar() )
| ^~~~~~~~~
| wxMenu
../src/msw/frame.cpp:947:29: error: 'mbar' was not declared in this scope
947 | if ( wxMenuBar* mbar = GetMenuBar() )
| ^~~~
../src/msw/frame.cpp:947:36: error: 'GetMenuBar' was not declared in this scope; did you mean 'GetMenu'?
947 | if ( wxMenuBar* mbar = GetMenuBar() )
| ^~~~~~~~~~
| GetMenu
make: *** [Makefile:29134: corelib_msw_frame.o] Error 1
```
Add `wxHAS_ANY_BUTTON` guards to src/msw/msgdlg.cpp
Without these the minimal MSW static-build succeeds, but then this
simple app:
```cpp
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString & title)
: wxFrame(NULL, wxID_ANY, title)
{}
private:
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
wxEND_EVENT_TABLE()
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame("My first WxWidgets App"))->Show(true);
return true;
}
};
wxDECLARE_APP(MyApp);
wxIMPLEMENT_APP(MyApp);
```
fails to link with this error:
```
$ g++ $($WXWIN/build-debug/wx-config --cxxflags) test.cpp $($WXWIN/build-debug/wx-config --libs)
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: $WXWIN/build-debug/lib/libwx_mswu_core-3.3.a(corelib_msw_msgdlg.o): in function `wxMessageDialog::AdjustButtonLabels()':
$WXWIN\build-debug/../src/msw/msgdlg.cpp:312:(.text+0xeb5): undefined reference to `wxMSWButton::GetFittingSize(wxWindow*, wxSize const&, int)'
collect2.exe: error: ld returned 1 exit status
```
Define gs_windowDisablers outside "#if wxUSE_MENUS" check This variable is not related to the menus and should be defined even if menus support is turned off. Also move ShouldUpdateMenuFromIdle() near the other menu-related functions instead of having it defined near the top of the file. This commit is best viewed with Git --color-moved option. See #26323.
Merge branch 'fix-minimal-msw-build' of github.com:tanzislam/wxWidgets Fixes for minimal wxMSW build with most features disabled. See #26323.
Stop reading past wxCharBuffer end on unterminated XPM quote The quote-stripping loop in wxXPMDecoder::ReadFile() sets p = q + 1 after strncpy(). If the closing " was missing, q stopped at the buffer terminator, so p ended up one past it and the outer for-loop's p++ then dereferenced two bytes off the end of the wxCharBuffer. Mirror the already-existing /*-comment treatment and break out of the loop when *q == '\0'. Closes #26499.
Fix static order initialization problem in wxCSConv wxCSConv::wxCSConv() called during global variables initialization could use the yet uninitialized global gs_nameCache. Fix this in the usual way, by wrapping the global in a function to ensure that it is always initialized before being used.
Fix user scaling in SVG sample Add missing conversion to the device units for the SVG view box. Closes #26396. Closes #26500.
Reject GIF files with LZW minimum code size > 11 The minimum code size byte that follows the local colour table in wxGIFDecoder::LoadGIF() is only checked for <= 0. dgif() sizes ab_prefix/ab_tail with allocSize = 4096 + 1, so a value of 12 starts ab_free at 4098 and the first alphabet update at gifdecod.cpp:457 writes one entry past the end of both arrays. The existing wxASSERT(ab_free < allocSize) already flagged this in debug builds. The new wxImage::BadGIFLZWMinCodeSize test feeds a 37-byte 2x1 GIF with code size 12 to LoadFile and asserts it is rejected. Closes #26501.
Fix memory leak when loading invalid GIF files This was already attempted back in 56ba039411 (fixed memory leaks when reading invalid GIFs, 2007-03-30) but the cleanup guard added there didn't really fix anything as we need to free memory in GIFImage, not wxGIFDecoder itself. Really fix this now by calling the newly added GIFImage::Free() and not wxGIFDecoder::Destroy(), which will be called by the dtor anyhow, on error. See #26501.
| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | |
| 14 | 14 | #include "wx/defs.h"
|
| 15 | 15 | #include "wx/gdiobj.h"
|
| 16 | +#include "wx/string.h"
|
|
| 16 | 17 | #include "wx/variant.h"
|
| 17 | 18 | |
| 18 | 19 | class WXDLLIMPEXP_FWD_CORE wxColour;
|
| ... | ... | @@ -889,7 +889,9 @@ bool MyPage::OnSave(const wxString& filename) |
| 889 | 889 | wxSVGFileDC tempSvgDC(svgSize);
|
| 890 | 890 | OnDraw(tempSvgDC);
|
| 891 | 891 | |
| 892 | - svgSize = wxSize(tempSvgDC.MaxX(), tempSvgDC.MaxY());
|
|
| 892 | + // MaxX()/MaxY() return logical units, but the SVG viewBox is in device units.
|
|
| 893 | + svgSize = wxSize(tempSvgDC.LogicalToDeviceX(tempSvgDC.MaxX()),
|
|
| 894 | + tempSvgDC.LogicalToDeviceY(tempSvgDC.MaxY()));
|
|
| 893 | 895 | svgSize.IncBy(15); // account for wxPen width exceeding bounds
|
| 894 | 896 | |
| 895 | 897 | wxSVGFileDC svgDC(svgSize, filename, pageNames[m_index]);
|
| ... | ... | @@ -51,6 +51,8 @@ wxBEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow) |
| 51 | 51 | #endif // wxUSE_STATUSBAR
|
| 52 | 52 | wxEND_EVENT_TABLE()
|
| 53 | 53 | |
| 54 | +#endif // wxUSE_MENUS
|
|
| 55 | + |
|
| 54 | 56 | // ----------------------------------------------------------------------------
|
| 55 | 57 | // globals
|
| 56 | 58 | // ----------------------------------------------------------------------------
|
| ... | ... | @@ -62,24 +64,6 @@ namespace |
| 62 | 64 | std::stack<wxWindowDisabler> gs_windowDisablers;
|
| 63 | 65 | } // anonymous namespace
|
| 64 | 66 | |
| 65 | -/* static */
|
|
| 66 | -bool wxFrameBase::ShouldUpdateMenuFromIdle()
|
|
| 67 | -{
|
|
| 68 | - // Usually this is determined at compile time and is determined by whether
|
|
| 69 | - // the platform supports wxEVT_MENU_OPEN, however in wxGTK we need to also
|
|
| 70 | - // check if we're using the global menu bar as we don't get EVT_MENU_OPEN
|
|
| 71 | - // for it and need to fall back to idle time updating even if normally
|
|
| 72 | - // wxUSE_IDLEMENUUPDATES is set to 0 for wxGTK.
|
|
| 73 | -#ifdef __WXGTK__
|
|
| 74 | - if ( wxApp::GTKIsUsingGlobalMenu() )
|
|
| 75 | - return true;
|
|
| 76 | -#endif // !__WXGTK__
|
|
| 77 | - |
|
| 78 | - return wxUSE_IDLEMENUUPDATES != 0;
|
|
| 79 | -}
|
|
| 80 | - |
|
| 81 | -#endif // wxUSE_MENUS
|
|
| 82 | - |
|
| 83 | 67 | // ============================================================================
|
| 84 | 68 | // implementation
|
| 85 | 69 | // ============================================================================
|
| ... | ... | @@ -418,6 +402,22 @@ void wxFrameBase::UpdateWindowUI(long flags) |
| 418 | 402 | |
| 419 | 403 | #if wxUSE_MENUS
|
| 420 | 404 | |
| 405 | +/* static */
|
|
| 406 | +bool wxFrameBase::ShouldUpdateMenuFromIdle()
|
|
| 407 | +{
|
|
| 408 | + // Usually this is determined at compile time and is determined by whether
|
|
| 409 | + // the platform supports wxEVT_MENU_OPEN, however in wxGTK we need to also
|
|
| 410 | + // check if we're using the global menu bar as we don't get EVT_MENU_OPEN
|
|
| 411 | + // for it and need to fall back to idle time updating even if normally
|
|
| 412 | + // wxUSE_IDLEMENUUPDATES is set to 0 for wxGTK.
|
|
| 413 | +#ifdef __WXGTK__
|
|
| 414 | + if ( wxApp::GTKIsUsingGlobalMenu() )
|
|
| 415 | + return true;
|
|
| 416 | +#endif // !__WXGTK__
|
|
| 417 | + |
|
| 418 | + return wxUSE_IDLEMENUUPDATES != 0;
|
|
| 419 | +}
|
|
| 420 | + |
|
| 421 | 421 | void wxFrameBase::OnMenuOpen(wxMenuEvent& event)
|
| 422 | 422 | {
|
| 423 | 423 | event.Skip();
|
| ... | ... | @@ -51,6 +51,15 @@ public: |
| 51 | 51 | // def ctor
|
| 52 | 52 | GIFImage();
|
| 53 | 53 | |
| 54 | + // Normally this class does _not_ free its memory as it is owned by
|
|
| 55 | + // wxGIFDecoder, but this function can be used to do it if an error happens
|
|
| 56 | + // before the image is added to the decoder.
|
|
| 57 | + void Free()
|
|
| 58 | + {
|
|
| 59 | + free(p);
|
|
| 60 | + free(pal);
|
|
| 61 | + }
|
|
| 62 | + |
|
| 54 | 63 | unsigned int w; // width
|
| 55 | 64 | unsigned int h; // height
|
| 56 | 65 | unsigned int left; // x coord (in logical screen)
|
| ... | ... | @@ -780,11 +789,11 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream) |
| 780 | 789 | // allocate memory for IMAGEN struct
|
| 781 | 790 | std::unique_ptr<GIFImage> pimg(new GIFImage());
|
| 782 | 791 | |
| 783 | - wxScopeGuard guardDestroy = wxMakeObjGuard(*this, &wxGIFDecoder::Destroy);
|
|
| 784 | - |
|
| 785 | 792 | if ( !pimg.get() )
|
| 786 | 793 | return wxGIF_MEMERR;
|
| 787 | 794 | |
| 795 | + wxScopeGuard guardDestroy = wxMakeObjGuard(*pimg, &GIFImage::Free);
|
|
| 796 | + |
|
| 788 | 797 | // fill in the data
|
| 789 | 798 | static const unsigned int idbSize = (2 + 2 + 2 + 2 + 1);
|
| 790 | 799 | stream.Read(buf, idbSize);
|
| ... | ... | @@ -859,7 +868,11 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream) |
| 859 | 868 | |
| 860 | 869 | // get initial code size from first byte in raster data
|
| 861 | 870 | bits = stream.GetC();
|
| 862 | - if (stream.Eof() || bits <= 0)
|
|
| 871 | + // dgif() sizes the LZW tables for codes up to 12 bits, so a
|
|
| 872 | + // minimum code size of 12 or more would start ab_free past the
|
|
| 873 | + // end of ab_prefix/ab_tail and corrupt the heap on the first
|
|
| 874 | + // alphabet update.
|
|
| 875 | + if (stream.Eof() || bits <= 0 || bits > 11)
|
|
| 863 | 876 | return wxGIF_INVFORMAT;
|
| 864 | 877 | |
| 865 | 878 | // decode image
|
| ... | ... | @@ -3051,7 +3051,11 @@ namespace std |
| 3051 | 3051 | |
| 3052 | 3052 | using wxEncodingNameCache = std::unordered_map<wxFontEncoding, wxString>;
|
| 3053 | 3053 | |
| 3054 | -static wxEncodingNameCache gs_nameCache;
|
|
| 3054 | +wxEncodingNameCache& GetEncodingNameCache()
|
|
| 3055 | +{
|
|
| 3056 | + static wxEncodingNameCache s_nameCache;
|
|
| 3057 | + return s_nameCache;
|
|
| 3058 | +}
|
|
| 3055 | 3059 | #endif
|
| 3056 | 3060 | |
| 3057 | 3061 | wxMBConv *wxCSConv::DoCreate() const
|
| ... | ... | @@ -3105,8 +3109,9 @@ wxMBConv *wxCSConv::DoCreate() const |
| 3105 | 3109 | }
|
| 3106 | 3110 | #if wxUSE_FONTMAP
|
| 3107 | 3111 | {
|
| 3108 | - const wxEncodingNameCache::iterator it = gs_nameCache.find(encoding);
|
|
| 3109 | - if ( it != gs_nameCache.end() )
|
|
| 3112 | + auto& nameCache = GetEncodingNameCache();
|
|
| 3113 | + const wxEncodingNameCache::iterator it = nameCache.find(encoding);
|
|
| 3114 | + if ( it != nameCache.end() )
|
|
| 3110 | 3115 | {
|
| 3111 | 3116 | if ( it->second.empty() )
|
| 3112 | 3117 | return nullptr;
|
| ... | ... | @@ -3134,14 +3139,14 @@ wxMBConv *wxCSConv::DoCreate() const |
| 3134 | 3139 | wxMBConv_iconv *conv = new wxMBConv_iconv(name.ToAscii());
|
| 3135 | 3140 | if ( conv->IsOk() )
|
| 3136 | 3141 | {
|
| 3137 | - gs_nameCache[encoding] = *names;
|
|
| 3142 | + nameCache[encoding] = *names;
|
|
| 3138 | 3143 | return conv;
|
| 3139 | 3144 | }
|
| 3140 | 3145 | |
| 3141 | 3146 | delete conv;
|
| 3142 | 3147 | }
|
| 3143 | 3148 | |
| 3144 | - gs_nameCache[encoding] = wxT(""); // cache the failure
|
|
| 3149 | + nameCache[encoding] = wxT(""); // cache the failure
|
|
| 3145 | 3150 | }
|
| 3146 | 3151 | }
|
| 3147 | 3152 | #endif // wxUSE_FONTMAP
|
| ... | ... | @@ -190,6 +190,12 @@ wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) |
| 190 | 190 | for (q = p + 1; *q != '\0'; q++)
|
| 191 | 191 | if (*q == '"')
|
| 192 | 192 | break;
|
| 193 | + |
|
| 194 | + // unterminated quoted string: stop processing rather than reading
|
|
| 195 | + // past the end of the buffer when the outer loop next advances p.
|
|
| 196 | + if (*q == '\0')
|
|
| 197 | + break;
|
|
| 198 | + |
|
| 193 | 199 | strncpy(xpm_buffer + i, p + 1, q - p - 1);
|
| 194 | 200 | i += q - p - 1;
|
| 195 | 201 | xpm_buffer[i++] = '\n';
|
| ... | ... | @@ -39,6 +39,7 @@ |
| 39 | 39 | #include "wx/statline.h"
|
| 40 | 40 | #endif
|
| 41 | 41 | |
| 42 | +#if wxUSE_STATTEXT
|
|
| 42 | 43 | // ----------------------------------------------------------------------------
|
| 43 | 44 | // wxTitleTextWrapper: simple class to create wrapped text in "title font"
|
| 44 | 45 | // ----------------------------------------------------------------------------
|
| ... | ... | @@ -61,6 +62,7 @@ protected: |
| 61 | 62 | return win;
|
| 62 | 63 | }
|
| 63 | 64 | };
|
| 65 | +#endif // wxUSE_STATTEXT
|
|
| 64 | 66 | |
| 65 | 67 | // ----------------------------------------------------------------------------
|
| 66 | 68 | // icons
|
| ... | ... | @@ -101,6 +103,7 @@ wxGenericMessageDialog::wxGenericMessageDialog( wxWindow *parent, |
| 101 | 103 | wxGCC_WARNING_RESTORE(maybe-uninitialized)
|
| 102 | 104 | #endif
|
| 103 | 105 | |
| 106 | +#if wxUSE_BUTTON
|
|
| 104 | 107 | wxSizer *wxGenericMessageDialog::CreateMsgDlgButtonSizer()
|
| 105 | 108 | {
|
| 106 | 109 | if ( HasCustomLabels() )
|
| ... | ... | @@ -165,6 +168,7 @@ wxSizer *wxGenericMessageDialog::CreateMsgDlgButtonSizer() |
| 165 | 168 | wxNO_DEFAULT | wxCANCEL_DEFAULT)
|
| 166 | 169 | );
|
| 167 | 170 | }
|
| 171 | +#endif // wxUSE_BUTTON
|
|
| 168 | 172 | |
| 169 | 173 | void wxGenericMessageDialog::DoCreateMsgdialog()
|
| 170 | 174 | {
|
| ... | ... | @@ -229,10 +233,12 @@ void wxGenericMessageDialog::DoCreateMsgdialog() |
| 229 | 233 | AddMessageDialogCheckBox( topsizer );
|
| 230 | 234 | AddMessageDialogDetails( topsizer );
|
| 231 | 235 | |
| 236 | +#if wxUSE_BUTTON
|
|
| 232 | 237 | // 4) buttons
|
| 233 | 238 | wxSizer *sizerBtn = CreateMsgDlgButtonSizer();
|
| 234 | 239 | if ( sizerBtn )
|
| 235 | 240 | topsizer->Add(sizerBtn, 0, wxEXPAND | wxALL, 10 );
|
| 241 | +#endif // wxUSE_BUTTON
|
|
| 236 | 242 | |
| 237 | 243 | SetSizer( topsizer );
|
| 238 | 244 |
| ... | ... | @@ -913,11 +913,13 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara |
| 913 | 913 | WXLRESULT rc = 0;
|
| 914 | 914 | bool processed = false;
|
| 915 | 915 | |
| 916 | +#if wxUSE_MENUBAR
|
|
| 916 | 917 | if ( GetMenuBar() &&
|
| 917 | 918 | HandleMenuMessage(&rc, this, message, wParam, lParam) )
|
| 918 | 919 | {
|
| 919 | 920 | return rc;
|
| 920 | 921 | }
|
| 922 | +#endif // wxUSE_MENUBAR
|
|
| 921 | 923 | |
| 922 | 924 | switch ( message )
|
| 923 | 925 | {
|
| ... | ... | @@ -949,6 +951,7 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara |
| 949 | 951 | }
|
| 950 | 952 | break;
|
| 951 | 953 | |
| 954 | +#if wxUSE_MENUBAR
|
|
| 952 | 955 | case WM_INITMENUPOPUP:
|
| 953 | 956 | case WM_UNINITMENUPOPUP:
|
| 954 | 957 | // We get these messages from the menu bar even if the menu is
|
| ... | ... | @@ -964,6 +967,7 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara |
| 964 | 967 | }
|
| 965 | 968 | }
|
| 966 | 969 | break;
|
| 970 | +#endif // wxUSE_MENUBAR
|
|
| 967 | 971 | |
| 968 | 972 | case WM_QUERYDRAGICON:
|
| 969 | 973 | {
|
| ... | ... | @@ -121,10 +121,12 @@ wxMessageDialog::HookFunction(int code, WXWPARAM wParam, WXLPARAM lParam) |
| 121 | 121 | // too big to fit the display
|
| 122 | 122 | wnd->ReplaceStaticWithEdit();
|
| 123 | 123 | |
| 124 | +#ifdef wxHAS_ANY_BUTTON
|
|
| 124 | 125 | // update the labels if necessary: we need to do it before centering
|
| 125 | 126 | // the dialog as this can change its size
|
| 126 | 127 | if ( wnd->HasCustomLabels() )
|
| 127 | 128 | wnd->AdjustButtonLabels();
|
| 129 | +#endif // wxHAS_ANY_BUTTON
|
|
| 128 | 130 | |
| 129 | 131 | // centre the message box on its parent if requested
|
| 130 | 132 | if ( wnd->GetMessageDialogStyle() & wxCENTER )
|
| ... | ... | @@ -262,6 +264,7 @@ void wxMessageDialog::ReplaceStaticWithEdit() |
| 262 | 264 | }
|
| 263 | 265 | }
|
| 264 | 266 | |
| 267 | +#ifdef wxHAS_ANY_BUTTON
|
|
| 265 | 268 | void wxMessageDialog::AdjustButtonLabels()
|
| 266 | 269 | {
|
| 267 | 270 | // changing the button labels is the easy part but we also need to ensure
|
| ... | ... | @@ -371,6 +374,7 @@ void wxMessageDialog::AdjustButtonLabels() |
| 371 | 374 | rcBtn.right += wBtnNew + MARGIN_INNER;
|
| 372 | 375 | }
|
| 373 | 376 | }
|
| 377 | +#endif // wxHAS_ANY_BUTTON
|
|
| 374 | 378 | |
| 375 | 379 | /* static */
|
| 376 | 380 | wxFont wxMessageDialog::GetMessageFont()
|
| ... | ... | @@ -306,6 +306,7 @@ WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WX |
| 306 | 306 | }
|
| 307 | 307 | |
| 308 | 308 | #ifndef __WXUNIVERSAL__
|
| 309 | +#if wxUSE_MENUS
|
|
| 309 | 310 | // We need to generate events for the custom items added to the
|
| 310 | 311 | // system menu if it had been created (and presumably modified).
|
| 311 | 312 | // As SC_SIZE is the first of the system-defined commands, we
|
| ... | ... | @@ -316,6 +317,7 @@ WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WX |
| 316 | 317 | if ( m_menuSystem->MSWCommand(0 /* unused anyhow */, id) )
|
| 317 | 318 | processed = true;
|
| 318 | 319 | }
|
| 320 | +#endif // wxUSE_MENUS
|
|
| 319 | 321 | #endif // #ifndef __WXUNIVERSAL__
|
| 320 | 322 | }
|
| 321 | 323 | break;
|
| ... | ... | @@ -517,7 +519,9 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, |
| 517 | 519 | |
| 518 | 520 | wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
|
| 519 | 521 | {
|
| 522 | +#if wxUSE_MENUS
|
|
| 520 | 523 | delete m_menuSystem;
|
| 524 | +#endif // wxUSE_MENUS
|
|
| 521 | 525 | |
| 522 | 526 | SendDestroyEvent();
|
| 523 | 527 | }
|
| ... | ... | @@ -1221,6 +1225,7 @@ void wxTopLevelWindowMSW::RequestUserAttention(int flags) |
| 1221 | 1225 | wxMenu *wxTopLevelWindowMSW::MSWGetSystemMenu() const
|
| 1222 | 1226 | {
|
| 1223 | 1227 | #ifndef __WXUNIVERSAL__
|
| 1228 | +#if wxUSE_MENUS
|
|
| 1224 | 1229 | if ( !m_menuSystem )
|
| 1225 | 1230 | {
|
| 1226 | 1231 | HMENU hmenu = ::GetSystemMenu(GetHwnd(), FALSE);
|
| ... | ... | @@ -1246,6 +1251,7 @@ wxMenu *wxTopLevelWindowMSW::MSWGetSystemMenu() const |
| 1246 | 1251 | // correct but doesn't seem to have any serious drawbacks.
|
| 1247 | 1252 | m_menuSystem->SetInvokingWindow(self);
|
| 1248 | 1253 | }
|
| 1254 | +#endif // wxUSE_MENUS
|
|
| 1249 | 1255 | #endif // #ifndef __WXUNIVERSAL__
|
| 1250 | 1256 | |
| 1251 | 1257 | return m_menuSystem;
|
| ... | ... | @@ -93,6 +93,10 @@ |
| 93 | 93 | #include "wx/caret.h"
|
| 94 | 94 | #endif // wxUSE_CARET
|
| 95 | 95 | |
| 96 | +#if wxUSE_CONTROLS
|
|
| 97 | + #include "wx/control.h"
|
|
| 98 | +#endif // wxUSE_CONTROLS
|
|
| 99 | + |
|
| 96 | 100 | #if wxUSE_SPINCTRL
|
| 97 | 101 | #include "wx/spinctrl.h"
|
| 98 | 102 | #endif // wxUSE_SPINCTRL
|
| ... | ... | @@ -1310,6 +1310,33 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadGIF", "[image][gif][error]") |
| 1310 | 1310 | CHECK( image.GetSize() == wxSize(1200, 800) );
|
| 1311 | 1311 | }
|
| 1312 | 1312 | |
| 1313 | +TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadGIFLZWMinCodeSize",
|
|
| 1314 | + "[image][gif][error]")
|
|
| 1315 | +{
|
|
| 1316 | + // The LZW minimum code size byte that follows the local colour table is
|
|
| 1317 | + // not validated. dgif() sizes ab_prefix/ab_tail for codes up to 12 bits
|
|
| 1318 | + // (allocSize == 4096+1), so a code size of 12 makes ab_free start at 4098
|
|
| 1319 | + // and the first alphabet update then writes one entry past the end of
|
|
| 1320 | + // both arrays. The 2x1 image below is the minimum needed to exercise the
|
|
| 1321 | + // second LZW iteration where the alphabet update happens.
|
|
| 1322 | + static const unsigned char data[] =
|
|
| 1323 | + {
|
|
| 1324 | + 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // "GIF89a"
|
|
| 1325 | + 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // LSDB: 2x1, no GCT
|
|
| 1326 | + 0x2c, // image separator
|
|
| 1327 | + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, // 2x1 frame at 0,0
|
|
| 1328 | + 0x80, // LCT, depth=0 (2 col)
|
|
| 1329 | + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, // LCT entries
|
|
| 1330 | + 0x0c, // LZW min code size=12
|
|
| 1331 | + 0x04, 0x00, 0x20, 0x00, 0x00, // sub-block: codes 0,1
|
|
| 1332 | + 0x00, // sub-block terminator
|
|
| 1333 | + 0x3b, // trailer
|
|
| 1334 | + };
|
|
| 1335 | + wxMemoryInputStream mis(data, WXSIZEOF(data));
|
|
| 1336 | + wxImage img;
|
|
| 1337 | + REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_GIF) );
|
|
| 1338 | +}
|
|
| 1339 | + |
|
| 1313 | 1340 | #endif // wxUSE_GIF
|
| 1314 | 1341 | |
| 1315 | 1342 | #if wxUSE_PCX
|
| ... | ... | @@ -1361,6 +1388,22 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadXPM", "[image][xpm][error]") |
| 1361 | 1388 | REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_XPM) );
|
| 1362 | 1389 | }
|
| 1363 | 1390 | |
| 1391 | +TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadXPMUnterminatedQuote",
|
|
| 1392 | + "[image][xpm][error]")
|
|
| 1393 | +{
|
|
| 1394 | + // A payload whose final " is never closed: the quote-stripping loop in
|
|
| 1395 | + // wxXPMDecoder::ReadFile() advanced p past the buffer terminator after
|
|
| 1396 | + // strncpy() and then dereferenced one byte further on the next outer
|
|
| 1397 | + // for-loop iteration, reading past the end of the wxCharBuffer.
|
|
| 1398 | + static const unsigned char data[] =
|
|
| 1399 | + {
|
|
| 1400 | + 0x22,0x61,0x62,0x63,
|
|
| 1401 | + };
|
|
| 1402 | + wxMemoryInputStream mis(data, WXSIZEOF(data));
|
|
| 1403 | + wxImage img;
|
|
| 1404 | + REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_XPM) );
|
|
| 1405 | +}
|
|
| 1406 | + |
|
| 1364 | 1407 | #endif // wxUSE_XPM
|
| 1365 | 1408 | |
| 1366 | 1409 | #if wxUSE_IFF
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help