]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/list.cpp
fix for always terminating intermediate UniChar String for 4 bytes wchar_t
[wxWidgets.git] / src / common / list.cpp
index ac936bb26570a3d1b6b1de7304c059d9c1ae2012..26ace46fb5b4336265a0850f104e8c7d435d4f25 100644 (file)
-/////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
 // 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 (const 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();
+
+  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, NULL, 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 __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 (const 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 (const 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 )
+    {
+        prev = position->GetPrevious();
+        next = position;
+    }
+    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 )
     {
-      wxObject *each = current->Data ();
-      if (each == object)
-       return current;
+        m_nodeLast = node;
     }
-  return NULL;
+
+    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, 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 = 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 (const 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;
 }
 
-wxNode *wxList::Append (const char *key, wxObject * object)
+bool wxListBase::DeleteNode(wxNodeBase *node)
 {
-  wxNode *node = new wxNode (this, last_node, NULL, object, key);
-  if (!first_node)
-    first_node = node;
-  last_node = node;
-  n++;
-  return node;
+    if ( !DetachNode(node) )
+        return FALSE;
+
+    DoDeleteNode(node);
+
+    return TRUE;
+}
+
+bool wxListBase::DeleteObject(void *object)
+{
+    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)
@@ -454,8 +495,8 @@ wxObject *wxList::LastThat(wxListIterateFunction F)
 //   }
 //
 //   void main()
-//   { 
-//     wxList list;
+//   {
+//     wxListBase list;
 //
 //     list.Append(new wxString("DEF"));
 //     list.Append(new wxString("GHI"));
@@ -463,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;
 
-wxStringList::wxStringList (void):
-wxList ()
+    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;
+}
+
+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 = NULL;
-  last_node = NULL;
+}
 
-  if (!first)
-    return;
+void wxObjectListNode::DeleteData()
+{
+    delete (wxObject *)GetData();
+}
 
-  va_list ap;
+// ----------------------------------------------------------------------------
+// wxStringList
+// ----------------------------------------------------------------------------
+
+static inline wxChar* MYcopystring(const wxString& s)
+{
+    wxChar* copy = new wxChar[s.length() + 1];
+    return wxStrcpy(copy, s.c_str());
+}
 
-  va_start (ap, first);
+static inline wxChar* MYcopystring(const wxChar* s)
+{
+    wxChar* copy = new wxChar[wxStrlen(s) + 1];
+    return wxStrcpy(copy, s);
+}
 
-  wxNode *last = new wxNode (this, NULL, NULL, (wxObject *) copystring (first));
-  first_node = last;
-  n = 1;
+IMPLEMENT_DYNAMIC_CLASS(wxStringList, wxObject)
 
-  for (;;)
+// 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 __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);
 
-       }
-    }                          // for
+  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 (const 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