// File: rurban[P]dgnlib/dgnwrite.cpp
// Function: DGNCloneElement
DGNElemCore *DGNCloneElement( DGNHandle hDGNSrc, DGNHandle hDGNDst, 
                              DGNElemCore *psSrcElement )

{
    DGNElemCore *psClone = NULL;

    DGNLoadTCB( hDGNDst );

/* -------------------------------------------------------------------- */
/*      Per structure specific copying.  The core is fixed up later.    */
/* -------------------------------------------------------------------- */
    if( psSrcElement->stype == DGNST_CORE )
    {
        psClone = (DGNElemCore *) CPLMalloc(sizeof(DGNElemCore));
        memcpy( psClone, psSrcElement, sizeof(DGNElemCore) );
    }
    else if( psSrcElement->stype == DGNST_MULTIPOINT )
    {
        DGNElemMultiPoint *psMP, *psSrcMP;
        int               nSize;

        psSrcMP = (DGNElemMultiPoint *) psSrcElement;

        nSize = sizeof(DGNElemMultiPoint) 
            + sizeof(DGNPoint) * (psSrcMP->num_vertices-2);

        psMP = (DGNElemMultiPoint *) CPLMalloc( nSize );
        memcpy( psMP, psSrcElement, nSize );

        psClone = (DGNElemCore *) psMP;
    }
    else if( psSrcElement->stype == DGNST_ARC )
    {
        DGNElemArc *psArc;

        psArc = (DGNElemArc *) CPLMalloc(sizeof(DGNElemArc));
        memcpy( psArc, psSrcElement, sizeof(DGNElemArc) );

        psClone = (DGNElemCore *) psArc;
    }
    else if( psSrcElement->stype == DGNST_TEXT )
    {
        DGNElemText       *psText, *psSrcText;
        int               nSize;

        psSrcText = (DGNElemText *) psSrcElement;
        nSize = sizeof(DGNElemText) + strlen(psSrcText->string);

        psText = (DGNElemText *) CPLMalloc( nSize );
        memcpy( psText, psSrcElement, nSize );

        psClone = (DGNElemCore *) psText;
    }
    else if( psSrcElement->stype == DGNST_TEXT_NODE )
    {
        DGNElemTextNode *psNode;

        psNode = (DGNElemTextNode *) 
            CPLMalloc(sizeof(DGNElemTextNode));
        memcpy( psNode, psSrcElement, sizeof(DGNElemTextNode) );

        psClone = (DGNElemCore *) psNode;
    }
    else if( psSrcElement->stype == DGNST_COMPLEX_HEADER )
    {
        DGNElemComplexHeader *psCH;

        psCH = (DGNElemComplexHeader *) 
            CPLMalloc(sizeof(DGNElemComplexHeader));
        memcpy( psCH, psSrcElement, sizeof(DGNElemComplexHeader) );

        psClone = (DGNElemCore *) psCH;
    }
    else if( psSrcElement->stype == DGNST_COLORTABLE )
    {
        DGNElemColorTable *psCT;

        psCT = (DGNElemColorTable *) CPLMalloc(sizeof(DGNElemColorTable));
        memcpy( psCT, psSrcElement, sizeof(DGNElemColorTable) );

        psClone = (DGNElemCore *) psCT;
    }
    else if( psSrcElement->stype == DGNST_TCB )
    {
        DGNElemTCB *psTCB;

        psTCB = (DGNElemTCB *) CPLMalloc(sizeof(DGNElemTCB));
        memcpy( psTCB, psSrcElement, sizeof(DGNElemTCB) );

        psClone = (DGNElemCore *) psTCB;
    }
    else if( psSrcElement->stype == DGNST_CELL_HEADER )
    {
        DGNElemCellHeader *psCH;

        psCH = (DGNElemCellHeader *) CPLMalloc(sizeof(DGNElemCellHeader));
        memcpy( psCH, psSrcElement, sizeof(DGNElemCellHeader) );

        psClone = (DGNElemCore *) psCH;
    }
    else if( psSrcElement->stype == DGNST_CELL_LIBRARY )
    {
        DGNElemCellLibrary *psCL;
        
        psCL = (DGNElemCellLibrary *) CPLMalloc(sizeof(DGNElemCellLibrary));
        memcpy( psCL, psSrcElement, sizeof(DGNElemCellLibrary) );

        psClone = (DGNElemCore *) psCL;
    }
    else if( psSrcElement->stype == DGNST_TAG_VALUE )
    {
        DGNElemTagValue *psTV;
        
        psTV = (DGNElemTagValue *) CPLMalloc(sizeof(DGNElemTagValue));
        memcpy( psTV, psSrcElement, sizeof(DGNElemTagValue) );

        if( psTV->tagType == 1 )
            psTV->tagValue.string = CPLStrdup( psTV->tagValue.string );

        psClone = (DGNElemCore *) psTV;
    }
    else if( psSrcElement->stype == DGNST_TAG_SET )
    {
        DGNElemTagSet *psTS;
        int iTag;
        DGNTagDef *pasTagList;
        
        psTS = (DGNElemTagSet *) CPLMalloc(sizeof(DGNElemTagSet));
        memcpy( psTS, psSrcElement, sizeof(DGNElemTagSet) );

        psTS->tagSetName = CPLStrdup( psTS->tagSetName );
        
        pasTagList = (DGNTagDef *) 
            CPLMalloc( sizeof(DGNTagDef) * psTS->tagCount );
        memcpy( pasTagList, psTS->tagList, 
                sizeof(DGNTagDef) * psTS->tagCount );

        for( iTag = 0; iTag < psTS->tagCount; iTag++ )
        {
            pasTagList[iTag].name = CPLStrdup( pasTagList[iTag].name );
            pasTagList[iTag].prompt = CPLStrdup( pasTagList[iTag].prompt );
            if( pasTagList[iTag].type == 1 )
                pasTagList[iTag].defaultValue.string = 
                    CPLStrdup( pasTagList[iTag].defaultValue.string);
        }

        psTS->tagList = pasTagList;
        psClone = (DGNElemCore *) psTS;
    }
    else if( psSrcElement->stype == DGNST_CONE )
    {
        DGNElemCone *psCone;

        psCone = (DGNElemCone *) CPLMalloc(sizeof(DGNElemCone));
        memcpy( psCone, psSrcElement, sizeof(DGNElemCone) );

        psClone = (DGNElemCore *) psCone;
    }
    else if( psSrcElement->stype == DGNST_BSPLINE_SURFACE_HEADER )
    {
        DGNElemBSplineSurfaceHeader *psSurface;

        psSurface = (DGNElemBSplineSurfaceHeader *) 
          CPLMalloc(sizeof(DGNElemBSplineSurfaceHeader));
        memcpy( psSurface, psSrcElement, sizeof(DGNElemBSplineSurfaceHeader) );

        psClone = (DGNElemCore *) psSurface;
    }
    else if( psSrcElement->stype == DGNST_BSPLINE_CURVE_HEADER )
    {
        DGNElemBSplineCurveHeader *psCurve;

        psCurve = (DGNElemBSplineCurveHeader *) 
          CPLMalloc(sizeof(DGNElemBSplineCurveHeader));
        memcpy( psCurve, psSrcElement, sizeof(DGNElemBSplineCurveHeader) );

        psClone = (DGNElemCore *) psCurve;
    }
    else if( psSrcElement->stype == DGNST_BSPLINE_SURFACE_BOUNDARY )
    {
        DGNElemBSplineSurfaceBoundary *psBSB, *psSrcBSB;
        int               nSize;

        psSrcBSB = (DGNElemBSplineSurfaceBoundary *) psSrcElement;

        nSize = sizeof(DGNElemBSplineSurfaceBoundary) 
            + sizeof(DGNPoint) * (psSrcBSB->numverts-1);

        psBSB = (DGNElemBSplineSurfaceBoundary *) CPLMalloc( nSize );
        memcpy( psBSB, psSrcElement, nSize );

        psClone = (DGNElemCore *) psBSB;
    }
    else if( psSrcElement->stype == DGNST_KNOT_WEIGHT )
    {
        DGNElemKnotWeight *psArray;
        int               nSize, numelems;

        // FIXME: Is it OK to assume that the # of elements corresponds
        // directly to the element size? kintel 20051218.
        numelems = (psSrcElement->size - 36 - psSrcElement->attr_bytes)/4;

        nSize = sizeof(DGNElemKnotWeight) + sizeof(long) * (numelems-1);

        psArray = (DGNElemKnotWeight *) CPLMalloc( nSize );
        memcpy( psArray, psSrcElement, nSize );

        psClone = (DGNElemCore *) psArray;
    }
    else if( psSrcElement->stype == DGNST_SHARED_CELL_DEFN )
    {
        DGNElemSharedCellDefn *psCH;

        psCH = (DGNElemSharedCellDefn *)CPLMalloc(sizeof(DGNElemSharedCellDefn));
        memcpy( psCH, psSrcElement, sizeof(DGNElemSharedCellDefn) );

        psClone = (DGNElemCore *) psCH;
    }
    else
    {
        CPLAssert( FALSE );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Copy core raw data, and attributes.                             */
/* -------------------------------------------------------------------- */
    if( psClone->raw_bytes != 0 )
    {
        psClone->raw_data = (unsigned char *) CPLMalloc(psClone->raw_bytes);
        memcpy( psClone->raw_data, psSrcElement->raw_data, 
                psClone->raw_bytes );
    }

    if( psClone->attr_bytes != 0 )
    {
        psClone->attr_data = (unsigned char *) CPLMalloc(psClone->attr_bytes);
        memcpy( psClone->attr_data, psSrcElement->attr_data, 
                psClone->attr_bytes );
    }

/* -------------------------------------------------------------------- */
/*      Clear location and id information.                              */
/* -------------------------------------------------------------------- */
    psClone->offset = -1;
    psClone->element_id = -1;

    return psClone;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11190
movq -0x20(%rbp), %rax
cmpl $0x1, 0xc(%rax)
jne 0x127c7
movl $0x50, %edi
callq 0x3040
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x50, %edx
callq 0x2240
jmp 0x12e35
movq -0x20(%rbp), %rax
cmpl $0x2, 0xc(%rax)
jne 0x1281d
movq -0x20(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movl 0x50(%rax), %eax
subl $0x2, %eax
cltq
imulq $0x18, %rax, %rax
addq $0x88, %rax
movl %eax, -0x3c(%rbp)
movslq -0x3c(%rbp), %rdi
callq 0x3040
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
movq -0x20(%rbp), %rsi
movslq -0x3c(%rbp), %rdx
callq 0x2240
movq -0x30(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e33
movq -0x20(%rbp), %rax
cmpl $0x5, 0xc(%rax)
jne 0x12854
movl $0xa0, %edi
callq 0x3040
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0xa0, %edx
callq 0x2240
movq -0x48(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e31
movq -0x20(%rbp), %rax
cmpl $0x6, 0xc(%rax)
jne 0x128aa
movq -0x20(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdi
addq $0x88, %rdi
callq 0x2120
addq $0x90, %rax
movl %eax, -0x5c(%rbp)
movslq -0x5c(%rbp), %rdi
callq 0x3040
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x20(%rbp), %rsi
movslq -0x5c(%rbp), %rdx
callq 0x2240
movq -0x50(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e2f
movq -0x20(%rbp), %rax
cmpl $0xd, 0xc(%rax)
jne 0x128e1
movl $0xa0, %edi
callq 0x3040
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0xa0, %edx
callq 0x2240
movq -0x68(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e2d
movq -0x20(%rbp), %rax
cmpl $0x7, 0xc(%rax)
jne 0x12918
movl $0x60, %edi
callq 0x3040
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x60, %edx
callq 0x2240
movq -0x70(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e2b
movq -0x20(%rbp), %rax
cmpl $0x3, 0xc(%rax)
jne 0x1294f
movl $0x358, %edi            # imm = 0x358
callq 0x3040
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x358, %edx            # imm = 0x358
callq 0x2240
movq -0x78(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e29
movq -0x20(%rbp), %rax
cmpl $0x4, 0xc(%rax)
jne 0x12986
movl $0x550, %edi            # imm = 0x550
callq 0x3040
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x550, %edx            # imm = 0x550
callq 0x2240
movq -0x80(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e27
movq -0x20(%rbp), %rax
cmpl $0x8, 0xc(%rax)
jne 0x129c6
movl $0x110, %edi            # imm = 0x110
callq 0x3040
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x110, %edx            # imm = 0x110
callq 0x2240
movq -0x88(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e25
movq -0x20(%rbp), %rax
cmpl $0xb, 0xc(%rax)
jne 0x12a06
movl $0x88, %edi
callq 0x3040
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x88, %edx
callq 0x2240
movq -0x90(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e23
movq -0x20(%rbp), %rax
cmpl $0x9, 0xc(%rax)
jne 0x12a71
movl $0x68, %edi
callq 0x3040
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x68, %edx
callq 0x2240
movq -0x98(%rbp), %rax
cmpl $0x1, 0x50(%rax)
jne 0x12a61
movq -0x98(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x31e0
movq %rax, %rcx
movq -0x98(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0x98(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e21
movq -0x20(%rbp), %rax
cmpl $0xa, 0xc(%rax)
jne 0x12c23
movl $0x70, %edi
callq 0x3040
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x70, %edx
callq 0x2240
movq -0xa0(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x31e0
movq %rax, %rcx
movq -0xa0(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0xa0(%rbp), %rax
movslq 0x50(%rax), %rax
imulq $0x28, %rax, %rdi
callq 0x3040
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rdi
movq -0xa0(%rbp), %rax
movq 0x68(%rax), %rsi
movq -0xa0(%rbp), %rax
movslq 0x50(%rax), %rax
imulq $0x28, %rax, %rdx
callq 0x2240
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
movq -0xa0(%rbp), %rcx
cmpl 0x50(%rcx), %eax
jge 0x12c01
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq (%rax), %rdi
callq 0x31e0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x10(%rax), %rdi
callq 0x31e0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
cmpl $0x1, 0x18(%rax)
jne 0x12beb
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rdi
callq 0x31e0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
movslq -0xa4(%rbp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x20(%rax)
jmp 0x12bed
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x12b0e
movq -0xb0(%rbp), %rcx
movq -0xa0(%rbp), %rax
movq %rcx, 0x68(%rax)
movq -0xa0(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e1f
movq -0x20(%rbp), %rax
cmpl $0xc, 0xc(%rax)
jne 0x12c63
movl $0xa8, %edi
callq 0x3040
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0xa8, %edx
callq 0x2240
movq -0xb8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e1d
movq -0x20(%rbp), %rax
cmpl $0xe, 0xc(%rax)
jne 0x12ca3
movl $0x70, %edi
callq 0x3040
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x70, %edx
callq 0x2240
movq -0xc0(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e1b
movq -0x20(%rbp), %rax
cmpl $0xf, 0xc(%rax)
jne 0x12ce3
movl $0x60, %edi
callq 0x3040
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x60, %edx
callq 0x2240
movq -0xc8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e19
movq -0x20(%rbp), %rax
cmpl $0x10, 0xc(%rax)
jne 0x12d50
movq -0x20(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movswl 0x52(%rax), %eax
subl $0x1, %eax
cltq
imulq $0x18, %rax, %rax
addq $0x70, %rax
movl %eax, -0xdc(%rbp)
movslq -0xdc(%rbp), %rdi
callq 0x3040
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
movq -0x20(%rbp), %rsi
movslq -0xdc(%rbp), %rdx
callq 0x2240
movq -0xd0(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e17
movq -0x20(%rbp), %rax
cmpl $0x11, 0xc(%rax)
jne 0x12dc9
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
subl $0x24, %eax
movq -0x20(%rbp), %rcx
subl 0x34(%rcx), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %eax, -0xf0(%rbp)
movl -0xf0(%rbp), %eax
subl $0x1, %eax
cltq
shlq $0x3, %rax
addq $0x58, %rax
movl %eax, -0xec(%rbp)
movslq -0xec(%rbp), %rdi
callq 0x3040
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movslq -0xec(%rbp), %rdx
callq 0x2240
movq -0xe8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e15
movq -0x20(%rbp), %rax
cmpl $0x12, 0xc(%rax)
jne 0x12e06
movl $0x58, %edi
callq 0x3040
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x58, %edx
callq 0x2240
movq -0xf8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x12e13
movq $0x0, -0x8(%rbp)
jmp 0x12ed0
jmp 0x12e15
jmp 0x12e17
jmp 0x12e19
jmp 0x12e1b
jmp 0x12e1d
jmp 0x12e1f
jmp 0x12e21
jmp 0x12e23
jmp 0x12e25
jmp 0x12e27
jmp 0x12e29
jmp 0x12e2b
jmp 0x12e2d
jmp 0x12e2f
jmp 0x12e31
jmp 0x12e33
jmp 0x12e35
movq -0x28(%rbp), %rax
cmpl $0x0, 0x40(%rax)
je 0x12e74
movq -0x28(%rbp), %rax
movslq 0x40(%rax), %rdi
callq 0x3040
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x28(%rbp), %rax
movq 0x48(%rax), %rdi
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rsi
movq -0x28(%rbp), %rax
movslq 0x40(%rax), %rdx
callq 0x2240
movq -0x28(%rbp), %rax
cmpl $0x0, 0x34(%rax)
je 0x12eb3
movq -0x28(%rbp), %rax
movslq 0x34(%rax), %rdi
callq 0x3040
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rdi
movq -0x20(%rbp), %rax
movq 0x38(%rax), %rsi
movq -0x28(%rbp), %rax
movslq 0x34(%rax), %rdx
callq 0x2240
movq -0x28(%rbp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movq -0x28(%rbp), %rax
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nopl (%rax)