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 compatibility_iterator GetFirst() const \
267 return compatibility_iterator( this, \
268 const_cast< liT* >(this)->begin() ); \
270 compatibility_iterator GetLast() const \
272 iterator i = const_cast< liT* >(this)->end(); \
273 return compatibility_iterator( this, !empty() ? --i : i ); \
275 compatibility_iterator Member( elT e ) const \
276 { return Find( e ); } \
277 compatibility_iterator Nth( int n ) const \
278 { return Item( n ); } \
279 int IndexOf( elT e ) const \
280 { return Find( e ).IndexOf(); } \
282 compatibility_iterator Append( elT e ) \
287 compatibility_iterator Insert( elT e ) \
290 return compatibility_iterator( this, begin() ); \
292 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
294 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
296 compatibility_iterator Insert( size_t idx, elT e ) \
298 return compatibility_iterator( this, \
299 insert( Item( idx ).m_iter, e ) ); \
302 void DeleteContents( bool destroy ) \
303 { m_destroy = destroy; } \
304 bool GetDeleteContents() const \
305 { return m_destroy; } \
306 void Erase( const compatibility_iterator& i ) \
309 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
312 bool DeleteNode( const compatibility_iterator& i ) \
321 bool DeleteObject( elT e ) \
323 return DeleteNode( Find( e ) ); \
328 std::for_each( begin(), end(), \
329 _WX_LIST_HELPER_##liT::DeleteFunction ); \
332 /* Workaround for broken VC6 std::list::sort() see above */ \
333 void Sort( wxSortCompareFunction compfunc ) \
334 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
335 ~liT() { Clear(); } \
338 #define WX_DECLARE_LIST(elementtype, listname) \
339 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
340 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
341 WX_DECLARE_LIST(elementtype, listname)
343 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
344 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
345 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
346 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
348 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
349 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
350 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
351 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
353 // this macro must be inserted in your program after
354 // #include "wx/listimpl.cpp"
355 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
357 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
358 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
360 #else // if !wxUSE_STL
362 // due to circular header dependencies this function has to be declared here
363 // (normally it's found in utils.h which includes itself list.h...)
364 #if WXWIN_COMPATIBILITY_2_4
365 extern WXDLLIMPEXP_BASE wxChar
* copystring(const wxChar
*s
);
368 // undef it to get rid of old, deprecated functions
369 #define wxLIST_COMPATIBILITY
371 // -----------------------------------------------------------------------------
372 // key stuff: a list may be optionally keyed on integer or string key
373 // -----------------------------------------------------------------------------
381 // a struct which may contain both types of keys
383 // implementation note: on one hand, this class allows to have only one function
384 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
385 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
386 // wxList::Find(const char *).
387 class WXDLLIMPEXP_BASE wxListKey
391 wxListKey() : m_keyType(wxKEY_NONE
)
393 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
394 { m_key
.integer
= i
; }
395 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
396 { m_key
.string
= wxStrdup(s
); }
397 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
398 { m_key
.string
= wxStrdup(s
.c_str()); }
401 wxKeyType
GetKeyType() const { return m_keyType
; }
402 const wxChar
*GetString() const
403 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
404 long GetNumber() const
405 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
408 // Note: implementation moved to list.cpp to prevent BC++ inline
409 // expansion warning.
410 bool operator==(wxListKeyValue value
) const ;
415 if ( m_keyType
== wxKEY_STRING
)
421 wxListKeyValue m_key
;
424 // -----------------------------------------------------------------------------
425 // wxNodeBase class is a (base for) node in a double linked list
426 // -----------------------------------------------------------------------------
428 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
430 class WXDLLIMPEXP_BASE wxListBase
;
432 class WXDLLIMPEXP_BASE wxNodeBase
434 friend class wxListBase
;
437 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
438 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
439 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
441 const wxListKey
& key
= wxDefaultListKey
);
443 virtual ~wxNodeBase();
445 // FIXME no check is done that the list is really keyed on strings
446 const wxChar
*GetKeyString() const { return m_key
.string
; }
447 long GetKeyInteger() const { return m_key
.integer
; }
449 // Necessary for some existing code
450 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
451 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
453 #ifdef wxLIST_COMPATIBILITY
454 // compatibility methods, use Get* instead.
455 wxDEPRECATED( wxNode
*Next() const );
456 wxDEPRECATED( wxNode
*Previous() const );
457 wxDEPRECATED( wxObject
*Data() const );
458 #endif // wxLIST_COMPATIBILITY
461 // all these are going to be "overloaded" in the derived classes
462 wxNodeBase
*GetNext() const { return m_next
; }
463 wxNodeBase
*GetPrevious() const { return m_previous
; }
465 void *GetData() const { return m_data
; }
466 void SetData(void *data
) { m_data
= data
; }
468 // get 0-based index of this node within the list or wxNOT_FOUND
471 virtual void DeleteData() { }
473 // for wxList::iterator
474 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
476 // optional key stuff
477 wxListKeyValue m_key
;
479 void *m_data
; // user data
480 wxNodeBase
*m_next
, // next and previous nodes in the list
483 wxListBase
*m_list
; // list we belong to
485 DECLARE_NO_COPY_CLASS(wxNodeBase
)
488 // -----------------------------------------------------------------------------
489 // a double-linked list class
490 // -----------------------------------------------------------------------------
492 class WXDLLIMPEXP_BASE wxList
;
494 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
496 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
497 friend class wxHashTableBase
; // should be able to call untyped Find()
500 // default ctor & dtor
501 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
503 virtual ~wxListBase();
506 // count of items in the list
507 size_t GetCount() const { return m_count
; }
509 // return true if this list is empty
510 bool IsEmpty() const { return m_count
== 0; }
517 // instruct it to destroy user data when deleting nodes
518 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
520 // query if to delete
521 bool GetDeleteContents() const
522 { return m_destroy
; }
525 wxKeyType
GetKeyType() const
526 { return m_keyType
; }
528 // set the keytype (required by the serial code)
529 void SetKeyType(wxKeyType keyType
)
530 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
532 #ifdef wxLIST_COMPATIBILITY
533 // compatibility methods from old wxList
534 wxDEPRECATED( int Number() const ); // use GetCount instead.
535 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
536 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
537 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
539 // kludge for typesafe list migration in core classes.
540 wxDEPRECATED( operator wxList
&() const );
541 #endif // wxLIST_COMPATIBILITY
545 // all methods here are "overloaded" in derived classes to provide compile
546 // time type checking
548 // create a node for the list of this type
549 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
551 const wxListKey
& key
= wxDefaultListKey
) = 0;
553 // Can't access these from derived classes otherwise (bug in Salford C++?)
560 wxListBase(size_t count
, void *elements
[]);
561 // from a sequence of objects
562 wxListBase(void *object
, ... /* terminate with NULL */);
565 void Assign(const wxListBase
& list
)
566 { Clear(); DoCopy(list
); }
568 // get list head/tail
569 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
570 wxNodeBase
*GetLast() const { return m_nodeLast
; }
572 // by (0-based) index
573 wxNodeBase
*Item(size_t index
) const;
575 // get the list item's data
576 void *operator[](size_t n
) const
578 wxNodeBase
*node
= Item(n
);
580 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
584 // append to end of list
585 wxNodeBase
*Prepend(void *object
)
586 { return (wxNodeBase
*)wxListBase::Insert(object
); }
587 // append to beginning of list
588 wxNodeBase
*Append(void *object
);
589 // insert a new item at the beginning of the list
590 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
591 // insert a new item at the given position
592 wxNodeBase
*Insert(size_t pos
, void *object
)
593 { return pos
== GetCount() ? Append(object
)
594 : Insert(Item(pos
), object
); }
595 // insert before given node or at front of list if prev == NULL
596 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
599 wxNodeBase
*Append(long key
, void *object
);
600 wxNodeBase
*Append(const wxChar
*key
, void *object
);
602 // removes node from the list but doesn't delete it (returns pointer
603 // to the node or NULL if it wasn't found in the list)
604 wxNodeBase
*DetachNode(wxNodeBase
*node
);
605 // delete element from list, returns false if node not found
606 bool DeleteNode(wxNodeBase
*node
);
607 // finds object pointer and deletes node (and object if DeleteContents
608 // is on), returns false if object not found
609 bool DeleteObject(void *object
);
611 // search (all return NULL if item not found)
613 wxNodeBase
*Find(const void *object
) const;
616 wxNodeBase
*Find(const wxListKey
& key
) const;
618 // get 0-based index of object or wxNOT_FOUND
619 int IndexOf( void *object
) const;
621 // this function allows the sorting of arbitrary lists by giving
622 // a function to compare two list elements. The list is sorted in place.
623 void Sort(const wxSortCompareFunction compfunc
);
625 // functions for iterating over the list
626 void *FirstThat(wxListIterateFunction func
);
627 void ForEach(wxListIterateFunction func
);
628 void *LastThat(wxListIterateFunction func
);
630 // for STL interface, "last" points to one after the last node
631 // of the controlled sequence (NULL for the end of the list)
633 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
636 // common part of all ctors
637 void Init(wxKeyType keyType
= wxKEY_NONE
);
640 // common part of copy ctor and assignment operator
641 void DoCopy(const wxListBase
& list
);
642 // common part of all Append()s
643 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
644 // free node's data and node itself
645 void DoDeleteNode(wxNodeBase
*node
);
647 size_t m_count
; // number of elements in the list
648 bool m_destroy
; // destroy user data when deleting list items?
649 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
652 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
655 // -----------------------------------------------------------------------------
656 // macros for definition of "template" list type
657 // -----------------------------------------------------------------------------
659 // and now some heavy magic...
661 // declare a list type named 'name' and containing elements of type 'T *'
662 // (as a by product of macro expansion you also get wx##name##Node
663 // wxNode-derived type)
665 // implementation details:
666 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
667 // for the list of given type - this allows us to pass only the list name
668 // to WX_DEFINE_LIST() even if it needs both the name and the type
670 // 2. We redefine all non-type-safe wxList functions with type-safe versions
671 // which don't take any space (everything is inline), but bring compile
672 // time error checking.
674 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
675 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
676 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
677 // interesting capability to store polymorphic objects in the list and is
678 // particularly useful with, for example, "wxWindow *" list where the
679 // wxWindowBase pointers are put into the list, but wxWindow pointers are
680 // retrieved from it.
682 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
683 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
684 // it results in compiler warnings when this operator doesn't make sense
685 // (i.e. stored elements are not pointers)
687 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
688 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
689 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
691 classexp nodetype : public wxNodeBase \
694 nodetype(wxListBase *list = (wxListBase *)NULL, \
695 nodetype *previous = (nodetype *)NULL, \
696 nodetype *next = (nodetype *)NULL, \
697 T *data = (T *)NULL, \
698 const wxListKey& key = wxDefaultListKey) \
699 : wxNodeBase(list, previous, next, data, key) { } \
701 nodetype *GetNext() const \
702 { return (nodetype *)wxNodeBase::GetNext(); } \
703 nodetype *GetPrevious() const \
704 { return (nodetype *)wxNodeBase::GetPrevious(); } \
707 { return (T *)wxNodeBase::GetData(); } \
708 void SetData(T *data) \
709 { wxNodeBase::SetData(data); } \
712 virtual void DeleteData(); \
714 DECLARE_NO_COPY_CLASS(nodetype) \
717 classexp name : public wxListBase \
720 typedef nodetype Node; \
721 classexp compatibility_iterator \
724 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
726 Node *operator->() const { return m_ptr; } \
727 operator Node *() const { return m_ptr; } \
733 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
735 name(const name& list) : wxListBase(list.GetKeyType()) \
737 name(size_t count, T *elements[]) \
738 : wxListBase(count, (void **)elements) { } \
740 name& operator=(const name& list) \
741 { Assign(list); return *this; } \
743 nodetype *GetFirst() const \
744 { return (nodetype *)wxListBase::GetFirst(); } \
745 nodetype *GetLast() const \
746 { return (nodetype *)wxListBase::GetLast(); } \
748 nodetype *Item(size_t index) const \
749 { return (nodetype *)wxListBase::Item(index); } \
751 T *operator[](size_t index) const \
753 nodetype *node = Item(index); \
754 return node ? (T*)(node->GetData()) : (T*)NULL; \
757 nodetype *Append(Tbase *object) \
758 { return (nodetype *)wxListBase::Append(object); } \
759 nodetype *Insert(Tbase *object) \
760 { return (nodetype *)Insert((nodetype*)NULL, object); } \
761 nodetype *Insert(size_t pos, Tbase *object) \
762 { return (nodetype *)wxListBase::Insert(pos, object); } \
763 nodetype *Insert(nodetype *prev, Tbase *object) \
764 { return (nodetype *)wxListBase::Insert(prev, object); } \
766 nodetype *Append(long key, void *object) \
767 { return (nodetype *)wxListBase::Append(key, object); } \
768 nodetype *Append(const wxChar *key, void *object) \
769 { return (nodetype *)wxListBase::Append(key, object); } \
771 nodetype *DetachNode(nodetype *node) \
772 { return (nodetype *)wxListBase::DetachNode(node); } \
773 bool DeleteNode(nodetype *node) \
774 { return wxListBase::DeleteNode(node); } \
775 bool DeleteObject(Tbase *object) \
776 { return wxListBase::DeleteObject(object); } \
777 void Erase(nodetype *it) \
778 { DeleteNode(it); } \
780 nodetype *Find(const Tbase *object) const \
781 { return (nodetype *)wxListBase::Find(object); } \
783 virtual nodetype *Find(const wxListKey& key) const \
784 { return (nodetype *)wxListBase::Find(key); } \
786 int IndexOf(Tbase *object) const \
787 { return wxListBase::IndexOf(object); } \
789 void Sort(wxSortCompareFunction func) \
790 { wxListBase::Sort(func); } \
791 void Sort(wxSortFuncFor_##name func) \
792 { Sort((wxSortCompareFunction)func); } \
795 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
797 const wxListKey& key = wxDefaultListKey) \
799 return new nodetype(this, \
800 (nodetype *)prev, (nodetype *)next, \
803 /* STL interface */ \
805 typedef size_t size_type; \
806 typedef int difference_type; \
807 typedef T* value_type; \
808 typedef Tbase* base_value_type; \
809 typedef value_type& reference; \
810 typedef const value_type& const_reference; \
811 typedef base_value_type& base_reference; \
812 typedef const base_value_type& const_base_reference; \
818 typedef nodetype Node; \
819 typedef iterator itor; \
820 typedef T* value_type; \
821 typedef value_type* ptr_type; \
822 typedef value_type& reference; \
827 typedef reference reference_type; \
828 typedef ptr_type pointer_type; \
830 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
831 iterator() : m_node(NULL), m_init(NULL) { } \
832 reference_type operator*() const \
833 { return *(pointer_type)m_node->GetDataPtr(); } \
835 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
836 const itor operator++(int) \
837 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
840 m_node = m_node ? m_node->GetPrevious() : m_init; \
843 const itor operator--(int) \
846 m_node = m_node ? m_node->GetPrevious() : m_init; \
849 bool operator!=(const itor& it) const \
850 { return it.m_node != m_node; } \
851 bool operator==(const itor& it) const \
852 { return it.m_node == m_node; } \
854 classexp const_iterator \
858 typedef nodetype Node; \
859 typedef T* value_type; \
860 typedef const value_type& const_reference; \
861 typedef const_iterator itor; \
862 typedef value_type* ptr_type; \
867 typedef const_reference reference_type; \
868 typedef const ptr_type pointer_type; \
870 const_iterator(Node* node, Node* init) \
871 : m_node(node), m_init(init) { } \
872 const_iterator() : m_node(NULL), m_init(NULL) { } \
873 const_iterator(const iterator& it) \
874 : m_node(it.m_node), m_init(it.m_init) { } \
875 reference_type operator*() const \
876 { return *(pointer_type)m_node->GetDataPtr(); } \
878 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
879 const itor operator++(int) \
880 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
883 m_node = m_node ? m_node->GetPrevious() : m_init; \
886 const itor operator--(int) \
889 m_node = m_node ? m_node->GetPrevious() : m_init; \
892 bool operator!=(const itor& it) const \
893 { return it.m_node != m_node; } \
894 bool operator==(const itor& it) const \
895 { return it.m_node == m_node; } \
897 classexp reverse_iterator \
901 typedef nodetype Node; \
902 typedef T* value_type; \
903 typedef reverse_iterator itor; \
904 typedef value_type* ptr_type; \
905 typedef value_type& reference; \
910 typedef reference reference_type; \
911 typedef ptr_type pointer_type; \
913 reverse_iterator(Node* node, Node* init) \
914 : m_node(node), m_init(init) { } \
915 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
916 reference_type operator*() const \
917 { return *(pointer_type)m_node->GetDataPtr(); } \
920 { m_node = m_node->GetPrevious(); return *this; } \
921 const itor operator++(int) \
922 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
924 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
925 const itor operator--(int) \
928 m_node = m_node ? m_node->GetNext() : m_init; \
931 bool operator!=(const itor& it) const \
932 { return it.m_node != m_node; } \
933 bool operator==(const itor& it) const \
934 { return it.m_node == m_node; } \
936 classexp const_reverse_iterator \
940 typedef nodetype Node; \
941 typedef T* value_type; \
942 typedef const_reverse_iterator itor; \
943 typedef value_type* ptr_type; \
944 typedef const value_type& const_reference; \
949 typedef const_reference reference_type; \
950 typedef const ptr_type pointer_type; \
952 const_reverse_iterator(Node* node, Node* init) \
953 : m_node(node), m_init(init) { } \
954 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
955 const_reverse_iterator(const reverse_iterator& it) \
956 : m_node(it.m_node), m_init(it.m_init) { } \
957 reference_type operator*() const \
958 { return *(pointer_type)m_node->GetDataPtr(); } \
961 { m_node = m_node->GetPrevious(); return *this; } \
962 const itor operator++(int) \
963 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
965 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
966 const itor operator--(int) \
969 m_node = m_node ? m_node->GetNext() : m_init; \
972 bool operator!=(const itor& it) const \
973 { return it.m_node != m_node; } \
974 bool operator==(const itor& it) const \
975 { return it.m_node == m_node; } \
978 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
980 name(const const_iterator& first, const const_iterator& last) \
981 { assign(first, last); } \
982 iterator begin() { return iterator(GetFirst(), GetLast()); } \
983 const_iterator begin() const \
984 { return const_iterator(GetFirst(), GetLast()); } \
985 iterator end() { return iterator(NULL, GetLast()); } \
986 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
987 reverse_iterator rbegin() \
988 { return reverse_iterator(GetLast(), GetFirst()); } \
989 const_reverse_iterator rbegin() const \
990 { return const_reverse_iterator(GetLast(), GetFirst()); } \
991 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
992 const_reverse_iterator rend() const \
993 { return const_reverse_iterator(NULL, GetFirst()); } \
994 void resize(size_type n, value_type v = value_type()) \
1001 size_type size() const { return GetCount(); } \
1002 size_type max_size() const { return INT_MAX; } \
1003 bool empty() const { return IsEmpty(); } \
1004 reference front() { return *begin(); } \
1005 const_reference front() const { return *begin(); } \
1006 reference back() { iterator tmp = end(); return *--tmp; } \
1007 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1008 void push_front(const_reference v = value_type()) \
1009 { Insert(GetFirst(), (const_base_reference)v); } \
1010 void pop_front() { DeleteNode(GetFirst()); } \
1011 void push_back(const_reference v = value_type()) \
1012 { Append((const_base_reference)v); } \
1013 void pop_back() { DeleteNode(GetLast()); } \
1014 void assign(const_iterator first, const const_iterator& last) \
1017 for(; first != last; ++first) \
1018 Append((const_base_reference)*first); \
1020 void assign(size_type n, const_reference v = value_type()) \
1023 for(size_type i = 0; i < n; ++i) \
1024 Append((const_base_reference)v); \
1026 iterator insert(const iterator& it, const_reference v = value_type())\
1028 Insert(it.m_node, (const_base_reference)v); \
1029 return iterator(it.m_node->GetPrevious(), GetLast()); \
1031 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1033 for(size_type i = 0; i < n; ++i) \
1034 Insert(it.m_node, (const_base_reference)v); \
1036 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1038 for(; first != last; ++first) \
1039 Insert(it.m_node, (const_base_reference)*first); \
1041 iterator erase(const iterator& it) \
1043 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1044 DeleteNode(it.m_node); return next; \
1046 iterator erase(const iterator& first, const iterator& last) \
1048 iterator next = last; ++next; \
1049 DeleteNodes(first.m_node, last.m_node); \
1052 void clear() { Clear(); } \
1053 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1054 { insert(it, first, last); l.erase(first, last); } \
1055 void splice(const iterator& it, name& l) \
1056 { splice(it, l, l.begin(), l.end() ); } \
1057 void splice(const iterator& it, name& l, const iterator& first) \
1059 iterator tmp = first; ++tmp; \
1060 if(it == first || it == tmp) return; \
1061 insert(it, *first); \
1064 void remove(const_reference v) \
1065 { DeleteObject((const_base_reference)v); } \
1068 /* void swap(name& l) \
1070 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1071 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1072 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1073 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1074 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1078 #define WX_LIST_PTROP \
1079 pointer_type operator->() const \
1080 { return (pointer_type)m_node->GetDataPtr(); }
1081 #define WX_LIST_PTROP_NONE
1083 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1084 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1085 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1086 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1088 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1089 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1090 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1091 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1093 #define WX_DECLARE_LIST(elementtype, listname) \
1094 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1095 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1096 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1097 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1098 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1100 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1101 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1102 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1104 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1105 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1107 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1108 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1109 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1111 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1112 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1113 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1114 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1115 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1116 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1118 // this macro must be inserted in your program after
1119 // #include "wx/listimpl.cpp"
1120 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1122 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1123 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1125 #endif // !wxUSE_STL
1127 // ============================================================================
1128 // now we can define classes 100% compatible with the old ones
1129 // ============================================================================
1131 // ----------------------------------------------------------------------------
1132 // commonly used list classes
1133 // ----------------------------------------------------------------------------
1135 #if defined(wxLIST_COMPATIBILITY)
1137 // inline compatibility functions
1141 // ----------------------------------------------------------------------------
1142 // wxNodeBase deprecated methods
1143 // ----------------------------------------------------------------------------
1145 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1146 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1147 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1149 // ----------------------------------------------------------------------------
1150 // wxListBase deprecated methods
1151 // ----------------------------------------------------------------------------
1153 inline int wxListBase::Number() const { return (int)GetCount(); }
1154 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1155 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1156 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1157 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1161 // define this to make a lot of noise about use of the old wxList classes.
1162 //#define wxWARN_COMPAT_LIST_USE
1164 // ----------------------------------------------------------------------------
1165 // wxList compatibility class: in fact, it's a list of wxObjects
1166 // ----------------------------------------------------------------------------
1168 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1169 class WXDLLIMPEXP_BASE
);
1171 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1174 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1176 wxDEPRECATED( wxList(int key_type
) );
1178 wxList(int key_type
= wxKEY_NONE
);
1181 // this destructor is required for Darwin
1185 wxList
& operator=(const wxList
& list
)
1186 { (void) wxListBase::operator=(list
); return *this; }
1188 // compatibility methods
1189 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1194 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1199 DECLARE_DYNAMIC_CLASS(wxList
)
1205 // -----------------------------------------------------------------------------
1206 // wxStringList class for compatibility with the old code
1207 // -----------------------------------------------------------------------------
1208 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1210 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1215 #ifdef wxWARN_COMPAT_LIST_USE
1217 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1220 wxStringList(const wxChar
*first
...);
1223 // copying the string list: the strings are copied, too (extremely
1225 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1226 wxStringList
& operator=(const wxStringList
& other
)
1227 { Clear(); DoCopy(other
); return *this; }
1230 // makes a copy of the string
1231 wxNode
*Add(const wxChar
*s
);
1233 // Append to beginning of list
1234 wxNode
*Prepend(const wxChar
*s
);
1236 bool Delete(const wxChar
*s
);
1238 wxChar
**ListToArray(bool new_copies
= false) const;
1239 bool Member(const wxChar
*s
) const;
1245 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1247 DECLARE_DYNAMIC_CLASS(wxStringList
)
1250 #else // if wxUSE_STL
1252 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1254 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1257 compatibility_iterator
Append(wxChar
* s
)
1258 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1259 compatibility_iterator
Insert(wxChar
* s
)
1260 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1261 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1265 return wxStringListBase::Insert(pos
, tmp
);
1267 compatibility_iterator
Add(const wxChar
* s
)
1268 { push_back(s
); return GetLast(); }
1269 compatibility_iterator
Prepend(const wxChar
* s
)
1270 { push_front(s
); return GetFirst(); }
1275 #endif // wxLIST_COMPATIBILITY
1277 // delete all list elements
1279 // NB: the class declaration of the list elements must be visible from the
1280 // place where you use this macro, otherwise the proper destructor may not
1281 // be called (a decent compiler should give a warning about it, but don't
1283 #define WX_CLEAR_LIST(type, list) \
1285 type::iterator it, en; \
1286 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1291 #endif // _WX_LISTH__