/* * Unnamed children (children_notag) have no sence without HText - * delete them and their links if we are about to free HText. * Document currently exists. Called within HText_free(). */ PUBLIC void HTAnchor_delete_links ARGS1( HTParentAnchor *, me) { HTList *cur; HTChildAnchor *child; /* * Do nothing if nothing to do. */ if (!me || !me->document) { return; } /* * Mark ourselves busy, so that recursive calls * on this HTParentAnchor0 will not free it from under our feet. - kw */ me->parent->underway = TRUE; /* * Delete all outgoing links from unnamed children. */ if (!HTList_isEmpty(&me->children_notag)) { cur = &me->children_notag; while ((child = (HTChildAnchor *)HTList_unlinkLastObject(cur)) != 0) { deleteLinks(child); /* child allocated in HText pool, HText_free() will free it later*/ } } me->parent->underway = FALSE; }
/* * Recursively try to delete destination anchor of this child. * In any event, this will tell destination anchor that we * no longer consider it a destination. */ PRIVATE void deleteLinks ARGS1( HTChildAnchor *, me) { /* * Unregister me with our destination anchor's parent. */ if (me->dest) { HTParentAnchor0 *parent = me->dest->parent; /* * Start. Set the dest pointer to zero. */ me->dest = NULL; /* * Remove me from the parent's sources so that the * parent knows one less anchor is its dest. */ if ((me->parent != parent) && !HTList_isEmpty(&parent->sources)) { /* * Really should only need to deregister once. */ HTList_unlinkObject(&parent->sources, (void *)me); } /* * Recursive call. * Test here to avoid calling overhead. * Don't delete if document is loaded or being loaded. */ if ((me->parent != parent) && !parent->underway && (!parent->info || !parent->info->document)) { HTAnchor_delete(parent); } /* * At this point, we haven't a destination. Set it to be * so. * Leave the HTAtom pointed to by type up to other code to * handle (reusable, near static). */ me->type = NULL; } }
PUBLIC BOOL HTAnchor_delete (HTParentAnchor * me) { /* Don't delete if document is loaded */ if (!me || me->document) { HTTRACE(ANCH_TRACE, "Anchor...... Not deleted\n"); return NO; } /* Recursively try to delete target anchors */ delete_links ((HTAnchor *) me); if (!HTList_isEmpty(me->sources)) { /* There are still incoming links */ /* ** Delete all outgoing links from children, if any */ if (me->children) { int cnt = 0; for (; cnt<CHILD_HASH_SIZE; cnt++) { HTList * kids = me->children[cnt]; if (kids) { HTChildAnchor * child; while ((child = (HTChildAnchor *) HTList_nextObject(kids))) delete_links((HTAnchor *) child); return NO; /* Parent not deleted */ } } } /* ** No more incoming links : kill everything ** First, recursively delete children */ if (me->children) { int cnt = 0; for (; cnt<CHILD_HASH_SIZE; cnt++) { HTList * kids = me->children[cnt]; if (kids) { HTChildAnchor * child; while ((child=(HTChildAnchor *) HTList_removeLastObject(kids))) delete_links((HTAnchor *) child); HT_FREE(child->tag); HT_FREE(child); } } } } /* 2001/03/06: Bug fix by Serge Adda <*****@*****.**> HTAnchor_delete wasn't removing the reference to the deleted anchor. This caused a bug whenever requesting another anchor for the same URL. */ if (adult_table) { int hash; const char *p; HTList * adults; HTList * grownups; HTList * last; HTParentAnchor * foundAnchor; /* Select list from hash table */ for(p=me->address, hash=0; *p; p++) hash = (int) ((hash * 3 + (*(unsigned char*)p)) % PARENT_HASH_SIZE); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; last = grownups; while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){ if (!strcmp(foundAnchor->address, me->address)) { HTList_quickRemoveElement (grownups, last); break; } last = grownups; } } /* Now kill myself */ delete_parent(me); return YES; /* Parent deleted */ #if 0 if (! HTList_isEmpty (me->sources)) { /* There are still incoming links */ /* Delete all outgoing links from children, if any */ HTList *kids = me->children; while ((child = (HTChildAnchor *) HTList_nextObject (kids))) delete_links ((HTAnchor *) child); return NO; /* Parent not deleted */ } /* No more incoming links : kill everything */ /* First, recursively delete children */ while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) { delete_links ((HTAnchor *) child); HT_FREE(child->tag); HT_FREE(child); } #endif }
PUBLIC BOOL HTAnchor_delete ARGS1( HTParentAnchor0 *, me) { /* * Memory leaks fixed. * 05-27-94 Lynx 2-3-1 Garrett Arch Blythe */ HTBTElement *ele; HTChildAnchor *child; /* * Do nothing if nothing to do. */ if (!me) { return(NO); } /* * Don't delete if document is loaded or being loaded. */ if (me->underway || (me->info && me->info->document)) { return(NO); } /* * Mark ourselves busy, so that recursive calls of this function * on this HTParentAnchor0 will not free it from under our feet. - kw */ me->underway = TRUE; { /* * Delete all outgoing links from named children. * Do not delete named children itself (may have incoming links). */ if (me->children) { ele = HTBTree_next(me->children, NULL); while (ele != NULL) { child = (HTChildAnchor *)HTBTree_object(ele); if (child->dest) deleteLinks(child); ele = HTBTree_next(me->children, ele); } } } me->underway = FALSE; /* * There are still incoming links to this one (we are the * destination of another anchor). */ if (!HTList_isEmpty(&me->sources)) { /* * Can't delete parent, still have sources. */ return(NO); } /* * No more incoming and outgoing links : kill everything * First, delete named children. */ if (me->children) { ele = HTBTree_next(me->children, NULL); while (ele != NULL) { child = (HTChildAnchor *)HTBTree_object(ele); FREE(child->tag); FREE(child); ele = HTBTree_next(me->children, ele); } HTBTree_free(me->children); } /* * Delete the ParentAnchor, if any. (Document was already deleted). */ if (me->info) { HTParentAnchor_free(me->info); FREE(me->info); } /* * Remove ourselves from the hash table's list. */ HTList_unlinkObject(&(adult_table[me->adult_hash]), (void *)me); /* * Free the address. */ FREE(me->address); /* * Finally, kill the parent anchor passed in. */ FREE(me); return(YES); }
BOOL HTQueue_isEmpty(HTList *me) { return HTList_isEmpty(me); }