X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c67daf87774c71ae9f73af9969008af220e52a11..1d73f41603de8103218a8460792f244230c6a7b1:/src/common/list.cpp diff --git a/src/common/list.cpp b/src/common/list.cpp index 0db540b157..26ace46fb5 100644 --- a/src/common/list.cpp +++ b/src/common/list.cpp @@ -1,405 +1,479 @@ -///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // Name: list.cpp // Purpose: wxList implementation // Author: Julian Smart -// Modified by: +// Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license -///////////////////////////////////////////////////////////////////////////// +// Copyright: (c) Julian Smart +// Licence: wxWindows licence +//////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "list.h" +// ============================================================================= +// declarations +// ============================================================================= + +// ----------------------------------------------------------------------------- +// headers +// ----------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "list.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/defs.h" -#include "wx/list.h" -#include "wx/utils.h" -#include -#endif - -// Sun CC compatibility (interference with xview/pkg.h, apparently...) -#if defined(SUN_CC) && defined(__XVIEW__) -#undef va_start -#undef va_end -#undef va_arg -#undef va_list + #pragma hdrstop #endif #include #include #include -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxNode, wxObject) -IMPLEMENT_DYNAMIC_CLASS(wxList, wxObject) -IMPLEMENT_DYNAMIC_CLASS(wxStringList, wxList) +#ifndef WX_PRECOMP + #include "wx/defs.h" + #include "wx/list.h" #endif -wxNode::wxNode (wxList * the_list, wxNode * last_one, wxNode * next_one, - wxObject * object) -{ - data = object; - previous = last_one; - next = next_one; - list = the_list; - key.string = (char *) NULL; +#if !wxUSE_STL - if (previous) - previous->next = this; +// ============================================================================= +// implementation +// ============================================================================= - if (next) - next->previous = this; -} +// ----------------------------------------------------------------------------- +// wxListKey +// ----------------------------------------------------------------------------- +wxListKey wxDefaultListKey; -// Keyed constructor -wxNode::wxNode (wxList * the_list, wxNode * last_one, wxNode * next_one, - wxObject * object, long the_key) +bool wxListKey::operator==(wxListKeyValue value) const { - data = object; - previous = last_one; - next = next_one; - list = the_list; - key.integer = the_key; - - if (previous) - previous->next = this; - - if (next) - next->previous = this; -} - -wxNode::wxNode (wxList * the_list, wxNode * last_one, wxNode * next_one, - wxObject * object, const char *the_key) -{ - data = object; - previous = last_one; - next = next_one; - list = the_list; - key.string = copystring (the_key); + switch ( m_keyType ) + { + default: + wxFAIL_MSG(wxT("bad key type.")); + // let compiler optimize the line above away in release build + // by not putting return here... - if (previous) - previous->next = this; + case wxKEY_STRING: + return wxStrcmp(m_key.string, value.string) == 0; - if (next) - next->previous = this; + case wxKEY_INTEGER: + return m_key.integer == value.integer; + } } +// ----------------------------------------------------------------------------- +// wxNodeBase +// ----------------------------------------------------------------------------- -wxNode::~wxNode (void) +wxNodeBase::wxNodeBase(wxListBase *list, + wxNodeBase *previous, wxNodeBase *next, + void *data, const wxListKey& key) { - if (list) - list->n--; + m_list = list; + m_data = data; + m_previous = previous; + m_next = next; + + switch ( key.GetKeyType() ) + { + case wxKEY_NONE: + break; - if (list && list->destroy_data) - delete data; + case wxKEY_INTEGER: + m_key.integer = key.GetNumber(); + break; - if (list && list->key_type == wxKEY_STRING && key.string) - delete[]key.string; + case wxKEY_STRING: + // to be free()d later + m_key.string = wxStrdup(key.GetString()); + break; - // Make next node point back to the previous node from here - if (next) - next->previous = previous; - else if (list) - // If there's a new end of list (deleting the last one) - // make sure the list knows about it. - list->last_node = previous; + default: + wxFAIL_MSG(wxT("invalid key type")); + } - // Make the previous node point to the next node from here - if (previous) - previous->next = next; + if ( previous ) + previous->m_next = this; - // Or if no previous node (start of list), make sure list points at - // the next node which becomes the first!. - else if (list) - list->first_node = next; + if ( next ) + next->m_previous = this; } -wxList::wxList (void) +wxNodeBase::~wxNodeBase() { - first_node = (wxNode *) NULL; - last_node = (wxNode *) NULL; - n = 0; - destroy_data = 0; - key_type = wxKEY_NONE; + // handle the case when we're being deleted from the list by the user (i.e. + // not by the list itself from DeleteNode) - we must do it for + // compatibility with old code + if ( m_list != NULL ) + { + if ( m_list->m_keyType == wxKEY_STRING ) + { + free(m_key.string); + } + + m_list->DetachNode(this); + } } -wxList::wxList (int N, wxObject * Objects[]) +int wxNodeBase::IndexOf() const { - wxNode *last = (wxNode *) NULL; + wxCHECK_MSG( m_list, wxNOT_FOUND, wxT("node doesn't belong to a list in IndexOf")); + + // It would be more efficient to implement IndexOf() completely inside + // wxListBase (only traverse the list once), but this is probably a more + // reusable way of doing it. Can always be optimized at a later date (since + // IndexOf() resides in wxListBase as well) if efficiency is a problem. + int i; + wxNodeBase *prev = m_previous; - int i; - for (i = 0; i < N; i++) + for( i = 0; prev; i++ ) { - wxNode *next = new wxNode (this, last, (wxNode *) NULL, Objects[i]); - last = next; - if (i == 0) - first_node = next; + prev = prev->m_previous; } - last_node = last; - n = N; - key_type = wxKEY_NONE; + + return i; } -wxList::wxList (const unsigned int the_key_type) +// ----------------------------------------------------------------------------- +// wxListBase +// ----------------------------------------------------------------------------- + +void wxListBase::Init(wxKeyType keyType) { - n = 0; - destroy_data = 0; - first_node = (wxNode *) NULL; - last_node = (wxNode *) NULL; - key_type = the_key_type; + m_nodeFirst = + m_nodeLast = (wxNodeBase *) NULL; + m_count = 0; + m_destroy = FALSE; + m_keyType = keyType; } -// Variable argument list, terminated by a zero -wxList::wxList (wxObject * first_one...) +wxListBase::wxListBase(size_t count, void *elements[]) { -// #ifndef __SGI__ - va_list ap; + Init(); + + for ( size_t n = 0; n < count; n++ ) + { + Append(elements[n]); + } +} - va_start (ap, first_one); +void wxListBase::DoCopy(const wxListBase& list) +{ + wxASSERT_MSG( !list.m_destroy, + wxT("copying list which owns it's elements is a bad idea") ); - wxNode *last = new wxNode (this, (wxNode *) NULL, (wxNode *) NULL, first_one); - first_node = last; - n = 1; + m_destroy = list.m_destroy; + m_keyType = list.m_keyType; + m_nodeFirst = + m_nodeLast = (wxNodeBase *) NULL; - for (;;) + switch (m_keyType) { - wxObject *object = va_arg (ap, wxObject *); -// if (object == NULL) // Doesn't work in Windows -- segment is non-zero for NULL! -#ifdef __WXMSW__ - if ((int) object == 0) -#else - if ((long) object == 0) -#endif - break; - else - { - wxNode *node = new wxNode (this, last, (wxNode *) NULL, object); - last = node; - n++; - } + case wxKEY_INTEGER: + { + long key; + for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() ) + { + key = node->GetKeyInteger(); + Append(key, node->GetData()); + } + break; + } + + case wxKEY_STRING: + { + const wxChar *key; + for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() ) + { + key = node->GetKeyString(); + Append(key, node->GetData()); + } + break; + } + + default: + { + for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() ) + { + Append(node->GetData()); + } + break; + } } - last_node = last; - va_end (ap); - destroy_data = 0; - key_type = wxKEY_NONE; -/* -#else - fprintf (stderr, "Error: cannot use variable-argument functions on SGI!\n"); -#endif -*/ + wxASSERT_MSG( m_count == list.m_count, _T("logic error in wxList::DoCopy") ); } -wxList::~wxList (void) +wxListBase::~wxListBase() { - wxNode *each = first_node; - while (each) - { - wxNode *next = each->Next (); - delete each; + wxNodeBase *each = m_nodeFirst; + while ( each != NULL ) + { + wxNodeBase *next = each->GetNext(); + DoDeleteNode(each); each = next; - } + } } -wxNode *wxList::Append(wxObject *object) +wxNodeBase *wxListBase::AppendCommon(wxNodeBase *node) { - wxNode *node = new wxNode(this, last_node, (wxNode *) NULL, object); - if (!first_node) - first_node = node; - last_node = node; - n ++; + if ( !m_nodeFirst ) + { + m_nodeFirst = node; + m_nodeLast = m_nodeFirst; + } + else + { + m_nodeLast->m_next = node; + m_nodeLast = node; + } + + m_count++; + return node; } -wxNode *wxList::Nth (int i) const +wxNodeBase *wxListBase::Append(void *object) { - int j = 0; - for (wxNode * current = First (); current; current = current->Next ()) - { - if (j++ == i) - return current; - } - return (wxNode *) NULL; // No such element + // all objects in a keyed list should have a key + wxCHECK_MSG( m_keyType == wxKEY_NONE, (wxNodeBase *)NULL, + wxT("need a key for the object to append") ); + + // we use wxDefaultListKey even though it is the default parameter value + // because gcc under Mac OS X seems to miscompile this call otherwise + wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object, + wxDefaultListKey); + return AppendCommon(node); } -wxNode *wxList::Find (long key) const +wxNodeBase *wxListBase::Append(long key, void *object) { - wxNode *current = First(); - while (current) - { - if (current->key.integer == key) - return current; - current = current->Next(); - } - - return (wxNode *) NULL; // Not found! + wxCHECK_MSG( (m_keyType == wxKEY_INTEGER) || + (m_keyType == wxKEY_NONE && m_count == 0), + (wxNodeBase *)NULL, + wxT("can't append object with numeric key to this list") ); + + wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object, key); + return AppendCommon(node); } -wxNode *wxList::Find (const char *key) const +wxNodeBase *wxListBase::Append (const wxChar *key, void *object) { - wxNode *current = First(); - while (current) - { - if (!current->key.string) - { - wxFatalError (_("wxList: string key not present, probably did not Append correctly!")); - break; - } - if (strcmp (current->key.string, key) == 0) - return current; - current = current->Next(); - } - - return (wxNode *) NULL; // Not found! + wxCHECK_MSG( (m_keyType == wxKEY_STRING) || + (m_keyType == wxKEY_NONE && m_count == 0), + (wxNodeBase *)NULL, + wxT("can't append object with string key to this list") ); + wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object, key); + return AppendCommon(node); } -wxNode *wxList::Member (wxObject * object) const +wxNodeBase *wxListBase::Insert(wxNodeBase *position, void *object) { - for (wxNode * current = First (); current; current = current->Next ()) + // all objects in a keyed list should have a key + wxCHECK_MSG( m_keyType == wxKEY_NONE, (wxNodeBase *)NULL, + wxT("need a key for the object to insert") ); + + wxCHECK_MSG( !position || position->m_list == this, (wxNodeBase *)NULL, + wxT("can't insert before a node from another list") ); + + // previous and next node for the node being inserted + wxNodeBase *prev, *next; + if ( position ) { - wxObject *each = current->Data (); - if (each == object) - return current; + prev = position->GetPrevious(); + next = position; } - return (wxNode *) NULL; + else + { + // inserting in the beginning of the list + prev = (wxNodeBase *)NULL; + next = m_nodeFirst; + } + + // wxDefaultListKey: see comment in Append() above + wxNodeBase *node = CreateNode(prev, next, object, wxDefaultListKey); + if ( !m_nodeFirst ) + { + m_nodeLast = node; + } + + if ( prev == NULL ) + { + m_nodeFirst = node; + } + + m_count++; + + return node; } -bool wxList::DeleteNode (wxNode * node) +wxNodeBase *wxListBase::Item(size_t n) const { - if (node) + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) { - delete node; - return TRUE; + if ( n-- == 0 ) + { + return current; + } } - return FALSE; + + wxFAIL_MSG( wxT("invalid index in wxListBase::Item") ); + + return (wxNodeBase *)NULL; } -bool wxList::DeleteObject (wxObject * object) +wxNodeBase *wxListBase::Find(const wxListKey& key) const { - // Search list for object - for (wxNode * current = first_node; current; current = current->Next ()) + wxASSERT_MSG( m_keyType == key.GetKeyType(), + wxT("this list is not keyed on the type of this key") ); + + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) { - if (current->Data () == object) - { - delete current; - return TRUE; - } + if ( key == current->m_key ) + { + return current; + } } - return FALSE; // Did not find the object + // not found + return (wxNodeBase *)NULL; } - -// Insert new node at front of list -wxNode *wxList::Insert (wxObject * object) +wxNodeBase *wxListBase::Find(void *object) const { - wxNode *node = new wxNode (this, (wxNode *) NULL, First (), object); - first_node = node; - - if (!(node->Next ())) - last_node = node; + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) + { + if ( current->GetData() == object ) + return current; + } - n++; - return node; + // not found + return (wxNodeBase *)NULL; } +int wxListBase::IndexOf(void *object) const +{ + wxNodeBase *node = Find( object ); + + return node ? node->IndexOf() : wxNOT_FOUND; +} -// Insert new node before given node. -wxNode *wxList::Insert (wxNode * position, wxObject * object) +void wxListBase::DoDeleteNode(wxNodeBase *node) { - wxNode *prev = (wxNode *) NULL; - if (position) - prev = position->Previous (); + // free node's data + if ( m_keyType == wxKEY_STRING ) + { + free(node->m_key.string); + } - wxNode *node = new wxNode (this, prev, position, object); - if (!first_node) + if ( m_destroy ) { - first_node = node; - last_node = node; + node->DeleteData(); } - if (!prev) - first_node = node; - n++; - return node; + // so that the node knows that it's being deleted by the list + node->m_list = NULL; + delete node; +} + +wxNodeBase *wxListBase::DetachNode(wxNodeBase *node) +{ + wxCHECK_MSG( node, NULL, wxT("detaching NULL wxNodeBase") ); + wxCHECK_MSG( node->m_list == this, NULL, + wxT("detaching node which is not from this list") ); + + // update the list + wxNodeBase **prevNext = node->GetPrevious() ? &node->GetPrevious()->m_next + : &m_nodeFirst; + wxNodeBase **nextPrev = node->GetNext() ? &node->GetNext()->m_previous + : &m_nodeLast; + + *prevNext = node->GetNext(); + *nextPrev = node->GetPrevious(); + + m_count--; + + // mark the node as not belonging to this list any more + node->m_list = NULL; + + return node; } -// Keyed append -wxNode *wxList::Append (long key, wxObject * object) +bool wxListBase::DeleteNode(wxNodeBase *node) { - wxNode *node = new wxNode (this, last_node, (wxNode *) NULL, object, key); - if (!first_node) - first_node = node; - last_node = node; - n++; - return node; + if ( !DetachNode(node) ) + return FALSE; + + DoDeleteNode(node); + + return TRUE; } -wxNode *wxList::Append (const char *key, wxObject * object) +bool wxListBase::DeleteObject(void *object) { - wxNode *node = new wxNode (this, last_node, (wxNode *) NULL, object, key); - if (!first_node) - first_node = node; - last_node = node; - n++; - return node; + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) + { + if ( current->GetData() == object ) + { + DeleteNode(current); + return TRUE; + } + } + + // not found + return FALSE; } -void wxList::Clear (void) +void wxListBase::Clear() { - wxNode *current = first_node; - while (current) + wxNodeBase *current = m_nodeFirst; + while ( current ) { - wxNode *next = current->Next (); - delete current; - current = next; + wxNodeBase *next = current->GetNext(); + DoDeleteNode(current); + current = next; } - first_node = (wxNode *) NULL; - last_node = (wxNode *) NULL; - n = 0; + + m_nodeFirst = + m_nodeLast = (wxNodeBase *)NULL; + + m_count = 0; } -//Executes function F with all items present in the list -void wxList::ForEach(wxListIterateFunction F) +void wxListBase::ForEach(wxListIterateFunction F) { - wxNode *each = first_node; - while (each) - { (*F)( each->Data ()); - each = each->Next(); + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) + { + (*F)(current->GetData()); } } -// Returns a pointer to the item which returns TRUE with function F -// or NULL if no such item found -wxObject *wxList::FirstThat(wxListIterateFunction F) + +void *wxListBase::FirstThat(wxListIterateFunction F) { - wxNode *each = first_node; - while (each) - { if ((*F)( each->Data ())) return each->Data(); - each = each->Next(); + for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) + { + if ( (*F)(current->GetData()) ) + return current->GetData(); } - return (wxNode *) NULL; + + return (wxNodeBase *)NULL; } -// Like FirstThat, but proceeds from the end backward -wxObject *wxList::LastThat(wxListIterateFunction F) + +void *wxListBase::LastThat(wxListIterateFunction F) { - wxNode *each = last_node; - while (each) - { if ((*F)( each->Data ())) return each->Data(); - each = each->Previous(); + for ( wxNodeBase *current = GetLast(); current; current = current->GetPrevious() ) + { + if ( (*F)(current->GetData()) ) + return current->GetData(); } - return (wxNode *) NULL; + + return (wxNodeBase *)NULL; } // (stefan.hammes@urz.uni-heidelberg.de) @@ -421,8 +495,8 @@ wxObject *wxList::LastThat(wxListIterateFunction F) // } // // void main() -// { -// wxList list; +// { +// wxListBase list; // // list.Append(new wxString("DEF")); // list.Append(new wxString("GHI")); @@ -430,178 +504,256 @@ wxObject *wxList::LastThat(wxListIterateFunction F) // list.Sort(listcompare); // } -void wxList::Sort(const wxSortCompareFunction compfunc) -{ - // allocate an array for the wxObject pointers of the list - const size_t num = Number(); - wxObject **objArray = new wxObject *[num]; - wxObject **objPtr = objArray; - - // go through the list and put the pointers into the array - wxNode *node = First(); - while(node!=NULL){ - *objPtr++ = node->Data(); - node = node->Next(); - } - // sort the array - qsort((void *)objArray,num,sizeof(wxObject *),compfunc); - // put the sorted pointers back into the list - objPtr = objArray; - node = First(); - while(node!=NULL){ - node->SetData(*objPtr++); - node = node->Next(); - } - // free the array - delete[] objArray; +void wxListBase::Sort(const wxSortCompareFunction compfunc) +{ + // allocate an array for the wxObject pointers of the list + const size_t num = GetCount(); + void **objArray = new void *[num]; + void **objPtr = objArray; + + // go through the list and put the pointers into the array + wxNodeBase *node; + for ( node = GetFirst(); node; node = node->GetNext() ) + { + *objPtr++ = node->GetData(); + } + + // sort the array + qsort((void *)objArray,num,sizeof(wxObject *), +#ifdef __WXWINCE__ + (int (__cdecl *)(const void *,const void *)) +#endif + compfunc); + + // put the sorted pointers back into the list + objPtr = objArray; + for ( node = GetFirst(); node; node = node->GetNext() ) + { + node->SetData(*objPtr++); + } + + // free the array + delete[] objArray; } -/* - * String list - * - */ +void wxListBase::Reverse() +{ + wxNodeBase* node = m_nodeFirst; + wxNodeBase* tmp; + + while (node) + { + // swap prev and next pointers + tmp = node->m_next; + node->m_next = node->m_previous; + node->m_previous = tmp; -wxStringList::wxStringList (void): -wxList () + // this is the node that was next before swapping + node = tmp; + } + + // swap first and last node + tmp = m_nodeFirst; m_nodeFirst = m_nodeLast; m_nodeLast = tmp; +} + +void wxListBase::DeleteNodes(wxNodeBase* first, wxNodeBase* last) { + wxNodeBase* node = first; + + while (node != last) + { + wxNodeBase* next = node->GetNext(); + DeleteNode(node); + node = next; + } } -// Variable argument list, terminated by a zero -// Makes new storage for the strings -wxStringList::wxStringList (const char *first...) +// ============================================================================ +// compatibility section from now on +// ============================================================================ + +#ifdef wxLIST_COMPATIBILITY + +// ----------------------------------------------------------------------------- +// wxList (a.k.a. wxObjectList) +// ----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxList, wxObject) + +wxList::wxList( int key_type ) + : wxObjectList( (wxKeyType)key_type ) { -// #ifndef __SGI__ - n = 0; - destroy_data = 0; - key_type = wxKEY_NONE; - first_node = (wxNode *) NULL; - last_node = (wxNode *) NULL; +} - if (!first) - return; +void wxObjectListNode::DeleteData() +{ + delete (wxObject *)GetData(); +} - va_list ap; +// ---------------------------------------------------------------------------- +// wxStringList +// ---------------------------------------------------------------------------- - va_start (ap, first); +static inline wxChar* MYcopystring(const wxString& s) +{ + wxChar* copy = new wxChar[s.length() + 1]; + return wxStrcpy(copy, s.c_str()); +} - wxNode *last = new wxNode (this, (wxNode *) NULL, (wxNode *) NULL, (wxObject *) copystring (first)); - first_node = last; - n = 1; +static inline wxChar* MYcopystring(const wxChar* s) +{ + wxChar* copy = new wxChar[wxStrlen(s) + 1]; + return wxStrcpy(copy, s); +} - for (;;) +IMPLEMENT_DYNAMIC_CLASS(wxStringList, wxObject) + +// instead of WX_DEFINE_LIST(wxStringListBase) we define this function +// ourselves +void wxStringListNode::DeleteData() +{ + delete [] (char *)GetData(); +} + +bool wxStringList::Delete(const wxChar *s) +{ + wxStringListNode *current; + + for ( current = GetFirst(); current; current = current->GetNext() ) { - char *s = va_arg (ap, char *); -// if (s == NULL) -#ifdef __WXMSW__ - if ((int) s == 0) -#else - if ((long) s == 0) -#endif - break; - else - { - wxNode *node = new wxNode (this, last, (wxNode *) NULL, (wxObject *) copystring (s)); - last = node; - n++; - } + if ( wxStrcmp(current->GetData(), s) == 0 ) + { + DeleteNode(current); + return TRUE; + } } - last_node = last; - va_end (ap); -/* -#else - fprintf (stderr, "Error: cannot use variable-argument functions on SGI!\n"); -#endif -*/ + + // not found + return FALSE; } -wxStringList::~wxStringList (void) +void wxStringList::DoCopy(const wxStringList& other) { - wxNode *each = first_node; - while (each) + wxASSERT( GetCount() == 0 ); // this list must be empty before copying! + + size_t count = other.GetCount(); + for ( size_t n = 0; n < count; n++ ) { - char *s = (char *) each->Data (); - delete[]s; - wxNode *next = each->Next (); - delete each; - each = next; + Add(other.Item(n)->GetData()); } } -wxNode *wxStringList::Add (const char *s) +wxStringList::wxStringList() { - return Append ((wxObject *) (copystring (s))); + DeleteContents(TRUE); } -void wxStringList::Delete (const char *s) +// Variable argument list, terminated by a zero +// Makes new storage for the strings +wxStringList::wxStringList (const wxChar *first, ...) { - for (wxNode * node = First (); node; node = node->Next ()) - { - char *string = (char *) node->Data (); - if (string == s || strcmp (string, s) == 0) - { - delete[]string; - delete node; - break; // Done! + DeleteContents(TRUE); + if ( !first ) + return; - } - } // for + va_list ap; + va_start(ap, first); + + const wxChar *s = first; + for (;;) + { + Add(s); + s = va_arg(ap, const wxChar *); + // if (s == NULL) +#ifdef __WXMSW__ + if ((int)(long) s == 0) +#else + if ((long) s == 0) +#endif + break; + } + + va_end(ap); } // Only makes new strings if arg is TRUE -char **wxStringList::ListToArray (bool new_copies) const +wxChar **wxStringList::ListToArray(bool new_copies) const +{ + wxChar **string_array = new wxChar *[GetCount()]; + wxStringListNode *node = GetFirst(); + for (size_t i = 0; i < GetCount(); i++) + { + wxChar *s = node->GetData(); + if ( new_copies ) + string_array[i] = MYcopystring(s); + else + string_array[i] = s; + node = node->GetNext(); + } + + return string_array; +} + +// Checks whether s is a member of the list +bool wxStringList::Member(const wxChar *s) const { - char **string_array = new char *[Number ()]; - wxNode *node = First (); - int i; - for (i = 0; i < n; i++) + for ( wxStringListNode *node = GetFirst(); node; node = node->GetNext() ) { - char *s = (char *) node->Data (); - if (new_copies) - string_array[i] = copystring (s); - else - string_array[i] = s; - node = node->Next (); + const wxChar *s1 = node->GetData(); + if (s == s1 || wxStrcmp (s, s1) == 0) + return TRUE; } - return string_array; + + return FALSE; } -static int -wx_comparestrings (const void *arg1, const void *arg2) +#ifdef __WXWINCE__ +extern "C" int __cdecl +#else +extern "C" int LINKAGEMODE +#endif + +wx_comparestrings(const void *arg1, const void *arg2) { - char **s1 = (char **) arg1; - char **s2 = (char **) arg2; + wxChar **s1 = (wxChar **) arg1; + wxChar **s2 = (wxChar **) arg2; - return strcmp (*s1, *s2); + return wxStrcmp (*s1, *s2); } // Sort a list of strings - deallocates old nodes, allocates new -void wxStringList::Sort (void) +void wxStringList::Sort() { - size_t N = n; - char **array = new char *[N]; + size_t N = GetCount(); + wxChar **array = new wxChar *[N]; + wxStringListNode *node; - size_t i = 0; - for (wxNode * node = First (); node; node = node->Next ()) - array[i++] = (char *) node->Data (); + size_t i = 0; + for ( node = GetFirst(); node; node = node->GetNext() ) + { + array[i++] = node->GetData(); + } - qsort (array, N, sizeof (char *), wx_comparestrings); - Clear (); + qsort (array, N, sizeof (wxChar *), wx_comparestrings); - for (i = 0; i < N; i++) - Append ((wxObject *) (array[i])); + i = 0; + for ( node = GetFirst(); node; node = node->GetNext() ) + node->SetData( array[i++] ); - delete[]array; + delete [] array; } -// Checks whether s is a member of the list -bool wxStringList::Member (const char *s) const +wxNode *wxStringList::Add(const wxChar *s) { - for (wxNode * node = First (); node; node = node->Next ()) - { - const char *s1 = (const char *) node->Data (); - if (s == s1 || strcmp (s, s1) == 0) - return TRUE; - } - return FALSE; + return (wxNode *)wxStringListBase::Append(MYcopystring(s)); +} + +wxNode *wxStringList::Prepend(const wxChar *s) +{ + return (wxNode *)wxStringListBase::Insert(MYcopystring(s)); } + +#endif // wxLIST_COMPATIBILITY + +#endif // !wxUSE_STL