]> git.saurik.com Git - wxWidgets.git/blob - src/common/ctrlsub.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / ctrlsub.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/ctrlsub.cpp
3 // Purpose: wxItemContainer implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 22.10.99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_CONTROLS
28
29 #ifndef WX_PRECOMP
30 #include "wx/ctrlsub.h"
31 #include "wx/arrstr.h"
32 #endif
33
34 IMPLEMENT_ABSTRACT_CLASS(wxControlWithItems, wxControl)
35
36 // ============================================================================
37 // wxItemContainerImmutable implementation
38 // ============================================================================
39
40 wxItemContainerImmutable::~wxItemContainerImmutable()
41 {
42 // this destructor is required for Darwin
43 }
44
45 // ----------------------------------------------------------------------------
46 // selection
47 // ----------------------------------------------------------------------------
48
49 wxString wxItemContainerImmutable::GetStringSelection() const
50 {
51 wxString s;
52
53 int sel = GetSelection();
54 if ( sel != wxNOT_FOUND )
55 s = GetString((unsigned int)sel);
56
57 return s;
58 }
59
60 bool wxItemContainerImmutable::SetStringSelection(const wxString& s)
61 {
62 const int sel = FindString(s);
63 if ( sel == wxNOT_FOUND )
64 return false;
65
66 SetSelection(sel);
67
68 return true;
69 }
70
71 wxArrayString wxItemContainerImmutable::GetStrings() const
72 {
73 wxArrayString result;
74
75 const unsigned int count = GetCount();
76 result.Alloc(count);
77 for ( unsigned int n = 0; n < count; n++ )
78 result.Add(GetString(n));
79
80 return result;
81 }
82
83 // ============================================================================
84 // wxItemContainer implementation
85 // ============================================================================
86
87 wxItemContainer::~wxItemContainer()
88 {
89 // this destructor is required for Darwin
90 }
91
92 // ----------------------------------------------------------------------------
93 // deleting items
94 // ----------------------------------------------------------------------------
95
96 void wxItemContainer::Clear()
97 {
98 if ( HasClientObjectData() )
99 {
100 const unsigned count = GetCount();
101 for ( unsigned i = 0; i < count; ++i )
102 ResetItemClientObject(i);
103 }
104
105 SetClientDataType(wxClientData_None);
106
107 DoClear();
108 }
109
110 void wxItemContainer::Delete(unsigned int pos)
111 {
112 wxCHECK_RET( pos < GetCount(), wxT("invalid index") );
113
114 if ( HasClientObjectData() )
115 ResetItemClientObject(pos);
116
117 DoDeleteOneItem(pos);
118
119 if ( IsEmpty() )
120 {
121 SetClientDataType(wxClientData_None);
122 }
123 }
124
125 // ----------------------------------------------------------------------------
126 //
127 // ----------------------------------------------------------------------------
128
129 int wxItemContainer::DoInsertItemsInLoop(const wxArrayStringsAdapter& items,
130 unsigned int pos,
131 void **clientData,
132 wxClientDataType type)
133 {
134 int n = wxNOT_FOUND;
135
136 const unsigned int count = items.GetCount();
137 for ( unsigned int i = 0; i < count; ++i )
138 {
139 n = DoInsertOneItem(items[i], pos++);
140 if ( n == wxNOT_FOUND )
141 break;
142
143 AssignNewItemClientData(n, clientData, i, type);
144 }
145
146 return n;
147 }
148
149 int
150 wxItemContainer::DoInsertOneItem(const wxString& WXUNUSED(item),
151 unsigned int WXUNUSED(pos))
152 {
153 wxFAIL_MSG( wxT("Must be overridden if DoInsertItemsInLoop() is used") );
154
155 return wxNOT_FOUND;
156 }
157
158
159 // ----------------------------------------------------------------------------
160 // client data
161 // ----------------------------------------------------------------------------
162
163 void wxItemContainer::SetClientObject(unsigned int n, wxClientData *data)
164 {
165 wxASSERT_MSG( !HasClientUntypedData(),
166 wxT("can't have both object and void client data") );
167
168 wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientObject()" );
169
170 if ( HasClientObjectData() )
171 {
172 wxClientData * clientDataOld
173 = static_cast<wxClientData *>(DoGetItemClientData(n));
174 if ( clientDataOld )
175 delete clientDataOld;
176 }
177 else // didn't have any client data so far
178 {
179 // now we have object client data
180 DoInitItemClientData();
181
182 SetClientDataType(wxClientData_Object);
183 }
184
185 DoSetItemClientData(n, data);
186 }
187
188 wxClientData *wxItemContainer::GetClientObject(unsigned int n) const
189 {
190 wxCHECK_MSG( HasClientObjectData(), NULL,
191 wxT("this window doesn't have object client data") );
192
193 wxCHECK_MSG( IsValid(n), NULL,
194 "Invalid index passed to GetClientObject()" );
195
196 return static_cast<wxClientData *>(DoGetItemClientData(n));
197 }
198
199 wxClientData *wxItemContainer::DetachClientObject(unsigned int n)
200 {
201 wxClientData * const data = GetClientObject(n);
202 if ( data )
203 {
204 // reset the pointer as we don't own it any more
205 DoSetItemClientData(n, NULL);
206 }
207
208 return data;
209 }
210
211 void wxItemContainer::SetClientData(unsigned int n, void *data)
212 {
213 if ( !HasClientData() )
214 {
215 DoInitItemClientData();
216 SetClientDataType(wxClientData_Void);
217 }
218
219 wxASSERT_MSG( HasClientUntypedData(),
220 wxT("can't have both object and void client data") );
221
222 wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientData()" );
223
224 DoSetItemClientData(n, data);
225 }
226
227 void *wxItemContainer::GetClientData(unsigned int n) const
228 {
229 wxCHECK_MSG( HasClientUntypedData(), NULL,
230 wxT("this window doesn't have void client data") );
231
232 wxCHECK_MSG( IsValid(n), NULL,
233 "Invalid index passed to GetClientData()" );
234
235 return DoGetItemClientData(n);
236 }
237
238 void wxItemContainer::AssignNewItemClientData(unsigned int pos,
239 void **clientData,
240 unsigned int n,
241 wxClientDataType type)
242 {
243 switch ( type )
244 {
245 case wxClientData_Object:
246 SetClientObject
247 (
248 pos,
249 (reinterpret_cast<wxClientData **>(clientData))[n]
250 );
251 break;
252
253 case wxClientData_Void:
254 SetClientData(pos, clientData[n]);
255 break;
256
257 default:
258 wxFAIL_MSG( wxT("unknown client data type") );
259 // fall through
260
261 case wxClientData_None:
262 // nothing to do
263 break;
264 }
265 }
266
267 void wxItemContainer::ResetItemClientObject(unsigned int n)
268 {
269 wxClientData * const data = GetClientObject(n);
270 if ( data )
271 {
272 delete data;
273 DoSetItemClientData(n, NULL);
274 }
275 }
276
277 // ============================================================================
278 // wxControlWithItems implementation
279 // ============================================================================
280
281 void
282 wxControlWithItemsBase::InitCommandEventWithItems(wxCommandEvent& event, int n)
283 {
284 InitCommandEvent(event);
285
286 if ( n != wxNOT_FOUND )
287 {
288 if ( HasClientObjectData() )
289 event.SetClientObject(GetClientObject(n));
290 else if ( HasClientUntypedData() )
291 event.SetClientData(GetClientData(n));
292 }
293 }
294
295 #endif // wxUSE_CONTROLS