void DIALOG_EDIT_COMPONENT_IN_LIBRARY::BrowseAndSelectDocFile( wxCommandEvent& event )
{
    PROJECT&        prj = Prj();
    SEARCH_STACK*   search = prj.SchSearchS();

    wxString    mask = wxT( "*" );
    wxString    docpath = prj.GetRString( PROJECT::DOC_PATH );

    if( !docpath )
        docpath = search->LastVisitedPath( wxT( "doc" ) );

    wxString    fullFileName = EDA_FILE_SELECTOR( _( "Doc Files" ),
                                                  docpath,
                                                  wxEmptyString,
                                                  wxEmptyString,
                                                  mask,
                                                  this,
                                                  wxFD_OPEN,
                                                  true );
    if( fullFileName.IsEmpty() )
        return;

    /* If the path is already in the library search paths
     * list, just add the library name to the list.  Otherwise, add
     * the library name with the full or relative path.
     * the relative path, when possible is preferable,
     * because it preserve use of default libraries paths, when the path is a sub path of
     * these default paths
     */
    wxFileName fn = fullFileName;

    prj.SetRString( PROJECT::DOC_PATH, fn.GetPath() );

    wxString filename = search->FilenameWithRelativePathInSearchList(
            fullFileName, wxPathOnly( Prj().GetProjectFullName() ) );

    // Filenames are always stored in unix like mode, ie separator "\" is stored as "/"
    // to ensure files are identical under unices and windows
#ifdef __WINDOWS__
    filename.Replace( wxT( "\\" ), wxT( "/" ) );
#endif
    m_DocfileCtrl->SetValue( filename );
}
bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile )
{
    wxFileName fn;
    wxString   msg;

    m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );

    PART_LIB* lib = GetCurLib();

    // Just in case the library hasn't been cached yet.
    lib->GetCount();

    if( !lib )
    {
        DisplayError( this, _( "No library specified." ) );
        return false;
    }

    wxString oldFileName = lib->GetFullFileName();

    if( GetScreen()->IsModify() )
    {
        if( IsOK( this, _( "Include last component changes?" ) ) )
        {
            lib->EnableBuffering();

            try
            {
                SaveOnePart( lib, false );
            }
            catch( ... )
            {
                lib->EnableBuffering( false );
                msg.Printf( _( "Unexpected error occured saving part to '%s' symbol library." ),
                            lib->GetName() );
                DisplayError( this, msg );
                return false;
            }

            lib->EnableBuffering( false );
        }
    }

    if( newFile )
    {
        PROJECT&        prj = Prj();
        SEARCH_STACK*   search = prj.SchSearchS();

        // Get a new name for the library
        wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );

        if( !default_path )
            default_path = search->LastVisitedPath();

        wxFileDialog dlg( this, _( "Part Library Name:" ), default_path,
                          wxEmptyString, SchematicLibraryFileWildcard,
                          wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

        if( dlg.ShowModal() == wxID_CANCEL )
            return false;

        fn = dlg.GetPath();

        // The GTK file chooser doesn't return the file extension added to
        // file name so add it here.
        if( fn.GetExt().IsEmpty() )
            fn.SetExt( SchematicLibraryFileExtension );

        prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
    }
    else
    {
        fn = wxFileName( lib->GetFullFileName() );

        msg.Printf( _( "Modify library file '%s' ?" ), GetChars( fn.GetFullPath() ) );

        if( !IsOK( this, msg ) )
            return false;
    }

    // Verify the user has write privileges before attempting to save the library file.
    if( !IsWritable( fn ) )
        return false;

    ClearMsgPanel();

    wxFileName libFileName = fn;
    wxFileName backupFileName = fn;

    // Rename the old .lib file to .bak.
    if( libFileName.FileExists() )
    {
        backupFileName.SetExt( "bak" );

        if( backupFileName.FileExists() )
            wxRemoveFile( backupFileName.GetFullPath() );

        if( !wxRenameFile( libFileName.GetFullPath(), backupFileName.GetFullPath() ) )
        {
            libFileName.MakeAbsolute();
            msg = _( "Failed to rename old component library file " ) +
                  backupFileName.GetFullPath();
            DisplayError( this, msg );
        }
    }

    wxFileName docFileName = libFileName;

    docFileName.SetExt( DOC_EXT );

    // Rename .doc file to .bck.
    if( docFileName.FileExists() )
    {
        backupFileName.SetExt( "bck" );

        if( backupFileName.FileExists() )
            wxRemoveFile( backupFileName.GetFullPath() );

        if( !wxRenameFile( docFileName.GetFullPath(), backupFileName.GetFullPath() ) )
        {
            msg = _( "Failed to save old library document file " ) + backupFileName.GetFullPath();
            DisplayError( this, msg );
        }
    }

    try
    {
        lib->SetFileName( fn.GetFullPath() );
        lib->Save();
    }
    catch( ... /* IO_ERROR ioe */ )
    {
        lib->SetFileName( oldFileName );
        msg.Printf( _( "Failed to create symbol library file '%s'" ),
                    GetChars( docFileName.GetFullPath() ) );
        DisplayError( this, msg );
        return false;
    }

    lib->SetFileName( oldFileName );
    msg.Printf( _( "Library file '%s' saved" ), GetChars( fn.GetFullPath() ) );
    fn.SetExt( DOC_EXT );
    wxString msg1;
    msg1.Printf( _( "Documentation file '%s' saved" ), GetChars( fn.GetFullPath() ) );
    AppendMsgPanel( msg, msg1, BLUE );
    UpdateAliasSelectList();
    UpdatePartSelectList();
    refreshSchematic();

    return true;
}
void LIB_EDIT_FRAME::LoadOneSymbol()
{
    LIB_PART*       part = GetCurPart();

    // Exit if no library entry is selected or a command is in progress.
    if( !part || ( m_drawItem && m_drawItem->GetFlags() ) )
        return;

    PROJECT&        prj = Prj();
    SEARCH_STACK*   search = prj.SchSearchS();

    m_canvas->SetIgnoreMouseEvents( true );

    wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
    if( !default_path )
        default_path = search->LastVisitedPath();

    wxFileDialog dlg( this, _( "Import Symbol Drawings" ), default_path,
                      wxEmptyString, SchematicSymbolFileWildcard,
                      wxFD_OPEN | wxFD_FILE_MUST_EXIST );

    if( dlg.ShowModal() == wxID_CANCEL )
        return;

    SetCrossHairPosition( wxPoint( 0, 0 ) );
    m_canvas->MoveCursorToCrossHair();
    m_canvas->SetIgnoreMouseEvents( false );

    wxString filename = dlg.GetPath();

    prj.SetRString( PROJECT::SCH_LIB_PATH, filename );

    std::unique_ptr<PART_LIB> lib( new PART_LIB( LIBRARY_TYPE_SYMBOL, filename ) );

    wxString err;

    if( !lib->Load( err ) )
    {
        wxString msg = wxString::Format( _(
            "Error '%s' occurred loading part file '%s'." ),
            GetChars( err ),
            GetChars( filename )
            );
        DisplayError( this, msg );
        return;
    }

    if( lib->IsEmpty() )
    {
        wxString msg = wxString::Format( _(
            "No parts found in part file '%s'." ),
            GetChars( filename )
            );
        DisplayError( this, msg );
        return;
    }

    if( lib->GetCount() > 1 )
    {
        wxString msg = wxString::Format( _(
            "More than one part in part file '%s'." ),
            GetChars( filename )
            );
        wxMessageBox( msg, _( "Warning" ), wxOK | wxICON_EXCLAMATION, this );
    }

    LIB_PART*   first = lib->GetFirstEntry()->GetPart();
    LIB_ITEMS&  drawList = first->GetDrawItemList();

    for( LIB_ITEM& item : drawList )
    {
        if( item.Type() == LIB_FIELD_T )
            continue;

        if( item.GetUnit() )
            item.SetUnit( m_unit );

        if( item.GetConvert() )
            item.SetConvert( m_convert );

        item.SetFlags( IS_NEW | SELECTED );

        LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();

        newItem->SetParent( part );
        part->AddDrawItem( newItem );
    }

    part->RemoveDuplicateDrawItems();
    part->ClearSelectedItems();

    OnModify();
    m_canvas->Refresh();
}
void LIB_EDIT_FRAME::SaveOneSymbol()
{
    wxString        msg;
    PROJECT&        prj = Prj();
    SEARCH_STACK*   search = prj.SchSearchS();
    LIB_PART*       part = GetCurPart();

    if( !part || part->GetDrawItemList().empty() )
        return;

    wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
    if( !default_path )
        default_path = search->LastVisitedPath();

    wxFileDialog dlg( this, _( "Export Symbol Drawings" ), default_path,
                      part->GetName(), SchematicSymbolFileWildcard,
                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

    if( dlg.ShowModal() == wxID_CANCEL )
        return;

    wxFileName fn = dlg.GetPath();

    /* The GTK file chooser doesn't return the file extension added to
     * file name so add it here. */
    if( fn.GetExt().IsEmpty() )
        fn.SetExt( SchematicSymbolFileExtension );

    prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );

    msg.Printf( _( "Saving symbol in '%s'" ), GetChars( fn.GetPath() ) );
    SetStatusText( msg );

    wxString line;

    // File header
    line << wxT( LIBFILE_IDENT ) << wxT( " " ) << LIB_VERSION_MAJOR
         << wxT( "." ) << LIB_VERSION_MINOR << wxT( "  SYMBOL  " )
         << wxT( "Date: " ) << DateAndTime() << wxT( "\n" );

    // Component name comment and definition.
    line << wxT( "# SYMBOL " ) << part->GetName() << wxT( "\n#\nDEF " )
         << part->GetName() << wxT( " " );

    if( !part->GetReferenceField().GetText().IsEmpty() )
        line << part->GetReferenceField().GetText() << wxT( " " );
    else
        line << wxT( "~ " );

    line << 0 << wxT( " " ) << part->GetPinNameOffset() << wxT( " " );

    if( part->ShowPinNumbers() )
        line << wxT( "Y " );
    else
        line << wxT( "N " );

    if( part->ShowPinNames() )
        line << wxT( "Y " );
    else
        line << wxT( "N " );

    line << wxT( "1 0 N\n" );

    try
    {
        FILE_OUTPUTFORMATTER    formatter( fn.GetFullPath() );

        try
        {
            formatter.Print( 0, "%s", TO_UTF8( line ) );
            part->GetReferenceField().Save( formatter );
            part->GetValueField().Save( formatter );
            formatter.Print( 0, "DRAW\n" );

            LIB_ITEMS& drawList = part->GetDrawItemList();

            for( LIB_ITEM& item : drawList )
            {
                if( item.Type() == LIB_FIELD_T )
                    continue;

                // Don't save unused parts or alternate body styles.
                if( m_unit && item.GetUnit() && ( item.GetUnit() != m_unit ) )
                    continue;

                if( m_convert && item.GetConvert() && ( item.GetConvert() != m_convert ) )
                    continue;

                item.Save( formatter );
            }

            formatter.Print( 0, "ENDDRAW\n" );
            formatter.Print( 0, "ENDDEF\n" );
        }
        catch( const IO_ERROR& ioe )
        {
            msg.Printf( _( "An error occurred attempting to save symbol file '%s'" ),
                        GetChars( fn.GetFullPath() ) );
            DisplayError( this, msg );
        }
    }
    catch( const IO_ERROR& ioe )
    {
        DisplayError( this, ioe.errorText );
        return;
    }
}