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