-/////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// 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"
-#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 <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#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 = 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 = NULL;
- last_node = 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 = 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, 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 = NULL;
- last_node = 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();
- va_start (ap, first_one);
+ for ( size_t n = 0; n < count; n++ )
+ {
+ Append(elements[n]);
+ }
+}
- wxNode *last = new wxNode (this, NULL, NULL, first_one);
- first_node = last;
- n = 1;
+void wxListBase::DoCopy(const wxListBase& list)
+{
+ wxASSERT_MSG( !list.m_destroy,
+ wxT("copying list which owns it's elements is a bad idea") );
- for (;;)
+ m_destroy = list.m_destroy;
+ m_keyType = list.m_keyType;
+ m_nodeFirst =
+ m_nodeLast = (wxNodeBase *) NULL;
+
+ switch (m_keyType)
{
- wxObject *object = va_arg (ap, wxObject *);
-// if (object == NULL) // Doesn't work in Windows -- segment is non-zero for NULL!
-#ifdef __WINDOWS__
- if ((int) object == 0)
-#else
- if ((long) object == 0)
-#endif
- break;
- else
- {
- wxNode *node = new wxNode (this, last, 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;
- }
+ }
}
-#ifdef USE_STORABLE_CLASSES
-wxList::wxList( istream &stream, char *WXUNUSED(data) )
+wxNodeBase *wxListBase::AppendCommon(wxNodeBase *node)
{
- char buf[200];
- unsigned int num;
- stream.read( (char*)(&num), sizeof(num) );
- for (unsigned int i = 0; i < num; i++)
- {
- int len;
- stream.read( (char*)(&len), sizeof(len) );
- stream.read( (char*)(&buf), len );
- buf[len] = 0;
- Append( wxCreateStoredObject( buf, stream, NULL ) );
- };
-};
-
-void wxList::StoreObject( ostream &stream )
-{
- unsigned int num = Number();
- stream.write( (char*)(&num), sizeof(num) );
- wxNode *node = First();
- while (node)
- {
- wxObject *obj = (wxObject*) node->Data();
- wxClassInfo *obj_info = obj->GetClassInfo();
- int len = strlen(obj_info->className);
- stream.write( (char*)(&len), sizeof(len) );
- stream.write( obj_info->className, len );
- obj->StoreObject( stream );
- node = node->Next();
- };
-};
-#endif
-
-wxNode *wxList::Append(wxObject *object)
-{
- wxNode *node = new wxNode(this, last_node, 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 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 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 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 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(const void *object) const
{
- wxNode *node = new wxNode (this, 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 );
-// Insert new node before given node.
-wxNode *wxList::Insert (wxNode * position, wxObject * object)
+ return node ? node->IndexOf() : wxNOT_FOUND;
+}
+
+void wxListBase::DoDeleteNode(wxNodeBase *node)
{
- wxNode *prev = 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;
}
-// Keyed append
-wxNode *wxList::Append (long key, wxObject * object)
+wxNodeBase *wxListBase::DetachNode(wxNodeBase *node)
{
- wxNode *node = new wxNode (this, last_node, NULL, object, key);
- if (!first_node)
- first_node = node;
- last_node = node;
- n++;
- return 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;
+}
+
+bool wxListBase::DeleteNode(wxNodeBase *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, 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 = NULL;
- last_node = 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 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 NULL;
+
+ return (wxNodeBase *)NULL;
}
// (stefan.hammes@urz.uni-heidelberg.de)
// }
//
// void main()
-// {
-// wxList list;
+// {
+// wxListBase list;
//
// list.Append(new wxString("DEF"));
// list.Append(new wxString("GHI"));
// 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;
+}
+
+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;
+
+ // 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;
}
-/*
- * String list
- *
- */
+void wxListBase::DeleteNodes(wxNodeBase* first, wxNodeBase* last)
+{
+ wxNodeBase* node = first;
+
+ while (node != last)
+ {
+ wxNodeBase* next = node->GetNext();
+ DeleteNode(node);
+ node = next;
+ }
+}
+
+// ============================================================================
+// compatibility section from now on
+// ============================================================================
+
+#ifdef wxLIST_COMPATIBILITY
+
+// -----------------------------------------------------------------------------
+// wxList (a.k.a. wxObjectList)
+// -----------------------------------------------------------------------------
-wxStringList::wxStringList (void):
-wxList ()
+IMPLEMENT_DYNAMIC_CLASS(wxList, wxObject)
+
+wxList::wxList( int key_type )
+ : wxObjectList( (wxKeyType)key_type )
{
}
-// Variable argument list, terminated by a zero
-// Makes new storage for the strings
-wxStringList::wxStringList (const char *first...)
+void wxObjectListNode::DeleteData()
{
-// #ifndef __SGI__
- n = 0;
- destroy_data = 0;
- key_type = wxKEY_NONE;
- first_node = NULL;
- last_node = NULL;
+ delete (wxObject *)GetData();
+}
- if (!first)
- return;
+// ----------------------------------------------------------------------------
+// wxStringList
+// ----------------------------------------------------------------------------
- va_list ap;
+static inline wxChar* MYcopystring(const wxChar* s)
+{
+ wxChar* copy = new wxChar[wxStrlen(s) + 1];
+ return wxStrcpy(copy, s);
+}
- va_start (ap, first);
+IMPLEMENT_DYNAMIC_CLASS(wxStringList, wxObject)
- wxNode *last = new wxNode (this, NULL, NULL, (wxObject *) copystring (first));
- first_node = last;
- n = 1;
+// instead of WX_DEFINE_LIST(wxStringListBase) we define this function
+// ourselves
+void wxStringListNode::DeleteData()
+{
+ delete [] (char *)GetData();
+}
- for (;;)
+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 __WINDOWS__
- if ((int) s == 0)
-#else
- if ((long) s == 0)
-#endif
- break;
- else
- {
- wxNode *node = new wxNode (this, last, 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;
+
+ 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);
+}
- }
- } // for
+// Only makes new strings if arg is true
+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;
}
-// Only makes new strings if arg is TRUE
-char **wxStringList::ListToArray (bool new_copies) const
+// 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)
+{
+ return (wxNode *)wxStringListBase::Append(MYcopystring(s));
+}
+
+wxNode *wxStringList::Prepend(const wxChar *s)
+{
+ return (wxNode *)wxStringListBase::Insert(MYcopystring(s));
+}
+
+#endif // wxLIST_COMPATIBILITY
+
+#else // wxUSE_STL = 1
+
+ #include <wx/listimpl.cpp>
+ WX_DEFINE_LIST(wxObjectList);
+
+// with wxUSE_STL wxStringList contains wxString objects, not pointers
+void wxStringListBase::DeleteFunction( const wxString WXUNUSED(X) )
{
- 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;
}
+
+#endif // !wxUSE_STL
+