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: 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 // the real wxList-class declaration
161 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
162 decl _WX_LIST_HELPER_##liT \
164 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
166 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
169 VC6_WORKAROUND(elT, liT, decl) \
170 decl liT : public std::list<elT> \
175 decl compatibility_iterator \
178 /* Workaround for broken VC6 nested class name resolution */ \
179 typedef std::list<elT>::iterator iterator; \
185 compatibility_iterator() \
186 : m_iter(), m_list( NULL ) {} \
187 compatibility_iterator( liT* li, iterator i ) \
188 : m_iter( i ), m_list( li ) {} \
189 compatibility_iterator( const liT* li, iterator i ) \
190 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
192 compatibility_iterator* operator->() { return this; } \
193 const compatibility_iterator* operator->() const { return this; } \
195 bool operator==(const compatibility_iterator& i) const \
197 wxASSERT_MSG( m_list && i.m_list, \
198 _T("comparing invalid iterators is illegal") ); \
199 return (m_list == i.m_list) && (m_iter == i.m_iter); \
201 bool operator!=(const compatibility_iterator& i) const \
202 { return !( operator==( i ) ); } \
203 operator bool() const \
204 { return m_list ? m_iter != m_list->end() : false; } \
205 bool operator !() const \
206 { return !( operator bool() ); } \
208 elT GetData() const \
209 { return *m_iter; } \
210 void SetData( elT e ) \
213 compatibility_iterator GetNext() const \
215 iterator i = m_iter; \
216 return compatibility_iterator( m_list, ++i ); \
218 compatibility_iterator GetPrevious() const \
220 if ( m_iter == m_list->begin() ) \
221 return compatibility_iterator(); \
223 iterator i = m_iter; \
224 return compatibility_iterator( m_list, --i ); \
226 int IndexOf() const \
228 return *this ? std::distance( m_list->begin(), m_iter ) \
233 liT() : m_destroy( false ) {} \
235 compatibility_iterator Find( const elT e ) const \
237 liT* _this = const_cast< liT* >( this ); \
238 return compatibility_iterator( _this, \
239 std::find( _this->begin(), _this->end(), e ) ); \
242 bool IsEmpty() const \
243 { return empty(); } \
244 size_t GetCount() const \
247 { return static_cast< int >( GetCount() ); } \
249 compatibility_iterator Item( size_t idx ) const \
251 iterator i = const_cast< liT* >(this)->begin(); \
252 std::advance( i, idx ); \
253 return compatibility_iterator( this, i ); \
255 compatibility_iterator GetFirst() const \
257 return compatibility_iterator( this, \
258 const_cast< liT* >(this)->begin() ); \
260 compatibility_iterator GetLast() const \
262 iterator i = const_cast< liT* >(this)->end(); \
263 return compatibility_iterator( this, !empty() ? --i : i ); \
265 compatibility_iterator Member( elT e ) const \
266 { return Find( e ); } \
267 compatibility_iterator Nth( int n ) const \
268 { return Item( n ); } \
269 int IndexOf( elT e ) const \
270 { return Find( e ).IndexOf(); } \
272 compatibility_iterator Append( elT e ) \
277 compatibility_iterator Insert( elT e ) \
280 return compatibility_iterator( this, begin() ); \
282 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
284 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
286 compatibility_iterator Insert( size_t idx, elT e ) \
288 return compatibility_iterator( this, \
289 insert( Item( idx ).m_iter, e ) ); \
292 void DeleteContents( bool destroy ) \
293 { m_destroy = destroy; } \
294 bool GetDeleteContents() const \
295 { return m_destroy; } \
296 void Erase( const compatibility_iterator& i ) \
299 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
302 bool DeleteNode( const compatibility_iterator& i ) \
311 bool DeleteObject( elT e ) \
313 return DeleteNode( Find( e ) ); \
318 std::for_each( begin(), end(), \
319 _WX_LIST_HELPER_##liT::DeleteFunction ); \
322 /* Workaround for broken VC6 std::list::sort() see above */ \
323 void Sort( wxSortCompareFunction compfunc ) \
324 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
325 ~liT() { Clear(); } \
328 #define WX_DECLARE_LIST(elementtype, listname) \
329 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
330 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
331 WX_DECLARE_LIST(elementtype, listname)
333 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
334 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
335 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
336 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
338 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
339 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
340 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
341 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
343 // this macro must be inserted in your program after
344 // #include "wx/listimpl.cpp"
345 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
347 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
348 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
350 #else // if !wxUSE_STL
352 // due to circular header dependencies this function has to be declared here
353 // (normally it's found in utils.h which includes itself list.h...)
354 #if WXWIN_COMPATIBILITY_2_4
355 extern WXDLLIMPEXP_BASE wxChar
* copystring(const wxChar
*s
);
358 // undef it to get rid of old, deprecated functions
359 #define wxLIST_COMPATIBILITY
361 // -----------------------------------------------------------------------------
362 // key stuff: a list may be optionally keyed on integer or string key
363 // -----------------------------------------------------------------------------
371 // a struct which may contain both types of keys
373 // implementation note: on one hand, this class allows to have only one function
374 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
375 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
376 // wxList::Find(const char *).
377 class WXDLLIMPEXP_BASE wxListKey
381 wxListKey() : m_keyType(wxKEY_NONE
)
383 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
384 { m_key
.integer
= i
; }
385 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
386 { m_key
.string
= wxStrdup(s
); }
387 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
388 { m_key
.string
= wxStrdup(s
.c_str()); }
391 wxKeyType
GetKeyType() const { return m_keyType
; }
392 const wxChar
*GetString() const
393 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
394 long GetNumber() const
395 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
398 // Note: implementation moved to list.cpp to prevent BC++ inline
399 // expansion warning.
400 bool operator==(wxListKeyValue value
) const ;
405 if ( m_keyType
== wxKEY_STRING
)
411 wxListKeyValue m_key
;
414 // -----------------------------------------------------------------------------
415 // wxNodeBase class is a (base for) node in a double linked list
416 // -----------------------------------------------------------------------------
418 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
420 class WXDLLIMPEXP_BASE wxListBase
;
422 class WXDLLIMPEXP_BASE wxNodeBase
424 friend class wxListBase
;
427 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
428 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
429 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
431 const wxListKey
& key
= wxDefaultListKey
);
433 virtual ~wxNodeBase();
435 // FIXME no check is done that the list is really keyed on strings
436 const wxChar
*GetKeyString() const { return m_key
.string
; }
437 long GetKeyInteger() const { return m_key
.integer
; }
439 // Necessary for some existing code
440 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
441 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
443 #ifdef wxLIST_COMPATIBILITY
444 // compatibility methods, use Get* instead.
445 wxDEPRECATED( wxNode
*Next() const );
446 wxDEPRECATED( wxNode
*Previous() const );
447 wxDEPRECATED( wxObject
*Data() const );
448 #endif // wxLIST_COMPATIBILITY
451 // all these are going to be "overloaded" in the derived classes
452 wxNodeBase
*GetNext() const { return m_next
; }
453 wxNodeBase
*GetPrevious() const { return m_previous
; }
455 void *GetData() const { return m_data
; }
456 void SetData(void *data
) { m_data
= data
; }
458 // get 0-based index of this node within the list or wxNOT_FOUND
461 virtual void DeleteData() { }
463 // for wxList::iterator
464 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
466 // optional key stuff
467 wxListKeyValue m_key
;
469 void *m_data
; // user data
470 wxNodeBase
*m_next
, // next and previous nodes in the list
473 wxListBase
*m_list
; // list we belong to
475 DECLARE_NO_COPY_CLASS(wxNodeBase
)
478 // -----------------------------------------------------------------------------
479 // a double-linked list class
480 // -----------------------------------------------------------------------------
482 class WXDLLIMPEXP_BASE wxList
;
484 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
486 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
487 friend class wxHashTableBase
; // should be able to call untyped Find()
490 // default ctor & dtor
491 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
493 virtual ~wxListBase();
496 // count of items in the list
497 size_t GetCount() const { return m_count
; }
499 // return true if this list is empty
500 bool IsEmpty() const { return m_count
== 0; }
507 // instruct it to destroy user data when deleting nodes
508 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
510 // query if to delete
511 bool GetDeleteContents() const
512 { return m_destroy
; }
515 wxKeyType
GetKeyType() const
516 { return m_keyType
; }
518 // set the keytype (required by the serial code)
519 void SetKeyType(wxKeyType keyType
)
520 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
522 #ifdef wxLIST_COMPATIBILITY
523 // compatibility methods from old wxList
524 wxDEPRECATED( int Number() const ); // use GetCount instead.
525 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
526 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
527 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
529 // kludge for typesafe list migration in core classes.
530 wxDEPRECATED( operator wxList
&() const );
531 #endif // wxLIST_COMPATIBILITY
535 // all methods here are "overloaded" in derived classes to provide compile
536 // time type checking
538 // create a node for the list of this type
539 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
541 const wxListKey
& key
= wxDefaultListKey
) = 0;
543 // Can't access these from derived classes otherwise (bug in Salford C++?)
550 wxListBase(size_t count
, void *elements
[]);
551 // from a sequence of objects
552 wxListBase(void *object
, ... /* terminate with NULL */);
555 void Assign(const wxListBase
& list
)
556 { Clear(); DoCopy(list
); }
558 // get list head/tail
559 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
560 wxNodeBase
*GetLast() const { return m_nodeLast
; }
562 // by (0-based) index
563 wxNodeBase
*Item(size_t index
) const;
565 // get the list item's data
566 void *operator[](size_t n
) const
568 wxNodeBase
*node
= Item(n
);
570 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
574 // append to end of list
575 wxNodeBase
*Prepend(void *object
)
576 { return (wxNodeBase
*)wxListBase::Insert(object
); }
577 // append to beginning of list
578 wxNodeBase
*Append(void *object
);
579 // insert a new item at the beginning of the list
580 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
581 // insert a new item at the given position
582 wxNodeBase
*Insert(size_t pos
, void *object
)
583 { return pos
== GetCount() ? Append(object
)
584 : Insert(Item(pos
), object
); }
585 // insert before given node or at front of list if prev == NULL
586 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
589 wxNodeBase
*Append(long key
, void *object
);
590 wxNodeBase
*Append(const wxChar
*key
, void *object
);
592 // removes node from the list but doesn't delete it (returns pointer
593 // to the node or NULL if it wasn't found in the list)
594 wxNodeBase
*DetachNode(wxNodeBase
*node
);
595 // delete element from list, returns false if node not found
596 bool DeleteNode(wxNodeBase
*node
);
597 // finds object pointer and deletes node (and object if DeleteContents
598 // is on), returns false if object not found
599 bool DeleteObject(void *object
);
601 // search (all return NULL if item not found)
603 wxNodeBase
*Find(const void *object
) const;
606 wxNodeBase
*Find(const wxListKey
& key
) const;
608 // get 0-based index of object or wxNOT_FOUND
609 int IndexOf( void *object
) const;
611 // this function allows the sorting of arbitrary lists by giving
612 // a function to compare two list elements. The list is sorted in place.
613 void Sort(const wxSortCompareFunction compfunc
);
615 // functions for iterating over the list
616 void *FirstThat(wxListIterateFunction func
);
617 void ForEach(wxListIterateFunction func
);
618 void *LastThat(wxListIterateFunction func
);
620 // for STL interface, "last" points to one after the last node
621 // of the controlled sequence (NULL for the end of the list)
623 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
626 // common part of all ctors
627 void Init(wxKeyType keyType
= wxKEY_NONE
);
630 // common part of copy ctor and assignment operator
631 void DoCopy(const wxListBase
& list
);
632 // common part of all Append()s
633 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
634 // free node's data and node itself
635 void DoDeleteNode(wxNodeBase
*node
);
637 size_t m_count
; // number of elements in the list
638 bool m_destroy
; // destroy user data when deleting list items?
639 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
642 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
645 // -----------------------------------------------------------------------------
646 // macros for definition of "template" list type
647 // -----------------------------------------------------------------------------
649 // and now some heavy magic...
651 // declare a list type named 'name' and containing elements of type 'T *'
652 // (as a by product of macro expansion you also get wx##name##Node
653 // wxNode-derived type)
655 // implementation details:
656 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
657 // for the list of given type - this allows us to pass only the list name
658 // to WX_DEFINE_LIST() even if it needs both the name and the type
660 // 2. We redefine all non-type-safe wxList functions with type-safe versions
661 // which don't take any space (everything is inline), but bring compile
662 // time error checking.
664 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
665 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
666 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
667 // interesting capability to store polymorphic objects in the list and is
668 // particularly useful with, for example, "wxWindow *" list where the
669 // wxWindowBase pointers are put into the list, but wxWindow pointers are
670 // retrieved from it.
672 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
673 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
674 // it results in compiler warnings when this operator doesn't make sense
675 // (i.e. stored elements are not pointers)
677 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
678 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
679 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
681 classexp nodetype : public wxNodeBase \
684 nodetype(wxListBase *list = (wxListBase *)NULL, \
685 nodetype *previous = (nodetype *)NULL, \
686 nodetype *next = (nodetype *)NULL, \
687 T *data = (T *)NULL, \
688 const wxListKey& key = wxDefaultListKey) \
689 : wxNodeBase(list, previous, next, data, key) { } \
691 nodetype *GetNext() const \
692 { return (nodetype *)wxNodeBase::GetNext(); } \
693 nodetype *GetPrevious() const \
694 { return (nodetype *)wxNodeBase::GetPrevious(); } \
697 { return (T *)wxNodeBase::GetData(); } \
698 void SetData(T *data) \
699 { wxNodeBase::SetData(data); } \
702 virtual void DeleteData(); \
704 DECLARE_NO_COPY_CLASS(nodetype) \
707 classexp name : public wxListBase \
710 typedef nodetype Node; \
711 classexp compatibility_iterator \
714 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
716 Node *operator->() const { return m_ptr; } \
717 operator Node *() const { return m_ptr; } \
723 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
725 name(const name& list) : wxListBase(list.GetKeyType()) \
727 name(size_t count, T *elements[]) \
728 : wxListBase(count, (void **)elements) { } \
730 name& operator=(const name& list) \
731 { Assign(list); return *this; } \
733 nodetype *GetFirst() const \
734 { return (nodetype *)wxListBase::GetFirst(); } \
735 nodetype *GetLast() const \
736 { return (nodetype *)wxListBase::GetLast(); } \
738 nodetype *Item(size_t index) const \
739 { return (nodetype *)wxListBase::Item(index); } \
741 T *operator[](size_t index) const \
743 nodetype *node = Item(index); \
744 return node ? (T*)(node->GetData()) : (T*)NULL; \
747 nodetype *Append(Tbase *object) \
748 { return (nodetype *)wxListBase::Append(object); } \
749 nodetype *Insert(Tbase *object) \
750 { return (nodetype *)Insert((nodetype*)NULL, object); } \
751 nodetype *Insert(size_t pos, Tbase *object) \
752 { return (nodetype *)wxListBase::Insert(pos, object); } \
753 nodetype *Insert(nodetype *prev, Tbase *object) \
754 { return (nodetype *)wxListBase::Insert(prev, object); } \
756 nodetype *Append(long key, void *object) \
757 { return (nodetype *)wxListBase::Append(key, object); } \
758 nodetype *Append(const wxChar *key, void *object) \
759 { return (nodetype *)wxListBase::Append(key, object); } \
761 nodetype *DetachNode(nodetype *node) \
762 { return (nodetype *)wxListBase::DetachNode(node); } \
763 bool DeleteNode(nodetype *node) \
764 { return wxListBase::DeleteNode(node); } \
765 bool DeleteObject(Tbase *object) \
766 { return wxListBase::DeleteObject(object); } \
767 void Erase(nodetype *it) \
768 { DeleteNode(it); } \
770 nodetype *Find(const Tbase *object) const \
771 { return (nodetype *)wxListBase::Find(object); } \
773 virtual nodetype *Find(const wxListKey& key) const \
774 { return (nodetype *)wxListBase::Find(key); } \
776 int IndexOf(Tbase *object) const \
777 { return wxListBase::IndexOf(object); } \
779 void Sort(wxSortCompareFunction func) \
780 { wxListBase::Sort(func); } \
781 void Sort(wxSortFuncFor_##name func) \
782 { Sort((wxSortCompareFunction)func); } \
785 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
787 const wxListKey& key = wxDefaultListKey) \
789 return new nodetype(this, \
790 (nodetype *)prev, (nodetype *)next, \
793 /* STL interface */ \
795 typedef size_t size_type; \
796 typedef int difference_type; \
797 typedef T* value_type; \
798 typedef Tbase* base_value_type; \
799 typedef value_type& reference; \
800 typedef const value_type& const_reference; \
801 typedef base_value_type& base_reference; \
802 typedef const base_value_type& const_base_reference; \
808 typedef nodetype Node; \
809 typedef iterator itor; \
810 typedef T* value_type; \
811 typedef value_type* ptr_type; \
812 typedef value_type& reference; \
817 typedef reference reference_type; \
818 typedef ptr_type pointer_type; \
820 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
821 iterator() : m_node(NULL), m_init(NULL) { } \
822 reference_type operator*() const \
823 { return *(pointer_type)m_node->GetDataPtr(); } \
825 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
826 const itor operator++(int) \
827 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
830 m_node = m_node ? m_node->GetPrevious() : m_init; \
833 const itor operator--(int) \
836 m_node = m_node ? m_node->GetPrevious() : m_init; \
839 bool operator!=(const itor& it) const \
840 { return it.m_node != m_node; } \
841 bool operator==(const itor& it) const \
842 { return it.m_node == m_node; } \
844 classexp const_iterator \
848 typedef nodetype Node; \
849 typedef T* value_type; \
850 typedef const value_type& const_reference; \
851 typedef const_iterator itor; \
852 typedef value_type* ptr_type; \
857 typedef const_reference reference_type; \
858 typedef const ptr_type pointer_type; \
860 const_iterator(Node* node, Node* init) \
861 : m_node(node), m_init(init) { } \
862 const_iterator() : m_node(NULL), m_init(NULL) { } \
863 const_iterator(const iterator& it) \
864 : m_node(it.m_node), m_init(it.m_init) { } \
865 reference_type operator*() const \
866 { return *(pointer_type)m_node->GetDataPtr(); } \
868 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
869 const itor operator++(int) \
870 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
873 m_node = m_node ? m_node->GetPrevious() : m_init; \
876 const itor operator--(int) \
879 m_node = m_node ? m_node->GetPrevious() : m_init; \
882 bool operator!=(const itor& it) const \
883 { return it.m_node != m_node; } \
884 bool operator==(const itor& it) const \
885 { return it.m_node == m_node; } \
887 classexp reverse_iterator \
891 typedef nodetype Node; \
892 typedef T* value_type; \
893 typedef reverse_iterator itor; \
894 typedef value_type* ptr_type; \
895 typedef value_type& reference; \
900 typedef reference reference_type; \
901 typedef ptr_type pointer_type; \
903 reverse_iterator(Node* node, Node* init) \
904 : m_node(node), m_init(init) { } \
905 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
906 reference_type operator*() const \
907 { return *(pointer_type)m_node->GetDataPtr(); } \
910 { m_node = m_node->GetPrevious(); return *this; } \
911 const itor operator++(int) \
912 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
914 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
915 const itor operator--(int) \
918 m_node = m_node ? m_node->GetNext() : m_init; \
921 bool operator!=(const itor& it) const \
922 { return it.m_node != m_node; } \
923 bool operator==(const itor& it) const \
924 { return it.m_node == m_node; } \
926 classexp const_reverse_iterator \
930 typedef nodetype Node; \
931 typedef T* value_type; \
932 typedef const_reverse_iterator itor; \
933 typedef value_type* ptr_type; \
934 typedef const value_type& const_reference; \
939 typedef const_reference reference_type; \
940 typedef const ptr_type pointer_type; \
942 const_reverse_iterator(Node* node, Node* init) \
943 : m_node(node), m_init(init) { } \
944 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
945 const_reverse_iterator(const reverse_iterator& it) \
946 : m_node(it.m_node), m_init(it.m_init) { } \
947 reference_type operator*() const \
948 { return *(pointer_type)m_node->GetDataPtr(); } \
951 { m_node = m_node->GetPrevious(); return *this; } \
952 const itor operator++(int) \
953 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
955 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
956 const itor operator--(int) \
959 m_node = m_node ? m_node->GetNext() : m_init; \
962 bool operator!=(const itor& it) const \
963 { return it.m_node != m_node; } \
964 bool operator==(const itor& it) const \
965 { return it.m_node == m_node; } \
968 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
970 name(const const_iterator& first, const const_iterator& last) \
971 { assign(first, last); } \
972 iterator begin() { return iterator(GetFirst(), GetLast()); } \
973 const_iterator begin() const \
974 { return const_iterator(GetFirst(), GetLast()); } \
975 iterator end() { return iterator(NULL, GetLast()); } \
976 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
977 reverse_iterator rbegin() \
978 { return reverse_iterator(GetLast(), GetFirst()); } \
979 const_reverse_iterator rbegin() const \
980 { return const_reverse_iterator(GetLast(), GetFirst()); } \
981 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
982 const_reverse_iterator rend() const \
983 { return const_reverse_iterator(NULL, GetFirst()); } \
984 void resize(size_type n, value_type v = value_type()) \
991 size_type size() const { return GetCount(); } \
992 size_type max_size() const { return INT_MAX; } \
993 bool empty() const { return IsEmpty(); } \
994 reference front() { return *begin(); } \
995 const_reference front() const { return *begin(); } \
996 reference back() { iterator tmp = end(); return *--tmp; } \
997 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
998 void push_front(const_reference v = value_type()) \
999 { Insert(GetFirst(), (const_base_reference)v); } \
1000 void pop_front() { DeleteNode(GetFirst()); } \
1001 void push_back(const_reference v = value_type()) \
1002 { Append((const_base_reference)v); } \
1003 void pop_back() { DeleteNode(GetLast()); } \
1004 void assign(const_iterator first, const const_iterator& last) \
1007 for(; first != last; ++first) \
1008 Append((const_base_reference)*first); \
1010 void assign(size_type n, const_reference v = value_type()) \
1013 for(size_type i = 0; i < n; ++i) \
1014 Append((const_base_reference)v); \
1016 iterator insert(const iterator& it, const_reference v = value_type())\
1018 Insert(it.m_node, (const_base_reference)v); \
1019 return iterator(it.m_node->GetPrevious(), GetLast()); \
1021 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1023 for(size_type i = 0; i < n; ++i) \
1024 Insert(it.m_node, (const_base_reference)v); \
1026 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1028 for(; first != last; ++first) \
1029 Insert(it.m_node, (const_base_reference)*first); \
1031 iterator erase(const iterator& it) \
1033 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1034 DeleteNode(it.m_node); return next; \
1036 iterator erase(const iterator& first, const iterator& last) \
1038 iterator next = last; ++next; \
1039 DeleteNodes(first.m_node, last.m_node); \
1042 void clear() { Clear(); } \
1043 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1044 { insert(it, first, last); l.erase(first, last); } \
1045 void splice(const iterator& it, name& l) \
1046 { splice(it, l, l.begin(), l.end() ); } \
1047 void splice(const iterator& it, name& l, const iterator& first) \
1049 iterator tmp = first; ++tmp; \
1050 if(it == first || it == tmp) return; \
1051 insert(it, *first); \
1054 void remove(const_reference v) \
1055 { DeleteObject((const_base_reference)v); } \
1058 /* void swap(name& l) \
1060 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1061 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1062 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1063 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1064 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1068 #define WX_LIST_PTROP \
1069 pointer_type operator->() const \
1070 { return (pointer_type)m_node->GetDataPtr(); }
1071 #define WX_LIST_PTROP_NONE
1073 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1074 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1075 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1076 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1078 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1079 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1080 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1081 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1083 #define WX_DECLARE_LIST(elementtype, listname) \
1084 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1085 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1086 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1087 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1088 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1090 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1091 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1092 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1094 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1095 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1097 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1098 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1099 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1101 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1102 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1103 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1104 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1105 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1106 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1108 // this macro must be inserted in your program after
1109 // #include "wx/listimpl.cpp"
1110 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1112 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1113 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1115 #endif // !wxUSE_STL
1117 // ============================================================================
1118 // now we can define classes 100% compatible with the old ones
1119 // ============================================================================
1121 // ----------------------------------------------------------------------------
1122 // commonly used list classes
1123 // ----------------------------------------------------------------------------
1125 #if defined(wxLIST_COMPATIBILITY)
1127 // inline compatibility functions
1131 // ----------------------------------------------------------------------------
1132 // wxNodeBase deprecated methods
1133 // ----------------------------------------------------------------------------
1135 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1136 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1137 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1139 // ----------------------------------------------------------------------------
1140 // wxListBase deprecated methods
1141 // ----------------------------------------------------------------------------
1143 inline int wxListBase::Number() const { return (int)GetCount(); }
1144 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1145 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1146 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1147 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1151 // define this to make a lot of noise about use of the old wxList classes.
1152 //#define wxWARN_COMPAT_LIST_USE
1154 // ----------------------------------------------------------------------------
1155 // wxList compatibility class: in fact, it's a list of wxObjects
1156 // ----------------------------------------------------------------------------
1158 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1159 class WXDLLIMPEXP_BASE
);
1161 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1164 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1166 wxDEPRECATED( wxList(int key_type
) );
1168 wxList(int key_type
= wxKEY_NONE
);
1171 // this destructor is required for Darwin
1175 wxList
& operator=(const wxList
& list
)
1176 { (void) wxListBase::operator=(list
); return *this; }
1178 // compatibility methods
1179 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1184 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1189 DECLARE_DYNAMIC_CLASS(wxList
)
1195 // -----------------------------------------------------------------------------
1196 // wxStringList class for compatibility with the old code
1197 // -----------------------------------------------------------------------------
1198 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1200 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1205 #ifdef wxWARN_COMPAT_LIST_USE
1207 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1210 wxStringList(const wxChar
*first
...);
1213 // copying the string list: the strings are copied, too (extremely
1215 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1216 wxStringList
& operator=(const wxStringList
& other
)
1217 { Clear(); DoCopy(other
); return *this; }
1220 // makes a copy of the string
1221 wxNode
*Add(const wxChar
*s
);
1223 // Append to beginning of list
1224 wxNode
*Prepend(const wxChar
*s
);
1226 bool Delete(const wxChar
*s
);
1228 wxChar
**ListToArray(bool new_copies
= false) const;
1229 bool Member(const wxChar
*s
) const;
1235 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1237 DECLARE_DYNAMIC_CLASS(wxStringList
)
1240 #else // if wxUSE_STL
1242 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1244 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1247 compatibility_iterator
Append(wxChar
* s
)
1248 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1249 compatibility_iterator
Insert(wxChar
* s
)
1250 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1251 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1255 return wxStringListBase::Insert(pos
, tmp
);
1257 compatibility_iterator
Add(const wxChar
* s
)
1258 { push_back(s
); return GetLast(); }
1259 compatibility_iterator
Prepend(const wxChar
* s
)
1260 { push_front(s
); return GetFirst(); }
1265 #endif // wxLIST_COMPATIBILITY
1267 // delete all list elements
1269 // NB: the class declaration of the list elements must be visible from the
1270 // place where you use this macro, otherwise the proper destructor may not
1271 // be called (a decent compiler should give a warning about it, but don't
1273 #define WX_CLEAR_LIST(type, list) \
1275 type::iterator it, en; \
1276 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1281 #endif // _WX_LISTH__