]> git.saurik.com Git - wxWidgets.git/blame - include/wx/list.h
Small fixes for Tex2RTF but alas, we still get memory problems.
[wxWidgets.git] / include / wx / list.h
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: list.h
3// Purpose: wxList, wxStringList classes
4// Author: Julian Smart
fd3f686c 5// Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
c801d85f
KB
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
e146b8c8 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
fd3f686c
VZ
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
34138703
JS
25#ifndef _WX_LISTH__
26#define _WX_LISTH__
c801d85f
KB
27
28#ifdef __GNUG__
0d3820b3 29#pragma interface "list.h"
c801d85f
KB
30#endif
31
fd3f686c
VZ
32// -----------------------------------------------------------------------------
33// headers
34// -----------------------------------------------------------------------------
35
c801d85f 36#include "wx/defs.h"
fd3f686c 37#include "wx/debug.h"
c801d85f 38#include "wx/object.h"
3bef6c4c 39#include "wx/string.h"
c801d85f 40
fd3f686c
VZ
41// due to circular header dependencies this function has to be declared here
42// (normally it's found in utils.h which includes itself list.h...)
9d2f3c71 43extern WXDLLEXPORT wxChar* copystring(const wxChar *s);
fd3f686c
VZ
44
45class WXDLLEXPORT wxObjectListNode;
46typedef wxObjectListNode wxNode;
47
48// undef it to get rid of old, deprecated functions
49#define wxLIST_COMPATIBILITY
c801d85f 50
fd3f686c
VZ
51// -----------------------------------------------------------------------------
52// constants
53// -----------------------------------------------------------------------------
54enum wxKeyType
55{
56 wxKEY_NONE,
57 wxKEY_INTEGER,
58 wxKEY_STRING
59};
60
61// -----------------------------------------------------------------------------
62// types
63// -----------------------------------------------------------------------------
64
65// type of compare function for list sort operation (as in 'qsort'): it should
66// return a negative value, 0 or positive value if the first element is less
67// than, equal or greater than the second
54da4255 68typedef int (* LINKAGEMODE wxSortCompareFunction)(const void *elem1, const void *elem2);
fd3f686c
VZ
69
70//
54da4255 71typedef int (* LINKAGEMODE wxListIterateFunction)(void *current);
fd3f686c
VZ
72
73// -----------------------------------------------------------------------------
74// key stuff: a list may be optionally keyed on integer or string key
75// -----------------------------------------------------------------------------
76
77union wxListKeyValue
c801d85f 78{
c801d85f 79 long integer;
9d2f3c71 80 wxChar *string;
c801d85f
KB
81};
82
fd3f686c
VZ
83// a struct which may contain both types of keys
84//
85// implementation note: on one hand, this class allows to have only one function
86// for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
87// resolve ambiguity which we would otherwise have with wxStringList::Find() and
88// wxList::Find(const char *).
89class WXDLLEXPORT wxListKey
90{
91public:
92 // implicit ctors
93 wxListKey()
94 { m_keyType = wxKEY_NONE; }
95 wxListKey(long i)
96 { m_keyType = wxKEY_INTEGER; m_key.integer = i; }
9d2f3c71
OK
97 wxListKey(const wxChar *s)
98 { m_keyType = wxKEY_STRING; m_key.string = wxStrdup(s); }
fd3f686c 99 wxListKey(const wxString& s)
9d2f3c71 100 { m_keyType = wxKEY_STRING; m_key.string = wxStrdup(s.c_str()); }
fd3f686c
VZ
101
102 // accessors
103 wxKeyType GetKeyType() const { return m_keyType; }
9d2f3c71 104 const wxChar *GetString() const
fd3f686c
VZ
105 { wxASSERT( m_keyType == wxKEY_STRING ); return m_key.string; }
106 long GetNumber() const
107 { wxASSERT( m_keyType == wxKEY_INTEGER ); return m_key.integer; }
108
6164d85e
JS
109 // comparison
110 // Note: implementation moved to list.cpp to prevent BC++ inline
111 // expansion warning.
112 bool operator==(wxListKeyValue value) const ;
fd3f686c
VZ
113
114 // dtor
115 ~wxListKey()
116 {
117 if ( m_keyType == wxKEY_STRING )
118 free(m_key.string);
119 }
120
121private:
122 wxKeyType m_keyType;
123 wxListKeyValue m_key;
124};
125
126// -----------------------------------------------------------------------------
127// wxNodeBase class is a (base for) node in a double linked list
128// -----------------------------------------------------------------------------
129
2432b92d
JS
130WXDLLEXPORT_DATA(extern wxListKey) wxDefaultListKey;
131
fd3f686c
VZ
132class WXDLLEXPORT wxNodeBase
133{
134friend class wxListBase;
135public:
136 // ctor
137 wxNodeBase(wxListBase *list = (wxListBase *)NULL,
138 wxNodeBase *previous = (wxNodeBase *)NULL,
139 wxNodeBase *next = (wxNodeBase *)NULL,
140 void *data = NULL,
2432b92d 141 const wxListKey& key = wxDefaultListKey);
fd3f686c
VZ
142
143 virtual ~wxNodeBase();
144
f03fc89f 145 // FIXME no check is done that the list is really keyed on strings
9d2f3c71 146 const wxChar *GetKeyString() const { return m_key.string; }
74e34480 147 long GetKeyInteger() const { return m_key.integer; }
fd3f686c 148
4fabb575 149 // Necessary for some existing code
9d2f3c71 150 void SetKeyString(wxChar* s) { m_key.string = s; }
4fabb575
JS
151 void SetKeyInteger(long i) { m_key.integer = i; }
152
fd3f686c
VZ
153#ifdef wxLIST_COMPATIBILITY
154 // compatibility methods
155 wxNode *Next() const { return (wxNode *)GetNext(); }
156 wxNode *Previous() const { return (wxNode *)GetPrevious(); }
157 wxObject *Data() const { return (wxObject *)GetData(); }
158#endif // wxLIST_COMPATIBILITY
159
160protected:
161 // all these are going to be "overloaded" in the derived classes
162 wxNodeBase *GetNext() const { return m_next; }
163 wxNodeBase *GetPrevious() const { return m_previous; }
164
165 void *GetData() const { return m_data; }
166 void SetData(void *data) { m_data = data; }
167
3c67202d 168 // get 0-based index of this node within the list or wxNOT_FOUND
77c5eefb
VZ
169 int IndexOf() const;
170
fd3f686c
VZ
171 virtual void DeleteData() { }
172
173private:
174 // optional key stuff
175 wxListKeyValue m_key;
176
177 void *m_data; // user data
178 wxNodeBase *m_next, // next and previous nodes in the list
179 *m_previous;
180
181 wxListBase *m_list; // list we belong to
182};
183
184// -----------------------------------------------------------------------------
185// a double-linked list class
186// -----------------------------------------------------------------------------
187class WXDLLEXPORT wxListBase : public wxObject
188{
bcaa23de
VZ
189friend class wxNodeBase; // should be able to call DetachNode()
190friend class wxHashTableBase; // should be able to call untyped Find()
fd3f686c
VZ
191public:
192 // default ctor & dtor
193 wxListBase(wxKeyType keyType = wxKEY_NONE) { Init(keyType); }
194 virtual ~wxListBase();
195
196 // accessors
197 // count of items in the list
198 size_t GetCount() const { return m_count; }
c801d85f 199
fd3f686c 200 // operations
e146b8c8 201
fd3f686c 202 // delete all nodes
db9504c5 203 void Clear();
e146b8c8 204
fd3f686c
VZ
205 // instruct it to destroy user data when deleting nodes
206 void DeleteContents(bool destroy) { m_destroy = destroy; }
207
907789a0
RR
208 // query if to delete
209 bool GetDeleteContents() const
210 { return m_destroy; }
e146b8c8 211
907789a0
RR
212 // get the keytype
213 wxKeyType GetKeyType() const
214 { return m_keyType; }
215
216 // set the keytype (required by the serial code)
217 void SetKeyType(wxKeyType keyType)
218 { wxASSERT( m_count==0 ); m_keyType = keyType; }
219
e146b8c8
VZ
220#ifdef wxLIST_COMPATIBILITY
221 int Number() const { return GetCount(); }
222 wxNode *First() const { return (wxNode *)GetFirst(); }
223 wxNode *Last() const { return (wxNode *)GetLast(); }
224 wxNode *Nth(size_t index) const { return (wxNode *)Item(index); }
225#endif // wxLIST_COMPATIBILITY
226
fd3f686c 227protected:
a3ef5bf5 228
fd3f686c
VZ
229 // all methods here are "overloaded" in derived classes to provide compile
230 // time type checking
231
232 // create a node for the list of this type
233 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next,
234 void *data,
2432b92d 235 const wxListKey& key = wxDefaultListKey) = 0;
fd3f686c 236
a3ef5bf5
JS
237// Can't access these from derived classes otherwise (bug in Salford C++?)
238#ifdef __SALFORDC__
239public:
240#endif
241
fd3f686c
VZ
242 // ctors
243 // from an array
244 wxListBase(size_t count, void *elements[]);
245 // from a sequence of objects
246 wxListBase(void *object, ... /* terminate with NULL */);
247
a3ef5bf5 248protected:
fd3f686c
VZ
249 // copy ctor and assignment operator
250 wxListBase(const wxListBase& list)
251 { DoCopy(list); }
252 wxListBase& operator=(const wxListBase& list)
253 { Clear(); DoCopy(list); return *this; }
254
255 // get list head/tail
256 wxNodeBase *GetFirst() const { return m_nodeFirst; }
257 wxNodeBase *GetLast() const { return m_nodeLast; }
258
259 // by (0-based) index
260 wxNodeBase *Item(size_t index) const;
261
262 // get the list item's data
263 void *operator[](size_t index) const
a802c3a1 264 { wxNodeBase *node = Item(index); return node ? node->GetData() : (wxNodeBase*)NULL; }
fd3f686c
VZ
265
266 // operations
267 // append to end of list
268 wxNodeBase *Append(void *object);
269 // insert a new item at the beginning of the list
a802c3a1 270 wxNodeBase *Insert(void *object) { return Insert( (wxNodeBase*)NULL, object); }
d8996187
VZ
271 // insert a new item at the given position
272 wxNodeBase *Insert(size_t pos, void *object)
273 { return pos == GetCount() ? Append(object)
274 : Insert(Item(pos), object); }
fd3f686c
VZ
275 // insert before given node or at front of list if prev == NULL
276 wxNodeBase *Insert(wxNodeBase *prev, void *object);
277
278 // keyed append
279 wxNodeBase *Append(long key, void *object);
9d2f3c71 280 wxNodeBase *Append(const wxChar *key, void *object);
fd3f686c
VZ
281
282 // removes node from the list but doesn't delete it (returns pointer
283 // to the node or NULL if it wasn't found in the list)
284 wxNodeBase *DetachNode(wxNodeBase *node);
285 // delete element from list, returns FALSE if node not found
286 bool DeleteNode(wxNodeBase *node);
287 // finds object pointer and deletes node (and object if DeleteContents
288 // is on), returns FALSE if object not found
77c5eefb 289 bool DeleteObject(void *object);
fd3f686c
VZ
290
291 // search (all return NULL if item not found)
292 // by data
293 wxNodeBase *Find(void *object) const;
294
295 // by key
296 wxNodeBase *Find(const wxListKey& key) const;
297
3c67202d 298 // get 0-based index of object or wxNOT_FOUND
77c5eefb
VZ
299 int IndexOf( void *object ) const;
300
fd3f686c
VZ
301 // this function allows the sorting of arbitrary lists by giving
302 // a function to compare two list elements. The list is sorted in place.
6164d85e 303 void Sort(const wxSortCompareFunction compfunc);
fd3f686c
VZ
304
305 // functions for iterating over the list
306 void *FirstThat(wxListIterateFunction func);
307 void ForEach(wxListIterateFunction func);
308 void *LastThat(wxListIterateFunction func);
e146b8c8 309
fd3f686c
VZ
310private:
311 // helpers
312 // common part of all ctors
62448488 313 void Init(wxKeyType keyType = wxKEY_NONE);
fd3f686c
VZ
314 // common part of copy ctor and assignment operator
315 void DoCopy(const wxListBase& list);
316 // common part of all Append()s
317 wxNodeBase *AppendCommon(wxNodeBase *node);
318 // free node's data and node itself
319 void DoDeleteNode(wxNodeBase *node);
320
321 size_t m_count; // number of elements in the list
322 bool m_destroy; // destroy user data when deleting list items?
323 wxNodeBase *m_nodeFirst, // pointers to the head and tail of the list
324 *m_nodeLast;
325
326 wxKeyType m_keyType; // type of our keys (may be wxKEY_NONE)
327};
328
329// -----------------------------------------------------------------------------
330// macros for definition of "template" list type
331// -----------------------------------------------------------------------------
332
333// and now some heavy magic...
334
335// declare a list type named 'name' and containing elements of type 'T *'
336// (as a by product of macro expansion you also get wx##name##Node
ce3ed50d 337// wxNode-derived type)
fd3f686c
VZ
338//
339// implementation details:
ce3ed50d 340// 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
fd3f686c
VZ
341// for the list of given type - this allows us to pass only the list name
342// to WX_DEFINE_LIST() even if it needs both the name and the type
343//
ce3ed50d
JS
344// 2. We redefine all non-type-safe wxList functions with type-safe versions
345// which don't take any space (everything is inline), but bring compile
fd3f686c 346// time error checking.
f03fc89f
VZ
347//
348// 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
349// a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
350// generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
351// interesting capability to store polymorphic objects in the list and is
352// particularly useful with, for example, "wxWindow *" list where the
353// wxWindowBase pointers are put into the list, but wxWindow pointers are
354// retrieved from it.
355
356#define WX_DECLARE_LIST_3(T, Tbase, name, nodetype) \
ba059d80 357 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
fd3f686c
VZ
358 \
359 class WXDLLEXPORT nodetype : public wxNodeBase \
360 { \
361 public: \
362 nodetype(wxListBase *list = (wxListBase *)NULL, \
363 nodetype *previous = (nodetype *)NULL, \
364 nodetype *next = (nodetype *)NULL, \
7f985bd3 365 T *data = (T *)NULL, \
e146b8c8 366 const wxListKey& key = wxDefaultListKey) \
fd3f686c
VZ
367 : wxNodeBase(list, previous, next, data, key) { } \
368 \
369 nodetype *GetNext() const \
370 { return (nodetype *)wxNodeBase::GetNext(); } \
371 nodetype *GetPrevious() const \
372 { return (nodetype *)wxNodeBase::GetPrevious(); } \
373 \
374 T *GetData() const \
375 { return (T *)wxNodeBase::GetData(); } \
376 void SetData(T *data) \
377 { wxNodeBase::SetData(data); } \
378 \
379 virtual void DeleteData(); \
380 }; \
381 \
e146b8c8 382 class WXDLLEXPORT name : public wxListBase \
fd3f686c
VZ
383 { \
384 public: \
e2a3cc0c
VZ
385 typedef nodetype Node; \
386 \
fd3f686c
VZ
387 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
388 { } \
389 name(size_t count, T *elements[]) \
390 : wxListBase(count, (void **)elements) { } \
391 \
392 nodetype *GetFirst() const \
393 { return (nodetype *)wxListBase::GetFirst(); } \
394 nodetype *GetLast() const \
395 { return (nodetype *)wxListBase::GetLast(); } \
396 \
397 nodetype *Item(size_t index) const \
398 { return (nodetype *)wxListBase::Item(index); } \
399 \
400 T *operator[](size_t index) const \
401 { \
402 nodetype *node = Item(index); \
7f985bd3 403 return node ? (T*)(node->GetData()) : (T*)NULL; \
fd3f686c
VZ
404 } \
405 \
f03fc89f 406 nodetype *Append(Tbase *object) \
fd3f686c 407 { return (nodetype *)wxListBase::Append(object); } \
f03fc89f 408 nodetype *Insert(Tbase *object) \
a802c3a1 409 { return (nodetype *)Insert((nodetype*)NULL, object); } \
d8996187
VZ
410 nodetype *Insert(size_t pos, Tbase *object) \
411 { return (nodetype *)wxListBase::Insert(pos, object); } \
f03fc89f 412 nodetype *Insert(nodetype *prev, Tbase *object) \
fd3f686c
VZ
413 { return (nodetype *)wxListBase::Insert(prev, object); } \
414 \
415 nodetype *Append(long key, void *object) \
416 { return (nodetype *)wxListBase::Append(key, object); } \
9d2f3c71 417 nodetype *Append(const wxChar *key, void *object) \
fd3f686c
VZ
418 { return (nodetype *)wxListBase::Append(key, object); } \
419 \
420 nodetype *DetachNode(nodetype *node) \
421 { return (nodetype *)wxListBase::DetachNode(node); } \
422 bool DeleteNode(nodetype *node) \
423 { return wxListBase::DeleteNode(node); } \
f03fc89f 424 bool DeleteObject(Tbase *object) \
fd3f686c
VZ
425 { return wxListBase::DeleteObject(object); } \
426 \
f03fc89f 427 nodetype *Find(Tbase *object) const \
fd3f686c
VZ
428 { return (nodetype *)wxListBase::Find(object); } \
429 \
430 virtual nodetype *Find(const wxListKey& key) const \
431 { return (nodetype *)wxListBase::Find(key); } \
432 \
f03fc89f 433 int IndexOf(Tbase *object) const \
77c5eefb
VZ
434 { return wxListBase::IndexOf(object); } \
435 \
fd3f686c
VZ
436 void Sort(wxSortFuncFor_##name func) \
437 { wxListBase::Sort((wxSortCompareFunction)func); } \
438 \
439 protected: \
440 wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
441 void *data, \
e146b8c8 442 const wxListKey& key = wxDefaultListKey) \
fd3f686c
VZ
443 { \
444 return new nodetype(this, \
445 (nodetype *)prev, (nodetype *)next, \
446 (T *)data, key); \
447 } \
385bcb35 448 }
fd3f686c 449
f03fc89f
VZ
450#define WX_DECLARE_LIST_2(elementtype, listname, nodename) \
451 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename)
452
fd3f686c
VZ
453#define WX_DECLARE_LIST(elementtype, listname) \
454 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
455 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node)
456
457// this macro must be inserted in your program after
458// #include <wx/listimpl.cpp>
459#define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
460
fd3f686c
VZ
461// =============================================================================
462// now we can define classes 100% compatible with the old ones
463// =============================================================================
464
e146b8c8 465// ----------------------------------------------------------------------------
f03fc89f 466// commonly used list classes
e146b8c8
VZ
467// ----------------------------------------------------------------------------
468
fd3f686c
VZ
469#ifdef wxLIST_COMPATIBILITY
470
471// -----------------------------------------------------------------------------
472// wxList compatibility class: in fact, it's a list of wxObjects
473// -----------------------------------------------------------------------------
474
475WX_DECLARE_LIST_2(wxObject, wxObjectList, wxObjectListNode);
476
477class WXDLLEXPORT wxList : public wxObjectList
c801d85f 478{
fd3f686c
VZ
479public:
480 wxList(int key_type = wxKEY_NONE) : wxObjectList((wxKeyType)key_type) { }
481
482 // compatibility methods
3bef6c4c
VZ
483 void Sort(wxSortCompareFunction compfunc) { wxListBase::Sort(compfunc); }
484
fd3f686c 485 wxNode *Member(wxObject *object) const { return (wxNode *)Find(object); }
c801d85f
KB
486};
487
fd3f686c
VZ
488// -----------------------------------------------------------------------------
489// wxStringList class for compatibility with the old code
490// -----------------------------------------------------------------------------
77c5eefb 491
9d2f3c71 492WX_DECLARE_LIST_2(wxChar, wxStringListBase, wxStringListNode);
fd3f686c
VZ
493
494class WXDLLEXPORT wxStringList : public wxStringListBase
c801d85f 495{
fd3f686c
VZ
496public:
497 // ctors and such
498 // default
499 wxStringList() { DeleteContents(TRUE); }
9d2f3c71 500 wxStringList(const wxChar *first ...);
fd3f686c 501
db9504c5
VZ
502 // copying the string list: the strings are copied, too (extremely
503 // inefficient!)
504 wxStringList(const wxStringList& other) { DoCopy(other); }
505 wxStringList& operator=(const wxStringList& other)
506 { Clear(); DoCopy(other); return *this; }
507
fd3f686c
VZ
508 // operations
509 // makes a copy of the string
9d2f3c71 510 wxNode *Add(const wxChar *s)
fd3f686c
VZ
511 { return (wxNode *)wxStringListBase::Append(copystring(s)); }
512
9d2f3c71 513 bool Delete(const wxChar *s);
fd3f686c 514
9d2f3c71
OK
515 wxChar **ListToArray(bool new_copies = FALSE) const;
516 bool Member(const wxChar *s) const;
fd3f686c
VZ
517
518 // alphabetic sort
519 void Sort();
520
db9504c5
VZ
521private:
522 void DoCopy(const wxStringList&); // common part of copy ctor and operator=
c801d85f
KB
523};
524
fd3f686c
VZ
525#endif // wxLIST_COMPATIBILITY
526
c801d85f 527#endif
34138703 528 // _WX_LISTH__