Back to index

plt-scheme  4.2.1
wb_list.cxx
Go to the documentation of this file.
00001 /*
00002  * File:             wb_list.cc
00003  * Purpose:   List implementation
00004  * Author:           Julian Smart
00005  * Created:   1993
00006  * Updated:   August 1994
00007  * Copyright: (c) 2004-2009 PLT Scheme Inc.
00008  * Copyright: (c) 1993, AIAI, University of Edinburgh
00009  */
00010 
00011 #pragma implementation "wx_list.h"
00012 
00013 #if defined(_MSC_VER)
00014 # include "wx.h"
00015 #else
00016 # ifdef wx_xt
00017 #  define  Uses_wxList
00018 #  define  Uses_wxStringList
00019 #  include "wx.h"
00020 # else
00021 #  ifdef WX_CARBON
00022 #   include "wx_list.h"
00023 #   include "wx_utils.h"
00024 #  endif
00025 # endif
00026 #endif
00027 
00028 #include <stdarg.h>
00029 #include <string.h>
00030 
00031 void wxNode::Setup(wxNode * last_one, wxNode * next_one, 
00032                  wxObject * object)
00033 {
00034   data = object;
00035   previous = last_one;
00036   next = next_one;
00037   integer_key = 0;
00038   string_key = NULL;
00039 
00040   if (previous)
00041     previous->next = this;
00042 
00043   if (next)
00044     next->previous = this;  
00045 }
00046 
00047 wxNode::wxNode (wxNode * last_one, wxNode * next_one,
00048               wxObject * object)
00049 {
00050   Setup(last_one, next_one, object);
00051 }
00052 
00053 // Keyed constructor
00054 wxNode::wxNode (wxNode * last_one, wxNode * next_one,
00055               wxObject * object, long the_key)
00056 {
00057   Setup(last_one, next_one, object);
00058   integer_key = the_key;
00059 }
00060 
00061 wxNode::wxNode (wxNode * last_one, wxNode * next_one,
00062               wxObject * object, const char *the_key)
00063 {
00064   Setup(last_one, next_one, object);
00065   string_key = copystring(the_key);
00066 }
00067 
00068 wxNode::wxNode (wxNode * last_one, wxNode * next_one,
00069               wxObject * object, void *the_key)
00070 {
00071   Setup(last_one, next_one, object);
00072   string_key = (char *)the_key;
00073 }
00074 
00075 
00076 void wxNode::Kill(wxList *list)
00077 {
00078   if (list)
00079     list->n--;
00080 
00081 #ifndef wx_mac
00082   if (list && list->destroy_data)
00083     DELETE_OBJ data;
00084 #endif
00085 
00086   // Make next node point back to the previous node from here
00087   if (next)
00088     next->previous = previous;
00089   else if (list)
00090     // If there's a new end of list (deleting the last one)
00091     // make sure the list knows about it.
00092     list->last_node = previous;
00093 
00094   // Make the previous node point to the next node from here
00095   if (previous)
00096     previous->next = next;
00097 
00098   // Or if no previous node (start of list), make sure list points at
00099   // the next node which becomes the first!.
00100   else if (list)
00101     list->first_node = next;
00102 
00103   next = previous = NULL;
00104 }
00105 
00106 #ifdef wx_mac
00107 wxList::wxList(DestroyDataCode destroyData, Bool clean_up)
00108 : wxObject(clean_up)
00109 {
00110   __type = wxTYPE_LIST;
00111   first_node = NULL;
00112   last_node = NULL;
00113   n = 0;
00114   destroy_data = destroyData;
00115   key_type = wxKEY_NONE;
00116 }
00117 #else // wx_mac
00118 wxList::wxList (void)
00119 {
00120   __type = wxTYPE_LIST;
00121   first_node = NULL;
00122   last_node = NULL;
00123   n = 0;
00124   destroy_data = 0;
00125   key_type = wxKEY_NONE;
00126 }
00127 #endif // wx_mac
00128 
00129 wxList::wxList (int N, wxObject * Objects[])
00130 {
00131   wxNode *last = NULL;
00132   int i;
00133 
00134   __type = wxTYPE_LIST;
00135 
00136   for (i = 0; i < N; i++) {
00137     wxNode *next;
00138     next = new WXGC_PTRS wxNode(last, NULL, Objects[i]);
00139     last = next;
00140     if (i == 0)
00141       first_node = next;
00142   }
00143   last_node = last;
00144   n = N;
00145   key_type = wxKEY_NONE;
00146 }
00147 
00148 wxList::wxList(KeyType the_key_type, Bool clean_up)
00149 : wxObject(clean_up)
00150 {
00151   __type = wxTYPE_LIST;
00152   n = 0;
00153   destroy_data = 0;
00154   first_node = NULL;
00155   last_node = NULL;
00156   key_type = the_key_type;
00157 }
00158 
00159 wxList::~wxList (void)
00160 {
00161   wxNode *each = first_node;
00162   wxNode *next;
00163 
00164   while (each) {
00165     next = each->Next ();
00166     
00167     each->Kill(this);
00168     DELETE_OBJ each;
00169     
00170     each = next;
00171   }
00172 
00173   first_node = last_node = NULL;
00174 }
00175 
00176 wxNode *wxList::Nth (int i)
00177 {
00178   int j = 0;
00179   wxNode * current;
00180   for (current = First (); current; current = current->Next ()) {
00181     if (j++ == i)
00182       return current;
00183   }
00184   return NULL;                     // No such element
00185 
00186 }
00187 
00188 wxNode *wxList::Find(long key)
00189 {
00190   wxNode *current;
00191   current = First();
00192   while (current) {
00193     if (current->integer_key == key)
00194       return current;
00195     current = current->Next();
00196   }
00197     
00198   return NULL;                     // Not found!
00199 }
00200 
00201 wxNode *wxList::Find(const char *key)
00202 {
00203   wxNode *current;
00204   current = First();
00205   while (current) {
00206     if (!current->string_key) {
00207       wxFatalError ("wxList: string key not present, probably did not Append correctly!");
00208       break;
00209     }
00210     if (strcmp (current->string_key, key) == 0)
00211       return current;
00212     current = current->Next();
00213   }
00214 
00215   return NULL;                     // Not found!
00216 
00217 }
00218 
00219 wxNode *wxList::FindPtr(void *key)
00220 {
00221   wxNode *current;
00222   current = First();
00223   while (current) {
00224     if ((void *)current->string_key == key)
00225       return current;
00226     current = current->Next();
00227   }
00228   
00229   return NULL;                     // Not found!
00230 }
00231 
00232 wxNode *wxList::Member (wxObject * object)
00233 {
00234   wxNode * current;
00235   for (current = First (); current; current = current->Next ()) {
00236     wxObject *each;
00237     each = current->Data ();
00238     if (each == object)
00239       return current;
00240   }
00241   return NULL;
00242 }
00243 
00244 Bool wxList::DeleteNode (wxNode * node)
00245 {
00246   if (node) {
00247     node->Kill(this);
00248     DELETE_OBJ node;
00249     return TRUE;
00250   }
00251   return FALSE;
00252 }
00253 
00254 Bool wxList::DeleteObject (wxObject * object)
00255 {
00256   wxNode * current;
00257   // Search list for object
00258   for (current = first_node; current; current = current->Next ()) {
00259     if (current->Data () == object) {
00260       current->Kill(this);
00261       DELETE_OBJ current;
00262       return TRUE;
00263     }
00264   }
00265   return FALSE;                    // Did not find the object
00266 }
00267 
00268 
00269 wxNode *wxList::Append(wxObject *object)
00270 {
00271   wxNode *node;
00272   node = new WXGC_PTRS wxNode(last_node, NULL, object);
00273   return DoAppend(node);
00274 }
00275 
00276 // Insert new node at front of list
00277 wxNode *wxList::Insert (wxObject * object)
00278 {
00279   wxNode *node;
00280 
00281   node = First();
00282   node = new WXGC_PTRS wxNode(NULL, node, object);
00283   first_node = node;
00284 
00285   if (!(node->Next()))
00286     last_node = node;
00287 
00288   n++;
00289   return node;
00290 }
00291 
00292 
00293 // Insert new node before given node.
00294 wxNode *wxList::Insert (wxNode * position, wxObject * object)
00295 {
00296   wxNode *prev = NULL;
00297   wxNode *node;
00298   if (position)
00299     prev = position->Previous ();
00300 
00301   node = new WXGC_PTRS wxNode(prev, position, object);
00302   if (!first_node) {
00303       first_node = node;
00304       last_node = node;
00305   }
00306   if (!prev)
00307     first_node = node;
00308 
00309   n++;
00310   return node;
00311 }
00312 
00313 // Keyed append
00314 wxNode *wxList::Append (long key, wxObject * object)
00315 {
00316   wxNode *node;
00317   node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
00318   return DoAppend(node);
00319 }
00320 
00321 wxNode *wxList::Append (const char *key, wxObject * object)
00322 {
00323   wxNode *node;
00324   node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
00325   return DoAppend(node);
00326 }
00327 
00328 wxNode *wxList::Append (void *key, wxObject * object)
00329 {
00330   wxNode *node;
00331   node = new WXGC_PTRS wxNode(last_node, NULL, object, key);
00332   return DoAppend(node);
00333 }
00334 
00335 wxNode *wxList::DoAppend(wxNode *node)
00336 {
00337   if (!first_node)
00338     first_node = node;
00339   last_node = node;
00340   n++;
00341   return node;
00342 }
00343 
00344 void wxList::Clear (void)
00345 {
00346   wxNode *current, *next;
00347 
00348   current = first_node;
00349   while (current) {
00350     next = current->Next();
00351     DELETE_OBJ current;
00352     current = next;
00353   }
00354   first_node = NULL;
00355   last_node = NULL;
00356   n = 0;
00357 }
00358 
00359 #ifdef wx_mac
00360 long wxList::MemberIndex(wxObject *object) // WCH wx_mac added 8/12/94
00361 {
00362   long result = 0;
00363   wxNode *current;
00364   wxNode *found = NULL;
00365   current = First();
00366   while (current && !found)
00367   {
00368     wxObject *each;
00369     each = current->Data();
00370     if (each == object)
00371       found = current;
00372     else {
00373       current = current->Next();
00374       result++;
00375     }
00376   }
00377   return (found ? result : -1);
00378 }
00379 
00380 Bool wxList::OnDeleteObject(wxObject *object)  // mac platform only
00381 {
00382   int destroy_data_saved = destroy_data; // kludge
00383   destroy_data = kNoDestroyData; // kludge
00384 
00385   DeleteObject(object);
00386     
00387   destroy_data = destroy_data_saved; // kludge
00388   
00389   return FALSE;
00390 }
00391 #endif // wx_mac
00392 
00393 /*
00394  * String list
00395  *
00396  */
00397 
00398 wxStringList::wxStringList (void):
00399 #ifdef wx_mac
00400  wxList(kNoDestroyData, FALSE)
00401 #else
00402  wxList ()
00403 #endif
00404 {
00405   __type = wxTYPE_STRING_LIST;
00406 }
00407 
00408 #ifdef MEMORY_USE_METHOD
00409 long wxList::MemoryUse(void)
00410 {
00411   wxNode *node;
00412   long s = 0;
00413 
00414   for (node = First(); node; node = node->Next()) {
00415     s += sizeof(wxNode);
00416   }
00417   
00418   return s + wxObject::MemoryUse();
00419 }
00420 #endif
00421 
00422 wxStringList::~wxStringList (void)
00423 {
00424   wxNode *each, *next;
00425 
00426   each = first_node;
00427   while (each) {
00428     next = each->Next();
00429     DELETE_OBJ each;
00430     each = next;
00431   }
00432 }
00433 
00434 wxNode *wxStringList::Add (const char *s)
00435 {
00436   s = copystring(s);
00437   return Append ((wxObject *)s);
00438 }
00439 
00440 void wxStringList::Delete (const char *s)
00441 {
00442   wxNode * node;
00443   for (node = First (); node; node = node->Next ()) {
00444     char *string;
00445     string = (char *) node->Data ();
00446     if (string == s || strcmp (string, s) == 0) {
00447       DELETE_OBJ node;
00448       break;         // Done!
00449     }
00450   }
00451 }
00452 
00453 // Only makes new strings if arg is TRUE
00454 char **wxStringList::ListToArray (Bool new_copies)
00455 {
00456   char **string_array;
00457   wxNode *node;
00458   int i, nbr;
00459 
00460   nbr = Number();
00461   string_array = new WXGC_PTRS char *[nbr];
00462   node = First ();
00463   for (i = 0; i < n; i++) {
00464     char *s;
00465     s = (char *) node->Data ();
00466     if (new_copies) {
00467       char *ss;
00468       ss = copystring(s);
00469       string_array[i] = ss;
00470     } else
00471       string_array[i] = s;
00472     node = node->Next();
00473   }
00474   return string_array;
00475 }
00476 
00477 // Checks whether s is a member of the list
00478 Bool wxStringList::Member (const char *s)
00479 {
00480   wxNode * node;
00481   for (node = First (); node; node = node->Next ()) {
00482     const char *s1;
00483     s1 = (const char *) node->Data ();
00484     if (s == s1 || strcmp (s, s1) == 0)
00485       return TRUE;
00486   }
00487 
00488   return FALSE;
00489 }
00490 
00491 /****************************************************************************/
00492 
00493 wxChildNode* wxChildNode::Next()
00494 {
00495   return owner->FindNode(this);
00496 }
00497 
00498 wxObject* wxChildNode::Data()
00499 {
00500   if (strong)
00501     return strong;
00502   else if (weak) {
00503     wxObject *v;
00504     v = cnGET_WEAK(weak);
00505 #ifdef MZ_PRECISE_GC
00506     if (!gcOBJ_TO_PTR(v))
00507       return NULL;
00508     if (v->__type == -1) {
00509       /* Finalized! */
00510       return NULL;
00511     }
00512 #endif
00513     return v;
00514   } else
00515     return NULL;
00516 }
00517 
00518 Bool wxChildNode::IsShown()
00519 {
00520   return strong ? TRUE : FALSE;
00521 }
00522 
00523 wxChildList::wxChildList()
00524 {
00525   n = 0;
00526   size = 0;
00527   nodes = NULL;
00528 }
00529 
00530 wxChildList::~wxChildList()
00531 {
00532   
00533 }
00534 
00535 void wxChildList::Append(wxObject *object)
00536 {
00537   int i;
00538   wxChildNode *cn, **naya;
00539 
00540   cn = new WXGC_PTRS wxChildNode;
00541 
00542   cn->owner = this;
00543   cn->strong = object;
00544   cn->weak = NULL;
00545   
00546   for (i = 0; i < size; i++) {
00547     if (!nodes[i]) {
00548       nodes[i] = cn;
00549       n++;
00550       return;
00551     }
00552   }
00553 
00554   size = (size * 2) + 20;
00555   naya = new WXGC_PTRS wxChildNode* [size];
00556   for (i = 0; i < n; i++) {
00557     naya[i] = nodes[i];
00558   }
00559 
00560   nodes = naya;
00561   nodes[n++] = cn;
00562 }
00563 
00564 Bool wxChildList::DeleteObject(wxObject *object)
00565 {
00566   int i;
00567 
00568   for (i = 0; i < size; i++) {
00569     wxChildNode *node;
00570     node = nodes[i];
00571     if (node && (node->Data() == object)) {
00572       node->strong = NULL;
00573       node->weak = NULL;
00574       nodes[i] = NULL;
00575       n--;
00576 
00577       return TRUE;
00578     }
00579   }
00580 
00581   return FALSE;
00582 }
00583 
00584 Bool wxChildList::DeleteNode(wxChildNode *node)
00585 {
00586   int i;
00587 
00588   for (i = 0; i < size; i++) {
00589     wxChildNode *nodei;
00590     nodei = nodes[i];
00591     if (nodei == node) {
00592       nodei->strong = NULL;
00593       nodei->weak = NULL;
00594       nodes[i] = NULL;
00595       n--;
00596 
00597       return TRUE;
00598     }
00599   }
00600 
00601   return FALSE;
00602 }
00603 
00604 wxChildNode *wxChildList::FindNode(wxChildNode *after)
00605 {
00606   int i;
00607 
00608   if (after) {
00609     for (i = 0; i < size; i++) {
00610       if (nodes[i] == after)
00611        break;
00612     }
00613     i++;
00614   } else
00615     i = 0;
00616 
00617   return NextNode(i);
00618 }
00619 
00620 wxChildNode *wxChildList::NextNode(int &pos)
00621 {
00622   int i;
00623 
00624   for (i = pos; i < size; i++) {
00625     if (nodes[i]) {
00626       wxChildNode *node;
00627       node = nodes[i];
00628       
00629       if (node->Data()) {
00630        pos = i + 1;
00631        return node;
00632       }
00633       /* GC: */
00634       node->strong = NULL;
00635       node->weak = NULL;
00636       nodes[i] = NULL;
00637       n--;
00638     }
00639   }
00640 
00641   return NULL;
00642 }
00643 
00644 void wxChildList::Show(wxObject *object, int show)
00645 {
00646   int i;
00647 
00648   for (i = 0; i < size; i++) {
00649     wxChildNode *node;
00650     node = nodes[i];
00651     if (node && (node->Data() == object)) {
00652       if (show > 0) {
00653        if (node->strong)
00654          return;
00655        node->strong = object;
00656        node->weak = NULL;
00657       } else {
00658 #ifdef MZ_PRECISE_GC
00659        void *weak;
00660 #else
00661        wxObject **weak;
00662 #endif
00663 
00664        if (node->weak)
00665          return;
00666 
00667 #ifdef MZ_PRECISE_GC
00668        /* If show < 0, box should be weaker: it should go to NULL when
00669           object is finalized. But the GC doesn't do that, so instead we
00670           check for finalization in node->Data(). */
00671        weak = GC_malloc_weak_box(gcOBJ_TO_PTR(object), NULL, 0);
00672 #else
00673        weak = new WXGC_ATOMIC wxObject*;
00674        *weak = object;
00675        if (show < 0)
00676          GC_general_register_disappearing_link((void **)weak, object);
00677 #endif
00678 
00679        node->weak = weak;
00680        node->strong = NULL;
00681       }
00682       return;
00683     }
00684   }
00685 }
00686 
00687 Bool wxChildList::IsShown(wxObject *object)
00688 {
00689   int i;
00690 
00691   for (i = 0; i < size; i++) {
00692     wxChildNode *node;
00693     node = nodes[i];
00694     if (node && (node->Data() == object)) {
00695       return (node->strong) ? TRUE : FALSE;
00696     }
00697   }
00698 
00699   return FALSE;
00700 }