437 lines
8.9 KiB
C
437 lines
8.9 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* $XConsortium: travP.c /main/3 1995/11/06 18:42:00 rswiston $
|
|
*
|
|
* @(#)travP.c 1.9 14 Feb 1994
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement between
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
* Sun's specific written approval. This document and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* TraversalP.c - functions used by traversal code. DO NOT USE OR MODIFY
|
|
* THESE FUNCTIONS UNLESS YOU ARE WORKING ON TRAVERSALS!!!
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "travP.h"
|
|
|
|
static ABObj travP_obj_salient_parent(ABObj obj, ABTraversal trav);
|
|
static ABObj travP_obj_salient_first_child(ABObj obj, ABTraversal trav);
|
|
static ABObj travP_obj_salient_next_sibling(ABObj obj, ABTraversal trav);
|
|
static ABObj travP_obj_salient_prev_sibling(ABObj obj, ABTraversal trav);
|
|
static ABObj find_first_non_subobj_child(ABObj obj, ABObj compRoot);
|
|
static ABObj find_ancestor_prev_sibling(ABObj obj, ABObj searchRoot);
|
|
static ABObj find_ancestor_next_sibling(ABObj obj, ABObj searchRoot);
|
|
|
|
|
|
ABObj
|
|
travP_obj_parent(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj parent= NULL;
|
|
|
|
switch (travP_get_qualifier(trav))
|
|
{
|
|
case AB_TRAV_SALIENT:
|
|
case AB_TRAV_SALIENT_CHILDREN:
|
|
case AB_TRAV_SALIENT_UI:
|
|
case AB_TRAV_SALIENT_UI_CHILDREN:
|
|
parent= travP_obj_salient_parent(obj, trav);
|
|
break;
|
|
|
|
default:
|
|
parent= obj->parent;
|
|
break;
|
|
}
|
|
|
|
return parent;
|
|
}
|
|
|
|
|
|
ABObj
|
|
travP_obj_first_child(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj child= NULL;
|
|
|
|
switch (travP_get_qualifier(trav))
|
|
{
|
|
case AB_TRAV_SALIENT:
|
|
case AB_TRAV_SALIENT_CHILDREN:
|
|
case AB_TRAV_SALIENT_UI:
|
|
case AB_TRAV_SALIENT_UI_CHILDREN:
|
|
child= travP_obj_salient_first_child(obj, trav);
|
|
break;
|
|
|
|
default:
|
|
child= obj->first_child;
|
|
break;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
|
|
|
|
ABObj
|
|
travP_obj_next_sibling(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj sib= NULL;
|
|
|
|
switch (travP_get_qualifier(trav))
|
|
{
|
|
case AB_TRAV_SALIENT:
|
|
case AB_TRAV_SALIENT_CHILDREN:
|
|
case AB_TRAV_SALIENT_UI:
|
|
case AB_TRAV_SALIENT_UI_CHILDREN:
|
|
sib= travP_obj_salient_next_sibling(obj, trav);
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* Don't go past the root node.
|
|
*/
|
|
if (obj != trav->rootObj)
|
|
{
|
|
sib= obj->next_sibling;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return sib;
|
|
}
|
|
|
|
|
|
ABObj
|
|
travP_obj_prev_sibling(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj sib= NULL;
|
|
|
|
switch (travP_get_qualifier(trav))
|
|
{
|
|
case AB_TRAV_SALIENT:
|
|
case AB_TRAV_SALIENT_CHILDREN:
|
|
case AB_TRAV_SALIENT_UI:
|
|
case AB_TRAV_SALIENT_UI_CHILDREN:
|
|
sib= travP_obj_salient_prev_sibling(obj, trav);
|
|
break;
|
|
|
|
default:
|
|
sib= obj->prev_sibling;
|
|
break;
|
|
}
|
|
|
|
return sib;
|
|
}
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** SALIENTS **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
static ABObj
|
|
travP_obj_salient_parent(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj parent= obj;
|
|
|
|
if (parent->part_of != NULL)
|
|
{
|
|
parent= parent->part_of;
|
|
}
|
|
parent= parent->parent;
|
|
if ((parent != NULL) && (parent->part_of != NULL))
|
|
{
|
|
parent= parent->part_of;
|
|
}
|
|
|
|
/*
|
|
* Be sure to stay inside traversal bounds
|
|
*/
|
|
if (parent != NULL)
|
|
{
|
|
ABObj ancestor= NULL;
|
|
for (ancestor= obj->parent;
|
|
(ancestor != NULL) && (ancestor != parent);
|
|
ancestor= ancestor->parent)
|
|
{
|
|
if (ancestor == trav->rootObj)
|
|
{
|
|
/* parent is above the traversal root. */
|
|
parent= NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return parent;
|
|
}
|
|
|
|
|
|
static ABObj
|
|
travP_obj_salient_first_child(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj child= NULL;
|
|
trav= trav;
|
|
|
|
if (obj_is_sub(obj) || obj_is_root(obj))
|
|
{
|
|
child= find_first_non_subobj_child(obj, obj_get_root(obj));
|
|
}
|
|
else
|
|
{
|
|
child= obj->first_child;
|
|
}
|
|
return child;
|
|
}
|
|
|
|
/*
|
|
* We need to find the leftmost child that is not part of this
|
|
* composite object.
|
|
*/
|
|
static ABObj
|
|
find_first_non_subobj_child(ABObj obj, ABObj compRoot)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj child= NULL;
|
|
|
|
/*
|
|
* Mondo recursion!! - we're going to recurse back into ourselves,
|
|
* as well as call trav_ functions. Can you say "no global variables?"
|
|
*
|
|
* Thought you could. :-)
|
|
*/
|
|
for (trav_open(&trav, obj, AB_TRAV_CHILDREN);
|
|
(child= trav_next(&trav)) != NULL; )
|
|
{
|
|
if (obj_get_root(child) != compRoot)
|
|
{
|
|
/*
|
|
* This is the object we want!!
|
|
*/
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* this child is still part of the composite. */
|
|
/* look at its children */
|
|
child= find_first_non_subobj_child(child, compRoot);
|
|
if (child != NULL)
|
|
{
|
|
/*
|
|
* found it!!
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return child;
|
|
}
|
|
|
|
static ABObj
|
|
travP_obj_salient_prev_sibling(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj curObj= NULL;
|
|
ABObj compRoot= NULL;
|
|
BOOL firstTime= TRUE;
|
|
|
|
curObj= obj;
|
|
compRoot= obj_get_root(curObj->parent);
|
|
while ( (curObj != NULL)
|
|
&& ((!obj_is_salient(curObj)) || (firstTime)) )
|
|
{
|
|
firstTime= FALSE;
|
|
if (obj_is_root(curObj))
|
|
{
|
|
if (curObj->prev_sibling != NULL)
|
|
{
|
|
curObj= curObj->prev_sibling;
|
|
}
|
|
else
|
|
{
|
|
curObj= find_ancestor_prev_sibling(curObj, compRoot);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (curObj->first_child != NULL)
|
|
{
|
|
curObj= curObj->first_child;
|
|
}
|
|
else
|
|
{
|
|
if (curObj->prev_sibling != NULL)
|
|
{
|
|
curObj= curObj->prev_sibling;
|
|
}
|
|
else
|
|
{
|
|
curObj= find_ancestor_prev_sibling(curObj, compRoot);
|
|
}
|
|
}
|
|
}
|
|
} /* while curObj */
|
|
|
|
return curObj;
|
|
} /* travP_obj_salient_prev_sibling */
|
|
|
|
|
|
static ABObj
|
|
travP_obj_salient_next_sibling(ABObj obj, ABTraversal trav)
|
|
{
|
|
ABObj curObj= NULL;
|
|
ABObj compRoot= NULL;
|
|
BOOL firstTime= TRUE;
|
|
ABObj searchTop = NULL;
|
|
|
|
curObj= obj;
|
|
compRoot= obj_get_root(curObj->parent);
|
|
|
|
/*
|
|
* Be sure we don't go above the traversal root.
|
|
*/
|
|
searchTop =
|
|
(obj_is_descendant_of(trav->rootObj, compRoot)?
|
|
trav->rootObj /* compRoot is above traversal root */
|
|
:
|
|
compRoot);
|
|
|
|
while ( (curObj != NULL)
|
|
&& ((!obj_is_salient(curObj)) || (firstTime)) )
|
|
{
|
|
firstTime= FALSE;
|
|
|
|
/* don't go past traversal root */
|
|
if (curObj == trav->rootObj)
|
|
{
|
|
curObj = NULL;
|
|
break;
|
|
}
|
|
|
|
if (obj_is_root(curObj))
|
|
{
|
|
if (curObj->next_sibling != NULL)
|
|
{
|
|
curObj= curObj->next_sibling;
|
|
}
|
|
else
|
|
{
|
|
curObj= find_ancestor_next_sibling(curObj, searchTop);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (curObj->first_child != NULL)
|
|
{
|
|
curObj= curObj->first_child;
|
|
}
|
|
else
|
|
{
|
|
if (curObj->next_sibling != NULL)
|
|
{
|
|
curObj= curObj->next_sibling;
|
|
}
|
|
else
|
|
{
|
|
curObj= find_ancestor_next_sibling(curObj, searchTop);
|
|
}
|
|
}
|
|
}
|
|
} /* while curObj */
|
|
|
|
return curObj;
|
|
} /* travP_obj_salient_next_sibling */
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** GENERAL UTITILITY FUNCTIONS **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
|
|
/*
|
|
* Finds the first ancestor with a sibling to its left (prev_sibling).
|
|
* Returns the sibling.
|
|
*/
|
|
static ABObj
|
|
find_ancestor_prev_sibling(ABObj obj, ABObj searchRoot)
|
|
{
|
|
ABObj newObj= NULL;
|
|
ABObj ancestor= NULL;
|
|
|
|
for (ancestor= obj->parent;
|
|
(ancestor != NULL) && (ancestor != searchRoot);
|
|
ancestor= ancestor->parent)
|
|
{
|
|
if (ancestor->prev_sibling != NULL)
|
|
{
|
|
newObj= ancestor->prev_sibling;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return newObj;
|
|
}
|
|
|
|
|
|
/*
|
|
* Finds the first ancestor with a sibling to its right (next_sibling).
|
|
* Returns the sibling.
|
|
*/
|
|
static ABObj
|
|
find_ancestor_next_sibling(ABObj obj, ABObj searchRoot)
|
|
{
|
|
ABObj newObj= NULL;
|
|
ABObj ancestor;
|
|
|
|
for (ancestor= obj->parent;
|
|
(ancestor != NULL) && (ancestor != searchRoot);
|
|
ancestor= ancestor->parent)
|
|
{
|
|
if (ancestor->next_sibling != NULL)
|
|
{
|
|
newObj= ancestor->next_sibling;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return newObj;
|
|
}
|
|
|