gecko-dev/lib/xp/xp_ncent.c

882 строки
27 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "xp.h"
#include "xp_ncent.h"
/* xp_ncent.c
* Contains various housekeeping dealing with the NavCenter
* in an XP layer.
*/
#ifdef MOZILLA_CLIENT
/* Define this if you want frame children in the nav center.
#define WANTFRAMES
*/
static XP_List *xp_GlobalLastActiveContext = NULL;
static XP_List *xp_GlobalDockedNavCenters = NULL;
static XP_List *xp_GlobalNavCenters = NULL;
static XP_List *xp_GlobalNavCenterInfo = NULL;
static XP_List *xp_GlobalViewHTMLPanes = NULL;
/* Various info that should be displayed in a NavCenter should
* the context have some nav centers to display in.
*/
typedef struct {
MWContext *m_pContext;
char *m_pUrl;
XP_List *m_pSitemaps;
} NavCenterContextInfo;
/* HT_Pane to MWContext association for tracking docked state.
*/
typedef struct {
MWContext *m_pContext;
HT_Pane m_htPane;
} DockedNavCenter;
/* HT_View to MWContext association for loading HTML into
* a NavCenter pane.
*/
typedef struct {
HT_View m_htView;
MWContext *m_pContext;
} ViewHTMLPane;
/* Find filter for nav center contexts.
*/
static XP_Bool xp_canbenavcentertarget(MWContext *pCX)
{
XP_Bool bRetval = FALSE;
if(NULL == pCX) {
/* Invalid param.
*/
}
else if(MWContextBrowser != pCX->type) {
/* Only looking for browser contexts.
*/
}
else if(pCX->is_grid_cell) {
/* Grid cells not allowed
*/
}
else if(EDT_IS_EDITOR(pCX)) {
/* Editor contexts not allowed
*/
}
else if(pCX->name && 0 == XP_STRCASECMP(pCX->name, "Netscape_Netcaster_Drawer")) {
/* Netcaster windows not allowed
*/
}
else {
bRetval = TRUE;
}
return(bRetval);
}
/* Function to return last active context which fits nav center
* criteria.
*/
static MWContext *xp_lastactivenavcentercontext(void)
{
return(XP_GetLastActiveContext(xp_canbenavcentertarget));
}
/* Return nav center info for a context.
* Can return NULL.
*/
static NavCenterContextInfo *xp_getnavcenterinfo(MWContext *pContext)
{
NavCenterContextInfo *pInfo = NULL;
if(pContext) {
XP_List *pTraverse = xp_GlobalNavCenterInfo;
/* Go through the global list and return the object if found.
*/
while((pInfo = (NavCenterContextInfo *)XP_ListNextObject(pTraverse))) {
if(pContext == pInfo->m_pContext) {
break;
}
pInfo = NULL;
}
}
return(pInfo);
}
/* Clean out the structure except for context pointer
*/
static void xp_gutnavcenterinfo(NavCenterContextInfo *pInfo)
{
if(pInfo) {
if(pInfo->m_pUrl) {
XP_FREE(pInfo->m_pUrl);
pInfo->m_pUrl = NULL;
}
if(pInfo->m_pSitemaps) {
XP_List *pTraverse = pInfo->m_pSitemaps;
char *pTemp = NULL;
while((pTemp = (char *)XP_ListNextObject(pTraverse))) {
XP_FREE(pTemp);
}
XP_ListDestroy(pInfo->m_pSitemaps);
pInfo->m_pSitemaps = NULL;
}
}
}
/* Initialzie a nav center with various data.
* It should be emptied or uninitialized before doing this.
* Docked state, and active browser need to be set before
* doing this in order for proper operation.
*/
static void xp_initnavcenter(HT_Pane htPane, MWContext *pContext, XP_Bool bInitFlag)
{
if(bInitFlag) {
if(NULL == pContext) {
pContext = XP_GetNavCenterContext(htPane);
}
if(pContext) {
NavCenterContextInfo *pInfo = xp_getnavcenterinfo(pContext);
if(pInfo && pInfo->m_pUrl) {
HT_AddRelatedLinksFor(htPane, pInfo->m_pUrl);
if(pInfo->m_pSitemaps) {
XP_List *pLoop = pInfo->m_pSitemaps;
char *pSitemap = NULL;
while((pSitemap = (char *)XP_ListNextObject(pLoop))) {
HT_AddSitemapFor(htPane, pInfo->m_pUrl, pSitemap, NULL);
}
}
}
#ifdef WANTFRAMES
if(pContext->grid_children) {
XP_List *pTraverse = pContext->grid_children;
MWContext *pChild = NULL;
while((pChild = (MWContext *)XP_ListNextObject(pTraverse))) {
xp_initnavcenter(htPane, pChild, bInitFlag);
}
}
#endif
}
}
}
/* Uninitialize a nav center with current info.
* Use this before changing activation or docking state, or pass in
* the context to uninit from.
*/
static void xp_uninitnavcenter(HT_Pane htPane, MWContext *pContext, XP_Bool bInitFlag)
{
if(bInitFlag) {
if(NULL == pContext) {
pContext = XP_GetNavCenterContext(htPane);
}
if(pContext) {
NavCenterContextInfo *pInfo = xp_getnavcenterinfo(pContext);
if(pInfo && pInfo->m_pUrl) {
HT_ExitPage(htPane, pInfo->m_pUrl);
}
#ifdef WANTFRAMES
if(pContext->grid_children) {
XP_List *pTraverse = pContext->grid_children;
MWContext *pChild = NULL;
while((pChild = (MWContext *)XP_ListNextObject(pTraverse))) {
xp_uninitnavcenter(htPane, pChild, bInitFlag);
}
}
#endif
}
}
}
/* Call these to get a list of NavCenters which a context
* will effect.
* WARNING: The list will not be updated should any of
* the data to which it refers changes. The operation
* should be atomic and synchronous for best results.
* The object in the list is just a HT_Pane cast to void *.
* Caller must XP_ListDestroy return value when finished.
* Pass in NULL as the context to get a list of floating
* nav centers (this basically excludes docked nav
* centers).
* Could return NULL....
*/
static XP_List *xp_getnavcenterlist(MWContext *pContext)
{
XP_List *pRetval = NULL;
MWContext *pCX = XP_GetNonGridContext(pContext);
if((pCX && MWContextBrowser == pCX->type) || NULL == pCX) {
/* Create the return value up front.
* This could be optimized to only be created when needed.
*/
pRetval = XP_ListNew();
if(pRetval) {
XP_List *pTraverse = xp_GlobalDockedNavCenters;
DockedNavCenter *pDNC = NULL;
/* Is there a docked NavCenter?
*/
if(pCX) {
while((pDNC = (DockedNavCenter *)XP_ListNextObject(pTraverse))) {
if(pCX == pDNC->m_pContext) {
XP_ListAddObject(pRetval, (void *)pDNC->m_htPane);
break;
}
}
}
/* Add any nondocked NavCenters, if the context is the active one or
* there is no context.
*/
if(NULL == pCX || xp_lastactivenavcentercontext() == pCX) {
HT_Pane htFloater = NULL;
pTraverse = xp_GlobalNavCenters;
while((htFloater = (HT_Pane)XP_ListNextObject(pTraverse))) {
if(FALSE == XP_IsNavCenterDocked(htFloater)) {
XP_ListAddObject(pRetval, (void *)htFloater);
}
}
}
/* Get rid of the list if empty.
*/
if(XP_ListIsEmpty(pRetval)) {
XP_ListDestroy(pRetval);
pRetval = NULL;
}
}
}
return(pRetval);
}
/* The active top level browser window has changed.
* We need to update any floating nav centers.
*/
static void xp_unactivatebrowser(MWContext *pOld)
{
if(pOld) {
XP_List *pFloatingNavCenters = xp_getnavcenterlist(NULL);
if(pFloatingNavCenters) {
/* Handle removal of any old data.
*/
XP_List *pTraverse = pFloatingNavCenters;
HT_Pane htFloater = NULL;
while((htFloater = (HT_Pane)XP_ListNextObject(pTraverse))) {
xp_uninitnavcenter(htFloater, pOld, TRUE);
xp_initnavcenter(htFloater, NULL, TRUE);
}
XP_ListDestroy(pFloatingNavCenters);
pFloatingNavCenters = NULL;
}
}
}
/* Private docking routing, can override auto-initialization for
* custom optimization.
*/
static void xp_docknavcenter(HT_Pane htPane, MWContext *pCX, XP_Bool bInitFlag)
{
pCX = XP_GetNonGridContext(pCX);
if(pCX && MWContextBrowser == pCX->type && htPane) {
DockedNavCenter *pNew = XP_NEW_ZAP(DockedNavCenter);
/* Need to uninit nav center from current info
* if a different context.
*/
XP_Bool bInit = FALSE;
if(pCX != XP_GetNavCenterContext(htPane)) {
xp_uninitnavcenter(htPane, NULL, bInitFlag);
bInit = TRUE;
}
if(pNew) {
pNew->m_pContext = pCX;
pNew->m_htPane = htPane;
if(NULL == xp_GlobalDockedNavCenters) {
xp_GlobalDockedNavCenters = XP_ListNew();
if(NULL == xp_GlobalDockedNavCenters) {
XP_FREE(pNew);
pNew = NULL;
}
}
if(xp_GlobalDockedNavCenters) {
XP_ListAddObject(xp_GlobalDockedNavCenters, (void *)pNew);
}
}
/* nav center needs re-init.
*/
if(bInit) {
xp_initnavcenter(htPane, NULL, bInitFlag);
}
}
}
/* Private undocking routing, can override auto-initialization for
* custom optimization.
*/
static void xp_undocknavcenter(HT_Pane htPane, XP_Bool bInitFlag)
{
MWContext *pCX = XP_GetNavCenterContext(htPane);
if(pCX && htPane && xp_GlobalDockedNavCenters) {
XP_List *pTraverse = xp_GlobalDockedNavCenters;
DockedNavCenter *pDNC = NULL;
XP_Bool bInit = FALSE;
/* If this will make the nav center of a different context,
* we will need to uninit.
*/
if(pCX != xp_lastactivenavcentercontext()) {
xp_uninitnavcenter(htPane, NULL, bInitFlag);
bInit = TRUE;
}
while((pDNC = (DockedNavCenter *)XP_ListNextObject(pTraverse))) {
if(pCX == pDNC->m_pContext && htPane == pDNC->m_htPane) {
/* pTraverse points beyond pDNC now, removing it will
* not destroy the sanctity of the loop.
*/
XP_ListRemoveObject(xp_GlobalDockedNavCenters, (void *)pDNC);
XP_FREE(pDNC);
break;
}
}
if(XP_ListIsEmpty(xp_GlobalDockedNavCenters)) {
XP_ListDestroy(xp_GlobalDockedNavCenters);
xp_GlobalDockedNavCenters = NULL;
}
if(bInit) {
/* Need to re-init the nav center.
*/
xp_initnavcenter(htPane, NULL, bInitFlag);
}
}
}
/* Remove any view to context association.
*/
void xp_removeviewassociation(HT_View htView, MWContext *pCX)
{
XP_List *pTraverse = xp_GlobalViewHTMLPanes;
ViewHTMLPane *pVHP = NULL;
XP_Bool bRemove = FALSE;
while((pVHP = (ViewHTMLPane *)XP_ListNextObject(pTraverse))) {
if(pCX && pCX == pVHP->m_pContext) {
bRemove = TRUE;
}
else if(htView && htView == pVHP->m_htView) {
bRemove = TRUE;
}
if(bRemove) {
XP_ListRemoveObject(xp_GlobalViewHTMLPanes, pVHP);
XP_FREE(pVHP);
pVHP = NULL;
if(XP_ListIsEmpty(xp_GlobalViewHTMLPanes)) {
XP_ListDestroy(xp_GlobalViewHTMLPanes);
xp_GlobalViewHTMLPanes = NULL;
}
break;
}
bRemove = FALSE;
}
}
/* Return HTML Pane context in the NavCenter.
*/
MWContext *xp_gethtmlpane(HT_View htView)
{
MWContext *pRetval = NULL;
if(htView) {
XP_List *pTraverse = xp_GlobalViewHTMLPanes;
ViewHTMLPane *pVHP = NULL;
while((pVHP = (ViewHTMLPane *)XP_ListNextObject(pTraverse))) {
if(htView == pVHP->m_htView) {
pRetval = pVHP->m_pContext;
break;
}
}
}
return(pRetval);
}
/* Call this when a context becomes active.
* A simple list of the contexts is kept, effectively a stack
* of active contexts.
*/
void XP_SetLastActiveContext(MWContext *pCX)
{
if(pCX) {
if(!xp_GlobalLastActiveContext) {
xp_GlobalLastActiveContext = XP_ListNew();
}
if(xp_GlobalLastActiveContext) {
MWContext *pAfterSet = NULL;
MWContext *pBeforeSet = NULL;
pBeforeSet = xp_lastactivenavcentercontext();
/* Remove the context from the stack.
* It will be added at the top.
*/
if(XP_ListPeekTopObject(xp_GlobalLastActiveContext) != pCX) {
XP_ListRemoveObject(xp_GlobalLastActiveContext, (void *)pCX);
XP_ListAddObject(xp_GlobalLastActiveContext, (void *)pCX);
}
pAfterSet = xp_lastactivenavcentercontext();
/* Did the top level browser change.
* If so, we need to notify floating nav centers.
*/
if(pBeforeSet != pAfterSet) {
xp_unactivatebrowser(pBeforeSet);
}
}
}
}
/* Call this to get the last active context.
* If specified, pCallMe will decide what is a valid return value
* and what is not.
*/
MWContext *XP_GetLastActiveContext(ContextMatch MatchCallback)
{
XP_List *pTraverse = xp_GlobalLastActiveContext;
MWContext *pCX = NULL;
while((pCX = (MWContext *)XP_ListNextObject(pTraverse))) {
if(MatchCallback) {
if(MatchCallback(pCX)) {
break;
}
}
else {
/* No callback, really want last active.
*/
break;
}
pCX = NULL;
}
return(pCX);
}
/* Removes context from last active stack.
* Just call this before context destruction.
*/
void XP_RemoveContextFromLastActiveStack(MWContext *pCX)
{
if(pCX && xp_GlobalLastActiveContext) {
MWContext *pBeforeRemove = NULL;
MWContext *pAfterRemove = NULL;
pBeforeRemove = xp_lastactivenavcentercontext();
XP_ListRemoveObject(xp_GlobalLastActiveContext, (void *)pCX);
pAfterRemove = xp_lastactivenavcentercontext();
if(XP_ListIsEmpty(xp_GlobalLastActiveContext)) {
XP_ListDestroy(xp_GlobalLastActiveContext);
xp_GlobalLastActiveContext = NULL;
}
/* Did the top level browser change.
* If so, we need to notify floating nav centers.
*/
if(pBeforeRemove != pAfterRemove) {
xp_unactivatebrowser(pBeforeRemove);
}
}
}
/* Inform us about a new NavCenter.
* Call this after creation of a NavCenter.
* The second parameter is only valid if created in a docked
* state. Pass in NULL otherwise.
*/
void XP_RegisterNavCenter(HT_Pane htPane, MWContext *pDocked)
{
if(htPane) {
if(NULL == xp_GlobalNavCenters) {
xp_GlobalNavCenters = XP_ListNew();
}
if(xp_GlobalNavCenters) {
XP_ListAddObject(xp_GlobalNavCenters, (void *)htPane);
}
/* Handle creation in a docked state.
*/
if(pDocked) {
xp_docknavcenter(htPane, pDocked, FALSE);
}
/* Initialize it with whatever info.
*/
xp_initnavcenter(htPane, NULL, TRUE);
}
}
/* Unregister a NavCenter.
* Call this when ready to delete the NavCenter.
*/
void XP_UnregisterNavCenter(HT_Pane htPane)
{
if(htPane) {
/* Remove whatever info it may be holding.
*/
xp_uninitnavcenter(htPane, NULL, TRUE);
/* Can obviously no longer be docked.
* Have it perform no init, uninit.
*/
if(XP_IsNavCenterDocked(htPane)) {
xp_undocknavcenter(htPane, FALSE);
}
/* List cleanup.
*/
if (xp_GlobalNavCenters) {
XP_ListRemoveObject(xp_GlobalNavCenters, (void *)htPane);
if(XP_ListIsEmpty(xp_GlobalNavCenters)) {
XP_ListDestroy(xp_GlobalNavCenters);
xp_GlobalNavCenters = NULL;
}
}
}
}
/* Call this when docking a NavCenter to a top level window.
* This includes creating a NavCenter in a docked state, or
* docking a nav center when it was already docked in
* a different window.
*/
void XP_DockNavCenter(HT_Pane htPane, MWContext *pCX)
{
XP_Bool bPrevDock = FALSE;
if(XP_IsNavCenterDocked(htPane)) {
bPrevDock = TRUE;
}
if(FALSE == bPrevDock) {
xp_docknavcenter(htPane, pCX, TRUE);
}
else {
/* Previously already docked.
* Avoid a redock to some context scenario.
* Optimize auto init/uninit.
*/
MWContext *pOldCX = XP_GetNavCenterContext(htPane);
if(pOldCX != pCX) {
xp_uninitnavcenter(htPane, NULL, TRUE);
xp_undocknavcenter(htPane, FALSE);
xp_docknavcenter(htPane, pCX, FALSE);
xp_initnavcenter(htPane, NULL, TRUE);
}
}
}
/* Call this when undocking a NavCenter from a top level window.
*/
void XP_UndockNavCenter(HT_Pane htPane)
{
xp_undocknavcenter(htPane, TRUE);
}
/* Returns wether or not a NavCenter is docked.
* This basically allows you to tell the difference between a docked
* or last active window return value from XP_GetNavCenterContext.
*/
XP_Bool XP_IsNavCenterDocked(HT_Pane htPane)
{
XP_Bool bRetval = FALSE;
XP_List *pTraverse = xp_GlobalDockedNavCenters;
DockedNavCenter *pDNC = NULL;
/* Look through docked list.
*/
while((pDNC = (DockedNavCenter *)XP_ListNextObject(pTraverse))) {
if(htPane == pDNC->m_htPane) {
bRetval = TRUE;
break;
}
}
return(bRetval);
}
/* Call this to determine the context which a NavCenter operation
* will target.
* If not docked, picks last active browser window.
* Could return NULL....
*/
MWContext *XP_GetNavCenterContext(HT_Pane htPane)
{
MWContext *pRetval = NULL;
XP_List *pTraverse = xp_GlobalDockedNavCenters;
DockedNavCenter *pDNC = NULL;
/* Look through docked list first.
*/
while((pDNC = (DockedNavCenter *)XP_ListNextObject(pTraverse))) {
if(htPane == pDNC->m_htPane) {
pRetval = pDNC->m_pContext;
break;
}
}
/* Use last active top level browser window.
*/
if(NULL == pRetval) {
pRetval = xp_lastactivenavcentercontext();
}
return(pRetval);
}
/* Call this when visiting a new page for a context.
*/
void XP_SetNavCenterUrl(MWContext *pContext, char *pUrl)
{
if(pUrl && pContext) {
MWContext *pBrowser = XP_GetNonGridContext(pContext);
#ifndef WANTFRAMES
if(pBrowser != pContext) {
return;
}
#endif
if(MWContextBrowser == pBrowser->type) {
NavCenterContextInfo *pInfo = xp_getnavcenterinfo(pContext);
if(NULL == pInfo) {
if(NULL == xp_GlobalNavCenterInfo) {
xp_GlobalNavCenterInfo = XP_ListNew();
}
if(xp_GlobalNavCenterInfo) {
pInfo = XP_NEW_ZAP(NavCenterContextInfo);
pInfo->m_pContext = pContext;
XP_ListAddObject(xp_GlobalNavCenterInfo, (void *)pInfo);
}
}
if(pInfo) {
XP_Bool bChangedUrls = FALSE;
if(pInfo->m_pUrl) {
if(XP_STRCMP(pUrl, pInfo->m_pUrl)) {
bChangedUrls = TRUE;
}
}
else {
bChangedUrls = TRUE;
}
if(bChangedUrls) {
/* Blow away the current nav center info and gut
* our info struct.
*/
XP_List *pCenters = xp_getnavcenterlist(pContext);
if(pCenters) {
XP_List *pTraverse = pCenters;
HT_Pane htPane = NULL;
while((htPane = (HT_Pane)XP_ListNextObject(pTraverse))) {
xp_uninitnavcenter(htPane, pContext, TRUE);
}
}
xp_gutnavcenterinfo(pInfo);
/* Copy over the url.
*/
pInfo->m_pUrl = XP_STRDUP(pUrl);
/* Update any watching nav centers.
*/
if(pCenters) {
XP_List *pTraverse = pCenters;
HT_Pane htPane = NULL;
while((htPane = (HT_Pane)XP_ListNextObject(pTraverse))) {
xp_initnavcenter(htPane, pContext, TRUE);
}
XP_ListDestroy(pCenters);
pCenters = NULL;
}
}
}
}
}
}
/* Add a sitemap for a context.
* The url has to be set for a context before this will work.
*/
void XP_AddNavCenterSitemap(MWContext *pContext, char *pSitemap, char* name)
{
if(pSitemap && pContext) {
MWContext *pBrowser = XP_GetNonGridContext(pContext);
#ifndef WANTFRAMES
if(pBrowser != pContext) {
return;
}
#endif
if(MWContextBrowser == pBrowser->type) {
NavCenterContextInfo *pInfo = xp_getnavcenterinfo(pContext);
if(pInfo && pInfo->m_pUrl) {
XP_Bool bDuplicate = FALSE;
if(pInfo->m_pSitemaps) {
XP_List *pTraverse = pInfo->m_pSitemaps;
char *pCheck = NULL;
while((pCheck = (char *)XP_ListNextObject(pTraverse))) {
if(0 == XP_STRCMP(pCheck, pSitemap)) {
bDuplicate = TRUE;
}
}
}
else {
/* Create the list, first time.
*/
pInfo->m_pSitemaps = XP_ListNew();
}
if(FALSE == bDuplicate && pInfo->m_pSitemaps) {
char *pDup = XP_STRDUP(pSitemap);
/* Add entry to list.
*/
if(pDup) {
XP_ListAddObject(pInfo->m_pSitemaps, (void *)pDup);
}
}
if(FALSE == bDuplicate) {
/* Display entry in various nav centers.
*/
XP_List *pCenters = xp_getnavcenterlist(pContext);
if(pCenters) {
XP_List *pTraverse = pCenters;
HT_Pane htPane = NULL;
while((htPane = (HT_Pane)XP_ListNextObject(pTraverse))) {
HT_AddSitemapFor(htPane, pInfo->m_pUrl, pSitemap, name);
}
XP_ListDestroy(pCenters);
pCenters = NULL;
}
}
}
}
}
}
/* Call this to association an HTML Pane MWContext to a NavCenter view.
*/
void XP_RegisterViewHTMLPane(HT_View htView, MWContext *pContext)
{
if(htView && pContext) {
ViewHTMLPane *pNew = XP_NEW_ZAP(ViewHTMLPane);
if(pNew) {
pNew->m_htView = htView;
pNew->m_pContext = pContext;
if(NULL == xp_GlobalViewHTMLPanes) {
xp_GlobalViewHTMLPanes = XP_ListNew();
if(NULL == xp_GlobalViewHTMLPanes) {
XP_FREE(pNew);
pNew = NULL;
}
}
if(xp_GlobalViewHTMLPanes) {
XP_ListAddObject(xp_GlobalViewHTMLPanes, (void *)pNew);
}
}
}
}
/* RDF HT Backend calls this to load content into the HTML view
* of a NavCenter HT_View.
*/
int XP_GetURLForView(HT_View htView, char *pAddress)
{
int iRetval = MK_NO_ACTION;
if(htView && pAddress) {
MWContext *pHTMLPane = xp_gethtmlpane(htView);
if(pHTMLPane) {
URL_Struct *pUrl = NET_CreateURLStruct(pAddress, NET_DONT_RELOAD);
if(pUrl) {
iRetval = FE_GetURL(pHTMLPane, pUrl);
}
}
}
return(iRetval);
}
/* Call this to remove nav center info for a context.
* Just call this before context destruction.
*/
void XP_RemoveNavCenterInfo(MWContext *pContext)
{
MWContext *pCX = XP_GetNonGridContext(pContext);
if(pCX && MWContextBrowser == pCX->type) {
XP_List *pNavCenters = xp_getnavcenterlist(pContext);
NavCenterContextInfo *pInfo = xp_getnavcenterinfo(pContext);
if(pNavCenters) {
XP_List *pTraverse = pNavCenters;
HT_Pane htPane = NULL;
while((htPane = (HT_Pane)XP_ListNextObject(pTraverse))) {
xp_uninitnavcenter(htPane, pContext, TRUE);
if(pCX == pContext && XP_IsNavCenterDocked(htPane)) {
xp_undocknavcenter(htPane, FALSE);
}
}
XP_ListDestroy(pNavCenters);
pNavCenters = NULL;
}
if(pInfo) {
XP_ListRemoveObject(xp_GlobalNavCenterInfo, (void *)pInfo);
if(XP_ListIsEmpty(xp_GlobalNavCenterInfo)) {
XP_ListDestroy(xp_GlobalNavCenterInfo);
xp_GlobalNavCenterInfo = NULL;
}
xp_gutnavcenterinfo(pInfo);
XP_FREE(pInfo);
pInfo = NULL;
}
}
/* Don't use the top level non-grid context for this one,
* as it may have grid children. though itself not
* going away.
*/
if(pContext) {
xp_removeviewassociation(NULL, pContext);
}
}
#endif /* MOZILLA_CLIENT */