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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) && \
29 !(defined(__MINGW32__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
30 #pragma interface "list.h"
33 // -----------------------------------------------------------------------------
35 // -----------------------------------------------------------------------------
38 #include "wx/object.h"
39 #include "wx/string.h"
42 #include "wx/beforestd.h"
46 #include "wx/afterstd.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 // type of compare function for list sort operation (as in 'qsort'): it should
54 // return a negative value, 0 or positive value if the first element is less
55 // than, equal or greater than the second
59 typedef int (* LINKAGEMODE wxSortCompareFunction
)(const void *elem1
, const void *elem2
);
62 class WXDLLIMPEXP_BASE wxObjectListNode
;
63 typedef wxObjectListNode wxNode
;
66 typedef int (* LINKAGEMODE wxListIterateFunction
)(void *current
);
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 #if !defined(wxENUM_KEY_TYPE_DEFINED)
73 #define wxENUM_KEY_TYPE_DEFINED
86 #define wxLIST_COMPATIBILITY
88 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
89 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
90 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
91 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
93 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
94 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
95 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
96 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
98 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
99 WX_DECLARE_LIST_XO(elT*, liT, decl)
101 #if !defined( __VISUALC__ )
104 class WXDLLIMPEXP_BASE wxList_SortFunction
107 wxList_SortFunction(wxSortCompareFunction f
) : m_f(f
) { }
108 bool operator()(const T
& i1
, const T
& i2
)
109 { return m_f((T
*)&i1
, (T
*)&i2
) < 0; }
111 wxSortCompareFunction m_f
;
114 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
115 #define VC6_WORKAROUND(elT, liT, decl)
117 #else // if defined( __VISUALC__ )
119 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
120 #define VC6_WORKAROUND(elT, liT, decl) \
123 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
124 /* to be passed into std::list::sort() */ \
126 struct std::greater<elT> \
129 wxSortCompareFunction m_CompFunc; \
131 greater( wxSortCompareFunction compfunc = NULL ) \
132 : m_CompFunc( compfunc ) {} \
133 bool operator()(const elT X, const elT Y) const \
135 return m_CompFunc ? \
136 ( m_CompFunc( X, Y ) < 0 ) : \
141 #endif // defined( __VISUALC__ )
143 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
144 VC6_WORKAROUND(elT, liT, decl) \
145 decl liT : public std::list<elT> \
150 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
151 static void DeleteFunction( const _WX_LIST_ITEM_TYPE_##liT X ); \
153 class compatibility_iterator \
156 /* Workaround for broken VC6 nested class name resolution */ \
157 typedef std::list<elT>::iterator iterator; \
163 compatibility_iterator() \
164 : m_iter(), m_list( NULL ) {} \
165 compatibility_iterator( liT* li, iterator i ) \
166 : m_iter( i ), m_list( li ) {} \
167 compatibility_iterator( const liT* li, iterator i ) \
168 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
170 compatibility_iterator* operator->() { return this; } \
171 const compatibility_iterator* operator->() const { return this; } \
173 bool operator==(const compatibility_iterator& i) \
174 { return (m_list == i.m_list) && (m_iter == i.m_iter); } \
175 bool operator!=(const compatibility_iterator& i) \
176 { return !( operator==( i ) ); } \
177 operator bool() const \
178 { return m_list ? m_iter != m_list->end() : false; } \
179 bool operator !() const \
180 { return !( operator bool() ); } \
182 elT GetData() const \
183 { return *m_iter; } \
184 void SetData( elT e ) \
187 compatibility_iterator GetNext() const \
189 iterator i = m_iter; \
190 return compatibility_iterator( m_list, ++i ); \
192 compatibility_iterator GetPrevious() const \
194 iterator i = m_iter; \
195 return compatibility_iterator( m_list, --i ); \
197 int IndexOf() const \
200 m_iter != m_list->end() ? \
201 std::distance( m_list->begin(), m_iter ) : \
207 liT() : m_destroy( false ) {} \
209 compatibility_iterator Find( const elT e ) const \
211 liT* _this = const_cast< liT* >( this ); \
212 return compatibility_iterator( _this, \
213 std::find( _this->begin(), _this->end(), e ) ); \
216 bool IsEmpty() const \
217 { return empty(); } \
218 size_t GetCount() const \
221 { return static_cast< int >( GetCount() ); } \
223 compatibility_iterator Item( size_t idx ) const \
225 iterator i = const_cast< liT* >(this)->begin(); \
226 std::advance( i, idx ); \
227 return compatibility_iterator( this, i ); \
229 compatibility_iterator GetFirst() const \
231 return compatibility_iterator( this, \
232 const_cast< liT* >(this)->begin() ); \
234 compatibility_iterator GetLast() const \
236 iterator i = const_cast< liT* >(this)->end(); \
237 return compatibility_iterator( this, !empty() ? --i : i ); \
239 compatibility_iterator Member( elT e ) const \
240 { return Find( e ); } \
241 compatibility_iterator Nth( int n ) const \
242 { return Item( n ); } \
243 int IndexOf( elT e ) const \
244 { return Find( e ).IndexOf(); } \
246 compatibility_iterator Append( elT e ) \
251 compatibility_iterator Insert( elT e ) \
254 return compatibility_iterator( this, begin() ); \
256 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
258 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
260 compatibility_iterator Insert( size_t idx, elT e ) \
262 return compatibility_iterator( this, \
263 insert( Item( idx ).m_iter, e ) ); \
266 void DeleteContents( bool destroy ) \
267 { m_destroy = destroy; } \
268 bool GetDeleteContents() const \
269 { return m_destroy; } \
270 void Erase( const compatibility_iterator& i ) \
273 DeleteFunction( i->GetData() ); \
276 bool DeleteNode( const compatibility_iterator& i ) \
285 bool DeleteObject( elT e ) \
287 return DeleteNode( Find( e ) ); \
292 std::for_each( begin(), end(), DeleteFunction ); \
295 /* Workaround for broken VC6 std::list::sort() see above */ \
296 void Sort( wxSortCompareFunction compfunc ) \
297 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
298 ~liT() { Clear(); } \
301 #define WX_DECLARE_LIST(elementtype, listname) \
302 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
303 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
304 WX_DECLARE_LIST(elementtype, listname)
306 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
307 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
308 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
309 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
311 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
312 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
313 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
314 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
316 // this macro must be inserted in your program after
317 // #include <wx/listimpl.cpp>
318 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
320 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
321 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
323 #else // if !wxUSE_STL
325 // due to circular header dependencies this function has to be declared here
326 // (normally it's found in utils.h which includes itself list.h...)
327 #if WXWIN_COMPATIBILITY_2_4
328 extern WXDLLIMPEXP_BASE wxChar
* copystring(const wxChar
*s
);
331 class WXDLLEXPORT wxObjectListNode
;
332 typedef wxObjectListNode wxNode
;
334 // undef it to get rid of old, deprecated functions
335 #define wxLIST_COMPATIBILITY
337 // -----------------------------------------------------------------------------
338 // key stuff: a list may be optionally keyed on integer or string key
339 // -----------------------------------------------------------------------------
347 // a struct which may contain both types of keys
349 // implementation note: on one hand, this class allows to have only one function
350 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
351 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
352 // wxList::Find(const char *).
353 class WXDLLIMPEXP_BASE wxListKey
357 wxListKey() : m_keyType(wxKEY_NONE
)
359 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
360 { m_key
.integer
= i
; }
361 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
362 { m_key
.string
= wxStrdup(s
); }
363 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
364 { m_key
.string
= wxStrdup(s
.c_str()); }
367 wxKeyType
GetKeyType() const { return m_keyType
; }
368 const wxChar
*GetString() const
369 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
370 long GetNumber() const
371 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
374 // Note: implementation moved to list.cpp to prevent BC++ inline
375 // expansion warning.
376 bool operator==(wxListKeyValue value
) const ;
381 if ( m_keyType
== wxKEY_STRING
)
387 wxListKeyValue m_key
;
390 // -----------------------------------------------------------------------------
391 // wxNodeBase class is a (base for) node in a double linked list
392 // -----------------------------------------------------------------------------
394 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
396 class WXDLLIMPEXP_BASE wxListBase
;
398 class WXDLLIMPEXP_BASE wxNodeBase
400 friend class wxListBase
;
403 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
404 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
405 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
407 const wxListKey
& key
= wxDefaultListKey
);
409 virtual ~wxNodeBase();
411 // FIXME no check is done that the list is really keyed on strings
412 const wxChar
*GetKeyString() const { return m_key
.string
; }
413 long GetKeyInteger() const { return m_key
.integer
; }
415 // Necessary for some existing code
416 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
417 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
419 #ifdef wxLIST_COMPATIBILITY
420 // compatibility methods, use Get* instead.
421 wxDEPRECATED( wxNode
*Next() const );
422 wxDEPRECATED( wxNode
*Previous() const );
423 wxDEPRECATED( wxObject
*Data() const );
424 #endif // wxLIST_COMPATIBILITY
427 // all these are going to be "overloaded" in the derived classes
428 wxNodeBase
*GetNext() const { return m_next
; }
429 wxNodeBase
*GetPrevious() const { return m_previous
; }
431 void *GetData() const { return m_data
; }
432 void SetData(void *data
) { m_data
= data
; }
434 // get 0-based index of this node within the list or wxNOT_FOUND
437 virtual void DeleteData() { }
439 // for wxList::iterator
440 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
442 // optional key stuff
443 wxListKeyValue m_key
;
445 void *m_data
; // user data
446 wxNodeBase
*m_next
, // next and previous nodes in the list
449 wxListBase
*m_list
; // list we belong to
451 DECLARE_NO_COPY_CLASS(wxNodeBase
)
454 // -----------------------------------------------------------------------------
455 // a double-linked list class
456 // -----------------------------------------------------------------------------
458 class WXDLLIMPEXP_BASE wxList
;
460 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
462 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
463 friend class wxHashTableBase
; // should be able to call untyped Find()
465 // common part of all ctors
466 void Init(wxKeyType keyType
= wxKEY_NONE
); // Must be declared before it's used (for VC++ 1.5)
468 // default ctor & dtor
469 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
471 virtual ~wxListBase();
474 // count of items in the list
475 size_t GetCount() const { return m_count
; }
477 // return true if this list is empty
478 bool IsEmpty() const { return m_count
== 0; }
485 // instruct it to destroy user data when deleting nodes
486 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
488 // query if to delete
489 bool GetDeleteContents() const
490 { return m_destroy
; }
493 wxKeyType
GetKeyType() const
494 { return m_keyType
; }
496 // set the keytype (required by the serial code)
497 void SetKeyType(wxKeyType keyType
)
498 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
500 #ifdef wxLIST_COMPATIBILITY
501 // compatibility methods from old wxList
502 wxDEPRECATED( int Number() const ); // use GetCount instead.
503 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
504 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
505 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
507 // kludge for typesafe list migration in core classes.
508 wxDEPRECATED( operator wxList
&() const );
509 #endif // wxLIST_COMPATIBILITY
513 // all methods here are "overloaded" in derived classes to provide compile
514 // time type checking
516 // create a node for the list of this type
517 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
519 const wxListKey
& key
= wxDefaultListKey
) = 0;
521 // Can't access these from derived classes otherwise (bug in Salford C++?)
528 wxListBase(size_t count
, void *elements
[]);
529 // from a sequence of objects
530 wxListBase(void *object
, ... /* terminate with NULL */);
533 void Assign(const wxListBase
& list
)
534 { Clear(); DoCopy(list
); }
536 // get list head/tail
537 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
538 wxNodeBase
*GetLast() const { return m_nodeLast
; }
540 // by (0-based) index
541 wxNodeBase
*Item(size_t index
) const;
543 // get the list item's data
544 void *operator[](size_t n
) const
546 wxNodeBase
*node
= Item(n
);
548 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
552 // append to end of list
553 wxNodeBase
*Prepend(void *object
)
554 { return (wxNodeBase
*)wxListBase::Insert(object
); }
555 // append to beginning of list
556 wxNodeBase
*Append(void *object
);
557 // insert a new item at the beginning of the list
558 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
559 // insert a new item at the given position
560 wxNodeBase
*Insert(size_t pos
, void *object
)
561 { return pos
== GetCount() ? Append(object
)
562 : Insert(Item(pos
), object
); }
563 // insert before given node or at front of list if prev == NULL
564 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
567 wxNodeBase
*Append(long key
, void *object
);
568 wxNodeBase
*Append(const wxChar
*key
, void *object
);
570 // removes node from the list but doesn't delete it (returns pointer
571 // to the node or NULL if it wasn't found in the list)
572 wxNodeBase
*DetachNode(wxNodeBase
*node
);
573 // delete element from list, returns false if node not found
574 bool DeleteNode(wxNodeBase
*node
);
575 // finds object pointer and deletes node (and object if DeleteContents
576 // is on), returns false if object not found
577 bool DeleteObject(void *object
);
579 // search (all return NULL if item not found)
581 wxNodeBase
*Find(const void *object
) const;
584 wxNodeBase
*Find(const wxListKey
& key
) const;
586 // get 0-based index of object or wxNOT_FOUND
587 int IndexOf( void *object
) const;
589 // this function allows the sorting of arbitrary lists by giving
590 // a function to compare two list elements. The list is sorted in place.
591 void Sort(const wxSortCompareFunction compfunc
);
593 // functions for iterating over the list
594 void *FirstThat(wxListIterateFunction func
);
595 void ForEach(wxListIterateFunction func
);
596 void *LastThat(wxListIterateFunction func
);
598 // for STL interface, "last" points to one after the last node
599 // of the controlled sequence (NULL for the end of the list)
601 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
604 // common part of copy ctor and assignment operator
605 void DoCopy(const wxListBase
& list
);
606 // common part of all Append()s
607 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
608 // free node's data and node itself
609 void DoDeleteNode(wxNodeBase
*node
);
611 size_t m_count
; // number of elements in the list
612 bool m_destroy
; // destroy user data when deleting list items?
613 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
616 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
619 // -----------------------------------------------------------------------------
620 // macros for definition of "template" list type
621 // -----------------------------------------------------------------------------
623 // and now some heavy magic...
625 // declare a list type named 'name' and containing elements of type 'T *'
626 // (as a by product of macro expansion you also get wx##name##Node
627 // wxNode-derived type)
629 // implementation details:
630 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
631 // for the list of given type - this allows us to pass only the list name
632 // to WX_DEFINE_LIST() even if it needs both the name and the type
634 // 2. We redefine all non-type-safe wxList functions with type-safe versions
635 // which don't take any space (everything is inline), but bring compile
636 // time error checking.
638 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
639 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
640 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
641 // interesting capability to store polymorphic objects in the list and is
642 // particularly useful with, for example, "wxWindow *" list where the
643 // wxWindowBase pointers are put into the list, but wxWindow pointers are
644 // retrieved from it.
646 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
647 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
648 // it results in compiler warnings when this operator doesn't make sense
649 // (i.e. stored elements are not pointers)
651 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
652 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
653 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
655 classexp nodetype : public wxNodeBase \
658 nodetype(wxListBase *list = (wxListBase *)NULL, \
659 nodetype *previous = (nodetype *)NULL, \
660 nodetype *next = (nodetype *)NULL, \
661 T *data = (T *)NULL, \
662 const wxListKey& key = wxDefaultListKey) \
663 : wxNodeBase(list, previous, next, data, key) { } \
665 nodetype *GetNext() const \
666 { return (nodetype *)wxNodeBase::GetNext(); } \
667 nodetype *GetPrevious() const \
668 { return (nodetype *)wxNodeBase::GetPrevious(); } \
671 { return (T *)wxNodeBase::GetData(); } \
672 void SetData(T *data) \
673 { wxNodeBase::SetData(data); } \
675 virtual void DeleteData(); \
677 DECLARE_NO_COPY_CLASS(nodetype) \
680 classexp name : public wxListBase \
683 typedef nodetype Node; \
684 typedef Node* compatibility_iterator; \
686 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
688 name(const name& list) : wxListBase(list.GetKeyType()) \
690 name(size_t count, T *elements[]) \
691 : wxListBase(count, (void **)elements) { } \
693 name& operator=(const name& list) \
694 { Assign(list); return *this; } \
696 nodetype *GetFirst() const \
697 { return (nodetype *)wxListBase::GetFirst(); } \
698 nodetype *GetLast() const \
699 { return (nodetype *)wxListBase::GetLast(); } \
701 nodetype *Item(size_t index) const \
702 { return (nodetype *)wxListBase::Item(index); } \
704 T *operator[](size_t index) const \
706 nodetype *node = Item(index); \
707 return node ? (T*)(node->GetData()) : (T*)NULL; \
710 nodetype *Append(Tbase *object) \
711 { return (nodetype *)wxListBase::Append(object); } \
712 nodetype *Insert(Tbase *object) \
713 { return (nodetype *)Insert((nodetype*)NULL, object); } \
714 nodetype *Insert(size_t pos, Tbase *object) \
715 { return (nodetype *)wxListBase::Insert(pos, object); } \
716 nodetype *Insert(nodetype *prev, Tbase *object) \
717 { return (nodetype *)wxListBase::Insert(prev, object); } \
719 nodetype *Append(long key, void *object) \
720 { return (nodetype *)wxListBase::Append(key, object); } \
721 nodetype *Append(const wxChar *key, void *object) \
722 { return (nodetype *)wxListBase::Append(key, object); } \
724 nodetype *DetachNode(nodetype *node) \
725 { return (nodetype *)wxListBase::DetachNode(node); } \
726 bool DeleteNode(nodetype *node) \
727 { return wxListBase::DeleteNode(node); } \
728 bool DeleteObject(Tbase *object) \
729 { return wxListBase::DeleteObject(object); } \
730 void Erase(compatibility_iterator it) \
731 { DeleteNode(it); } \
733 nodetype *Find(const Tbase *object) const \
734 { return (nodetype *)wxListBase::Find(object); } \
736 virtual nodetype *Find(const wxListKey& key) const \
737 { return (nodetype *)wxListBase::Find(key); } \
739 int IndexOf(Tbase *object) const \
740 { return wxListBase::IndexOf(object); } \
742 void Sort(wxSortCompareFunction func) \
743 { wxListBase::Sort(func); } \
744 void Sort(wxSortFuncFor_##name func) \
745 { Sort((wxSortCompareFunction)func); } \
748 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
750 const wxListKey& key = wxDefaultListKey) \
752 return new nodetype(this, \
753 (nodetype *)prev, (nodetype *)next, \
756 /* STL interface */ \
758 typedef size_t size_type; \
759 typedef int difference_type; \
760 typedef T* value_type; \
761 typedef Tbase* base_value_type; \
762 typedef value_type& reference; \
763 typedef const value_type& const_reference; \
764 typedef base_value_type& base_reference; \
765 typedef const base_value_type& const_base_reference; \
771 typedef nodetype Node; \
772 typedef iterator itor; \
773 typedef T* value_type; \
774 typedef value_type* ptr_type; \
775 typedef value_type& reference; \
780 typedef reference reference_type; \
781 typedef ptr_type pointer_type; \
783 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
784 iterator() : m_node(NULL), m_init(NULL) { } \
785 reference_type operator*() const \
786 { return *(pointer_type)m_node->GetDataPtr(); } \
788 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
789 itor operator++(int) \
790 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
793 m_node = m_node ? m_node->GetPrevious() : m_init; \
796 itor operator--(int) \
799 m_node = m_node ? m_node->GetPrevious() : m_init; \
802 bool operator!=(const itor& it) const \
803 { return it.m_node != m_node; } \
804 bool operator==(const itor& it) const \
805 { return it.m_node == m_node; } \
807 class const_iterator \
811 typedef nodetype Node; \
812 typedef T* value_type; \
813 typedef const value_type& const_reference; \
814 typedef const_iterator itor; \
815 typedef value_type* ptr_type; \
820 typedef const_reference reference_type; \
821 typedef const ptr_type pointer_type; \
823 const_iterator(Node* node, Node* init) \
824 : m_node(node), m_init(init) { } \
825 const_iterator() : m_node(NULL), m_init(NULL) { } \
826 const_iterator(const iterator& it) \
827 : m_node(it.m_node), m_init(it.m_init) { } \
828 reference_type operator*() const \
829 { return *(pointer_type)m_node->GetDataPtr(); } \
831 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
832 itor operator++(int) \
833 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
836 m_node = m_node ? m_node->GetPrevious() : m_init; \
839 itor operator--(int) \
842 m_node = m_node ? m_node->GetPrevious() : m_init; \
845 bool operator!=(const itor& it) const \
846 { return it.m_node != m_node; } \
847 bool operator==(const itor& it) const \
848 { return it.m_node == m_node; } \
850 class reverse_iterator \
854 typedef nodetype Node; \
855 typedef T* value_type; \
856 typedef reverse_iterator itor; \
857 typedef value_type* ptr_type; \
858 typedef value_type& reference; \
863 typedef reference reference_type; \
864 typedef ptr_type pointer_type; \
866 reverse_iterator(Node* node, Node* init) \
867 : m_node(node), m_init(init) { } \
868 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
869 reference_type operator*() const \
870 { return *(pointer_type)m_node->GetDataPtr(); } \
873 { m_node = m_node->GetPrevious(); return *this; } \
874 itor operator++(int) \
875 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
877 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
878 itor operator--(int) \
881 m_node = m_node ? m_node->GetNext() : m_init; \
884 bool operator!=(const itor& it) const \
885 { return it.m_node != m_node; } \
886 bool operator==(const itor& it) const \
887 { return it.m_node == m_node; } \
889 class const_reverse_iterator \
893 typedef nodetype Node; \
894 typedef T* value_type; \
895 typedef const_reverse_iterator itor; \
896 typedef value_type* ptr_type; \
897 typedef const value_type& const_reference; \
902 typedef const_reference reference_type; \
903 typedef const ptr_type pointer_type; \
905 const_reverse_iterator(Node* node, Node* init) \
906 : m_node(node), m_init(init) { } \
907 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
908 const_reverse_iterator(const reverse_iterator& it) \
909 : m_node(it.m_node), m_init(it.m_init) { } \
910 reference_type operator*() const \
911 { return *(pointer_type)m_node->GetDataPtr(); } \
914 { m_node = m_node->GetPrevious(); return *this; } \
915 itor operator++(int) \
916 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
918 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
919 itor operator--(int) \
922 m_node = m_node ? m_node->GetNext() : m_init; \
925 bool operator!=(const itor& it) const \
926 { return it.m_node != m_node; } \
927 bool operator==(const itor& it) const \
928 { return it.m_node == m_node; } \
931 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
933 name(const_iterator first, const_iterator last) \
934 { assign(first, last); } \
935 iterator begin() { return iterator(GetFirst(), GetLast()); } \
936 const_iterator begin() const \
937 { return const_iterator(GetFirst(), GetLast()); } \
938 iterator end() { return iterator(NULL, GetLast()); } \
939 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
940 reverse_iterator rbegin() \
941 { return reverse_iterator(GetLast(), GetFirst()); } \
942 const_reverse_iterator rbegin() const \
943 { return const_reverse_iterator(GetLast(), GetFirst()); } \
944 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
945 const_reverse_iterator rend() const \
946 { return const_reverse_iterator(NULL, GetFirst()); } \
947 void resize(size_type n, value_type v = value_type()) \
954 size_type size() const { return GetCount(); } \
955 size_type max_size() const { return INT_MAX; } \
956 bool empty() const { return IsEmpty(); } \
957 reference front() { return *begin(); } \
958 const_reference front() const { return *begin(); } \
959 reference back() { return *--end(); } \
960 const_reference back() const { return *--end(); } \
961 void push_front(const_reference v = value_type()) \
962 { Insert(GetFirst(), (const_base_reference)v); } \
963 void pop_front() { DeleteNode(GetFirst()); } \
964 void push_back(const_reference v = value_type()) \
965 { Append((const_base_reference)v); } \
966 void pop_back() { DeleteNode(GetLast()); } \
967 void assign(const_iterator first, const_iterator last) \
970 for(; first != last; ++first) \
971 Append((const_base_reference)*first); \
973 void assign(size_type n, const_reference v = value_type()) \
976 for(size_type i = 0; i < n; ++i) \
977 Append((const_base_reference)v); \
979 iterator insert(iterator it, const_reference v = value_type()) \
981 Insert(it.m_node, (const_base_reference)v); \
982 return iterator(it.m_node->GetPrevious(), GetLast()); \
984 void insert(iterator it, size_type n, const_reference v = value_type())\
986 for(size_type i = 0; i < n; ++i) \
987 Insert(it.m_node, (const_base_reference)v); \
989 void insert(iterator it, const_iterator first, const_iterator last) \
991 for(; first != last; ++first) \
992 Insert(it.m_node, (const_base_reference)*first); \
994 iterator erase(iterator it) \
996 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
997 DeleteNode(it.m_node); return next; \
999 iterator erase(iterator first, iterator last) \
1001 iterator next = last; ++next; \
1002 DeleteNodes(first.m_node, last.m_node); \
1005 void clear() { Clear(); } \
1006 void splice(iterator it, name& l, iterator first, iterator last) \
1007 { insert(it, first, last); l.erase(first, last); } \
1008 void splice(iterator it, name& l) \
1009 { splice(it, l, l.begin(), l.end() ); } \
1010 void splice(iterator it, name& l, iterator first) \
1012 iterator tmp = first; ++tmp; \
1013 if(it == first || it == tmp) return; \
1014 insert(it, *first); \
1017 void remove(const_reference v) \
1018 { DeleteObject((const_base_reference)v); } \
1021 /* void swap(name& l) \
1023 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1024 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1025 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1026 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1027 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1031 #define WX_LIST_PTROP \
1032 pointer_type operator->() const \
1033 { return (pointer_type)m_node->GetDataPtr(); }
1034 #define WX_LIST_PTROP_NONE
1036 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1037 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1038 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1039 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1041 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1042 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1043 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1044 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1046 #define WX_DECLARE_LIST(elementtype, listname) \
1047 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1048 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1049 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1050 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1051 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1053 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1054 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1055 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1057 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1058 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1060 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1061 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1062 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1064 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1065 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1066 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1067 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1068 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1069 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1071 // this macro must be inserted in your program after
1072 // #include <wx/listimpl.cpp>
1073 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1075 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1076 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1078 #endif // !wxUSE_STL
1080 // ============================================================================
1081 // now we can define classes 100% compatible with the old ones
1082 // ============================================================================
1084 // ----------------------------------------------------------------------------
1085 // commonly used list classes
1086 // ----------------------------------------------------------------------------
1088 #if defined(wxLIST_COMPATIBILITY)
1090 // inline compatibility functions
1094 // ----------------------------------------------------------------------------
1095 // wxNodeBase deprecated methods
1096 // ----------------------------------------------------------------------------
1098 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1099 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1100 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1102 // ----------------------------------------------------------------------------
1103 // wxListBase deprecated methods
1104 // ----------------------------------------------------------------------------
1106 inline int wxListBase::Number() const { return (int)GetCount(); }
1107 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1108 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1109 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1110 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1114 // define this to make a lot of noise about use of the old wxList classes.
1115 //#define wxWARN_COMPAT_LIST_USE
1117 // ----------------------------------------------------------------------------
1118 // wxList compatibility class: in fact, it's a list of wxObjects
1119 // ----------------------------------------------------------------------------
1121 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1122 class WXDLLIMPEXP_BASE
);
1124 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1127 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1129 wxDEPRECATED( wxList(int key_type
) );
1131 wxList(int key_type
= wxKEY_NONE
);
1134 // this destructor is required for Darwin
1138 wxList
& operator=(const wxList
& list
)
1139 { (void) wxListBase::operator=(list
); return *this; }
1141 // compatibility methods
1142 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1147 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1152 DECLARE_DYNAMIC_CLASS(wxList
)
1158 // -----------------------------------------------------------------------------
1159 // wxStringList class for compatibility with the old code
1160 // -----------------------------------------------------------------------------
1161 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1163 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1168 #ifdef wxWARN_COMPAT_LIST_USE
1170 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1173 wxStringList(const wxChar
*first
...);
1176 // copying the string list: the strings are copied, too (extremely
1178 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1179 wxStringList
& operator=(const wxStringList
& other
)
1180 { Clear(); DoCopy(other
); return *this; }
1183 // makes a copy of the string
1184 wxNode
*Add(const wxChar
*s
);
1186 // Append to beginning of list
1187 wxNode
*Prepend(const wxChar
*s
);
1189 bool Delete(const wxChar
*s
);
1191 wxChar
**ListToArray(bool new_copies
= false) const;
1192 bool Member(const wxChar
*s
) const;
1198 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1200 DECLARE_DYNAMIC_CLASS(wxStringList
)
1203 #else // if wxUSE_STL
1205 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1207 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1210 compatibility_iterator
Append(wxChar
* s
)
1211 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1212 compatibility_iterator
Insert(wxChar
* s
)
1213 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1214 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1218 return wxStringListBase::Insert(pos
, tmp
);
1220 compatibility_iterator
Add(const wxChar
* s
)
1221 { push_back(s
); return GetLast(); }
1222 compatibility_iterator
Prepend(const wxChar
* s
)
1223 { push_front(s
); return GetFirst(); }
1228 #endif // wxLIST_COMPATIBILITY
1230 // delete all list elements
1232 // NB: the class declaration of the list elements must be visible from the
1233 // place where you use this macro, otherwise the proper destructor may not
1234 // be called (a decent compiler should give a warning about it, but don't
1236 #define WX_CLEAR_LIST(type, list) \
1238 type::iterator it, en; \
1239 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \