bool PushPopToMovOptimization::Optimize(AsmCode& code, int index)
{
    if (index + 1 == code.Size())
    {
        return false;
    }

    AsmCmd1* cmd1 = dynamic_cast<AsmCmd1*>(code[index]);
    AsmCmd1* cmd2 = dynamic_cast<AsmCmd1*>(code[index + 1]);

    if (cmd1 && cmd2
        && *cmd1 == cmdPUSH  && *cmd2 == cmdPOP
        && *cmd1->GetArgument() != cmd2->GetArgument()
        && !IsMemory(cmd1->GetArgument()) && !IsMemory(cmd2->GetArgument()))
    {
            AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd2->GetArgument(), cmd1->GetArgument());
            code.Delete(index, index + 1);
            code.Insert(optCmd, index);
            return true;
    }

    return false;
}
bool MovChainOptimization::Optimize(AsmCode& code, int index)
{
    if (index + 1 == code.Size())
    {
        return false;
    }

    AsmCmd2* cmd1 = dynamic_cast<AsmCmd2*>(code[index]);
    AsmCmd2* cmd2 = dynamic_cast<AsmCmd2*>(code[index + 1]);

    if (cmd1 && cmd2
        && *cmd1 == cmdMOV && *cmd2 == cmdMOV
        && *cmd1->GetFirst() != EBP && *cmd1->GetSecond() != ESP
        && *cmd2->GetSecond() == cmd1->GetFirst()
        && !IsMemory(cmd1->GetSecond()) && !IsMemory(cmd2->GetFirst()))
    {
        AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd2->GetFirst(), cmd1->GetSecond());
        code.Delete(index, index + 1);
        code.Insert(optCmd, index);
        return true;
    }

    return false;
}
NODESIZE CNodePtrArray::Draw( const PVIEWINFO View, int x, int y )
{
    int tx;
    NODESIZE DrawSize;
    NODESIZE ChildDrawSize;
    ULONG ClassSize;

    if (m_bHidden)
        return DrawHidden( View, x, y );

    DrawSize.x = 0;
    DrawSize.y = 0;

    AddSelection( View, 0, y, g_FontHeight );
    AddDelete( View, x, y );
    AddTypeDrop( View, x, y );

    x = AddOpenClose( View, x, y );
    x = AddIcon( View, x, y, ICON_ARRAY, -1, -1 );

    tx = x;
    tx = AddAddressOffset( View, tx, y );

    tx = AddText( View, tx, y, g_clrType, HS_NONE, _T( "ArrayOfPointers " ) );
    tx = AddText( View, tx, y, g_clrName, HS_NAME, _T( "%s" ), m_strName );
    tx = AddText( View, tx, y, g_clrIndex, HS_NONE, _T( "[" ) );
    tx = AddText( View, tx, y, g_clrIndex, HS_EDIT, _T( "%u" ), m_ulPtrCount );
    tx = AddText( View, tx, y, g_clrIndex, HS_NONE, _T( "]" ) );

    tx = AddIcon( View, tx, y, ICON_LEFT, HS_SELECT, HS_CLICK );
    tx = AddText( View, tx, y, g_clrIndex, HS_NONE, _T( "(" ) );
    tx = AddText( View, tx, y, g_clrIndex, 1, _T( "%i" ), m_iCurrentIndex );
    tx = AddText( View, tx, y, g_clrIndex, HS_NONE, _T( ")" ) );
    tx = AddIcon( View, tx, y, ICON_RIGHT, HS_DROP, HS_CLICK );

    tx = AddText( View, tx, y, g_clrValue, HS_NONE, _T( "<%s* Size=%u>" ), m_pNodePtr->GetClass( )->GetName( ), GetMemorySize( ) );
    tx = AddIcon( View, tx, y, ICON_CHANGE, HS_CLICK, HS_CHANGE_X );

    tx += g_FontWidth;
    tx = AddComment( View, tx, y );

    y += g_FontHeight;
    if (m_LevelsOpen[View->Level])
    {
        if (IsMemory( View->Address + m_Offset + (sizeof( ULONG_PTR ) * m_iCurrentIndex) ))
        {
            ClassSize = m_pNodePtr->GetClass( )->GetMemorySize( );
            m_pNodePtr->Memory( )->SetSize( ClassSize );

            VIEWINFO NewView;
            memcpy( &NewView, View, sizeof( NewView ) );
            NewView.Data = m_pNodePtr->Memory( )->Data( );
            NewView.Address = *(ULONG_PTR*)(View->Data + m_Offset + (sizeof( ULONG_PTR ) * m_iCurrentIndex));

            ReClassReadMemory( (LPVOID)NewView.Address, (LPVOID)NewView.Data, ClassSize );

            ChildDrawSize = m_pNodePtr->GetClass( )->Draw( &NewView, x, y );

            y = ChildDrawSize.y;
            if (ChildDrawSize.x > DrawSize.x)
                DrawSize.x = ChildDrawSize.x;
        }
    }

    DrawSize.y = y;
    return DrawSize;
}