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
60 typedef int (* LINKAGEMODE wxSortCompareFunction
)(const void *elem1
, const void *elem2
);
63 class WXDLLIMPEXP_BASE wxObjectListNode
;
64 typedef wxObjectListNode wxNode
;
67 typedef int (* LINKAGEMODE wxListIterateFunction
)(void *current
);
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 #if !defined(wxENUM_KEY_TYPE_DEFINED)
74 #define wxENUM_KEY_TYPE_DEFINED
87 #define wxLIST_COMPATIBILITY
89 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
90 WX_DECLARE_LIST_X(elT, liT, decl)
92 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
93 WX_DECLARE_LIST_X(elT, liT, decl)
95 #define WX_DECLARE_LIST_X(elT, liT, decl) \
96 WX_DECLARE_LIST_XO(elT*, liT, decl)
98 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
99 decl liT : public std::list<elT> \
104 struct compatibility_iterator \
106 typedef std::list<elT>::iterator iterator; \
110 operator bool() const \
111 { return m_list && m_iter != m_list->end(); } \
112 bool operator !() const \
113 { return !m_list || m_iter == m_list->end(); } \
114 compatibility_iterator( const liT* li, iterator it ) \
115 : m_iter( it ), m_list( (liT*)li ) {} \
116 compatibility_iterator( liT* li, iterator it ) \
117 : m_iter( it ), m_list( li ) {} \
118 compatibility_iterator() : m_list( NULL ) { } \
119 dummy* operator->() { return (dummy*)this; } \
120 const dummy* operator->() const { return (const dummy*)this; } \
122 typedef struct compatibility_iterator citer; \
126 typedef std::list<elT>::iterator it; \
127 typedef compatibility_iterator citer; \
129 elT GetData() const \
131 citer* i = (citer*)this; \
132 return *(i->m_iter); \
134 citer GetNext() const \
136 citer* i = (citer*)this; \
137 it lit = i->m_iter; \
138 return citer( i->m_list, ++lit ); \
140 citer GetPrevious() const \
142 citer* i = (citer*)this; \
143 it lit = i->m_iter; \
144 return citer( i->m_list, ++lit ); \
146 void SetData( elT e ) \
148 citer* i = (citer*)this; \
155 iterator find( elT e ) \
158 for( it = begin(), en = end(); it != en; ++it ) \
166 citer Append( elT e ) { push_back( e ); return GetLast(); } \
167 void Clear() { clear(); } \
168 size_t GetCount() const { return size(); } \
169 citer GetFirst() const { return citer( this, ((liT*)this)->begin() ); } \
170 citer GetLast() const { return citer( this, --(((liT*)this)->end()) ); } \
171 bool IsEmpty() const { return empty(); } \
172 bool DeleteObject( elT e ) \
174 iterator it = find( e ); \
182 void Erase( const compatibility_iterator& it ) \
184 erase( it.m_iter ); \
186 citer Find( elT e ) const { return citer( this, ((liT*)this)->find( e ) ); } \
187 citer Member( elT e ) const { return Find( e ); } \
188 citer Insert( elT e ) \
189 { push_front( e ); return citer( this, begin() ); } \
190 citer Insert( size_t idx, elT e ) \
191 { return Insert( Item( idx ), e ); } \
192 citer Insert( citer idx, elT e ) \
193 { return citer( this, insert( idx.m_iter, e ) ); } \
194 citer Item( size_t idx ) const \
197 for( it = ((liT*)this)->begin(); idx; --idx ) \
199 return citer( this, it ); \
201 int IndexOf( elT e ) const \
203 const_iterator it, en; \
205 for( idx = 0, it = begin(), en = end(); it != en; ++it, ++idx ) \
208 return wxNOT_FOUND; \
212 #define WX_DECLARE_LIST(elementtype, listname) \
213 WX_DECLARE_LIST_X(elementtype, listname, class)
215 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
216 WX_DECLARE_LIST_X(elementtype, listname, class WXDLLEXPORT)
218 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
219 WX_DECLARE_LIST_X(elementtype, listname, class usergoo)
221 // this macro must be inserted in your program after
222 // #include <wx/listimpl.cpp>
223 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
225 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
226 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
228 #else // if !wxUSE_STL
230 // due to circular header dependencies this function has to be declared here
231 // (normally it's found in utils.h which includes itself list.h...)
232 extern WXDLLEXPORT wxChar
* copystring(const wxChar
*s
);
234 class WXDLLEXPORT wxObjectListNode
;
235 typedef wxObjectListNode wxNode
;
237 // undef it to get rid of old, deprecated functions
238 #define wxLIST_COMPATIBILITY
240 // -----------------------------------------------------------------------------
241 // key stuff: a list may be optionally keyed on integer or string key
242 // -----------------------------------------------------------------------------
250 // a struct which may contain both types of keys
252 // implementation note: on one hand, this class allows to have only one function
253 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
254 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
255 // wxList::Find(const char *).
256 class WXDLLIMPEXP_BASE wxListKey
260 wxListKey() : m_keyType(wxKEY_NONE
)
262 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
263 { m_key
.integer
= i
; }
264 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
265 { m_key
.string
= wxStrdup(s
); }
266 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
267 { m_key
.string
= wxStrdup(s
.c_str()); }
270 wxKeyType
GetKeyType() const { return m_keyType
; }
271 const wxChar
*GetString() const
272 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
273 long GetNumber() const
274 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
277 // Note: implementation moved to list.cpp to prevent BC++ inline
278 // expansion warning.
279 bool operator==(wxListKeyValue value
) const ;
284 if ( m_keyType
== wxKEY_STRING
)
290 wxListKeyValue m_key
;
293 // -----------------------------------------------------------------------------
294 // wxNodeBase class is a (base for) node in a double linked list
295 // -----------------------------------------------------------------------------
297 WXDLLIMPEXP_DATA_BASE(extern wxListKey
) wxDefaultListKey
;
299 class WXDLLIMPEXP_BASE wxListBase
;
301 class WXDLLIMPEXP_BASE wxNodeBase
303 friend class wxListBase
;
306 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
307 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
308 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
310 const wxListKey
& key
= wxDefaultListKey
);
312 virtual ~wxNodeBase();
314 // FIXME no check is done that the list is really keyed on strings
315 const wxChar
*GetKeyString() const { return m_key
.string
; }
316 long GetKeyInteger() const { return m_key
.integer
; }
318 // Necessary for some existing code
319 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
320 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
322 #ifdef wxLIST_COMPATIBILITY
323 // compatibility methods, use Get* instead.
324 wxDEPRECATED( wxNode
*Next() const );
325 wxDEPRECATED( wxNode
*Previous() const );
326 wxDEPRECATED( wxObject
*Data() const );
327 #endif // wxLIST_COMPATIBILITY
330 // all these are going to be "overloaded" in the derived classes
331 wxNodeBase
*GetNext() const { return m_next
; }
332 wxNodeBase
*GetPrevious() const { return m_previous
; }
334 void *GetData() const { return m_data
; }
335 void SetData(void *data
) { m_data
= data
; }
337 // get 0-based index of this node within the list or wxNOT_FOUND
340 virtual void DeleteData() { }
342 // for wxList::iterator
343 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
345 // optional key stuff
346 wxListKeyValue m_key
;
348 void *m_data
; // user data
349 wxNodeBase
*m_next
, // next and previous nodes in the list
352 wxListBase
*m_list
; // list we belong to
354 DECLARE_NO_COPY_CLASS(wxNodeBase
)
357 // -----------------------------------------------------------------------------
358 // a double-linked list class
359 // -----------------------------------------------------------------------------
363 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
365 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
366 friend class wxHashTableBase
; // should be able to call untyped Find()
368 // common part of all ctors
369 void Init(wxKeyType keyType
= wxKEY_NONE
); // Must be declared before it's used (for VC++ 1.5)
371 // default ctor & dtor
372 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
374 virtual ~wxListBase();
377 // count of items in the list
378 size_t GetCount() const { return m_count
; }
380 // return TRUE if this list is empty
381 bool IsEmpty() const { return m_count
== 0; }
388 // instruct it to destroy user data when deleting nodes
389 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
391 // query if to delete
392 bool GetDeleteContents() const
393 { return m_destroy
; }
396 wxKeyType
GetKeyType() const
397 { return m_keyType
; }
399 // set the keytype (required by the serial code)
400 void SetKeyType(wxKeyType keyType
)
401 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
403 #ifdef wxLIST_COMPATIBILITY
404 // compatibility methods from old wxList
405 wxDEPRECATED( int Number() const ); // use GetCount instead.
406 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
407 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
408 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
410 // kludge for typesafe list migration in core classes.
411 wxDEPRECATED( operator wxList
&() const );
412 #endif // wxLIST_COMPATIBILITY
416 // all methods here are "overloaded" in derived classes to provide compile
417 // time type checking
419 // create a node for the list of this type
420 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
422 const wxListKey
& key
= wxDefaultListKey
) = 0;
424 // Can't access these from derived classes otherwise (bug in Salford C++?)
431 wxListBase(size_t count
, void *elements
[]);
432 // from a sequence of objects
433 wxListBase(void *object
, ... /* terminate with NULL */);
436 // copy ctor and assignment operator
437 wxListBase(const wxListBase
& list
) : wxObject()
438 { Init(); DoCopy(list
); }
439 wxListBase
& operator=(const wxListBase
& list
)
440 { Clear(); DoCopy(list
); return *this; }
442 // get list head/tail
443 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
444 wxNodeBase
*GetLast() const { return m_nodeLast
; }
446 // by (0-based) index
447 wxNodeBase
*Item(size_t index
) const;
449 // get the list item's data
450 void *operator[](size_t n
) const
452 wxNodeBase
*node
= Item(n
);
454 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
458 // append to end of list
459 wxNodeBase
*Prepend(void *object
)
460 { return (wxNodeBase
*)wxListBase::Insert(object
); }
461 // append to beginning of list
462 wxNodeBase
*Append(void *object
);
463 // insert a new item at the beginning of the list
464 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
465 // insert a new item at the given position
466 wxNodeBase
*Insert(size_t pos
, void *object
)
467 { return pos
== GetCount() ? Append(object
)
468 : Insert(Item(pos
), object
); }
469 // insert before given node or at front of list if prev == NULL
470 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
473 wxNodeBase
*Append(long key
, void *object
);
474 wxNodeBase
*Append(const wxChar
*key
, void *object
);
476 // removes node from the list but doesn't delete it (returns pointer
477 // to the node or NULL if it wasn't found in the list)
478 wxNodeBase
*DetachNode(wxNodeBase
*node
);
479 // delete element from list, returns FALSE if node not found
480 bool DeleteNode(wxNodeBase
*node
);
481 // finds object pointer and deletes node (and object if DeleteContents
482 // is on), returns FALSE if object not found
483 bool DeleteObject(void *object
);
485 // search (all return NULL if item not found)
487 wxNodeBase
*Find(void *object
) const;
490 wxNodeBase
*Find(const wxListKey
& key
) const;
492 // get 0-based index of object or wxNOT_FOUND
493 int IndexOf( void *object
) const;
495 // this function allows the sorting of arbitrary lists by giving
496 // a function to compare two list elements. The list is sorted in place.
497 void Sort(const wxSortCompareFunction compfunc
);
499 // functions for iterating over the list
500 void *FirstThat(wxListIterateFunction func
);
501 void ForEach(wxListIterateFunction func
);
502 void *LastThat(wxListIterateFunction func
);
504 // for STL interface, "last" points to one after the last node
505 // of the controlled sequence (NULL for the end of the list)
507 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
510 // common part of copy ctor and assignment operator
511 void DoCopy(const wxListBase
& list
);
512 // common part of all Append()s
513 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
514 // free node's data and node itself
515 void DoDeleteNode(wxNodeBase
*node
);
517 size_t m_count
; // number of elements in the list
518 bool m_destroy
; // destroy user data when deleting list items?
519 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
522 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
525 // -----------------------------------------------------------------------------
526 // macros for definition of "template" list type
527 // -----------------------------------------------------------------------------
529 // and now some heavy magic...
531 // declare a list type named 'name' and containing elements of type 'T *'
532 // (as a by product of macro expansion you also get wx##name##Node
533 // wxNode-derived type)
535 // implementation details:
536 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
537 // for the list of given type - this allows us to pass only the list name
538 // to WX_DEFINE_LIST() even if it needs both the name and the type
540 // 2. We redefine all non-type-safe wxList functions with type-safe versions
541 // which don't take any space (everything is inline), but bring compile
542 // time error checking.
544 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
545 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
546 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
547 // interesting capability to store polymorphic objects in the list and is
548 // particularly useful with, for example, "wxWindow *" list where the
549 // wxWindowBase pointers are put into the list, but wxWindow pointers are
550 // retrieved from it.
552 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
553 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
555 classexp nodetype : public wxNodeBase \
558 nodetype(wxListBase *list = (wxListBase *)NULL, \
559 nodetype *previous = (nodetype *)NULL, \
560 nodetype *next = (nodetype *)NULL, \
561 T *data = (T *)NULL, \
562 const wxListKey& key = wxDefaultListKey) \
563 : wxNodeBase(list, previous, next, data, key) { } \
565 nodetype *GetNext() const \
566 { return (nodetype *)wxNodeBase::GetNext(); } \
567 nodetype *GetPrevious() const \
568 { return (nodetype *)wxNodeBase::GetPrevious(); } \
571 { return (T *)wxNodeBase::GetData(); } \
572 void SetData(T *data) \
573 { wxNodeBase::SetData(data); } \
575 virtual void DeleteData(); \
578 classexp name : public wxListBase \
581 typedef nodetype Node; \
582 typedef Node* compatibility_iterator; \
584 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
586 name(size_t count, T *elements[]) \
587 : wxListBase(count, (void **)elements) { } \
589 name& operator=(const name& list) \
590 { (void) wxListBase::operator=(list); return *this; } \
592 nodetype *GetFirst() const \
593 { return (nodetype *)wxListBase::GetFirst(); } \
594 nodetype *GetLast() const \
595 { return (nodetype *)wxListBase::GetLast(); } \
597 nodetype *Item(size_t index) const \
598 { return (nodetype *)wxListBase::Item(index); } \
600 T *operator[](size_t index) const \
602 nodetype *node = Item(index); \
603 return node ? (T*)(node->GetData()) : (T*)NULL; \
606 nodetype *Append(Tbase *object) \
607 { return (nodetype *)wxListBase::Append(object); } \
608 nodetype *Insert(Tbase *object) \
609 { return (nodetype *)Insert((nodetype*)NULL, object); } \
610 nodetype *Insert(size_t pos, Tbase *object) \
611 { return (nodetype *)wxListBase::Insert(pos, object); } \
612 nodetype *Insert(nodetype *prev, Tbase *object) \
613 { return (nodetype *)wxListBase::Insert(prev, object); } \
615 nodetype *Append(long key, void *object) \
616 { return (nodetype *)wxListBase::Append(key, object); } \
617 nodetype *Append(const wxChar *key, void *object) \
618 { return (nodetype *)wxListBase::Append(key, object); } \
620 nodetype *DetachNode(nodetype *node) \
621 { return (nodetype *)wxListBase::DetachNode(node); } \
622 bool DeleteNode(nodetype *node) \
623 { return wxListBase::DeleteNode(node); } \
624 bool DeleteObject(Tbase *object) \
625 { return wxListBase::DeleteObject(object); } \
626 void Erase(compatibility_iterator it) \
627 { DeleteNode(it); } \
629 nodetype *Find(Tbase *object) const \
630 { return (nodetype *)wxListBase::Find(object); } \
632 virtual nodetype *Find(const wxListKey& key) const \
633 { return (nodetype *)wxListBase::Find(key); } \
635 int IndexOf(Tbase *object) const \
636 { return wxListBase::IndexOf(object); } \
638 void Sort(wxSortFuncFor_##name func) \
639 { wxListBase::Sort((wxSortCompareFunction)func); } \
642 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
644 const wxListKey& key = wxDefaultListKey) \
646 return new nodetype(this, \
647 (nodetype *)prev, (nodetype *)next, \
650 /* STL interface */ \
652 typedef size_t size_type; \
653 typedef int difference_type; \
654 typedef T* value_type; \
655 typedef Tbase* base_value_type; \
656 typedef value_type& reference; \
657 typedef const value_type& const_reference; \
658 typedef base_value_type& base_reference; \
659 typedef const base_value_type& const_base_reference; \
665 typedef nodetype Node; \
666 typedef iterator itor; \
667 typedef T* value_type; \
668 typedef value_type* ptr_type; \
669 typedef value_type& reference; \
674 typedef reference reference_type; \
675 typedef ptr_type pointer_type; \
677 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
678 iterator() : m_node(NULL), m_init(NULL) { } \
679 reference_type operator*() const \
680 { return *(pointer_type)m_node->GetDataPtr(); } \
681 pointer_type operator->() const \
682 { return (pointer_type)m_node->GetDataPtr(); } \
683 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
684 itor operator++(int) \
685 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
688 m_node = m_node ? m_node->GetPrevious() : m_init; \
691 itor operator--(int) \
694 m_node = m_node ? m_node->GetPrevious() : m_init; \
697 bool operator!=(const itor& it) const \
698 { return it.m_node != m_node; } \
699 bool operator==(const itor& it) const \
700 { return it.m_node == m_node; } \
702 class const_iterator \
706 typedef nodetype Node; \
707 typedef T* value_type; \
708 typedef const value_type& const_reference; \
709 typedef const_iterator itor; \
710 typedef value_type* ptr_type; \
715 typedef const_reference reference_type; \
716 typedef const ptr_type pointer_type; \
718 const_iterator(Node* node, Node* init) \
719 : m_node(node), m_init(init) { } \
720 const_iterator() : m_node(NULL), m_init(NULL) { } \
721 const_iterator(const iterator& it) \
722 : m_node(it.m_node), m_init(it.m_init) { } \
723 reference_type operator*() const \
724 { return *(pointer_type)m_node->GetDataPtr(); } \
725 pointer_type operator->() const \
726 { return (pointer_type)m_node->GetDataPtr(); } \
727 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
728 itor operator++(int) \
729 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
732 m_node = m_node ? m_node->GetPrevious() : m_init; \
735 itor operator--(int) \
738 m_node = m_node ? m_node->GetPrevious() : m_init; \
741 bool operator!=(const itor& it) const \
742 { return it.m_node != m_node; } \
743 bool operator==(const itor& it) const \
744 { return it.m_node == m_node; } \
746 class reverse_iterator \
750 typedef nodetype Node; \
751 typedef T* value_type; \
752 typedef reverse_iterator itor; \
753 typedef value_type* ptr_type; \
754 typedef value_type& reference; \
759 typedef reference reference_type; \
760 typedef ptr_type pointer_type; \
762 reverse_iterator(Node* node, Node* init) \
763 : m_node(node), m_init(init) { } \
764 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
765 reference_type operator*() const \
766 { return *(pointer_type)m_node->GetDataPtr(); } \
767 pointer_type operator->() const \
768 { return (pointer_type)m_node->GetDataPtr(); } \
770 { m_node = m_node->GetPrevious(); return *this; } \
771 itor operator++(int) \
772 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
774 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
775 itor operator--(int) \
778 m_node = m_node ? m_node->GetNext() : m_init; \
781 bool operator!=(const itor& it) const \
782 { return it.m_node != m_node; } \
783 bool operator==(const itor& it) const \
784 { return it.m_node == m_node; } \
786 class const_reverse_iterator \
790 typedef nodetype Node; \
791 typedef T* value_type; \
792 typedef const_reverse_iterator itor; \
793 typedef value_type* ptr_type; \
794 typedef const value_type& const_reference; \
799 typedef const_reference reference_type; \
800 typedef const ptr_type pointer_type; \
802 const_reverse_iterator(Node* node, Node* init) \
803 : m_node(node), m_init(init) { } \
804 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
805 const_reverse_iterator(const reverse_iterator& it) \
806 : m_node(it.m_node), m_init(it.m_init) { } \
807 reference_type operator*() const \
808 { return *(pointer_type)m_node->GetDataPtr(); } \
809 pointer_type operator->() const \
810 { return (pointer_type)m_node->GetDataPtr(); } \
812 { m_node = m_node->GetPrevious(); return *this; } \
813 itor operator++(int) \
814 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
816 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
817 itor operator--(int) \
820 m_node = m_node ? m_node->GetNext() : m_init; \
823 bool operator!=(const itor& it) const \
824 { return it.m_node != m_node; } \
825 bool operator==(const itor& it) const \
826 { return it.m_node == m_node; } \
829 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
831 name(const_iterator first, const_iterator last) \
832 { assign(first, last); } \
833 iterator begin() { return iterator(GetFirst(), GetLast()); } \
834 const_iterator begin() const \
835 { return const_iterator(GetFirst(), GetLast()); } \
836 iterator end() { return iterator(NULL, GetLast()); } \
837 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
838 reverse_iterator rbegin() \
839 { return reverse_iterator(GetLast(), GetFirst()); } \
840 const_reverse_iterator rbegin() const \
841 { return const_reverse_iterator(GetLast(), GetFirst()); } \
842 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
843 const_reverse_iterator rend() const \
844 { return const_reverse_iterator(NULL, GetFirst()); } \
845 void resize(size_type n, value_type v = value_type()) \
848 for(; n < size(); pop_back()); \
849 else if(n > size()) \
850 for(; n > size(); push_back(v)); \
852 size_type size() const { return GetCount(); } \
853 size_type max_size() const { return INT_MAX; } \
854 bool empty() const { return IsEmpty(); } \
855 reference front() { return *begin(); } \
856 const_reference front() const { return *begin(); } \
857 reference back() { return *--end(); } \
858 const_reference back() const { return *--end(); } \
859 void push_front(const_reference v = value_type()) \
860 { Insert(GetFirst(), (const_base_reference)v); } \
861 void pop_front() { DeleteNode(GetFirst()); } \
862 void push_back(const_reference v = value_type()) \
863 { Append((const_base_reference)v); } \
864 void pop_back() { DeleteNode(GetLast()); } \
865 void assign(const_iterator first, const_iterator last) \
868 for(; first != last; ++first) \
869 Append((const_base_reference)*first); \
871 void assign(size_type n, const_reference v = value_type()) \
874 for(size_type i = 0; i < n; ++i) \
875 Append((const_base_reference)v); \
877 iterator insert(iterator it, const_reference v = value_type()) \
879 Insert(it.m_node, (const_base_reference)v); \
880 return iterator(it.m_node->GetPrevious(), GetLast()); \
882 void insert(iterator it, size_type n, const_reference v = value_type())\
884 for(size_type i = 0; i < n; ++i) \
885 Insert(it.m_node, (const_base_reference)v); \
887 void insert(iterator it, const_iterator first, const_iterator last) \
889 for(; first != last; ++first) \
890 Insert(it.m_node, (const_base_reference)*first); \
892 iterator erase(iterator it) \
894 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
895 DeleteNode(it.m_node); return next; \
897 iterator erase(iterator first, iterator last) \
899 iterator next = last; ++next; \
900 DeleteNodes(first.m_node, last.m_node); \
903 void clear() { Clear(); } \
904 void splice(iterator it, name& l, iterator first, iterator last) \
905 { insert(it, first, last); l.erase(first, last); } \
906 void splice(iterator it, name& l) \
907 { splice(it, l, l.begin(), l.end() ); } \
908 void splice(iterator it, name& l, iterator first) \
910 iterator tmp = first; ++tmp; \
911 if(it == first || it == tmp) return; \
912 insert(it, *first); \
915 void remove(const_reference v) \
916 { DeleteObject((const_base_reference)v); } \
919 /* void swap(name& l) \
921 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
922 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
923 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
924 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
925 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
929 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
930 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
932 #define WX_DECLARE_LIST(elementtype, listname) \
933 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
934 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
936 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
937 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
938 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
940 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
941 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
942 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
944 // this macro must be inserted in your program after
945 // #include <wx/listimpl.cpp>
946 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
948 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
949 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
953 // =============================================================================
954 // now we can define classes 100% compatible with the old ones
955 // =============================================================================
957 // ----------------------------------------------------------------------------
958 // commonly used list classes
959 // ----------------------------------------------------------------------------
961 #ifdef wxLIST_COMPATIBILITY
963 // define this to make a lot of noise about use of the old wxList classes.
964 //#define wxWARN_COMPAT_LIST_USE
966 // -----------------------------------------------------------------------------
967 // wxList compatibility class: in fact, it's a list of wxObjects
968 // -----------------------------------------------------------------------------
969 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
, class WXDLLIMPEXP_BASE
);
971 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
974 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
975 wxDEPRECATED( wxList(int key_type
= wxKEY_NONE
) );
977 wxList(int key_type
= wxKEY_NONE
);
980 // this destructor is required for Darwin
984 wxList
& operator=(const wxList
& list
)
985 { (void) wxListBase::operator=(list
); return *this; }
987 // compatibility methods
988 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
993 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
998 DECLARE_DYNAMIC_CLASS(wxList
)
1004 // -----------------------------------------------------------------------------
1005 // wxStringList class for compatibility with the old code
1006 // -----------------------------------------------------------------------------
1007 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1009 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1014 #ifdef wxWARN_COMPAT_LIST_USE
1015 wxDEPRECATED( wxStringList() );
1016 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1019 wxStringList(const wxChar
*first
...);
1022 // copying the string list: the strings are copied, too (extremely
1024 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(TRUE
); DoCopy(other
); }
1025 wxStringList
& operator=(const wxStringList
& other
)
1026 { Clear(); DoCopy(other
); return *this; }
1029 // makes a copy of the string
1030 wxNode
*Add(const wxChar
*s
);
1032 // Append to beginning of list
1033 wxNode
*Prepend(const wxChar
*s
);
1035 bool Delete(const wxChar
*s
);
1037 wxChar
**ListToArray(bool new_copies
= FALSE
) const;
1038 bool Member(const wxChar
*s
) const;
1044 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1046 DECLARE_DYNAMIC_CLASS(wxStringList
)
1049 #else // if wxUSE_STL
1051 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLEXPORT
);
1053 class WXDLLEXPORT wxStringList
: public wxStringListBase
1056 compatibility_iterator
Append(wxChar
* s
)
1057 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1058 compatibility_iterator
Insert(wxChar
* s
)
1059 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1060 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1064 return wxStringListBase::Insert(pos
, tmp
);
1066 compatibility_iterator
Add(const wxChar
* s
)
1067 { push_back(s
); return GetLast(); }
1068 compatibility_iterator
Prepend(const wxChar
* s
)
1069 { push_front(s
); return GetFirst(); }
1074 #endif // wxLIST_COMPATIBILITY
1076 // delete all list elements
1078 // NB: the class declaration of the list elements must be visible from the
1079 // place where you use this macro, otherwise the proper destructor may not
1080 // be called (a decent compiler should give a warning about it, but don't
1082 #define WX_CLEAR_LIST(type, list) \
1084 type::iterator it, en; \
1085 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \