]> git.saurik.com Git - wxWidgets.git/blob - include/wx/list.h
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / include / wx / list.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/list.h
3 // Purpose: wxList, wxStringList classes
4 // Author: Julian Smart
5 // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
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
25 #ifndef _WX_LIST_H_
26 #define _WX_LIST_H_
27
28 // -----------------------------------------------------------------------------
29 // headers
30 // -----------------------------------------------------------------------------
31
32 #include "wx/defs.h"
33 #include "wx/object.h"
34 #include "wx/string.h"
35
36 #if wxUSE_STD_CONTAINERS
37 #include "wx/beforestd.h"
38 #include <algorithm>
39 #include <iterator>
40 #include <list>
41 #include "wx/afterstd.h"
42 #endif
43
44 // ----------------------------------------------------------------------------
45 // types
46 // ----------------------------------------------------------------------------
47
48 class WXDLLIMPEXP_FWD_BASE wxObjectListNode;
49 typedef wxObjectListNode wxNode;
50
51 #if wxUSE_STD_CONTAINERS
52
53 #define wxLIST_COMPATIBILITY
54
55 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
56 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
57 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
58 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
59
60 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
61 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
62 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
63 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
64
65 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
66 WX_DECLARE_LIST_XO(elT*, liT, decl)
67
68 #if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
69
70 template<class T>
71 class wxList_SortFunction
72 {
73 public:
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; }
77 private:
78 wxSortCompareFunction m_f;
79 };
80
81 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
82 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl)
83
84 #else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
85
86 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
87 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
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 ? \
103 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
104 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
105 ( X > Y ); \
106 } \
107 };
108
109 // helper for std::greater<elT> above:
110 template<typename T>
111 inline const void *wxListCastElementToVoidPtr(const T* ptr) { return ptr; }
112 inline const void *wxListCastElementToVoidPtr(const wxString& str)
113 { return (const char*)str; }
114
115 #endif // VC6/!VC6
116
117 /*
118 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
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
122 struct WXDLLIMPEXP_CORE Foo
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
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.
144 */
145
146 // the real wxList-class declaration
147 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
148 decl _WX_LIST_HELPER_##liT \
149 { \
150 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
151 typedef std::list<elT> BaseListType; \
152 public: \
153 static BaseListType EmptyList; \
154 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
155 }; \
156 \
157 WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
158 class liT : public std::list<elT> \
159 { \
160 private: \
161 typedef std::list<elT> BaseListType; \
162 \
163 bool m_destroy; \
164 \
165 public: \
166 class compatibility_iterator \
167 { \
168 private: \
169 /* Workaround for broken VC6 nested class name resolution */ \
170 typedef std::list<elT>::iterator iterator; \
171 friend class liT; \
172 \
173 iterator m_iter; \
174 liT * m_list; \
175 \
176 public: \
177 compatibility_iterator() \
178 : m_iter(_WX_LIST_HELPER_##liT::EmptyList.end()), m_list( NULL ) {} \
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 \
187 bool operator==(const compatibility_iterator& i) const \
188 { \
189 wxASSERT_MSG( m_list && i.m_list, \
190 wxT("comparing invalid iterators is illegal") ); \
191 return (m_list == i.m_list) && (m_iter == i.m_iter); \
192 } \
193 bool operator!=(const compatibility_iterator& i) const \
194 { return !( operator==( i ) ); } \
195 operator bool() const \
196 { return m_list ? m_iter != m_list->end() : false; } \
197 bool operator !() const \
198 { return !( operator bool() ); } \
199 \
200 elT GetData() const \
201 { return *m_iter; } \
202 void SetData( elT e ) \
203 { *m_iter = e; } \
204 \
205 compatibility_iterator GetNext() const \
206 { \
207 iterator i = m_iter; \
208 return compatibility_iterator( m_list, ++i ); \
209 } \
210 compatibility_iterator GetPrevious() const \
211 { \
212 if ( m_iter == m_list->begin() ) \
213 return compatibility_iterator(); \
214 \
215 iterator i = m_iter; \
216 return compatibility_iterator( m_list, --i ); \
217 } \
218 int IndexOf() const \
219 { \
220 return *this ? std::distance( m_list->begin(), m_iter ) \
221 : wxNOT_FOUND; \
222 } \
223 }; \
224 public: \
225 liT() : m_destroy( false ) {} \
226 \
227 compatibility_iterator Find( const elT e ) const \
228 { \
229 liT* _this = const_cast< liT* >( this ); \
230 return compatibility_iterator( _this, \
231 std::find( _this->begin(), _this->end(), e ) ); \
232 } \
233 \
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 \
242 { \
243 iterator i = const_cast< liT* >(this)->begin(); \
244 std::advance( i, idx ); \
245 return compatibility_iterator( this, i ); \
246 } \
247 elT operator[](size_t idx) const \
248 { \
249 return Item(idx).GetData(); \
250 } \
251 \
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 } \
262 bool Member( elT e ) const \
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 } \
279 compatibility_iterator Insert(const compatibility_iterator & i, elT e)\
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 ) \
296 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
297 erase( i.m_iter ); \
298 } \
299 bool DeleteNode( const compatibility_iterator& i ) \
300 { \
301 if( i ) \
302 { \
303 Erase( i ); \
304 return true; \
305 } \
306 return false; \
307 } \
308 bool DeleteObject( elT e ) \
309 { \
310 return DeleteNode( Find( e ) ); \
311 } \
312 void Clear() \
313 { \
314 if ( m_destroy ) \
315 std::for_each( begin(), end(), \
316 _WX_LIST_HELPER_##liT::DeleteFunction ); \
317 clear(); \
318 } \
319 /* Workaround for broken VC6 std::list::sort() see above */ \
320 void Sort( wxSortCompareFunction compfunc ) \
321 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
322 ~liT() { Clear(); } \
323 \
324 /* It needs access to our EmptyList */ \
325 friend class compatibility_iterator; \
326 }
327
328 #define WX_DECLARE_LIST(elementtype, listname) \
329 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
330 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
331 WX_DECLARE_LIST(elementtype, listname)
332
333 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
334 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
335 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
336 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
337
338 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
339 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
340 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
341 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
342
343 // this macro must be inserted in your program after
344 // #include "wx/listimpl.cpp"
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
350 #else // if !wxUSE_STD_CONTAINERS
351
352
353 // undef it to get rid of old, deprecated functions
354 #define wxLIST_COMPATIBILITY
355
356 // -----------------------------------------------------------------------------
357 // key stuff: a list may be optionally keyed on integer or string key
358 // -----------------------------------------------------------------------------
359
360 union wxListKeyValue
361 {
362 long integer;
363 wxString *string;
364 };
365
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 *).
372 class WXDLLIMPEXP_BASE wxListKey
373 {
374 public:
375 // implicit ctors
376 wxListKey() : m_keyType(wxKEY_NONE)
377 { }
378 wxListKey(long i) : m_keyType(wxKEY_INTEGER)
379 { m_key.integer = i; }
380 wxListKey(const wxString& s) : m_keyType(wxKEY_STRING)
381 { m_key.string = new wxString(s); }
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); }
386
387 // accessors
388 wxKeyType GetKeyType() const { return m_keyType; }
389 const wxString GetString() const
390 { wxASSERT( m_keyType == wxKEY_STRING ); return *m_key.string; }
391 long GetNumber() const
392 { wxASSERT( m_keyType == wxKEY_INTEGER ); return m_key.integer; }
393
394 // comparison
395 // Note: implementation moved to list.cpp to prevent BC++ inline
396 // expansion warning.
397 bool operator==(wxListKeyValue value) const ;
398
399 // dtor
400 ~wxListKey()
401 {
402 if ( m_keyType == wxKEY_STRING )
403 delete m_key.string;
404 }
405
406 private:
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
415 extern WXDLLIMPEXP_DATA_BASE(wxListKey) wxDefaultListKey;
416
417 class WXDLLIMPEXP_FWD_BASE wxListBase;
418
419 class WXDLLIMPEXP_BASE wxNodeBase
420 {
421 friend class wxListBase;
422 public:
423 // ctor
424 wxNodeBase(wxListBase *list = NULL,
425 wxNodeBase *previous = NULL,
426 wxNodeBase *next = NULL,
427 void *data = NULL,
428 const wxListKey& key = wxDefaultListKey);
429
430 virtual ~wxNodeBase();
431
432 // FIXME no check is done that the list is really keyed on strings
433 wxString GetKeyString() const { return *m_key.string; }
434 long GetKeyInteger() const { return m_key.integer; }
435
436 // Necessary for some existing code
437 void SetKeyString(const wxString& s) { m_key.string = new wxString(s); }
438 void SetKeyInteger(long i) { m_key.integer = i; }
439
440 #ifdef wxLIST_COMPATIBILITY
441 // compatibility methods, use Get* instead.
442 wxDEPRECATED( wxNode *Next() const );
443 wxDEPRECATED( wxNode *Previous() const );
444 wxDEPRECATED( wxObject *Data() const );
445 #endif // wxLIST_COMPATIBILITY
446
447 protected:
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
455 // get 0-based index of this node within the list or wxNOT_FOUND
456 int IndexOf() const;
457
458 virtual void DeleteData() { }
459 public:
460 // for wxList::iterator
461 void** GetDataPtr() const { return &(const_cast<wxNodeBase*>(this)->m_data); }
462 private:
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
471
472 wxDECLARE_NO_COPY_CLASS(wxNodeBase);
473 };
474
475 // -----------------------------------------------------------------------------
476 // a double-linked list class
477 // -----------------------------------------------------------------------------
478
479 class WXDLLIMPEXP_FWD_BASE wxList;
480
481 class WXDLLIMPEXP_BASE wxListBase
482 {
483 friend class wxNodeBase; // should be able to call DetachNode()
484 friend class wxHashTableBase; // should be able to call untyped Find()
485
486 public:
487 // default ctor & dtor
488 wxListBase(wxKeyType keyType = wxKEY_NONE)
489 { Init(keyType); }
490 virtual ~wxListBase();
491
492 // accessors
493 // count of items in the list
494 size_t GetCount() const { return m_count; }
495
496 // return true if this list is empty
497 bool IsEmpty() const { return m_count == 0; }
498
499 // operations
500
501 // delete all nodes
502 void Clear();
503
504 // instruct it to destroy user data when deleting nodes
505 void DeleteContents(bool destroy) { m_destroy = destroy; }
506
507 // query if to delete
508 bool GetDeleteContents() const
509 { return m_destroy; }
510
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
519 #ifdef wxLIST_COMPATIBILITY
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 );
528 #endif // wxLIST_COMPATIBILITY
529
530 protected:
531
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,
538 const wxListKey& key = wxDefaultListKey) = 0;
539
540
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
547 protected:
548 void Assign(const wxListBase& list)
549 { Clear(); DoCopy(list); }
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
559 void *operator[](size_t n) const
560 {
561 wxNodeBase *node = Item(n);
562
563 return node ? node->GetData() : NULL;
564 }
565
566 // operations
567 // append to end of list
568 wxNodeBase *Prepend(void *object)
569 { return (wxNodeBase *)wxListBase::Insert(object); }
570 // append to beginning of list
571 wxNodeBase *Append(void *object);
572 // insert a new item at the beginning of the list
573 wxNodeBase *Insert(void *object)
574 { return Insert(static_cast<wxNodeBase *>(NULL), object); }
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); }
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);
584 wxNodeBase *Append(const wxString& key, void *object);
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);
589 // delete element from list, returns false if node not found
590 bool DeleteNode(wxNodeBase *node);
591 // finds object pointer and deletes node (and object if DeleteContents
592 // is on), returns false if object not found
593 bool DeleteObject(void *object);
594
595 // search (all return NULL if item not found)
596 // by data
597 wxNodeBase *Find(const void *object) const;
598
599 // by key
600 wxNodeBase *Find(const wxListKey& key) const;
601
602 // get 0-based index of object or wxNOT_FOUND
603 int IndexOf( void *object ) const;
604
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.
607 void Sort(const wxSortCompareFunction compfunc);
608
609 // functions for iterating over the list
610 void *FirstThat(wxListIterateFunction func);
611 void ForEach(wxListIterateFunction func);
612 void *LastThat(wxListIterateFunction func);
613
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);
618 private:
619
620 // common part of all ctors
621 void Init(wxKeyType keyType = wxKEY_NONE);
622
623 // helpers
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
647 // wxNode-derived type)
648 //
649 // implementation details:
650 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
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 //
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
656 // time error checking.
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.
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)
670
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) \
673 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
674 \
675 classexp nodetype : public wxNodeBase \
676 { \
677 public: \
678 nodetype(wxListBase *list = NULL, \
679 nodetype *previous = NULL, \
680 nodetype *next = NULL, \
681 T *data = NULL, \
682 const wxListKey& key = wxDefaultListKey) \
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 \
695 protected: \
696 virtual void DeleteData(); \
697 \
698 DECLARE_NO_COPY_CLASS(nodetype) \
699 }; \
700 \
701 classexp name : public wxListBase \
702 { \
703 public: \
704 typedef nodetype Node; \
705 classexp compatibility_iterator \
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 }; \
716 \
717 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
718 { } \
719 name(const name& list) : wxListBase(list.GetKeyType()) \
720 { Assign(list); } \
721 name(size_t count, T *elements[]) \
722 : wxListBase(count, (void **)elements) { } \
723 \
724 name& operator=(const name& list) \
725 { if (&list != this) Assign(list); return *this; } \
726 \
727 nodetype *GetFirst() const \
728 { return (nodetype *)wxListBase::GetFirst(); } \
729 nodetype *GetLast() const \
730 { return (nodetype *)wxListBase::GetLast(); } \
731 \
732 nodetype *Item(size_t index) const \
733 { return (nodetype *)wxListBase::Item(index); } \
734 \
735 T *operator[](size_t index) const \
736 { \
737 nodetype *node = Item(index); \
738 return node ? (T*)(node->GetData()) : NULL; \
739 } \
740 \
741 nodetype *Append(Tbase *object) \
742 { return (nodetype *)wxListBase::Append(object); } \
743 nodetype *Insert(Tbase *object) \
744 { return (nodetype *)Insert(static_cast<nodetype *>(NULL), \
745 object); } \
746 nodetype *Insert(size_t pos, Tbase *object) \
747 { return (nodetype *)wxListBase::Insert(pos, object); } \
748 nodetype *Insert(nodetype *prev, Tbase *object) \
749 { return (nodetype *)wxListBase::Insert(prev, object); } \
750 \
751 nodetype *Append(long key, void *object) \
752 { return (nodetype *)wxListBase::Append(key, object); } \
753 nodetype *Append(const wxChar *key, void *object) \
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); } \
760 bool DeleteObject(Tbase *object) \
761 { return wxListBase::DeleteObject(object); } \
762 void Erase(nodetype *it) \
763 { DeleteNode(it); } \
764 \
765 nodetype *Find(const Tbase *object) const \
766 { return (nodetype *)wxListBase::Find(object); } \
767 \
768 virtual nodetype *Find(const wxListKey& key) const \
769 { return (nodetype *)wxListBase::Find(key); } \
770 \
771 bool Member(const Tbase *object) const \
772 { return Find(object) != NULL; } \
773 \
774 int IndexOf(Tbase *object) const \
775 { return wxListBase::IndexOf(object); } \
776 \
777 void Sort(wxSortCompareFunction func) \
778 { wxListBase::Sort(func); } \
779 void Sort(wxSortFuncFor_##name func) \
780 { Sort((wxSortCompareFunction)func); } \
781 \
782 protected: \
783 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
784 void *data, \
785 const wxListKey& key = wxDefaultListKey) \
786 { \
787 return new nodetype(this, \
788 (nodetype *)prev, (nodetype *)next, \
789 (T *)data, key); \
790 } \
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 \
802 classexp iterator \
803 { \
804 typedef name list; \
805 public: \
806 typedef nodetype Node; \
807 typedef iterator itor; \
808 typedef T* value_type; \
809 typedef value_type* ptr_type; \
810 typedef value_type& reference; \
811 \
812 Node* m_node; \
813 Node* m_init; \
814 public: \
815 typedef reference reference_type; \
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(); } \
822 ptrop \
823 itor& operator++() \
824 { \
825 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
826 m_node = m_node->GetNext(); \
827 return *this; \
828 } \
829 const itor operator++(int) \
830 { \
831 itor tmp = *this; \
832 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
833 m_node = m_node->GetNext(); \
834 return tmp; \
835 } \
836 itor& operator--() \
837 { \
838 m_node = m_node ? m_node->GetPrevious() : m_init; \
839 return *this; \
840 } \
841 const itor operator--(int) \
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 }; \
852 classexp const_iterator \
853 { \
854 typedef name list; \
855 public: \
856 typedef nodetype Node; \
857 typedef T* value_type; \
858 typedef const value_type& const_reference; \
859 typedef const_iterator itor; \
860 typedef value_type* ptr_type; \
861 \
862 Node* m_node; \
863 Node* m_init; \
864 public: \
865 typedef const_reference reference_type; \
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(); } \
875 ptrop \
876 itor& operator++() \
877 { \
878 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
879 m_node = m_node->GetNext(); \
880 return *this; \
881 } \
882 const itor operator++(int) \
883 { \
884 itor tmp = *this; \
885 wxASSERT_MSG( m_node, wxT("uninitialized iterator") ); \
886 m_node = m_node->GetNext(); \
887 return tmp; \
888 } \
889 itor& operator--() \
890 { \
891 m_node = m_node ? m_node->GetPrevious() : m_init; \
892 return *this; \
893 } \
894 const itor operator--(int) \
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 }; \
905 classexp reverse_iterator \
906 { \
907 typedef name list; \
908 public: \
909 typedef nodetype Node; \
910 typedef T* value_type; \
911 typedef reverse_iterator itor; \
912 typedef value_type* ptr_type; \
913 typedef value_type& reference; \
914 \
915 Node* m_node; \
916 Node* m_init; \
917 public: \
918 typedef reference reference_type; \
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(); } \
926 ptrop \
927 itor& operator++() \
928 { m_node = m_node->GetPrevious(); return *this; } \
929 const itor operator++(int) \
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; } \
933 const itor operator--(int) \
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 }; \
944 classexp const_reverse_iterator \
945 { \
946 typedef name list; \
947 public: \
948 typedef nodetype Node; \
949 typedef T* value_type; \
950 typedef const_reverse_iterator itor; \
951 typedef value_type* ptr_type; \
952 typedef const value_type& const_reference; \
953 \
954 Node* m_node; \
955 Node* m_init; \
956 public: \
957 typedef const_reference reference_type; \
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(); } \
967 ptrop \
968 itor& operator++() \
969 { m_node = m_node->GetPrevious(); return *this; } \
970 const itor operator++(int) \
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;}\
974 const itor operator--(int) \
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); } \
988 name(const const_iterator& first, const const_iterator& last) \
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 { \
1004 while (n < size()) \
1005 pop_back(); \
1006 while (n > size()) \
1007 push_back(v); \
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(); } \
1014 reference back() { iterator tmp = end(); return *--tmp; } \
1015 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
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()); } \
1022 void assign(const_iterator first, const const_iterator& last) \
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 } \
1034 iterator insert(const iterator& it, const_reference v) \
1035 { \
1036 if ( it == end() ) \
1037 { \
1038 Append((const_base_reference)v); \
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 } \
1047 else \
1048 { \
1049 Insert(it.m_node, (const_base_reference)v); \
1050 iterator itins(it); \
1051 return --itins; \
1052 } \
1053 } \
1054 void insert(const iterator& it, size_type n, const_reference v) \
1055 { \
1056 for(size_type i = 0; i < n; ++i) \
1057 insert(it, v); \
1058 } \
1059 void insert(const iterator& it, \
1060 const_iterator first, const const_iterator& last) \
1061 { \
1062 for(; first != last; ++first) \
1063 insert(it, *first); \
1064 } \
1065 iterator erase(const iterator& it) \
1066 { \
1067 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1068 DeleteNode(it.m_node); return next; \
1069 } \
1070 iterator erase(const iterator& first, const iterator& last) \
1071 { \
1072 iterator next = last; \
1073 if ( next != end() ) \
1074 ++next; \
1075 DeleteNodes(first.m_node, last.m_node); \
1076 return next; \
1077 } \
1078 void clear() { Clear(); } \
1079 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1080 { insert(it, first, last); l.erase(first, last); } \
1081 void splice(const iterator& it, name& l) \
1082 { splice(it, l, l.begin(), l.end() ); } \
1083 void splice(const iterator& it, name& l, const iterator& first) \
1084 { \
1085 if ( it != first ) \
1086 { \
1087 insert(it, *first); \
1088 l.erase(first); \
1089 } \
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 } */ \
1103 }
1104
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
1115 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1116 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1117 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1118 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1119
1120 #define WX_DECLARE_LIST(elementtype, listname) \
1121 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1122 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
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)
1126
1127 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1128 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1129 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1130
1131 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1132 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
1133
1134 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1135 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1136 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLIMPEXP_CORE)
1137
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)
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)
1144
1145 // this macro must be inserted in your program after
1146 // #include "wx/listimpl.cpp"
1147 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1148
1149 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1150 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1151
1152 #endif // !wxUSE_STD_CONTAINERS
1153
1154 // ============================================================================
1155 // now we can define classes 100% compatible with the old ones
1156 // ============================================================================
1157
1158 // ----------------------------------------------------------------------------
1159 // commonly used list classes
1160 // ----------------------------------------------------------------------------
1161
1162 #if defined(wxLIST_COMPATIBILITY)
1163
1164 // inline compatibility functions
1165
1166 #if !wxUSE_STD_CONTAINERS
1167
1168 // ----------------------------------------------------------------------------
1169 // wxNodeBase deprecated methods
1170 // ----------------------------------------------------------------------------
1171
1172 inline wxNode *wxNodeBase::Next() const { return (wxNode *)GetNext(); }
1173 inline wxNode *wxNodeBase::Previous() const { return (wxNode *)GetPrevious(); }
1174 inline wxObject *wxNodeBase::Data() const { return (wxObject *)GetData(); }
1175
1176 // ----------------------------------------------------------------------------
1177 // wxListBase deprecated methods
1178 // ----------------------------------------------------------------------------
1179
1180 inline int wxListBase::Number() const { return (int)GetCount(); }
1181 inline wxNode *wxListBase::First() const { return (wxNode *)GetFirst(); }
1182 inline wxNode *wxListBase::Last() const { return (wxNode *)GetLast(); }
1183 inline wxNode *wxListBase::Nth(size_t n) const { return (wxNode *)Item(n); }
1184 inline wxListBase::operator wxList&() const { return *(wxList*)this; }
1185
1186 #endif
1187
1188 // define this to make a lot of noise about use of the old wxList classes.
1189 //#define wxWARN_COMPAT_LIST_USE
1190
1191 // ----------------------------------------------------------------------------
1192 // wxList compatibility class: in fact, it's a list of wxObjects
1193 // ----------------------------------------------------------------------------
1194
1195 WX_DECLARE_LIST_2(wxObject, wxObjectList, wxObjectListNode,
1196 class WXDLLIMPEXP_BASE);
1197
1198 class WXDLLIMPEXP_BASE wxList : public wxObjectList
1199 {
1200 public:
1201 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STD_CONTAINERS
1202 wxList() { }
1203 wxDEPRECATED( wxList(int key_type) );
1204 #elif !wxUSE_STD_CONTAINERS
1205 wxList(int key_type = wxKEY_NONE);
1206 #endif
1207
1208 // this destructor is required for Darwin
1209 ~wxList() { }
1210
1211 #if !wxUSE_STD_CONTAINERS
1212 wxList& operator=(const wxList& list)
1213 { if (&list != this) Assign(list); return *this; }
1214
1215 // compatibility methods
1216 void Sort(wxSortCompareFunction compfunc) { wxListBase::Sort(compfunc); }
1217 #endif // !wxUSE_STD_CONTAINERS
1218 };
1219
1220 #if !wxUSE_STD_CONTAINERS
1221
1222 // -----------------------------------------------------------------------------
1223 // wxStringList class for compatibility with the old code
1224 // -----------------------------------------------------------------------------
1225 WX_DECLARE_LIST_2(wxChar, wxStringListBase, wxStringListNode, class WXDLLIMPEXP_BASE);
1226
1227 class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1228 {
1229 public:
1230 // ctors and such
1231 // default
1232 #ifdef wxWARN_COMPAT_LIST_USE
1233 wxStringList();
1234 wxDEPRECATED( wxStringList(const wxChar *first ...) ); // FIXME-UTF8
1235 #else
1236 wxStringList();
1237 wxStringList(const wxChar *first ...); // FIXME-UTF8
1238 #endif
1239
1240 // copying the string list: the strings are copied, too (extremely
1241 // inefficient!)
1242 wxStringList(const wxStringList& other) : wxStringListBase() { DeleteContents(true); DoCopy(other); }
1243 wxStringList& operator=(const wxStringList& other)
1244 {
1245 if (&other != this)
1246 {
1247 Clear();
1248 DoCopy(other);
1249 }
1250 return *this;
1251 }
1252
1253 // operations
1254 // makes a copy of the string
1255 wxNode *Add(const wxChar *s);
1256
1257 // Append to beginning of list
1258 wxNode *Prepend(const wxChar *s);
1259
1260 bool Delete(const wxChar *s);
1261
1262 wxChar **ListToArray(bool new_copies = false) const;
1263 bool Member(const wxChar *s) const;
1264
1265 // alphabetic sort
1266 void Sort();
1267
1268 private:
1269 void DoCopy(const wxStringList&); // common part of copy ctor and operator=
1270 };
1271
1272 #else // if wxUSE_STD_CONTAINERS
1273
1274 WX_DECLARE_LIST_XO(wxString, wxStringListBase, class WXDLLIMPEXP_BASE);
1275
1276 class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1277 {
1278 public:
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(); }
1293 };
1294
1295 #endif // wxUSE_STD_CONTAINERS
1296
1297 #endif // wxLIST_COMPATIBILITY
1298
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
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
1324 #endif // _WX_LISTH__