]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/rendcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / rendcmn.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/rendcmn.cpp
3// Purpose: wxRendererNative common functions
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 28.07.03
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/app.h"
28 #include "wx/log.h"
29 #include "wx/intl.h"
30#endif //WX_PRECOMP
31
32#include "wx/apptrait.h"
33#include "wx/renderer.h"
34
35#include "wx/scopedptr.h"
36
37#if wxUSE_DYNLIB_CLASS
38 #include "wx/dynlib.h"
39#endif // wxUSE_DYNLIB_CLASS
40
41// ----------------------------------------------------------------------------
42// wxRendererPtr: auto pointer holding the global renderer
43// ----------------------------------------------------------------------------
44
45typedef wxScopedPtr<wxRendererNative> wxRendererPtrBase;
46
47class wxRendererPtr : public wxRendererPtrBase
48{
49public:
50 // return true if we have a renderer, false otherwise
51 bool IsOk()
52 {
53 if ( !m_initialized )
54 {
55 // only try to create the renderer once
56 m_initialized = true;
57
58 DoInit();
59 }
60
61 return get() != NULL;
62 }
63
64 // return the global and unique wxRendererPtr
65 static wxRendererPtr& Get();
66
67private:
68 wxRendererPtr() : wxRendererPtrBase(NULL) { m_initialized = false; }
69
70 void DoInit()
71 {
72 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
73 if ( traits )
74 {
75 // ask the traits object to create a renderer for us
76 reset(traits->CreateRenderer());
77 }
78 }
79
80 bool m_initialized;
81
82 // just to suppress a gcc warning
83 friend class wxRendererPtrDummyFriend;
84
85 wxDECLARE_NO_COPY_CLASS(wxRendererPtr);
86};
87
88// return the global and unique wxRendererPtr
89/*static*/ wxRendererPtr& wxRendererPtr::Get()
90{
91 static wxRendererPtr s_renderer;
92
93 return s_renderer;
94}
95
96#if wxUSE_DYNLIB_CLASS
97
98// ----------------------------------------------------------------------------
99// wxRendererFromDynLib: represents a renderer dynamically loaded from a DLL
100// ----------------------------------------------------------------------------
101
102class wxRendererFromDynLib : public wxDelegateRendererNative
103{
104public:
105 // create the object wrapping the given renderer created from this DLL
106 //
107 // we take ownership of the pointer and will delete it (and also unload the
108 // DLL) when we're deleted
109 wxRendererFromDynLib(wxDynamicLibrary& dll, wxRendererNative *renderer)
110 : wxDelegateRendererNative(*renderer),
111 m_renderer(renderer),
112 m_dllHandle(dll.Detach())
113 {
114 }
115
116 virtual ~wxRendererFromDynLib()
117 {
118 delete m_renderer;
119 wxDynamicLibrary::Unload(m_dllHandle);
120 }
121
122private:
123 wxRendererNative *m_renderer;
124 wxDllType m_dllHandle;
125};
126
127#endif // wxUSE_DYNLIB_CLASS
128
129// ============================================================================
130// wxRendererNative implementation
131// ============================================================================
132
133wxRendererNative::~wxRendererNative()
134{
135 // empty but necessary
136}
137
138// ----------------------------------------------------------------------------
139// Managing the global renderer
140// ----------------------------------------------------------------------------
141
142/* static */
143wxRendererNative& wxRendererNative::Get()
144{
145 wxRendererPtr& renderer = wxRendererPtr::Get();
146
147 return renderer.IsOk() ? *renderer.get() : GetDefault();
148}
149
150/* static */
151wxRendererNative *wxRendererNative::Set(wxRendererNative *rendererNew)
152{
153 wxRendererPtr& renderer = wxRendererPtr::Get();
154
155 wxRendererNative *rendererOld = renderer.release();
156
157 renderer.reset(rendererNew);
158
159 return rendererOld;
160}
161
162
163// ----------------------------------------------------------------------------
164// Dynamic renderers loading
165// ----------------------------------------------------------------------------
166
167#if wxUSE_DYNLIB_CLASS
168
169/* static */
170wxRendererNative *wxRendererNative::Load(const wxString& name)
171{
172 wxString fullname = wxDynamicLibrary::CanonicalizePluginName(name);
173
174 wxDynamicLibrary dll(fullname);
175 if ( !dll.IsLoaded() )
176 return NULL;
177
178 // each theme DLL must export a wxCreateRenderer() function with this
179 // signature
180 typedef wxRendererNative *(*wxCreateRenderer_t)();
181
182 wxDYNLIB_FUNCTION(wxCreateRenderer_t, wxCreateRenderer, dll);
183 if ( !pfnwxCreateRenderer )
184 return NULL;
185
186 // create a renderer object
187 wxRendererNative *renderer = (*pfnwxCreateRenderer)();
188 if ( !renderer )
189 return NULL;
190
191 // check that its version is compatible with ours
192 wxRendererVersion ver = renderer->GetVersion();
193 if ( !wxRendererVersion::IsCompatible(ver) )
194 {
195 wxLogError(_("Renderer \"%s\" has incompatible version %d.%d and couldn't be loaded."),
196 name.c_str(), ver.version, ver.age);
197 delete renderer;
198
199 return NULL;
200 }
201
202 // finally wrap the renderer in an object which will delete it and unload
203 // the library when it is deleted and return it to the caller
204 return new wxRendererFromDynLib(dll, renderer);
205}
206
207#endif // wxUSE_DYNLIB_CLASS