]> git.saurik.com Git - wxWidgets.git/blame - src/common/list.cpp
Reorganize wxCollapsiblePane event and layout code under GTK+
[wxWidgets.git] / src / common / list.cpp
CommitLineData
fd3f686c 1////////////////////////////////////////////////////////////////////////////////
7ec69821 2// Name: src/common/list.cpp
c801d85f
KB
3// Purpose: wxList implementation
4// Author: Julian Smart
fd3f686c 5// Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
c801d85f
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
fd3f686c 10////////////////////////////////////////////////////////////////////////////////
c801d85f 11
fd3f686c
VZ
12// =============================================================================
13// declarations
14// =============================================================================
15
16// -----------------------------------------------------------------------------
17// headers
18// -----------------------------------------------------------------------------
7daab453 19
c801d85f
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
fd3f686c 24 #pragma hdrstop
c801d85f
KB
25#endif
26
fd3f686c
VZ
27#include <stdarg.h>
28#include <stdlib.h>
29#include <string.h>
30
c801d85f 31#ifndef WX_PRECOMP
fd3f686c 32 #include "wx/list.h"
062ccd65 33 #include "wx/crt.h"
c801d85f
KB
34#endif
35
df5168c4
MB
36#if !wxUSE_STL
37
fd3f686c
VZ
38// =============================================================================
39// implementation
40// =============================================================================
c801d85f 41
ff528365
VZ
42// -----------------------------------------------------------------------------
43// wxListKey
44// -----------------------------------------------------------------------------
8a2c6ef8
JS
45wxListKey wxDefaultListKey;
46
ff528365
VZ
47bool wxListKey::operator==(wxListKeyValue value) const
48{
49 switch ( m_keyType )
50 {
51 default:
223d09f6 52 wxFAIL_MSG(wxT("bad key type."));
ff528365
VZ
53 // let compiler optimize the line above away in release build
54 // by not putting return here...
55
56 case wxKEY_STRING:
81727065 57 return *m_key.string == *value.string;
ff528365
VZ
58
59 case wxKEY_INTEGER:
60 return m_key.integer == value.integer;
61 }
77c5eefb 62}
ff528365 63
fd3f686c
VZ
64// -----------------------------------------------------------------------------
65// wxNodeBase
66// -----------------------------------------------------------------------------
c801d85f 67
fd3f686c
VZ
68wxNodeBase::wxNodeBase(wxListBase *list,
69 wxNodeBase *previous, wxNodeBase *next,
70 void *data, const wxListKey& key)
c801d85f 71{
fd3f686c
VZ
72 m_list = list;
73 m_data = data;
74 m_previous = previous;
75 m_next = next;
77c5eefb 76
fd3f686c
VZ
77 switch ( key.GetKeyType() )
78 {
79 case wxKEY_NONE:
80 break;
77c5eefb 81
fd3f686c
VZ
82 case wxKEY_INTEGER:
83 m_key.integer = key.GetNumber();
84 break;
77c5eefb 85
fd3f686c
VZ
86 case wxKEY_STRING:
87 // to be free()d later
81727065 88 m_key.string = new wxString(key.GetString());
fd3f686c 89 break;
77c5eefb 90
fd3f686c 91 default:
223d09f6 92 wxFAIL_MSG(wxT("invalid key type"));
fd3f686c 93 }
77c5eefb 94
fd3f686c
VZ
95 if ( previous )
96 previous->m_next = this;
77c5eefb 97
fd3f686c
VZ
98 if ( next )
99 next->m_previous = this;
100}
c801d85f 101
fd3f686c
VZ
102wxNodeBase::~wxNodeBase()
103{
104 // handle the case when we're being deleted from the list by the user (i.e.
105 // not by the list itself from DeleteNode) - we must do it for
106 // compatibility with old code
107 if ( m_list != NULL )
108 {
09914df7
VZ
109 if ( m_list->m_keyType == wxKEY_STRING )
110 {
81727065 111 delete m_key.string;
09914df7
VZ
112 }
113
fd3f686c
VZ
114 m_list->DetachNode(this);
115 }
c801d85f
KB
116}
117
77c5eefb
VZ
118int wxNodeBase::IndexOf() const
119{
223d09f6 120 wxCHECK_MSG( m_list, wxNOT_FOUND, wxT("node doesn't belong to a list in IndexOf"));
77c5eefb
VZ
121
122 // It would be more efficient to implement IndexOf() completely inside
123 // wxListBase (only traverse the list once), but this is probably a more
124 // reusable way of doing it. Can always be optimized at a later date (since
125 // IndexOf() resides in wxListBase as well) if efficiency is a problem.
126 int i;
127 wxNodeBase *prev = m_previous;
128
129 for( i = 0; prev; i++ )
130 {
131 prev = prev->m_previous;
132 }
133
134 return i;
135}
136
fd3f686c
VZ
137// -----------------------------------------------------------------------------
138// wxListBase
139// -----------------------------------------------------------------------------
140
62448488 141void wxListBase::Init(wxKeyType keyType)
c801d85f 142{
fd3f686c 143 m_nodeFirst =
d3b9f782 144 m_nodeLast = NULL;
fd3f686c 145 m_count = 0;
f644b28c 146 m_destroy = false;
fd3f686c
VZ
147 m_keyType = keyType;
148}
c801d85f 149
fd3f686c
VZ
150wxListBase::wxListBase(size_t count, void *elements[])
151{
152 Init();
c801d85f 153
fd3f686c
VZ
154 for ( size_t n = 0; n < count; n++ )
155 {
156 Append(elements[n]);
157 }
c801d85f
KB
158}
159
fd3f686c 160void wxListBase::DoCopy(const wxListBase& list)
c801d85f 161{
fd3f686c 162 wxASSERT_MSG( !list.m_destroy,
223d09f6 163 wxT("copying list which owns it's elements is a bad idea") );
c801d85f 164
fd3f686c
VZ
165 m_destroy = list.m_destroy;
166 m_keyType = list.m_keyType;
167 m_nodeFirst =
d3b9f782 168 m_nodeLast = NULL;
c801d85f 169
3d0145a5
VZ
170 switch (m_keyType)
171 {
ecf9e593
VS
172 case wxKEY_INTEGER:
173 {
bcaa23de 174 long key;
ecf9e593
VS
175 for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() )
176 {
177 key = node->GetKeyInteger();
178 Append(key, node->GetData());
179 }
180 break;
181 }
182
183 case wxKEY_STRING:
184 {
bcaa23de 185 const wxChar *key;
ecf9e593
VS
186 for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() )
187 {
188 key = node->GetKeyString();
189 Append(key, node->GetData());
190 }
191 break;
192 }
193
194 default:
195 {
196 for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() )
197 {
198 Append(node->GetData());
199 }
200 break;
201 }
fd3f686c 202 }
f6bcfd97
BP
203
204 wxASSERT_MSG( m_count == list.m_count, _T("logic error in wxList::DoCopy") );
c801d85f
KB
205}
206
fd3f686c 207wxListBase::~wxListBase()
c801d85f 208{
fd3f686c
VZ
209 wxNodeBase *each = m_nodeFirst;
210 while ( each != NULL )
211 {
212 wxNodeBase *next = each->GetNext();
213 DoDeleteNode(each);
214 each = next;
215 }
c801d85f
KB
216}
217
fd3f686c 218wxNodeBase *wxListBase::AppendCommon(wxNodeBase *node)
c801d85f 219{
fd3f686c
VZ
220 if ( !m_nodeFirst )
221 {
222 m_nodeFirst = node;
223 m_nodeLast = m_nodeFirst;
224 }
225 else
226 {
227 m_nodeLast->m_next = node;
228 m_nodeLast = node;
229 }
230
231 m_count++;
232
233 return node;
c801d85f
KB
234}
235
fd3f686c 236wxNodeBase *wxListBase::Append(void *object)
c801d85f 237{
fd3f686c 238 // all objects in a keyed list should have a key
d3b9f782 239 wxCHECK_MSG( m_keyType == wxKEY_NONE, NULL,
223d09f6 240 wxT("need a key for the object to append") );
c801d85f 241
7daab453
VZ
242 // we use wxDefaultListKey even though it is the default parameter value
243 // because gcc under Mac OS X seems to miscompile this call otherwise
d3b9f782 244 wxNodeBase *node = CreateNode(m_nodeLast, NULL, object,
7daab453 245 wxDefaultListKey);
fd3f686c
VZ
246
247 return AppendCommon(node);
c801d85f
KB
248}
249
fd3f686c 250wxNodeBase *wxListBase::Append(long key, void *object)
c801d85f 251{
fd3f686c
VZ
252 wxCHECK_MSG( (m_keyType == wxKEY_INTEGER) ||
253 (m_keyType == wxKEY_NONE && m_count == 0),
d3b9f782 254 NULL,
223d09f6 255 wxT("can't append object with numeric key to this list") );
fd3f686c 256
d3b9f782 257 wxNodeBase *node = CreateNode(m_nodeLast, NULL, object, key);
fd3f686c 258 return AppendCommon(node);
c801d85f
KB
259}
260
81727065 261wxNodeBase *wxListBase::Append (const wxString& key, void *object)
c801d85f 262{
fd3f686c
VZ
263 wxCHECK_MSG( (m_keyType == wxKEY_STRING) ||
264 (m_keyType == wxKEY_NONE && m_count == 0),
d3b9f782 265 NULL,
223d09f6 266 wxT("can't append object with string key to this list") );
fd3f686c 267
d3b9f782 268 wxNodeBase *node = CreateNode(m_nodeLast, NULL, object, key);
fd3f686c
VZ
269 return AppendCommon(node);
270}
c801d85f 271
fd3f686c
VZ
272wxNodeBase *wxListBase::Insert(wxNodeBase *position, void *object)
273{
274 // all objects in a keyed list should have a key
d3b9f782 275 wxCHECK_MSG( m_keyType == wxKEY_NONE, NULL,
223d09f6 276 wxT("need a key for the object to insert") );
c801d85f 277
d3b9f782 278 wxCHECK_MSG( !position || position->m_list == this, NULL,
223d09f6 279 wxT("can't insert before a node from another list") );
ff528365
VZ
280
281 // previous and next node for the node being inserted
282 wxNodeBase *prev, *next;
fd3f686c 283 if ( position )
ff528365 284 {
fd3f686c 285 prev = position->GetPrevious();
ff528365
VZ
286 next = position;
287 }
288 else
289 {
290 // inserting in the beginning of the list
d3b9f782 291 prev = NULL;
ff528365
VZ
292 next = m_nodeFirst;
293 }
c801d85f 294
7daab453
VZ
295 // wxDefaultListKey: see comment in Append() above
296 wxNodeBase *node = CreateNode(prev, next, object, wxDefaultListKey);
fd3f686c 297 if ( !m_nodeFirst )
c801d85f 298 {
fd3f686c 299 m_nodeLast = node;
c801d85f 300 }
c801d85f 301
fd3f686c 302 if ( prev == NULL )
c801d85f 303 {
fd3f686c 304 m_nodeFirst = node;
c801d85f 305 }
c801d85f 306
fd3f686c
VZ
307 m_count++;
308
c801d85f
KB
309 return node;
310}
311
fd3f686c 312wxNodeBase *wxListBase::Item(size_t n) const
c801d85f 313{
fd3f686c 314 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
c801d85f 315 {
fd3f686c
VZ
316 if ( n-- == 0 )
317 {
318 return current;
319 }
c801d85f 320 }
c801d85f 321
223d09f6 322 wxFAIL_MSG( wxT("invalid index in wxListBase::Item") );
c801d85f 323
d3b9f782 324 return NULL;
c801d85f
KB
325}
326
fd3f686c 327wxNodeBase *wxListBase::Find(const wxListKey& key) const
c801d85f 328{
fd3f686c 329 wxASSERT_MSG( m_keyType == key.GetKeyType(),
223d09f6 330 wxT("this list is not keyed on the type of this key") );
c801d85f 331
fd3f686c
VZ
332 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
333 {
334 if ( key == current->m_key )
335 {
336 return current;
337 }
338 }
c801d85f 339
fd3f686c 340 // not found
d3b9f782 341 return NULL;
c801d85f
KB
342}
343
22d080f3 344wxNodeBase *wxListBase::Find(const void *object) const
c801d85f 345{
fd3f686c 346 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
c801d85f 347 {
fd3f686c
VZ
348 if ( current->GetData() == object )
349 return current;
c801d85f 350 }
fd3f686c
VZ
351
352 // not found
d3b9f782 353 return NULL;
c801d85f
KB
354}
355
77c5eefb
VZ
356int wxListBase::IndexOf(void *object) const
357{
358 wxNodeBase *node = Find( object );
359
3c67202d 360 return node ? node->IndexOf() : wxNOT_FOUND;
77c5eefb
VZ
361}
362
fd3f686c 363void wxListBase::DoDeleteNode(wxNodeBase *node)
c801d85f 364{
fd3f686c
VZ
365 // free node's data
366 if ( m_keyType == wxKEY_STRING )
c801d85f 367 {
fd3f686c 368 free(node->m_key.string);
c801d85f 369 }
c801d85f 370
fd3f686c 371 if ( m_destroy )
c801d85f 372 {
fd3f686c 373 node->DeleteData();
c801d85f 374 }
c801d85f 375
09914df7
VZ
376 // so that the node knows that it's being deleted by the list
377 node->m_list = NULL;
fd3f686c 378 delete node;
c801d85f
KB
379}
380
fd3f686c 381wxNodeBase *wxListBase::DetachNode(wxNodeBase *node)
c801d85f 382{
223d09f6 383 wxCHECK_MSG( node, NULL, wxT("detaching NULL wxNodeBase") );
fd3f686c 384 wxCHECK_MSG( node->m_list == this, NULL,
223d09f6 385 wxT("detaching node which is not from this list") );
c801d85f 386
fd3f686c
VZ
387 // update the list
388 wxNodeBase **prevNext = node->GetPrevious() ? &node->GetPrevious()->m_next
389 : &m_nodeFirst;
390 wxNodeBase **nextPrev = node->GetNext() ? &node->GetNext()->m_previous
391 : &m_nodeLast;
c801d85f 392
fd3f686c
VZ
393 *prevNext = node->GetNext();
394 *nextPrev = node->GetPrevious();
c801d85f 395
fd3f686c 396 m_count--;
c801d85f 397
fd3f686c
VZ
398 // mark the node as not belonging to this list any more
399 node->m_list = NULL;
c801d85f 400
fd3f686c 401 return node;
c801d85f
KB
402}
403
fd3f686c 404bool wxListBase::DeleteNode(wxNodeBase *node)
c801d85f 405{
fd3f686c 406 if ( !DetachNode(node) )
f644b28c 407 return false;
fd3f686c
VZ
408
409 DoDeleteNode(node);
410
f644b28c 411 return true;
c801d85f
KB
412}
413
fd3f686c 414bool wxListBase::DeleteObject(void *object)
c801d85f 415{
fd3f686c
VZ
416 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
417 {
418 if ( current->GetData() == object )
419 {
420 DeleteNode(current);
f644b28c 421 return true;
fd3f686c
VZ
422 }
423 }
424
425 // not found
f644b28c 426 return false;
c801d85f
KB
427}
428
fd3f686c 429void wxListBase::Clear()
c801d85f 430{
fd3f686c
VZ
431 wxNodeBase *current = m_nodeFirst;
432 while ( current )
c801d85f 433 {
fd3f686c
VZ
434 wxNodeBase *next = current->GetNext();
435 DoDeleteNode(current);
436 current = next;
c801d85f 437 }
fd3f686c
VZ
438
439 m_nodeFirst =
d3b9f782 440 m_nodeLast = NULL;
fd3f686c
VZ
441
442 m_count = 0;
c801d85f
KB
443}
444
fd3f686c 445void wxListBase::ForEach(wxListIterateFunction F)
c801d85f 446{
fd3f686c
VZ
447 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
448 {
449 (*F)(current->GetData());
c801d85f
KB
450 }
451}
fd3f686c
VZ
452
453void *wxListBase::FirstThat(wxListIterateFunction F)
c801d85f 454{
fd3f686c
VZ
455 for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() )
456 {
457 if ( (*F)(current->GetData()) )
458 return current->GetData();
c801d85f 459 }
fd3f686c 460
d3b9f782 461 return NULL;
c801d85f 462}
fd3f686c
VZ
463
464void *wxListBase::LastThat(wxListIterateFunction F)
c801d85f 465{
fd3f686c
VZ
466 for ( wxNodeBase *current = GetLast(); current; current = current->GetPrevious() )
467 {
468 if ( (*F)(current->GetData()) )
469 return current->GetData();
c801d85f 470 }
fd3f686c 471
d3b9f782 472 return NULL;
c801d85f
KB
473}
474
475// (stefan.hammes@urz.uni-heidelberg.de)
476//
477// function for sorting lists. the concept is borrowed from 'qsort'.
478// by giving a sort function, arbitrary lists can be sorted.
479// method:
480// - put wxObject pointers into an array
481// - sort the array with qsort
482// - put back the sorted wxObject pointers into the list
483//
484// CAVE: the sort function receives pointers to wxObject pointers (wxObject **),
485// so dereference right!
486// EXAMPLE:
487// int listcompare(const void *arg1, const void *arg2)
488// {
489// return(compare(**(wxString **)arg1,
490// **(wxString **)arg2));
491// }
492//
493// void main()
fd3f686c
VZ
494// {
495// wxListBase list;
c801d85f
KB
496//
497// list.Append(new wxString("DEF"));
498// list.Append(new wxString("GHI"));
499// list.Append(new wxString("ABC"));
500// list.Sort(listcompare);
501// }
502
fd3f686c 503void wxListBase::Sort(const wxSortCompareFunction compfunc)
c801d85f 504{
fd3f686c
VZ
505 // allocate an array for the wxObject pointers of the list
506 const size_t num = GetCount();
507 void **objArray = new void *[num];
508 void **objPtr = objArray;
509
510 // go through the list and put the pointers into the array
511 wxNodeBase *node;
b1d4dd7a 512 for ( node = GetFirst(); node; node = node->GetNext() )
fd3f686c 513 {
b1d4dd7a 514 *objPtr++ = node->GetData();
fd3f686c
VZ
515 }
516
517 // sort the array
1c193821
JS
518 qsort((void *)objArray,num,sizeof(wxObject *),
519#ifdef __WXWINCE__
520 (int (__cdecl *)(const void *,const void *))
521#endif
522 compfunc);
fd3f686c
VZ
523
524 // put the sorted pointers back into the list
525 objPtr = objArray;
b1d4dd7a 526 for ( node = GetFirst(); node; node = node->GetNext() )
fd3f686c
VZ
527 {
528 node->SetData(*objPtr++);
529 }
530
531 // free the array
532 delete[] objArray;
c801d85f
KB
533}
534
df5168c4
MB
535void wxListBase::Reverse()
536{
537 wxNodeBase* node = m_nodeFirst;
538 wxNodeBase* tmp;
539
540 while (node)
541 {
542 // swap prev and next pointers
543 tmp = node->m_next;
544 node->m_next = node->m_previous;
545 node->m_previous = tmp;
546
547 // this is the node that was next before swapping
548 node = tmp;
549 }
550
551 // swap first and last node
552 tmp = m_nodeFirst; m_nodeFirst = m_nodeLast; m_nodeLast = tmp;
553}
554
555void wxListBase::DeleteNodes(wxNodeBase* first, wxNodeBase* last)
556{
557 wxNodeBase* node = first;
558
559 while (node != last)
560 {
561 wxNodeBase* next = node->GetNext();
562 DeleteNode(node);
563 node = next;
564 }
565}
566
f98bd52a
VZ
567// ============================================================================
568// compatibility section from now on
569// ============================================================================
570
571#ifdef wxLIST_COMPATIBILITY
572
fd3f686c
VZ
573// -----------------------------------------------------------------------------
574// wxList (a.k.a. wxObjectList)
575// -----------------------------------------------------------------------------
c801d85f 576
b1d4dd7a
RL
577wxList::wxList( int key_type )
578 : wxObjectList( (wxKeyType)key_type )
579{
580}
581
fd3f686c 582void wxObjectListNode::DeleteData()
c801d85f 583{
fd3f686c 584 delete (wxObject *)GetData();
c801d85f
KB
585}
586
f526f752 587// ----------------------------------------------------------------------------
fd3f686c 588// wxStringList
f526f752
MB
589// ----------------------------------------------------------------------------
590
f526f752
MB
591static inline wxChar* MYcopystring(const wxChar* s)
592{
593 wxChar* copy = new wxChar[wxStrlen(s) + 1];
594 return wxStrcpy(copy, s);
595}
fd3f686c
VZ
596
597// instead of WX_DEFINE_LIST(wxStringListBase) we define this function
598// ourselves
599void wxStringListNode::DeleteData()
341287bf 600{
fd3f686c 601 delete [] (char *)GetData();
341287bf
JS
602}
603
50920146 604bool wxStringList::Delete(const wxChar *s)
f0824a5a
VZ
605{
606 wxStringListNode *current;
607
608 for ( current = GetFirst(); current; current = current->GetNext() )
609 {
50920146 610 if ( wxStrcmp(current->GetData(), s) == 0 )
f0824a5a
VZ
611 {
612 DeleteNode(current);
f644b28c 613 return true;
f0824a5a
VZ
614 }
615 }
616
617 // not found
f644b28c 618 return false;
f0824a5a
VZ
619}
620
db9504c5
VZ
621void wxStringList::DoCopy(const wxStringList& other)
622{
623 wxASSERT( GetCount() == 0 ); // this list must be empty before copying!
624
625 size_t count = other.GetCount();
626 for ( size_t n = 0; n < count; n++ )
627 {
77c5eefb 628 Add(other.Item(n)->GetData());
db9504c5
VZ
629 }
630}
631
b1d4dd7a
RL
632wxStringList::wxStringList()
633{
f644b28c 634 DeleteContents(true);
b1d4dd7a
RL
635}
636
c801d85f
KB
637// Variable argument list, terminated by a zero
638// Makes new storage for the strings
50920146 639wxStringList::wxStringList (const wxChar *first, ...)
c801d85f 640{
f644b28c 641 DeleteContents(true);
fd3f686c 642 if ( !first )
c801d85f
KB
643 return;
644
645 va_list ap;
fd3f686c 646 va_start(ap, first);
c801d85f 647
50920146 648 const wxChar *s = first;
c801d85f 649 for (;;)
fd3f686c
VZ
650 {
651 Add(s);
652
2cfcf22d
VZ
653 // icc gives this warning in its own va_arg() macro, argh
654#ifdef __INTELC__
655 #pragma warning(push)
656 #pragma warning(disable: 1684)
657#endif
658
50920146 659 s = va_arg(ap, const wxChar *);
2cfcf22d
VZ
660
661#ifdef __INTELC__
662 #pragma warning(pop)
c801d85f 663#endif
2cfcf22d
VZ
664
665 if ( !s )
fd3f686c
VZ
666 break;
667 }
c801d85f 668
fd3f686c 669 va_end(ap);
341287bf
JS
670}
671
f644b28c 672// Only makes new strings if arg is true
50920146 673wxChar **wxStringList::ListToArray(bool new_copies) const
341287bf 674{
50920146 675 wxChar **string_array = new wxChar *[GetCount()];
fd3f686c
VZ
676 wxStringListNode *node = GetFirst();
677 for (size_t i = 0; i < GetCount(); i++)
c801d85f 678 {
50920146 679 wxChar *s = node->GetData();
fd3f686c 680 if ( new_copies )
f526f752 681 string_array[i] = MYcopystring(s);
fd3f686c
VZ
682 else
683 string_array[i] = s;
684 node = node->GetNext();
c801d85f 685 }
c801d85f 686
fd3f686c 687 return string_array;
c801d85f
KB
688}
689
fd3f686c 690// Checks whether s is a member of the list
50920146 691bool wxStringList::Member(const wxChar *s) const
c801d85f 692{
fd3f686c 693 for ( wxStringListNode *node = GetFirst(); node; node = node->GetNext() )
c801d85f 694 {
50920146
OK
695 const wxChar *s1 = node->GetData();
696 if (s == s1 || wxStrcmp (s, s1) == 0)
f644b28c 697 return true;
c801d85f 698 }
fd3f686c 699
f644b28c 700 return false;
c801d85f
KB
701}
702
1c193821 703#ifdef __WXWINCE__
7d7b3f69
FM
704extern "C"
705{
706static int __cdecl
1c193821 707#else
7d7b3f69
FM
708extern "C"
709{
710static int LINKAGEMODE
1c193821
JS
711#endif
712
fd3f686c 713wx_comparestrings(const void *arg1, const void *arg2)
c801d85f 714{
50920146
OK
715 wxChar **s1 = (wxChar **) arg1;
716 wxChar **s2 = (wxChar **) arg2;
c801d85f 717
50920146 718 return wxStrcmp (*s1, *s2);
c801d85f
KB
719}
720
7d7b3f69
FM
721} // end of extern "C" (required because of GCC Bug c++/33078
722
c801d85f 723// Sort a list of strings - deallocates old nodes, allocates new
fd3f686c 724void wxStringList::Sort()
c801d85f 725{
fd3f686c 726 size_t N = GetCount();
50920146 727 wxChar **array = new wxChar *[N];
2a040d3f 728 wxStringListNode *node;
c801d85f 729
fd3f686c 730 size_t i = 0;
2a040d3f 731 for ( node = GetFirst(); node; node = node->GetNext() )
c801d85f 732 {
fd3f686c 733 array[i++] = node->GetData();
c801d85f 734 }
341287bf 735
50920146 736 qsort (array, N, sizeof (wxChar *), wx_comparestrings);
341287bf 737
9257d0b7
VZ
738 i = 0;
739 for ( node = GetFirst(); node; node = node->GetNext() )
740 node->SetData( array[i++] );
341287bf 741
9257d0b7 742 delete [] array;
341287bf 743}
f98bd52a 744
f526f752
MB
745wxNode *wxStringList::Add(const wxChar *s)
746{
d4d8988c
VZ
747 return (wxNode *)(wxStringListBase::Node *)
748 wxStringListBase::Append(MYcopystring(s));
f526f752 749}
f644b28c 750
f526f752
MB
751wxNode *wxStringList::Prepend(const wxChar *s)
752{
d4d8988c
VZ
753 return (wxNode *)(wxStringListBase::Node *)
754 wxStringListBase::Insert(MYcopystring(s));
f526f752
MB
755}
756
f98bd52a
VZ
757#endif // wxLIST_COMPATIBILITY
758
ed1288c1
VZ
759#else // wxUSE_STL = 1
760
7ec69821 761 #include "wx/listimpl.cpp"
412e0d47 762 WX_DEFINE_LIST(wxObjectList)
3543c79e
MB
763
764// with wxUSE_STL wxStringList contains wxString objects, not pointers
30a29593 765void _WX_LIST_HELPER_wxStringListBase::DeleteFunction( wxString WXUNUSED(X) )
3543c79e
MB
766{
767}
ed1288c1 768
1d300f25
VZ
769wxStringListBase::BaseListType wxStringListBase::EmptyList;
770
df5168c4 771#endif // !wxUSE_STL