Files
mars-flaim/flaim/src/gdcopy.cpp
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

234 lines
6.6 KiB
C++

//-------------------------------------------------------------------------
// Desc: Copy GEDCOM tree
// Tabs: 3
//
// Copyright (c) 1990-2000,2003-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: gdcopy.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
//-------------------------------------------------------------------------
#include "flaimsys.h"
/**************************************************************************
Name : GedNodeCopy
Area : GEDCOM
Desc : Allocates a new node, value, and tag and copies from the old node
its attached child(ren) and sibling(s).
Notes:
****************************************************************************/
NODE * GedNodeCopy(
POOL * pPool,
NODE * node,
NODE * childList,
NODE * sibList)
{
NODE * newNd;
FLMUINT bias;
FLMBYTE * vp;
RCODE rc;
HFDB hDb;
FLMUINT uiContainer;
FLMUINT uiRecId;
// If the node has source information, we need to copy it
if( RC_OK( GedGetRecSource( node, &hDb, &uiContainer, &uiRecId)))
{
// The passed in node contains record source information,
// so create a GEDCOM record source node
if( RC_BAD( gedCreateSourceNode( pPool, GedTagNum( node), hDb,
uiContainer, uiRecId, &newNd)))
{
return NULL;
}
}
else
{
// Create a normal (non-source) GEDCOM node
if( (newNd = GedNodeMake( pPool, GedTagNum( node), &rc)) == NULL)
{
return( NULL);
}
}
newNd->prior = NULL;
newNd->next = childList;
GedNodeLevelSet( newNd, 0);
if( (vp = (FLMBYTE *)GedAllocSpace( pPool, newNd, GedValType( node),
GedValLen( node), node->ui32EncId, GedEncLen( node))) != NULL)
{
f_memcpy( vp, GedValPtr( node), GedValLen( node));
if (node->ui32EncFlags & FLD_HAVE_ENCRYPTED_DATA)
{
f_memcpy( GedEncPtr( newNd), GedEncPtr( node), GedEncLen( node));
}
newNd->ui32EncFlags = node->ui32EncFlags;
}
else
{
return( NULL);
}
if( childList)
{
childList->prior = newNd;
for( /* find end of sub-tree */
bias = GedNodeLevel( childList) - 1
/* 1st child level should be 1 */
; childList->next /* continue to last in list */
; GedNodeLevelSub( childList, bias), /* correct relative level */
childList = childList->next /* follow list */
);
GedNodeLevelSub( childList, bias); /* correct last node in list */
childList->next = sibList;
}
else
childList = newNd; /* no child(ren)--sib(s) link to newNd */
if( sibList) /* attach sibling(s) */
{
sibList->prior = childList;
childList->next = sibList;
for( /* find end of sibList */
bias = GedNodeLevel( sibList) /* sib must be level 0 too */
; sibList->next
; GedNodeLevelSub( sibList, bias), /* correct relative level */
sibList = sibList->next
);
GedNodeLevelSub( sibList, bias); /* correct last node in list */
}
return( newNd);
}
/*API~*********************************************************************
Desc: Copies the entire contents of a tree.
****************************************************************************/
NODE * GedCopy(
POOL * pPool,
FLMUINT cnt,
NODE * tree)
{
NODE * oldNd;
NODE * newNd;
NODE * newRoot;
FLMUINT baseLevel;
if( tree)
{
newRoot = newNd = GedNodeCopy( pPool, tree, NULL, NULL);
if( newRoot)
{
for(
baseLevel = GedNodeLevel( tree)
; (tree = tree->next) != NULL && /* follow linked list */
(
GedNodeLevel( tree) > baseLevel || /* process sub-tree */
(
GedNodeLevel( tree) == baseLevel && /* if sibling in forest AND */
--cnt /* count not expired, do next tree */
)
)
;
)
{
oldNd = newNd; /* save for linking below */
if( (newNd = GedNodeCopy( pPool, tree, NULL, NULL)) != NULL)
{
oldNd->next = newNd; /* link up */
newNd->prior = oldNd;
GedNodeLevelSet( newNd, GedNodeLevel( tree) - baseLevel);
}
else
return( NULL);
}
}
return( newRoot);
}
return( NULL);
}
/*API~***********************************************************************
Name : GedClip
Area : GEDCOM/LINK
Desc : Unlinks a node or sub-tree from its parent and/or siblings.
Notes: Starting at the node specified by self, treeCnt sibling trees will
be unlinked from their parent node (if any), as well as from their
previous and next sibling nodes (if any). If the clipped siblings
had a previous sibling and a next sibling, the previous sibling and
the next sibling are reconnected as siblings. If the clipped
siblings had a parent, a next sibling, but no previous sibling, the
next sibling be reconnected to the parent as the parent's first
child.
*END************************************************************************/
NODE *
// A pointer to the input node/sub-tree (self) is returned. This
// allows GedClip to be used a a parameter to other functions which
// require a NODE * parameter.
GedClip(
FLMUINT treeCnt,
// [IN] Number of sibling trees to unlink.
NODE * self)
// [IN] Pointer to the node or sub-tree which is to be unlinked.
{
NODE * next;
if( self)
{
FLMUINT oldLevel = GedNodeLevel( self);
GedNodeLevelSet( self, 0); /* clipped tree now at level 0 */
for( /* skip to next sub-tree */
next = self->next;
next && /* stop at end of sub-tree */
(
GedNodeLevel( next) > oldLevel || /* continue if child level */
(
GedNodeLevel( next) == oldLevel && /* if forest sibling, --treeCnt */
--treeCnt /* continue if treeCnt != 0 */
)
)
; GedNodeLevelSub( next, oldLevel), // Adjust levels relative to new root
next = next->next)
{
;
}
if( self->prior)
{
self->prior->next = next; /* re-link the gap in old tree/forest */
}
if( next)
{
next->prior->next = NULL; /* clipped tree's end must be made null*/
next->prior = self->prior; /* re-link the gap in old tree/forest */
}
self->prior = NULL; /* clipped tree's head must now be root */
}
return( self);
}