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) const \
174 { return (m_list == i.m_list) && (m_iter == i.m_iter); } \
175 bool operator!=(const compatibility_iterator& i) const \
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 // undef it to get rid of old, deprecated functions
332 #define wxLIST_COMPATIBILITY
334 // -----------------------------------------------------------------------------
335 // key stuff: a list may be optionally keyed on integer or string key
336 // -----------------------------------------------------------------------------
344 // a struct which may contain both types of keys
346 // implementation note: on one hand, this class allows to have only one function
347 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
348 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
349 // wxList::Find(const char *).
350 class WXDLLIMPEXP_BASE wxListKey
354 wxListKey() : m_keyType(wxKEY_NONE
)
356 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
357 { m_key
.integer
= i
; }
358 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
359 { m_key
.string
= wxStrdup(s
); }
360 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
361 { m_key
.string
= wxStrdup(s
.c_str()); }
364 wxKeyType
GetKeyType() const { return m_keyType
; }
365 const wxChar
*GetString() const
366 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
367 long GetNumber() const
368 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
371 // Note: implementation moved to list.cpp to prevent BC++ inline
372 // expansion warning.
373 bool operator==(wxListKeyValue value
) const ;
378 if ( m_keyType
== wxKEY_STRING
)
384 wxListKeyValue m_key
;
387 // -----------------------------------------------------------------------------
388 // wxNodeBase class is a (base for) node in a double linked list
389 // -----------------------------------------------------------------------------
391 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
393 class WXDLLIMPEXP_BASE wxListBase
;
395 class WXDLLIMPEXP_BASE wxNodeBase
397 friend class wxListBase
;
400 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
401 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
402 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
404 const wxListKey
& key
= wxDefaultListKey
);
406 virtual ~wxNodeBase();
408 // FIXME no check is done that the list is really keyed on strings
409 const wxChar
*GetKeyString() const { return m_key
.string
; }
410 long GetKeyInteger() const { return m_key
.integer
; }
412 // Necessary for some existing code
413 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
414 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
416 #ifdef wxLIST_COMPATIBILITY
417 // compatibility methods, use Get* instead.
418 wxDEPRECATED( wxNode
*Next() const );
419 wxDEPRECATED( wxNode
*Previous() const );
420 wxDEPRECATED( wxObject
*Data() const );
421 #endif // wxLIST_COMPATIBILITY
424 // all these are going to be "overloaded" in the derived classes
425 wxNodeBase
*GetNext() const { return m_next
; }
426 wxNodeBase
*GetPrevious() const { return m_previous
; }
428 void *GetData() const { return m_data
; }
429 void SetData(void *data
) { m_data
= data
; }
431 // get 0-based index of this node within the list or wxNOT_FOUND
434 virtual void DeleteData() { }
436 // for wxList::iterator
437 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
439 // optional key stuff
440 wxListKeyValue m_key
;
442 void *m_data
; // user data
443 wxNodeBase
*m_next
, // next and previous nodes in the list
446 wxListBase
*m_list
; // list we belong to
448 DECLARE_NO_COPY_CLASS(wxNodeBase
)
451 // -----------------------------------------------------------------------------
452 // a double-linked list class
453 // -----------------------------------------------------------------------------
455 class WXDLLIMPEXP_BASE wxList
;
457 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
459 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
460 friend class wxHashTableBase
; // should be able to call untyped Find()
463 // default ctor & dtor
464 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
466 virtual ~wxListBase();
469 // count of items in the list
470 size_t GetCount() const { return m_count
; }
472 // return true if this list is empty
473 bool IsEmpty() const { return m_count
== 0; }
480 // instruct it to destroy user data when deleting nodes
481 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
483 // query if to delete
484 bool GetDeleteContents() const
485 { return m_destroy
; }
488 wxKeyType
GetKeyType() const
489 { return m_keyType
; }
491 // set the keytype (required by the serial code)
492 void SetKeyType(wxKeyType keyType
)
493 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
495 #ifdef wxLIST_COMPATIBILITY
496 // compatibility methods from old wxList
497 wxDEPRECATED( int Number() const ); // use GetCount instead.
498 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
499 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
500 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
502 // kludge for typesafe list migration in core classes.
503 wxDEPRECATED( operator wxList
&() const );
504 #endif // wxLIST_COMPATIBILITY
508 // all methods here are "overloaded" in derived classes to provide compile
509 // time type checking
511 // create a node for the list of this type
512 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
514 const wxListKey
& key
= wxDefaultListKey
) = 0;
516 // Can't access these from derived classes otherwise (bug in Salford C++?)
523 wxListBase(size_t count
, void *elements
[]);
524 // from a sequence of objects
525 wxListBase(void *object
, ... /* terminate with NULL */);
528 void Assign(const wxListBase
& list
)
529 { Clear(); DoCopy(list
); }
531 // get list head/tail
532 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
533 wxNodeBase
*GetLast() const { return m_nodeLast
; }
535 // by (0-based) index
536 wxNodeBase
*Item(size_t index
) const;
538 // get the list item's data
539 void *operator[](size_t n
) const
541 wxNodeBase
*node
= Item(n
);
543 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
547 // append to end of list
548 wxNodeBase
*Prepend(void *object
)
549 { return (wxNodeBase
*)wxListBase::Insert(object
); }
550 // append to beginning of list
551 wxNodeBase
*Append(void *object
);
552 // insert a new item at the beginning of the list
553 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
554 // insert a new item at the given position
555 wxNodeBase
*Insert(size_t pos
, void *object
)
556 { return pos
== GetCount() ? Append(object
)
557 : Insert(Item(pos
), object
); }
558 // insert before given node or at front of list if prev == NULL
559 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
562 wxNodeBase
*Append(long key
, void *object
);
563 wxNodeBase
*Append(const wxChar
*key
, void *object
);
565 // removes node from the list but doesn't delete it (returns pointer
566 // to the node or NULL if it wasn't found in the list)
567 wxNodeBase
*DetachNode(wxNodeBase
*node
);
568 // delete element from list, returns false if node not found
569 bool DeleteNode(wxNodeBase
*node
);
570 // finds object pointer and deletes node (and object if DeleteContents
571 // is on), returns false if object not found
572 bool DeleteObject(void *object
);
574 // search (all return NULL if item not found)
576 wxNodeBase
*Find(const void *object
) const;
579 wxNodeBase
*Find(const wxListKey
& key
) const;
581 // get 0-based index of object or wxNOT_FOUND
582 int IndexOf( void *object
) const;
584 // this function allows the sorting of arbitrary lists by giving
585 // a function to compare two list elements. The list is sorted in place.
586 void Sort(const wxSortCompareFunction compfunc
);
588 // functions for iterating over the list
589 void *FirstThat(wxListIterateFunction func
);
590 void ForEach(wxListIterateFunction func
);
591 void *LastThat(wxListIterateFunction func
);
593 // for STL interface, "last" points to one after the last node
594 // of the controlled sequence (NULL for the end of the list)
596 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
599 // common part of all ctors
600 void Init(wxKeyType keyType
= wxKEY_NONE
);
603 // common part of copy ctor and assignment operator
604 void DoCopy(const wxListBase
& list
);
605 // common part of all Append()s
606 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
607 // free node's data and node itself
608 void DoDeleteNode(wxNodeBase
*node
);
610 size_t m_count
; // number of elements in the list
611 bool m_destroy
; // destroy user data when deleting list items?
612 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
615 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
618 // -----------------------------------------------------------------------------
619 // macros for definition of "template" list type
620 // -----------------------------------------------------------------------------
622 // and now some heavy magic...
624 // declare a list type named 'name' and containing elements of type 'T *'
625 // (as a by product of macro expansion you also get wx##name##Node
626 // wxNode-derived type)
628 // implementation details:
629 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
630 // for the list of given type - this allows us to pass only the list name
631 // to WX_DEFINE_LIST() even if it needs both the name and the type
633 // 2. We redefine all non-type-safe wxList functions with type-safe versions
634 // which don't take any space (everything is inline), but bring compile
635 // time error checking.
637 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
638 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
639 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
640 // interesting capability to store polymorphic objects in the list and is
641 // particularly useful with, for example, "wxWindow *" list where the
642 // wxWindowBase pointers are put into the list, but wxWindow pointers are
643 // retrieved from it.
645 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
646 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
647 // it results in compiler warnings when this operator doesn't make sense
648 // (i.e. stored elements are not pointers)
650 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
651 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
652 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
654 classexp nodetype : public wxNodeBase \
657 nodetype(wxListBase *list = (wxListBase *)NULL, \
658 nodetype *previous = (nodetype *)NULL, \
659 nodetype *next = (nodetype *)NULL, \
660 T *data = (T *)NULL, \
661 const wxListKey& key = wxDefaultListKey) \
662 : wxNodeBase(list, previous, next, data, key) { } \
664 nodetype *GetNext() const \
665 { return (nodetype *)wxNodeBase::GetNext(); } \
666 nodetype *GetPrevious() const \
667 { return (nodetype *)wxNodeBase::GetPrevious(); } \
670 { return (T *)wxNodeBase::GetData(); } \
671 void SetData(T *data) \
672 { 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const_iterator& first, const 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() { iterator tmp = end(); return *--tmp; } \
960 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
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 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(const 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(const 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(const iterator& it, const_iterator first, const const_iterator& last)\
991 for(; first != last; ++first) \
992 Insert(it.m_node, (const_base_reference)*first); \
994 iterator erase(const iterator& it) \
996 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
997 DeleteNode(it.m_node); return next; \
999 iterator erase(const iterator& first, const iterator& last) \
1001 iterator next = last; ++next; \
1002 DeleteNodes(first.m_node, last.m_node); \
1005 void clear() { Clear(); } \
1006 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1007 { insert(it, first, last); l.erase(first, last); } \
1008 void splice(const iterator& it, name& l) \
1009 { splice(it, l, l.begin(), l.end() ); } \
1010 void splice(const iterator& it, name& l, const 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 ) \