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(__APPLE__) && \
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"
44 #include "wx/afterstd.h"
45 #if defined(__WXMSW__) && defined(__MINGW32__)
46 #include "wx/msw/winundef.h"
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // type of compare function for list sort operation (as in 'qsort'): it should
55 // return a negative value, 0 or positive value if the first element is less
56 // 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_X(elT, liT, decl)
91 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
92 WX_DECLARE_LIST_X(elT, liT, decl)
94 #define WX_DECLARE_LIST_X(elT, liT, decl) \
95 WX_DECLARE_LIST_XO(elT*, liT, decl)
97 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
98 decl liT : public std::list<elT> \
103 struct compatibility_iterator \
105 typedef std::list<elT>::iterator iterator; \
109 operator bool() const \
110 { return m_list && m_iter != m_list->end(); } \
111 bool operator !() const \
112 { return !m_list || m_iter == m_list->end(); } \
113 compatibility_iterator( const liT* li, iterator it ) \
114 : m_iter( it ), m_list( (liT*)li ) {} \
115 compatibility_iterator( liT* li, iterator it ) \
116 : m_iter( it ), m_list( li ) {} \
117 compatibility_iterator() : m_list( NULL ) { } \
118 dummy* operator->() { return (dummy*)this; } \
119 const dummy* operator->() const { return (const dummy*)this; } \
121 typedef struct compatibility_iterator citer; \
125 typedef std::list<elT>::iterator it; \
126 typedef compatibility_iterator citer; \
128 elT GetData() const \
130 citer* i = (citer*)this; \
131 return *(i->m_iter); \
133 citer GetNext() const \
135 citer* i = (citer*)this; \
136 it lit = i->m_iter; \
137 return citer( i->m_list, ++lit ); \
139 citer GetPrevious() const \
141 citer* i = (citer*)this; \
142 it lit = i->m_iter; \
143 return citer( i->m_list, ++lit ); \
145 void SetData( elT e ) \
147 citer* i = (citer*)this; \
154 iterator find( elT e ) \
157 for( it = begin(), en = end(); it != en; ++it ) \
165 citer Append( elT e ) { push_back( e ); return GetLast(); } \
166 void Clear() { clear(); } \
167 size_t GetCount() const { return size(); } \
168 citer GetFirst() const { return citer( this, ((liT*)this)->begin() ); } \
169 citer GetLast() const { return citer( this, --(((liT*)this)->end()) ); } \
170 bool IsEmpty() const { return empty(); } \
171 bool DeleteObject( elT e ) \
173 iterator it = find( e ); \
181 void Erase( const compatibility_iterator& it ) \
183 erase( it.m_iter ); \
185 citer Find( elT e ) const { return citer( this, ((liT*)this)->find( e ) ); } \
186 citer Member( elT e ) const { return Find( e ); } \
187 citer Insert( elT e ) \
188 { push_front( e ); return citer( this, begin() ); } \
189 citer Insert( size_t idx, elT e ) \
190 { return Insert( Item( idx ), e ); } \
191 citer Insert( citer idx, elT e ) \
192 { return citer( this, insert( idx.m_iter, e ) ); } \
193 citer Item( size_t idx ) const \
196 for( it = ((liT*)this)->begin(); idx; --idx ) \
198 return citer( this, it ); \
200 int IndexOf( elT e ) const \
202 const_iterator it, en; \
204 for( idx = 0, it = begin(), en = end(); it != en; ++it, ++idx ) \
207 return wxNOT_FOUND; \
211 #define WX_DECLARE_LIST(elementtype, listname) \
212 WX_DECLARE_LIST_X(elementtype, listname, class)
214 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
215 WX_DECLARE_LIST_X(elementtype, listname, class WXDLLEXPORT)
217 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
218 WX_DECLARE_LIST_X(elementtype, listname, class usergoo)
220 // this macro must be inserted in your program after
221 // #include <wx/listimpl.cpp>
222 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
224 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
225 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
227 #else // if !wxUSE_STL
229 // due to circular header dependencies this function has to be declared here
230 // (normally it's found in utils.h which includes itself list.h...)
231 extern WXDLLEXPORT wxChar
* copystring(const wxChar
*s
);
233 class WXDLLEXPORT wxObjectListNode
;
234 typedef wxObjectListNode wxNode
;
236 // undef it to get rid of old, deprecated functions
237 #define wxLIST_COMPATIBILITY
239 // -----------------------------------------------------------------------------
240 // key stuff: a list may be optionally keyed on integer or string key
241 // -----------------------------------------------------------------------------
249 // a struct which may contain both types of keys
251 // implementation note: on one hand, this class allows to have only one function
252 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
253 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
254 // wxList::Find(const char *).
255 class WXDLLIMPEXP_BASE wxListKey
259 wxListKey() : m_keyType(wxKEY_NONE
)
261 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
262 { m_key
.integer
= i
; }
263 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
264 { m_key
.string
= wxStrdup(s
); }
265 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
266 { m_key
.string
= wxStrdup(s
.c_str()); }
269 wxKeyType
GetKeyType() const { return m_keyType
; }
270 const wxChar
*GetString() const
271 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
272 long GetNumber() const
273 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
276 // Note: implementation moved to list.cpp to prevent BC++ inline
277 // expansion warning.
278 bool operator==(wxListKeyValue value
) const ;
283 if ( m_keyType
== wxKEY_STRING
)
289 wxListKeyValue m_key
;
292 // -----------------------------------------------------------------------------
293 // wxNodeBase class is a (base for) node in a double linked list
294 // -----------------------------------------------------------------------------
296 WXDLLIMPEXP_DATA_BASE(extern wxListKey
) wxDefaultListKey
;
298 class WXDLLIMPEXP_BASE wxListBase
;
300 class WXDLLIMPEXP_BASE wxNodeBase
302 friend class wxListBase
;
305 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
306 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
307 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
309 const wxListKey
& key
= wxDefaultListKey
);
311 virtual ~wxNodeBase();
313 // FIXME no check is done that the list is really keyed on strings
314 const wxChar
*GetKeyString() const { return m_key
.string
; }
315 long GetKeyInteger() const { return m_key
.integer
; }
317 // Necessary for some existing code
318 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
319 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
321 #ifdef wxLIST_COMPATIBILITY
322 // compatibility methods, use Get* instead.
323 wxDEPRECATED( wxNode
*Next() const );
324 wxDEPRECATED( wxNode
*Previous() const );
325 wxDEPRECATED( wxObject
*Data() const );
326 #endif // wxLIST_COMPATIBILITY
329 // all these are going to be "overloaded" in the derived classes
330 wxNodeBase
*GetNext() const { return m_next
; }
331 wxNodeBase
*GetPrevious() const { return m_previous
; }
333 void *GetData() const { return m_data
; }
334 void SetData(void *data
) { m_data
= data
; }
336 // get 0-based index of this node within the list or wxNOT_FOUND
339 virtual void DeleteData() { }
341 // for wxList::iterator
342 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
344 // optional key stuff
345 wxListKeyValue m_key
;
347 void *m_data
; // user data
348 wxNodeBase
*m_next
, // next and previous nodes in the list
351 wxListBase
*m_list
; // list we belong to
353 DECLARE_NO_COPY_CLASS(wxNodeBase
)
356 // -----------------------------------------------------------------------------
357 // a double-linked list class
358 // -----------------------------------------------------------------------------
362 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
364 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
365 friend class wxHashTableBase
; // should be able to call untyped Find()
367 // common part of all ctors
368 void Init(wxKeyType keyType
= wxKEY_NONE
); // Must be declared before it's used (for VC++ 1.5)
370 // default ctor & dtor
371 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
373 virtual ~wxListBase();
376 // count of items in the list
377 size_t GetCount() const { return m_count
; }
379 // return TRUE if this list is empty
380 bool IsEmpty() const { return m_count
== 0; }
387 // instruct it to destroy user data when deleting nodes
388 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
390 // query if to delete
391 bool GetDeleteContents() const
392 { return m_destroy
; }
395 wxKeyType
GetKeyType() const
396 { return m_keyType
; }
398 // set the keytype (required by the serial code)
399 void SetKeyType(wxKeyType keyType
)
400 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
402 #ifdef wxLIST_COMPATIBILITY
403 // compatibility methods from old wxList
404 wxDEPRECATED( int Number() const ); // use GetCount instead.
405 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
406 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
407 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
409 // kludge for typesafe list migration in core classes.
410 wxDEPRECATED( operator wxList
&() const );
411 #endif // wxLIST_COMPATIBILITY
415 // all methods here are "overloaded" in derived classes to provide compile
416 // time type checking
418 // create a node for the list of this type
419 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
421 const wxListKey
& key
= wxDefaultListKey
) = 0;
423 // Can't access these from derived classes otherwise (bug in Salford C++?)
430 wxListBase(size_t count
, void *elements
[]);
431 // from a sequence of objects
432 wxListBase(void *object
, ... /* terminate with NULL */);
435 // copy ctor and assignment operator
436 wxListBase(const wxListBase
& list
) : wxObject()
437 { Init(); DoCopy(list
); }
438 wxListBase
& operator=(const wxListBase
& list
)
439 { Clear(); DoCopy(list
); return *this; }
441 // get list head/tail
442 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
443 wxNodeBase
*GetLast() const { return m_nodeLast
; }
445 // by (0-based) index
446 wxNodeBase
*Item(size_t index
) const;
448 // get the list item's data
449 void *operator[](size_t n
) const
451 wxNodeBase
*node
= Item(n
);
453 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
457 // append to end of list
458 wxNodeBase
*Prepend(void *object
)
459 { return (wxNodeBase
*)wxListBase::Insert(object
); }
460 // append to beginning of list
461 wxNodeBase
*Append(void *object
);
462 // insert a new item at the beginning of the list
463 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
464 // insert a new item at the given position
465 wxNodeBase
*Insert(size_t pos
, void *object
)
466 { return pos
== GetCount() ? Append(object
)
467 : Insert(Item(pos
), object
); }
468 // insert before given node or at front of list if prev == NULL
469 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
472 wxNodeBase
*Append(long key
, void *object
);
473 wxNodeBase
*Append(const wxChar
*key
, void *object
);
475 // removes node from the list but doesn't delete it (returns pointer
476 // to the node or NULL if it wasn't found in the list)
477 wxNodeBase
*DetachNode(wxNodeBase
*node
);
478 // delete element from list, returns FALSE if node not found
479 bool DeleteNode(wxNodeBase
*node
);
480 // finds object pointer and deletes node (and object if DeleteContents
481 // is on), returns FALSE if object not found
482 bool DeleteObject(void *object
);
484 // search (all return NULL if item not found)
486 wxNodeBase
*Find(void *object
) const;
489 wxNodeBase
*Find(const wxListKey
& key
) const;
491 // get 0-based index of object or wxNOT_FOUND
492 int IndexOf( void *object
) const;
494 // this function allows the sorting of arbitrary lists by giving
495 // a function to compare two list elements. The list is sorted in place.
496 void Sort(const wxSortCompareFunction compfunc
);
498 // functions for iterating over the list
499 void *FirstThat(wxListIterateFunction func
);
500 void ForEach(wxListIterateFunction func
);
501 void *LastThat(wxListIterateFunction func
);
503 // for STL interface, "last" points to one after the last node
504 // of the controlled sequence (NULL for the end of the list)
506 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
509 // common part of copy ctor and assignment operator
510 void DoCopy(const wxListBase
& list
);
511 // common part of all Append()s
512 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
513 // free node's data and node itself
514 void DoDeleteNode(wxNodeBase
*node
);
516 size_t m_count
; // number of elements in the list
517 bool m_destroy
; // destroy user data when deleting list items?
518 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
521 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
524 // -----------------------------------------------------------------------------
525 // macros for definition of "template" list type
526 // -----------------------------------------------------------------------------
528 // and now some heavy magic...
530 // declare a list type named 'name' and containing elements of type 'T *'
531 // (as a by product of macro expansion you also get wx##name##Node
532 // wxNode-derived type)
534 // implementation details:
535 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
536 // for the list of given type - this allows us to pass only the list name
537 // to WX_DEFINE_LIST() even if it needs both the name and the type
539 // 2. We redefine all non-type-safe wxList functions with type-safe versions
540 // which don't take any space (everything is inline), but bring compile
541 // time error checking.
543 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
544 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
545 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
546 // interesting capability to store polymorphic objects in the list and is
547 // particularly useful with, for example, "wxWindow *" list where the
548 // wxWindowBase pointers are put into the list, but wxWindow pointers are
549 // retrieved from it.
551 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
552 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
554 classexp nodetype : public wxNodeBase \
557 nodetype(wxListBase *list = (wxListBase *)NULL, \
558 nodetype *previous = (nodetype *)NULL, \
559 nodetype *next = (nodetype *)NULL, \
560 T *data = (T *)NULL, \
561 const wxListKey& key = wxDefaultListKey) \
562 : wxNodeBase(list, previous, next, data, key) { } \
564 nodetype *GetNext() const \
565 { return (nodetype *)wxNodeBase::GetNext(); } \
566 nodetype *GetPrevious() const \
567 { return (nodetype *)wxNodeBase::GetPrevious(); } \
570 { return (T *)wxNodeBase::GetData(); } \
571 void SetData(T *data) \
572 { wxNodeBase::SetData(data); } \
574 virtual void DeleteData(); \
577 classexp name : public wxListBase \
580 typedef nodetype Node; \
581 typedef Node* compatibility_iterator; \
583 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
585 name(size_t count, T *elements[]) \
586 : wxListBase(count, (void **)elements) { } \
588 name& operator=(const name& list) \
589 { (void) wxListBase::operator=(list); return *this; } \
591 nodetype *GetFirst() const \
592 { return (nodetype *)wxListBase::GetFirst(); } \
593 nodetype *GetLast() const \
594 { return (nodetype *)wxListBase::GetLast(); } \
596 nodetype *Item(size_t index) const \
597 { return (nodetype *)wxListBase::Item(index); } \
599 T *operator[](size_t index) const \
601 nodetype *node = Item(index); \
602 return node ? (T*)(node->GetData()) : (T*)NULL; \
605 nodetype *Append(Tbase *object) \
606 { return (nodetype *)wxListBase::Append(object); } \
607 nodetype *Insert(Tbase *object) \
608 { return (nodetype *)Insert((nodetype*)NULL, object); } \
609 nodetype *Insert(size_t pos, Tbase *object) \
610 { return (nodetype *)wxListBase::Insert(pos, object); } \
611 nodetype *Insert(nodetype *prev, Tbase *object) \
612 { return (nodetype *)wxListBase::Insert(prev, object); } \
614 nodetype *Append(long key, void *object) \
615 { return (nodetype *)wxListBase::Append(key, object); } \
616 nodetype *Append(const wxChar *key, void *object) \
617 { return (nodetype *)wxListBase::Append(key, object); } \
619 nodetype *DetachNode(nodetype *node) \
620 { return (nodetype *)wxListBase::DetachNode(node); } \
621 bool DeleteNode(nodetype *node) \
622 { return wxListBase::DeleteNode(node); } \
623 bool DeleteObject(Tbase *object) \
624 { return wxListBase::DeleteObject(object); } \
625 void Erase(compatibility_iterator it) \
626 { DeleteNode(it); } \
628 nodetype *Find(Tbase *object) const \
629 { return (nodetype *)wxListBase::Find(object); } \
631 virtual nodetype *Find(const wxListKey& key) const \
632 { return (nodetype *)wxListBase::Find(key); } \
634 int IndexOf(Tbase *object) const \
635 { return wxListBase::IndexOf(object); } \
637 void Sort(wxSortFuncFor_##name func) \
638 { wxListBase::Sort((wxSortCompareFunction)func); } \
641 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
643 const wxListKey& key = wxDefaultListKey) \
645 return new nodetype(this, \
646 (nodetype *)prev, (nodetype *)next, \
649 /* STL interface */ \
651 typedef size_t size_type; \
652 typedef int difference_type; \
653 typedef T* value_type; \
654 typedef Tbase* base_value_type; \
655 typedef value_type& reference; \
656 typedef const value_type& const_reference; \
657 typedef base_value_type& base_reference; \
658 typedef const base_value_type& const_base_reference; \
664 typedef nodetype Node; \
665 typedef iterator itor; \
666 typedef T* value_type; \
667 typedef value_type* ptr_type; \
668 typedef value_type& reference; \
673 typedef reference reference_type; \
674 typedef ptr_type pointer_type; \
676 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
677 iterator() : m_node(NULL), m_init(NULL) { } \
678 reference_type operator*() const \
679 { return *(pointer_type)m_node->GetDataPtr(); } \
680 pointer_type operator->() const \
681 { return (pointer_type)m_node->GetDataPtr(); } \
682 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
683 itor operator++(int) \
684 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
687 m_node = m_node ? m_node->GetPrevious() : m_init; \
690 itor operator--(int) \
693 m_node = m_node ? m_node->GetPrevious() : m_init; \
696 bool operator!=(const itor& it) const \
697 { return it.m_node != m_node; } \
698 bool operator==(const itor& it) const \
699 { return it.m_node == m_node; } \
701 class const_iterator \
705 typedef nodetype Node; \
706 typedef T* value_type; \
707 typedef const value_type& const_reference; \
708 typedef const_iterator itor; \
709 typedef value_type* ptr_type; \
714 typedef const_reference reference_type; \
715 typedef const ptr_type pointer_type; \
717 const_iterator(Node* node, Node* init) \
718 : m_node(node), m_init(init) { } \
719 const_iterator() : m_node(NULL), m_init(NULL) { } \
720 const_iterator(const iterator& it) \
721 : m_node(it.m_node), m_init(it.m_init) { } \
722 reference_type operator*() const \
723 { return *(pointer_type)m_node->GetDataPtr(); } \
724 pointer_type operator->() const \
725 { return (pointer_type)m_node->GetDataPtr(); } \
726 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
727 itor operator++(int) \
728 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
731 m_node = m_node ? m_node->GetPrevious() : m_init; \
734 itor operator--(int) \
737 m_node = m_node ? m_node->GetPrevious() : m_init; \
740 bool operator!=(const itor& it) const \
741 { return it.m_node != m_node; } \
742 bool operator==(const itor& it) const \
743 { return it.m_node == m_node; } \
745 class reverse_iterator \
749 typedef nodetype Node; \
750 typedef T* value_type; \
751 typedef reverse_iterator itor; \
752 typedef value_type* ptr_type; \
753 typedef value_type& reference; \
758 typedef reference reference_type; \
759 typedef ptr_type pointer_type; \
761 reverse_iterator(Node* node, Node* init) \
762 : m_node(node), m_init(init) { } \
763 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
764 reference_type operator*() const \
765 { return *(pointer_type)m_node->GetDataPtr(); } \
766 pointer_type operator->() const \
767 { return (pointer_type)m_node->GetDataPtr(); } \
769 { m_node = m_node->GetPrevious(); return *this; } \
770 itor operator++(int) \
771 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
773 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
774 itor operator--(int) \
777 m_node = m_node ? m_node->GetNext() : m_init; \
780 bool operator!=(const itor& it) const \
781 { return it.m_node != m_node; } \
782 bool operator==(const itor& it) const \
783 { return it.m_node == m_node; } \
785 class const_reverse_iterator \
789 typedef nodetype Node; \
790 typedef T* value_type; \
791 typedef const_reverse_iterator itor; \
792 typedef value_type* ptr_type; \
793 typedef const value_type& const_reference; \
798 typedef const_reference reference_type; \
799 typedef const ptr_type pointer_type; \
801 const_reverse_iterator(Node* node, Node* init) \
802 : m_node(node), m_init(init) { } \
803 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
804 const_reverse_iterator(const reverse_iterator& it) \
805 : m_node(it.m_node), m_init(it.m_init) { } \
806 reference_type operator*() const \
807 { return *(pointer_type)m_node->GetDataPtr(); } \
808 pointer_type operator->() const \
809 { return (pointer_type)m_node->GetDataPtr(); } \
811 { m_node = m_node->GetPrevious(); return *this; } \
812 itor operator++(int) \
813 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
815 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
816 itor operator--(int) \
819 m_node = m_node ? m_node->GetNext() : m_init; \
822 bool operator!=(const itor& it) const \
823 { return it.m_node != m_node; } \
824 bool operator==(const itor& it) const \
825 { return it.m_node == m_node; } \
828 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
830 name(const_iterator first, const_iterator last) \
831 { assign(first, last); } \
832 iterator begin() { return iterator(GetFirst(), GetLast()); } \
833 const_iterator begin() const \
834 { return const_iterator(GetFirst(), GetLast()); } \
835 iterator end() { return iterator(NULL, GetLast()); } \
836 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
837 reverse_iterator rbegin() \
838 { return reverse_iterator(GetLast(), GetFirst()); } \
839 const_reverse_iterator rbegin() const \
840 { return const_reverse_iterator(GetLast(), GetFirst()); } \
841 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
842 const_reverse_iterator rend() const \
843 { return const_reverse_iterator(NULL, GetFirst()); } \
844 void resize(size_type n, value_type v = value_type()) \
847 for(; n < size(); pop_back()); \
848 else if(n > size()) \
849 for(; n > size(); push_back(v)); \
851 size_type size() const { return GetCount(); } \
852 size_type max_size() const { return INT_MAX; } \
853 bool empty() const { return IsEmpty(); } \
854 reference front() { return *begin(); } \
855 const_reference front() const { return *begin(); } \
856 reference back() { return *--end(); } \
857 const_reference back() const { return *--end(); } \
858 void push_front(const_reference v = value_type()) \
859 { Insert(GetFirst(), (const_base_reference)v); } \
860 void pop_front() { DeleteNode(GetFirst()); } \
861 void push_back(const_reference v = value_type()) \
862 { Append((const_base_reference)v); } \
863 void pop_back() { DeleteNode(GetLast()); } \
864 void assign(const_iterator first, const_iterator last) \
867 for(; first != last; ++first) \
868 Append((const_base_reference)*first); \
870 void assign(size_type n, const_reference v = value_type()) \
873 for(size_type i = 0; i < n; ++i) \
874 Append((const_base_reference)v); \
876 iterator insert(iterator it, const_reference v = value_type()) \
878 Insert(it.m_node, (const_base_reference)v); \
879 return iterator(it.m_node->GetPrevious(), GetLast()); \
881 void insert(iterator it, size_type n, const_reference v = value_type())\
883 for(size_type i = 0; i < n; ++i) \
884 Insert(it.m_node, (const_base_reference)v); \
886 void insert(iterator it, const_iterator first, const_iterator last) \
888 for(; first != last; ++first) \
889 Insert(it.m_node, (const_base_reference)*first); \
891 iterator erase(iterator it) \
893 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
894 DeleteNode(it.m_node); return next; \
896 iterator erase(iterator first, iterator last) \
898 iterator next = last; ++next; \
899 DeleteNodes(first.m_node, last.m_node); \
902 void clear() { Clear(); } \
903 void splice(iterator it, name& l, iterator first, iterator last) \
904 { insert(it, first, last); l.erase(first, last); } \
905 void splice(iterator it, name& l) \
906 { splice(it, l, l.begin(), l.end() ); } \
907 void splice(iterator it, name& l, iterator first) \
909 iterator tmp = first; ++tmp; \
910 if(it == first || it == tmp) return; \
911 insert(it, *first); \
914 void remove(const_reference v) \
915 { DeleteObject((const_base_reference)v); } \
918 /* void swap(name& l) \
920 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
921 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
922 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
923 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
924 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
928 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
929 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
931 #define WX_DECLARE_LIST(elementtype, listname) \
932 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
933 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
935 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
936 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
937 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
939 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
940 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
941 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
943 // this macro must be inserted in your program after
944 // #include <wx/listimpl.cpp>
945 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
947 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
948 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
952 // =============================================================================
953 // now we can define classes 100% compatible with the old ones
954 // =============================================================================
956 // ----------------------------------------------------------------------------
957 // commonly used list classes
958 // ----------------------------------------------------------------------------
960 #ifdef wxLIST_COMPATIBILITY
962 // define this to make a lot of noise about use of the old wxList classes.
963 //#define wxWARN_COMPAT_LIST_USE
965 // -----------------------------------------------------------------------------
966 // wxList compatibility class: in fact, it's a list of wxObjects
967 // -----------------------------------------------------------------------------
968 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
, class WXDLLIMPEXP_BASE
);
970 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
973 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
974 wxDEPRECATED( wxList(int key_type
= wxKEY_NONE
) );
976 wxList(int key_type
= wxKEY_NONE
);
979 // this destructor is required for Darwin
983 wxList
& operator=(const wxList
& list
)
984 { (void) wxListBase::operator=(list
); return *this; }
986 // compatibility methods
987 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
992 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
997 DECLARE_DYNAMIC_CLASS(wxList
)
1003 // -----------------------------------------------------------------------------
1004 // wxStringList class for compatibility with the old code
1005 // -----------------------------------------------------------------------------
1006 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1008 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1013 #ifdef wxWARN_COMPAT_LIST_USE
1014 wxDEPRECATED( wxStringList() );
1015 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1018 wxStringList(const wxChar
*first
...);
1021 // copying the string list: the strings are copied, too (extremely
1023 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(TRUE
); DoCopy(other
); }
1024 wxStringList
& operator=(const wxStringList
& other
)
1025 { Clear(); DoCopy(other
); return *this; }
1028 // makes a copy of the string
1029 wxNode
*Add(const wxChar
*s
);
1031 // Append to beginning of list
1032 wxNode
*Prepend(const wxChar
*s
);
1034 bool Delete(const wxChar
*s
);
1036 wxChar
**ListToArray(bool new_copies
= FALSE
) const;
1037 bool Member(const wxChar
*s
) const;
1043 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1045 DECLARE_DYNAMIC_CLASS(wxStringList
)
1048 #else // if wxUSE_STL
1050 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLEXPORT
);
1052 class WXDLLEXPORT wxStringList
: public wxStringListBase
1059 #endif // wxLIST_COMPATIBILITY
1061 // delete all list elements
1063 // NB: the class declaration of the list elements must be visible from the
1064 // place where you use this macro, otherwise the proper destructor may not
1065 // be called (a decent compiler should give a warning about it, but don't
1067 #define WX_CLEAR_LIST(type, list) \
1069 type::iterator it, en; \
1070 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \