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