X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6164d85e896743b16a0cf8b0610f5d17ceb47f36..5c87527c5a81eda63e7ccbda2f226ca02716e7da:/src/common/list.cpp?ds=sidebyside diff --git a/src/common/list.cpp b/src/common/list.cpp index f7b1ab0543..15535b3552 100644 --- a/src/common/list.cpp +++ b/src/common/list.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// -// Name: list.cpp +// Name: src/common/list.cpp // Purpose: wxList implementation // Author: Julian Smart // 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 //////////////////////////////////////////////////////////////////////////////// // ============================================================================= @@ -16,9 +16,6 @@ // ----------------------------------------------------------------------------- // headers // ----------------------------------------------------------------------------- -#ifdef __GNUG__ -#pragma implementation "list.h" -#endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -32,23 +29,38 @@ #include #ifndef WX_PRECOMP - #include "wx/defs.h" #include "wx/list.h" - #include "wx/utils.h" // for copystring() (beurk...) + #include "wx/crt.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 -#endif +#if !wxUSE_STL // ============================================================================= // implementation // ============================================================================= +// ----------------------------------------------------------------------------- +// wxListKey +// ----------------------------------------------------------------------------- +wxListKey wxDefaultListKey; + +bool wxListKey::operator==(wxListKeyValue value) const +{ + 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... + + case wxKEY_STRING: + return *m_key.string == *value.string; + + case wxKEY_INTEGER: + return m_key.integer == value.integer; + } +} + // ----------------------------------------------------------------------------- // wxNodeBase // ----------------------------------------------------------------------------- @@ -61,28 +73,28 @@ wxNodeBase::wxNodeBase(wxListBase *list, m_data = data; m_previous = previous; m_next = next; - + switch ( key.GetKeyType() ) { case wxKEY_NONE: break; - + case wxKEY_INTEGER: m_key.integer = key.GetNumber(); break; - + case wxKEY_STRING: // to be free()d later - m_key.string = strdup(key.GetString()); + m_key.string = new wxString(key.GetString()); break; - + default: - wxFAIL_MSG("invalid key type"); + wxFAIL_MSG(wxT("invalid key type")); } - + if ( previous ) previous->m_next = this; - + if ( next ) next->m_previous = this; } @@ -94,20 +106,44 @@ wxNodeBase::~wxNodeBase() // compatibility with old code if ( m_list != NULL ) { + if ( m_list->m_keyType == wxKEY_STRING ) + { + delete m_key.string; + } + m_list->DetachNode(this); } } +int wxNodeBase::IndexOf() const +{ + 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; + + for( i = 0; prev; i++ ) + { + prev = prev->m_previous; + } + + return i; +} + // ----------------------------------------------------------------------------- // wxListBase // ----------------------------------------------------------------------------- -void wxListBase::Init(wxKeyType keyType = wxKEY_NONE) +void wxListBase::Init(wxKeyType keyType) { m_nodeFirst = m_nodeLast = (wxNodeBase *) NULL; m_count = 0; - m_destroy = FALSE; + m_destroy = false; m_keyType = keyType; } @@ -124,18 +160,48 @@ wxListBase::wxListBase(size_t count, void *elements[]) void wxListBase::DoCopy(const wxListBase& list) { wxASSERT_MSG( !list.m_destroy, - "copying list which owns it's elements is a bad idea" ); + wxT("copying list which owns it's elements is a bad idea") ); - m_count = list.m_count; m_destroy = list.m_destroy; m_keyType = list.m_keyType; m_nodeFirst = m_nodeLast = (wxNodeBase *) NULL; - for ( wxNodeBase *node = list.GetFirst(); node; node = node->GetNext() ) + switch (m_keyType) { - Append(node); + 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; + } } + + wxASSERT_MSG( m_count == list.m_count, _T("logic error in wxList::DoCopy") ); } wxListBase::~wxListBase() @@ -171,9 +237,12 @@ wxNodeBase *wxListBase::Append(void *object) { // all objects in a keyed list should have a key wxCHECK_MSG( m_keyType == wxKEY_NONE, (wxNodeBase *)NULL, - "need a key for the object to append" ); + wxT("need a key for the object to append") ); - wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object); + // 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); } @@ -183,18 +252,18 @@ wxNodeBase *wxListBase::Append(long key, void *object) wxCHECK_MSG( (m_keyType == wxKEY_INTEGER) || (m_keyType == wxKEY_NONE && m_count == 0), (wxNodeBase *)NULL, - "can't append object with numeric key to this list" ); + wxT("can't append object with numeric key to this list") ); wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object, key); return AppendCommon(node); } -wxNodeBase *wxListBase::Append (const char *key, void *object) +wxNodeBase *wxListBase::Append (const wxString& key, void *object) { wxCHECK_MSG( (m_keyType == wxKEY_STRING) || (m_keyType == wxKEY_NONE && m_count == 0), (wxNodeBase *)NULL, - "can't append object with string key to this list" ); + wxT("can't append object with string key to this list") ); wxNodeBase *node = CreateNode(m_nodeLast, (wxNodeBase *)NULL, object, key); return AppendCommon(node); @@ -204,18 +273,29 @@ wxNodeBase *wxListBase::Insert(wxNodeBase *position, void *object) { // all objects in a keyed list should have a key wxCHECK_MSG( m_keyType == wxKEY_NONE, (wxNodeBase *)NULL, - "need a key for the object to insert" ); + 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") ); - wxNodeBase *prev = (wxNodeBase *)NULL; + // previous and next node for the node being inserted + wxNodeBase *prev, *next; if ( position ) + { prev = position->GetPrevious(); - //else - // inserting in the beginning of the list + next = position; + } + else + { + // inserting in the beginning of the list + prev = (wxNodeBase *)NULL; + next = m_nodeFirst; + } - wxNodeBase *node = CreateNode(prev, position, object); + // wxDefaultListKey: see comment in Append() above + wxNodeBase *node = CreateNode(prev, next, object, wxDefaultListKey); if ( !m_nodeFirst ) { - m_nodeFirst = node; m_nodeLast = node; } @@ -239,15 +319,15 @@ wxNodeBase *wxListBase::Item(size_t n) const } } - wxFAIL_MSG( "invalid index in wxListBase::Item" ); + wxFAIL_MSG( wxT("invalid index in wxListBase::Item") ); - return NULL; + return (wxNodeBase *)NULL; } wxNodeBase *wxListBase::Find(const wxListKey& key) const { wxASSERT_MSG( m_keyType == key.GetKeyType(), - "this list is not keyed on the type of this key" ); + wxT("this list is not keyed on the type of this key") ); for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) { @@ -261,7 +341,7 @@ wxNodeBase *wxListBase::Find(const wxListKey& key) const return (wxNodeBase *)NULL; } -wxNodeBase *wxListBase::Find(void *object) const +wxNodeBase *wxListBase::Find(const void *object) const { for ( wxNodeBase *current = GetFirst(); current; current = current->GetNext() ) { @@ -273,6 +353,13 @@ wxNodeBase *wxListBase::Find(void *object) const return (wxNodeBase *)NULL; } +int wxListBase::IndexOf(void *object) const +{ + wxNodeBase *node = Find( object ); + + return node ? node->IndexOf() : wxNOT_FOUND; +} + void wxListBase::DoDeleteNode(wxNodeBase *node) { // free node's data @@ -286,14 +373,16 @@ void wxListBase::DoDeleteNode(wxNodeBase *node) node->DeleteData(); } + // 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, "detaching NULL wxNodeBase" ); + wxCHECK_MSG( node, NULL, wxT("detaching NULL wxNodeBase") ); wxCHECK_MSG( node->m_list == this, NULL, - "detaching node which is not from this list" ); + wxT("detaching node which is not from this list") ); // update the list wxNodeBase **prevNext = node->GetPrevious() ? &node->GetPrevious()->m_next @@ -315,11 +404,11 @@ wxNodeBase *wxListBase::DetachNode(wxNodeBase *node) bool wxListBase::DeleteNode(wxNodeBase *node) { if ( !DetachNode(node) ) - return FALSE; + return false; DoDeleteNode(node); - return TRUE; + return true; } bool wxListBase::DeleteObject(void *object) @@ -329,15 +418,14 @@ bool wxListBase::DeleteObject(void *object) if ( current->GetData() == object ) { DeleteNode(current); - return TRUE; + return true; } } // not found - return FALSE; + return false; } - void wxListBase::Clear() { wxNodeBase *current = m_nodeFirst; @@ -421,17 +509,21 @@ void wxListBase::Sort(const wxSortCompareFunction compfunc) // go through the list and put the pointers into the array wxNodeBase *node; - for ( node = GetFirst(); node; node = node->Next() ) + for ( node = GetFirst(); node; node = node->GetNext() ) { - *objPtr++ = node->Data(); + *objPtr++ = node->GetData(); } // sort the array - qsort((void *)objArray,num,sizeof(wxObject *),compfunc); + 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->Next() ) + for ( node = GetFirst(); node; node = node->GetNext() ) { node->SetData(*objPtr++); } @@ -440,35 +532,67 @@ void wxListBase::Sort(const wxSortCompareFunction compfunc) delete[] objArray; } -bool wxListKey::operator==(wxListKeyValue value) const +void wxListBase::Reverse() +{ + wxNodeBase* node = m_nodeFirst; + wxNodeBase* tmp; + + while (node) { - switch ( m_keyType ) - { - default: - wxFAIL_MSG("bad key type."); - // let compiler optimize the line above away in release build - // by not putting return here... + // 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; + } - case wxKEY_STRING: - return strcmp(m_key.string, value.string) == 0; + // swap first and last node + tmp = m_nodeFirst; m_nodeFirst = m_nodeLast; m_nodeLast = tmp; +} - case wxKEY_INTEGER: - return m_key.integer == value.integer; - } +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) // ----------------------------------------------------------------------------- +wxList::wxList( int key_type ) + : wxObjectList( (wxKeyType)key_type ) +{ +} + void wxObjectListNode::DeleteData() { delete (wxObject *)GetData(); } -// ----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // wxStringList -// ----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +static inline wxChar* MYcopystring(const wxChar* s) +{ + wxChar* copy = new wxChar[wxStrlen(s) + 1]; + return wxStrcpy(copy, s); +} // instead of WX_DEFINE_LIST(wxStringListBase) we define this function // ourselves @@ -477,44 +601,84 @@ void wxStringListNode::DeleteData() delete [] (char *)GetData(); } +bool wxStringList::Delete(const wxChar *s) +{ + wxStringListNode *current; + + for ( current = GetFirst(); current; current = current->GetNext() ) + { + if ( wxStrcmp(current->GetData(), s) == 0 ) + { + DeleteNode(current); + return true; + } + } + + // not found + return false; +} + +void wxStringList::DoCopy(const wxStringList& other) +{ + wxASSERT( GetCount() == 0 ); // this list must be empty before copying! + + size_t count = other.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + Add(other.Item(n)->GetData()); + } +} + +wxStringList::wxStringList() +{ + DeleteContents(true); +} + // Variable argument list, terminated by a zero // Makes new storage for the strings -wxStringList::wxStringList (const char *first, ...) +wxStringList::wxStringList (const wxChar *first, ...) { + DeleteContents(true); if ( !first ) return; va_list ap; va_start(ap, first); - const char *s = first; + const wxChar *s = first; for (;;) { Add(s); - s = va_arg(ap, const char *); - // if (s == NULL) -#ifdef __WXMSW__ - if ((int) s == 0) -#else - if ((long) s == 0) + // icc gives this warning in its own va_arg() macro, argh +#ifdef __INTELC__ + #pragma warning(push) + #pragma warning(disable: 1684) #endif + + s = va_arg(ap, const wxChar *); + +#ifdef __INTELC__ + #pragma warning(pop) +#endif + + if ( !s ) break; } va_end(ap); } -// Only makes new strings if arg is TRUE -char **wxStringList::ListToArray(bool new_copies) const +// Only makes new strings if arg is true +wxChar **wxStringList::ListToArray(bool new_copies) const { - char **string_array = new char *[GetCount()]; + wxChar **string_array = new wxChar *[GetCount()]; wxStringListNode *node = GetFirst(); for (size_t i = 0; i < GetCount(); i++) { - char *s = node->GetData(); + wxChar *s = node->GetData(); if ( new_copies ) - string_array[i] = copystring(s); + string_array[i] = MYcopystring(s); else string_array[i] = s; node = node->GetNext(); @@ -524,45 +688,78 @@ char **wxStringList::ListToArray(bool new_copies) const } // Checks whether s is a member of the list -bool wxStringList::Member(const char *s) const +bool wxStringList::Member(const wxChar *s) const { for ( wxStringListNode *node = GetFirst(); node; node = node->GetNext() ) { - const char *s1 = node->GetData(); - if (s == s1 || strcmp (s, s1) == 0) - return TRUE; + const wxChar *s1 = node->GetData(); + if (s == s1 || wxStrcmp (s, s1) == 0) + return true; } - return FALSE; + return false; } -static int +#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() { size_t N = GetCount(); - char **array = new char *[N]; + wxChar **array = new wxChar *[N]; + wxStringListNode *node; size_t i = 0; - for ( wxStringListNode *node = GetFirst(); node; node = node->GetNext() ) + 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); + + i = 0; + for ( node = GetFirst(); node; node = node->GetNext() ) + node->SetData( array[i++] ); + + delete [] array; +} + +wxNode *wxStringList::Add(const wxChar *s) +{ + return (wxNode *)(wxStringListBase::Node *) + wxStringListBase::Append(MYcopystring(s)); +} + +wxNode *wxStringList::Prepend(const wxChar *s) +{ + return (wxNode *)(wxStringListBase::Node *) + wxStringListBase::Insert(MYcopystring(s)); +} + +#endif // wxLIST_COMPATIBILITY - for (i = 0; i < N; i++) - Append (array[i]); +#else // wxUSE_STL = 1 - delete[]array; + #include "wx/listimpl.cpp" + WX_DEFINE_LIST(wxObjectList) + +// with wxUSE_STL wxStringList contains wxString objects, not pointers +void _WX_LIST_HELPER_wxStringListBase::DeleteFunction( wxString WXUNUSED(X) ) +{ } +wxStringListBase::BaseListType wxStringListBase::EmptyList; + +#endif // !wxUSE_STL