home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / xp / xp_cntxt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  17.9 KB  |  708 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. #define M12N
  21.  
  22. #ifdef MOZILLA_CLIENT
  23.  
  24. /*
  25.  * xp_cntxt.c
  26.  * Contains various XP context related functions
  27.  * Recomended when FE communicates with lib code in a complex way
  28.  */
  29.  
  30. #include "xp.h"
  31. #include "shist.h"
  32. #include "glhist.h"
  33. #include "ssl.h"
  34. #include "libimg.h"             /* Image Lib public API. */
  35. #include "libmocha.h"
  36. #include "libevent.h"
  37. #include "intl_csi.h"
  38. #include "xp_ncent.h"
  39.  
  40. static XP_List * xp_GlobalContextList = NULL;
  41. static int32 global_context_id = 0;
  42.  
  43.  
  44. void
  45. XP_InitializeContext(MWContext *context)
  46. {
  47.     if (context != NULL)
  48.     {
  49.         context->context_id = ++global_context_id;
  50.       context->INTL_tag = INTL_TAG;
  51.     }
  52. }
  53.  
  54. /* WARNING ! the mac FE does not call this ! */
  55. MWContext *
  56. XP_NewContext(void)
  57. {
  58.     MWContext *context;
  59.  
  60.     context = XP_NEW_ZAP(MWContext);
  61.     XP_ASSERT(NULL != context);
  62.     if (NULL == context)
  63.     {
  64.         return NULL;
  65.     }
  66.     context->INTL_CSIInfo = INTL_CSICreate();
  67.     if (NULL == context->INTL_CSIInfo)
  68.     {
  69.         XP_FREE(context);
  70.         return NULL;
  71.     }
  72.     XP_InitializeContext(context);
  73.     return context;
  74. }
  75. /* WARNING ! the mac FE does not call this ! */
  76. void
  77. XP_DeleteContext(MWContext *context)
  78. {
  79.   XP_ASSERT(context);
  80.   INTL_CSIDestroy(context->INTL_CSIInfo);
  81.   XP_FREE(context);
  82. }
  83.  
  84. /* give access to the global context list to other code too.
  85.  */
  86. XP_List *XP_GetGlobalContextList(void)
  87. {
  88.     return(xp_GlobalContextList);
  89. }
  90.  
  91. /* cx_AddChildContext
  92.  * Adds child context to the parents children list
  93.  * NULL-safe
  94.  */
  95. void cx_AddChildContext(MWContext *parent, MWContext * child)
  96. {
  97.     if ((parent == NULL) || (child == NULL))
  98.         return;
  99.     if (parent->grid_children == NULL)
  100.         parent->grid_children = XP_ListNew();
  101.     if (parent->grid_children == NULL)
  102.         return;
  103.     XP_ListAddObject(parent->grid_children, child);
  104. }
  105.  
  106. /* cx_RemoveChildContext
  107.  * Removes child context from its parent
  108.  * NULL-safe
  109.  */
  110. void cx_RemoveChildContext(MWContext * child)
  111. {
  112.     if ((child == NULL) || (child->grid_parent == NULL))
  113.         return;
  114.     XP_ListRemoveObject(child->grid_parent->grid_children, child);
  115. }
  116.  
  117. /*
  118.  * if the passed context is in the global context list
  119.  * TRUE is returned.  Otherwise false
  120.  */
  121. Bool XP_IsContextInList(MWContext *context)
  122. {
  123.     if (context == NULL)
  124.         return FALSE;
  125.  
  126.     if (xp_GlobalContextList == NULL)
  127.         return(FALSE);
  128.  
  129.     return((XP_ListFindObject(xp_GlobalContextList, context)
  130.             ? TRUE : FALSE));
  131. }
  132.  
  133. /*
  134.  * The passed context is added to the global context list
  135.  */
  136. void XP_AddContextToList(MWContext *context)
  137. {
  138.     if (context == NULL)
  139.         return;
  140.  
  141.     if (xp_GlobalContextList == NULL)
  142.         xp_GlobalContextList = XP_ListNew();
  143.  
  144.     if (xp_GlobalContextList == NULL)
  145.         return;
  146.  
  147.     XP_ListRemoveObject(xp_GlobalContextList, context);    /* No dups */
  148.     XP_ListAddObject(xp_GlobalContextList, context);
  149.     cx_AddChildContext(context->grid_parent, context);
  150. }
  151.  
  152. void XP_UpdateParentContext(MWContext * child)
  153. {
  154.     cx_AddChildContext(child->grid_parent, child);
  155. }
  156. /*
  157.  * Removes the context from the context list
  158.  * Notifies all its children
  159.  */
  160. void XP_RemoveContextFromList(MWContext *context)
  161. {
  162.     int howMany;
  163.     int i;
  164.  
  165.     if (context == NULL)
  166.         return;
  167.     cx_RemoveChildContext(context);    /* Its parent does not point to it any more */
  168.     /* Now take care of the children, this should not really happen */
  169.     if (context->grid_children)
  170.     {
  171.         howMany = XP_ListCount(context->grid_children);
  172.         for (i = 1; i <= howMany; i++)
  173.         {
  174.             MWContext * child;
  175.             child = (MWContext *)XP_ListGetObjectNum(context->grid_children, 1);
  176.             if (child)
  177.                 child->grid_parent = NULL;
  178.             XP_ListRemoveObject(context->grid_children, child);
  179.         }
  180.         XP_ListDestroy(context->grid_children);
  181.         context->grid_children = NULL;
  182.     }
  183.     XP_ListRemoveObject(xp_GlobalContextList, context);
  184.     
  185.     /*  Remove from last active stack.
  186.      *  Remove any nav center info about the context.
  187.      */
  188.     XP_RemoveContextFromLastActiveStack(context);
  189.     XP_RemoveNavCenterInfo(context);
  190. }
  191.  
  192. /* the following was adapted from xp_FindNamedContextInChildren, but
  193. simplified for simply matching pointers instead of names. */
  194. Bool
  195. XP_IsChildContext(MWContext* parent,  MWContext* child)
  196. {
  197.     int i;
  198.     if (parent == child) {
  199.         return TRUE;
  200.     }
  201.     if (parent->grid_children) {
  202.         int count = XP_ListCount(parent->grid_children);
  203.         for (i = 1; i <= count; i++) {
  204.             MWContext* tchild =
  205.                 (MWContext*)XP_ListGetObjectNum(parent->grid_children, i);
  206.             if (child == tchild) {
  207.                 return TRUE;
  208.             }
  209.             else{
  210.                 XP_Bool found = XP_IsChildContext(tchild, child);
  211.                 if (found) return found;
  212.             }
  213.         }
  214.     }
  215.     return FALSE;
  216. }
  217.  
  218.  
  219. MWContext*
  220. xp_FindNamedContextInChildren(MWContext* self, char* name, MWContext* excludeChild)
  221. {
  222.     int i;
  223. /*
  224.     XP_TRACE(("Searching for %s: context %0x, name=%s, title=%s\n",
  225.               (name ? name : ""), self,
  226.               (self->name ? self->name : ""), (self->title ? self->title : "")));
  227. */
  228.     if (self->name && XP_STRCMP(self->name, name) == 0) {
  229. /*
  230.         XP_TRACE(("Found %s context %0x name=%s\n", (name ? name : ""),
  231.                   self, self->name));
  232. */
  233.         return self;
  234.     }
  235.     if (self->grid_children) {
  236.         int count = XP_ListCount(self->grid_children);
  237.         for (i = 1; i <= count; i++) {
  238.             MWContext* child =
  239.                 (MWContext*)XP_ListGetObjectNum(self->grid_children, i);
  240.             if (child != excludeChild) {
  241.                 MWContext* found = xp_FindNamedContextInChildren(child, name, NULL);
  242.                 if (found) return found;
  243.             }
  244.         }
  245.     }
  246.     return NULL;
  247. }
  248.  
  249. /*
  250.  * Finds a context that should be loaded with the URL, given
  251.  * a name and current (refering) context.
  252.  *
  253.  * If the context returned is not NULL, name is already assigned to context
  254.  * structure. You should load the URL into this context.
  255.  *
  256.  * If you get back a NULL, you should create a new window
  257.  *
  258.  * Both context and current context can be null.
  259.  * Once the grids are in, there should be some kind of a logic that searches
  260.  * siblings first. 
  261.  */
  262.  
  263. MWContext * XP_FindNamedContextInList(MWContext * context, char *name)
  264. {
  265.     int i;
  266.     
  267.     if ((name == NULL) || (xp_GlobalContextList == NULL))
  268.         return context;
  269.  
  270.     /*
  271.      * Check for special magic window target names
  272.      */
  273.     if (name[0] == '_')
  274.     {
  275.         if (XP_STRNCMP(name, "_self", 5) == 0)
  276.         {
  277.             return context;
  278.         }
  279.         else if (XP_STRNCMP(name, "_parent", 7) == 0)
  280.         {
  281.             if ((context)&&(context->grid_parent))
  282.             {
  283.                 return context->grid_parent;
  284.             }
  285.             else
  286.             {
  287.                 return context;
  288.             }
  289.         }
  290.         else if (XP_STRNCMP(name, "_top", 4) == 0)
  291.         {
  292.             MWContext *top;
  293.  
  294.             top = context;
  295.             while ((top)&&(top->grid_parent))
  296.             {
  297.                 top = top->grid_parent;
  298.             }
  299.             return top;
  300.         }
  301.         else if (XP_STRNCMP(name, "_blank", 6) == 0)
  302.         {
  303.             return NULL;
  304.         }
  305.         /* else, search for the name, below */
  306.     }
  307.     
  308.     {
  309.         MWContext* cx = context;
  310.         MWContext* found;
  311.         if (context) {
  312.             /* If our current context has the right name, go there */
  313.             if (cx->name && 
  314.                 (XP_STRCMP(cx->name, name) == 0))
  315.                 return cx;
  316.             found = xp_FindNamedContextInChildren(cx, name, NULL);
  317.             if (found) return found;
  318.             while (cx->is_grid_cell) {
  319.                 MWContext* parent = cx->grid_parent;
  320.                 found = xp_FindNamedContextInChildren(parent, name, cx);
  321.                 if (found) return found;
  322.                 cx = parent;
  323.             }
  324.         }
  325.  
  326.         /* otherwise, just get any other context */
  327.         for (i=1; i<= XP_ListCount(xp_GlobalContextList); i++)
  328.         {
  329.             MWContext* compContext = (MWContext *)XP_ListGetObjectNum(xp_GlobalContextList, i);
  330.             /* Only search other top-level contexts that aren't the one we just came from: */
  331.             if (!compContext->is_grid_cell && compContext != cx) {
  332.                 found = xp_FindNamedContextInChildren(compContext, name, NULL);
  333.                 if (found) return found;
  334.             }
  335.         }
  336.     }
  337.     return NULL;
  338. }
  339.  
  340.  
  341. /*
  342.  * Finds a context that should be loaded with the URL, given
  343.  * a type and current (refering) context.  Return NULL if there is none.
  344.  */
  345. MWContext * XP_FindContextOfType (MWContext * context, MWContextType type)
  346. {
  347.     int i;
  348.  
  349.     /* The other types aren't "real" - they don't have windows.  (Actually,
  350.        neither do all of these, but it's damned useful to be able to find the
  351.        biff context...) */
  352.     XP_ASSERT (type == MWContextBrowser ||
  353.                type == MWContextMail ||
  354.                type == MWContextNews ||
  355.                type == MWContextMessageComposition ||
  356.                type == MWContextBookmarks ||
  357.                type == MWContextAddressBook ||
  358.                type == MWContextBiff ||
  359.                type == MWContextMailMsg ||
  360.                type == MWContextNewsMsg ||
  361.                type == MWContextEditor ||
  362.                type == MWContextPane); 
  363.     /* Added MWContextEditor, needed for bug 61630  */
  364.  
  365.     /* If our current context has the right type, go there */
  366.     if (context && context->type == type)
  367.         return context;
  368.     
  369.     /* otherwise, just get any other context */
  370.     for (i=1; i<= XP_ListCount(xp_GlobalContextList); i++)
  371.     {
  372.         MWContext * compContext = (MWContext *)XP_ListGetObjectNum(xp_GlobalContextList, i);
  373.         if (compContext->type == type)
  374.             return compContext;
  375.     }
  376.     return NULL;
  377. }
  378.  
  379. MWContext*
  380. XP_FindSomeContext()
  381. {
  382.     MWContext* cx = XP_FindContextOfType(NULL, MWContextBrowser);
  383.     if (!cx)
  384.         cx = XP_FindContextOfType(NULL, MWContextMail);
  385.     if (!cx)
  386.         cx = XP_FindContextOfType(NULL, MWContextNews);
  387.     if (!cx)
  388.         cx = XP_FindContextOfType(NULL, MWContextPane);
  389. #if 0    /* dp says don't do this */
  390.     if (!cx)
  391.         cx = fe_all_MWContexts->context;
  392. #endif
  393.     return cx;
  394. }
  395.  
  396. /* Returns the first non-grid parent of a given context (can be the context
  397.  * itself if it's not a grid cell). 
  398.  */
  399. MWContext *
  400. XP_GetNonGridContext(MWContext *context)
  401. {
  402.     MWContext* ctxt = context;
  403.     while (ctxt && ctxt->is_grid_cell)
  404.     ctxt = ctxt->grid_parent;
  405.     return ctxt;
  406. }
  407.  
  408. /* FE should call XP_FindNamedAnchor before getting a URL 
  409.  * that is going into an HTML window (output_format is FO_CACHE_AND_PRESENT
  410.  *
  411.  * if named anchor is found:
  412.  * XP_FindNamedAnchor 
  413.  *                    - updates context history, and global history properly
  414.  * if it is not found, we do not touch any arguments
  415.  *
  416.  * Usage:
  417.  * In your GetURL routine
  418.  * if (XP_FindNamedAnchor(context, url, &x, &y))
  419.  *  {
  420.  *         SetDocPosition(x,y);
  421.  *        if (url->history_num == 0)    // if you are not handling go back this way, do not do this
  422.  *            SHIST_AddDocument( &fContext, SHIST_CreateHistoryEntry( url, he->title) );
  423.  *        else
  424.  *            SHIST_SetCurrent(&fContext->hist, url->history_num);
  425.  *      SetURLTextField(url->address);
  426.  *      SetURLTextFieldTitle( ... url->is_netsite ... );
  427.  *        NET_FreeURLStruct(url);
  428.  *      RegenerateHistoryMenuAndDialogBoxContents()
  429.  *  }
  430.  * else
  431.  *        NET_GetURL
  432.  */
  433. Bool XP_FindNamedAnchor(MWContext * context, URL_Struct * url, 
  434.                             int32 *xpos, int32 *ypos)
  435. {
  436.     History_entry *he;
  437.     
  438.     if (!context)
  439.         return FALSE;
  440.  
  441.     he = SHIST_GetCurrent (&context->hist);
  442.     
  443.     if (he
  444.         && he->address
  445.         && url
  446.         && url->address
  447.         && XP_STRCHR(url->address, '#') /* it must have a named hash */
  448.         && url->method == URL_GET_METHOD
  449.         && url->force_reload == NET_DONT_RELOAD
  450.         && LO_LocateNamedAnchor(context, url, xpos, ypos))
  451.     {
  452.         GH_UpdateGlobalHistory( url );
  453.         /* don't do this - jwz. */
  454.         /* NET_FreeURLStruct( url ); */
  455.         return TRUE;
  456.     }
  457.     return FALSE;    
  458. }
  459.  
  460. /* XP_RefreshAnchors
  461.  * call it after loading a new URL to refresh all the anchors
  462.  */
  463. void XP_RefreshAnchors()
  464. {
  465.     int i;
  466.     for (i=1; i<= XP_ListCount(xp_GlobalContextList); i++)
  467.     {
  468.         MWContext * compContext = (MWContext *)XP_ListGetObjectNum(xp_GlobalContextList, i);
  469.         LO_RefreshAnchors(compContext);
  470.     }
  471. }
  472.  
  473. /* XP_InterruptContext
  474.  * interrupts this context, and all the grid cells it encloses
  475.  */
  476. void XP_InterruptContext(MWContext * context)
  477. {
  478.     int i = 1;
  479.     MWContext * child;
  480.  
  481.     if (context == NULL)
  482.         return;
  483.  
  484.     /* Interrupt the children recursively first.
  485.      * This avoids the scenario where the context is destroyed during
  486.      *  an interrupt and we end up dereferencing a freed context.
  487.      * This also avoids crazy hacks like caching the grid_children
  488.      *  context list until after the interrupt, and then doing the
  489.      *  below loop.  That can also crash if the grid_children context
  490.      *  list is freed off....
  491.      * Bug fix 58770
  492.      */
  493.     while(child = (MWContext *)XP_ListGetObjectNum(context->grid_children, i++))
  494.         XP_InterruptContext(child);
  495.  
  496.     NET_InterruptWindow(context);
  497.     if (context->img_cx)
  498.         IL_InterruptContext(context->img_cx);
  499.     ET_InterruptContext(context);
  500. }
  501.  
  502. Bool XP_IsContextBusy(MWContext * context)
  503. {
  504.     int i = 1;
  505.     MWContext * child;
  506.     
  507.     if (context == NULL)
  508.         return FALSE;
  509.  
  510.     if (NET_AreThereActiveConnectionsForWindow(context))
  511.         return TRUE;
  512.     
  513.     while ((child = (MWContext*)XP_ListGetObjectNum (context->grid_children,
  514.                                                      i++)))
  515.         if (XP_IsContextBusy(child))
  516.             return TRUE;
  517.     
  518.     return FALSE;
  519. }
  520.  
  521. Bool XP_IsContextStoppable(MWContext * context)
  522. {
  523.     int i = 1;
  524.     MWContext * child;
  525.     
  526.     if (context == NULL)
  527.         return FALSE;
  528.  
  529.     if (NET_AreThereActiveConnectionsForWindow(context))
  530.         return TRUE;
  531.     
  532.     if (LM_IsActive(context))
  533.         return TRUE;
  534.  
  535.     while ((child = (MWContext*)XP_ListGetObjectNum (context->grid_children,
  536.                                                      i++)))
  537.         if (XP_IsContextStoppable(child))
  538.             return TRUE;
  539.     
  540.     return FALSE;
  541. }
  542.  
  543. /*
  544.  *    Will return the lowest security status of the context
  545.  *        and it's children.
  546.  *    Lowest means lowest in security, not in numberic value.
  547.  *
  548.  *    Possible returns are:
  549.  *    SSL_SECURITY_STATUS_NOOPT
  550.  *    SSL_SECURITY_STATUS_OFF
  551.  *    SSL_SECURITY_STATUS_ON_HIGH
  552.  *    SSL_SECURITY_STATUS_ON_LOW
  553.  */
  554. int XP_GetSecurityStatus(MWContext *pContext)    {
  555.     History_entry *pHistEnt;
  556.     MWContext *pChild;
  557.     int iRetval, iIndex;
  558.  
  559.     /*
  560.      *    No context, no security.
  561.      */
  562.     if(pContext == NULL)    {
  563.         return(SSL_SECURITY_STATUS_NOOPT);
  564.     }
  565.  
  566.     /*
  567.      *    Obtain the context's current history entry (it holds
  568.      *        security info).
  569.      */
  570.     pHistEnt = SHIST_GetCurrent(&(pContext->hist));
  571.     if(pHistEnt == NULL)    {
  572.         /*
  573.          *    Nothing loaded, Confusion ensues here.
  574.          *    If we've a parent context, then our security
  575.          *        is a noopt (shouldn't be counted towards
  576.          *        the whole).
  577.          *    If we've no parent context, then our security
  578.          *        is off.
  579.          *    This allows grids to have empty panes, but to
  580.          *        still be secure if all grids which have
  581.          *        something loaded are secure.
  582.          */
  583.         if(pContext->grid_parent == NULL)    {
  584.             return(SSL_SECURITY_STATUS_OFF);
  585.         }
  586.         else    {
  587.             return(SSL_SECURITY_STATUS_NOOPT);
  588.         }
  589.     }
  590.  
  591.     /*
  592.      *    Our security status.
  593.      */
  594.     iRetval = pHistEnt->security_on;
  595.  
  596.     /*
  597.      *    If we're a grid parent, our security status
  598.      *        is a noopt (doesn't affect the whole).
  599.      *    This allows the parent grid document to be non
  600.      *        secure, and all the inner grids to be secure,
  601.      *        and therefore the document should still be
  602.      *        considered secure as a whole.
  603.      */
  604.     if(XP_ListIsEmpty(pContext->grid_children))    {
  605.         return(iRetval);
  606.     }
  607.     iRetval = SSL_SECURITY_STATUS_NOOPT;
  608.  
  609.     /*
  610.      *    Go through each child, getting it's security status.
  611.      *    We combine them all and return that value.
  612.      */
  613.     iIndex = 1;
  614.     while((pChild = (MWContext *)XP_ListGetObjectNum(
  615.         pContext->grid_children, iIndex++)))    {
  616.  
  617.         switch(XP_GetSecurityStatus(pChild))    {
  618.         case SSL_SECURITY_STATUS_NOOPT:
  619.             /*
  620.              *    No definable security status.  Don't
  621.              *        change our current value.
  622.              */
  623.             break;
  624.         case SSL_SECURITY_STATUS_OFF:
  625.             /*
  626.              *    No need in continuing if we're turning
  627.              *        off security altogether.
  628.              */
  629.             return(SSL_SECURITY_STATUS_OFF);
  630.             break;
  631.         case SSL_SECURITY_STATUS_ON_LOW:
  632.             /*
  633.              *    Change the return value to lower security.
  634.              */
  635.             iRetval = SSL_SECURITY_STATUS_ON_LOW;
  636.             break;
  637.         case SSL_SECURITY_STATUS_ON_HIGH:
  638.             /*
  639.              *    If we're currently noopt, then we should
  640.              *        change the security status to HIGH.
  641.              *    Otherwise, don't change the cumulative status
  642.              *        which could be lower than HIGH.
  643.              */
  644.             if(iRetval == SSL_SECURITY_STATUS_NOOPT)    {
  645.                 iRetval = SSL_SECURITY_STATUS_ON_HIGH;
  646.             }
  647.             break;
  648. #ifdef FORTEZZA
  649.         case SSL_SECURITY_STATUS_FORTEZZA:
  650.             /*
  651.              * If any fortezza, set to fortezza..
  652.              */
  653.             iRetval = SSL_SECURITY_STATUS_FORTEZZA;
  654.             break;
  655. #endif
  656.         default:
  657.             /*
  658.              *    Shouldn't be here, unless new security status
  659.              *        introduced.
  660.              */
  661.             XP_ASSERT(0);
  662.             break;
  663.         }
  664.     }
  665.  
  666.     /*
  667.      *    Context is somewhat secure, either high or low.
  668.      *    This could also be noopt, meaning no definable security,
  669.      *        so turn off your UI as if SSL_SECURITY_STATUS_OFF.
  670.      *    We can't just change the return value of
  671.      *        SSL_SECURITY_STATUS_NOOPT to OFF because this
  672.      *        breaks the recursive correctness of this routine.
  673.      *    Handle it accordingly.
  674.      */
  675.     return(iRetval);
  676. }
  677.  
  678. /*
  679.  *    Count the contexts of the said type.
  680.  *    The second parameter is a flag indicating wether or not the contexts
  681.  *        counted can have parent contexts (top level context switch).
  682.  */
  683. int XP_ContextCount(MWContextType cxType, XP_Bool bTopLevel)
  684. {
  685.     int iRetval = 0;
  686.     int iTraverse;
  687.     MWContext *pContext;
  688.  
  689.     /*
  690.      *    Loop through the contexts.
  691.      */
  692.     for(iTraverse = 1; iTraverse <= XP_ListCount(xp_GlobalContextList); iTraverse++)    {
  693.         pContext = (MWContext *)XP_ListGetObjectNum(xp_GlobalContextList, iTraverse);
  694.         if(cxType == MWContextAny || pContext->type == cxType)    {
  695.             /*
  696.              *    See if there's to be no parent.
  697.              */
  698.             if(bTopLevel == FALSE || pContext->is_grid_cell == FALSE)    {
  699.                 iRetval++;
  700.             }
  701.         }
  702.     }
  703.     
  704.     return(iRetval);
  705. }
  706.  
  707. #endif /* MOZILLA_CLIENT */
  708.