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__ )
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__ )
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 ) : \
136 #endif // defined( __VISUALC__ )
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; \
185 decl compatibility_iterator \
188 /* Workaround for broken VC6 nested class name resolution */ \
189 typedef std::list<elT>::iterator iterator; \
195 compatibility_iterator() \
196 : m_iter(EmptyList.end()), m_list( NULL ) {} \
197 compatibility_iterator( liT* li, iterator i ) \
198 : m_iter( i ), m_list( li ) {} \
199 compatibility_iterator( const liT* li, iterator i ) \
200 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
202 compatibility_iterator* operator->() { return this; } \
203 const compatibility_iterator* operator->() const { return this; } \
205 bool operator==(const compatibility_iterator& i) const \
207 wxASSERT_MSG( m_list && i.m_list, \
208 _T("comparing invalid iterators is illegal") ); \
209 return (m_list == i.m_list) && (m_iter == i.m_iter); \
211 bool operator!=(const compatibility_iterator& i) const \
212 { return !( operator==( i ) ); } \
213 operator bool() const \
214 { return m_list ? m_iter != m_list->end() : false; } \
215 bool operator !() const \
216 { return !( operator bool() ); } \
218 elT GetData() const \
219 { return *m_iter; } \
220 void SetData( elT e ) \
223 compatibility_iterator GetNext() const \
225 iterator i = m_iter; \
226 return compatibility_iterator( m_list, ++i ); \
228 compatibility_iterator GetPrevious() const \
230 if ( m_iter == m_list->begin() ) \
231 return compatibility_iterator(); \
233 iterator i = m_iter; \
234 return compatibility_iterator( m_list, --i ); \
236 int IndexOf() const \
238 return *this ? std::distance( m_list->begin(), m_iter ) \
243 liT() : m_destroy( false ) {} \
245 compatibility_iterator Find( const elT e ) const \
247 liT* _this = const_cast< liT* >( this ); \
248 return compatibility_iterator( _this, \
249 std::find( _this->begin(), _this->end(), e ) ); \
252 bool IsEmpty() const \
253 { return empty(); } \
254 size_t GetCount() const \
257 { return static_cast< int >( GetCount() ); } \
259 compatibility_iterator Item( size_t idx ) const \
261 iterator i = const_cast< liT* >(this)->begin(); \
262 std::advance( i, idx ); \
263 return compatibility_iterator( this, i ); \
265 elT operator[](size_t idx) const \
267 return Item(idx).GetData(); \
270 compatibility_iterator GetFirst() const \
272 return compatibility_iterator( this, \
273 const_cast< liT* >(this)->begin() ); \
275 compatibility_iterator GetLast() const \
277 iterator i = const_cast< liT* >(this)->end(); \
278 return compatibility_iterator( this, !empty() ? --i : i ); \
280 compatibility_iterator Member( elT e ) const \
281 { return Find( e ); } \
282 compatibility_iterator Nth( int n ) const \
283 { return Item( n ); } \
284 int IndexOf( elT e ) const \
285 { return Find( e ).IndexOf(); } \
287 compatibility_iterator Append( elT e ) \
292 compatibility_iterator Insert( elT e ) \
295 return compatibility_iterator( this, begin() ); \
297 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
299 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
301 compatibility_iterator Insert( size_t idx, elT e ) \
303 return compatibility_iterator( this, \
304 insert( Item( idx ).m_iter, e ) ); \
307 void DeleteContents( bool destroy ) \
308 { m_destroy = destroy; } \
309 bool GetDeleteContents() const \
310 { return m_destroy; } \
311 void Erase( const compatibility_iterator& i ) \
314 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
317 bool DeleteNode( const compatibility_iterator& i ) \
326 bool DeleteObject( elT e ) \
328 return DeleteNode( Find( e ) ); \
333 std::for_each( begin(), end(), \
334 _WX_LIST_HELPER_##liT::DeleteFunction ); \
337 /* Workaround for broken VC6 std::list::sort() see above */ \
338 void Sort( wxSortCompareFunction compfunc ) \
339 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
340 ~liT() { Clear(); } \
343 #define WX_DECLARE_LIST(elementtype, listname) \
344 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
345 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
346 WX_DECLARE_LIST(elementtype, listname)
348 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
349 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
350 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
351 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
353 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
354 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
355 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
356 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
358 // this macro must be inserted in your program after
359 // #include "wx/listimpl.cpp"
360 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
362 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
363 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
365 #else // if !wxUSE_STL
367 // due to circular header dependencies this function has to be declared here
368 // (normally it's found in utils.h which includes itself list.h...)
369 #if WXWIN_COMPATIBILITY_2_4
370 extern WXDLLIMPEXP_BASE wxChar
* copystring(const wxChar
*s
);
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 wxChar
*s
) : m_keyType(wxKEY_STRING
)
401 { m_key
.string
= wxStrdup(s
); }
402 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
403 { m_key
.string
= wxStrdup(s
.c_str()); }
406 wxKeyType
GetKeyType() const { return m_keyType
; }
407 const wxChar
*GetString() const
408 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
409 long GetNumber() const
410 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
413 // Note: implementation moved to list.cpp to prevent BC++ inline
414 // expansion warning.
415 bool operator==(wxListKeyValue value
) const ;
420 if ( m_keyType
== wxKEY_STRING
)
426 wxListKeyValue m_key
;
429 // -----------------------------------------------------------------------------
430 // wxNodeBase class is a (base for) node in a double linked list
431 // -----------------------------------------------------------------------------
433 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
435 class WXDLLIMPEXP_BASE wxListBase
;
437 class WXDLLIMPEXP_BASE wxNodeBase
439 friend class wxListBase
;
442 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
443 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
444 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
446 const wxListKey
& key
= wxDefaultListKey
);
448 virtual ~wxNodeBase();
450 // FIXME no check is done that the list is really keyed on strings
451 const wxChar
*GetKeyString() const { return m_key
.string
; }
452 long GetKeyInteger() const { return m_key
.integer
; }
454 // Necessary for some existing code
455 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
456 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
458 #ifdef wxLIST_COMPATIBILITY
459 // compatibility methods, use Get* instead.
460 wxDEPRECATED( wxNode
*Next() const );
461 wxDEPRECATED( wxNode
*Previous() const );
462 wxDEPRECATED( wxObject
*Data() const );
463 #endif // wxLIST_COMPATIBILITY
466 // all these are going to be "overloaded" in the derived classes
467 wxNodeBase
*GetNext() const { return m_next
; }
468 wxNodeBase
*GetPrevious() const { return m_previous
; }
470 void *GetData() const { return m_data
; }
471 void SetData(void *data
) { m_data
= data
; }
473 // get 0-based index of this node within the list or wxNOT_FOUND
476 virtual void DeleteData() { }
478 // for wxList::iterator
479 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
481 // optional key stuff
482 wxListKeyValue m_key
;
484 void *m_data
; // user data
485 wxNodeBase
*m_next
, // next and previous nodes in the list
488 wxListBase
*m_list
; // list we belong to
490 DECLARE_NO_COPY_CLASS(wxNodeBase
)
493 // -----------------------------------------------------------------------------
494 // a double-linked list class
495 // -----------------------------------------------------------------------------
497 class WXDLLIMPEXP_BASE wxList
;
499 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
501 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
502 friend class wxHashTableBase
; // should be able to call untyped Find()
505 // default ctor & dtor
506 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
508 virtual ~wxListBase();
511 // count of items in the list
512 size_t GetCount() const { return m_count
; }
514 // return true if this list is empty
515 bool IsEmpty() const { return m_count
== 0; }
522 // instruct it to destroy user data when deleting nodes
523 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
525 // query if to delete
526 bool GetDeleteContents() const
527 { return m_destroy
; }
530 wxKeyType
GetKeyType() const
531 { return m_keyType
; }
533 // set the keytype (required by the serial code)
534 void SetKeyType(wxKeyType keyType
)
535 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
537 #ifdef wxLIST_COMPATIBILITY
538 // compatibility methods from old wxList
539 wxDEPRECATED( int Number() const ); // use GetCount instead.
540 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
541 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
542 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
544 // kludge for typesafe list migration in core classes.
545 wxDEPRECATED( operator wxList
&() const );
546 #endif // wxLIST_COMPATIBILITY
550 // all methods here are "overloaded" in derived classes to provide compile
551 // time type checking
553 // create a node for the list of this type
554 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
556 const wxListKey
& key
= wxDefaultListKey
) = 0;
558 // Can't access these from derived classes otherwise (bug in Salford C++?)
565 wxListBase(size_t count
, void *elements
[]);
566 // from a sequence of objects
567 wxListBase(void *object
, ... /* terminate with NULL */);
570 void Assign(const wxListBase
& list
)
571 { Clear(); DoCopy(list
); }
573 // get list head/tail
574 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
575 wxNodeBase
*GetLast() const { return m_nodeLast
; }
577 // by (0-based) index
578 wxNodeBase
*Item(size_t index
) const;
580 // get the list item's data
581 void *operator[](size_t n
) const
583 wxNodeBase
*node
= Item(n
);
585 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
589 // append to end of list
590 wxNodeBase
*Prepend(void *object
)
591 { return (wxNodeBase
*)wxListBase::Insert(object
); }
592 // append to beginning of list
593 wxNodeBase
*Append(void *object
);
594 // insert a new item at the beginning of the list
595 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
596 // insert a new item at the given position
597 wxNodeBase
*Insert(size_t pos
, void *object
)
598 { return pos
== GetCount() ? Append(object
)
599 : Insert(Item(pos
), object
); }
600 // insert before given node or at front of list if prev == NULL
601 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
604 wxNodeBase
*Append(long key
, void *object
);
605 wxNodeBase
*Append(const wxChar
*key
, void *object
);
607 // removes node from the list but doesn't delete it (returns pointer
608 // to the node or NULL if it wasn't found in the list)
609 wxNodeBase
*DetachNode(wxNodeBase
*node
);
610 // delete element from list, returns false if node not found
611 bool DeleteNode(wxNodeBase
*node
);
612 // finds object pointer and deletes node (and object if DeleteContents
613 // is on), returns false if object not found
614 bool DeleteObject(void *object
);
616 // search (all return NULL if item not found)
618 wxNodeBase
*Find(const void *object
) const;
621 wxNodeBase
*Find(const wxListKey
& key
) const;
623 // get 0-based index of object or wxNOT_FOUND
624 int IndexOf( void *object
) const;
626 // this function allows the sorting of arbitrary lists by giving
627 // a function to compare two list elements. The list is sorted in place.
628 void Sort(const wxSortCompareFunction compfunc
);
630 // functions for iterating over the list
631 void *FirstThat(wxListIterateFunction func
);
632 void ForEach(wxListIterateFunction func
);
633 void *LastThat(wxListIterateFunction func
);
635 // for STL interface, "last" points to one after the last node
636 // of the controlled sequence (NULL for the end of the list)
638 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
641 // common part of all ctors
642 void Init(wxKeyType keyType
= wxKEY_NONE
);
645 // common part of copy ctor and assignment operator
646 void DoCopy(const wxListBase
& list
);
647 // common part of all Append()s
648 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
649 // free node's data and node itself
650 void DoDeleteNode(wxNodeBase
*node
);
652 size_t m_count
; // number of elements in the list
653 bool m_destroy
; // destroy user data when deleting list items?
654 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
657 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
660 // -----------------------------------------------------------------------------
661 // macros for definition of "template" list type
662 // -----------------------------------------------------------------------------
664 // and now some heavy magic...
666 // declare a list type named 'name' and containing elements of type 'T *'
667 // (as a by product of macro expansion you also get wx##name##Node
668 // wxNode-derived type)
670 // implementation details:
671 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
672 // for the list of given type - this allows us to pass only the list name
673 // to WX_DEFINE_LIST() even if it needs both the name and the type
675 // 2. We redefine all non-type-safe wxList functions with type-safe versions
676 // which don't take any space (everything is inline), but bring compile
677 // time error checking.
679 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
680 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
681 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
682 // interesting capability to store polymorphic objects in the list and is
683 // particularly useful with, for example, "wxWindow *" list where the
684 // wxWindowBase pointers are put into the list, but wxWindow pointers are
685 // retrieved from it.
687 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
688 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
689 // it results in compiler warnings when this operator doesn't make sense
690 // (i.e. stored elements are not pointers)
692 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
693 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
694 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
696 classexp nodetype : public wxNodeBase \
699 nodetype(wxListBase *list = (wxListBase *)NULL, \
700 nodetype *previous = (nodetype *)NULL, \
701 nodetype *next = (nodetype *)NULL, \
702 T *data = (T *)NULL, \
703 const wxListKey& key = wxDefaultListKey) \
704 : wxNodeBase(list, previous, next, data, key) { } \
706 nodetype *GetNext() const \
707 { return (nodetype *)wxNodeBase::GetNext(); } \
708 nodetype *GetPrevious() const \
709 { return (nodetype *)wxNodeBase::GetPrevious(); } \
712 { return (T *)wxNodeBase::GetData(); } \
713 void SetData(T *data) \
714 { wxNodeBase::SetData(data); } \
717 virtual void DeleteData(); \
719 DECLARE_NO_COPY_CLASS(nodetype) \
722 classexp name : public wxListBase \
725 typedef nodetype Node; \
726 classexp compatibility_iterator \
729 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
731 Node *operator->() const { return m_ptr; } \
732 operator Node *() const { return m_ptr; } \
738 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
740 name(const name& list) : wxListBase(list.GetKeyType()) \
742 name(size_t count, T *elements[]) \
743 : wxListBase(count, (void **)elements) { } \
745 name& operator=(const name& list) \
746 { Assign(list); return *this; } \
748 nodetype *GetFirst() const \
749 { return (nodetype *)wxListBase::GetFirst(); } \
750 nodetype *GetLast() const \
751 { return (nodetype *)wxListBase::GetLast(); } \
753 nodetype *Item(size_t index) const \
754 { return (nodetype *)wxListBase::Item(index); } \
756 T *operator[](size_t index) const \
758 nodetype *node = Item(index); \
759 return node ? (T*)(node->GetData()) : (T*)NULL; \
762 nodetype *Append(Tbase *object) \
763 { return (nodetype *)wxListBase::Append(object); } \
764 nodetype *Insert(Tbase *object) \
765 { return (nodetype *)Insert((nodetype*)NULL, object); } \
766 nodetype *Insert(size_t pos, Tbase *object) \
767 { return (nodetype *)wxListBase::Insert(pos, object); } \
768 nodetype *Insert(nodetype *prev, Tbase *object) \
769 { return (nodetype *)wxListBase::Insert(prev, object); } \
771 nodetype *Append(long key, void *object) \
772 { return (nodetype *)wxListBase::Append(key, object); } \
773 nodetype *Append(const wxChar *key, void *object) \
774 { return (nodetype *)wxListBase::Append(key, object); } \
776 nodetype *DetachNode(nodetype *node) \
777 { return (nodetype *)wxListBase::DetachNode(node); } \
778 bool DeleteNode(nodetype *node) \
779 { return wxListBase::DeleteNode(node); } \
780 bool DeleteObject(Tbase *object) \
781 { return wxListBase::DeleteObject(object); } \
782 void Erase(nodetype *it) \
783 { DeleteNode(it); } \
785 nodetype *Find(const Tbase *object) const \
786 { return (nodetype *)wxListBase::Find(object); } \
788 virtual nodetype *Find(const wxListKey& key) const \
789 { return (nodetype *)wxListBase::Find(key); } \
791 int IndexOf(Tbase *object) const \
792 { return wxListBase::IndexOf(object); } \
794 void Sort(wxSortCompareFunction func) \
795 { wxListBase::Sort(func); } \
796 void Sort(wxSortFuncFor_##name func) \
797 { Sort((wxSortCompareFunction)func); } \
800 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
802 const wxListKey& key = wxDefaultListKey) \
804 return new nodetype(this, \
805 (nodetype *)prev, (nodetype *)next, \
808 /* STL interface */ \
810 typedef size_t size_type; \
811 typedef int difference_type; \
812 typedef T* value_type; \
813 typedef Tbase* base_value_type; \
814 typedef value_type& reference; \
815 typedef const value_type& const_reference; \
816 typedef base_value_type& base_reference; \
817 typedef const base_value_type& const_base_reference; \
823 typedef nodetype Node; \
824 typedef iterator itor; \
825 typedef T* value_type; \
826 typedef value_type* ptr_type; \
827 typedef value_type& reference; \
832 typedef reference reference_type; \
833 typedef ptr_type pointer_type; \
835 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
836 iterator() : m_node(NULL), m_init(NULL) { } \
837 reference_type operator*() const \
838 { return *(pointer_type)m_node->GetDataPtr(); } \
840 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
841 const itor operator++(int) \
842 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
845 m_node = m_node ? m_node->GetPrevious() : m_init; \
848 const itor operator--(int) \
851 m_node = m_node ? m_node->GetPrevious() : m_init; \
854 bool operator!=(const itor& it) const \
855 { return it.m_node != m_node; } \
856 bool operator==(const itor& it) const \
857 { return it.m_node == m_node; } \
859 classexp const_iterator \
863 typedef nodetype Node; \
864 typedef T* value_type; \
865 typedef const value_type& const_reference; \
866 typedef const_iterator itor; \
867 typedef value_type* ptr_type; \
872 typedef const_reference reference_type; \
873 typedef const ptr_type pointer_type; \
875 const_iterator(Node* node, Node* init) \
876 : m_node(node), m_init(init) { } \
877 const_iterator() : m_node(NULL), m_init(NULL) { } \
878 const_iterator(const iterator& it) \
879 : m_node(it.m_node), m_init(it.m_init) { } \
880 reference_type operator*() const \
881 { return *(pointer_type)m_node->GetDataPtr(); } \
883 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
884 const itor operator++(int) \
885 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
888 m_node = m_node ? m_node->GetPrevious() : m_init; \
891 const itor operator--(int) \
894 m_node = m_node ? m_node->GetPrevious() : m_init; \
897 bool operator!=(const itor& it) const \
898 { return it.m_node != m_node; } \
899 bool operator==(const itor& it) const \
900 { return it.m_node == m_node; } \
902 classexp reverse_iterator \
906 typedef nodetype Node; \
907 typedef T* value_type; \
908 typedef reverse_iterator itor; \
909 typedef value_type* ptr_type; \
910 typedef value_type& reference; \
915 typedef reference reference_type; \
916 typedef ptr_type pointer_type; \
918 reverse_iterator(Node* node, Node* init) \
919 : m_node(node), m_init(init) { } \
920 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
921 reference_type operator*() const \
922 { return *(pointer_type)m_node->GetDataPtr(); } \
925 { m_node = m_node->GetPrevious(); return *this; } \
926 const itor operator++(int) \
927 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
929 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
930 const itor operator--(int) \
933 m_node = m_node ? m_node->GetNext() : m_init; \
936 bool operator!=(const itor& it) const \
937 { return it.m_node != m_node; } \
938 bool operator==(const itor& it) const \
939 { return it.m_node == m_node; } \
941 classexp const_reverse_iterator \
945 typedef nodetype Node; \
946 typedef T* value_type; \
947 typedef const_reverse_iterator itor; \
948 typedef value_type* ptr_type; \
949 typedef const value_type& const_reference; \
954 typedef const_reference reference_type; \
955 typedef const ptr_type pointer_type; \
957 const_reverse_iterator(Node* node, Node* init) \
958 : m_node(node), m_init(init) { } \
959 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
960 const_reverse_iterator(const reverse_iterator& it) \
961 : m_node(it.m_node), m_init(it.m_init) { } \
962 reference_type operator*() const \
963 { return *(pointer_type)m_node->GetDataPtr(); } \
966 { m_node = m_node->GetPrevious(); return *this; } \
967 const itor operator++(int) \
968 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
970 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
971 const itor operator--(int) \
974 m_node = m_node ? m_node->GetNext() : m_init; \
977 bool operator!=(const itor& it) const \
978 { return it.m_node != m_node; } \
979 bool operator==(const itor& it) const \
980 { return it.m_node == m_node; } \
983 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
985 name(const const_iterator& first, const const_iterator& last) \
986 { assign(first, last); } \
987 iterator begin() { return iterator(GetFirst(), GetLast()); } \
988 const_iterator begin() const \
989 { return const_iterator(GetFirst(), GetLast()); } \
990 iterator end() { return iterator(NULL, GetLast()); } \
991 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
992 reverse_iterator rbegin() \
993 { return reverse_iterator(GetLast(), GetFirst()); } \
994 const_reverse_iterator rbegin() const \
995 { return const_reverse_iterator(GetLast(), GetFirst()); } \
996 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
997 const_reverse_iterator rend() const \
998 { return const_reverse_iterator(NULL, GetFirst()); } \
999 void resize(size_type n, value_type v = value_type()) \
1001 while (n < size()) \
1003 while (n > size()) \
1006 size_type size() const { return GetCount(); } \
1007 size_type max_size() const { return INT_MAX; } \
1008 bool empty() const { return IsEmpty(); } \
1009 reference front() { return *begin(); } \
1010 const_reference front() const { return *begin(); } \
1011 reference back() { iterator tmp = end(); return *--tmp; } \
1012 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1013 void push_front(const_reference v = value_type()) \
1014 { Insert(GetFirst(), (const_base_reference)v); } \
1015 void pop_front() { DeleteNode(GetFirst()); } \
1016 void push_back(const_reference v = value_type()) \
1017 { Append((const_base_reference)v); } \
1018 void pop_back() { DeleteNode(GetLast()); } \
1019 void assign(const_iterator first, const const_iterator& last) \
1022 for(; first != last; ++first) \
1023 Append((const_base_reference)*first); \
1025 void assign(size_type n, const_reference v = value_type()) \
1028 for(size_type i = 0; i < n; ++i) \
1029 Append((const_base_reference)v); \
1031 iterator insert(const iterator& it, const_reference v = value_type())\
1033 Insert(it.m_node, (const_base_reference)v); \
1034 return iterator(it.m_node->GetPrevious(), GetLast()); \
1036 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1038 for(size_type i = 0; i < n; ++i) \
1039 Insert(it.m_node, (const_base_reference)v); \
1041 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1043 for(; first != last; ++first) \
1044 Insert(it.m_node, (const_base_reference)*first); \
1046 iterator erase(const iterator& it) \
1048 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1049 DeleteNode(it.m_node); return next; \
1051 iterator erase(const iterator& first, const iterator& last) \
1053 iterator next = last; ++next; \
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 iterator tmp = first; ++tmp; \
1065 if(it == first || it == tmp) return; \
1066 insert(it, *first); \
1069 void remove(const_reference v) \
1070 { DeleteObject((const_base_reference)v); } \
1073 /* void swap(name& l) \
1075 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1076 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1077 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1078 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1079 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1083 #define WX_LIST_PTROP \
1084 pointer_type operator->() const \
1085 { return (pointer_type)m_node->GetDataPtr(); }
1086 #define WX_LIST_PTROP_NONE
1088 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1089 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1090 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1091 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1093 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1094 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1095 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1096 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1098 #define WX_DECLARE_LIST(elementtype, listname) \
1099 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1100 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1101 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1102 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1103 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1105 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1106 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1107 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1109 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1110 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1112 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1113 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1114 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1116 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1117 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1118 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1119 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1120 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1121 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1123 // this macro must be inserted in your program after
1124 // #include "wx/listimpl.cpp"
1125 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1127 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1128 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1130 #endif // !wxUSE_STL
1132 // ============================================================================
1133 // now we can define classes 100% compatible with the old ones
1134 // ============================================================================
1136 // ----------------------------------------------------------------------------
1137 // commonly used list classes
1138 // ----------------------------------------------------------------------------
1140 #if defined(wxLIST_COMPATIBILITY)
1142 // inline compatibility functions
1146 // ----------------------------------------------------------------------------
1147 // wxNodeBase deprecated methods
1148 // ----------------------------------------------------------------------------
1150 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1151 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1152 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1154 // ----------------------------------------------------------------------------
1155 // wxListBase deprecated methods
1156 // ----------------------------------------------------------------------------
1158 inline int wxListBase::Number() const { return (int)GetCount(); }
1159 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1160 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1161 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1162 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1166 // define this to make a lot of noise about use of the old wxList classes.
1167 //#define wxWARN_COMPAT_LIST_USE
1169 // ----------------------------------------------------------------------------
1170 // wxList compatibility class: in fact, it's a list of wxObjects
1171 // ----------------------------------------------------------------------------
1173 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1174 class WXDLLIMPEXP_BASE
);
1176 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1179 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1181 wxDEPRECATED( wxList(int key_type
) );
1183 wxList(int key_type
= wxKEY_NONE
);
1186 // this destructor is required for Darwin
1190 wxList
& operator=(const wxList
& list
)
1191 { (void) wxListBase::operator=(list
); return *this; }
1193 // compatibility methods
1194 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1199 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1204 DECLARE_DYNAMIC_CLASS(wxList
)
1210 // -----------------------------------------------------------------------------
1211 // wxStringList class for compatibility with the old code
1212 // -----------------------------------------------------------------------------
1213 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1215 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1220 #ifdef wxWARN_COMPAT_LIST_USE
1222 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1225 wxStringList(const wxChar
*first
...);
1228 // copying the string list: the strings are copied, too (extremely
1230 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1231 wxStringList
& operator=(const wxStringList
& other
)
1232 { Clear(); DoCopy(other
); return *this; }
1235 // makes a copy of the string
1236 wxNode
*Add(const wxChar
*s
);
1238 // Append to beginning of list
1239 wxNode
*Prepend(const wxChar
*s
);
1241 bool Delete(const wxChar
*s
);
1243 wxChar
**ListToArray(bool new_copies
= false) const;
1244 bool Member(const wxChar
*s
) const;
1250 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1252 DECLARE_DYNAMIC_CLASS(wxStringList
)
1255 #else // if wxUSE_STL
1257 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1259 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1262 compatibility_iterator
Append(wxChar
* s
)
1263 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1264 compatibility_iterator
Insert(wxChar
* s
)
1265 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1266 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1270 return wxStringListBase::Insert(pos
, tmp
);
1272 compatibility_iterator
Add(const wxChar
* s
)
1273 { push_back(s
); return GetLast(); }
1274 compatibility_iterator
Prepend(const wxChar
* s
)
1275 { push_front(s
); return GetFirst(); }
1280 #endif // wxLIST_COMPATIBILITY
1282 // delete all list elements
1284 // NB: the class declaration of the list elements must be visible from the
1285 // place where you use this macro, otherwise the proper destructor may not
1286 // be called (a decent compiler should give a warning about it, but don't
1288 #define WX_CLEAR_LIST(type, list) \
1290 type::iterator it, en; \
1291 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1296 #endif // _WX_LISTH__