]> git.saurik.com Git - wxWidgets.git/blob - include/wx/list.h
Corrections
[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 class WXDLLEXPORT wxObjectListNode;
332
333 // undef it to get rid of old, deprecated functions
334 #define wxLIST_COMPATIBILITY
335
336 // -----------------------------------------------------------------------------
337 // key stuff: a list may be optionally keyed on integer or string key
338 // -----------------------------------------------------------------------------
339
340 union wxListKeyValue
341 {
342 long integer;
343 wxChar *string;
344 };
345
346 // a struct which may contain both types of keys
347 //
348 // implementation note: on one hand, this class allows to have only one function
349 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
350 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
351 // wxList::Find(const char *).
352 class WXDLLIMPEXP_BASE wxListKey
353 {
354 public:
355 // implicit ctors
356 wxListKey() : m_keyType(wxKEY_NONE)
357 { }
358 wxListKey(long i) : m_keyType(wxKEY_INTEGER)
359 { m_key.integer = i; }
360 wxListKey(const wxChar *s) : m_keyType(wxKEY_STRING)
361 { m_key.string = wxStrdup(s); }
362 wxListKey(const wxString& s) : m_keyType(wxKEY_STRING)
363 { m_key.string = wxStrdup(s.c_str()); }
364
365 // accessors
366 wxKeyType GetKeyType() const { return m_keyType; }
367 const wxChar *GetString() const
368 { wxASSERT( m_keyType == wxKEY_STRING ); return m_key.string; }
369 long GetNumber() const
370 { wxASSERT( m_keyType == wxKEY_INTEGER ); return m_key.integer; }
371
372 // comparison
373 // Note: implementation moved to list.cpp to prevent BC++ inline
374 // expansion warning.
375 bool operator==(wxListKeyValue value) const ;
376
377 // dtor
378 ~wxListKey()
379 {
380 if ( m_keyType == wxKEY_STRING )
381 free(m_key.string);
382 }
383
384 private:
385 wxKeyType m_keyType;
386 wxListKeyValue m_key;
387 };
388
389 // -----------------------------------------------------------------------------
390 // wxNodeBase class is a (base for) node in a double linked list
391 // -----------------------------------------------------------------------------
392
393 extern WXDLLIMPEXP_DATA_BASE(wxListKey) wxDefaultListKey;
394
395 class WXDLLIMPEXP_BASE wxListBase;
396
397 class WXDLLIMPEXP_BASE wxNodeBase
398 {
399 friend class wxListBase;
400 public:
401 // ctor
402 wxNodeBase(wxListBase *list = (wxListBase *)NULL,
403 wxNodeBase *previous = (wxNodeBase *)NULL,
404 wxNodeBase *next = (wxNodeBase *)NULL,
405 void *data = NULL,
406 const wxListKey& key = wxDefaultListKey);
407
408 virtual ~wxNodeBase();
409
410 // FIXME no check is done that the list is really keyed on strings
411 const wxChar *GetKeyString() const { return m_key.string; }
412 long GetKeyInteger() const { return m_key.integer; }
413
414 // Necessary for some existing code
415 void SetKeyString(wxChar* s) { m_key.string = s; }
416 void SetKeyInteger(long i) { m_key.integer = i; }
417
418 #ifdef wxLIST_COMPATIBILITY
419 // compatibility methods, use Get* instead.
420 wxDEPRECATED( wxNode *Next() const );
421 wxDEPRECATED( wxNode *Previous() const );
422 wxDEPRECATED( wxObject *Data() const );
423 #endif // wxLIST_COMPATIBILITY
424
425 protected:
426 // all these are going to be "overloaded" in the derived classes
427 wxNodeBase *GetNext() const { return m_next; }
428 wxNodeBase *GetPrevious() const { return m_previous; }
429
430 void *GetData() const { return m_data; }
431 void SetData(void *data) { m_data = data; }
432
433 // get 0-based index of this node within the list or wxNOT_FOUND
434 int IndexOf() const;
435
436 virtual void DeleteData() { }
437 public:
438 // for wxList::iterator
439 void** GetDataPtr() const { return &(((wxNodeBase*)this)->m_data); }
440 private:
441 // optional key stuff
442 wxListKeyValue m_key;
443
444 void *m_data; // user data
445 wxNodeBase *m_next, // next and previous nodes in the list
446 *m_previous;
447
448 wxListBase *m_list; // list we belong to
449
450 DECLARE_NO_COPY_CLASS(wxNodeBase)
451 };
452
453 // -----------------------------------------------------------------------------
454 // a double-linked list class
455 // -----------------------------------------------------------------------------
456
457 class WXDLLIMPEXP_BASE wxList;
458
459 class WXDLLIMPEXP_BASE wxListBase : public wxObject
460 {
461 friend class WXDLLIMPEXP_BASE wxNodeBase; // should be able to call DetachNode()
462 friend class wxHashTableBase; // should be able to call untyped Find()
463
464 public:
465 // default ctor & dtor
466 wxListBase(wxKeyType keyType = wxKEY_NONE)
467 { Init(keyType); }
468 virtual ~wxListBase();
469
470 // accessors
471 // count of items in the list
472 size_t GetCount() const { return m_count; }
473
474 // return true if this list is empty
475 bool IsEmpty() const { return m_count == 0; }
476
477 // operations
478
479 // delete all nodes
480 void Clear();
481
482 // instruct it to destroy user data when deleting nodes
483 void DeleteContents(bool destroy) { m_destroy = destroy; }
484
485 // query if to delete
486 bool GetDeleteContents() const
487 { return m_destroy; }
488
489 // get the keytype
490 wxKeyType GetKeyType() const
491 { return m_keyType; }
492
493 // set the keytype (required by the serial code)
494 void SetKeyType(wxKeyType keyType)
495 { wxASSERT( m_count==0 ); m_keyType = keyType; }
496
497 #ifdef wxLIST_COMPATIBILITY
498 // compatibility methods from old wxList
499 wxDEPRECATED( int Number() const ); // use GetCount instead.
500 wxDEPRECATED( wxNode *First() const ); // use GetFirst
501 wxDEPRECATED( wxNode *Last() const ); // use GetLast
502 wxDEPRECATED( wxNode *Nth(size_t n) const ); // use Item
503
504 // kludge for typesafe list migration in core classes.
505 wxDEPRECATED( operator wxList&() const );
506 #endif // wxLIST_COMPATIBILITY
507
508 protected:
509
510 // all methods here are "overloaded" in derived classes to provide compile
511 // time type checking
512
513 // create a node for the list of this type
514 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next,
515 void *data,
516 const wxListKey& key = wxDefaultListKey) = 0;
517
518 // Can't access these from derived classes otherwise (bug in Salford C++?)
519 #ifdef __SALFORDC__
520 public:
521 #endif
522
523 // ctors
524 // from an array
525 wxListBase(size_t count, void *elements[]);
526 // from a sequence of objects
527 wxListBase(void *object, ... /* terminate with NULL */);
528
529 protected:
530 void Assign(const wxListBase& list)
531 { Clear(); DoCopy(list); }
532
533 // get list head/tail
534 wxNodeBase *GetFirst() const { return m_nodeFirst; }
535 wxNodeBase *GetLast() const { return m_nodeLast; }
536
537 // by (0-based) index
538 wxNodeBase *Item(size_t index) const;
539
540 // get the list item's data
541 void *operator[](size_t n) const
542 {
543 wxNodeBase *node = Item(n);
544
545 return node ? node->GetData() : (wxNodeBase *)NULL;
546 }
547
548 // operations
549 // append to end of list
550 wxNodeBase *Prepend(void *object)
551 { return (wxNodeBase *)wxListBase::Insert(object); }
552 // append to beginning of list
553 wxNodeBase *Append(void *object);
554 // insert a new item at the beginning of the list
555 wxNodeBase *Insert(void *object) { return Insert( (wxNodeBase*)NULL, object); }
556 // insert a new item at the given position
557 wxNodeBase *Insert(size_t pos, void *object)
558 { return pos == GetCount() ? Append(object)
559 : Insert(Item(pos), object); }
560 // insert before given node or at front of list if prev == NULL
561 wxNodeBase *Insert(wxNodeBase *prev, void *object);
562
563 // keyed append
564 wxNodeBase *Append(long key, void *object);
565 wxNodeBase *Append(const wxChar *key, void *object);
566
567 // removes node from the list but doesn't delete it (returns pointer
568 // to the node or NULL if it wasn't found in the list)
569 wxNodeBase *DetachNode(wxNodeBase *node);
570 // delete element from list, returns false if node not found
571 bool DeleteNode(wxNodeBase *node);
572 // finds object pointer and deletes node (and object if DeleteContents
573 // is on), returns false if object not found
574 bool DeleteObject(void *object);
575
576 // search (all return NULL if item not found)
577 // by data
578 wxNodeBase *Find(const void *object) const;
579
580 // by key
581 wxNodeBase *Find(const wxListKey& key) const;
582
583 // get 0-based index of object or wxNOT_FOUND
584 int IndexOf( void *object ) const;
585
586 // this function allows the sorting of arbitrary lists by giving
587 // a function to compare two list elements. The list is sorted in place.
588 void Sort(const wxSortCompareFunction compfunc);
589
590 // functions for iterating over the list
591 void *FirstThat(wxListIterateFunction func);
592 void ForEach(wxListIterateFunction func);
593 void *LastThat(wxListIterateFunction func);
594
595 // for STL interface, "last" points to one after the last node
596 // of the controlled sequence (NULL for the end of the list)
597 void Reverse();
598 void DeleteNodes(wxNodeBase* first, wxNodeBase* last);
599 private:
600
601 // common part of all ctors
602 void Init(wxKeyType keyType = wxKEY_NONE);
603
604 // helpers
605 // common part of copy ctor and assignment operator
606 void DoCopy(const wxListBase& list);
607 // common part of all Append()s
608 wxNodeBase *AppendCommon(wxNodeBase *node);
609 // free node's data and node itself
610 void DoDeleteNode(wxNodeBase *node);
611
612 size_t m_count; // number of elements in the list
613 bool m_destroy; // destroy user data when deleting list items?
614 wxNodeBase *m_nodeFirst, // pointers to the head and tail of the list
615 *m_nodeLast;
616
617 wxKeyType m_keyType; // type of our keys (may be wxKEY_NONE)
618 };
619
620 // -----------------------------------------------------------------------------
621 // macros for definition of "template" list type
622 // -----------------------------------------------------------------------------
623
624 // and now some heavy magic...
625
626 // declare a list type named 'name' and containing elements of type 'T *'
627 // (as a by product of macro expansion you also get wx##name##Node
628 // wxNode-derived type)
629 //
630 // implementation details:
631 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
632 // for the list of given type - this allows us to pass only the list name
633 // to WX_DEFINE_LIST() even if it needs both the name and the type
634 //
635 // 2. We redefine all non-type-safe wxList functions with type-safe versions
636 // which don't take any space (everything is inline), but bring compile
637 // time error checking.
638 //
639 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
640 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
641 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
642 // interesting capability to store polymorphic objects in the list and is
643 // particularly useful with, for example, "wxWindow *" list where the
644 // wxWindowBase pointers are put into the list, but wxWindow pointers are
645 // retrieved from it.
646 //
647 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
648 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
649 // it results in compiler warnings when this operator doesn't make sense
650 // (i.e. stored elements are not pointers)
651
652 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
653 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
654 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
655 \
656 classexp nodetype : public wxNodeBase \
657 { \
658 public: \
659 nodetype(wxListBase *list = (wxListBase *)NULL, \
660 nodetype *previous = (nodetype *)NULL, \
661 nodetype *next = (nodetype *)NULL, \
662 T *data = (T *)NULL, \
663 const wxListKey& key = wxDefaultListKey) \
664 : wxNodeBase(list, previous, next, data, key) { } \
665 \
666 nodetype *GetNext() const \
667 { return (nodetype *)wxNodeBase::GetNext(); } \
668 nodetype *GetPrevious() const \
669 { return (nodetype *)wxNodeBase::GetPrevious(); } \
670 \
671 T *GetData() const \
672 { return (T *)wxNodeBase::GetData(); } \
673 void SetData(T *data) \
674 { wxNodeBase::SetData(data); } \
675 \
676 protected: \
677 virtual void DeleteData(); \
678 \
679 DECLARE_NO_COPY_CLASS(nodetype) \
680 }; \
681 \
682 classexp name : public wxListBase \
683 { \
684 public: \
685 typedef nodetype Node; \
686 typedef Node* compatibility_iterator; \
687 \
688 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
689 { } \
690 name(const name& list) : wxListBase(list.GetKeyType()) \
691 { Assign(list); } \
692 name(size_t count, T *elements[]) \
693 : wxListBase(count, (void **)elements) { } \
694 \
695 name& operator=(const name& list) \
696 { Assign(list); return *this; } \
697 \
698 nodetype *GetFirst() const \
699 { return (nodetype *)wxListBase::GetFirst(); } \
700 nodetype *GetLast() const \
701 { return (nodetype *)wxListBase::GetLast(); } \
702 \
703 nodetype *Item(size_t index) const \
704 { return (nodetype *)wxListBase::Item(index); } \
705 \
706 T *operator[](size_t index) const \
707 { \
708 nodetype *node = Item(index); \
709 return node ? (T*)(node->GetData()) : (T*)NULL; \
710 } \
711 \
712 nodetype *Append(Tbase *object) \
713 { return (nodetype *)wxListBase::Append(object); } \
714 nodetype *Insert(Tbase *object) \
715 { return (nodetype *)Insert((nodetype*)NULL, object); } \
716 nodetype *Insert(size_t pos, Tbase *object) \
717 { return (nodetype *)wxListBase::Insert(pos, object); } \
718 nodetype *Insert(nodetype *prev, Tbase *object) \
719 { return (nodetype *)wxListBase::Insert(prev, object); } \
720 \
721 nodetype *Append(long key, void *object) \
722 { return (nodetype *)wxListBase::Append(key, object); } \
723 nodetype *Append(const wxChar *key, void *object) \
724 { return (nodetype *)wxListBase::Append(key, object); } \
725 \
726 nodetype *DetachNode(nodetype *node) \
727 { return (nodetype *)wxListBase::DetachNode(node); } \
728 bool DeleteNode(nodetype *node) \
729 { return wxListBase::DeleteNode(node); } \
730 bool DeleteObject(Tbase *object) \
731 { return wxListBase::DeleteObject(object); } \
732 void Erase(compatibility_iterator it) \
733 { DeleteNode(it); } \
734 \
735 nodetype *Find(const Tbase *object) const \
736 { return (nodetype *)wxListBase::Find(object); } \
737 \
738 virtual nodetype *Find(const wxListKey& key) const \
739 { return (nodetype *)wxListBase::Find(key); } \
740 \
741 int IndexOf(Tbase *object) const \
742 { return wxListBase::IndexOf(object); } \
743 \
744 void Sort(wxSortCompareFunction func) \
745 { wxListBase::Sort(func); } \
746 void Sort(wxSortFuncFor_##name func) \
747 { Sort((wxSortCompareFunction)func); } \
748 \
749 protected: \
750 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
751 void *data, \
752 const wxListKey& key = wxDefaultListKey) \
753 { \
754 return new nodetype(this, \
755 (nodetype *)prev, (nodetype *)next, \
756 (T *)data, key); \
757 } \
758 /* STL interface */ \
759 public: \
760 typedef size_t size_type; \
761 typedef int difference_type; \
762 typedef T* value_type; \
763 typedef Tbase* base_value_type; \
764 typedef value_type& reference; \
765 typedef const value_type& const_reference; \
766 typedef base_value_type& base_reference; \
767 typedef const base_value_type& const_base_reference; \
768 \
769 class iterator \
770 { \
771 typedef name list; \
772 public: \
773 typedef nodetype Node; \
774 typedef iterator itor; \
775 typedef T* value_type; \
776 typedef value_type* ptr_type; \
777 typedef value_type& reference; \
778 \
779 Node* m_node; \
780 Node* m_init; \
781 public: \
782 typedef reference reference_type; \
783 typedef ptr_type pointer_type; \
784 \
785 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
786 iterator() : m_node(NULL), m_init(NULL) { } \
787 reference_type operator*() const \
788 { return *(pointer_type)m_node->GetDataPtr(); } \
789 ptrop \
790 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
791 const itor operator++(int) \
792 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
793 itor& operator--() \
794 { \
795 m_node = m_node ? m_node->GetPrevious() : m_init; \
796 return *this; \
797 } \
798 const itor operator--(int) \
799 { \
800 itor tmp = *this; \
801 m_node = m_node ? m_node->GetPrevious() : m_init; \
802 return tmp; \
803 } \
804 bool operator!=(const itor& it) const \
805 { return it.m_node != m_node; } \
806 bool operator==(const itor& it) const \
807 { return it.m_node == m_node; } \
808 }; \
809 class const_iterator \
810 { \
811 typedef name list; \
812 public: \
813 typedef nodetype Node; \
814 typedef T* value_type; \
815 typedef const value_type& const_reference; \
816 typedef const_iterator itor; \
817 typedef value_type* ptr_type; \
818 \
819 Node* m_node; \
820 Node* m_init; \
821 public: \
822 typedef const_reference reference_type; \
823 typedef const ptr_type pointer_type; \
824 \
825 const_iterator(Node* node, Node* init) \
826 : m_node(node), m_init(init) { } \
827 const_iterator() : m_node(NULL), m_init(NULL) { } \
828 const_iterator(const iterator& it) \
829 : m_node(it.m_node), m_init(it.m_init) { } \
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 class reverse_iterator \
853 { \
854 typedef name list; \
855 public: \
856 typedef nodetype Node; \
857 typedef T* value_type; \
858 typedef reverse_iterator itor; \
859 typedef value_type* ptr_type; \
860 typedef value_type& reference; \
861 \
862 Node* m_node; \
863 Node* m_init; \
864 public: \
865 typedef reference reference_type; \
866 typedef ptr_type pointer_type; \
867 \
868 reverse_iterator(Node* node, Node* init) \
869 : m_node(node), m_init(init) { } \
870 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
871 reference_type operator*() const \
872 { return *(pointer_type)m_node->GetDataPtr(); } \
873 ptrop \
874 itor& operator++() \
875 { m_node = m_node->GetPrevious(); return *this; } \
876 const itor operator++(int) \
877 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
878 itor& operator--() \
879 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
880 const itor operator--(int) \
881 { \
882 itor tmp = *this; \
883 m_node = m_node ? m_node->GetNext() : m_init; \
884 return tmp; \
885 } \
886 bool operator!=(const itor& it) const \
887 { return it.m_node != m_node; } \
888 bool operator==(const itor& it) const \
889 { return it.m_node == m_node; } \
890 }; \
891 class const_reverse_iterator \
892 { \
893 typedef name list; \
894 public: \
895 typedef nodetype Node; \
896 typedef T* value_type; \
897 typedef const_reverse_iterator itor; \
898 typedef value_type* ptr_type; \
899 typedef const value_type& const_reference; \
900 \
901 Node* m_node; \
902 Node* m_init; \
903 public: \
904 typedef const_reference reference_type; \
905 typedef const ptr_type pointer_type; \
906 \
907 const_reverse_iterator(Node* node, Node* init) \
908 : m_node(node), m_init(init) { } \
909 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
910 const_reverse_iterator(const reverse_iterator& it) \
911 : m_node(it.m_node), m_init(it.m_init) { } \
912 reference_type operator*() const \
913 { return *(pointer_type)m_node->GetDataPtr(); } \
914 ptrop \
915 itor& operator++() \
916 { m_node = m_node->GetPrevious(); return *this; } \
917 const itor operator++(int) \
918 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
919 itor& operator--() \
920 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
921 const itor operator--(int) \
922 { \
923 itor tmp = *this; \
924 m_node = m_node ? m_node->GetNext() : m_init; \
925 return tmp; \
926 } \
927 bool operator!=(const itor& it) const \
928 { return it.m_node != m_node; } \
929 bool operator==(const itor& it) const \
930 { return it.m_node == m_node; } \
931 }; \
932 \
933 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
934 { assign(n, v); } \
935 name(const const_iterator& first, const const_iterator& last) \
936 { assign(first, last); } \
937 iterator begin() { return iterator(GetFirst(), GetLast()); } \
938 const_iterator begin() const \
939 { return const_iterator(GetFirst(), GetLast()); } \
940 iterator end() { return iterator(NULL, GetLast()); } \
941 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
942 reverse_iterator rbegin() \
943 { return reverse_iterator(GetLast(), GetFirst()); } \
944 const_reverse_iterator rbegin() const \
945 { return const_reverse_iterator(GetLast(), GetFirst()); } \
946 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
947 const_reverse_iterator rend() const \
948 { return const_reverse_iterator(NULL, GetFirst()); } \
949 void resize(size_type n, value_type v = value_type()) \
950 { \
951 while (n < size()) \
952 pop_back(); \
953 while (n > size()) \
954 push_back(v); \
955 } \
956 size_type size() const { return GetCount(); } \
957 size_type max_size() const { return INT_MAX; } \
958 bool empty() const { return IsEmpty(); } \
959 reference front() { return *begin(); } \
960 const_reference front() const { return *begin(); } \
961 reference back() { iterator tmp = end(); return *--tmp; } \
962 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
963 void push_front(const_reference v = value_type()) \
964 { Insert(GetFirst(), (const_base_reference)v); } \
965 void pop_front() { DeleteNode(GetFirst()); } \
966 void push_back(const_reference v = value_type()) \
967 { Append((const_base_reference)v); } \
968 void pop_back() { DeleteNode(GetLast()); } \
969 void assign(const_iterator first, const const_iterator& last) \
970 { \
971 clear(); \
972 for(; first != last; ++first) \
973 Append((const_base_reference)*first); \
974 } \
975 void assign(size_type n, const_reference v = value_type()) \
976 { \
977 clear(); \
978 for(size_type i = 0; i < n; ++i) \
979 Append((const_base_reference)v); \
980 } \
981 iterator insert(const iterator& it, const_reference v = value_type())\
982 { \
983 Insert(it.m_node, (const_base_reference)v); \
984 return iterator(it.m_node->GetPrevious(), GetLast()); \
985 } \
986 void insert(const iterator& it, size_type n, const_reference v = value_type())\
987 { \
988 for(size_type i = 0; i < n; ++i) \
989 Insert(it.m_node, (const_base_reference)v); \
990 } \
991 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
992 { \
993 for(; first != last; ++first) \
994 Insert(it.m_node, (const_base_reference)*first); \
995 } \
996 iterator erase(const iterator& it) \
997 { \
998 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
999 DeleteNode(it.m_node); return next; \
1000 } \
1001 iterator erase(const iterator& first, const iterator& last) \
1002 { \
1003 iterator next = last; ++next; \
1004 DeleteNodes(first.m_node, last.m_node); \
1005 return next; \
1006 } \
1007 void clear() { Clear(); } \
1008 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1009 { insert(it, first, last); l.erase(first, last); } \
1010 void splice(const iterator& it, name& l) \
1011 { splice(it, l, l.begin(), l.end() ); } \
1012 void splice(const iterator& it, name& l, const iterator& first) \
1013 { \
1014 iterator tmp = first; ++tmp; \
1015 if(it == first || it == tmp) return; \
1016 insert(it, *first); \
1017 l.erase(first); \
1018 } \
1019 void remove(const_reference v) \
1020 { DeleteObject((const_base_reference)v); } \
1021 void reverse() \
1022 { Reverse(); } \
1023 /* void swap(name& l) \
1024 { \
1025 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1026 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1027 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1028 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1029 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1030 } */ \
1031 }
1032
1033 #define WX_LIST_PTROP \
1034 pointer_type operator->() const \
1035 { return (pointer_type)m_node->GetDataPtr(); }
1036 #define WX_LIST_PTROP_NONE
1037
1038 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1039 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1040 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1041 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1042
1043 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1044 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1045 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1046 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1047
1048 #define WX_DECLARE_LIST(elementtype, listname) \
1049 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1050 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1051 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1052 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1053 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1054
1055 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1056 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1057 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1058
1059 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1060 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1061
1062 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1063 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1064 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1065
1066 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1067 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1068 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1069 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1070 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1071 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1072
1073 // this macro must be inserted in your program after
1074 // #include <wx/listimpl.cpp>
1075 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1076
1077 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1078 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1079
1080 #endif // !wxUSE_STL
1081
1082 // ============================================================================
1083 // now we can define classes 100% compatible with the old ones
1084 // ============================================================================
1085
1086 // ----------------------------------------------------------------------------
1087 // commonly used list classes
1088 // ----------------------------------------------------------------------------
1089
1090 #if defined(wxLIST_COMPATIBILITY)
1091
1092 // inline compatibility functions
1093
1094 #if !wxUSE_STL
1095
1096 // ----------------------------------------------------------------------------
1097 // wxNodeBase deprecated methods
1098 // ----------------------------------------------------------------------------
1099
1100 inline wxNode *wxNodeBase::Next() const { return (wxNode *)GetNext(); }
1101 inline wxNode *wxNodeBase::Previous() const { return (wxNode *)GetPrevious(); }
1102 inline wxObject *wxNodeBase::Data() const { return (wxObject *)GetData(); }
1103
1104 // ----------------------------------------------------------------------------
1105 // wxListBase deprecated methods
1106 // ----------------------------------------------------------------------------
1107
1108 inline int wxListBase::Number() const { return (int)GetCount(); }
1109 inline wxNode *wxListBase::First() const { return (wxNode *)GetFirst(); }
1110 inline wxNode *wxListBase::Last() const { return (wxNode *)GetLast(); }
1111 inline wxNode *wxListBase::Nth(size_t n) const { return (wxNode *)Item(n); }
1112 inline wxListBase::operator wxList&() const { return *(wxList*)this; }
1113
1114 #endif
1115
1116 // define this to make a lot of noise about use of the old wxList classes.
1117 //#define wxWARN_COMPAT_LIST_USE
1118
1119 // ----------------------------------------------------------------------------
1120 // wxList compatibility class: in fact, it's a list of wxObjects
1121 // ----------------------------------------------------------------------------
1122
1123 WX_DECLARE_LIST_2(wxObject, wxObjectList, wxObjectListNode,
1124 class WXDLLIMPEXP_BASE);
1125
1126 class WXDLLIMPEXP_BASE wxList : public wxObjectList
1127 {
1128 public:
1129 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1130 wxList() { };
1131 wxDEPRECATED( wxList(int key_type) );
1132 #elif !wxUSE_STL
1133 wxList(int key_type = wxKEY_NONE);
1134 #endif
1135
1136 // this destructor is required for Darwin
1137 ~wxList() { }
1138
1139 #if !wxUSE_STL
1140 wxList& operator=(const wxList& list)
1141 { (void) wxListBase::operator=(list); return *this; }
1142
1143 // compatibility methods
1144 void Sort(wxSortCompareFunction compfunc) { wxListBase::Sort(compfunc); }
1145 #endif
1146
1147 #if wxUSE_STL
1148 #else
1149 wxNode *Member(wxObject *object) const { return (wxNode *)Find(object); }
1150 #endif
1151
1152 private:
1153 #if !wxUSE_STL
1154 DECLARE_DYNAMIC_CLASS(wxList)
1155 #endif
1156 };
1157
1158 #if !wxUSE_STL
1159
1160 // -----------------------------------------------------------------------------
1161 // wxStringList class for compatibility with the old code
1162 // -----------------------------------------------------------------------------
1163 WX_DECLARE_LIST_2(wxChar, wxStringListBase, wxStringListNode, class WXDLLIMPEXP_BASE);
1164
1165 class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1166 {
1167 public:
1168 // ctors and such
1169 // default
1170 #ifdef wxWARN_COMPAT_LIST_USE
1171 wxStringList();
1172 wxDEPRECATED( wxStringList(const wxChar *first ...) );
1173 #else
1174 wxStringList();
1175 wxStringList(const wxChar *first ...);
1176 #endif
1177
1178 // copying the string list: the strings are copied, too (extremely
1179 // inefficient!)
1180 wxStringList(const wxStringList& other) : wxStringListBase() { DeleteContents(true); DoCopy(other); }
1181 wxStringList& operator=(const wxStringList& other)
1182 { Clear(); DoCopy(other); return *this; }
1183
1184 // operations
1185 // makes a copy of the string
1186 wxNode *Add(const wxChar *s);
1187
1188 // Append to beginning of list
1189 wxNode *Prepend(const wxChar *s);
1190
1191 bool Delete(const wxChar *s);
1192
1193 wxChar **ListToArray(bool new_copies = false) const;
1194 bool Member(const wxChar *s) const;
1195
1196 // alphabetic sort
1197 void Sort();
1198
1199 private:
1200 void DoCopy(const wxStringList&); // common part of copy ctor and operator=
1201
1202 DECLARE_DYNAMIC_CLASS(wxStringList)
1203 };
1204
1205 #else // if wxUSE_STL
1206
1207 WX_DECLARE_LIST_XO(wxString, wxStringListBase, class WXDLLIMPEXP_BASE);
1208
1209 class WXDLLIMPEXP_BASE wxStringList : public wxStringListBase
1210 {
1211 public:
1212 compatibility_iterator Append(wxChar* s)
1213 { wxString tmp = s; delete[] s; return wxStringListBase::Append(tmp); }
1214 compatibility_iterator Insert(wxChar* s)
1215 { wxString tmp = s; delete[] s; return wxStringListBase::Insert(tmp); }
1216 compatibility_iterator Insert(size_t pos, wxChar* s)
1217 {
1218 wxString tmp = s;
1219 delete[] s;
1220 return wxStringListBase::Insert(pos, tmp);
1221 }
1222 compatibility_iterator Add(const wxChar* s)
1223 { push_back(s); return GetLast(); }
1224 compatibility_iterator Prepend(const wxChar* s)
1225 { push_front(s); return GetFirst(); }
1226 };
1227
1228 #endif // wxUSE_STL
1229
1230 #endif // wxLIST_COMPATIBILITY
1231
1232 // delete all list elements
1233 //
1234 // NB: the class declaration of the list elements must be visible from the
1235 // place where you use this macro, otherwise the proper destructor may not
1236 // be called (a decent compiler should give a warning about it, but don't
1237 // count on it)!
1238 #define WX_CLEAR_LIST(type, list) \
1239 { \
1240 type::iterator it, en; \
1241 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1242 delete *it; \
1243 (list).clear(); \
1244 }
1245
1246 #endif
1247 // _WX_LISTH__