void DIALOG_CHOOSE_COMPONENT::OnHandlePreviewRepaint( wxPaintEvent& aRepaintEvent ) { int unit = 0; LIB_ALIAS* selection = m_search_container->GetSelectedAlias( &unit ); LIB_PART* part = selection ? selection->GetPart() : NULL; // Don't draw anything (not even the background) if we don't have // a part to show if( !part ) return; if( selection->IsRoot() ) { // just show the part directly renderPreview( part, unit ); } else { // switch out the name temporarily for the alias name wxString tmp( part->GetName() ); part->SetName( selection->GetName() ); renderPreview( part, unit ); part->SetName( tmp ); } }
void LIB_EDIT_FRAME::fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary ) { wxString newName; for( unsigned int i = 0; i < aPart->GetAliasCount(); ++i ) { LIB_ALIAS* alias = aPart->GetAlias( i ); int sfx = 0; newName = alias->GetName(); while( m_libMgr->PartExists( newName, aLibrary ) ) { if( sfx == 0 ) newName = wxString::Format( "%s_copy", alias->GetName() ); else newName = wxString::Format( "%s_copy%d", alias->GetName(), sfx ); ++sfx; } if( i == 0 ) aPart->SetName( newName ); else alias->SetName( newName ); } }
void LIB_VIEW_FRAME::updatePreviewSymbol() { LIB_ALIAS* alias = getSelectedAlias(); KIGFX::SCH_VIEW* view = GetCanvas()->GetView(); if( m_previewItem ) { view->Remove( m_previewItem ); m_previewItem = nullptr; } ClearMsgPanel(); if( alias ) { GetRenderSettings()->m_ShowUnit = m_unit; GetRenderSettings()->m_ShowConvert = m_convert; view->Add( alias ); m_previewItem = alias; AppendMsgPanel( _( "Name" ), alias->GetName(), BLUE, 6 ); AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 6 ); AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY ); } GetCanvas()->ForceRefresh(); }
LIB_PART* SchGetLibPart( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable, PART_LIB* aCacheLib, wxWindow* aParent, bool aShowErrorMsg ) { LIB_ALIAS* alias = SchGetLibAlias( aLibId, aLibTable, aCacheLib, aParent, aShowErrorMsg ); return ( alias ) ? alias->GetPart() : NULL; }
void LIB_VIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) { wxString msg; LIB_ALIAS* LibEntry; int ii, id = event.GetId(); switch( id ) { case ID_LIBVIEW_SELECT_LIB: SelectCurrentLibrary(); break; case ID_LIBVIEW_SELECT_PART: SelectAndViewLibraryPart( NEW_PART ); break; case ID_LIBVIEW_NEXT: SelectAndViewLibraryPart( NEXT_PART ); break; case ID_LIBVIEW_PREVIOUS: SelectAndViewLibraryPart( PREVIOUS_PART ); break; case ID_LIBVIEW_VIEWDOC: LibEntry = CMP_LIBRARY::FindLibraryEntry( m_entryName, m_libraryName ); if( LibEntry && ( !LibEntry->GetDocFileName().IsEmpty() ) ) GetAssociatedDocument( this, LibEntry->GetDocFileName(), &wxGetApp().GetLibraryPathList() ); break; case ID_LIBVIEW_DE_MORGAN_NORMAL_BUTT: m_mainToolBar->ToggleTool( ID_LIBVIEW_DE_MORGAN_NORMAL_BUTT, true ); m_mainToolBar->ToggleTool( ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT, false ); m_convert = 1; m_canvas->Refresh(); break; case ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT: m_mainToolBar->ToggleTool( ID_LIBVIEW_DE_MORGAN_NORMAL_BUTT, false ); m_mainToolBar->ToggleTool( ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT, true ); m_convert = 2; m_canvas->Refresh(); break; case ID_LIBVIEW_SELECT_PART_NUMBER: ii = SelpartBox->GetCurrentSelection(); if( ii < 0 ) return; m_unit = ii + 1; m_canvas->Refresh(); break; default: msg << wxT( "LIB_VIEW_FRAME::Process_Special_Functions error: id = " ) << id; DisplayError( this, msg ); break; } }
void LIB_EDIT_FRAME::OnImportPart( wxCommandEvent& event ) { wxString msg; m_lastDrawItem = NULL; wxString libName = getTargetLib(); if( !m_libMgr->LibraryExists( libName ) ) { libName = SelectLibraryFromList(); if( !m_libMgr->LibraryExists( libName ) ) return; } wxFileDialog dlg( this, _( "Import Symbol" ), m_mruPath, wxEmptyString, SchematicLibraryFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_CANCEL ) return; wxFileName fn = dlg.GetPath(); m_mruPath = fn.GetPath(); wxArrayString symbols; SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); // TODO dialog to select the part to be imported if there is more than one try { pi->EnumerateSymbolLib( symbols, fn.GetFullPath() ); } catch( const IO_ERROR& ioe ) { msg.Printf( _( "Cannot import symbol library \"%s\"." ), fn.GetFullPath() ); DisplayErrorMessage( this, msg, ioe.What() ); return; } if( symbols.empty() ) { msg.Printf( _( "Symbol library file \"%s\" is empty." ), fn.GetFullPath() ); DisplayError( this, msg ); return; } wxString symbolName = symbols[0]; LIB_ALIAS* entry = pi->LoadSymbol( fn.GetFullPath(), symbolName ); if( m_libMgr->PartExists( symbols[0], libName ) ) { msg.Printf( _( "Symbol \"%s\" already exists in library \"%s\"." ), symbolName, libName ); DisplayError( this, msg ); return; } m_libMgr->UpdatePart( entry->GetPart(), libName ); SyncLibraries( false ); loadPart( symbolName, libName, 1 ); }
void LIB_VIEW_FRAME::ViewOneLibraryContent( CMP_LIBRARY* Lib, int Flag ) { int NumOfParts = 0; LIB_ALIAS* LibEntry; wxString CmpName; if( Lib ) NumOfParts = Lib->GetCount(); if( NumOfParts == 0 ) { DisplayError( this, wxT( "No library or library is empty!" ) ); return; } if( Lib == NULL ) return; if( Flag == NEW_PART ) { DisplayComponentsNamesInLib( this, Lib, CmpName, m_entryName ); } if( Flag == NEXT_PART ) { LibEntry = Lib->GetNextEntry( m_entryName ); if( LibEntry ) CmpName = LibEntry->GetName(); } if( Flag == PREVIOUS_PART ) { LibEntry = Lib->GetPreviousEntry( m_entryName ); if( LibEntry ) CmpName = LibEntry->GetName(); } m_unit = 1; m_convert = 1; LibEntry = Lib->FindEntry( CmpName ); m_entryName = CmpName; DisplayLibInfos(); Zoom_Automatique( false ); m_canvas->Refresh( ); if( m_CmpList ) { int id = m_CmpList->FindString( m_entryName.GetData() ); if( id >= 0 ) m_CmpList->SetSelection( id ); } ReCreateHToolbar(); }
LIB_COMPONENT* CMP_LIBRARY::FindComponent( const wxChar* aName ) { LIB_COMPONENT* component = NULL; LIB_ALIAS* entry = FindEntry( aName ); if( entry != NULL ) component = entry->GetComponent(); return component; }
LIB_PART* LIB_VIEW_FRAME::getSelectedSymbol() const { LIB_PART* symbol = NULL; LIB_ALIAS* alias = getSelectedAlias(); if( alias ) symbol = alias->GetPart(); return symbol; }
void LIB_VIEW_FRAME::onViewSymbolDocument( wxCommandEvent& aEvent ) { LIB_ALIAS* entry = Prj().SchLibs()->FindLibraryAlias( m_entryName, m_libraryName ); if( entry && !entry->GetDocFileName().IsEmpty() ) { SEARCH_STACK* lib_search = Prj().SchSearchS(); GetAssociatedDocument( this, entry->GetDocFileName(), lib_search ); } }
CMP_LIBRARY::~CMP_LIBRARY() { for( LIB_ALIAS_MAP::iterator it=aliases.begin(); it!=aliases.end(); it++ ) { LIB_ALIAS* alias = (*it).second; LIB_COMPONENT* component = alias->GetComponent(); alias = component->RemoveAlias( alias ); if( alias == NULL ) delete component; } }
// Used in DataBaseGetName: this is a callback function for EDA_LIST_DIALOG // to display keywords and description of a component void DisplayCmpDocAndKeywords( wxString& Name ) { LIB_ALIAS* CmpEntry = NULL; CmpEntry = CMP_LIBRARY::FindLibraryEntry( Name ); if( CmpEntry == NULL ) return; Name = wxT( "Description: " ) + CmpEntry->GetDescription(); Name += wxT( "\nKey Words: " ) + CmpEntry->GetKeyWords(); }
void AddMenusForComponent( wxMenu* PopMenu, SCH_COMPONENT* Component ) { if( Component->Type() != SCH_COMPONENT_T ) { wxASSERT( 0 ); return; } wxString msg; LIB_ALIAS* libEntry; libEntry = CMP_LIBRARY::FindLibraryEntry( Component->GetLibName() ); if( !Component->GetFlags() ) { msg.Printf( _( "Move Component %s" ), GetChars( Component->GetField( REFERENCE )->GetText() ) ); msg = AddHotkeyName( msg, s_Schematic_Hokeys_Descr, HK_MOVE_COMPONENT_OR_ITEM ); AddMenuItem( PopMenu, ID_SCH_MOVE_ITEM, msg, KiBitmap( move_xpm ) ); msg = AddHotkeyName( _( "Drag Component" ), s_Schematic_Hokeys_Descr, HK_DRAG ); AddMenuItem( PopMenu, ID_SCH_DRAG_ITEM, msg, KiBitmap( move_xpm ) ); } wxMenu* orientmenu = new wxMenu; msg = AddHotkeyName( _( "Rotate +" ), s_Schematic_Hokeys_Descr, HK_ROTATE ); AddMenuItem( orientmenu, ID_SCH_ROTATE_COUNTERCLOCKWISE, msg, KiBitmap( rotate_ccw_xpm ) ); AddMenuItem( orientmenu, ID_SCH_ROTATE_CLOCKWISE, _( "Rotate -" ), KiBitmap( rotate_cw_xpm ) ); msg = AddHotkeyName( _( "Mirror --" ), s_Schematic_Hokeys_Descr, HK_MIRROR_X_COMPONENT ); AddMenuItem( orientmenu, ID_SCH_MIRROR_X, msg, KiBitmap( mirror_v_xpm ) ); msg = AddHotkeyName( _( "Mirror ||" ), s_Schematic_Hokeys_Descr, HK_MIRROR_Y_COMPONENT ); AddMenuItem( orientmenu, ID_SCH_MIRROR_Y, msg, KiBitmap( mirror_h_xpm ) ); msg = AddHotkeyName( _( "Normal" ), s_Schematic_Hokeys_Descr, HK_ORIENT_NORMAL_COMPONENT ); AddMenuItem( orientmenu, ID_SCH_ORIENT_NORMAL, msg, KiBitmap( normal_xpm ) ); AddMenuItem( PopMenu, orientmenu, ID_POPUP_SCH_GENERIC_ORIENT_CMP, _( "Orient Component" ), KiBitmap( orient_xpm ) ); AddMenusForEditComponent( PopMenu, Component ); if( !Component->GetFlags() ) { msg = AddHotkeyName( _( "Copy Component" ), s_Schematic_Hokeys_Descr, HK_COPY_COMPONENT_OR_LABEL ); AddMenuItem( PopMenu, ID_POPUP_SCH_COPY_ITEM, msg, KiBitmap( copy_button_xpm ) ); msg = AddHotkeyName( _( "Delete Component" ), s_Schematic_Hokeys_Descr, HK_DELETE ); AddMenuItem( PopMenu, ID_POPUP_SCH_DELETE_CMP, msg, KiBitmap( delete_xpm ) ); } if( libEntry && !libEntry->GetDocFileName().IsEmpty() ) AddMenuItem( PopMenu, ID_POPUP_SCH_DISPLAYDOC_CMP, _( "Doc" ), KiBitmap( datasheet_xpm ) ); }
// Used in DataBaseGetName: this is a callback function for EDA_LIST_DIALOG // to display keywords and description of a component void DisplayCmpDocAndKeywords( wxString& aName, void* aData ) { PART_LIBS* libs = (PART_LIBS*) aData; wxASSERT( libs ); LIB_ALIAS* part = libs->FindLibraryEntry( aName ); if( !part ) return; aName = wxT( "Description: " ) + part->GetDescription(); aName += wxT( "\nKey Words: " ) + part->GetKeyWords(); }
void SetHtmlAliasOf() { if( m_part->IsRoot() ) { m_html.Replace( "__ALIASOF__", wxEmptyString ); } else { LIB_PART* root = m_part->GetPart(); const wxString root_name = ( root ? root->GetName() : _( "Unknown" ) ); m_html.Replace( "__ALIASOF__", wxString::Format( AliasOfFormat, EscapedHTML( root_name ) ) ); } }
void LIB_EDIT_FRAME::OnUpdateViewDoc( wxUpdateUIEvent& event ) { bool enable = false; if( m_component != NULL && m_library != NULL ) { LIB_ALIAS* alias = m_component->GetAlias( m_aliasName ); wxCHECK_RET( alias != NULL, wxT( "Alias <" ) + m_aliasName + wxT( "> not found." ) ); enable = !alias->GetDocFileName().IsEmpty(); } event.Enable( enable ); }
void LIB_EDIT_FRAME::DisplayCmpDoc() { LIB_ALIAS* alias; PART_LIB* lib = GetCurLib(); LIB_PART* part = GetCurPart(); ClearMsgPanel(); if( !lib || !part ) return; wxString msg = part->GetName(); AppendMsgPanel( _( "Name" ), msg, BLUE, 8 ); if( m_aliasName == part->GetName() ) msg = _( "None" ); else msg = m_aliasName; alias = part->GetAlias( m_aliasName ); wxCHECK_RET( alias != NULL, "Alias not found in component." ); AppendMsgPanel( _( "Alias" ), msg, RED, 8 ); static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); msg = UnitLetter[m_unit]; AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 ); if( m_convert > 1 ) msg = _( "Convert" ); else msg = _( "Normal" ); AppendMsgPanel( _( "Body" ), msg, GREEN, 8 ); if( part->IsPower() ) msg = _( "Power Symbol" ); else msg = _( "Part" ); AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 ); AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 8 ); AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY ); AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY ); }
LIB_PART* LIB_EDIT_FRAME::getTargetPart() const { LIB_ALIAS* alias = nullptr; if( m_treePane->GetLibTree()->IsMenuActive() ) { LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId(); alias = m_libMgr->GetAlias( libId.GetLibItemName(), libId.GetLibNickname() ); } else if( LIB_PART* part = GetCurPart() ) { alias = part->GetAlias( 0 ); } return alias ? alias->GetPart() : nullptr; }
const BOX2I LIB_VIEW_FRAME::GetDocumentExtents() const { LIB_ALIAS* alias = getSelectedAlias(); LIB_PART* part = alias ? alias->GetPart() : nullptr; if( !part ) { return BOX2I( VECTOR2I(-200, -200), VECTOR2I( 400, 400 ) ); } else { EDA_RECT bbox = part->GetUnitBoundingBox( m_unit, m_convert ); return BOX2I( bbox.GetOrigin(), VECTOR2I( bbox.GetWidth(), bbox.GetHeight() ) ); } }
void LIB_EDIT_FRAME::OnUpdateViewDoc( wxUpdateUIEvent& event ) { bool enable = false; PART_LIB* lib = GetCurLib(); LIB_PART* part = GetCurPart(); if( part && lib ) { LIB_ALIAS* alias = part->GetAlias( m_aliasName ); wxCHECK_RET( alias != NULL, wxT( "Alias <" ) + m_aliasName + wxT( "> not found." ) ); enable = !alias->GetDocFileName().IsEmpty(); } event.Enable( enable ); }
LIB_COMPONENT* CMP_LIBRARY::FindComponent( const wxString& aName ) { #if 0 && defined(DEBUG) if( !aName.Cmp( wxT( "TI_STELLARIS_BOOSTERPACK" ) ) ) { int breakhere = 1; (void) breakhere; } #endif LIB_COMPONENT* component = NULL; LIB_ALIAS* entry = FindEntry( aName ); if( entry ) component = entry->GetComponent(); return component; }
void LIB_EDIT_FRAME::OnViewEntryDoc( wxCommandEvent& event ) { if( m_component == NULL ) return; wxString fileName; LIB_ALIAS* alias = m_component->GetAlias( m_aliasName ); wxCHECK_RET( alias != NULL, wxT( "Alias not found." ) ); fileName = alias->GetDocFileName(); if( !fileName.IsEmpty() ) { SEARCH_STACK* lib_search = &Prj().SchSearchS(); GetAssociatedDocument( this, fileName, lib_search ); } }
void SetHtmlKeywords() { wxString keywords = m_part->GetKeyWords(); if( keywords.empty() ) m_html.Replace( "__KEY__", wxEmptyString ); else m_html.Replace( "__KEY__", wxString::Format( KeywordsFormat, EscapedHTML( keywords ) ) ); }
void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event ) { SCH_COMPONENT* component = NULL; if( event.GetId() == ID_POPUP_SCH_CALL_LIBEDIT_AND_LOAD_CMP ) { SCH_ITEM* item = GetScreen()->GetCurItem(); if( (item == NULL) || (item->GetFlags() != 0) || ( item->Type() != SCH_COMPONENT_T ) ) { wxMessageBox( _("Error: not a component or no component" ) ); return; } component = (SCH_COMPONENT*) item; } LIB_EDIT_FRAME* libeditFrame = LIB_EDIT_FRAME::GetActiveLibraryEditor();; if( libeditFrame ) { if( libeditFrame->IsIconized() ) libeditFrame->Iconize( false ); libeditFrame->Raise(); } else { wxWindow* w = Kiface().CreateWindow( this, LIBEDITOR_FRAME_TYPE, &Kiway() ); libeditFrame = dynamic_cast<LIB_EDIT_FRAME*>( w ); } if( component ) { LIB_ALIAS* entry = CMP_LIBRARY::FindLibraryEntry( component->GetLibName() ); if( entry == NULL ) // Should not occur return; CMP_LIBRARY* library = entry->GetLibrary(); libeditFrame->LoadComponentAndSelectLib( entry, library ); } }
double LIB_VIEW_FRAME::BestZoom() { LIB_PART* part = NULL; double defaultLibraryZoom = 7.33; if( m_libraryName.IsEmpty() || m_entryName.IsEmpty() ) { SetScrollCenterPosition( wxPoint( 0, 0 ) ); return defaultLibraryZoom; } LIB_ALIAS* alias = nullptr; try { alias = Prj().SchSymbolLibTable()->LoadSymbol( m_libraryName, m_entryName ); } catch( ... ) { } if( alias ) part = alias->GetPart(); if( !part ) { SetScrollCenterPosition( wxPoint( 0, 0 ) ); return defaultLibraryZoom; } EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert ); double sizeX = (double) boundingBox.GetWidth(); double sizeY = (double) boundingBox.GetHeight(); wxPoint centre = boundingBox.Centre(); // Reserve a 20% margin around component bounding box. double margin_scale_factor = 1.2; return bestZoom( sizeX, sizeY, margin_scale_factor, centre ); }
LIB_ALIAS* CMP_LIBRARY::RemoveEntry( LIB_ALIAS* aEntry ) { wxCHECK_MSG( aEntry != NULL, NULL, wxT( "NULL pointer cannot be removed from library." ) ); LIB_ALIAS_MAP::iterator it = aliases.find( aEntry->GetName() ); if( it == aliases.end() ) return NULL; // If the entry pointer doesn't match the name it is mapped to in the library, we // have done something terribly wrong. wxCHECK_MSG( (*it).second == aEntry, NULL, wxT( "Pointer mismatch while attempting to remove entry <" ) + aEntry->GetName() + wxT( "> from library <" ) + GetName() + wxT( ">." ) ); LIB_ALIAS* alias = (LIB_ALIAS*) aEntry; LIB_COMPONENT* component = alias->GetComponent(); alias = component->RemoveAlias( alias ); if( alias == NULL ) { delete component; if( aliases.size() > 1 ) { LIB_ALIAS_MAP::iterator next = it; next++; if( next == aliases.end() ) next = aliases.begin(); alias = (*next).second; } } aliases.erase( it ); isModified = true; return alias; }
void SetHtmlDesc() { wxString raw_desc; if( m_part->IsRoot() ) { raw_desc = m_part->GetDescription(); } else { LIB_PART* root = m_part->GetPart(); for( size_t i = 0; i < root->GetAliasCount(); ++i ) { LIB_ALIAS* alias = root->GetAlias( i ); if( alias && !alias->GetDescription().empty() ) { raw_desc = alias->GetDescription(); break; } } } m_html.Replace( "__DESC__", wxString::Format( DescFormat, EscapedHTML( raw_desc ) ) ); }
void SetHtmlFieldTable() { wxString fieldtable; LIB_FIELDS fields; m_part->GetPart()->GetFields( fields ); for( auto const & field: fields ) { fieldtable += GetHtmlFieldRow( field ); } m_html.Replace( "__FIELDS__", fieldtable ); }
void DIALOG_EDIT_COMPONENT_IN_LIBRARY::InitPanelDoc() { LIB_ALIAS* alias; LIB_PART* component = m_Parent->GetCurPart(); if( component == NULL ) return; wxString aliasname = m_Parent->GetAliasName(); if( aliasname.IsEmpty() ) return; alias = component->GetAlias( aliasname ); if( alias != NULL ) { m_DocCtrl->SetValue( alias->GetDescription() ); m_KeywordsCtrl->SetValue( alias->GetKeyWords() ); m_DocfileCtrl->SetValue( alias->GetDocFileName() ); } }
/** * Function RedrawActiveWindow * Display the current selected component. * If the component is an alias, the ROOT component is displayed */ void LIB_VIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg ) { LIB_COMPONENT* component; LIB_ALIAS* entry; CMP_LIBRARY* lib; wxString msg; wxString tmp; lib = CMP_LIBRARY::FindLibrary( m_libraryName ); if( lib == NULL ) return; entry = lib->FindEntry( m_entryName ); if( entry == NULL ) return; component = entry->GetComponent(); m_canvas->DrawBackGround( DC ); if( !entry->IsRoot() ) { if( component == NULL ) // Should not occur return; // Temporarily change the name field text to reflect the alias name. msg = entry->GetName(); tmp = component->GetName(); component->SetName( msg ); if( m_unit < 1 ) m_unit = 1; if( m_convert < 1 ) m_convert = 1; } else { msg = _( "None" ); } component->Draw( m_canvas, DC, wxPoint( 0, 0 ), m_unit, m_convert, GR_DEFAULT_DRAWMODE ); /* Redraw the cursor */ m_canvas->DrawCrossHair( DC ); if( !tmp.IsEmpty() ) component->SetName( tmp ); ClearMsgPanel(); AppendMsgPanel( _( "Part" ), component->GetName(), BLUE, 6 ); AppendMsgPanel( _( "Alias" ), msg, RED, 6 ); AppendMsgPanel( _( "Description" ), entry->GetDescription(), CYAN, 6 ); AppendMsgPanel( _( "Key words" ), entry->GetKeyWords(), DARKDARKGRAY ); }