]> git.saurik.com Git - wxWidgets.git/blame_incremental - include/wx/list.h
wxDC rework, forgot these
[wxWidgets.git] / include / wx / list.h
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/list.h
3// Purpose: wxList, wxStringList classes
4// Author: Julian Smart
5// Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12/*
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
16
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
22 like the old class.
23*/
24
25#ifndef _WX_LISTH__
26#define _WX_LISTH__
27
28// -----------------------------------------------------------------------------
29// headers
30// -----------------------------------------------------------------------------
31
32#include "wx/defs.h"
33#include "wx/object.h"
34#include "wx/string.h"
35
36#if wxUSE_STL
37 #include "wx/beforestd.h"
38 #include <algorithm>
39 #include <iterator>
40 #include <list>
41 #include "wx/afterstd.h"
42#endif
43
44// ----------------------------------------------------------------------------
45// types
46// ----------------------------------------------------------------------------
47
48// type of compare function for list sort operation (as in 'qsort'): it should
49// return a negative value, 0 or positive value if the first element is less
50// than, equal or greater than the second
51
52extern "C"
53{
54typedef int (* LINKAGEMODE wxSortCompareFunction)(const void *elem1, const void *elem2);
55}
56
57class WXDLLIMPEXP_FWD_BASE wxObjectListNode;
58typedef wxObjectListNode wxNode;
59
60//
61typedef int (* LINKAGEMODE wxListIterateFunction)(void *current);
62
63#if wxUSE_STL
64
65#define wxLIST_COMPATIBILITY
66
67#define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
68 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
69#define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
70 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
71
72#define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
73 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
74#define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
75 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
76
77#define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
78 WX_DECLARE_LIST_XO(elT*, liT, decl)
79
80#if !defined(__VISUALC__) || __VISUALC__ >= 1300 // == !VC6
81
82template<class T>
83class WXDLLIMPEXP_BASE wxList_SortFunction
84{
85public:
86 wxList_SortFunction(wxSortCompareFunction f) : m_f(f) { }
87 bool operator()(const T& i1, const T& i2)
88 { return m_f((T*)&i1, (T*)&i2) < 0; }
89private:
90 wxSortCompareFunction m_f;
91};
92
93#define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
94#define WX_LIST_VC6_WORKAROUND(elT, liT, decl)
95
96#else // if defined( __VISUALC__ ) && __VISUALC__ < 1300 // == VC6
97
98#define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
99#define WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
100 decl liT; \
101 \
102 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
103 /* to be passed into std::list::sort() */ \
104 template <> \
105 struct std::greater<elT> \
106 { \
107 private: \
108 wxSortCompareFunction m_CompFunc; \
109 public: \
110 greater( wxSortCompareFunction compfunc = NULL ) \
111 : m_CompFunc( compfunc ) {} \
112 bool operator()(const elT X, const elT Y) const \
113 { \
114 return m_CompFunc ? \
115 ( m_CompFunc( wxListCastElementToVoidPtr(X), \
116 wxListCastElementToVoidPtr(Y) ) < 0 ) : \
117 ( X > Y ); \
118 } \
119 };
120
121// helper for std::greater<elT> above:
122template<typename T>
123inline const void *wxListCastElementToVoidPtr(const T* ptr) { return ptr; }
124inline const void *wxListCastElementToVoidPtr(const wxString& str)
125 { return (const char*)str; }
126
127#endif // VC6/!VC6
128
129/*
130 Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround
131 for mingw 3.2.3 compiler bug that prevents a static function of liT class
132 from being exported into dll. A minimal code snippet reproducing the bug:
133
134 struct WXDLLEXPORT Foo
135 {
136 static void Bar();
137 struct SomeInnerClass
138 {
139 friend class Foo; // comment this out to make it link
140 };
141 ~Foo()
142 {
143 Bar();
144 }
145 };
146
147 The program does not link under mingw_gcc 3.2.3 producing undefined
148 reference to Foo::Bar() function
149
150
151 Note 2: the EmptyList is needed to allow having a NULL pointer-like
152 invalid iterator. We used to use just an uninitialized iterator object
153 instead but this fails with some debug/checked versions of STL, notably the
154 glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate
155 invalid iterator.
156 */
157
158// the real wxList-class declaration
159#define WX_DECLARE_LIST_XO(elT, liT, decl) \
160 decl _WX_LIST_HELPER_##liT \
161 { \
162 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
163 public: \
164 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
165 }; \
166 \
167 WX_LIST_VC6_WORKAROUND(elT, liT, decl) \
168 decl liT : public std::list<elT> \
169 { \
170 private: \
171 typedef std::list<elT> BaseListType; \
172 static BaseListType EmptyList; \
173 \
174 bool m_destroy; \
175 \
176 public: \
177 decl compatibility_iterator \
178 { \
179 private: \
180 /* Workaround for broken VC6 nested class name resolution */ \
181 typedef std::list<elT>::iterator iterator; \
182 friend class liT; \
183 \
184 iterator m_iter; \
185 liT * m_list; \
186 \
187 public: \
188 compatibility_iterator() \
189 : m_iter(EmptyList.end()), m_list( NULL ) {} \
190 compatibility_iterator( liT* li, iterator i ) \
191 : m_iter( i ), m_list( li ) {} \
192 compatibility_iterator( const liT* li, iterator i ) \
193 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
194 \
195 compatibility_iterator* operator->() { return this; } \
196 const compatibility_iterator* operator->() const { return this; } \
197 \
198 bool operator==(const compatibility_iterator& i) const \
199 { \
200 wxASSERT_MSG( m_list && i.m_list, \
201 _T("comparing invalid iterators is illegal") ); \
202 return (m_list == i.m_list) && (m_iter == i.m_iter); \
203 } \
204 bool operator!=(const compatibility_iterator& i) const \
205 { return !( operator==( i ) ); } \
206 operator bool() const \
207 { return m_list ? m_iter != m_list->end() : false; } \
208 bool operator !() const \
209 { return !( operator bool() ); } \
210 \
211 elT GetData() const \
212 { return *m_iter; } \
213 void SetData( elT e ) \
214 { *m_iter = e; } \
215 \
216 compatibility_iterator GetNext() const \
217 { \
218 iterator i = m_iter; \
219 return compatibility_iterator( m_list, ++i ); \
220 } \
221 compatibility_iterator GetPrevious() const \
222 { \
223 if ( m_iter == m_list->begin() ) \
224 return compatibility_iterator(); \
225 \
226 iterator i = m_iter; \
227 return compatibility_iterator( m_list, --i ); \
228 } \
229 int IndexOf() const \
230 { \
231 return *this ? std::distance( m_list->begin(), m_iter ) \
232 : wxNOT_FOUND; \
233 } \
234 }; \
235 public: \
236 liT() : m_destroy( false ) {} \
237 \
238 compatibility_iterator Find( const elT e ) const \
239 { \
240 liT* _this = const_cast< liT* >( this ); \
241 return compatibility_iterator( _this, \
242 std::find( _this->begin(), _this->end(), e ) ); \
243 } \
244 \
245 bool IsEmpty() const \
246 { return empty(); } \
247 size_t GetCount() const \
248 { return size(); } \
249 int Number() const \
250 { return static_cast< int >( GetCount() ); } \
251 \
252 compatibility_iterator Item( size_t idx ) const \
253 { \
254 iterator i = const_cast< liT* >(this)->begin(); \
255 std::advance( i, idx ); \
256 return compatibility_iterator( this, i ); \
257 } \
258 elT operator[](size_t idx) const \
259 { \
260 return Item(idx).GetData(); \
261 } \
262 \
263 compatibility_iterator GetFirst() const \
264 { \
265 return compatibility_iterator( this, \
266 const_cast< liT* >(this)->begin() ); \
267 } \
268 compatibility_iterator GetLast() const \
269 { \
270 iterator i = const_cast< liT* >(this)->end(); \
271 return compatibility_iterator( this, !empty() ? --i : i ); \
272 } \
273 compatibility_iterator Member( elT e ) const \
274 { return Find( e ); } \
275 compatibility_iterator Nth( int n ) const \
276 { return Item( n ); } \
277 int IndexOf( elT e ) const \
278 { return Find( e ).IndexOf(); } \
279 \
280 compatibility_iterator Append( elT e ) \
281 { \
282 push_back( e ); \
283 return GetLast(); \
284 } \
285 compatibility_iterator Insert( elT e ) \
286 { \
287 push_front( e ); \
288 return compatibility_iterator( this, begin() ); \
289 } \
290 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
291 { \
292 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
293 } \
294 compatibility_iterator Insert( size_t idx, elT e ) \
295 { \
296 return compatibility_iterator( this, \
297 insert( Item( idx ).m_iter, e ) ); \
298 } \
299 \
300 void DeleteContents( bool destroy ) \
301 { m_destroy = destroy; } \
302 bool GetDeleteContents() const \
303 { return m_destroy; } \
304 void Erase( const compatibility_iterator& i ) \
305 { \
306 if ( m_destroy ) \
307 _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \
308 erase( i.m_iter ); \
309 } \
310 bool DeleteNode( const compatibility_iterator& i ) \
311 { \
312 if( i ) \
313 { \
314 Erase( i ); \
315 return true; \
316 } \
317 return false; \
318 } \
319 bool DeleteObject( elT e ) \
320 { \
321 return DeleteNode( Find( e ) ); \
322 } \
323 void Clear() \
324 { \
325 if ( m_destroy ) \
326 std::for_each( begin(), end(), \
327 _WX_LIST_HELPER_##liT::DeleteFunction ); \
328 clear(); \
329 } \
330 /* Workaround for broken VC6 std::list::sort() see above */ \
331 void Sort( wxSortCompareFunction compfunc ) \
332 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
333 ~liT() { Clear(); } \
334 \
335 /* It needs access to our EmptyList */ \
336 friend class compatibility_iterator; \
337 }
338
339#define WX_DECLARE_LIST(elementtype, listname) \
340 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
341#define WX_DECLARE_LIST_PTR(elementtype, listname) \
342 WX_DECLARE_LIST(elementtype, listname)
343
344#define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
345 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
346#define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
347 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
348
349#define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
350 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
351#define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
352 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
353
354// this macro must be inserted in your program after
355// #include "wx/listimpl.cpp"
356#define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
357
358#define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
359#define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
360
361#else // if !wxUSE_STL
362
363
364// undef it to get rid of old, deprecated functions
365#define wxLIST_COMPATIBILITY
366
367// -----------------------------------------------------------------------------
368// key stuff: a list may be optionally keyed on integer or string key
369// -----------------------------------------------------------------------------
370
371union wxListKeyValue
372{
373 long integer;
374 wxString *string;
375};
376
377// a struct which may contain both types of keys
378//
379// implementation note: on one hand, this class allows to have only one function
380// for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
381// resolve ambiguity which we would otherwise have with wxStringList::Find() and
382// wxList::Find(const char *).
383class WXDLLIMPEXP_BASE wxListKey
384{
385public:
386 // implicit ctors
387 wxListKey() : m_keyType(wxKEY_NONE)
388 { }
389 wxListKey(long i) : m_keyType(wxKEY_INTEGER)
390 { m_key.integer = i; }
391 wxListKey(const wxString& s) : m_keyType(wxKEY_STRING)
392 { m_key.string = new wxString(s); }
393 wxListKey(const char *s) : m_keyType(wxKEY_STRING)
394 { m_key.string = new wxString(s); }
395 wxListKey(const wchar_t *s) : m_keyType(wxKEY_STRING)
396 { m_key.string = new wxString(s); }
397
398 // accessors
399 wxKeyType GetKeyType() const { return m_keyType; }
400 const wxString GetString() const
401 { wxASSERT( m_keyType == wxKEY_STRING ); return *m_key.string; }
402 long GetNumber() const
403 { wxASSERT( m_keyType == wxKEY_INTEGER ); return m_key.integer; }
404
405 // comparison
406 // Note: implementation moved to list.cpp to prevent BC++ inline
407 // expansion warning.
408 bool operator==(wxListKeyValue value) const ;
409
410 // dtor
411 ~wxListKey()
412 {
413 if ( m_keyType == wxKEY_STRING )
414 delete m_key.string;
415 }
416
417private:
418 wxKeyType m_keyType;
419 wxListKeyValue m_key;
420};
421
422// -----------------------------------------------------------------------------
423// wxNodeBase class is a (base for) node in a double linked list
424// -----------------------------------------------------------------------------
425
426extern WXDLLIMPEXP_DATA_BASE(wxListKey) wxDefaultListKey;
427
428class WXDLLIMPEXP_FWD_BASE wxListBase;
429
430class WXDLLIMPEXP_BASE wxNodeBase
431{
432friend class wxListBase;
433public:
434 // ctor
435 wxNodeBase(wxListBase *list = (wxListBase *)NULL,
436 wxNodeBase *previous = (wxNodeBase *)NULL,
437 wxNodeBase *next = (wxNodeBase *)NULL,
438 void *data = NULL,
439 const wxListKey& key = wxDefaultListKey);
440
441 virtual ~wxNodeBase();
442
443 // FIXME no check is done that the list is really keyed on strings
444 wxString GetKeyString() const { return *m_key.string; }
445 long GetKeyInteger() const { return m_key.integer; }
446
447 // Necessary for some existing code
448 void SetKeyString(const wxString& s) { m_key.string = new wxString(s); }
449 void SetKeyInteger(long i) { m_key.integer = i; }
450
451#ifdef wxLIST_COMPATIBILITY
452 // compatibility methods, use Get* instead.
453 wxDEPRECATED( wxNode *Next() const );
454 wxDEPRECATED( wxNode *Previous() const );
455 wxDEPRECATED( wxObject *Data() const );
456#endif // wxLIST_COMPATIBILITY
457
458protected:
459 // all these are going to be "overloaded" in the derived classes
460 wxNodeBase *GetNext() const { return m_next; }
461 wxNodeBase *GetPrevious() const { return m_previous; }
462
463 void *GetData() const { return m_data; }
464 void SetData(void *data) { m_data = data; }
465
466 // get 0-based index of this node within the list or wxNOT_FOUND
467 int IndexOf() const;
468
469 virtual void DeleteData() { }
470public:
471 // for wxList::iterator
472 void** GetDataPtr() const { return &(((wxNodeBase*)this)->m_data); }
473private:
474 // optional key stuff
475 wxListKeyValue m_key;
476
477 void *m_data; // user data
478 wxNodeBase *m_next, // next and previous nodes in the list
479 *m_previous;
480
481 wxListBase *m_list; // list we belong to
482
483 DECLARE_NO_COPY_CLASS(wxNodeBase)
484};
485
486// -----------------------------------------------------------------------------
487// a double-linked list class
488// -----------------------------------------------------------------------------
489
490class WXDLLIMPEXP_FWD_BASE wxList;
491
492class WXDLLIMPEXP_BASE wxListBase
493{
494friend class wxNodeBase; // should be able to call DetachNode()
495friend class wxHashTableBase; // should be able to call untyped Find()
496
497public:
498 // default ctor & dtor
499 wxListBase(wxKeyType keyType = wxKEY_NONE)
500 { Init(keyType); }
501 virtual ~wxListBase();
502
503 // accessors
504 // count of items in the list
505 size_t GetCount() const { return m_count; }
506
507 // return true if this list is empty
508 bool IsEmpty() const { return m_count == 0; }
509
510 // operations
511
512 // delete all nodes
513 void Clear();
514
515 // instruct it to destroy user data when deleting nodes
516 void DeleteContents(bool destroy) { m_destroy = destroy; }
517
518 // query if to delete
519 bool GetDeleteContents() const
520 { return m_destroy; }
521
522 // get the keytype
523 wxKeyType GetKeyType() const
524 { return m_keyType; }
525
526 // set the keytype (required by the serial code)
527 void SetKeyType(wxKeyType keyType)
528 { wxASSERT( m_count==0 ); m_keyType = keyType; }
529
530#ifdef wxLIST_COMPATIBILITY
531 // compatibility methods from old wxList
532 wxDEPRECATED( int Number() const ); // use GetCount instead.
533 wxDEPRECATED( wxNode *First() const ); // use GetFirst
534 wxDEPRECATED( wxNode *Last() const ); // use GetLast
535 wxDEPRECATED( wxNode *Nth(size_t n) const ); // use Item
536
537 // kludge for typesafe list migration in core classes.
538 wxDEPRECATED( operator wxList&() const );
539#endif // wxLIST_COMPATIBILITY
540
541protected:
542
543 // all methods here are "overloaded" in derived classes to provide compile
544 // time type checking
545
546 // create a node for the list of this type
547 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next,
548 void *data,
549 const wxListKey& key = wxDefaultListKey) = 0;
550
551// Can't access these from derived classes otherwise (bug in Salford C++?)
552#ifdef __SALFORDC__
553public:
554#endif
555
556 // ctors
557 // from an array
558 wxListBase(size_t count, void *elements[]);
559 // from a sequence of objects
560 wxListBase(void *object, ... /* terminate with NULL */);
561
562protected:
563 void Assign(const wxListBase& list)
564 { Clear(); DoCopy(list); }
565
566 // get list head/tail
567 wxNodeBase *GetFirst() const { return m_nodeFirst; }
568 wxNodeBase *GetLast() const { return m_nodeLast; }
569
570 // by (0-based) index
571 wxNodeBase *Item(size_t index) const;
572
573 // get the list item's data
574 void *operator[](size_t n) const
575 {
576 wxNodeBase *node = Item(n);
577
578 return node ? node->GetData() : (wxNodeBase *)NULL;
579 }
580
581 // operations
582 // append to end of list
583 wxNodeBase *Prepend(void *object)
584 { return (wxNodeBase *)wxListBase::Insert(object); }
585 // append to beginning of list
586 wxNodeBase *Append(void *object);
587 // insert a new item at the beginning of the list
588 wxNodeBase *Insert(void *object) { return Insert( (wxNodeBase*)NULL, object); }
589 // insert a new item at the given position
590 wxNodeBase *Insert(size_t pos, void *object)
591 { return pos == GetCount() ? Append(object)
592 : Insert(Item(pos), object); }
593 // insert before given node or at front of list if prev == NULL
594 wxNodeBase *Insert(wxNodeBase *prev, void *object);
595
596 // keyed append
597 wxNodeBase *Append(long key, void *object);
598 wxNodeBase *Append(const wxString& key, void *object);
599
600 // removes node from the list but doesn't delete it (returns pointer
601 // to the node or NULL if it wasn't found in the list)
602 wxNodeBase *DetachNode(wxNodeBase *node);
603 // delete element from list, returns false if node not found
604 bool DeleteNode(wxNodeBase *node);
605 // finds object pointer and deletes node (and object if DeleteContents
606 // is on), returns false if object not found
607 bool DeleteObject(void *object);
608
609 // search (all return NULL if item not found)
610 // by data
611 wxNodeBase *Find(const void *object) const;
612
613 // by key
614 wxNodeBase *Find(const wxListKey& key) const;
615
616 // get 0-based index of object or wxNOT_FOUND
617 int IndexOf( void *object ) const;
618
619 // this function allows the sorting of arbitrary lists by giving
620 // a function to compare two list elements. The list is sorted in place.
621 void Sort(const wxSortCompareFunction compfunc);
622
623 // functions for iterating over the list
624 void *FirstThat(wxListIterateFunction func);
625 void ForEach(wxListIterateFunction func);
626 void *LastThat(wxListIterateFunction func);
627
628 // for STL interface, "last" points to one after the last node
629 // of the controlled sequence (NULL for the end of the list)
630 void Reverse();
631 void DeleteNodes(wxNodeBase* first, wxNodeBase* last);
632private:
633
634 // common part of all ctors
635 void Init(wxKeyType keyType = wxKEY_NONE);
636
637 // helpers
638 // common part of copy ctor and assignment operator
639 void DoCopy(const wxListBase& list);
640 // common part of all Append()s
641 wxNodeBase *AppendCommon(wxNodeBase *node);
642 // free node's data and node itself
643 void DoDeleteNode(wxNodeBase *node);
644
645 size_t m_count; // number of elements in the list
646 bool m_destroy; // destroy user data when deleting list items?
647 wxNodeBase *m_nodeFirst, // pointers to the head and tail of the list
648 *m_nodeLast;
649
650 wxKeyType m_keyType; // type of our keys (may be wxKEY_NONE)
651};
652
653// -----------------------------------------------------------------------------
654// macros for definition of "template" list type
655// -----------------------------------------------------------------------------
656
657// and now some heavy magic...
658
659// declare a list type named 'name' and containing elements of type 'T *'
660// (as a by product of macro expansion you also get wx##name##Node
661// wxNode-derived type)
662//
663// implementation details:
664// 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
665// for the list of given type - this allows us to pass only the list name
666// to WX_DEFINE_LIST() even if it needs both the name and the type
667//
668// 2. We redefine all non-type-safe wxList functions with type-safe versions
669// which don't take any space (everything is inline), but bring compile
670// time error checking.
671//
672// 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
673// a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
674// generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
675// interesting capability to store polymorphic objects in the list and is
676// particularly useful with, for example, "wxWindow *" list where the
677// wxWindowBase pointers are put into the list, but wxWindow pointers are
678// retrieved from it.
679//
680// 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
681// WX_DECLARE_LIST_4 to allow defining classes without operator->() as
682// it results in compiler warnings when this operator doesn't make sense
683// (i.e. stored elements are not pointers)
684
685// common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
686#define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
687 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
688 \
689 classexp nodetype : public wxNodeBase \
690 { \
691 public: \
692 nodetype(wxListBase *list = (wxListBase *)NULL, \
693 nodetype *previous = (nodetype *)NULL, \
694 nodetype *next = (nodetype *)NULL, \
695 T *data = (T *)NULL, \
696 const wxListKey& key = wxDefaultListKey) \
697 : wxNodeBase(list, previous, next, data, key) { } \
698 \
699 nodetype *GetNext() const \
700 { return (nodetype *)wxNodeBase::GetNext(); } \
701 nodetype *GetPrevious() const \
702 { return (nodetype *)wxNodeBase::GetPrevious(); } \
703 \
704 T *GetData() const \
705 { return (T *)wxNodeBase::GetData(); } \
706 void SetData(T *data) \
707 { wxNodeBase::SetData(data); } \
708 \
709 protected: \
710 virtual void DeleteData(); \
711 \
712 DECLARE_NO_COPY_CLASS(nodetype) \
713 }; \
714 \
715 classexp name : public wxListBase \
716 { \
717 public: \
718 typedef nodetype Node; \
719 classexp compatibility_iterator \
720 { \
721 public: \
722 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
723 \
724 Node *operator->() const { return m_ptr; } \
725 operator Node *() const { return m_ptr; } \
726 \
727 private: \
728 Node *m_ptr; \
729 }; \
730 \
731 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
732 { } \
733 name(const name& list) : wxListBase(list.GetKeyType()) \
734 { Assign(list); } \
735 name(size_t count, T *elements[]) \
736 : wxListBase(count, (void **)elements) { } \
737 \
738 name& operator=(const name& list) \
739 { Assign(list); return *this; } \
740 \
741 nodetype *GetFirst() const \
742 { return (nodetype *)wxListBase::GetFirst(); } \
743 nodetype *GetLast() const \
744 { return (nodetype *)wxListBase::GetLast(); } \
745 \
746 nodetype *Item(size_t index) const \
747 { return (nodetype *)wxListBase::Item(index); } \
748 \
749 T *operator[](size_t index) const \
750 { \
751 nodetype *node = Item(index); \
752 return node ? (T*)(node->GetData()) : (T*)NULL; \
753 } \
754 \
755 nodetype *Append(Tbase *object) \
756 { return (nodetype *)wxListBase::Append(object); } \
757 nodetype *Insert(Tbase *object) \
758 { return (nodetype *)Insert((nodetype*)NULL, object); } \
759 nodetype *Insert(size_t pos, Tbase *object) \
760 { return (nodetype *)wxListBase::Insert(pos, object); } \
761 nodetype *Insert(nodetype *prev, Tbase *object) \
762 { return (nodetype *)wxListBase::Insert(prev, object); } \
763 \
764 nodetype *Append(long key, void *object) \
765 { return (nodetype *)wxListBase::Append(key, object); } \
766 nodetype *Append(const wxChar *key, void *object) \
767 { return (nodetype *)wxListBase::Append(key, object); } \
768 \
769 nodetype *DetachNode(nodetype *node) \
770 { return (nodetype *)wxListBase::DetachNode(node); } \
771 bool DeleteNode(nodetype *node) \
772 { return wxListBase::DeleteNode(node); } \
773 bool DeleteObject(Tbase *object) \
774 { return wxListBase::DeleteObject(object); } \
775 void Erase(nodetype *it) \
776 { DeleteNode(it); } \
777 \
778 nodetype *Find(const Tbase *object) const \
779 { return (nodetype *)wxListBase::Find(object); } \
780 \
781 virtual nodetype *Find(const wxListKey& key) const \
782 { return (nodetype *)wxListBase::Find(key); } \
783 \
784 int IndexOf(Tbase *object) const \
785 { return wxListBase::IndexOf(object); } \
786 \
787 void Sort(wxSortCompareFunction func) \
788 { wxListBase::Sort(func); } \
789 void Sort(wxSortFuncFor_##name func) \
790 { Sort((wxSortCompareFunction)func); } \
791 \
792 protected: \
793 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
794 void *data, \
795 const wxListKey& key = wxDefaultListKey) \
796 { \
797 return new nodetype(this, \
798 (nodetype *)prev, (nodetype *)next, \
799 (T *)data, key); \
800 } \
801 /* STL interface */ \
802 public: \
803 typedef size_t size_type; \
804 typedef int difference_type; \
805 typedef T* value_type; \
806 typedef Tbase* base_value_type; \
807 typedef value_type& reference; \
808 typedef const value_type& const_reference; \
809 typedef base_value_type& base_reference; \
810 typedef const base_value_type& const_base_reference; \
811 \
812 classexp iterator \
813 { \
814 typedef name list; \
815 public: \
816 typedef nodetype Node; \
817 typedef iterator itor; \
818 typedef T* value_type; \
819 typedef value_type* ptr_type; \
820 typedef value_type& reference; \
821 \
822 Node* m_node; \
823 Node* m_init; \
824 public: \
825 typedef reference reference_type; \
826 typedef ptr_type pointer_type; \
827 \
828 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
829 iterator() : m_node(NULL), m_init(NULL) { } \
830 reference_type operator*() const \
831 { return *(pointer_type)m_node->GetDataPtr(); } \
832 ptrop \
833 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
834 const itor operator++(int) \
835 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
836 itor& operator--() \
837 { \
838 m_node = m_node ? m_node->GetPrevious() : m_init; \
839 return *this; \
840 } \
841 const itor operator--(int) \
842 { \
843 itor tmp = *this; \
844 m_node = m_node ? m_node->GetPrevious() : m_init; \
845 return tmp; \
846 } \
847 bool operator!=(const itor& it) const \
848 { return it.m_node != m_node; } \
849 bool operator==(const itor& it) const \
850 { return it.m_node == m_node; } \
851 }; \
852 classexp const_iterator \
853 { \
854 typedef name list; \
855 public: \
856 typedef nodetype Node; \
857 typedef T* value_type; \
858 typedef const value_type& const_reference; \
859 typedef const_iterator itor; \
860 typedef value_type* ptr_type; \
861 \
862 Node* m_node; \
863 Node* m_init; \
864 public: \
865 typedef const_reference reference_type; \
866 typedef const ptr_type pointer_type; \
867 \
868 const_iterator(Node* node, Node* init) \
869 : m_node(node), m_init(init) { } \
870 const_iterator() : m_node(NULL), m_init(NULL) { } \
871 const_iterator(const iterator& it) \
872 : m_node(it.m_node), m_init(it.m_init) { } \
873 reference_type operator*() const \
874 { return *(pointer_type)m_node->GetDataPtr(); } \
875 ptrop \
876 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
877 const itor operator++(int) \
878 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
879 itor& operator--() \
880 { \
881 m_node = m_node ? m_node->GetPrevious() : m_init; \
882 return *this; \
883 } \
884 const itor operator--(int) \
885 { \
886 itor tmp = *this; \
887 m_node = m_node ? m_node->GetPrevious() : m_init; \
888 return tmp; \
889 } \
890 bool operator!=(const itor& it) const \
891 { return it.m_node != m_node; } \
892 bool operator==(const itor& it) const \
893 { return it.m_node == m_node; } \
894 }; \
895 classexp reverse_iterator \
896 { \
897 typedef name list; \
898 public: \
899 typedef nodetype Node; \
900 typedef T* value_type; \
901 typedef reverse_iterator itor; \
902 typedef value_type* ptr_type; \
903 typedef value_type& reference; \
904 \
905 Node* m_node; \
906 Node* m_init; \
907 public: \
908 typedef reference reference_type; \
909 typedef ptr_type pointer_type; \
910 \
911 reverse_iterator(Node* node, Node* init) \
912 : m_node(node), m_init(init) { } \
913 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
914 reference_type operator*() const \
915 { return *(pointer_type)m_node->GetDataPtr(); } \
916 ptrop \
917 itor& operator++() \
918 { m_node = m_node->GetPrevious(); return *this; } \
919 const itor operator++(int) \
920 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
921 itor& operator--() \
922 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
923 const itor operator--(int) \
924 { \
925 itor tmp = *this; \
926 m_node = m_node ? m_node->GetNext() : m_init; \
927 return tmp; \
928 } \
929 bool operator!=(const itor& it) const \
930 { return it.m_node != m_node; } \
931 bool operator==(const itor& it) const \
932 { return it.m_node == m_node; } \
933 }; \
934 classexp const_reverse_iterator \
935 { \
936 typedef name list; \
937 public: \
938 typedef nodetype Node; \
939 typedef T* value_type; \
940 typedef const_reverse_iterator itor; \
941 typedef value_type* ptr_type; \
942 typedef const value_type& const_reference; \
943 \
944 Node* m_node; \
945 Node* m_init; \
946 public: \
947 typedef const_reference reference_type; \
948 typedef const ptr_type pointer_type; \
949 \
950 const_reverse_iterator(Node* node, Node* init) \
951 : m_node(node), m_init(init) { } \
952 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
953 const_reverse_iterator(const reverse_iterator& it) \
954 : m_node(it.m_node), m_init(it.m_init) { } \
955 reference_type operator*() const \
956 { return *(pointer_type)m_node->GetDataPtr(); } \
957 ptrop \
958 itor& operator++() \
959 { m_node = m_node->GetPrevious(); return *this; } \
960 const itor operator++(int) \
961 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
962 itor& operator--() \
963 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
964 const itor operator--(int) \
965 { \
966 itor tmp = *this; \
967 m_node = m_node ? m_node->GetNext() : m_init; \
968 return tmp; \
969 } \
970 bool operator!=(const itor& it) const \
971 { return it.m_node != m_node; } \
972 bool operator==(const itor& it) const \
973 { return it.m_node == m_node; } \
974 }; \
975 \
976 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
977 { assign(n, v); } \
978 name(const const_iterator& first, const const_iterator& last) \
979 { assign(first, last); } \
980 iterator begin() { return iterator(GetFirst(), GetLast()); } \
981 const_iterator begin() const \
982 { return const_iterator(GetFirst(), GetLast()); } \
983 iterator end() { return iterator(NULL, GetLast()); } \
984 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
985 reverse_iterator rbegin() \
986 { return reverse_iterator(GetLast(), GetFirst()); } \
987 const_reverse_iterator rbegin() const \
988 { return const_reverse_iterator(GetLast(), GetFirst()); } \
989 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
990 const_reverse_iterator rend() const \
991 { return const_reverse_iterator(NULL, GetFirst()); } \
992 void resize(size_type n, value_type v = value_type()) \
993 { \
994 while (n < size()) \
995 pop_back(); \
996 while (n > size()) \
997 push_back(v); \
998 } \
999 size_type size() const { return GetCount(); } \
1000 size_type max_size() const { return INT_MAX; } \
1001 bool empty() const { return IsEmpty(); } \
1002 reference front() { return *begin(); } \
1003 const_reference front() const { return *begin(); } \
1004 reference back() { iterator tmp = end(); return *--tmp; } \
1005 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
1006 void push_front(const_reference v = value_type()) \
1007 { Insert(GetFirst(), (const_base_reference)v); } \
1008 void pop_front() { DeleteNode(GetFirst()); } \
1009 void push_back(const_reference v = value_type()) \
1010 { Append((const_base_reference)v); } \
1011 void pop_back() { DeleteNode(GetLast()); } \
1012 void assign(const_iterator first, const const_iterator& last) \
1013 { \
1014 clear(); \
1015 for(; first != last; ++first) \
1016 Append((const_base_reference)*first); \
1017 } \
1018 void assign(size_type n, const_reference v = value_type()) \
1019 { \
1020 clear(); \
1021 for(size_type i = 0; i < n; ++i) \
1022 Append((const_base_reference)v); \
1023 } \
1024 iterator insert(const iterator& it, const_reference v = value_type())\
1025 { \
1026 Insert(it.m_node, (const_base_reference)v); \
1027 iterator itprev(it); \
1028 return itprev--; \
1029 } \
1030 void insert(const iterator& it, size_type n, const_reference v = value_type())\
1031 { \
1032 for(size_type i = 0; i < n; ++i) \
1033 Insert(it.m_node, (const_base_reference)v); \
1034 } \
1035 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1036 { \
1037 for(; first != last; ++first) \
1038 Insert(it.m_node, (const_base_reference)*first); \
1039 } \
1040 iterator erase(const iterator& it) \
1041 { \
1042 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1043 DeleteNode(it.m_node); return next; \
1044 } \
1045 iterator erase(const iterator& first, const iterator& last) \
1046 { \
1047 iterator next = last; ++next; \
1048 DeleteNodes(first.m_node, last.m_node); \
1049 return next; \
1050 } \
1051 void clear() { Clear(); } \
1052 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1053 { insert(it, first, last); l.erase(first, last); } \
1054 void splice(const iterator& it, name& l) \
1055 { splice(it, l, l.begin(), l.end() ); } \
1056 void splice(const iterator& it, name& l, const iterator& first) \
1057 { \
1058 iterator tmp = first; ++tmp; \
1059 if(it == first || it == tmp) return; \
1060 insert(it, *first); \
1061 l.erase(first); \
1062 } \
1063 void remove(const_reference v) \
1064 { DeleteObject((const_base_reference)v); } \
1065 void reverse() \
1066 { Reverse(); } \
1067 /* void swap(name& l) \
1068 { \
1069 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1070 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1071 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1072 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1073 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1074 } */ \
1075 }
1076
1077#define WX_LIST_PTROP \
1078 pointer_type operator->() const \
1079 { return (pointer_type)m_node->GetDataPtr(); }
1080#define WX_LIST_PTROP_NONE
1081
1082#define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1083 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1084#define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1085 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1086
1087#define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1088 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1089#define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1090 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1091
1092#define WX_DECLARE_LIST(elementtype, listname) \
1093 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1094 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1095#define WX_DECLARE_LIST_PTR(elementtype, listname) \
1096 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1097 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1098
1099#define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1100 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1101 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1102
1103#define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1104 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1105
1106#define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1107 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1108 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1109
1110#define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1111 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1112 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1113#define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1114 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1115 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1116
1117// this macro must be inserted in your program after
1118// #include "wx/listimpl.cpp"
1119#define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1120
1121#define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1122#define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1123
1124#endif // !wxUSE_STL
1125
1126// ============================================================================
1127// now we can define classes 100% compatible with the old ones
1128// ============================================================================
1129
1130// ----------------------------------------------------------------------------
1131// commonly used list classes
1132// ----------------------------------------------------------------------------
1133
1134#if defined(wxLIST_COMPATIBILITY)
1135
1136// inline compatibility functions
1137
1138#if !wxUSE_STL
1139
1140// ----------------------------------------------------------------------------
1141// wxNodeBase deprecated methods
1142// ----------------------------------------------------------------------------
1143
1144inline wxNode *wxNodeBase::Next() const { return (wxNode *)GetNext(); }
1145inline wxNode *wxNodeBase::Previous() const { return (wxNode *)GetPrevious(); }
1146inline wxObject *wxNodeBase::Data() const { return (wxObject *)GetData(); }
1147
1148// ----------------------------------------------------------------------------
1149// wxListBase deprecated methods
1150// ----------------------------------------------------------------------------
1151
1152inline int wxListBase::Number() const { return (int)GetCount(); }
1153inline wxNode *wxListBase::First() const { return (wxNode *)GetFirst(); }
1154inline wxNode *wxListBase::Last() const { return (wxNode *)GetLast(); }
1155inline wxNode *wxListBase::Nth(size_t n) const { return (wxNode *)Item(n); }
1156inline wxListBase::operator wxList&() const { return *(wxList*)this; }
1157
1158#endif
1159
1160// define this to make a lot of noise about use of the old wxList classes.
1161//#define wxWARN_COMPAT_LIST_USE
1162
1163// ----------------------------------------------------------------------------
1164// wxList compatibility class: in fact, it's a list of wxObjects
1165// ----------------------------------------------------------------------------
1166
1167WX_DECLARE_LIST_2(wxObject, wxObjectList, wxObjectListNode,
1168 class WXDLLIMPEXP_BASE);
1169
1170class WXDLLIMPEXP_BASE wxList : public wxObjectList
1171{
1172public:
1173#if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1174 wxList() { };
1175 wxDEPRECATED( wxList(int key_type) );
1176#elif !wxUSE_STL
1177 wxList(int key_type = wxKEY_NONE);
1178#endif
1179
1180 // this destructor is required for Darwin
1181 ~wxList() { }
1182
1183#if !wxUSE_STL
1184 wxList& operator=(const wxList& list)
1185 { Assign(list); return *this; }
1186
1187 // compatibility methods
1188 void Sort(wxSortCompareFunction compfunc) { wxListBase::Sort(compfunc); }
1189#endif
1190
1191#if wxUSE_STL
1192#else
1193 wxNode *Member(wxObject *object) const { return (wxNode *)Find(object); }
1194#endif
1195};
1196
1197#if !wxUSE_STL
1198
1199// -----------------------------------------------------------------------------
1200// wxStringList class for compatibility with the old code
1201// -----------------------------------------------------------------------------
1202WX_DECLARE_LIST_2(wxChar, wxStringListBase, wxStringListNode, class WXDLLIMPEXP_BASE);
1203
1204class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1205{
1206public:
1207 // ctors and such
1208 // default
1209#ifdef wxWARN_COMPAT_LIST_USE
1210 wxStringList();
1211 wxDEPRECATED( wxStringList(const wxChar *first ...) ); // FIXME-UTF8
1212#else
1213 wxStringList();
1214 wxStringList(const wxChar *first ...); // FIXME-UTF8
1215#endif
1216
1217 // copying the string list: the strings are copied, too (extremely
1218 // inefficient!)
1219 wxStringList(const wxStringList& other) : wxStringListBase() { DeleteContents(true); DoCopy(other); }
1220 wxStringList& operator=(const wxStringList& other)
1221 { Clear(); DoCopy(other); return *this; }
1222
1223 // operations
1224 // makes a copy of the string
1225 wxNode *Add(const wxChar *s);
1226
1227 // Append to beginning of list
1228 wxNode *Prepend(const wxChar *s);
1229
1230 bool Delete(const wxChar *s);
1231
1232 wxChar **ListToArray(bool new_copies = false) const;
1233 bool Member(const wxChar *s) const;
1234
1235 // alphabetic sort
1236 void Sort();
1237
1238private:
1239 void DoCopy(const wxStringList&); // common part of copy ctor and operator=
1240};
1241
1242#else // if wxUSE_STL
1243
1244WX_DECLARE_LIST_XO(wxString, wxStringListBase, class WXDLLIMPEXP_BASE);
1245
1246class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1247{
1248public:
1249 compatibility_iterator Append(wxChar* s)
1250 { wxString tmp = s; delete[] s; return wxStringListBase::Append(tmp); }
1251 compatibility_iterator Insert(wxChar* s)
1252 { wxString tmp = s; delete[] s; return wxStringListBase::Insert(tmp); }
1253 compatibility_iterator Insert(size_t pos, wxChar* s)
1254 {
1255 wxString tmp = s;
1256 delete[] s;
1257 return wxStringListBase::Insert(pos, tmp);
1258 }
1259 compatibility_iterator Add(const wxChar* s)
1260 { push_back(s); return GetLast(); }
1261 compatibility_iterator Prepend(const wxChar* s)
1262 { push_front(s); return GetFirst(); }
1263};
1264
1265#endif // wxUSE_STL
1266
1267#endif // wxLIST_COMPATIBILITY
1268
1269// delete all list elements
1270//
1271// NB: the class declaration of the list elements must be visible from the
1272// place where you use this macro, otherwise the proper destructor may not
1273// be called (a decent compiler should give a warning about it, but don't
1274// count on it)!
1275#define WX_CLEAR_LIST(type, list) \
1276 { \
1277 type::iterator it, en; \
1278 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1279 delete *it; \
1280 (list).clear(); \
1281 }
1282
1283#endif // _WX_LISTH__