XP_List * pList = GetCallbackFuncList((int32)FRAME_ON_UNLOAD);
XP_List * pList = LAPIGetCallbackFuncList((int32)FRAME_ON_UNLOAD);
lo_InternalDiscardDocument(MWContext *context, lo_DocState *state,						   pa_DocData *doc_data, Bool bWholeDoc){	int32 doc_id;	LO_Element *recycle_list;	LO_Element **line_array;	LO_TextAttr **text_attr_hash;	/* Look in doc_data->url_struct for the *new* document's reload flag. */	JSBool resize_reload = 		(JSBool)(doc_data != NULL && doc_data->url_struct->resize_reload);    /* XXX We're not getting rid of stuff on the deferred image list when     * the editor does a relayout. The problem is that there might still be     * entries on the list that corresponds to the old state of the document.     */    if (bWholeDoc)	    lo_discard_unprocessed_deferred_images(context);	/*	 * Order is crucial here: run the onunload handlers in a frames tree	 * from the top down, but destroy frames bottom-up.  Look for the	 * LM_ReleaseDocument call below, almost at the end of this function.	 * This way, onunload handlers get to use their kids' properties, and	 * kids get to use their parent's properties and functions.	 */	if (bWholeDoc)	{		pa_DocData *old_doc_data;				old_doc_data = state->top_state->doc_data;		if (old_doc_data != NULL)		{			NET_StreamClass *parser_stream;			parser_stream = old_doc_data->parser_stream;			parser_stream->abort(parser_stream, 0);			state->top_state->doc_data = NULL;		}	}#ifdef LAYPROBE_API	{		/* Send a notification when a frame unloads */		XP_List * pList = GetCallbackFuncList((int32)FRAME_ON_UNLOAD);				if (pList)		{			while (pList = pList->next)			{				if (pList->object)					(*((ID_NOTIFY_PT)pList->object))((void*)context);			}		}				/* clean up allocated memory */		if (state->top_state->LAPIprobe)		{			LAPIDestroyProbe(state->top_state->LAPIprobe);			state->top_state->LAPIprobe = NULL;		}	}#endif /* LAYPROBE_API */	if ( state->top_state->trash != NULL)	{		lo_RecycleElements(context, state,			state->top_state->trash);		state->top_state->trash = NULL;	}	if (state->float_list != NULL)	{		lo_RecycleElements(context, state, state->float_list);		state->float_list = NULL;	}	if (state->line_array != NULL)	{		LO_Element *eptr;		LO_Element **line_array_tmp;#ifdef XP_WIN16		{			XP_Block *larray_array;			intn cnt;			XP_LOCK_BLOCK(larray_array, XP_Block *,					state->larray_array);			cnt = state->larray_array_size - 1;			while (cnt > 0)			{				XP_FREE_BLOCK(larray_array[cnt]);				cnt--;			}			state->line_array = larray_array[0];			XP_UNLOCK_BLOCK(state->larray_array);			XP_FREE_BLOCK(state->larray_array);		}#endif /* XP_WIN16 */		eptr = NULL;		XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);		eptr = line_array[0];		line_array_tmp = (LO_Element **)state->line_array;		state->line_array = NULL;        /* If this is a relayout delete, the elements are already owned by the document. So         * don't recycle them.         */		if ( bWholeDoc && eptr != NULL)		{			lo_RecycleElements(context, state, eptr);		}		XP_UNLOCK_BLOCK(line_array_tmp);		XP_FREE_BLOCK(line_array_tmp);	}	if ( bWholeDoc && state->top_state->text_attr_hash != NULL)	{		LO_TextAttr *attr;		LO_TextAttr *attr_ptr;		int i;		XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **,			state->top_state->text_attr_hash);		for (i=0; i<FONT_HASH_SIZE; i++)		{			attr_ptr = text_attr_hash[i];			while (attr_ptr != NULL)			{				attr = attr_ptr;				if (attr->FE_Data != NULL)				{					FE_ReleaseTextAttrFeData(context, attr);					attr->FE_Data = NULL;				}				attr_ptr = attr_ptr->next;				XP_DELETE(attr);			}			text_attr_hash[i] = NULL;		}		XP_UNLOCK_BLOCK(state->top_state->text_attr_hash);		XP_FREE_BLOCK(state->top_state->text_attr_hash);		state->top_state->text_attr_hash = NULL;	}	if ( bWholeDoc && state->top_state->font_face_array != NULL)	{		int i;		char **face_list;		PA_LOCK(face_list, char **, state->top_state->font_face_array);		for (i=0; i < state->top_state->font_face_array_len; i++)		{			XP_FREE(face_list[i]);		}		PA_UNLOCK(state->top_state->font_face_array);		PA_FREE(state->top_state->font_face_array);		state->top_state->font_face_array = NULL;		state->top_state->font_face_array_len = 0;		state->top_state->font_face_array_size = 0;	}	if ( bWholeDoc && state->top_state->map_list != NULL)	{		lo_MapRec *map_list;		map_list = state->top_state->map_list;		while (map_list != NULL)		{			map_list = lo_FreeMap(map_list);		}		state->top_state->map_list = NULL;	}    if (bWholeDoc)        lo_DeleteDocLists(context, &state->top_state->doc_lists);    else if (state->top_state->doc_lists.name_list != NULL)	{		lo_NameList *nptr;		nptr = state->top_state->doc_lists.name_list;		while (nptr != NULL)		{			lo_NameList *name_rec;			name_rec = nptr;			nptr = nptr->next;			if (name_rec->name != NULL)			{				PA_FREE(name_rec->name);			}			XP_DELETE(name_rec);		}		state->top_state->doc_lists.name_list = NULL;	}	if ( bWholeDoc && state->top_state->the_grid != NULL)	{		pa_DocData *save;		lo_GridRec *grid;		lo_GridCellRec *cell_ptr;		Bool incomplete;		save = lo_internal_doc_data;		lo_internal_doc_data = doc_data;		grid = state->top_state->the_grid;		cell_ptr = grid->cell_list;		/*		 * If this grid document finished loading, save		 * its grid data to be restored when we return through		 * history.		 * We still have to free the FE grid windows.		 */		incomplete = (state->top_state->layout_status != PA_COMPLETE);		if (incomplete == FALSE)		{			while (cell_ptr != NULL)			{				intn cell_status;				char *old_url;				cell_status =					lo_GetCurrentGridCellStatus(cell_ptr);				/*				 * Only save cell history for COMPLETE cells.				 */				if (cell_status == PA_COMPLETE)				{				    /*				     * free the original url for this cell.				     */				    old_url = cell_ptr->url;				    if (cell_ptr->url != NULL)				    {						XP_FREE(cell_ptr->url);				    }				    /*				     * Fetch the url for the current contents				     * of the cell, and save that.				     */				    cell_ptr->url =					lo_GetCurrentGridCellUrl(cell_ptr);				    cell_ptr->hist_list = NULL;				    if (cell_ptr->context != NULL)				    {					cell_ptr->hist_list = FE_FreeGridWindow(						cell_ptr->context, TRUE);				    }				}				else				{				    incomplete = TRUE;				    cell_ptr->hist_list = NULL;				    if (cell_ptr->context != NULL)				    {					(void)FE_FreeGridWindow(						cell_ptr->context, FALSE);				    }				}				cell_ptr->context = NULL;				cell_ptr = cell_ptr->next;			}		}		/*		 * Check again in case one or more frames were incomplete.		 * Also, some special windows have no history (such as		 * the document info window).  We can't save grid		 * data for those windows and should free it instead.		 */		if ((incomplete == FALSE)&&			(state->top_state->savedData.Grid != NULL))		{			state->top_state->savedData.Grid->the_grid =				state->top_state->the_grid;			state->top_state->savedData.Grid->main_width =				grid->main_width;			state->top_state->savedData.Grid->main_height =				grid->main_height;		}		/*		 * Else free up everything now.		 */		else		{			cell_ptr = grid->cell_list;			/*			 * It is important to NULL out the cell_list			 * now because FE_FreeGridWindow() could lead to			 * somone trying to traverse it while we are in			 * the middle of deleting it.			 */			grid->cell_list = NULL;			while (cell_ptr != NULL)			{				lo_GridCellRec *tmp_cell;				if (cell_ptr->context != NULL)				{					/*					 * The context still owns its history					 * list, so null the cell's pointer to					 * be clear.  If this cell doesn't have					 * a context, then it owns the history					 * list and lo_FreeGridCellRec() will					 * free it.					 */					cell_ptr->hist_list = NULL;					(void)FE_FreeGridWindow(						cell_ptr->context, FALSE);				}				tmp_cell = cell_ptr;				cell_ptr = cell_ptr->next;				lo_FreeGridCellRec(context, grid, tmp_cell);			}			lo_FreeGridRec(grid);		}		state->top_state->the_grid = NULL;		lo_internal_doc_data = save;	}	if ( bWholeDoc && state->top_state->url != NULL)	{		XP_FREE(state->top_state->url);		state->top_state->url = NULL;	}	if ( bWholeDoc )	{		XP_FREEIF(state->top_state->inline_stream_blocked_base_url);        XP_FREEIF(state->top_state->main_stream_blocked_base_url);        XP_FREEIF(state->top_state->base_url);	}	if ( bWholeDoc && state->top_state->base_target != NULL)	{		XP_FREE(state->top_state->base_target);		state->top_state->base_target = NULL;	}	if ( bWholeDoc && state->top_state->name_target != NULL)	{		XP_FREE(state->top_state->name_target);		state->top_state->name_target = NULL;	}#ifdef HTML_CERTIFICATE_SUPPORT	if ( bWholeDoc && state->top_state->cert_list != NULL)	{		lo_Certificate *cptr;		cptr = state->top_state->cert_list;		while (cptr != NULL)		{			lo_Certificate *lo_cert;			lo_cert = cptr;			cptr = cptr->next;			if (lo_cert->name != NULL)			{				PA_FREE(lo_cert->name);			}			if (lo_cert->cert != NULL)			{				CERT_DestroyCertificate(lo_cert->cert);			}			XP_DELETE(lo_cert);		}		state->top_state->cert_list = NULL;	}#endif /* HTML_CERTIFICATE_SUPPORT */	if (bWholeDoc && state->top_state->unknown_head_tag != NULL)	{		XP_FREE(state->top_state->unknown_head_tag);		state->top_state->unknown_head_tag = NULL;	}	if(resize_reload)	{		/* LJM: Save the JSS state in the hist so that we can get it	 	 * once the resize is complete		 */		History_entry *he = SHIST_GetCurrent(&context->hist);		if (he)		{			he->savedData.style_stack = state->top_state->style_stack;			state->top_state->style_stack = 0;		}		else		{			if (state->top_state->style_stack != 0)				STYLESTACK_Delete(state->top_state->style_stack);			state->top_state->style_stack = 0;		}	}	else	{		if (state->top_state->style_stack != 0)			STYLESTACK_Delete(state->top_state->style_stack);		state->top_state->style_stack = 0;	}	/* XXX all this because grid docs are never re-parsed after first load. */	if (!resize_reload &&		((state->top_state->savedData.OnLoad != NULL)||		 (state->top_state->savedData.OnUnload != NULL)||		 (state->top_state->savedData.OnFocus != NULL)||		 (state->top_state->savedData.OnBlur != NULL)||		 (state->top_state->savedData.OnHelp != NULL)||		 (state->top_state->savedData.OnMouseOver != NULL)||		 (state->top_state->savedData.OnMouseOut != NULL)||		 (state->top_state->savedData.OnDragDrop != NULL)||		 (state->top_state->savedData.OnMove != NULL)||		 (state->top_state->savedData.OnResize != NULL)))	{		History_entry *he = SHIST_GetCurrent(&context->hist);		if (he)		{			he->savedData.OnLoad = state->top_state->savedData.OnLoad;			he->savedData.OnUnload = state->top_state->savedData.OnUnload;			he->savedData.OnFocus = state->top_state->savedData.OnFocus;			he->savedData.OnBlur = state->top_state->savedData.OnBlur; 			he->savedData.OnHelp = state->top_state->savedData.OnHelp; 			he->savedData.OnMouseOver = state->top_state->savedData.OnMouseOver; 			he->savedData.OnMouseOut = state->top_state->savedData.OnMouseOut; 			he->savedData.OnDragDrop = state->top_state->savedData.OnDragDrop; 			he->savedData.OnMove = state->top_state->savedData.OnMove; 			he->savedData.OnResize = state->top_state->savedData.OnResize;		}		else		{			if (state->top_state->savedData.OnLoad != NULL)				PA_FREE(state->top_state->savedData.OnLoad);			if (state->top_state->savedData.OnUnload != NULL)				PA_FREE(state->top_state->savedData.OnUnload);			if (state->top_state->savedData.OnFocus != NULL)				PA_FREE(state->top_state->savedData.OnFocus);			if (state->top_state->savedData.OnBlur != NULL)				PA_FREE(state->top_state->savedData.OnBlur);			if (state->top_state->savedData.OnHelp != NULL)				PA_FREE(state->top_state->savedData.OnHelp);			if (state->top_state->savedData.OnMouseOver != NULL)				PA_FREE(state->top_state->savedData.OnMouseOver);			if (state->top_state->savedData.OnMouseOut != NULL)				PA_FREE(state->top_state->savedData.OnMouseOut);			if (state->top_state->savedData.OnDragDrop != NULL)				PA_FREE(state->top_state->savedData.OnDragDrop);			if (state->top_state->savedData.OnMove != NULL)				PA_FREE(state->top_state->savedData.OnMove);			if (state->top_state->savedData.OnResize != NULL)				PA_FREE(state->top_state->savedData.OnResize);		}		state->top_state->savedData.OnLoad = NULL;		state->top_state->savedData.OnUnload = NULL;		state->top_state->savedData.OnFocus = NULL;		state->top_state->savedData.OnBlur = NULL;		state->top_state->savedData.OnHelp = NULL;		state->top_state->savedData.OnMouseOver = NULL;		state->top_state->savedData.OnMouseOut = NULL;		state->top_state->savedData.OnDragDrop = NULL;		state->top_state->savedData.OnMove = NULL;		state->top_state->savedData.OnResize = NULL;	}	if ( bWholeDoc )	{#ifdef WEBFONTS	    /* Release webfonts loaded by this document */	    if (WF_fbu && !resize_reload)	    {		    nffbu_ReleaseWebfonts(WF_fbu, context, NULL);	    }#endif /* WEBFONTS */        recycle_list = state->top_state->recycle_list;        /* Some lo_ImageStructs may have been reclaimed by the Memory Arenas           code without actually calling IL_DestroyImage first.  This call           frees up any remaining image lib requests. */        IL_DestroyImageGroup(context->img_cx);        lo_DestroyBlinkers(context);        if (state->top_state->layers)         {            int i;            lo_TopState *top_state = state->top_state;            /* If we're resizing, prevent the GC'ing of the JS object             * associated with this layer when the layer destructor is             * called, since we want to preserve it across a resize,             * except for those layers created with JS's new operator,             * which aren't preserved across resize.  */            if (resize_reload)            {                for (i = 1; i <= state->top_state->max_layer_num; i++)                {                    lo_LayerDocState *layer_state = state->top_state->layers[i];                    if (!layer_state || layer_state->is_constructed_layer)                        continue;                                    layer_state->mocha_object = NULL;                    state->top_state->layers[i] = NULL;                }            }            /* Delete the main document layer_state */            top_state->layers[0]->layer = NULL;            lo_DeleteLayerState(context, state, top_state->layers[0]);                        top_state->num_layers_allocated = 0;            top_state->max_layer_num = 0;            lo_DeleteLayerStack(state);        }        if (context->compositor){            lo_DestroyLayers(context);            /* Reset the compositor to do on-screen compositing by default. */            CL_SetCompositorOffscreenDrawing(context->compositor,                                             CL_OFFSCREEN_AUTO);            CL_SetCompositorEnabled(context->compositor, PR_FALSE);        }        XP_FREEIF(state->top_state->layers);    }    if ( bWholeDoc ) {    	/* throw out mocha cruft */    	ET_ReleaseDocument(context, resize_reload);	    XP_DELETE(state->top_state);	    XP_DELETE(state);	    /*	     * Get the unique document ID, and remove this	     * documents layout state.	     */	    doc_id = XP_DOCID(context);	    lo_RemoveTopState(doc_id);    }    else    {        XP_DELETE(state);        recycle_list = NULL;    }	return(recycle_list);}