racket/src/wxcommon/wb_list.cxx
Eli Barzilay 8a2753efb8 2008 -> 2009
svn: r13001
2009-01-04 15:34:50 +00:00

697 lines
12 KiB
C++

/*
* File: wb_list.cc
* Purpose: List implementation
* Author: Julian Smart
* Created: 1993
* Updated: August 1994
* Copyright: (c) 2004-2009 PLT Scheme Inc.
* Copyright: (c) 1993, AIAI, University of Edinburgh
*/
#pragma implementation "wx_list.h"
#if defined(_MSC_VER)
# include "wx.h"
#else
# ifdef wx_xt
# define Uses_wxList
# define Uses_wxStringList
# include "wx.h"
# else
# ifdef WX_CARBON
# include "wx_list.h"
# include "wx_utils.h"
# endif
# endif
#endif
#include <stdarg.h>
#include <string.h>
void wxNode::Setup(wxNode * last_one, wxNode * next_one,
wxObject * object)
{
data = object;
previous = last_one;
next = next_one;
integer_key = 0;
string_key = NULL;
if (previous)
previous->next = this;
if (next)
next->previous = this;
}
wxNode::wxNode (wxNode * last_one, wxNode * next_one,
wxObject * object)
{
Setup(last_one, next_one, object);
}
// Keyed constructor
wxNode::wxNode (wxNode * last_one, wxNode * next_one,
wxObject * object, long the_key)
{
Setup(last_one, next_one, object);
integer_key = the_key;
}
wxNode::wxNode (wxNode * last_one, wxNode * next_one,
wxObject * object, const char *the_key)
{
Setup(last_one, next_one, object);
string_key = copystring(the_key);
}
wxNode::wxNode (wxNode * last_one, wxNode * next_one,
wxObject * object, void *the_key)
{
Setup(last_one, next_one, object);
string_key = (char *)the_key;
}
void wxNode::Kill(wxList *list)
{
if (list)
list->n--;
#ifndef wx_mac
if (list && list->destroy_data)
DELETE_OBJ data;
#endif
// 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;
// Make the previous node point to the next node from here
if (previous)
previous->next = next;
// 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;
next = previous = NULL;
}
#ifdef wx_mac
wxList::wxList(DestroyDataCode destroyData, Bool clean_up)
: wxObject(clean_up)
{
__type = wxTYPE_LIST;
first_node = NULL;
last_node = NULL;
n = 0;
destroy_data = destroyData;
key_type = wxKEY_NONE;
}
#else // wx_mac
wxList::wxList (void)
{
__type = wxTYPE_LIST;
first_node = NULL;
last_node = NULL;
n = 0;
destroy_data = 0;
key_type = wxKEY_NONE;
}
#endif // wx_mac
wxList::wxList (int N, wxObject * Objects[])
{
wxNode *last = NULL;
int i;
__type = wxTYPE_LIST;
for (i = 0; i < N; i++) {
wxNode *next;
next = new WXGC_PTRS wxNode(last, NULL, Objects[i]);
last = next;
if (i == 0)
first_node = next;
}
last_node = last;
n = N;
key_type = wxKEY_NONE;
}
wxList::wxList(KeyType the_key_type, Bool clean_up)
: wxObject(clean_up)
{
__type = wxTYPE_LIST;
n = 0;
destroy_data = 0;
first_node = NULL;
last_node = NULL;
key_type = the_key_type;
}
wxList::~wxList (void)
{
wxNode *each = first_node;
wxNode *next;
while (each) {
next = each->Next ();
each->Kill(this);
DELETE_OBJ each;
each = next;
}
first_node = last_node = NULL;
}
wxNode *wxList::Nth (int i)
{
int j = 0;
wxNode * current;
for (current = First (); current; current = current->Next ()) {
if (j++ == i)
return current;
}
return NULL; // No such element
}
wxNode *wxList::Find(long key)
{
wxNode *current;
current = First();
while (current) {
if (current->integer_key == key)
return current;
current = current->Next();
}
return NULL; // Not found!
}
wxNode *wxList::Find(const char *key)
{
wxNode *current;
current = First();
while (current) {
if (!current->string_key) {
wxFatalError ("wxList: string key not present, probably did not Append correctly!");
break;
}
if (strcmp (current->string_key, key) == 0)
return current;
current = current->Next();
}
return NULL; // Not found!
}
wxNode *wxList::FindPtr(void *key)
{
wxNode *current;
current = First();
while (current) {
if ((void *)current->string_key == key)
return current;
current = current->Next();
}
return NULL; // Not found!
}
wxNode *wxList::Member (wxObject * object)
{
wxNode * current;
for (current = First (); current; current = current->Next ()) {
wxObject *each;
each = current->Data ();
if (each == object)
return current;
}
return NULL;
}
Bool wxList::DeleteNode (wxNode * node)
{
if (node) {
node->Kill(this);
DELETE_OBJ node;
return TRUE;
}
return FALSE;
}
Bool wxList::DeleteObject (wxObject * object)
{
wxNode * current;
// Search list for object
for (current = first_node; current; current = current->Next ()) {
if (current->Data () == object) {
current->Kill(this);
DELETE_OBJ current;
return TRUE;
}
}
return FALSE; // Did not find the object
}
wxNode *wxList::Append(wxObject *object)
{
wxNode *node;
node = new WXGC_PTRS wxNode(last_node, NULL, object);
return DoAppend(node);
}
// Insert new node at front of list
wxNode *wxList::Insert (wxObject * object)
{
wxNode *node;
node = First();
node = new WXGC_PTRS wxNode(NULL, node, object);
first_node = node;
if (!(node->Next()))
last_node = node;
n++;
return node;
}
// Insert new node before given node.
wxNode *wxList::Insert (wxNode * position, wxObject * object)
{
wxNode *prev = NULL;
wxNode *node;
if (position)
prev = position->Previous ();
node = new WXGC_PTRS wxNode(prev, position, object);
if (!first_node) {
first_node = node;
last_node = node;
}
if (!prev)
first_node = node;
n++;
return node;
}
// Keyed append
wxNode *wxList::Append (long key, wxObject * object)
{
wxNode *node;
node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
return DoAppend(node);
}
wxNode *wxList::Append (const char *key, wxObject * object)
{
wxNode *node;
node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
return DoAppend(node);
}
wxNode *wxList::Append (void *key, wxObject * object)
{
wxNode *node;
node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
return DoAppend(node);
}
wxNode *wxList::DoAppend(wxNode *node)
{
if (!first_node)
first_node = node;
last_node = node;
n++;
return node;
}
void wxList::Clear (void)
{
wxNode *current, *next;
current = first_node;
while (current) {
next = current->Next();
DELETE_OBJ current;
current = next;
}
first_node = NULL;
last_node = NULL;
n = 0;
}
#ifdef wx_mac
long wxList::MemberIndex(wxObject *object) // WCH wx_mac added 8/12/94
{
long result = 0;
wxNode *current;
wxNode *found = NULL;
current = First();
while (current && !found)
{
wxObject *each;
each = current->Data();
if (each == object)
found = current;
else {
current = current->Next();
result++;
}
}
return (found ? result : -1);
}
Bool wxList::OnDeleteObject(wxObject *object) // mac platform only
{
int destroy_data_saved = destroy_data; // kludge
destroy_data = kNoDestroyData; // kludge
DeleteObject(object);
destroy_data = destroy_data_saved; // kludge
return FALSE;
}
#endif // wx_mac
/*
* String list
*
*/
wxStringList::wxStringList (void):
wxList ()
{
__type = wxTYPE_STRING_LIST;
}
#ifdef MEMORY_USE_METHOD
long wxList::MemoryUse(void)
{
wxNode *node;
long s = 0;
for (node = First(); node; node = node->Next()) {
s += sizeof(wxNode);
}
return s + wxObject::MemoryUse();
}
#endif
wxStringList::~wxStringList (void)
{
wxNode *each, *next;
each = first_node;
while (each) {
next = each->Next();
DELETE_OBJ each;
each = next;
}
}
wxNode *wxStringList::Add (const char *s)
{
s = copystring(s);
return Append ((wxObject *)s);
}
void wxStringList::Delete (const char *s)
{
wxNode * node;
for (node = First (); node; node = node->Next ()) {
char *string;
string = (char *) node->Data ();
if (string == s || strcmp (string, s) == 0) {
DELETE_OBJ node;
break; // Done!
}
}
}
// Only makes new strings if arg is TRUE
char **wxStringList::ListToArray (Bool new_copies)
{
char **string_array;
wxNode *node;
int i, nbr;
nbr = Number();
string_array = new WXGC_PTRS char *[nbr];
node = First ();
for (i = 0; i < n; i++) {
char *s;
s = (char *) node->Data ();
if (new_copies) {
char *ss;
ss = copystring(s);
string_array[i] = ss;
} else
string_array[i] = s;
node = node->Next();
}
return string_array;
}
// Checks whether s is a member of the list
Bool wxStringList::Member (const char *s)
{
wxNode * node;
for (node = First (); node; node = node->Next ()) {
const char *s1;
s1 = (const char *) node->Data ();
if (s == s1 || strcmp (s, s1) == 0)
return TRUE;
}
return FALSE;
}
/****************************************************************************/
wxChildNode* wxChildNode::Next()
{
return owner->FindNode(this);
}
wxObject* wxChildNode::Data()
{
if (strong)
return strong;
else if (weak) {
wxObject *v;
v = cnGET_WEAK(weak);
#ifdef MZ_PRECISE_GC
if (!gcOBJ_TO_PTR(v))
return NULL;
if (v->__type == -1) {
/* Finalized! */
return NULL;
}
#endif
return v;
} else
return NULL;
}
Bool wxChildNode::IsShown()
{
return strong ? TRUE : FALSE;
}
wxChildList::wxChildList()
{
n = 0;
size = 0;
nodes = NULL;
}
wxChildList::~wxChildList()
{
}
void wxChildList::Append(wxObject *object)
{
int i;
wxChildNode *cn, **naya;
cn = new WXGC_PTRS wxChildNode;
cn->owner = this;
cn->strong = object;
cn->weak = NULL;
for (i = 0; i < size; i++) {
if (!nodes[i]) {
nodes[i] = cn;
n++;
return;
}
}
size = (size * 2) + 20;
naya = new WXGC_PTRS wxChildNode* [size];
for (i = 0; i < n; i++) {
naya[i] = nodes[i];
}
nodes = naya;
nodes[n++] = cn;
}
Bool wxChildList::DeleteObject(wxObject *object)
{
int i;
for (i = 0; i < size; i++) {
wxChildNode *node;
node = nodes[i];
if (node && (node->Data() == object)) {
node->strong = NULL;
node->weak = NULL;
nodes[i] = NULL;
n--;
return TRUE;
}
}
return FALSE;
}
Bool wxChildList::DeleteNode(wxChildNode *node)
{
int i;
for (i = 0; i < size; i++) {
wxChildNode *nodei;
nodei = nodes[i];
if (nodei == node) {
nodei->strong = NULL;
nodei->weak = NULL;
nodes[i] = NULL;
n--;
return TRUE;
}
}
return FALSE;
}
wxChildNode *wxChildList::FindNode(wxChildNode *after)
{
int i;
if (after) {
for (i = 0; i < size; i++) {
if (nodes[i] == after)
break;
}
i++;
} else
i = 0;
return NextNode(i);
}
wxChildNode *wxChildList::NextNode(int &pos)
{
int i;
for (i = pos; i < size; i++) {
if (nodes[i]) {
wxChildNode *node;
node = nodes[i];
if (node->Data()) {
pos = i + 1;
return node;
}
/* GC: */
node->strong = NULL;
node->weak = NULL;
nodes[i] = NULL;
n--;
}
}
return NULL;
}
void wxChildList::Show(wxObject *object, int show)
{
int i;
for (i = 0; i < size; i++) {
wxChildNode *node;
node = nodes[i];
if (node && (node->Data() == object)) {
if (show > 0) {
if (node->strong)
return;
node->strong = object;
node->weak = NULL;
} else {
#ifdef MZ_PRECISE_GC
void *weak;
#else
wxObject **weak;
#endif
if (node->weak)
return;
#ifdef MZ_PRECISE_GC
/* If show < 0, box should be weaker: it should go to NULL when
object is finalized. But the GC doesn't do that, so instead we
check for finalization in node->Data(). */
weak = GC_malloc_weak_box(gcOBJ_TO_PTR(object), NULL, 0);
#else
weak = new WXGC_ATOMIC wxObject*;
*weak = object;
if (show < 0)
GC_general_register_disappearing_link((void **)weak, object);
#endif
node->weak = weak;
node->strong = NULL;
}
return;
}
}
}
Bool wxChildList::IsShown(wxObject *object)
{
int i;
for (i = 0; i < size; i++) {
wxChildNode *node;
node = nodes[i];
if (node && (node->Data() == object)) {
return (node->strong) ? TRUE : FALSE;
}
}
return FALSE;
}