1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxList, wxStringList classes
4 // Author: Julian Smart
5 // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
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
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
28 // -----------------------------------------------------------------------------
30 // -----------------------------------------------------------------------------
33 #include "wx/object.h"
34 #include "wx/string.h"
37 #include "wx/beforestd.h"
41 #include "wx/afterstd.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 class WXDLLIMPEXP_FWD_BASE wxObjectListNode
;
49 typedef wxObjectListNode wxNode
;
53 #define wxLIST_COMPATIBILITY
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)
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) \
65 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
66 WX_DECLARE_LIST_XO(elT*, liT, decl)
68 #if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
71 class wxList_SortFunction
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; }
78 wxSortCompareFunction m_f
;
81 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
82 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl)
84 #else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
86 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
87 #define WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
90 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
91 /* to be passed into std::list::sort() */ \
93 struct std::greater<elT> \
96 wxSortCompareFunction m_CompFunc; \
98 greater( wxSortCompareFunction compfunc = NULL ) \
99 : m_CompFunc( compfunc ) {} \
100 bool operator()(const elT X, const elT Y) const \
102 return m_CompFunc ? \
103 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
104 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
109 // helper for std::greater<elT> above:
111 inline const void *wxListCastElementToVoidPtr(const T
* ptr
) { return ptr
; }
112 inline const void *wxListCastElementToVoidPtr(const wxString
& str
)
113 { return (const char*)str
; }
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:
122 struct WXDLLIMPEXP_CORE Foo
125 struct SomeInnerClass
127 friend class Foo; // comment this out to make it link
135 The program does not link under mingw_gcc 3.2.3 producing undefined
136 reference to Foo::Bar() function
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
146 // the real wxList-class declaration
147 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
148 decl _WX_LIST_HELPER_##liT \
150 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
152 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
155 WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
156 decl liT : public std::list<elT> \
159 typedef std::list<elT> BaseListType; \
160 static BaseListType EmptyList; \
165 decl compatibility_iterator \
168 /* Workaround for broken VC6 nested class name resolution */ \
169 typedef std::list<elT>::iterator iterator; \
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 ) ) {} \
183 compatibility_iterator* operator->() { return this; } \
184 const compatibility_iterator* operator->() const { return this; } \
186 bool operator==(const compatibility_iterator& i) const \
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); \
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() ); } \
199 elT GetData() const \
200 { return *m_iter; } \
201 void SetData( elT e ) \
204 compatibility_iterator GetNext() const \
206 iterator i = m_iter; \
207 return compatibility_iterator( m_list, ++i ); \
209 compatibility_iterator GetPrevious() const \
211 if ( m_iter == m_list->begin() ) \
212 return compatibility_iterator(); \
214 iterator i = m_iter; \
215 return compatibility_iterator( m_list, --i ); \
217 int IndexOf() const \
219 return *this ? std::distance( m_list->begin(), m_iter ) \
224 liT() : m_destroy( false ) {} \
226 compatibility_iterator Find( const elT e ) const \
228 liT* _this = const_cast< liT* >( this ); \
229 return compatibility_iterator( _this, \
230 std::find( _this->begin(), _this->end(), e ) ); \
233 bool IsEmpty() const \
234 { return empty(); } \
235 size_t GetCount() const \
238 { return static_cast< int >( GetCount() ); } \
240 compatibility_iterator Item( size_t idx ) const \
242 iterator i = const_cast< liT* >(this)->begin(); \
243 std::advance( i, idx ); \
244 return compatibility_iterator( this, i ); \
246 elT operator[](size_t idx) const \
248 return Item(idx).GetData(); \
251 compatibility_iterator GetFirst() const \
253 return compatibility_iterator( this, \
254 const_cast< liT* >(this)->begin() ); \
256 compatibility_iterator GetLast() const \
258 iterator i = const_cast< liT* >(this)->end(); \
259 return compatibility_iterator( this, !empty() ? --i : i ); \
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(); } \
268 compatibility_iterator Append( elT e ) \
273 compatibility_iterator Insert( elT e ) \
276 return compatibility_iterator( this, begin() ); \
278 compatibility_iterator Insert(const compatibility_iterator & i, elT e)\
280 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
282 compatibility_iterator Insert( size_t idx, elT e ) \
284 return compatibility_iterator( this, \
285 insert( Item( idx ).m_iter, e ) ); \
288 void DeleteContents( bool destroy ) \
289 { m_destroy = destroy; } \
290 bool GetDeleteContents() const \
291 { return m_destroy; } \
292 void Erase( const compatibility_iterator& i ) \
295 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
298 bool DeleteNode( const compatibility_iterator& i ) \
307 bool DeleteObject( elT e ) \
309 return DeleteNode( Find( e ) ); \
314 std::for_each( begin(), end(), \
315 _WX_LIST_HELPER_##liT::DeleteFunction ); \
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(); } \
323 /* It needs access to our EmptyList */ \
324 friend class compatibility_iterator; \
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)
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)
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)
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!"
346 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
347 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
349 #else // if !wxUSE_STL
352 // undef it to get rid of old, deprecated functions
353 #define wxLIST_COMPATIBILITY
355 // -----------------------------------------------------------------------------
356 // key stuff: a list may be optionally keyed on integer or string key
357 // -----------------------------------------------------------------------------
365 // a struct which may contain both types of keys
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
375 wxListKey() : m_keyType(wxKEY_NONE
)
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
); }
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
; }
394 // Note: implementation moved to list.cpp to prevent BC++ inline
395 // expansion warning.
396 bool operator==(wxListKeyValue value
) const ;
401 if ( m_keyType
== wxKEY_STRING
)
407 wxListKeyValue m_key
;
410 // -----------------------------------------------------------------------------
411 // wxNodeBase class is a (base for) node in a double linked list
412 // -----------------------------------------------------------------------------
414 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
416 class WXDLLIMPEXP_FWD_BASE wxListBase
;
418 class WXDLLIMPEXP_BASE wxNodeBase
420 friend class wxListBase
;
423 wxNodeBase(wxListBase
*list
= NULL
,
424 wxNodeBase
*previous
= NULL
,
425 wxNodeBase
*next
= NULL
,
427 const wxListKey
& key
= wxDefaultListKey
);
429 virtual ~wxNodeBase();
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
; }
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
; }
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
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
; }
451 void *GetData() const { return m_data
; }
452 void SetData(void *data
) { m_data
= data
; }
454 // get 0-based index of this node within the list or wxNOT_FOUND
457 virtual void DeleteData() { }
459 // for wxList::iterator
460 void** GetDataPtr() const { return &(const_cast<wxNodeBase
*>(this)->m_data
); }
462 // optional key stuff
463 wxListKeyValue m_key
;
465 void *m_data
; // user data
466 wxNodeBase
*m_next
, // next and previous nodes in the list
469 wxListBase
*m_list
; // list we belong to
471 wxDECLARE_NO_COPY_CLASS(wxNodeBase
);
474 // -----------------------------------------------------------------------------
475 // a double-linked list class
476 // -----------------------------------------------------------------------------
478 class WXDLLIMPEXP_FWD_BASE wxList
;
480 class WXDLLIMPEXP_BASE wxListBase
482 friend class wxNodeBase
; // should be able to call DetachNode()
483 friend class wxHashTableBase
; // should be able to call untyped Find()
486 // default ctor & dtor
487 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
489 virtual ~wxListBase();
492 // count of items in the list
493 size_t GetCount() const { return m_count
; }
495 // return true if this list is empty
496 bool IsEmpty() const { return m_count
== 0; }
503 // instruct it to destroy user data when deleting nodes
504 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
506 // query if to delete
507 bool GetDeleteContents() const
508 { return m_destroy
; }
511 wxKeyType
GetKeyType() const
512 { return m_keyType
; }
514 // set the keytype (required by the serial code)
515 void SetKeyType(wxKeyType keyType
)
516 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
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
525 // kludge for typesafe list migration in core classes.
526 wxDEPRECATED( operator wxList
&() const );
527 #endif // wxLIST_COMPATIBILITY
531 // all methods here are "overloaded" in derived classes to provide compile
532 // time type checking
534 // create a node for the list of this type
535 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
537 const wxListKey
& key
= wxDefaultListKey
) = 0;
542 wxListBase(size_t count
, void *elements
[]);
543 // from a sequence of objects
544 wxListBase(void *object
, ... /* terminate with NULL */);
547 void Assign(const wxListBase
& list
)
548 { Clear(); DoCopy(list
); }
550 // get list head/tail
551 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
552 wxNodeBase
*GetLast() const { return m_nodeLast
; }
554 // by (0-based) index
555 wxNodeBase
*Item(size_t index
) const;
557 // get the list item's data
558 void *operator[](size_t n
) const
560 wxNodeBase
*node
= Item(n
);
562 return node
? node
->GetData() : NULL
;
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
);
582 wxNodeBase
*Append(long key
, void *object
);
583 wxNodeBase
*Append(const wxString
& key
, void *object
);
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
);
594 // search (all return NULL if item not found)
596 wxNodeBase
*Find(const void *object
) const;
599 wxNodeBase
*Find(const wxListKey
& key
) const;
601 // get 0-based index of object or wxNOT_FOUND
602 int IndexOf( void *object
) const;
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
);
608 // functions for iterating over the list
609 void *FirstThat(wxListIterateFunction func
);
610 void ForEach(wxListIterateFunction func
);
611 void *LastThat(wxListIterateFunction func
);
613 // for STL interface, "last" points to one after the last node
614 // of the controlled sequence (NULL for the end of the list)
616 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
619 // common part of all ctors
620 void Init(wxKeyType keyType
= wxKEY_NONE
);
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
);
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
635 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
638 // -----------------------------------------------------------------------------
639 // macros for definition of "template" list type
640 // -----------------------------------------------------------------------------
642 // and now some heavy magic...
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)
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
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.
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.
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)
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 **); \
674 classexp nodetype : public wxNodeBase \
677 nodetype(wxListBase *list = NULL, \
678 nodetype *previous = NULL, \
679 nodetype *next = NULL, \
681 const wxListKey& key = wxDefaultListKey) \
682 : wxNodeBase(list, previous, next, data, key) { } \
684 nodetype *GetNext() const \
685 { return (nodetype *)wxNodeBase::GetNext(); } \
686 nodetype *GetPrevious() const \
687 { return (nodetype *)wxNodeBase::GetPrevious(); } \
690 { return (T *)wxNodeBase::GetData(); } \
691 void SetData(T *data) \
692 { wxNodeBase::SetData(data); } \
695 virtual void DeleteData(); \
697 DECLARE_NO_COPY_CLASS(nodetype) \
700 classexp name : public wxListBase \
703 typedef nodetype Node; \
704 classexp compatibility_iterator \
707 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
709 Node *operator->() const { return m_ptr; } \
710 operator Node *() const { return m_ptr; } \
716 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
718 name(const name& list) : wxListBase(list.GetKeyType()) \
720 name(size_t count, T *elements[]) \
721 : wxListBase(count, (void **)elements) { } \
723 name& operator=(const name& list) \
724 { if (&list != this) Assign(list); return *this; } \
726 nodetype *GetFirst() const \
727 { return (nodetype *)wxListBase::GetFirst(); } \
728 nodetype *GetLast() const \
729 { return (nodetype *)wxListBase::GetLast(); } \
731 nodetype *Item(size_t index) const \
732 { return (nodetype *)wxListBase::Item(index); } \
734 T *operator[](size_t index) const \
736 nodetype *node = Item(index); \
737 return node ? (T*)(node->GetData()) : NULL; \
740 nodetype *Append(Tbase *object) \
741 { return (nodetype *)wxListBase::Append(object); } \
742 nodetype *Insert(Tbase *object) \
743 { return (nodetype *)Insert(static_cast<nodetype *>(NULL), \
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); } \
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); } \
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); } \
764 nodetype *Find(const Tbase *object) const \
765 { return (nodetype *)wxListBase::Find(object); } \
767 virtual nodetype *Find(const wxListKey& key) const \
768 { return (nodetype *)wxListBase::Find(key); } \
770 bool Member(const Tbase *object) const \
771 { return Find(object) != NULL; } \
773 int IndexOf(Tbase *object) const \
774 { return wxListBase::IndexOf(object); } \
776 void Sort(wxSortCompareFunction func) \
777 { wxListBase::Sort(func); } \
778 void Sort(wxSortFuncFor_##name func) \
779 { Sort((wxSortCompareFunction)func); } \
782 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
784 const wxListKey& key = wxDefaultListKey) \
786 return new nodetype(this, \
787 (nodetype *)prev, (nodetype *)next, \
790 /* STL interface */ \
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; \
805 typedef nodetype Node; \
806 typedef iterator itor; \
807 typedef T* value_type; \
808 typedef value_type* ptr_type; \
809 typedef value_type& reference; \
814 typedef reference reference_type; \
815 typedef ptr_type pointer_type; \
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(); } \
822 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
823 const itor operator++(int) \
824 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
827 m_node = m_node ? m_node->GetPrevious() : m_init; \
830 const itor operator--(int) \
833 m_node = m_node ? m_node->GetPrevious() : m_init; \
836 bool operator!=(const itor& it) const \
837 { return it.m_node != m_node; } \
838 bool operator==(const itor& it) const \
839 { return it.m_node == m_node; } \
841 classexp const_iterator \
845 typedef nodetype Node; \
846 typedef T* value_type; \
847 typedef const value_type& const_reference; \
848 typedef const_iterator itor; \
849 typedef value_type* ptr_type; \
854 typedef const_reference reference_type; \
855 typedef const ptr_type pointer_type; \
857 const_iterator(Node* node, Node* init) \
858 : m_node(node), m_init(init) { } \
859 const_iterator() : m_node(NULL), m_init(NULL) { } \
860 const_iterator(const iterator& it) \
861 : m_node(it.m_node), m_init(it.m_init) { } \
862 reference_type operator*() const \
863 { return *(pointer_type)m_node->GetDataPtr(); } \
865 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
866 const itor operator++(int) \
867 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
870 m_node = m_node ? m_node->GetPrevious() : m_init; \
873 const itor operator--(int) \
876 m_node = m_node ? m_node->GetPrevious() : m_init; \
879 bool operator!=(const itor& it) const \
880 { return it.m_node != m_node; } \
881 bool operator==(const itor& it) const \
882 { return it.m_node == m_node; } \
884 classexp reverse_iterator \
888 typedef nodetype Node; \
889 typedef T* value_type; \
890 typedef reverse_iterator itor; \
891 typedef value_type* ptr_type; \
892 typedef value_type& reference; \
897 typedef reference reference_type; \
898 typedef ptr_type pointer_type; \
900 reverse_iterator(Node* node, Node* init) \
901 : m_node(node), m_init(init) { } \
902 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
903 reference_type operator*() const \
904 { return *(pointer_type)m_node->GetDataPtr(); } \
907 { m_node = m_node->GetPrevious(); return *this; } \
908 const itor operator++(int) \
909 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
911 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
912 const itor operator--(int) \
915 m_node = m_node ? m_node->GetNext() : m_init; \
918 bool operator!=(const itor& it) const \
919 { return it.m_node != m_node; } \
920 bool operator==(const itor& it) const \
921 { return it.m_node == m_node; } \
923 classexp const_reverse_iterator \
927 typedef nodetype Node; \
928 typedef T* value_type; \
929 typedef const_reverse_iterator itor; \
930 typedef value_type* ptr_type; \
931 typedef const value_type& const_reference; \
936 typedef const_reference reference_type; \
937 typedef const ptr_type pointer_type; \
939 const_reverse_iterator(Node* node, Node* init) \
940 : m_node(node), m_init(init) { } \
941 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
942 const_reverse_iterator(const reverse_iterator& it) \
943 : m_node(it.m_node), m_init(it.m_init) { } \
944 reference_type operator*() const \
945 { return *(pointer_type)m_node->GetDataPtr(); } \
948 { m_node = m_node->GetPrevious(); return *this; } \
949 const itor operator++(int) \
950 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
952 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
953 const itor operator--(int) \
956 m_node = m_node ? m_node->GetNext() : m_init; \
959 bool operator!=(const itor& it) const \
960 { return it.m_node != m_node; } \
961 bool operator==(const itor& it) const \
962 { return it.m_node == m_node; } \
965 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
967 name(const const_iterator& first, const const_iterator& last) \
968 { assign(first, last); } \
969 iterator begin() { return iterator(GetFirst(), GetLast()); } \
970 const_iterator begin() const \
971 { return const_iterator(GetFirst(), GetLast()); } \
972 iterator end() { return iterator(NULL, GetLast()); } \
973 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
974 reverse_iterator rbegin() \
975 { return reverse_iterator(GetLast(), GetFirst()); } \
976 const_reverse_iterator rbegin() const \
977 { return const_reverse_iterator(GetLast(), GetFirst()); } \
978 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
979 const_reverse_iterator rend() const \
980 { return const_reverse_iterator(NULL, GetFirst()); } \
981 void resize(size_type n, value_type v = value_type()) \
988 size_type size() const { return GetCount(); } \
989 size_type max_size() const { return INT_MAX; } \
990 bool empty() const { return IsEmpty(); } \
991 reference front() { return *begin(); } \
992 const_reference front() const { return *begin(); } \
993 reference back() { iterator tmp = end(); return *--tmp; } \
994 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
995 void push_front(const_reference v = value_type()) \
996 { Insert(GetFirst(), (const_base_reference)v); } \
997 void pop_front() { DeleteNode(GetFirst()); } \
998 void push_back(const_reference v = value_type()) \
999 { Append((const_base_reference)v); } \
1000 void pop_back() { DeleteNode(GetLast()); } \
1001 void assign(const_iterator first, const const_iterator& last) \
1004 for(; first != last; ++first) \
1005 Append((const_base_reference)*first); \
1007 void assign(size_type n, const_reference v = value_type()) \
1010 for(size_type i = 0; i < n; ++i) \
1011 Append((const_base_reference)v); \
1013 iterator insert(const iterator& it, const_reference v) \
1015 if ( it == end() ) \
1017 Append((const_base_reference)v); \
1019 note that this is the new end(), the old one was \
1020 invalidated by the Append() call, and this is why we \
1021 can't use the same code as in the normal case below \
1023 iterator itins(end()); \
1028 Insert(it.m_node, (const_base_reference)v); \
1029 iterator itins(it); \
1033 void insert(const iterator& it, size_type n, const_reference v) \
1035 for(size_type i = 0; i < n; ++i) \
1038 void insert(const iterator& it, \
1039 const_iterator first, const const_iterator& last) \
1041 for(; first != last; ++first) \
1042 insert(it, *first); \
1044 iterator erase(const iterator& it) \
1046 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1047 DeleteNode(it.m_node); return next; \
1049 iterator erase(const iterator& first, const iterator& last) \
1051 iterator next = last; \
1052 if ( next != end() ) \
1054 DeleteNodes(first.m_node, last.m_node); \
1057 void clear() { Clear(); } \
1058 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1059 { insert(it, first, last); l.erase(first, last); } \
1060 void splice(const iterator& it, name& l) \
1061 { splice(it, l, l.begin(), l.end() ); } \
1062 void splice(const iterator& it, name& l, const iterator& first) \
1064 if ( it != first ) \
1066 insert(it, *first); \
1070 void remove(const_reference v) \
1071 { DeleteObject((const_base_reference)v); } \
1074 /* void swap(name& l) \
1076 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1077 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1078 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1079 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1080 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1084 #define WX_LIST_PTROP \
1085 pointer_type operator->() const \
1086 { return (pointer_type)m_node->GetDataPtr(); }
1087 #define WX_LIST_PTROP_NONE
1089 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1090 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1091 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1092 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1094 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1095 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1096 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1097 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1099 #define WX_DECLARE_LIST(elementtype, listname) \
1100 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1101 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1102 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1103 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1104 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1106 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1107 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1108 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1110 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1111 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLIMPEXP_CORE)
1113 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1114 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1115 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLIMPEXP_CORE)
1117 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1118 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1119 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1120 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1121 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1122 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1124 // this macro must be inserted in your program after
1125 // #include "wx/listimpl.cpp"
1126 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1128 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1129 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1131 #endif // !wxUSE_STL
1133 // ============================================================================
1134 // now we can define classes 100% compatible with the old ones
1135 // ============================================================================
1137 // ----------------------------------------------------------------------------
1138 // commonly used list classes
1139 // ----------------------------------------------------------------------------
1141 #if defined(wxLIST_COMPATIBILITY)
1143 // inline compatibility functions
1147 // ----------------------------------------------------------------------------
1148 // wxNodeBase deprecated methods
1149 // ----------------------------------------------------------------------------
1151 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1152 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1153 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1155 // ----------------------------------------------------------------------------
1156 // wxListBase deprecated methods
1157 // ----------------------------------------------------------------------------
1159 inline int wxListBase::Number() const { return (int)GetCount(); }
1160 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1161 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1162 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1163 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1167 // define this to make a lot of noise about use of the old wxList classes.
1168 //#define wxWARN_COMPAT_LIST_USE
1170 // ----------------------------------------------------------------------------
1171 // wxList compatibility class: in fact, it's a list of wxObjects
1172 // ----------------------------------------------------------------------------
1174 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1175 class WXDLLIMPEXP_BASE
);
1177 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1180 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1182 wxDEPRECATED( wxList(int key_type
) );
1184 wxList(int key_type
= wxKEY_NONE
);
1187 // this destructor is required for Darwin
1191 wxList
& operator=(const wxList
& list
)
1192 { if (&list
!= this) Assign(list
); return *this; }
1194 // compatibility methods
1195 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1196 #endif // !wxUSE_STL
1201 // -----------------------------------------------------------------------------
1202 // wxStringList class for compatibility with the old code
1203 // -----------------------------------------------------------------------------
1204 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1206 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1211 #ifdef wxWARN_COMPAT_LIST_USE
1213 wxDEPRECATED( wxStringList(const wxChar
*first
...) ); // FIXME-UTF8
1216 wxStringList(const wxChar
*first
...); // FIXME-UTF8
1219 // copying the string list: the strings are copied, too (extremely
1221 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1222 wxStringList
& operator=(const wxStringList
& other
)
1233 // makes a copy of the string
1234 wxNode
*Add(const wxChar
*s
);
1236 // Append to beginning of list
1237 wxNode
*Prepend(const wxChar
*s
);
1239 bool Delete(const wxChar
*s
);
1241 wxChar
**ListToArray(bool new_copies
= false) const;
1242 bool Member(const wxChar
*s
) const;
1248 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1251 #else // if wxUSE_STL
1253 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1255 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1258 compatibility_iterator
Append(wxChar
* s
)
1259 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1260 compatibility_iterator
Insert(wxChar
* s
)
1261 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1262 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1266 return wxStringListBase::Insert(pos
, tmp
);
1268 compatibility_iterator
Add(const wxChar
* s
)
1269 { push_back(s
); return GetLast(); }
1270 compatibility_iterator
Prepend(const wxChar
* s
)
1271 { push_front(s
); return GetFirst(); }
1276 #endif // wxLIST_COMPATIBILITY
1278 // delete all list elements
1280 // NB: the class declaration of the list elements must be visible from the
1281 // place where you use this macro, otherwise the proper destructor may not
1282 // be called (a decent compiler should give a warning about it, but don't
1284 #define WX_CLEAR_LIST(type, list) \
1286 type::iterator it, en; \
1287 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1292 // append all element of one list to another one
1293 #define WX_APPEND_LIST(list, other) \
1295 wxList::compatibility_iterator node = other->GetFirst(); \
1298 (list)->push_back(node->GetData()); \
1299 node = node->GetNext(); \
1303 #endif // _WX_LISTH__