
#include <wx/tooltip.h>
#include <algorithm>

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "confirm.h"

#include "program.h"
#include "general.h"
#include "protos.h"
#include "class_library.h"

#include "dialog_edit_component_in_schematic.h"


int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_SelectedRow;


wxSize DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = wxDefaultSize;


void InstallCmpeditFrame( WinEDA_SchematicFrame* parent, wxPoint& pos,
                          SCH_COMPONENT* aComponent )
{
    if( aComponent == NULL )    // Null component not accepted
        return;

    parent->DrawPanel->m_IgnoreMouseEvents = TRUE;
    if( aComponent->Type() != TYPE_SCH_COMPONENT )
    {
        DisplayError( parent,
                      wxT( "InstallCmpeditFrame() error: This item is not a component" ) );
    }
    else
    {
        DIALOG_EDIT_COMPONENT_IN_SCHEMATIC* dialog =
            new DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( parent );

        dialog->InitBuffers( aComponent );

        wxSize sizeNow = dialog->GetSize();

        // this relies on wxDefaultSize being -1,-1, be careful here.
        if( sizeNow.GetWidth()
            < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetWidth()
          || sizeNow.GetHeight()
            < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetHeight() )
        {
            dialog->SetSize( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize );
        }

        // make sure the chipnameTextCtrl is wide enough to hold any
        // unusually long chip names:
        EnsureTextCtrlWidth( dialog->chipnameTextCtrl );

        dialog->ShowModal();

        // Some of the field values are long and are not always fully visible
        // because the window comes up too narrow.
        // Remember user's manual window resizing efforts here so it comes up
        // wide enough next time.
        DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = dialog->GetSize();

        dialog->Destroy();
    }

    parent->DrawPanel->MouseToCursorSchema();
    parent->DrawPanel->m_IgnoreMouseEvents = false;
}


DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( wxWindow* parent ) :
    DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP( parent )
{
    m_Parent = (WinEDA_SchematicFrame*) parent;

    m_LibEntry = NULL;
    m_skipCopyFromPanel = false;

    wxListItem columnLabel;

    columnLabel.SetImage( -1 );

    columnLabel.SetText( _( "Name" ) );
    fieldListCtrl->InsertColumn( 0, columnLabel );

    columnLabel.SetText( _( "Value" ) );
    fieldListCtrl->InsertColumn( 1, columnLabel );

    wxString label = _( "Size" ) + ReturnUnitSymbol( g_UnitMetric );
    textSizeLabel->SetLabel( label );

    label  = _( "Pos " );
    label += _( "X" );
    label += ReturnUnitSymbol( g_UnitMetric );
    posXLabel->SetLabel( label );

    label  = _( "Pos " );
    label += _( "Y" );
    label += ReturnUnitSymbol( g_UnitMetric );
    posYLabel->SetLabel( label );

    copySelectedFieldToPanel();

    wxToolTip::Enable( true );

    if( GetSizer() )
    {
        GetSizer()->SetSizeHints( this );
    }

}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::reinitializeFieldsIdAndDefaultNames( )
{
    for( unsigned new_id = FIELD1; new_id < m_FieldsBuf.size(); new_id++ )
    {
        unsigned old_id = m_FieldsBuf[new_id].m_FieldId;
        if ( old_id != new_id )
        {
            if ( m_FieldsBuf[new_id].m_Name == ReturnDefaultFieldName( old_id ) )
                 m_FieldsBuf[new_id].m_Name = ReturnDefaultFieldName( new_id );
            m_FieldsBuf[new_id].m_FieldId = new_id;
        }
    }
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& event )
{
    D( printf( "OnListItemDeselected()\n" ); )

    if( !m_skipCopyFromPanel )
    {
        if( !copyPanelToSelectedField() )
            event.Skip();   // do not go to the next row
    }
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event )
{
    D( printf( "OnListItemSelected()\n" ); )

    // remember the selected row, statically
    s_SelectedRow = event.GetIndex();

    copySelectedFieldToPanel();
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnCancelButtonClick( wxCommandEvent& event )
{
    EndModal( 1 );
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions()
{
    wxString newname = chipnameTextCtrl->GetValue();

    newname.MakeUpper();
    newname.Replace( wxT( " " ), wxT( "_" ) );

    if( newname.IsEmpty() )
        DisplayError( this, _( "No Component Name!" ) );

    else if( newname.CmpNoCase( m_Cmp->m_ChipName ) )
    {
        if( CMP_LIBRARY::FindLibraryEntry( newname ) == NULL )
        {
            wxString message;
            message.Printf( _( "Component [%s] not found!" ), newname.GetData() );
            DisplayError( this, message );
        }
        else    // Change component from lib!
        {
            m_Cmp->m_ChipName = newname;
        }
    }

    // For components with multiple shapes (De Morgan representation) Set the
    // selected shape:
    if( convertCheckBox->IsEnabled() )
    {
        m_Cmp->m_Convert = convertCheckBox->GetValue() ? 2 : 1;
    }

    //Set the part selection in multiple part per pakcage
    if( m_Cmp->m_Multi )
    {
        int unit_selection = unitChoice->GetCurrentSelection() + 1;
        m_Cmp->SetUnitSelection( m_Parent->GetSheet(), unit_selection );
        m_Cmp->m_Multi = unit_selection;
    }

    switch( orientationRadioBox->GetSelection() )
    {
    case 0:
        m_Cmp->SetOrientation( CMP_ORIENT_0 );
        break;

    case 1:
        m_Cmp->SetOrientation( CMP_ORIENT_90 );
        break;

    case 2:
        m_Cmp->SetOrientation( CMP_ORIENT_180 );
        break;

    case 3:
        m_Cmp->SetOrientation( CMP_ORIENT_270 );
        break;
    }

    int mirror = mirrorRadioBox->GetSelection();

    switch( mirror )
    {
    case 0:
        break;

    case 1:
        m_Cmp->SetOrientation( CMP_MIRROR_X );
        break;

    case 2:
        m_Cmp->SetOrientation( CMP_MIRROR_Y );
        break;
    }
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event )
{
    if( !copyPanelToSelectedField() )
        return;

    copyPanelToOptions();

    /* save old cmp in undo list if not already in edit, or moving ... */
    if( m_Cmp->m_Flags == 0 )
        m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED );

    // change all field positions from relative to absolute
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
    {
        m_FieldsBuf[i].m_Pos += m_Cmp->m_Pos;
    }

    // delete any fields with no name
    for( unsigned i = FIELD1;  i<m_FieldsBuf.size(); )
    {
        if( m_FieldsBuf[i].m_Name.IsEmpty() )
        {
            m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
            continue;
        }

        ++i;
    }

    LIB_COMPONENT* entry =
        CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );

    if( entry &&  entry->isPower() )
        m_FieldsBuf[VALUE].m_Text = m_Cmp->m_ChipName;

    // copy all the fields back, and change the length of m_Fields.
    m_Cmp->SetFields( m_FieldsBuf );
    
    // Reference has a specific initialisation, depending on the current active sheet
    // because for a given component, in a complexe hierarchy, there are more than one
    // reference.
    m_Cmp->SetRef( m_Parent->GetSheet(), m_FieldsBuf[REFERENCE].m_Text );


    m_Parent->OnModify( );

    m_Parent->TestDanglingEnds( m_Parent->GetScreen()->EEDrawList, NULL );

    m_Parent->DrawPanel->Refresh( TRUE );

    EndModal( 0 );
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::addFieldButtonHandler( wxCommandEvent& event )
{
    // in case m_FieldsBuf[REFERENCE].m_Orient has changed on screen only, grab
    // screen contents.
    if( !copyPanelToSelectedField() )
        return;

    unsigned  fieldNdx = m_FieldsBuf.size();

    SCH_FIELD blank( wxPoint(), fieldNdx, m_Cmp );

    blank.m_Orient = m_FieldsBuf[REFERENCE].m_Orient;

    m_FieldsBuf.push_back( blank );
    m_FieldsBuf[fieldNdx].m_Name = ReturnDefaultFieldName(fieldNdx);

    m_skipCopyFromPanel = true;
    setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );

    setSelectedFieldNdx( fieldNdx );
    m_skipCopyFromPanel = false;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEvent& event )
{
    unsigned fieldNdx = getSelectedFieldNdx();

    if( fieldNdx >= m_FieldsBuf.size() )    // traps the -1 case too
        return;

    if( fieldNdx < FIELD1 )
    {
        wxBell();
        return;
    }

    m_skipCopyFromPanel = true;
    m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx );
    fieldListCtrl->DeleteItem( fieldNdx );

    if( fieldNdx >= m_FieldsBuf.size() )
        --fieldNdx;

    // Reinitialize fields IDs and default names:
    reinitializeFieldsIdAndDefaultNames();
    updateDisplay( );

    setSelectedFieldNdx( fieldNdx );
    m_skipCopyFromPanel = false;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC:: moveUpButtonHandler( wxCommandEvent& event )
{
    unsigned fieldNdx = getSelectedFieldNdx();

    if( fieldNdx >= m_FieldsBuf.size() )    // traps the -1 case too
        return;

    if( fieldNdx <= FIELD1 )
    {
        wxBell();
        return;
    }

    if( !copyPanelToSelectedField() )
        return;

    // swap the fieldNdx field with the one before it, in both the vector
    // and in the fieldListCtrl
    SCH_FIELD tmp = m_FieldsBuf[fieldNdx - 1];

    D( printf( "tmp.m_Text=\"%s\" tmp.m_Name=\"%s\"\n",
              CONV_TO_UTF8( tmp.m_Text ), CONV_TO_UTF8( tmp.m_Name ) ); )

    m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
    setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] );

    m_FieldsBuf[fieldNdx] = tmp;
    setRowItem( fieldNdx, tmp );

    // Reinitialize fields IDs and default names:
    reinitializeFieldsIdAndDefaultNames();
    updateDisplay( );

    m_skipCopyFromPanel = true;
    setSelectedFieldNdx( fieldNdx - 1 );
    m_skipCopyFromPanel = false;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setSelectedFieldNdx( int aFieldNdx )
{
    /* deselect old selection, but I think this is done by single selection
     * flag within fieldListCtrl.
     * fieldListCtrl->SetItemState( s_SelectedRow, 0,
     *                              wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
     */

    if( aFieldNdx >= (int) m_FieldsBuf.size() )
        aFieldNdx = m_FieldsBuf.size() - 1;

    if( aFieldNdx < 0 )
        aFieldNdx = 0;

    fieldListCtrl->SetItemState( aFieldNdx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
    fieldListCtrl->EnsureVisible( aFieldNdx );

    s_SelectedRow = aFieldNdx;
}


int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::getSelectedFieldNdx()
{
    return s_SelectedRow;
}



static bool SortFieldsById(const SCH_FIELD& item1, const SCH_FIELD& item2)
{
    return item1.m_FieldId < item2.m_FieldId;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent )
{
    m_Cmp = aComponent;

    m_LibEntry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );

#if 0 && defined(DEBUG)
    for( int i = 0;  i<aComponent->GetFieldCount();  ++i )
    {
        printf( "Orig[%d] (x=%d, y=%d)\n", i, aComponent->m_Fields[i].m_Pos.x,
                aComponent->m_Fields[i].m_Pos.y );
    }

#endif

    // copy all the fields to a work area
    m_FieldsBuf = aComponent->m_Fields;

    // Sort files by field id,if they are not entered by id
    sort(m_FieldsBuf.begin(), m_FieldsBuf.end(), SortFieldsById);

#if 0 && defined(DEBUG)
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
    {
        printf( "m_FieldsBuf[%d] (x=%d, y=%d)\n", i, m_FieldsBuf[i].m_Pos.x,
                m_FieldsBuf[i].m_Pos.y );
    }

#endif

    m_FieldsBuf[REFERENCE].m_Text = m_Cmp->GetRef( m_Parent->GetSheet() );

    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
    {
        // make the editable field position relative to the component
        m_FieldsBuf[i].m_Pos -= m_Cmp->m_Pos;

        setRowItem( i, m_FieldsBuf[i] );
    }

#if 0 && defined(DEBUG)
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
    {
        printf( "after[%d] (x=%d, y=%d)\n", i, m_FieldsBuf[i].m_Pos.x,
                m_FieldsBuf[i].m_Pos.y );
    }

#endif

    copyOptionsToPanel();

    // put focus on the list ctrl
    fieldListCtrl->SetFocus();

    // resume editing at the last row edited, last time dialog was up.
    setSelectedFieldNdx( s_SelectedRow );
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setRowItem( int              aFieldNdx,
                                                     const SCH_FIELD& aField )
{
    wxASSERT( aFieldNdx >= 0 );

    // insert blanks if aFieldNdx is referencing a "yet to be defined" row
    while( aFieldNdx >= fieldListCtrl->GetItemCount() )
    {
        long ndx = fieldListCtrl->InsertItem( fieldListCtrl->GetItemCount(), wxEmptyString );

        wxASSERT( ndx >= 0 );

        fieldListCtrl->SetItem( ndx, 1, wxEmptyString );
    }

    fieldListCtrl->SetItem( aFieldNdx, 0, aField.m_Name );
    fieldListCtrl->SetItem( aFieldNdx, 1, aField.m_Text );

    // recompute the column widths here, after setting texts
    fieldListCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE );
    fieldListCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE );
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel()
{
    unsigned fieldNdx = getSelectedFieldNdx();

    if( fieldNdx >= m_FieldsBuf.size() )    // traps the -1 case too
        return;

    SCH_FIELD& field = m_FieldsBuf[fieldNdx];

    showCheckBox->SetValue( !(field.m_Attributs & TEXT_NO_VISIBLE) );

    rotateCheckBox->SetValue( field.m_Orient == TEXT_ORIENT_VERT );

    int style = 0;
    if( field.m_Italic )
        style = 1;
    if( field.m_Bold )
        style |= 2;
    m_StyleRadioBox->SetSelection( style );

    fieldNameTextCtrl->SetValue( field.m_Name );

    // if fieldNdx == REFERENCE, VALUE, FOOTPRINT, or DATASHEET, then
    //disable editing
    fieldNameTextCtrl->Enable(  fieldNdx >= FIELD1 );
    fieldNameTextCtrl->SetEditable( fieldNdx >= FIELD1 );
    moveUpButton->Enable( fieldNdx >= FIELD1 );   /* disable move up button
                                                   * for non moveable fields */
    // if fieldNdx == REFERENCE, VALUE, then disable delete button
    deleteFieldButton->Enable( fieldNdx > VALUE );

    fieldValueTextCtrl->SetValue( field.m_Text );

    // For power symbols, the value is NOR editable, because value and pin
    // name must be same and can be edited only in library editor
    if( fieldNdx == VALUE && m_LibEntry && m_LibEntry->isPower() )
        fieldValueTextCtrl->Enable( false );
    else
        fieldValueTextCtrl->Enable( true );

    textSizeTextCtrl->SetValue(
        WinEDA_GraphicTextCtrl::FormatSize( EESCHEMA_INTERNAL_UNIT,
                                            g_UnitMetric, field.m_Size.x ) );

    wxPoint coord = field.m_Pos;
    wxPoint zero  = -m_Cmp->m_Pos;  // relative zero

    // If the field value is empty and the position is at relative zero, we
    // set the initial position as a small offset from the ref field, and
    // orient it the same as the ref field.  That is likely to put it at least
    // close to the desired position.
    if( coord == zero && field.m_Text.IsEmpty() )
    {
        rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].m_Orient == TEXT_ORIENT_VERT );

        coord.x = m_FieldsBuf[REFERENCE].m_Pos.x
            + ( fieldNdx - FIELD1 + 1 ) * 100;
        coord.y = m_FieldsBuf[REFERENCE].m_Pos.y
            + ( fieldNdx - FIELD1 + 1 ) * 100;

        // coord can compute negative if field is < FIELD1, e.g. FOOTPRINT.
        // That is ok, we basically don't want all the new empty fields on
        // top of each other.
    }

    wxString coordText = ReturnStringFromValue( g_UnitMetric, coord.x,
                                                EESCHEMA_INTERNAL_UNIT );
    posXTextCtrl->SetValue( coordText );

    coordText = ReturnStringFromValue( g_UnitMetric, coord.y,
                                       EESCHEMA_INTERNAL_UNIT );
    posYTextCtrl->SetValue( coordText );
}


bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField()
{
    unsigned fieldNdx = getSelectedFieldNdx();

    if( fieldNdx >= m_FieldsBuf.size() )        // traps the -1 case too
        return true;

    SCH_FIELD& field = m_FieldsBuf[fieldNdx];

    if( showCheckBox->GetValue() )
        field.m_Attributs &= ~TEXT_NO_VISIBLE;
    else
        field.m_Attributs |= TEXT_NO_VISIBLE;

    if( rotateCheckBox->GetValue() )
        field.m_Orient = TEXT_ORIENT_VERT;
    else
        field.m_Orient = TEXT_ORIENT_HORIZ;

    rotateCheckBox->SetValue( field.m_Orient == TEXT_ORIENT_VERT );


    field.m_Name = fieldNameTextCtrl->GetValue();
    /* Void fields texts for REFERENCE and VALUE (value is the name of the
     * compinent in lib ! ) are not allowed
     * change them only for a new non void value
     * When woid, usually netlists are broken
     */
    if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
        field.m_Text = fieldValueTextCtrl->GetValue();

    setRowItem( fieldNdx, field );  // update fieldListCtrl

    field.m_Size.x = WinEDA_GraphicTextCtrl::ParseSize(
        textSizeTextCtrl->GetValue(), EESCHEMA_INTERNAL_UNIT, g_UnitMetric );
    field.m_Size.y = field.m_Size.x;

    int style = m_StyleRadioBox->GetSelection();
    if( (style & 1 ) != 0 )
        field.m_Italic = true;
    else
        field.m_Italic = false;

    if( (style & 2 ) != 0 )
        field.m_Bold = true;
    else
        field.m_Bold = false;

    double value;

    posXTextCtrl->GetValue().ToDouble( &value );
    field.m_Pos.x = From_User_Unit( g_UnitMetric, value,
                                    EESCHEMA_INTERNAL_UNIT );

    posYTextCtrl->GetValue().ToDouble( &value );
    field.m_Pos.y = From_User_Unit( g_UnitMetric, value,
                                    EESCHEMA_INTERNAL_UNIT );

    return true;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
{
    int choiceCount = unitChoice->GetCount();

    // Remove non existing choices (choiceCount must be <= number for parts)
    int unitcount = m_LibEntry ? m_LibEntry->GetPartCount() : 1;

    if( unitcount < 1 )
        unitcount = 1;

    if( unitcount < choiceCount )
    {
        while( unitcount < choiceCount )
        {
            choiceCount--;
            unitChoice->Delete( choiceCount );
        }
    }

    // For components with multiple parts per package, set the unit selection
    choiceCount = unitChoice->GetCount();
    if( m_Cmp->m_Multi <= choiceCount )
        unitChoice->SetSelection( m_Cmp->m_Multi - 1 );

    // Disable unit selection if only one unit exists:
    if( choiceCount <= 1 )
        unitChoice->Enable( false );

    int orientation = m_Cmp->GetOrientation()
        & ~( CMP_MIRROR_X | CMP_MIRROR_Y );

    if( orientation == CMP_ORIENT_90 )
        orientationRadioBox->SetSelection( 1 );
    else if( orientation == CMP_ORIENT_180 )
        orientationRadioBox->SetSelection( 2 );
    else if( orientation == CMP_ORIENT_270 )
        orientationRadioBox->SetSelection( 3 );
    else
        orientationRadioBox->SetSelection( 0 );

    int mirror = m_Cmp->GetOrientation() & ( CMP_MIRROR_X | CMP_MIRROR_Y );

    if( mirror == CMP_MIRROR_X )
    {
        mirrorRadioBox->SetSelection( 1 );
        D( printf( "mirror=X,1\n" ); )
    }
    else if( mirror == CMP_MIRROR_Y )
    {
        mirrorRadioBox->SetSelection( 2 );
        D( printf( "mirror=Y,2\n" ); )
    }
    else
        mirrorRadioBox->SetSelection( 0 );

    // Activate/Desactivate the normal/convert option ? (activated only if
    // the component has more than one shape)
    if( m_Cmp->m_Convert > 1 )
    {
        convertCheckBox->SetValue( true );
    }

    if( m_LibEntry == NULL || !m_LibEntry->HasConversion() )
    {
        convertCheckBox->Enable( false );
    }

    // Show the "Parts Locked" option?
    if( !m_LibEntry || !m_LibEntry->m_UnitSelectionLocked )
    {
        D( printf( "partsAreLocked->false\n" ); )
        partsAreLockedLabel->Show( false );
    }

    // Positionnement de la reference en librairie
    chipnameTextCtrl->SetValue( m_Cmp->m_ChipName );
}

#include "kicad_device_context.h"

/* reinitialise components parametres to default values found in lib
 */
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event )
{
    LIB_COMPONENT* entry;

    if( m_Cmp == NULL )
        return;

    entry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );

    if( entry == NULL )
        return;

    INSTALL_DC( dc, m_Parent->DrawPanel );

    RedrawOneStruct( m_Parent->DrawPanel, &dc, m_Cmp, g_XorMode );

    /* Initialise fields values to default values found in library:  */
    LIB_FIELD& refField = entry->GetReferenceField();
    m_Cmp->GetField( REFERENCE )->m_Pos = refField.m_Pos + m_Cmp->m_Pos;
    m_Cmp->GetField( REFERENCE )->ImportValues( refField );

    LIB_FIELD& valField = entry->GetValueField();
    m_Cmp->GetField( VALUE )->m_Pos = valField.m_Pos + m_Cmp->m_Pos;
    m_Cmp->GetField( VALUE )->ImportValues( valField );

    m_Cmp->SetOrientation( CMP_NORMAL );

    m_Parent->OnModify( );

    RedrawOneStruct( m_Parent->DrawPanel, &dc, m_Cmp, GR_DEFAULT_DRAWMODE );
    EndModal( 1 );
}
