1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxList implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "list.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
29 // Sun CC compatibility (interference with xview/pkg.h, apparently...)
30 #if defined(SUN_CC) && defined(__XVIEW__)
41 #if !USE_SHARED_LIBRARY
42 IMPLEMENT_DYNAMIC_CLASS(wxNode
, wxObject
)
43 IMPLEMENT_DYNAMIC_CLASS(wxList
, wxObject
)
44 IMPLEMENT_DYNAMIC_CLASS(wxStringList
, wxList
)
47 wxNode::wxNode (wxList
* the_list
, wxNode
* last_one
, wxNode
* next_one
,
57 previous
->next
= this;
60 next
->previous
= this;
64 wxNode::wxNode (wxList
* the_list
, wxNode
* last_one
, wxNode
* next_one
,
65 wxObject
* object
, long the_key
)
71 key
.integer
= the_key
;
74 previous
->next
= this;
77 next
->previous
= this;
80 wxNode::wxNode (wxList
* the_list
, wxNode
* last_one
, wxNode
* next_one
,
81 wxObject
* object
, const char *the_key
)
87 key
.string
= copystring (the_key
);
90 previous
->next
= this;
93 next
->previous
= this;
97 wxNode::~wxNode (void)
102 if (list
&& list
->destroy_data
)
105 if (list
&& list
->key_type
== wxKEY_STRING
&& key
.string
)
108 // Make next node point back to the previous node from here
110 next
->previous
= previous
;
112 // If there's a new end of list (deleting the last one)
113 // make sure the list knows about it.
114 list
->last_node
= previous
;
116 // Make the previous node point to the next node from here
118 previous
->next
= next
;
120 // Or if no previous node (start of list), make sure list points at
121 // the next node which becomes the first!.
123 list
->first_node
= next
;
126 wxList::wxList (void)
132 key_type
= wxKEY_NONE
;
135 wxList::wxList (int N
, wxObject
* Objects
[])
140 for (i
= 0; i
< N
; i
++)
142 wxNode
*next
= new wxNode (this, last
, NULL
, Objects
[i
]);
149 key_type
= wxKEY_NONE
;
152 wxList::wxList (const unsigned int the_key_type
)
158 key_type
= the_key_type
;
161 // Variable argument list, terminated by a zero
162 wxList::wxList (wxObject
* first_one
...)
167 va_start (ap
, first_one
);
169 wxNode
*last
= new wxNode (this, NULL
, NULL
, first_one
);
175 wxObject
*object
= va_arg (ap
, wxObject
*);
176 // if (object == NULL) // Doesn't work in Windows -- segment is non-zero for NULL!
178 if ((int) object
== 0)
180 if ((long) object
== 0)
185 wxNode
*node
= new wxNode (this, last
, NULL
, object
);
194 key_type
= wxKEY_NONE
;
197 fprintf (stderr, "Error: cannot use variable-argument functions on SGI!\n");
202 wxList::~wxList (void)
204 wxNode
*each
= first_node
;
207 wxNode
*next
= each
->Next ();
213 #ifdef USE_STORABLE_CLASSES
214 wxList::wxList( istream
&stream
, char *WXUNUSED(data
) )
218 stream
.read( (char*)(&num
), sizeof(num
) );
219 for (unsigned int i
= 0; i
< num
; i
++)
222 stream
.read( (char*)(&len
), sizeof(len
) );
223 stream
.read( (char*)(&buf
), len
);
225 Append( wxCreateStoredObject( buf
, stream
, NULL
) );
229 void wxList::StoreObject( ostream
&stream
)
231 unsigned int num
= Number();
232 stream
.write( (char*)(&num
), sizeof(num
) );
233 wxNode
*node
= First();
236 wxObject
*obj
= (wxObject
*) node
->Data();
237 wxClassInfo
*obj_info
= obj
->GetClassInfo();
238 int len
= strlen(obj_info
->className
);
239 stream
.write( (char*)(&len
), sizeof(len
) );
240 stream
.write( obj_info
->className
, len
);
241 obj
->StoreObject( stream
);
247 wxNode
*wxList::Append(wxObject
*object
)
249 wxNode
*node
= new wxNode(this, last_node
, NULL
, object
);
257 wxNode
*wxList::Nth (int i
) const
260 for (wxNode
* current
= First (); current
; current
= current
->Next ())
265 return NULL
; // No such element
269 wxNode
*wxList::Find (long key
) const
271 wxNode
*current
= First();
274 if (current
->key
.integer
== key
)
276 current
= current
->Next();
279 return NULL
; // Not found!
282 wxNode
*wxList::Find (const char *key
) const
284 wxNode
*current
= First();
287 if (!current
->key
.string
)
289 wxFatalError ("wxList: string key not present, probably did not Append correctly!");
292 if (strcmp (current
->key
.string
, key
) == 0)
294 current
= current
->Next();
297 return NULL
; // Not found!
301 wxNode
*wxList::Member (wxObject
* object
) const
303 for (wxNode
* current
= First (); current
; current
= current
->Next ())
305 wxObject
*each
= current
->Data ();
312 bool wxList::DeleteNode (wxNode
* node
)
322 bool wxList::DeleteObject (wxObject
* object
)
324 // Search list for object
325 for (wxNode
* current
= first_node
; current
; current
= current
->Next ())
327 if (current
->Data () == object
)
333 return FALSE
; // Did not find the object
338 // Insert new node at front of list
339 wxNode
*wxList::Insert (wxObject
* object
)
341 wxNode
*node
= new wxNode (this, NULL
, First (), object
);
344 if (!(node
->Next ()))
352 // Insert new node before given node.
353 wxNode
*wxList::Insert (wxNode
* position
, wxObject
* object
)
357 prev
= position
->Previous ();
359 wxNode
*node
= new wxNode (this, prev
, position
, object
);
373 wxNode
*wxList::Append (long key
, wxObject
* object
)
375 wxNode
*node
= new wxNode (this, last_node
, NULL
, object
, key
);
383 wxNode
*wxList::Append (const char *key
, wxObject
* object
)
385 wxNode
*node
= new wxNode (this, last_node
, NULL
, object
, key
);
393 void wxList::Clear (void)
395 wxNode
*current
= first_node
;
398 wxNode
*next
= current
->Next ();
407 //Executes function F with all items present in the list
408 void wxList::ForEach(wxListIterateFunction F
)
410 wxNode
*each
= first_node
;
412 { (*F
)( each
->Data ());
416 // Returns a pointer to the item which returns TRUE with function F
417 // or NULL if no such item found
418 wxObject
*wxList::FirstThat(wxListIterateFunction F
)
420 wxNode
*each
= first_node
;
422 { if ((*F
)( each
->Data ())) return each
->Data();
427 // Like FirstThat, but proceeds from the end backward
428 wxObject
*wxList::LastThat(wxListIterateFunction F
)
430 wxNode
*each
= last_node
;
432 { if ((*F
)( each
->Data ())) return each
->Data();
433 each
= each
->Previous();
438 // (stefan.hammes@urz.uni-heidelberg.de)
440 // function for sorting lists. the concept is borrowed from 'qsort'.
441 // by giving a sort function, arbitrary lists can be sorted.
443 // - put wxObject pointers into an array
444 // - sort the array with qsort
445 // - put back the sorted wxObject pointers into the list
447 // CAVE: the sort function receives pointers to wxObject pointers (wxObject **),
448 // so dereference right!
450 // int listcompare(const void *arg1, const void *arg2)
452 // return(compare(**(wxString **)arg1,
453 // **(wxString **)arg2));
460 // list.Append(new wxString("DEF"));
461 // list.Append(new wxString("GHI"));
462 // list.Append(new wxString("ABC"));
463 // list.Sort(listcompare);
466 void wxList::Sort(const wxSortCompareFunction compfunc
)
468 // allocate an array for the wxObject pointers of the list
469 const size_t num
= Number();
470 wxObject
**objArray
= new wxObject
*[num
];
471 wxObject
**objPtr
= objArray
;
473 // go through the list and put the pointers into the array
474 wxNode
*node
= First();
476 *objPtr
++ = node
->Data();
480 qsort((void *)objArray
,num
,sizeof(wxObject
*),compfunc
);
481 // put the sorted pointers back into the list
485 node
->SetData(*objPtr
++);
497 wxStringList::wxStringList (void):
502 // Variable argument list, terminated by a zero
503 // Makes new storage for the strings
504 wxStringList::wxStringList (const char *first
...)
509 key_type
= wxKEY_NONE
;
518 va_start (ap
, first
);
520 wxNode
*last
= new wxNode (this, NULL
, NULL
, (wxObject
*) copystring (first
));
526 char *s
= va_arg (ap
, char *);
536 wxNode
*node
= new wxNode (this, last
, NULL
, (wxObject
*) copystring (s
));
545 fprintf (stderr, "Error: cannot use variable-argument functions on SGI!\n");
550 wxStringList::~wxStringList (void)
552 wxNode
*each
= first_node
;
555 char *s
= (char *) each
->Data ();
557 wxNode
*next
= each
->Next ();
563 wxNode
*wxStringList::Add (const char *s
)
565 return Append ((wxObject
*) (copystring (s
)));
568 void wxStringList::Delete (const char *s
)
570 for (wxNode
* node
= First (); node
; node
= node
->Next ())
572 char *string
= (char *) node
->Data ();
573 if (string
== s
|| strcmp (string
, s
) == 0)
584 // Only makes new strings if arg is TRUE
585 char **wxStringList::ListToArray (bool new_copies
) const
587 char **string_array
= new char *[Number ()];
588 wxNode
*node
= First ();
590 for (i
= 0; i
< n
; i
++)
592 char *s
= (char *) node
->Data ();
594 string_array
[i
] = copystring (s
);
597 node
= node
->Next ();
603 wx_comparestrings (const void *arg1
, const void *arg2
)
605 char **s1
= (char **) arg1
;
606 char **s2
= (char **) arg2
;
608 return strcmp (*s1
, *s2
);
611 // Sort a list of strings - deallocates old nodes, allocates new
612 void wxStringList::Sort (void)
615 char **array
= new char *[N
];
618 for (wxNode
* node
= First (); node
; node
= node
->Next ())
619 array
[i
++] = (char *) node
->Data ();
621 qsort (array
, N
, sizeof (char *), wx_comparestrings
);
624 for (i
= 0; i
< N
; i
++)
625 Append ((wxObject
*) (array
[i
]));
630 // Checks whether s is a member of the list
631 bool wxStringList::Member (const char *s
) const
633 for (wxNode
* node
= First (); node
; node
= node
->Next ())
635 const char *s1
= (const char *) node
->Data ();
636 if (s
== s1
|| strcmp (s
, s1
) == 0)