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 // type of compare function for list sort operation (as in 'qsort'): it should
49 // return a negative value, 0 or positive value if the first element is less
50 // than, equal or greater than the second
54 typedef int (* LINKAGEMODE wxSortCompareFunction
)(const void *elem1
, const void *elem2
);
57 class WXDLLIMPEXP_BASE wxObjectListNode
;
58 typedef wxObjectListNode wxNode
;
61 typedef int (* LINKAGEMODE wxListIterateFunction
)(void *current
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #if !defined(wxENUM_KEY_TYPE_DEFINED)
68 #define wxENUM_KEY_TYPE_DEFINED
81 #define wxLIST_COMPATIBILITY
83 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
84 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
85 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
86 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
88 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
89 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
90 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
91 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
93 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
94 WX_DECLARE_LIST_XO(elT*, liT, decl)
96 #if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
99 class WXDLLIMPEXP_BASE wxList_SortFunction
102 wxList_SortFunction(wxSortCompareFunction f
) : m_f(f
) { }
103 bool operator()(const T
& i1
, const T
& i2
)
104 { return m_f((T
*)&i1
, (T
*)&i2
) < 0; }
106 wxSortCompareFunction m_f
;
109 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
110 #define VC6_WORKAROUND(elT, liT, decl)
112 #else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
114 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
115 #define VC6_WORKAROUND(elT, liT, decl) \
118 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
119 /* to be passed into std::list::sort() */ \
121 struct std::greater<elT> \
124 wxSortCompareFunction m_CompFunc; \
126 greater( wxSortCompareFunction compfunc = NULL ) \
127 : m_CompFunc( compfunc ) {} \
128 bool operator()(const elT X, const elT Y) const \
130 return m_CompFunc ? \
131 ( m_CompFunc( X, Y ) < 0 ) : \
139 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
140 for mingw 3.2.3 compiler bug that prevents a static function of liT class
141 from being exported into dll. A minimal code snippet reproducing the bug:
143 struct WXDLLEXPORT Foo
146 struct SomeInnerClass
148 friend class Foo; // comment this out to make it link
156 The program does not link under mingw_gcc 3.2.3 producing undefined
157 reference to Foo::Bar() function
160 Note 2: the EmptyList is needed to allow having a NULL pointer-like
161 invalid iterator. We used to use just an uninitialized iterator object
162 instead but this fails with some debug/checked versions of STL, notably the
163 glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate
167 // the real wxList-class declaration
168 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
169 decl _WX_LIST_HELPER_##liT \
171 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
173 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
176 VC6_WORKAROUND(elT, liT, decl) \
177 decl liT : public std::list<elT> \
180 typedef std::list<elT> BaseListType; \
181 static BaseListType EmptyList; \
186 decl compatibility_iterator \
189 /* Workaround for broken VC6 nested class name resolution */ \
190 typedef std::list<elT>::iterator iterator; \
197 compatibility_iterator() \
198 : m_iter(EmptyList.end()), m_list( NULL ) {} \
199 compatibility_iterator( liT* li, iterator i ) \
200 : m_iter( i ), m_list( li ) {} \
201 compatibility_iterator( const liT* li, iterator i ) \
202 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
204 compatibility_iterator* operator->() { return this; } \
205 const compatibility_iterator* operator->() const { return this; } \
207 bool operator==(const compatibility_iterator& i) const \
209 wxASSERT_MSG( m_list && i.m_list, \
210 _T("comparing invalid iterators is illegal") ); \
211 return (m_list == i.m_list) && (m_iter == i.m_iter); \
213 bool operator!=(const compatibility_iterator& i) const \
214 { return !( operator==( i ) ); } \
215 operator bool() const \
216 { return m_list ? m_iter != m_list->end() : false; } \
217 bool operator !() const \
218 { return !( operator bool() ); } \
220 elT GetData() const \
221 { return *m_iter; } \
222 void SetData( elT e ) \
225 compatibility_iterator GetNext() const \
227 iterator i = m_iter; \
228 return compatibility_iterator( m_list, ++i ); \
230 compatibility_iterator GetPrevious() const \
232 if ( m_iter == m_list->begin() ) \
233 return compatibility_iterator(); \
235 iterator i = m_iter; \
236 return compatibility_iterator( m_list, --i ); \
238 int IndexOf() const \
240 return *this ? std::distance( m_list->begin(), m_iter ) \
245 liT() : m_destroy( false ) {} \
247 compatibility_iterator Find( const elT e ) const \
249 liT* _this = const_cast< liT* >( this ); \
250 return compatibility_iterator( _this, \
251 std::find( _this->begin(), _this->end(), e ) ); \
254 bool IsEmpty() const \
255 { return empty(); } \
256 size_t GetCount() const \
259 { return static_cast< int >( GetCount() ); } \
261 compatibility_iterator Item( size_t idx ) const \
263 iterator i = const_cast< liT* >(this)->begin(); \
264 std::advance( i, idx ); \
265 return compatibility_iterator( this, i ); \
267 elT operator[](size_t idx) const \
269 return Item(idx).GetData(); \
272 compatibility_iterator GetFirst() const \
274 return compatibility_iterator( this, \
275 const_cast< liT* >(this)->begin() ); \
277 compatibility_iterator GetLast() const \
279 iterator i = const_cast< liT* >(this)->end(); \
280 return compatibility_iterator( this, !empty() ? --i : i ); \
282 compatibility_iterator Member( elT e ) const \
283 { return Find( e ); } \
284 compatibility_iterator Nth( int n ) const \
285 { return Item( n ); } \
286 int IndexOf( elT e ) const \
287 { return Find( e ).IndexOf(); } \
289 compatibility_iterator Append( elT e ) \
294 compatibility_iterator Insert( elT e ) \
297 return compatibility_iterator( this, begin() ); \
299 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
301 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
303 compatibility_iterator Insert( size_t idx, elT e ) \
305 return compatibility_iterator( this, \
306 insert( Item( idx ).m_iter, e ) ); \
309 void DeleteContents( bool destroy ) \
310 { m_destroy = destroy; } \
311 bool GetDeleteContents() const \
312 { return m_destroy; } \
313 void Erase( const compatibility_iterator& i ) \
316 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
319 bool DeleteNode( const compatibility_iterator& i ) \
328 bool DeleteObject( elT e ) \
330 return DeleteNode( Find( e ) ); \
335 std::for_each( begin(), end(), \
336 _WX_LIST_HELPER_##liT::DeleteFunction ); \
339 /* Workaround for broken VC6 std::list::sort() see above */ \
340 void Sort( wxSortCompareFunction compfunc ) \
341 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
342 ~liT() { Clear(); } \
344 /* It needs access to our EmptyList */ \
345 friend decl compatibility_iterator; \
348 #define WX_DECLARE_LIST(elementtype, listname) \
349 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
350 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
351 WX_DECLARE_LIST(elementtype, listname)
353 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
354 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
355 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
356 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
358 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
359 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
360 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
361 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
363 // this macro must be inserted in your program after
364 // #include "wx/listimpl.cpp"
365 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
367 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
368 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
370 #else // if !wxUSE_STL
373 // undef it to get rid of old, deprecated functions
374 #define wxLIST_COMPATIBILITY
376 // -----------------------------------------------------------------------------
377 // key stuff: a list may be optionally keyed on integer or string key
378 // -----------------------------------------------------------------------------
386 // a struct which may contain both types of keys
388 // implementation note: on one hand, this class allows to have only one function
389 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
390 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
391 // wxList::Find(const char *).
392 class WXDLLIMPEXP_BASE wxListKey
396 wxListKey() : m_keyType(wxKEY_NONE
)
398 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
399 { m_key
.integer
= i
; }
400 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
401 { m_key
.string
= new wxString(s
); }
404 wxKeyType
GetKeyType() const { return m_keyType
; }
405 const wxString
GetString() const
406 { wxASSERT( m_keyType
== wxKEY_STRING
); return *m_key
.string
; }
407 long GetNumber() const
408 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
411 // Note: implementation moved to list.cpp to prevent BC++ inline
412 // expansion warning.
413 bool operator==(wxListKeyValue value
) const ;
418 if ( m_keyType
== wxKEY_STRING
)
424 wxListKeyValue m_key
;
427 // -----------------------------------------------------------------------------
428 // wxNodeBase class is a (base for) node in a double linked list
429 // -----------------------------------------------------------------------------
431 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
433 class WXDLLIMPEXP_BASE wxListBase
;
435 class WXDLLIMPEXP_BASE wxNodeBase
437 friend class wxListBase
;
440 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
441 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
442 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
444 const wxListKey
& key
= wxDefaultListKey
);
446 virtual ~wxNodeBase();
448 // FIXME no check is done that the list is really keyed on strings
449 wxString
GetKeyString() const { return *m_key
.string
; }
450 long GetKeyInteger() const { return m_key
.integer
; }
452 // Necessary for some existing code
453 void SetKeyString(const wxString
& s
) { m_key
.string
= new wxString(s
); }
454 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
456 #ifdef wxLIST_COMPATIBILITY
457 // compatibility methods, use Get* instead.
458 wxDEPRECATED( wxNode
*Next() const );
459 wxDEPRECATED( wxNode
*Previous() const );
460 wxDEPRECATED( wxObject
*Data() const );
461 #endif // wxLIST_COMPATIBILITY
464 // all these are going to be "overloaded" in the derived classes
465 wxNodeBase
*GetNext() const { return m_next
; }
466 wxNodeBase
*GetPrevious() const { return m_previous
; }
468 void *GetData() const { return m_data
; }
469 void SetData(void *data
) { m_data
= data
; }
471 // get 0-based index of this node within the list or wxNOT_FOUND
474 virtual void DeleteData() { }
476 // for wxList::iterator
477 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
479 // optional key stuff
480 wxListKeyValue m_key
;
482 void *m_data
; // user data
483 wxNodeBase
*m_next
, // next and previous nodes in the list
486 wxListBase
*m_list
; // list we belong to
488 DECLARE_NO_COPY_CLASS(wxNodeBase
)
491 // -----------------------------------------------------------------------------
492 // a double-linked list class
493 // -----------------------------------------------------------------------------
495 class WXDLLIMPEXP_BASE wxList
;
497 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
499 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
500 friend class wxHashTableBase
; // should be able to call untyped Find()
503 // default ctor & dtor
504 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
506 virtual ~wxListBase();
509 // count of items in the list
510 size_t GetCount() const { return m_count
; }
512 // return true if this list is empty
513 bool IsEmpty() const { return m_count
== 0; }
520 // instruct it to destroy user data when deleting nodes
521 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
523 // query if to delete
524 bool GetDeleteContents() const
525 { return m_destroy
; }
528 wxKeyType
GetKeyType() const
529 { return m_keyType
; }
531 // set the keytype (required by the serial code)
532 void SetKeyType(wxKeyType keyType
)
533 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
535 #ifdef wxLIST_COMPATIBILITY
536 // compatibility methods from old wxList
537 wxDEPRECATED( int Number() const ); // use GetCount instead.
538 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
539 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
540 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
542 // kludge for typesafe list migration in core classes.
543 wxDEPRECATED( operator wxList
&() const );
544 #endif // wxLIST_COMPATIBILITY
548 // all methods here are "overloaded" in derived classes to provide compile
549 // time type checking
551 // create a node for the list of this type
552 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
554 const wxListKey
& key
= wxDefaultListKey
) = 0;
556 // Can't access these from derived classes otherwise (bug in Salford C++?)
563 wxListBase(size_t count
, void *elements
[]);
564 // from a sequence of objects
565 wxListBase(void *object
, ... /* terminate with NULL */);
568 void Assign(const wxListBase
& list
)
569 { Clear(); DoCopy(list
); }
571 // get list head/tail
572 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
573 wxNodeBase
*GetLast() const { return m_nodeLast
; }
575 // by (0-based) index
576 wxNodeBase
*Item(size_t index
) const;
578 // get the list item's data
579 void *operator[](size_t n
) const
581 wxNodeBase
*node
= Item(n
);
583 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
587 // append to end of list
588 wxNodeBase
*Prepend(void *object
)
589 { return (wxNodeBase
*)wxListBase::Insert(object
); }
590 // append to beginning of list
591 wxNodeBase
*Append(void *object
);
592 // insert a new item at the beginning of the list
593 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
594 // insert a new item at the given position
595 wxNodeBase
*Insert(size_t pos
, void *object
)
596 { return pos
== GetCount() ? Append(object
)
597 : Insert(Item(pos
), object
); }
598 // insert before given node or at front of list if prev == NULL
599 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
602 wxNodeBase
*Append(long key
, void *object
);
603 wxNodeBase
*Append(const wxString
& key
, void *object
);
605 // removes node from the list but doesn't delete it (returns pointer
606 // to the node or NULL if it wasn't found in the list)
607 wxNodeBase
*DetachNode(wxNodeBase
*node
);
608 // delete element from list, returns false if node not found
609 bool DeleteNode(wxNodeBase
*node
);
610 // finds object pointer and deletes node (and object if DeleteContents
611 // is on), returns false if object not found
612 bool DeleteObject(void *object
);
614 // search (all return NULL if item not found)
616 wxNodeBase
*Find(const void *object
) const;
619 wxNodeBase
*Find(const wxListKey
& key
) const;
621 // get 0-based index of object or wxNOT_FOUND
622 int IndexOf( void *object
) const;
624 // this function allows the sorting of arbitrary lists by giving
625 // a function to compare two list elements. The list is sorted in place.
626 void Sort(const wxSortCompareFunction compfunc
);
628 // functions for iterating over the list
629 void *FirstThat(wxListIterateFunction func
);
630 void ForEach(wxListIterateFunction func
);
631 void *LastThat(wxListIterateFunction func
);
633 // for STL interface, "last" points to one after the last node
634 // of the controlled sequence (NULL for the end of the list)
636 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
639 // common part of all ctors
640 void Init(wxKeyType keyType
= wxKEY_NONE
);
643 // common part of copy ctor and assignment operator
644 void DoCopy(const wxListBase
& list
);
645 // common part of all Append()s
646 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
647 // free node's data and node itself
648 void DoDeleteNode(wxNodeBase
*node
);
650 size_t m_count
; // number of elements in the list
651 bool m_destroy
; // destroy user data when deleting list items?
652 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
655 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
658 // -----------------------------------------------------------------------------
659 // macros for definition of "template" list type
660 // -----------------------------------------------------------------------------
662 // and now some heavy magic...
664 // declare a list type named 'name' and containing elements of type 'T *'
665 // (as a by product of macro expansion you also get wx##name##Node
666 // wxNode-derived type)
668 // implementation details:
669 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
670 // for the list of given type - this allows us to pass only the list name
671 // to WX_DEFINE_LIST() even if it needs both the name and the type
673 // 2. We redefine all non-type-safe wxList functions with type-safe versions
674 // which don't take any space (everything is inline), but bring compile
675 // time error checking.
677 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
678 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
679 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
680 // interesting capability to store polymorphic objects in the list and is
681 // particularly useful with, for example, "wxWindow *" list where the
682 // wxWindowBase pointers are put into the list, but wxWindow pointers are
683 // retrieved from it.
685 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
686 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
687 // it results in compiler warnings when this operator doesn't make sense
688 // (i.e. stored elements are not pointers)
690 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
691 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
692 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
694 classexp nodetype : public wxNodeBase \
697 nodetype(wxListBase *list = (wxListBase *)NULL, \
698 nodetype *previous = (nodetype *)NULL, \
699 nodetype *next = (nodetype *)NULL, \
700 T *data = (T *)NULL, \
701 const wxListKey& key = wxDefaultListKey) \
702 : wxNodeBase(list, previous, next, data, key) { } \
704 nodetype *GetNext() const \
705 { return (nodetype *)wxNodeBase::GetNext(); } \
706 nodetype *GetPrevious() const \
707 { return (nodetype *)wxNodeBase::GetPrevious(); } \
710 { return (T *)wxNodeBase::GetData(); } \
711 void SetData(T *data) \
712 { wxNodeBase::SetData(data); } \
715 virtual void DeleteData(); \
717 DECLARE_NO_COPY_CLASS(nodetype) \
720 classexp name : public wxListBase \
723 typedef nodetype Node; \
724 classexp compatibility_iterator \
727 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
729 Node *operator->() const { return m_ptr; } \
730 operator Node *() const { return m_ptr; } \
736 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
738 name(const name& list) : wxListBase(list.GetKeyType()) \
740 name(size_t count, T *elements[]) \
741 : wxListBase(count, (void **)elements) { } \
743 name& operator=(const name& list) \
744 { Assign(list); return *this; } \
746 nodetype *GetFirst() const \
747 { return (nodetype *)wxListBase::GetFirst(); } \
748 nodetype *GetLast() const \
749 { return (nodetype *)wxListBase::GetLast(); } \
751 nodetype *Item(size_t index) const \
752 { return (nodetype *)wxListBase::Item(index); } \
754 T *operator[](size_t index) const \
756 nodetype *node = Item(index); \
757 return node ? (T*)(node->GetData()) : (T*)NULL; \
760 nodetype *Append(Tbase *object) \
761 { return (nodetype *)wxListBase::Append(object); } \
762 nodetype *Insert(Tbase *object) \
763 { return (nodetype *)Insert((nodetype*)NULL, object); } \
764 nodetype *Insert(size_t pos, Tbase *object) \
765 { return (nodetype *)wxListBase::Insert(pos, object); } \
766 nodetype *Insert(nodetype *prev, Tbase *object) \
767 { return (nodetype *)wxListBase::Insert(prev, object); } \
769 nodetype *Append(long key, void *object) \
770 { return (nodetype *)wxListBase::Append(key, object); } \
771 nodetype *Append(const wxChar *key, void *object) \
772 { return (nodetype *)wxListBase::Append(key, object); } \
774 nodetype *DetachNode(nodetype *node) \
775 { return (nodetype *)wxListBase::DetachNode(node); } \
776 bool DeleteNode(nodetype *node) \
777 { return wxListBase::DeleteNode(node); } \
778 bool DeleteObject(Tbase *object) \
779 { return wxListBase::DeleteObject(object); } \
780 void Erase(nodetype *it) \
781 { DeleteNode(it); } \
783 nodetype *Find(const Tbase *object) const \
784 { return (nodetype *)wxListBase::Find(object); } \
786 virtual nodetype *Find(const wxListKey& key) const \
787 { return (nodetype *)wxListBase::Find(key); } \
789 int IndexOf(Tbase *object) const \
790 { return wxListBase::IndexOf(object); } \
792 void Sort(wxSortCompareFunction func) \
793 { wxListBase::Sort(func); } \
794 void Sort(wxSortFuncFor_##name func) \
795 { Sort((wxSortCompareFunction)func); } \
798 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
800 const wxListKey& key = wxDefaultListKey) \
802 return new nodetype(this, \
803 (nodetype *)prev, (nodetype *)next, \
806 /* STL interface */ \
808 typedef size_t size_type; \
809 typedef int difference_type; \
810 typedef T* value_type; \
811 typedef Tbase* base_value_type; \
812 typedef value_type& reference; \
813 typedef const value_type& const_reference; \
814 typedef base_value_type& base_reference; \
815 typedef const base_value_type& const_base_reference; \
821 typedef nodetype Node; \
822 typedef iterator itor; \
823 typedef T* value_type; \
824 typedef value_type* ptr_type; \
825 typedef value_type& reference; \
830 typedef reference reference_type; \
831 typedef ptr_type pointer_type; \
833 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
834 iterator() : m_node(NULL), m_init(NULL) { } \
835 reference_type operator*() const \
836 { return *(pointer_type)m_node->GetDataPtr(); } \
838 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
839 const itor operator++(int) \
840 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
843 m_node = m_node ? m_node->GetPrevious() : m_init; \
846 const itor operator--(int) \
849 m_node = m_node ? m_node->GetPrevious() : m_init; \
852 bool operator!=(const itor& it) const \
853 { return it.m_node != m_node; } \
854 bool operator==(const itor& it) const \
855 { return it.m_node == m_node; } \
857 classexp const_iterator \
861 typedef nodetype Node; \
862 typedef T* value_type; \
863 typedef const value_type& const_reference; \
864 typedef const_iterator itor; \
865 typedef value_type* ptr_type; \
870 typedef const_reference reference_type; \
871 typedef const ptr_type pointer_type; \
873 const_iterator(Node* node, Node* init) \
874 : m_node(node), m_init(init) { } \
875 const_iterator() : m_node(NULL), m_init(NULL) { } \
876 const_iterator(const iterator& it) \
877 : m_node(it.m_node), m_init(it.m_init) { } \
878 reference_type operator*() const \
879 { return *(pointer_type)m_node->GetDataPtr(); } \
881 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
882 const itor operator++(int) \
883 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
886 m_node = m_node ? m_node->GetPrevious() : m_init; \
889 const itor operator--(int) \
892 m_node = m_node ? m_node->GetPrevious() : m_init; \
895 bool operator!=(const itor& it) const \
896 { return it.m_node != m_node; } \
897 bool operator==(const itor& it) const \
898 { return it.m_node == m_node; } \
900 classexp reverse_iterator \
904 typedef nodetype Node; \
905 typedef T* value_type; \
906 typedef reverse_iterator itor; \
907 typedef value_type* ptr_type; \
908 typedef value_type& reference; \
913 typedef reference reference_type; \
914 typedef ptr_type pointer_type; \
916 reverse_iterator(Node* node, Node* init) \
917 : m_node(node), m_init(init) { } \
918 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
919 reference_type operator*() const \
920 { return *(pointer_type)m_node->GetDataPtr(); } \
923 { m_node = m_node->GetPrevious(); return *this; } \
924 const itor operator++(int) \
925 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
927 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
928 const itor operator--(int) \
931 m_node = m_node ? m_node->GetNext() : m_init; \
934 bool operator!=(const itor& it) const \
935 { return it.m_node != m_node; } \
936 bool operator==(const itor& it) const \
937 { return it.m_node == m_node; } \
939 classexp const_reverse_iterator \
943 typedef nodetype Node; \
944 typedef T* value_type; \
945 typedef const_reverse_iterator itor; \
946 typedef value_type* ptr_type; \
947 typedef const value_type& const_reference; \
952 typedef const_reference reference_type; \
953 typedef const ptr_type pointer_type; \
955 const_reverse_iterator(Node* node, Node* init) \
956 : m_node(node), m_init(init) { } \
957 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
958 const_reverse_iterator(const reverse_iterator& it) \
959 : m_node(it.m_node), m_init(it.m_init) { } \
960 reference_type operator*() const \
961 { return *(pointer_type)m_node->GetDataPtr(); } \
964 { m_node = m_node->GetPrevious(); return *this; } \
965 const itor operator++(int) \
966 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
968 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
969 const itor operator--(int) \
972 m_node = m_node ? m_node->GetNext() : m_init; \
975 bool operator!=(const itor& it) const \
976 { return it.m_node != m_node; } \
977 bool operator==(const itor& it) const \
978 { return it.m_node == m_node; } \
981 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
983 name(const const_iterator& first, const const_iterator& last) \
984 { assign(first, last); } \
985 iterator begin() { return iterator(GetFirst(), GetLast()); } \
986 const_iterator begin() const \
987 { return const_iterator(GetFirst(), GetLast()); } \
988 iterator end() { return iterator(NULL, GetLast()); } \
989 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
990 reverse_iterator rbegin() \
991 { return reverse_iterator(GetLast(), GetFirst()); } \
992 const_reverse_iterator rbegin() const \
993 { return const_reverse_iterator(GetLast(), GetFirst()); } \
994 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
995 const_reverse_iterator rend() const \
996 { return const_reverse_iterator(NULL, GetFirst()); } \
997 void resize(size_type n, value_type v = value_type()) \
1001 while (n > size()) \
1004 size_type size() const { return GetCount(); } \
1005 size_type max_size() const { return INT_MAX; } \
1006 bool empty() const { return IsEmpty(); } \
1007 reference front() { return *begin(); } \
1008 const_reference front() const { return *begin(); } \
1009 reference back() { iterator tmp = end(); return *--tmp; } \
1010 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1011 void push_front(const_reference v = value_type()) \
1012 { Insert(GetFirst(), (const_base_reference)v); } \
1013 void pop_front() { DeleteNode(GetFirst()); } \
1014 void push_back(const_reference v = value_type()) \
1015 { Append((const_base_reference)v); } \
1016 void pop_back() { DeleteNode(GetLast()); } \
1017 void assign(const_iterator first, const const_iterator& last) \
1020 for(; first != last; ++first) \
1021 Append((const_base_reference)*first); \
1023 void assign(size_type n, const_reference v = value_type()) \
1026 for(size_type i = 0; i < n; ++i) \
1027 Append((const_base_reference)v); \
1029 iterator insert(const iterator& it, const_reference v = value_type())\
1031 Insert(it.m_node, (const_base_reference)v); \
1032 return iterator(it.m_node->GetPrevious(), GetLast()); \
1034 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1036 for(size_type i = 0; i < n; ++i) \
1037 Insert(it.m_node, (const_base_reference)v); \
1039 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1041 for(; first != last; ++first) \
1042 Insert(it.m_node, (const_base_reference)*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; ++next; \
1052 DeleteNodes(first.m_node, last.m_node); \
1055 void clear() { Clear(); } \
1056 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1057 { insert(it, first, last); l.erase(first, last); } \
1058 void splice(const iterator& it, name& l) \
1059 { splice(it, l, l.begin(), l.end() ); } \
1060 void splice(const iterator& it, name& l, const iterator& first) \
1062 iterator tmp = first; ++tmp; \
1063 if(it == first || it == tmp) return; \
1064 insert(it, *first); \
1067 void remove(const_reference v) \
1068 { DeleteObject((const_base_reference)v); } \
1071 /* void swap(name& l) \
1073 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1074 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1075 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1076 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1077 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1081 #define WX_LIST_PTROP \
1082 pointer_type operator->() const \
1083 { return (pointer_type)m_node->GetDataPtr(); }
1084 #define WX_LIST_PTROP_NONE
1086 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1087 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1088 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1089 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1091 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1092 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1093 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1094 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1096 #define WX_DECLARE_LIST(elementtype, listname) \
1097 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1098 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1099 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1100 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1101 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1103 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1104 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1105 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1107 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1108 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1110 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1111 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1112 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1114 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1115 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1116 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1117 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1118 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1119 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1121 // this macro must be inserted in your program after
1122 // #include "wx/listimpl.cpp"
1123 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1125 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1126 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1128 #endif // !wxUSE_STL
1130 // ============================================================================
1131 // now we can define classes 100% compatible with the old ones
1132 // ============================================================================
1134 // ----------------------------------------------------------------------------
1135 // commonly used list classes
1136 // ----------------------------------------------------------------------------
1138 #if defined(wxLIST_COMPATIBILITY)
1140 // inline compatibility functions
1144 // ----------------------------------------------------------------------------
1145 // wxNodeBase deprecated methods
1146 // ----------------------------------------------------------------------------
1148 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1149 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1150 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1152 // ----------------------------------------------------------------------------
1153 // wxListBase deprecated methods
1154 // ----------------------------------------------------------------------------
1156 inline int wxListBase::Number() const { return (int)GetCount(); }
1157 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1158 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1159 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1160 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1164 // define this to make a lot of noise about use of the old wxList classes.
1165 //#define wxWARN_COMPAT_LIST_USE
1167 // ----------------------------------------------------------------------------
1168 // wxList compatibility class: in fact, it's a list of wxObjects
1169 // ----------------------------------------------------------------------------
1171 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1172 class WXDLLIMPEXP_BASE
);
1174 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1177 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1179 wxDEPRECATED( wxList(int key_type
) );
1181 wxList(int key_type
= wxKEY_NONE
);
1184 // this destructor is required for Darwin
1188 wxList
& operator=(const wxList
& list
)
1189 { (void) wxListBase::operator=(list
); return *this; }
1191 // compatibility methods
1192 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1197 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1202 DECLARE_DYNAMIC_CLASS(wxList
)
1208 // -----------------------------------------------------------------------------
1209 // wxStringList class for compatibility with the old code
1210 // -----------------------------------------------------------------------------
1211 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1213 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1218 #ifdef wxWARN_COMPAT_LIST_USE
1220 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1223 wxStringList(const wxChar
*first
...);
1226 // copying the string list: the strings are copied, too (extremely
1228 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1229 wxStringList
& operator=(const wxStringList
& other
)
1230 { Clear(); DoCopy(other
); return *this; }
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=
1250 DECLARE_DYNAMIC_CLASS(wxStringList
)
1253 #else // if wxUSE_STL
1255 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1257 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1260 compatibility_iterator
Append(wxChar
* s
)
1261 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1262 compatibility_iterator
Insert(wxChar
* s
)
1263 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1264 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1268 return wxStringListBase::Insert(pos
, tmp
);
1270 compatibility_iterator
Add(const wxChar
* s
)
1271 { push_back(s
); return GetLast(); }
1272 compatibility_iterator
Prepend(const wxChar
* s
)
1273 { push_front(s
); return GetFirst(); }
1278 #endif // wxLIST_COMPATIBILITY
1280 // delete all list elements
1282 // NB: the class declaration of the list elements must be visible from the
1283 // place where you use this macro, otherwise the proper destructor may not
1284 // be called (a decent compiler should give a warning about it, but don't
1286 #define WX_CLEAR_LIST(type, list) \
1288 type::iterator it, en; \
1289 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1294 #endif // _WX_LISTH__