]> git.saurik.com Git - wxWidgets.git/blame - include/wx/list.h
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / include / wx / list.h
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
c0089c96 2// Name: wx/list.h
c801d85f
KB
3// Purpose: wxList, wxStringList classes
4// Author: Julian Smart
fd3f686c 5// Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
c801d85f
KB
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
fd3f686c
VZ
12/*
13 All this is quite ugly but serves two purposes:
14 1. Be almost 100% compatible with old, untyped, wxList class
15 2. Ensure compile-time type checking for the linked lists
16
17 The idea is to have one base class (wxListBase) working with "void *" data,
18 but to hide these untyped functions - i.e. make them protected, so they
19 can only be used from derived classes which have inline member functions
20 working with right types. This achieves the 2nd goal. As for the first one,
21 we provide a special derivation of wxListBase called wxList which looks just
22 like the old class.
23*/
24
162e998c
PC
25#ifndef _WX_LIST_H_
26#define _WX_LIST_H_
c801d85f 27
fd3f686c
VZ
28// -----------------------------------------------------------------------------
29// headers
30// -----------------------------------------------------------------------------
31
c801d85f
KB
32#include "wx/defs.h"
33#include "wx/object.h"
3bef6c4c 34#include "wx/string.h"
c801d85f 35
01871bf6 36#if wxUSE_STD_CONTAINERS
df5168c4 37 #include "wx/beforestd.h"
ed1288c1
VZ
38 #include <algorithm>
39 #include <iterator>
df5168c4
MB
40 #include <list>
41 #include "wx/afterstd.h"
df5168c4
MB
42#endif
43
44// ----------------------------------------------------------------------------
45// types
46// ----------------------------------------------------------------------------
47
b5dbe15d 48class WXDLLIMPEXP_FWD_BASE wxObjectListNode;
fd3f686c
VZ
49typedef wxObjectListNode wxNode;
50
01871bf6 51#if wxUSE_STD_CONTAINERS
fd3f686c 52
df5168c4
MB
53#define wxLIST_COMPATIBILITY
54
55#define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
f794be6a 56 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
6de44038
VZ
57#define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
58 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
df5168c4
MB
59
60#define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
f794be6a 61 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
6de44038
VZ
62#define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
63 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
df5168c4 64
f794be6a 65#define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
df5168c4
MB
66 WX_DECLARE_LIST_XO(elT*, liT, decl)
67
a4c1cdc9 68#if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
168da56b 69
30bda36c 70template<class T>
c6ed0728 71class wxList_SortFunction
30bda36c
MB
72{
73public:
74 wxList_SortFunction(wxSortCompareFunction f) : m_f(f) { }
75 bool operator()(const T& i1, const T& i2)
76 { return m_f((T*)&i1, (T*)&i2) < 0; }
77private:
78 wxSortCompareFunction m_f;
79};
80
168da56b 81#define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
cae92a49 82#define WX_LIST_VC6_WORKAROUND(elT, liT, decl)
168da56b 83
a4c1cdc9 84#else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
168da56b 85
543ab300 86#define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
cae92a49 87#define WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
168da56b
MB
88 decl liT; \
89 \
90 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
91 /* to be passed into std::list::sort() */ \
92 template <> \
93 struct std::greater<elT> \
94 { \
95 private: \
96 wxSortCompareFunction m_CompFunc; \
97 public: \
98 greater( wxSortCompareFunction compfunc = NULL ) \
99 : m_CompFunc( compfunc ) {} \
100 bool operator()(const elT X, const elT Y) const \
101 { \
102 return m_CompFunc ? \
8a7afe4d
VS
103 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
104 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
168da56b
MB
105 ( X > Y ); \
106 } \
107 };
108
8a7afe4d
VS
109// helper for std::greater<elT> above:
110template<typename T>
111inline const void *wxListCastElementToVoidPtr(const T* ptr) { return ptr; }
112inline const void *wxListCastElementToVoidPtr(const wxString& str)
113 { return (const char*)str; }
114
a4c1cdc9 115#endif // VC6/!VC6
168da56b 116
30a29593 117/*
7d13fbc6 118 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
30a29593
VZ
119 for mingw 3.2.3 compiler bug that prevents a static function of liT class
120 from being exported into dll. A minimal code snippet reproducing the bug:
121
53a2db12 122 struct WXDLLIMPEXP_CORE Foo
30a29593
VZ
123 {
124 static void Bar();
125 struct SomeInnerClass
126 {
127 friend class Foo; // comment this out to make it link
128 };
129 ~Foo()
130 {
131 Bar();
132 }
133 };
134
135 The program does not link under mingw_gcc 3.2.3 producing undefined
136 reference to Foo::Bar() function
7d13fbc6
VZ
137
138
139 Note 2: the EmptyList is needed to allow having a NULL pointer-like
140 invalid iterator. We used to use just an uninitialized iterator object
141 instead but this fails with some debug/checked versions of STL, notably the
142 glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate
143 invalid iterator.
30a29593
VZ
144 */
145
146// the real wxList-class declaration
ed1288c1 147#define WX_DECLARE_LIST_XO(elT, liT, decl) \
3871d4ca 148 decl _WX_LIST_HELPER_##liT \
30a29593
VZ
149 { \
150 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
1bc5ddea 151 typedef std::list<elT> BaseListType; \
30a29593 152 public: \
1bc5ddea 153 static BaseListType EmptyList; \
30a29593
VZ
154 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
155 }; \
156 \
cae92a49 157 WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
1bc5ddea 158 class liT : public std::list<elT> \
831c2889
VZ
159 { \
160 private: \
7d13fbc6 161 typedef std::list<elT> BaseListType; \
7d13fbc6 162 \
831c2889 163 bool m_destroy; \
cd840087 164 \
ed1288c1 165 public: \
1bc5ddea 166 class compatibility_iterator \
df5168c4 167 { \
ed1288c1 168 private: \
cd840087
VZ
169 /* Workaround for broken VC6 nested class name resolution */ \
170 typedef std::list<elT>::iterator iterator; \
171 friend class liT; \
172 \
df5168c4
MB
173 iterator m_iter; \
174 liT * m_list; \
cd840087 175 \
df5168c4 176 public: \
ed1288c1 177 compatibility_iterator() \
1bc5ddea 178 : m_iter(_WX_LIST_HELPER_##liT::EmptyList.end()), m_list( NULL ) {} \
ed1288c1
VZ
179 compatibility_iterator( liT* li, iterator i ) \
180 : m_iter( i ), m_list( li ) {} \
181 compatibility_iterator( const liT* li, iterator i ) \
182 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
183 \
184 compatibility_iterator* operator->() { return this; } \
185 const compatibility_iterator* operator->() const { return this; } \
186 \
60d8e886 187 bool operator==(const compatibility_iterator& i) const \
b4affacc
VZ
188 { \
189 wxASSERT_MSG( m_list && i.m_list, \
9a83f860 190 wxT("comparing invalid iterators is illegal") ); \
b4affacc
VZ
191 return (m_list == i.m_list) && (m_iter == i.m_iter); \
192 } \
60d8e886 193 bool operator!=(const compatibility_iterator& i) const \
ed1288c1 194 { return !( operator==( i ) ); } \
df5168c4 195 operator bool() const \
ed1288c1 196 { return m_list ? m_iter != m_list->end() : false; } \
df5168c4 197 bool operator !() const \
ed1288c1 198 { return !( operator bool() ); } \
df5168c4 199 \
df5168c4 200 elT GetData() const \
ed1288c1
VZ
201 { return *m_iter; } \
202 void SetData( elT e ) \
203 { *m_iter = e; } \
204 \
205 compatibility_iterator GetNext() const \
df5168c4 206 { \
ed1288c1
VZ
207 iterator i = m_iter; \
208 return compatibility_iterator( m_list, ++i ); \
df5168c4 209 } \
ed1288c1 210 compatibility_iterator GetPrevious() const \
df5168c4 211 { \
5d9ef6de
VZ
212 if ( m_iter == m_list->begin() ) \
213 return compatibility_iterator(); \
214 \
ed1288c1
VZ
215 iterator i = m_iter; \
216 return compatibility_iterator( m_list, --i ); \
df5168c4 217 } \
ed1288c1 218 int IndexOf() const \
df5168c4 219 { \
0b6cf205
VZ
220 return *this ? std::distance( m_list->begin(), m_iter ) \
221 : wxNOT_FOUND; \
df5168c4 222 } \
df5168c4 223 }; \
ed1288c1
VZ
224 public: \
225 liT() : m_destroy( false ) {} \
226 \
227 compatibility_iterator Find( const elT e ) const \
df5168c4 228 { \
ed1288c1
VZ
229 liT* _this = const_cast< liT* >( this ); \
230 return compatibility_iterator( _this, \
231 std::find( _this->begin(), _this->end(), e ) ); \
df5168c4 232 } \
df5168c4 233 \
ed1288c1
VZ
234 bool IsEmpty() const \
235 { return empty(); } \
236 size_t GetCount() const \
237 { return size(); } \
238 int Number() const \
239 { return static_cast< int >( GetCount() ); } \
240 \
241 compatibility_iterator Item( size_t idx ) const \
df5168c4 242 { \
ed1288c1
VZ
243 iterator i = const_cast< liT* >(this)->begin(); \
244 std::advance( i, idx ); \
245 return compatibility_iterator( this, i ); \
246 } \
af867f95 247 elT operator[](size_t idx) const \
9ea1246b 248 { \
af867f95 249 return Item(idx).GetData(); \
9ea1246b
VZ
250 } \
251 \
ed1288c1
VZ
252 compatibility_iterator GetFirst() const \
253 { \
254 return compatibility_iterator( this, \
255 const_cast< liT* >(this)->begin() ); \
256 } \
257 compatibility_iterator GetLast() const \
258 { \
259 iterator i = const_cast< liT* >(this)->end(); \
260 return compatibility_iterator( this, !empty() ? --i : i ); \
261 } \
0f08aa44 262 bool Member( elT e ) const \
ed1288c1
VZ
263 { return Find( e ); } \
264 compatibility_iterator Nth( int n ) const \
265 { return Item( n ); } \
266 int IndexOf( elT e ) const \
267 { return Find( e ).IndexOf(); } \
268 \
269 compatibility_iterator Append( elT e ) \
270 { \
271 push_back( e ); \
272 return GetLast(); \
273 } \
274 compatibility_iterator Insert( elT e ) \
275 { \
276 push_front( e ); \
277 return compatibility_iterator( this, begin() ); \
278 } \
8ad170cb 279 compatibility_iterator Insert(const compatibility_iterator & i, elT e)\
ed1288c1
VZ
280 { \
281 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
282 } \
283 compatibility_iterator Insert( size_t idx, elT e ) \
284 { \
285 return compatibility_iterator( this, \
286 insert( Item( idx ).m_iter, e ) ); \
287 } \
288 \
289 void DeleteContents( bool destroy ) \
290 { m_destroy = destroy; } \
291 bool GetDeleteContents() const \
292 { return m_destroy; } \
293 void Erase( const compatibility_iterator& i ) \
294 { \
295 if ( m_destroy ) \
30a29593 296 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
ed1288c1
VZ
297 erase( i.m_iter ); \
298 } \
299 bool DeleteNode( const compatibility_iterator& i ) \
300 { \
301 if( i ) \
df5168c4 302 { \
ed1288c1 303 Erase( i ); \
df5168c4
MB
304 return true; \
305 } \
306 return false; \
307 } \
ed1288c1 308 bool DeleteObject( elT e ) \
df5168c4 309 { \
ed1288c1 310 return DeleteNode( Find( e ) ); \
df5168c4 311 } \
ed1288c1 312 void Clear() \
df5168c4 313 { \
ed1288c1 314 if ( m_destroy ) \
30a29593
VZ
315 std::for_each( begin(), end(), \
316 _WX_LIST_HELPER_##liT::DeleteFunction ); \
ed1288c1 317 clear(); \
df5168c4 318 } \
831c2889 319 /* Workaround for broken VC6 std::list::sort() see above */ \
ed1288c1 320 void Sort( wxSortCompareFunction compfunc ) \
168da56b 321 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
ed1288c1 322 ~liT() { Clear(); } \
cd840087
VZ
323 \
324 /* It needs access to our EmptyList */ \
e5eaf557 325 friend class compatibility_iterator; \
df5168c4
MB
326 }
327
328#define WX_DECLARE_LIST(elementtype, listname) \
f794be6a 329 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
6de44038
VZ
330#define WX_DECLARE_LIST_PTR(elementtype, listname) \
331 WX_DECLARE_LIST(elementtype, listname)
df5168c4
MB
332
333#define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
53a2db12 334 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
6de44038
VZ
335#define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
336 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
df5168c4
MB
337
338#define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
f794be6a 339 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
6de44038
VZ
340#define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
341 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
df5168c4
MB
342
343// this macro must be inserted in your program after
c0089c96 344// #include "wx/listimpl.cpp"
df5168c4
MB
345#define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
346
347#define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
348#define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
349
01871bf6 350#else // if !wxUSE_STD_CONTAINERS
df5168c4 351
df5168c4 352
df5168c4
MB
353// undef it to get rid of old, deprecated functions
354#define wxLIST_COMPATIBILITY
fd3f686c
VZ
355
356// -----------------------------------------------------------------------------
357// key stuff: a list may be optionally keyed on integer or string key
358// -----------------------------------------------------------------------------
359
360union wxListKeyValue
c801d85f 361{
c801d85f 362 long integer;
81727065 363 wxString *string;
c801d85f
KB
364};
365
fd3f686c
VZ
366// a struct which may contain both types of keys
367//
368// implementation note: on one hand, this class allows to have only one function
369// for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
370// resolve ambiguity which we would otherwise have with wxStringList::Find() and
371// wxList::Find(const char *).
bddd7a8d 372class WXDLLIMPEXP_BASE wxListKey
fd3f686c
VZ
373{
374public:
375 // implicit ctors
f2af4afb
GD
376 wxListKey() : m_keyType(wxKEY_NONE)
377 { }
378 wxListKey(long i) : m_keyType(wxKEY_INTEGER)
379 { m_key.integer = i; }
f2af4afb 380 wxListKey(const wxString& s) : m_keyType(wxKEY_STRING)
81727065 381 { m_key.string = new wxString(s); }
5abefd04
VS
382 wxListKey(const char *s) : m_keyType(wxKEY_STRING)
383 { m_key.string = new wxString(s); }
384 wxListKey(const wchar_t *s) : m_keyType(wxKEY_STRING)
385 { m_key.string = new wxString(s); }
fd3f686c
VZ
386
387 // accessors
388 wxKeyType GetKeyType() const { return m_keyType; }
81727065
VS
389 const wxString GetString() const
390 { wxASSERT( m_keyType == wxKEY_STRING ); return *m_key.string; }
fd3f686c
VZ
391 long GetNumber() const
392 { wxASSERT( m_keyType == wxKEY_INTEGER ); return m_key.integer; }
393
6164d85e
JS
394 // comparison
395 // Note: implementation moved to list.cpp to prevent BC++ inline
396 // expansion warning.
397 bool operator==(wxListKeyValue value) const ;
fd3f686c
VZ
398
399 // dtor
400 ~wxListKey()
401 {
402 if ( m_keyType == wxKEY_STRING )
81727065 403 delete m_key.string;
fd3f686c
VZ
404 }
405
406private:
407 wxKeyType m_keyType;
408 wxListKeyValue m_key;
409};
410
411// -----------------------------------------------------------------------------
412// wxNodeBase class is a (base for) node in a double linked list
413// -----------------------------------------------------------------------------
414
16cba29d 415extern WXDLLIMPEXP_DATA_BASE(wxListKey) wxDefaultListKey;
2432b92d 416
b5dbe15d 417class WXDLLIMPEXP_FWD_BASE wxListBase;
fbfb3fb3 418
bddd7a8d 419class WXDLLIMPEXP_BASE wxNodeBase
fd3f686c
VZ
420{
421friend class wxListBase;
422public:
423 // ctor
c23b255a
VZ
424 wxNodeBase(wxListBase *list = NULL,
425 wxNodeBase *previous = NULL,
426 wxNodeBase *next = NULL,
fd3f686c 427 void *data = NULL,
2432b92d 428 const wxListKey& key = wxDefaultListKey);
fd3f686c
VZ
429
430 virtual ~wxNodeBase();
431
f03fc89f 432 // FIXME no check is done that the list is really keyed on strings
81727065 433 wxString GetKeyString() const { return *m_key.string; }
74e34480 434 long GetKeyInteger() const { return m_key.integer; }
fd3f686c 435
4fabb575 436 // Necessary for some existing code
81727065 437 void SetKeyString(const wxString& s) { m_key.string = new wxString(s); }
4fabb575
JS
438 void SetKeyInteger(long i) { m_key.integer = i; }
439
fd3f686c 440#ifdef wxLIST_COMPATIBILITY
b1d4dd7a
RL
441 // compatibility methods, use Get* instead.
442 wxDEPRECATED( wxNode *Next() const );
443 wxDEPRECATED( wxNode *Previous() const );
444 wxDEPRECATED( wxObject *Data() const );
fd3f686c
VZ
445#endif // wxLIST_COMPATIBILITY
446
447protected:
448 // all these are going to be "overloaded" in the derived classes
449 wxNodeBase *GetNext() const { return m_next; }
450 wxNodeBase *GetPrevious() const { return m_previous; }
451
452 void *GetData() const { return m_data; }
453 void SetData(void *data) { m_data = data; }
454
3c67202d 455 // get 0-based index of this node within the list or wxNOT_FOUND
77c5eefb
VZ
456 int IndexOf() const;
457
fd3f686c 458 virtual void DeleteData() { }
df5168c4
MB
459public:
460 // for wxList::iterator
5c33522f 461 void** GetDataPtr() const { return &(const_cast<wxNodeBase*>(this)->m_data); }
fd3f686c
VZ
462private:
463 // optional key stuff
464 wxListKeyValue m_key;
465
466 void *m_data; // user data
467 wxNodeBase *m_next, // next and previous nodes in the list
468 *m_previous;
469
470 wxListBase *m_list; // list we belong to
f2af4afb 471
c0c133e1 472 wxDECLARE_NO_COPY_CLASS(wxNodeBase);
fd3f686c
VZ
473};
474
475// -----------------------------------------------------------------------------
476// a double-linked list class
477// -----------------------------------------------------------------------------
f98bd52a 478
b5dbe15d 479class WXDLLIMPEXP_FWD_BASE wxList;
b1d4dd7a 480
7e59e3d0 481class WXDLLIMPEXP_BASE wxListBase
fd3f686c 482{
e5eaf557 483friend class wxNodeBase; // should be able to call DetachNode()
bcaa23de 484friend class wxHashTableBase; // should be able to call untyped Find()
5a8231ef 485
fd3f686c
VZ
486public:
487 // default ctor & dtor
f2af4afb
GD
488 wxListBase(wxKeyType keyType = wxKEY_NONE)
489 { Init(keyType); }
fd3f686c
VZ
490 virtual ~wxListBase();
491
492 // accessors
493 // count of items in the list
494 size_t GetCount() const { return m_count; }
c801d85f 495
f644b28c 496 // return true if this list is empty
b79a8705
VZ
497 bool IsEmpty() const { return m_count == 0; }
498
fd3f686c 499 // operations
e146b8c8 500
fd3f686c 501 // delete all nodes
db9504c5 502 void Clear();
e146b8c8 503
fd3f686c
VZ
504 // instruct it to destroy user data when deleting nodes
505 void DeleteContents(bool destroy) { m_destroy = destroy; }
506
907789a0
RR
507 // query if to delete
508 bool GetDeleteContents() const
509 { return m_destroy; }
e146b8c8 510
907789a0
RR
511 // get the keytype
512 wxKeyType GetKeyType() const
513 { return m_keyType; }
514
515 // set the keytype (required by the serial code)
516 void SetKeyType(wxKeyType keyType)
517 { wxASSERT( m_count==0 ); m_keyType = keyType; }
518
e146b8c8 519#ifdef wxLIST_COMPATIBILITY
b1d4dd7a
RL
520 // compatibility methods from old wxList
521 wxDEPRECATED( int Number() const ); // use GetCount instead.
522 wxDEPRECATED( wxNode *First() const ); // use GetFirst
523 wxDEPRECATED( wxNode *Last() const ); // use GetLast
524 wxDEPRECATED( wxNode *Nth(size_t n) const ); // use Item
525
526 // kludge for typesafe list migration in core classes.
527 wxDEPRECATED( operator wxList&() const );
e146b8c8
VZ
528#endif // wxLIST_COMPATIBILITY
529
fd3f686c 530protected:
a3ef5bf5 531
fd3f686c
VZ
532 // all methods here are "overloaded" in derived classes to provide compile
533 // time type checking
534
535 // create a node for the list of this type
536 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next,
537 void *data,
2432b92d 538 const wxListKey& key = wxDefaultListKey) = 0;
fd3f686c 539
a3ef5bf5 540
fd3f686c
VZ
541 // ctors
542 // from an array
543 wxListBase(size_t count, void *elements[]);
544 // from a sequence of objects
545 wxListBase(void *object, ... /* terminate with NULL */);
546
a3ef5bf5 547protected:
00e09270
VZ
548 void Assign(const wxListBase& list)
549 { Clear(); DoCopy(list); }
fd3f686c
VZ
550
551 // get list head/tail
552 wxNodeBase *GetFirst() const { return m_nodeFirst; }
553 wxNodeBase *GetLast() const { return m_nodeLast; }
554
555 // by (0-based) index
556 wxNodeBase *Item(size_t index) const;
557
558 // get the list item's data
2b5f62a0
VZ
559 void *operator[](size_t n) const
560 {
561 wxNodeBase *node = Item(n);
562
c23b255a 563 return node ? node->GetData() : NULL;
2b5f62a0 564 }
fd3f686c
VZ
565
566 // operations
567 // append to end of list
890f8a7c
RR
568 wxNodeBase *Prepend(void *object)
569 { return (wxNodeBase *)wxListBase::Insert(object); }
570 // append to beginning of list
fd3f686c
VZ
571 wxNodeBase *Append(void *object);
572 // insert a new item at the beginning of the list
c23b255a
VZ
573 wxNodeBase *Insert(void *object)
574 { return Insert(static_cast<wxNodeBase *>(NULL), object); }
d8996187
VZ
575 // insert a new item at the given position
576 wxNodeBase *Insert(size_t pos, void *object)
577 { return pos == GetCount() ? Append(object)
578 : Insert(Item(pos), object); }
fd3f686c
VZ
579 // insert before given node or at front of list if prev == NULL
580 wxNodeBase *Insert(wxNodeBase *prev, void *object);
581
582 // keyed append
583 wxNodeBase *Append(long key, void *object);
81727065 584 wxNodeBase *Append(const wxString& key, void *object);
fd3f686c
VZ
585
586 // removes node from the list but doesn't delete it (returns pointer
587 // to the node or NULL if it wasn't found in the list)
588 wxNodeBase *DetachNode(wxNodeBase *node);
f644b28c 589 // delete element from list, returns false if node not found
fd3f686c
VZ
590 bool DeleteNode(wxNodeBase *node);
591 // finds object pointer and deletes node (and object if DeleteContents
f644b28c 592 // is on), returns false if object not found
77c5eefb 593 bool DeleteObject(void *object);
fd3f686c
VZ
594
595 // search (all return NULL if item not found)
596 // by data
22d080f3 597 wxNodeBase *Find(const void *object) const;
fd3f686c
VZ
598
599 // by key
600 wxNodeBase *Find(const wxListKey& key) const;
601
3c67202d 602 // get 0-based index of object or wxNOT_FOUND
77c5eefb
VZ
603 int IndexOf( void *object ) const;
604
fd3f686c
VZ
605 // this function allows the sorting of arbitrary lists by giving
606 // a function to compare two list elements. The list is sorted in place.
6164d85e 607 void Sort(const wxSortCompareFunction compfunc);
fd3f686c
VZ
608
609 // functions for iterating over the list
610 void *FirstThat(wxListIterateFunction func);
611 void ForEach(wxListIterateFunction func);
612 void *LastThat(wxListIterateFunction func);
e146b8c8 613
df5168c4
MB
614 // for STL interface, "last" points to one after the last node
615 // of the controlled sequence (NULL for the end of the list)
616 void Reverse();
617 void DeleteNodes(wxNodeBase* first, wxNodeBase* last);
fd3f686c 618private:
5a8231ef
WS
619
620 // common part of all ctors
621 void Init(wxKeyType keyType = wxKEY_NONE);
622
fd3f686c 623 // helpers
fd3f686c
VZ
624 // common part of copy ctor and assignment operator
625 void DoCopy(const wxListBase& list);
626 // common part of all Append()s
627 wxNodeBase *AppendCommon(wxNodeBase *node);
628 // free node's data and node itself
629 void DoDeleteNode(wxNodeBase *node);
630
631 size_t m_count; // number of elements in the list
632 bool m_destroy; // destroy user data when deleting list items?
633 wxNodeBase *m_nodeFirst, // pointers to the head and tail of the list
634 *m_nodeLast;
635
636 wxKeyType m_keyType; // type of our keys (may be wxKEY_NONE)
637};
638
639// -----------------------------------------------------------------------------
640// macros for definition of "template" list type
641// -----------------------------------------------------------------------------
642
643// and now some heavy magic...
644
645// declare a list type named 'name' and containing elements of type 'T *'
646// (as a by product of macro expansion you also get wx##name##Node
ce3ed50d 647// wxNode-derived type)
fd3f686c
VZ
648//
649// implementation details:
ce3ed50d 650// 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
fd3f686c
VZ
651// for the list of given type - this allows us to pass only the list name
652// to WX_DEFINE_LIST() even if it needs both the name and the type
653//
ce3ed50d
JS
654// 2. We redefine all non-type-safe wxList functions with type-safe versions
655// which don't take any space (everything is inline), but bring compile
fd3f686c 656// time error checking.
f03fc89f
VZ
657//
658// 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
659// a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
660// generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
661// interesting capability to store polymorphic objects in the list and is
662// particularly useful with, for example, "wxWindow *" list where the
663// wxWindowBase pointers are put into the list, but wxWindow pointers are
664// retrieved from it.
6de44038
VZ
665//
666// 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
667// WX_DECLARE_LIST_4 to allow defining classes without operator->() as
668// it results in compiler warnings when this operator doesn't make sense
669// (i.e. stored elements are not pointers)
f03fc89f 670
6de44038
VZ
671// common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
672#define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
ba059d80 673 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
fd3f686c 674 \
f6bcfd97 675 classexp nodetype : public wxNodeBase \
fd3f686c
VZ
676 { \
677 public: \
c23b255a
VZ
678 nodetype(wxListBase *list = NULL, \
679 nodetype *previous = NULL, \
680 nodetype *next = NULL, \
681 T *data = NULL, \
e146b8c8 682 const wxListKey& key = wxDefaultListKey) \
fd3f686c
VZ
683 : wxNodeBase(list, previous, next, data, key) { } \
684 \
685 nodetype *GetNext() const \
686 { return (nodetype *)wxNodeBase::GetNext(); } \
687 nodetype *GetPrevious() const \
688 { return (nodetype *)wxNodeBase::GetPrevious(); } \
689 \
690 T *GetData() const \
691 { return (T *)wxNodeBase::GetData(); } \
692 void SetData(T *data) \
693 { wxNodeBase::SetData(data); } \
694 \
60d8e886 695 protected: \
fd3f686c 696 virtual void DeleteData(); \
cd989b24
VZ
697 \
698 DECLARE_NO_COPY_CLASS(nodetype) \
fd3f686c
VZ
699 }; \
700 \
f6bcfd97 701 classexp name : public wxListBase \
fd3f686c
VZ
702 { \
703 public: \
e2a3cc0c 704 typedef nodetype Node; \
d294c9db 705 classexp compatibility_iterator \
0cc70962
VZ
706 { \
707 public: \
708 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
709 \
710 Node *operator->() const { return m_ptr; } \
711 operator Node *() const { return m_ptr; } \
712 \
713 private: \
714 Node *m_ptr; \
715 }; \
e2a3cc0c 716 \
fd3f686c
VZ
717 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
718 { } \
00e09270
VZ
719 name(const name& list) : wxListBase(list.GetKeyType()) \
720 { Assign(list); } \
fd3f686c
VZ
721 name(size_t count, T *elements[]) \
722 : wxListBase(count, (void **)elements) { } \
723 \
f6bcfd97 724 name& operator=(const name& list) \
162e998c 725 { if (&list != this) Assign(list); return *this; } \
f6bcfd97 726 \
2e4b087e 727 nodetype *GetFirst() const \
fd3f686c 728 { return (nodetype *)wxListBase::GetFirst(); } \
2e4b087e 729 nodetype *GetLast() const \
fd3f686c
VZ
730 { return (nodetype *)wxListBase::GetLast(); } \
731 \
2e4b087e 732 nodetype *Item(size_t index) const \
fd3f686c
VZ
733 { return (nodetype *)wxListBase::Item(index); } \
734 \
735 T *operator[](size_t index) const \
736 { \
737 nodetype *node = Item(index); \
c23b255a 738 return node ? (T*)(node->GetData()) : NULL; \
fd3f686c
VZ
739 } \
740 \
2e4b087e 741 nodetype *Append(Tbase *object) \
fd3f686c 742 { return (nodetype *)wxListBase::Append(object); } \
2e4b087e 743 nodetype *Insert(Tbase *object) \
c23b255a
VZ
744 { return (nodetype *)Insert(static_cast<nodetype *>(NULL), \
745 object); } \
2e4b087e 746 nodetype *Insert(size_t pos, Tbase *object) \
d8996187 747 { return (nodetype *)wxListBase::Insert(pos, object); } \
2e4b087e 748 nodetype *Insert(nodetype *prev, Tbase *object) \
fd3f686c
VZ
749 { return (nodetype *)wxListBase::Insert(prev, object); } \
750 \
2e4b087e 751 nodetype *Append(long key, void *object) \
fd3f686c 752 { return (nodetype *)wxListBase::Append(key, object); } \
2e4b087e 753 nodetype *Append(const wxChar *key, void *object) \
fd3f686c
VZ
754 { return (nodetype *)wxListBase::Append(key, object); } \
755 \
756 nodetype *DetachNode(nodetype *node) \
757 { return (nodetype *)wxListBase::DetachNode(node); } \
758 bool DeleteNode(nodetype *node) \
759 { return wxListBase::DeleteNode(node); } \
f03fc89f 760 bool DeleteObject(Tbase *object) \
fd3f686c 761 { return wxListBase::DeleteObject(object); } \
2e4b087e 762 void Erase(nodetype *it) \
df5168c4 763 { DeleteNode(it); } \
fd3f686c 764 \
2e4b087e 765 nodetype *Find(const Tbase *object) const \
fd3f686c
VZ
766 { return (nodetype *)wxListBase::Find(object); } \
767 \
768 virtual nodetype *Find(const wxListKey& key) const \
769 { return (nodetype *)wxListBase::Find(key); } \
770 \
20d88ec6
VZ
771 bool Member(const Tbase *object) const \
772 { return Find(object) != NULL; } \
773 \
f03fc89f 774 int IndexOf(Tbase *object) const \
77c5eefb
VZ
775 { return wxListBase::IndexOf(object); } \
776 \
ed1288c1
VZ
777 void Sort(wxSortCompareFunction func) \
778 { wxListBase::Sort(func); } \
fd3f686c 779 void Sort(wxSortFuncFor_##name func) \
ed1288c1 780 { Sort((wxSortCompareFunction)func); } \
fd3f686c
VZ
781 \
782 protected: \
ea48aff3 783 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
fd3f686c 784 void *data, \
e146b8c8 785 const wxListKey& key = wxDefaultListKey) \
fd3f686c
VZ
786 { \
787 return new nodetype(this, \
788 (nodetype *)prev, (nodetype *)next, \
789 (T *)data, key); \
790 } \
df5168c4
MB
791 /* STL interface */ \
792 public: \
793 typedef size_t size_type; \
794 typedef int difference_type; \
795 typedef T* value_type; \
796 typedef Tbase* base_value_type; \
797 typedef value_type& reference; \
798 typedef const value_type& const_reference; \
799 typedef base_value_type& base_reference; \
800 typedef const base_value_type& const_base_reference; \
801 \
d294c9db 802 classexp iterator \
df5168c4
MB
803 { \
804 typedef name list; \
805 public: \
37589419 806 typedef nodetype Node; \
df5168c4 807 typedef iterator itor; \
37589419
MB
808 typedef T* value_type; \
809 typedef value_type* ptr_type; \
810 typedef value_type& reference; \
df5168c4
MB
811 \
812 Node* m_node; \
813 Node* m_init; \
814 public: \
37589419 815 typedef reference reference_type; \
df5168c4
MB
816 typedef ptr_type pointer_type; \
817 \
818 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
819 iterator() : m_node(NULL), m_init(NULL) { } \
820 reference_type operator*() const \
821 { return *(pointer_type)m_node->GetDataPtr(); } \
6de44038 822 ptrop \
2f250cb6
SC
823 itor& operator++() \
824 { \
f67a33e3
SC
825 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
826 m_node = m_node->GetNext(); \
2f250cb6
SC
827 return *this; \
828 } \
60d8e886 829 const itor operator++(int) \
2f250cb6
SC
830 { \
831 itor tmp = *this; \
f67a33e3
SC
832 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
833 m_node = m_node->GetNext(); \
2f250cb6
SC
834 return tmp; \
835 } \
df5168c4
MB
836 itor& operator--() \
837 { \
838 m_node = m_node ? m_node->GetPrevious() : m_init; \
839 return *this; \
840 } \
60d8e886 841 const itor operator--(int) \
df5168c4
MB
842 { \
843 itor tmp = *this; \
844 m_node = m_node ? m_node->GetPrevious() : m_init; \
845 return tmp; \
846 } \
847 bool operator!=(const itor& it) const \
848 { return it.m_node != m_node; } \
849 bool operator==(const itor& it) const \
850 { return it.m_node == m_node; } \
851 }; \
d294c9db 852 classexp const_iterator \
df5168c4
MB
853 { \
854 typedef name list; \
855 public: \
37589419
MB
856 typedef nodetype Node; \
857 typedef T* value_type; \
858 typedef const value_type& const_reference; \
df5168c4 859 typedef const_iterator itor; \
37589419 860 typedef value_type* ptr_type; \
df5168c4
MB
861 \
862 Node* m_node; \
863 Node* m_init; \
864 public: \
37589419 865 typedef const_reference reference_type; \
df5168c4
MB
866 typedef const ptr_type pointer_type; \
867 \
868 const_iterator(Node* node, Node* init) \
869 : m_node(node), m_init(init) { } \
870 const_iterator() : m_node(NULL), m_init(NULL) { } \
871 const_iterator(const iterator& it) \
872 : m_node(it.m_node), m_init(it.m_init) { } \
873 reference_type operator*() const \
874 { return *(pointer_type)m_node->GetDataPtr(); } \
6de44038 875 ptrop \
2f250cb6
SC
876 itor& operator++() \
877 { \
f67a33e3
SC
878 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
879 m_node = m_node->GetNext(); \
2f250cb6
SC
880 return *this; \
881 } \
60d8e886 882 const itor operator++(int) \
2f250cb6
SC
883 { \
884 itor tmp = *this; \
f67a33e3
SC
885 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
886 m_node = m_node->GetNext(); \
2f250cb6
SC
887 return tmp; \
888 } \
df5168c4
MB
889 itor& operator--() \
890 { \
891 m_node = m_node ? m_node->GetPrevious() : m_init; \
892 return *this; \
893 } \
60d8e886 894 const itor operator--(int) \
df5168c4
MB
895 { \
896 itor tmp = *this; \
897 m_node = m_node ? m_node->GetPrevious() : m_init; \
898 return tmp; \
899 } \
900 bool operator!=(const itor& it) const \
901 { return it.m_node != m_node; } \
902 bool operator==(const itor& it) const \
903 { return it.m_node == m_node; } \
904 }; \
d294c9db 905 classexp reverse_iterator \
df5168c4
MB
906 { \
907 typedef name list; \
908 public: \
37589419
MB
909 typedef nodetype Node; \
910 typedef T* value_type; \
df5168c4 911 typedef reverse_iterator itor; \
37589419
MB
912 typedef value_type* ptr_type; \
913 typedef value_type& reference; \
df5168c4
MB
914 \
915 Node* m_node; \
916 Node* m_init; \
917 public: \
37589419 918 typedef reference reference_type; \
df5168c4
MB
919 typedef ptr_type pointer_type; \
920 \
921 reverse_iterator(Node* node, Node* init) \
922 : m_node(node), m_init(init) { } \
923 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
924 reference_type operator*() const \
925 { return *(pointer_type)m_node->GetDataPtr(); } \
6de44038 926 ptrop \
df5168c4
MB
927 itor& operator++() \
928 { m_node = m_node->GetPrevious(); return *this; } \
60d8e886 929 const itor operator++(int) \
df5168c4
MB
930 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
931 itor& operator--() \
932 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
60d8e886 933 const itor operator--(int) \
df5168c4
MB
934 { \
935 itor tmp = *this; \
936 m_node = m_node ? m_node->GetNext() : m_init; \
937 return tmp; \
938 } \
939 bool operator!=(const itor& it) const \
940 { return it.m_node != m_node; } \
941 bool operator==(const itor& it) const \
942 { return it.m_node == m_node; } \
943 }; \
d294c9db 944 classexp const_reverse_iterator \
df5168c4
MB
945 { \
946 typedef name list; \
947 public: \
37589419
MB
948 typedef nodetype Node; \
949 typedef T* value_type; \
df5168c4 950 typedef const_reverse_iterator itor; \
37589419
MB
951 typedef value_type* ptr_type; \
952 typedef const value_type& const_reference; \
df5168c4
MB
953 \
954 Node* m_node; \
955 Node* m_init; \
956 public: \
37589419 957 typedef const_reference reference_type; \
df5168c4
MB
958 typedef const ptr_type pointer_type; \
959 \
960 const_reverse_iterator(Node* node, Node* init) \
961 : m_node(node), m_init(init) { } \
962 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
963 const_reverse_iterator(const reverse_iterator& it) \
964 : m_node(it.m_node), m_init(it.m_init) { } \
965 reference_type operator*() const \
966 { return *(pointer_type)m_node->GetDataPtr(); } \
6de44038 967 ptrop \
df5168c4
MB
968 itor& operator++() \
969 { m_node = m_node->GetPrevious(); return *this; } \
60d8e886 970 const itor operator++(int) \
df5168c4
MB
971 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
972 itor& operator--() \
973 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
60d8e886 974 const itor operator--(int) \
df5168c4
MB
975 { \
976 itor tmp = *this; \
977 m_node = m_node ? m_node->GetNext() : m_init; \
978 return tmp; \
979 } \
980 bool operator!=(const itor& it) const \
981 { return it.m_node != m_node; } \
982 bool operator==(const itor& it) const \
983 { return it.m_node == m_node; } \
984 }; \
985 \
986 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
987 { assign(n, v); } \
60d8e886 988 name(const const_iterator& first, const const_iterator& last) \
df5168c4
MB
989 { assign(first, last); } \
990 iterator begin() { return iterator(GetFirst(), GetLast()); } \
991 const_iterator begin() const \
992 { return const_iterator(GetFirst(), GetLast()); } \
993 iterator end() { return iterator(NULL, GetLast()); } \
994 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
995 reverse_iterator rbegin() \
996 { return reverse_iterator(GetLast(), GetFirst()); } \
997 const_reverse_iterator rbegin() const \
998 { return const_reverse_iterator(GetLast(), GetFirst()); } \
999 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
1000 const_reverse_iterator rend() const \
1001 { return const_reverse_iterator(NULL, GetFirst()); } \
1002 void resize(size_type n, value_type v = value_type()) \
1003 { \
5751dd32
JS
1004 while (n < size()) \
1005 pop_back(); \
1006 while (n > size()) \
d56cc7b1 1007 push_back(v); \
df5168c4
MB
1008 } \
1009 size_type size() const { return GetCount(); } \
1010 size_type max_size() const { return INT_MAX; } \
1011 bool empty() const { return IsEmpty(); } \
1012 reference front() { return *begin(); } \
1013 const_reference front() const { return *begin(); } \
60d8e886
VZ
1014 reference back() { iterator tmp = end(); return *--tmp; } \
1015 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
df5168c4
MB
1016 void push_front(const_reference v = value_type()) \
1017 { Insert(GetFirst(), (const_base_reference)v); } \
1018 void pop_front() { DeleteNode(GetFirst()); } \
1019 void push_back(const_reference v = value_type()) \
1020 { Append((const_base_reference)v); } \
1021 void pop_back() { DeleteNode(GetLast()); } \
60d8e886 1022 void assign(const_iterator first, const const_iterator& last) \
df5168c4
MB
1023 { \
1024 clear(); \
1025 for(; first != last; ++first) \
1026 Append((const_base_reference)*first); \
1027 } \
1028 void assign(size_type n, const_reference v = value_type()) \
1029 { \
1030 clear(); \
1031 for(size_type i = 0; i < n; ++i) \
1032 Append((const_base_reference)v); \
1033 } \
b547eb0f 1034 iterator insert(const iterator& it, const_reference v) \
df5168c4 1035 { \
b9f9065e 1036 if ( it == end() ) \
8dd13d0f 1037 { \
b9f9065e 1038 Append((const_base_reference)v); \
8dd13d0f
VZ
1039 /* \
1040 note that this is the new end(), the old one was \
1041 invalidated by the Append() call, and this is why we \
1042 can't use the same code as in the normal case below \
1043 */ \
1044 iterator itins(end()); \
1045 return --itins; \
1046 } \
b9f9065e 1047 else \
8dd13d0f 1048 { \
b9f9065e 1049 Insert(it.m_node, (const_base_reference)v); \
8dd13d0f
VZ
1050 iterator itins(it); \
1051 return --itins; \
1052 } \
df5168c4 1053 } \
b547eb0f 1054 void insert(const iterator& it, size_type n, const_reference v) \
df5168c4
MB
1055 { \
1056 for(size_type i = 0; i < n; ++i) \
ab13878f 1057 insert(it, v); \
df5168c4 1058 } \
b547eb0f 1059 void insert(const iterator& it, \
b9f9065e 1060 const_iterator first, const const_iterator& last) \
df5168c4
MB
1061 { \
1062 for(; first != last; ++first) \
ab13878f 1063 insert(it, *first); \
df5168c4 1064 } \
60d8e886 1065 iterator erase(const iterator& it) \
df5168c4
MB
1066 { \
1067 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1068 DeleteNode(it.m_node); return next; \
1069 } \
60d8e886 1070 iterator erase(const iterator& first, const iterator& last) \
df5168c4 1071 { \
1416fc5f
VZ
1072 iterator next = last; \
1073 if ( next != end() ) \
1074 ++next; \
df5168c4
MB
1075 DeleteNodes(first.m_node, last.m_node); \
1076 return next; \
1077 } \
1078 void clear() { Clear(); } \
60d8e886 1079 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
df5168c4 1080 { insert(it, first, last); l.erase(first, last); } \
60d8e886 1081 void splice(const iterator& it, name& l) \
df5168c4 1082 { splice(it, l, l.begin(), l.end() ); } \
60d8e886 1083 void splice(const iterator& it, name& l, const iterator& first) \
df5168c4 1084 { \
7b8b72b5
VZ
1085 if ( it != first ) \
1086 { \
1087 insert(it, *first); \
1088 l.erase(first); \
1089 } \
df5168c4
MB
1090 } \
1091 void remove(const_reference v) \
1092 { DeleteObject((const_base_reference)v); } \
1093 void reverse() \
1094 { Reverse(); } \
1095 /* void swap(name& l) \
1096 { \
1097 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1098 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1099 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1100 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1101 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1102 } */ \
385bcb35 1103 }
fd3f686c 1104
6de44038
VZ
1105#define WX_LIST_PTROP \
1106 pointer_type operator->() const \
1107 { return (pointer_type)m_node->GetDataPtr(); }
1108#define WX_LIST_PTROP_NONE
1109
1110#define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1111 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1112#define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1113 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1114
f6bcfd97
BP
1115#define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1116 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
6de44038
VZ
1117#define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1118 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
f03fc89f 1119
fd3f686c
VZ
1120#define WX_DECLARE_LIST(elementtype, listname) \
1121 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
f6bcfd97 1122 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
6de44038
VZ
1123#define WX_DECLARE_LIST_PTR(elementtype, listname) \
1124 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1125 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
f6bcfd97 1126
45c1de35 1127#define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
f6bcfd97 1128 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
45c1de35 1129 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
f644b28c 1130
45c1de35 1131#define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
53a2db12 1132 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
45c1de35 1133
6de44038
VZ
1134#define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1135 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
53a2db12 1136 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLIMPEXP_CORE)
fd3f686c 1137
0b9ab0bd
RL
1138#define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1139 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1140 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
6de44038
VZ
1141#define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1142 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1143 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
0b9ab0bd 1144
fd3f686c 1145// this macro must be inserted in your program after
c0089c96 1146// #include "wx/listimpl.cpp"
fd3f686c
VZ
1147#define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1148
0b9ab0bd
RL
1149#define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1150#define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1151
01871bf6 1152#endif // !wxUSE_STD_CONTAINERS
0b9ab0bd 1153
69b9f4cc 1154// ============================================================================
fd3f686c 1155// now we can define classes 100% compatible with the old ones
69b9f4cc 1156// ============================================================================
fd3f686c 1157
e146b8c8 1158// ----------------------------------------------------------------------------
f03fc89f 1159// commonly used list classes
e146b8c8
VZ
1160// ----------------------------------------------------------------------------
1161
69b9f4cc 1162#if defined(wxLIST_COMPATIBILITY)
fd3f686c 1163
137b7303
VZ
1164// inline compatibility functions
1165
01871bf6 1166#if !wxUSE_STD_CONTAINERS
69b9f4cc
MB
1167
1168// ----------------------------------------------------------------------------
137b7303 1169// wxNodeBase deprecated methods
69b9f4cc 1170// ----------------------------------------------------------------------------
137b7303
VZ
1171
1172inline wxNode *wxNodeBase::Next() const { return (wxNode *)GetNext(); }
1173inline wxNode *wxNodeBase::Previous() const { return (wxNode *)GetPrevious(); }
1174inline wxObject *wxNodeBase::Data() const { return (wxObject *)GetData(); }
1175
69b9f4cc 1176// ----------------------------------------------------------------------------
137b7303 1177// wxListBase deprecated methods
69b9f4cc 1178// ----------------------------------------------------------------------------
137b7303
VZ
1179
1180inline int wxListBase::Number() const { return (int)GetCount(); }
1181inline wxNode *wxListBase::First() const { return (wxNode *)GetFirst(); }
1182inline wxNode *wxListBase::Last() const { return (wxNode *)GetLast(); }
1183inline wxNode *wxListBase::Nth(size_t n) const { return (wxNode *)Item(n); }
1184inline wxListBase::operator wxList&() const { return *(wxList*)this; }
1185
69b9f4cc 1186#endif
137b7303 1187
b1d4dd7a
RL
1188// define this to make a lot of noise about use of the old wxList classes.
1189//#define wxWARN_COMPAT_LIST_USE
1190
69b9f4cc 1191// ----------------------------------------------------------------------------
fd3f686c 1192// wxList compatibility class: in fact, it's a list of wxObjects
69b9f4cc 1193// ----------------------------------------------------------------------------
6de44038
VZ
1194
1195WX_DECLARE_LIST_2(wxObject, wxObjectList, wxObjectListNode,
1196 class WXDLLIMPEXP_BASE);
fd3f686c 1197
bddd7a8d 1198class WXDLLIMPEXP_BASE wxList : public wxObjectList
c801d85f 1199{
fd3f686c 1200public:
01871bf6 1201#if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STD_CONTAINERS
6dd0883d 1202 wxList() { }
728c62b6 1203 wxDEPRECATED( wxList(int key_type) );
01871bf6 1204#elif !wxUSE_STD_CONTAINERS
b1d4dd7a
RL
1205 wxList(int key_type = wxKEY_NONE);
1206#endif
1207
799ea011 1208 // this destructor is required for Darwin
f11bdd03 1209 ~wxList() { }
fd3f686c 1210
01871bf6 1211#if !wxUSE_STD_CONTAINERS
f6bcfd97 1212 wxList& operator=(const wxList& list)
162e998c 1213 { if (&list != this) Assign(list); return *this; }
f6bcfd97 1214
fd3f686c 1215 // compatibility methods
3bef6c4c 1216 void Sort(wxSortCompareFunction compfunc) { wxListBase::Sort(compfunc); }
01871bf6 1217#endif // !wxUSE_STD_CONTAINERS
c801d85f
KB
1218};
1219
01871bf6 1220#if !wxUSE_STD_CONTAINERS
df5168c4 1221
fd3f686c
VZ
1222// -----------------------------------------------------------------------------
1223// wxStringList class for compatibility with the old code
1224// -----------------------------------------------------------------------------
bddd7a8d 1225WX_DECLARE_LIST_2(wxChar, wxStringListBase, wxStringListNode, class WXDLLIMPEXP_BASE);
fd3f686c 1226
bddd7a8d 1227class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
c801d85f 1228{
fd3f686c
VZ
1229public:
1230 // ctors and such
1231 // default
b1d4dd7a 1232#ifdef wxWARN_COMPAT_LIST_USE
728c62b6 1233 wxStringList();
8a7afe4d 1234 wxDEPRECATED( wxStringList(const wxChar *first ...) ); // FIXME-UTF8
b1d4dd7a
RL
1235#else
1236 wxStringList();
8a7afe4d 1237 wxStringList(const wxChar *first ...); // FIXME-UTF8
b1d4dd7a 1238#endif
fd3f686c 1239
db9504c5
VZ
1240 // copying the string list: the strings are copied, too (extremely
1241 // inefficient!)
f644b28c 1242 wxStringList(const wxStringList& other) : wxStringListBase() { DeleteContents(true); DoCopy(other); }
db9504c5 1243 wxStringList& operator=(const wxStringList& other)
162e998c
PC
1244 {
1245 if (&other != this)
1246 {
1247 Clear();
1248 DoCopy(other);
1249 }
1250 return *this;
1251 }
db9504c5 1252
fd3f686c
VZ
1253 // operations
1254 // makes a copy of the string
f526f752 1255 wxNode *Add(const wxChar *s);
f644b28c 1256
890f8a7c 1257 // Append to beginning of list
f526f752 1258 wxNode *Prepend(const wxChar *s);
fd3f686c 1259
9d2f3c71 1260 bool Delete(const wxChar *s);
fd3f686c 1261
f644b28c 1262 wxChar **ListToArray(bool new_copies = false) const;
9d2f3c71 1263 bool Member(const wxChar *s) const;
fd3f686c
VZ
1264
1265 // alphabetic sort
1266 void Sort();
1267
db9504c5
VZ
1268private:
1269 void DoCopy(const wxStringList&); // common part of copy ctor and operator=
c801d85f
KB
1270};
1271
01871bf6 1272#else // if wxUSE_STD_CONTAINERS
df5168c4 1273
f455ffb2 1274WX_DECLARE_LIST_XO(wxString, wxStringListBase, class WXDLLIMPEXP_BASE);
df5168c4 1275
f455ffb2 1276class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
df5168c4
MB
1277{
1278public:
fd82f4e6
MB
1279 compatibility_iterator Append(wxChar* s)
1280 { wxString tmp = s; delete[] s; return wxStringListBase::Append(tmp); }
1281 compatibility_iterator Insert(wxChar* s)
1282 { wxString tmp = s; delete[] s; return wxStringListBase::Insert(tmp); }
1283 compatibility_iterator Insert(size_t pos, wxChar* s)
1284 {
1285 wxString tmp = s;
1286 delete[] s;
1287 return wxStringListBase::Insert(pos, tmp);
1288 }
1289 compatibility_iterator Add(const wxChar* s)
1290 { push_back(s); return GetLast(); }
1291 compatibility_iterator Prepend(const wxChar* s)
1292 { push_front(s); return GetFirst(); }
df5168c4
MB
1293};
1294
01871bf6 1295#endif // wxUSE_STD_CONTAINERS
df5168c4 1296
fd3f686c
VZ
1297#endif // wxLIST_COMPATIBILITY
1298
df5168c4
MB
1299// delete all list elements
1300//
1301// NB: the class declaration of the list elements must be visible from the
1302// place where you use this macro, otherwise the proper destructor may not
1303// be called (a decent compiler should give a warning about it, but don't
1304// count on it)!
1305#define WX_CLEAR_LIST(type, list) \
1306 { \
1307 type::iterator it, en; \
1308 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1309 delete *it; \
1310 (list).clear(); \
1311 }
1312
d48b06bd
FM
1313// append all element of one list to another one
1314#define WX_APPEND_LIST(list, other) \
1315 { \
1316 wxList::compatibility_iterator node = other->GetFirst(); \
1317 while ( node ) \
1318 { \
1319 (list)->push_back(node->GetData()); \
1320 node = node->GetNext(); \
1321 } \
1322 }
1323
c0089c96 1324#endif // _WX_LISTH__