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