1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxList, wxStringList classes
4 // Author: Julian Smart
5 // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 All this is quite ugly but serves two purposes:
14 1. Be almost 100% compatible with old, untyped, wxList class
15 2. Ensure compile-time type checking for the linked lists
17 The idea is to have one base class (wxListBase) working with "void *" data,
18 but to hide these untyped functions - i.e. make them protected, so they
19 can only be used from derived classes which have inline member functions
20 working with right types. This achieves the 2nd goal. As for the first one,
21 we provide a special derivation of wxListBase called wxList which looks just
28 // -----------------------------------------------------------------------------
30 // -----------------------------------------------------------------------------
33 #include "wx/object.h"
34 #include "wx/string.h"
37 #include "wx/beforestd.h"
41 #include "wx/afterstd.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 // type of compare function for list sort operation (as in 'qsort'): it should
49 // return a negative value, 0 or positive value if the first element is less
50 // than, equal or greater than the second
54 typedef int (* LINKAGEMODE wxSortCompareFunction
)(const void *elem1
, const void *elem2
);
57 class WXDLLIMPEXP_BASE wxObjectListNode
;
58 typedef wxObjectListNode wxNode
;
61 typedef int (* LINKAGEMODE wxListIterateFunction
)(void *current
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #if !defined(wxENUM_KEY_TYPE_DEFINED)
68 #define wxENUM_KEY_TYPE_DEFINED
81 #define wxLIST_COMPATIBILITY
83 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
84 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
85 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
86 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
88 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
89 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
90 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
91 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
93 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
94 WX_DECLARE_LIST_XO(elT*, liT, decl)
96 #if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
99 class WXDLLIMPEXP_BASE wxList_SortFunction
102 wxList_SortFunction(wxSortCompareFunction f
) : m_f(f
) { }
103 bool operator()(const T
& i1
, const T
& i2
)
104 { return m_f((T
*)&i1
, (T
*)&i2
) < 0; }
106 wxSortCompareFunction m_f
;
109 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
110 #define VC6_WORKAROUND(elT, liT, decl)
112 #else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
114 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
115 #define VC6_WORKAROUND(elT, liT, decl) \
118 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
119 /* to be passed into std::list::sort() */ \
121 struct std::greater<elT> \
124 wxSortCompareFunction m_CompFunc; \
126 greater( wxSortCompareFunction compfunc = NULL ) \
127 : m_CompFunc( compfunc ) {} \
128 bool operator()(const elT X, const elT Y) const \
130 return m_CompFunc ? \
131 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
132 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
137 // helper for std::greater<elT> above:
139 inline const void *wxListCastElementToVoidPtr(const T
* ptr
) { return ptr
; }
140 inline const void *wxListCastElementToVoidPtr(const wxString
& str
)
141 { return (const char*)str
; }
146 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
147 for mingw 3.2.3 compiler bug that prevents a static function of liT class
148 from being exported into dll. A minimal code snippet reproducing the bug:
150 struct WXDLLEXPORT Foo
153 struct SomeInnerClass
155 friend class Foo; // comment this out to make it link
163 The program does not link under mingw_gcc 3.2.3 producing undefined
164 reference to Foo::Bar() function
167 Note 2: the EmptyList is needed to allow having a NULL pointer-like
168 invalid iterator. We used to use just an uninitialized iterator object
169 instead but this fails with some debug/checked versions of STL, notably the
170 glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate
174 // the real wxList-class declaration
175 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
176 decl _WX_LIST_HELPER_##liT \
178 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
180 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
183 VC6_WORKAROUND(elT, liT, decl) \
184 decl liT : public std::list<elT> \
187 typedef std::list<elT> BaseListType; \
188 static BaseListType EmptyList; \
193 decl compatibility_iterator \
196 /* Workaround for broken VC6 nested class name resolution */ \
197 typedef std::list<elT>::iterator iterator; \
204 compatibility_iterator() \
205 : m_iter(EmptyList.end()), m_list( NULL ) {} \
206 compatibility_iterator( liT* li, iterator i ) \
207 : m_iter( i ), m_list( li ) {} \
208 compatibility_iterator( const liT* li, iterator i ) \
209 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
211 compatibility_iterator* operator->() { return this; } \
212 const compatibility_iterator* operator->() const { return this; } \
214 bool operator==(const compatibility_iterator& i) const \
216 wxASSERT_MSG( m_list && i.m_list, \
217 _T("comparing invalid iterators is illegal") ); \
218 return (m_list == i.m_list) && (m_iter == i.m_iter); \
220 bool operator!=(const compatibility_iterator& i) const \
221 { return !( operator==( i ) ); } \
222 operator bool() const \
223 { return m_list ? m_iter != m_list->end() : false; } \
224 bool operator !() const \
225 { return !( operator bool() ); } \
227 elT GetData() const \
228 { return *m_iter; } \
229 void SetData( elT e ) \
232 compatibility_iterator GetNext() const \
234 iterator i = m_iter; \
235 return compatibility_iterator( m_list, ++i ); \
237 compatibility_iterator GetPrevious() const \
239 if ( m_iter == m_list->begin() ) \
240 return compatibility_iterator(); \
242 iterator i = m_iter; \
243 return compatibility_iterator( m_list, --i ); \
245 int IndexOf() const \
247 return *this ? std::distance( m_list->begin(), m_iter ) \
252 liT() : m_destroy( false ) {} \
254 compatibility_iterator Find( const elT e ) const \
256 liT* _this = const_cast< liT* >( this ); \
257 return compatibility_iterator( _this, \
258 std::find( _this->begin(), _this->end(), e ) ); \
261 bool IsEmpty() const \
262 { return empty(); } \
263 size_t GetCount() const \
266 { return static_cast< int >( GetCount() ); } \
268 compatibility_iterator Item( size_t idx ) const \
270 iterator i = const_cast< liT* >(this)->begin(); \
271 std::advance( i, idx ); \
272 return compatibility_iterator( this, i ); \
274 elT operator[](size_t idx) const \
276 return Item(idx).GetData(); \
279 compatibility_iterator GetFirst() const \
281 return compatibility_iterator( this, \
282 const_cast< liT* >(this)->begin() ); \
284 compatibility_iterator GetLast() const \
286 iterator i = const_cast< liT* >(this)->end(); \
287 return compatibility_iterator( this, !empty() ? --i : i ); \
289 compatibility_iterator Member( elT e ) const \
290 { return Find( e ); } \
291 compatibility_iterator Nth( int n ) const \
292 { return Item( n ); } \
293 int IndexOf( elT e ) const \
294 { return Find( e ).IndexOf(); } \
296 compatibility_iterator Append( elT e ) \
301 compatibility_iterator Insert( elT e ) \
304 return compatibility_iterator( this, begin() ); \
306 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
308 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
310 compatibility_iterator Insert( size_t idx, elT e ) \
312 return compatibility_iterator( this, \
313 insert( Item( idx ).m_iter, e ) ); \
316 void DeleteContents( bool destroy ) \
317 { m_destroy = destroy; } \
318 bool GetDeleteContents() const \
319 { return m_destroy; } \
320 void Erase( const compatibility_iterator& i ) \
323 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
326 bool DeleteNode( const compatibility_iterator& i ) \
335 bool DeleteObject( elT e ) \
337 return DeleteNode( Find( e ) ); \
342 std::for_each( begin(), end(), \
343 _WX_LIST_HELPER_##liT::DeleteFunction ); \
346 /* Workaround for broken VC6 std::list::sort() see above */ \
347 void Sort( wxSortCompareFunction compfunc ) \
348 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
349 ~liT() { Clear(); } \
351 /* It needs access to our EmptyList */ \
352 friend decl compatibility_iterator; \
355 #define WX_DECLARE_LIST(elementtype, listname) \
356 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
357 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
358 WX_DECLARE_LIST(elementtype, listname)
360 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
361 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
362 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
363 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
365 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
366 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
367 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
368 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
370 // this macro must be inserted in your program after
371 // #include "wx/listimpl.cpp"
372 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
374 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
375 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
377 #else // if !wxUSE_STL
380 // undef it to get rid of old, deprecated functions
381 #define wxLIST_COMPATIBILITY
383 // -----------------------------------------------------------------------------
384 // key stuff: a list may be optionally keyed on integer or string key
385 // -----------------------------------------------------------------------------
393 // a struct which may contain both types of keys
395 // implementation note: on one hand, this class allows to have only one function
396 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
397 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
398 // wxList::Find(const char *).
399 class WXDLLIMPEXP_BASE wxListKey
403 wxListKey() : m_keyType(wxKEY_NONE
)
405 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
406 { m_key
.integer
= i
; }
407 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
408 { m_key
.string
= new wxString(s
); }
411 wxKeyType
GetKeyType() const { return m_keyType
; }
412 const wxString
GetString() const
413 { wxASSERT( m_keyType
== wxKEY_STRING
); return *m_key
.string
; }
414 long GetNumber() const
415 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
418 // Note: implementation moved to list.cpp to prevent BC++ inline
419 // expansion warning.
420 bool operator==(wxListKeyValue value
) const ;
425 if ( m_keyType
== wxKEY_STRING
)
431 wxListKeyValue m_key
;
434 // -----------------------------------------------------------------------------
435 // wxNodeBase class is a (base for) node in a double linked list
436 // -----------------------------------------------------------------------------
438 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
440 class WXDLLIMPEXP_BASE wxListBase
;
442 class WXDLLIMPEXP_BASE wxNodeBase
444 friend class wxListBase
;
447 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
448 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
449 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
451 const wxListKey
& key
= wxDefaultListKey
);
453 virtual ~wxNodeBase();
455 // FIXME no check is done that the list is really keyed on strings
456 wxString
GetKeyString() const { return *m_key
.string
; }
457 long GetKeyInteger() const { return m_key
.integer
; }
459 // Necessary for some existing code
460 void SetKeyString(const wxString
& s
) { m_key
.string
= new wxString(s
); }
461 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
463 #ifdef wxLIST_COMPATIBILITY
464 // compatibility methods, use Get* instead.
465 wxDEPRECATED( wxNode
*Next() const );
466 wxDEPRECATED( wxNode
*Previous() const );
467 wxDEPRECATED( wxObject
*Data() const );
468 #endif // wxLIST_COMPATIBILITY
471 // all these are going to be "overloaded" in the derived classes
472 wxNodeBase
*GetNext() const { return m_next
; }
473 wxNodeBase
*GetPrevious() const { return m_previous
; }
475 void *GetData() const { return m_data
; }
476 void SetData(void *data
) { m_data
= data
; }
478 // get 0-based index of this node within the list or wxNOT_FOUND
481 virtual void DeleteData() { }
483 // for wxList::iterator
484 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
486 // optional key stuff
487 wxListKeyValue m_key
;
489 void *m_data
; // user data
490 wxNodeBase
*m_next
, // next and previous nodes in the list
493 wxListBase
*m_list
; // list we belong to
495 DECLARE_NO_COPY_CLASS(wxNodeBase
)
498 // -----------------------------------------------------------------------------
499 // a double-linked list class
500 // -----------------------------------------------------------------------------
502 class WXDLLIMPEXP_BASE wxList
;
504 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
506 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
507 friend class wxHashTableBase
; // should be able to call untyped Find()
510 // default ctor & dtor
511 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
513 virtual ~wxListBase();
516 // count of items in the list
517 size_t GetCount() const { return m_count
; }
519 // return true if this list is empty
520 bool IsEmpty() const { return m_count
== 0; }
527 // instruct it to destroy user data when deleting nodes
528 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
530 // query if to delete
531 bool GetDeleteContents() const
532 { return m_destroy
; }
535 wxKeyType
GetKeyType() const
536 { return m_keyType
; }
538 // set the keytype (required by the serial code)
539 void SetKeyType(wxKeyType keyType
)
540 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
542 #ifdef wxLIST_COMPATIBILITY
543 // compatibility methods from old wxList
544 wxDEPRECATED( int Number() const ); // use GetCount instead.
545 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
546 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
547 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
549 // kludge for typesafe list migration in core classes.
550 wxDEPRECATED( operator wxList
&() const );
551 #endif // wxLIST_COMPATIBILITY
555 // all methods here are "overloaded" in derived classes to provide compile
556 // time type checking
558 // create a node for the list of this type
559 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
561 const wxListKey
& key
= wxDefaultListKey
) = 0;
563 // Can't access these from derived classes otherwise (bug in Salford C++?)
570 wxListBase(size_t count
, void *elements
[]);
571 // from a sequence of objects
572 wxListBase(void *object
, ... /* terminate with NULL */);
575 void Assign(const wxListBase
& list
)
576 { Clear(); DoCopy(list
); }
578 // get list head/tail
579 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
580 wxNodeBase
*GetLast() const { return m_nodeLast
; }
582 // by (0-based) index
583 wxNodeBase
*Item(size_t index
) const;
585 // get the list item's data
586 void *operator[](size_t n
) const
588 wxNodeBase
*node
= Item(n
);
590 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
594 // append to end of list
595 wxNodeBase
*Prepend(void *object
)
596 { return (wxNodeBase
*)wxListBase::Insert(object
); }
597 // append to beginning of list
598 wxNodeBase
*Append(void *object
);
599 // insert a new item at the beginning of the list
600 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
601 // insert a new item at the given position
602 wxNodeBase
*Insert(size_t pos
, void *object
)
603 { return pos
== GetCount() ? Append(object
)
604 : Insert(Item(pos
), object
); }
605 // insert before given node or at front of list if prev == NULL
606 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
609 wxNodeBase
*Append(long key
, void *object
);
610 wxNodeBase
*Append(const wxString
& key
, void *object
);
612 // removes node from the list but doesn't delete it (returns pointer
613 // to the node or NULL if it wasn't found in the list)
614 wxNodeBase
*DetachNode(wxNodeBase
*node
);
615 // delete element from list, returns false if node not found
616 bool DeleteNode(wxNodeBase
*node
);
617 // finds object pointer and deletes node (and object if DeleteContents
618 // is on), returns false if object not found
619 bool DeleteObject(void *object
);
621 // search (all return NULL if item not found)
623 wxNodeBase
*Find(const void *object
) const;
626 wxNodeBase
*Find(const wxListKey
& key
) const;
628 // get 0-based index of object or wxNOT_FOUND
629 int IndexOf( void *object
) const;
631 // this function allows the sorting of arbitrary lists by giving
632 // a function to compare two list elements. The list is sorted in place.
633 void Sort(const wxSortCompareFunction compfunc
);
635 // functions for iterating over the list
636 void *FirstThat(wxListIterateFunction func
);
637 void ForEach(wxListIterateFunction func
);
638 void *LastThat(wxListIterateFunction func
);
640 // for STL interface, "last" points to one after the last node
641 // of the controlled sequence (NULL for the end of the list)
643 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
646 // common part of all ctors
647 void Init(wxKeyType keyType
= wxKEY_NONE
);
650 // common part of copy ctor and assignment operator
651 void DoCopy(const wxListBase
& list
);
652 // common part of all Append()s
653 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
654 // free node's data and node itself
655 void DoDeleteNode(wxNodeBase
*node
);
657 size_t m_count
; // number of elements in the list
658 bool m_destroy
; // destroy user data when deleting list items?
659 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
662 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
665 // -----------------------------------------------------------------------------
666 // macros for definition of "template" list type
667 // -----------------------------------------------------------------------------
669 // and now some heavy magic...
671 // declare a list type named 'name' and containing elements of type 'T *'
672 // (as a by product of macro expansion you also get wx##name##Node
673 // wxNode-derived type)
675 // implementation details:
676 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
677 // for the list of given type - this allows us to pass only the list name
678 // to WX_DEFINE_LIST() even if it needs both the name and the type
680 // 2. We redefine all non-type-safe wxList functions with type-safe versions
681 // which don't take any space (everything is inline), but bring compile
682 // time error checking.
684 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
685 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
686 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
687 // interesting capability to store polymorphic objects in the list and is
688 // particularly useful with, for example, "wxWindow *" list where the
689 // wxWindowBase pointers are put into the list, but wxWindow pointers are
690 // retrieved from it.
692 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
693 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
694 // it results in compiler warnings when this operator doesn't make sense
695 // (i.e. stored elements are not pointers)
697 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
698 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
699 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
701 classexp nodetype : public wxNodeBase \
704 nodetype(wxListBase *list = (wxListBase *)NULL, \
705 nodetype *previous = (nodetype *)NULL, \
706 nodetype *next = (nodetype *)NULL, \
707 T *data = (T *)NULL, \
708 const wxListKey& key = wxDefaultListKey) \
709 : wxNodeBase(list, previous, next, data, key) { } \
711 nodetype *GetNext() const \
712 { return (nodetype *)wxNodeBase::GetNext(); } \
713 nodetype *GetPrevious() const \
714 { return (nodetype *)wxNodeBase::GetPrevious(); } \
717 { return (T *)wxNodeBase::GetData(); } \
718 void SetData(T *data) \
719 { wxNodeBase::SetData(data); } \
722 virtual void DeleteData(); \
724 DECLARE_NO_COPY_CLASS(nodetype) \
727 classexp name : public wxListBase \
730 typedef nodetype Node; \
731 classexp compatibility_iterator \
734 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
736 Node *operator->() const { return m_ptr; } \
737 operator Node *() const { return m_ptr; } \
743 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
745 name(const name& list) : wxListBase(list.GetKeyType()) \
747 name(size_t count, T *elements[]) \
748 : wxListBase(count, (void **)elements) { } \
750 name& operator=(const name& list) \
751 { Assign(list); return *this; } \
753 nodetype *GetFirst() const \
754 { return (nodetype *)wxListBase::GetFirst(); } \
755 nodetype *GetLast() const \
756 { return (nodetype *)wxListBase::GetLast(); } \
758 nodetype *Item(size_t index) const \
759 { return (nodetype *)wxListBase::Item(index); } \
761 T *operator[](size_t index) const \
763 nodetype *node = Item(index); \
764 return node ? (T*)(node->GetData()) : (T*)NULL; \
767 nodetype *Append(Tbase *object) \
768 { return (nodetype *)wxListBase::Append(object); } \
769 nodetype *Insert(Tbase *object) \
770 { return (nodetype *)Insert((nodetype*)NULL, object); } \
771 nodetype *Insert(size_t pos, Tbase *object) \
772 { return (nodetype *)wxListBase::Insert(pos, object); } \
773 nodetype *Insert(nodetype *prev, Tbase *object) \
774 { return (nodetype *)wxListBase::Insert(prev, object); } \
776 nodetype *Append(long key, void *object) \
777 { return (nodetype *)wxListBase::Append(key, object); } \
778 nodetype *Append(const wxChar *key, void *object) \
779 { return (nodetype *)wxListBase::Append(key, object); } \
781 nodetype *DetachNode(nodetype *node) \
782 { return (nodetype *)wxListBase::DetachNode(node); } \
783 bool DeleteNode(nodetype *node) \
784 { return wxListBase::DeleteNode(node); } \
785 bool DeleteObject(Tbase *object) \
786 { return wxListBase::DeleteObject(object); } \
787 void Erase(nodetype *it) \
788 { DeleteNode(it); } \
790 nodetype *Find(const Tbase *object) const \
791 { return (nodetype *)wxListBase::Find(object); } \
793 virtual nodetype *Find(const wxListKey& key) const \
794 { return (nodetype *)wxListBase::Find(key); } \
796 int IndexOf(Tbase *object) const \
797 { return wxListBase::IndexOf(object); } \
799 void Sort(wxSortCompareFunction func) \
800 { wxListBase::Sort(func); } \
801 void Sort(wxSortFuncFor_##name func) \
802 { Sort((wxSortCompareFunction)func); } \
805 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
807 const wxListKey& key = wxDefaultListKey) \
809 return new nodetype(this, \
810 (nodetype *)prev, (nodetype *)next, \
813 /* STL interface */ \
815 typedef size_t size_type; \
816 typedef int difference_type; \
817 typedef T* value_type; \
818 typedef Tbase* base_value_type; \
819 typedef value_type& reference; \
820 typedef const value_type& const_reference; \
821 typedef base_value_type& base_reference; \
822 typedef const base_value_type& const_base_reference; \
828 typedef nodetype Node; \
829 typedef iterator itor; \
830 typedef T* value_type; \
831 typedef value_type* ptr_type; \
832 typedef value_type& reference; \
837 typedef reference reference_type; \
838 typedef ptr_type pointer_type; \
840 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
841 iterator() : m_node(NULL), m_init(NULL) { } \
842 reference_type operator*() const \
843 { return *(pointer_type)m_node->GetDataPtr(); } \
845 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
846 const itor operator++(int) \
847 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
850 m_node = m_node ? m_node->GetPrevious() : m_init; \
853 const itor operator--(int) \
856 m_node = m_node ? m_node->GetPrevious() : m_init; \
859 bool operator!=(const itor& it) const \
860 { return it.m_node != m_node; } \
861 bool operator==(const itor& it) const \
862 { return it.m_node == m_node; } \
864 classexp const_iterator \
868 typedef nodetype Node; \
869 typedef T* value_type; \
870 typedef const value_type& const_reference; \
871 typedef const_iterator itor; \
872 typedef value_type* ptr_type; \
877 typedef const_reference reference_type; \
878 typedef const ptr_type pointer_type; \
880 const_iterator(Node* node, Node* init) \
881 : m_node(node), m_init(init) { } \
882 const_iterator() : m_node(NULL), m_init(NULL) { } \
883 const_iterator(const iterator& it) \
884 : m_node(it.m_node), m_init(it.m_init) { } \
885 reference_type operator*() const \
886 { return *(pointer_type)m_node->GetDataPtr(); } \
888 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
889 const itor operator++(int) \
890 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
893 m_node = m_node ? m_node->GetPrevious() : m_init; \
896 const itor operator--(int) \
899 m_node = m_node ? m_node->GetPrevious() : m_init; \
902 bool operator!=(const itor& it) const \
903 { return it.m_node != m_node; } \
904 bool operator==(const itor& it) const \
905 { return it.m_node == m_node; } \
907 classexp reverse_iterator \
911 typedef nodetype Node; \
912 typedef T* value_type; \
913 typedef reverse_iterator itor; \
914 typedef value_type* ptr_type; \
915 typedef value_type& reference; \
920 typedef reference reference_type; \
921 typedef ptr_type pointer_type; \
923 reverse_iterator(Node* node, Node* init) \
924 : m_node(node), m_init(init) { } \
925 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
926 reference_type operator*() const \
927 { return *(pointer_type)m_node->GetDataPtr(); } \
930 { m_node = m_node->GetPrevious(); return *this; } \
931 const itor operator++(int) \
932 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
934 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
935 const itor operator--(int) \
938 m_node = m_node ? m_node->GetNext() : m_init; \
941 bool operator!=(const itor& it) const \
942 { return it.m_node != m_node; } \
943 bool operator==(const itor& it) const \
944 { return it.m_node == m_node; } \
946 classexp const_reverse_iterator \
950 typedef nodetype Node; \
951 typedef T* value_type; \
952 typedef const_reverse_iterator itor; \
953 typedef value_type* ptr_type; \
954 typedef const value_type& const_reference; \
959 typedef const_reference reference_type; \
960 typedef const ptr_type pointer_type; \
962 const_reverse_iterator(Node* node, Node* init) \
963 : m_node(node), m_init(init) { } \
964 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
965 const_reverse_iterator(const reverse_iterator& it) \
966 : m_node(it.m_node), m_init(it.m_init) { } \
967 reference_type operator*() const \
968 { return *(pointer_type)m_node->GetDataPtr(); } \
971 { m_node = m_node->GetPrevious(); return *this; } \
972 const itor operator++(int) \
973 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
975 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
976 const itor operator--(int) \
979 m_node = m_node ? m_node->GetNext() : m_init; \
982 bool operator!=(const itor& it) const \
983 { return it.m_node != m_node; } \
984 bool operator==(const itor& it) const \
985 { return it.m_node == m_node; } \
988 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
990 name(const const_iterator& first, const const_iterator& last) \
991 { assign(first, last); } \
992 iterator begin() { return iterator(GetFirst(), GetLast()); } \
993 const_iterator begin() const \
994 { return const_iterator(GetFirst(), GetLast()); } \
995 iterator end() { return iterator(NULL, GetLast()); } \
996 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
997 reverse_iterator rbegin() \
998 { return reverse_iterator(GetLast(), GetFirst()); } \
999 const_reverse_iterator rbegin() const \
1000 { return const_reverse_iterator(GetLast(), GetFirst()); } \
1001 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
1002 const_reverse_iterator rend() const \
1003 { return const_reverse_iterator(NULL, GetFirst()); } \
1004 void resize(size_type n, value_type v = value_type()) \
1006 while (n < size()) \
1008 while (n > size()) \
1011 size_type size() const { return GetCount(); } \
1012 size_type max_size() const { return INT_MAX; } \
1013 bool empty() const { return IsEmpty(); } \
1014 reference front() { return *begin(); } \
1015 const_reference front() const { return *begin(); } \
1016 reference back() { iterator tmp = end(); return *--tmp; } \
1017 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1018 void push_front(const_reference v = value_type()) \
1019 { Insert(GetFirst(), (const_base_reference)v); } \
1020 void pop_front() { DeleteNode(GetFirst()); } \
1021 void push_back(const_reference v = value_type()) \
1022 { Append((const_base_reference)v); } \
1023 void pop_back() { DeleteNode(GetLast()); } \
1024 void assign(const_iterator first, const const_iterator& last) \
1027 for(; first != last; ++first) \
1028 Append((const_base_reference)*first); \
1030 void assign(size_type n, const_reference v = value_type()) \
1033 for(size_type i = 0; i < n; ++i) \
1034 Append((const_base_reference)v); \
1036 iterator insert(const iterator& it, const_reference v = value_type())\
1038 Insert(it.m_node, (const_base_reference)v); \
1039 return iterator(it.m_node->GetPrevious(), GetLast()); \
1041 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1043 for(size_type i = 0; i < n; ++i) \
1044 Insert(it.m_node, (const_base_reference)v); \
1046 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1048 for(; first != last; ++first) \
1049 Insert(it.m_node, (const_base_reference)*first); \
1051 iterator erase(const iterator& it) \
1053 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1054 DeleteNode(it.m_node); return next; \
1056 iterator erase(const iterator& first, const iterator& last) \
1058 iterator next = last; ++next; \
1059 DeleteNodes(first.m_node, last.m_node); \
1062 void clear() { Clear(); } \
1063 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1064 { insert(it, first, last); l.erase(first, last); } \
1065 void splice(const iterator& it, name& l) \
1066 { splice(it, l, l.begin(), l.end() ); } \
1067 void splice(const iterator& it, name& l, const iterator& first) \
1069 iterator tmp = first; ++tmp; \
1070 if(it == first || it == tmp) return; \
1071 insert(it, *first); \
1074 void remove(const_reference v) \
1075 { DeleteObject((const_base_reference)v); } \
1078 /* void swap(name& l) \
1080 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1081 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1082 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1083 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1084 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1088 #define WX_LIST_PTROP \
1089 pointer_type operator->() const \
1090 { return (pointer_type)m_node->GetDataPtr(); }
1091 #define WX_LIST_PTROP_NONE
1093 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1094 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1095 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1096 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1098 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1099 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1100 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1101 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1103 #define WX_DECLARE_LIST(elementtype, listname) \
1104 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1105 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1106 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1107 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1108 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1110 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1111 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1112 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1114 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1115 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1117 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1118 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1119 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1121 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1122 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1123 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1124 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1125 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1126 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1128 // this macro must be inserted in your program after
1129 // #include "wx/listimpl.cpp"
1130 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1132 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1133 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1135 #endif // !wxUSE_STL
1137 // ============================================================================
1138 // now we can define classes 100% compatible with the old ones
1139 // ============================================================================
1141 // ----------------------------------------------------------------------------
1142 // commonly used list classes
1143 // ----------------------------------------------------------------------------
1145 #if defined(wxLIST_COMPATIBILITY)
1147 // inline compatibility functions
1151 // ----------------------------------------------------------------------------
1152 // wxNodeBase deprecated methods
1153 // ----------------------------------------------------------------------------
1155 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1156 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1157 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1159 // ----------------------------------------------------------------------------
1160 // wxListBase deprecated methods
1161 // ----------------------------------------------------------------------------
1163 inline int wxListBase::Number() const { return (int)GetCount(); }
1164 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1165 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1166 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1167 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1171 // define this to make a lot of noise about use of the old wxList classes.
1172 //#define wxWARN_COMPAT_LIST_USE
1174 // ----------------------------------------------------------------------------
1175 // wxList compatibility class: in fact, it's a list of wxObjects
1176 // ----------------------------------------------------------------------------
1178 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1179 class WXDLLIMPEXP_BASE
);
1181 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1184 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1186 wxDEPRECATED( wxList(int key_type
) );
1188 wxList(int key_type
= wxKEY_NONE
);
1191 // this destructor is required for Darwin
1195 wxList
& operator=(const wxList
& list
)
1196 { (void) wxListBase::operator=(list
); return *this; }
1198 // compatibility methods
1199 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1204 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1209 DECLARE_DYNAMIC_CLASS(wxList
)
1215 // -----------------------------------------------------------------------------
1216 // wxStringList class for compatibility with the old code
1217 // -----------------------------------------------------------------------------
1218 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1220 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1225 #ifdef wxWARN_COMPAT_LIST_USE
1227 wxDEPRECATED( wxStringList(const wxChar
*first
...) ); // FIXME-UTF8
1230 wxStringList(const wxChar
*first
...); // FIXME-UTF8
1233 // copying the string list: the strings are copied, too (extremely
1235 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1236 wxStringList
& operator=(const wxStringList
& other
)
1237 { Clear(); DoCopy(other
); return *this; }
1240 // makes a copy of the string
1241 wxNode
*Add(const wxChar
*s
);
1243 // Append to beginning of list
1244 wxNode
*Prepend(const wxChar
*s
);
1246 bool Delete(const wxChar
*s
);
1248 wxChar
**ListToArray(bool new_copies
= false) const;
1249 bool Member(const wxChar
*s
) const;
1255 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1257 DECLARE_DYNAMIC_CLASS(wxStringList
)
1260 #else // if wxUSE_STL
1262 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1264 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1267 compatibility_iterator
Append(wxChar
* s
)
1268 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1269 compatibility_iterator
Insert(wxChar
* s
)
1270 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1271 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1275 return wxStringListBase::Insert(pos
, tmp
);
1277 compatibility_iterator
Add(const wxChar
* s
)
1278 { push_back(s
); return GetLast(); }
1279 compatibility_iterator
Prepend(const wxChar
* s
)
1280 { push_front(s
); return GetFirst(); }
1285 #endif // wxLIST_COMPATIBILITY
1287 // delete all list elements
1289 // NB: the class declaration of the list elements must be visible from the
1290 // place where you use this macro, otherwise the proper destructor may not
1291 // be called (a decent compiler should give a warning about it, but don't
1293 #define WX_CLEAR_LIST(type, list) \
1295 type::iterator it, en; \
1296 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1301 #endif // _WX_LISTH__