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