1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr 5 * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com> 6 * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, you may find one here: 20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 21 * or you may search the http://www.gnu.org website for the version 2 license, 22 * or you may write to the Free Software Foundation, Inc., 23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 24 */ 25 26 /** 27 * @file symbol_library.h 28 * @brief Definition for symbol library class. 29 */ 30 31 #ifndef SYMBOL_LIBRARY_H 32 #define SYMBOL_LIBRARY_H 33 34 #include <map> 35 #include <mutex> 36 #include <boost/ptr_container/ptr_vector.hpp> 37 #include <wx/filename.h> 38 39 #include <sch_io_mgr.h> 40 #include <project.h> 41 42 class LIB_SYMBOL; 43 class LIB_ID; 44 class LINE_READER; 45 class OUTPUTFORMATTER; 46 class SCH_LEGACY_PLUGIN; 47 class SCH_PLUGIN; 48 49 50 #define DOC_EXT "dcm" 51 52 /* 53 * Symbol Library version and file header macros. 54 */ 55 #define LIB_VERSION_MAJOR 2 56 #define LIB_VERSION_MINOR 4 57 58 /* Must be the first line of symbol library (.lib) files. */ 59 #define LIBFILE_IDENT "EESchema-LIBRARY Version" 60 61 #define LIB_VERSION( major, minor ) ( major * 100 + minor ) 62 63 #define IS_LIB_CURRENT_VERSION( major, minor ) \ 64 ( \ 65 LIB_VERSION( major1, minor1 ) == \ 66 LIB_VERSION( LIB_VERSION_MAJOR, LIB_VERSION_MINOR) \ 67 ) 68 69 /* 70 * Library versions 2.4 and lower use the old separate library (.lib) and 71 * document (.dcm) files. Symbol libraries after 2.4 merged the library 72 * and document files into a single library file. This macro checks if the 73 * library version supports the old format 74 */ 75 #define USE_OLD_DOC_FILE_FORMAT( major, minor ) \ 76 ( LIB_VERSION( major, minor ) <= LIB_VERSION( 2, 4 ) ) 77 78 enum class SCH_LIB_TYPE 79 { 80 LT_EESCHEMA, 81 LT_SYMBOL 82 }; 83 84 // Helper class to filter a list of libraries, and/or a list of SYMBOL_LIB 85 // in dialogs 86 class SCHLIB_FILTER 87 { 88 public: SCHLIB_FILTER()89 SCHLIB_FILTER() 90 { 91 m_filterPowerSymbols = false; 92 m_forceLoad = false; 93 } 94 95 /** 96 * add a lib name to the allowed libraries 97 */ AddLib(const wxString & aLibName)98 void AddLib( const wxString& aLibName ) 99 { 100 m_allowedLibs.Add( aLibName ); 101 m_forceLoad = false; 102 } 103 104 105 /** 106 * add a lib name to the allowed libraries 107 */ LoadFrom(const wxString & aLibName)108 void LoadFrom( const wxString& aLibName ) 109 { 110 m_allowedLibs.Clear(); 111 m_allowedLibs.Add( aLibName ); 112 m_forceLoad = true; 113 } 114 115 /** 116 * Clear the allowed libraries list (allows all libs) 117 */ ClearLibList()118 void ClearLibList() 119 { 120 m_allowedLibs.Clear(); 121 m_forceLoad = false; 122 } 123 124 /** 125 * Set the filtering of power symbols 126 */ FilterPowerSymbols(bool aFilterEnable)127 void FilterPowerSymbols( bool aFilterEnable ) 128 { 129 m_filterPowerSymbols = aFilterEnable; 130 } 131 132 // Accessors 133 134 /** 135 * @return true if the filtering of power symbols is on 136 */ GetFilterPowerSymbols()137 bool GetFilterPowerSymbols() const { return m_filterPowerSymbols; } 138 139 140 /** 141 * @return am wxArrayString of the names of allowed libs 142 */ GetAllowedLibList()143 const wxArrayString& GetAllowedLibList() const { return m_allowedLibs; } 144 145 /** 146 * @return the name of the lib to use to load a symbol, or an a empty string 147 * Useful to load (in lib editor or lib viewer) a symbol from a given library 148 */ GetLibSource()149 const wxString& GetLibSource() const 150 { 151 static wxString dummy; 152 153 if( m_forceLoad && m_allowedLibs.GetCount() > 0 ) 154 return m_allowedLibs[0]; 155 else 156 return dummy; 157 } 158 159 private: 160 wxArrayString m_allowedLibs; ///< a list of lib names to list some libraries 161 ///< if empty: no filter 162 bool m_filterPowerSymbols; ///< true to filter (show only) power symbols 163 bool m_forceLoad; // When true, load a symbol lib from the lib 164 // which is given in m_allowedLibs[0] 165 }; 166 167 168 /* Helpers for creating a list of symbol libraries. */ 169 class SYMBOL_LIB; 170 class wxRegEx; 171 172 /** 173 * LIB_SYMBOL map sorting. 174 */ 175 struct LibSymbolMapSort 176 { operatorLibSymbolMapSort177 bool operator() ( const wxString& aItem1, const wxString& aItem2 ) const 178 { 179 return aItem1 < aItem2; 180 } 181 }; 182 183 /// Symbol map used by symbol library object. 184 185 typedef std::map< wxString, LIB_SYMBOL*, LibSymbolMapSort > LIB_SYMBOL_MAP; 186 typedef boost::ptr_vector< SYMBOL_LIB > SYMBOL_LIBS_BASE; 187 188 189 /** 190 * A collection of #SYMBOL_LIB objects. 191 * 192 * It extends from PROJECT::_ELEM so it can be hung in the PROJECT. It does not use any 193 * UI calls, but rather simply throws an IO_ERROR when there is a problem. 194 */ 195 class SYMBOL_LIBS : public SYMBOL_LIBS_BASE, public PROJECT::_ELEM 196 { 197 public: Type()198 KICAD_T Type() override { return SYMBOL_LIBS_T; } 199 200 static int s_modify_generation; ///< helper for GetModifyHash() 201 static std::mutex s_generationMutex; 202 SYMBOL_LIBS()203 SYMBOL_LIBS() 204 { 205 IncrementModifyGeneration(); 206 } 207 IncrementModifyGeneration()208 static void IncrementModifyGeneration() 209 { 210 std::lock_guard<std::mutex> mut( SYMBOL_LIBS::s_generationMutex ); 211 ++SYMBOL_LIBS::s_modify_generation; 212 } 213 GetModifyGeneration()214 static int GetModifyGeneration() 215 { 216 std::lock_guard<std::mutex> mut( SYMBOL_LIBS::s_generationMutex ); 217 return SYMBOL_LIBS::s_modify_generation; 218 } 219 220 /// Return the modification hash for all libraries. The value returned 221 /// changes on every library modification. 222 int GetModifyHash(); 223 224 /** 225 * Allocate and adds a symbol library to the library list. 226 * 227 * @param aFileName is the file name object of symbol library. 228 * @throw IO_ERROR if there's any problem loading. 229 */ 230 SYMBOL_LIB* AddLibrary( const wxString& aFileName ); 231 232 /** 233 * Insert a symbol library into the library list. 234 * 235 * @param aFileName is the file name object of symbol library. 236 * @param aIterator is an iterator to insert library in front of. 237 * @return the new SYMBOL_LIB, which remains owned by this SYMBOL_LIBS container. 238 * @throw IO_ERROR if there's any problem loading. 239 */ 240 SYMBOL_LIB* AddLibrary( const wxString& aFileName, SYMBOL_LIBS::iterator& aIterator ); 241 242 /** 243 * Load all of the project's libraries into this container, which should 244 * be cleared before calling it. 245 * 246 * @note This method is only to be used when loading legacy projects. All further symbol 247 * library access should be done via the symbol library table. 248 */ 249 void LoadAllLibraries( PROJECT* aProject, bool aShowProgress=true ); 250 251 /** 252 * Save or load the names of the currently configured symbol libraries (without paths). 253 */ 254 static void LibNamesAndPaths( PROJECT* aProject, bool doSave, 255 wxString* aPaths, wxArrayString* aNames = nullptr ); 256 257 /** 258 * Return the name of the cache library after potentially fixing it from 259 * an older naming scheme. That is, the old file is renamed if needed. 260 * 261 * @param aFullProjectFilename is the *.pro filename with absolute path. 262 */ 263 static const wxString CacheName( const wxString& aFullProjectFilename ); 264 265 /** 266 * Find a symbol library by \a aName. 267 * 268 * @param aName is the library file name without path or extension to find. 269 * @return the symbol library if found, otherwise NULL. 270 */ 271 SYMBOL_LIB* FindLibrary( const wxString& aName ); 272 273 SYMBOL_LIB* FindLibraryByFullFileName( const wxString& aFullFileName ); 274 275 SYMBOL_LIB* GetCacheLibrary(); 276 277 /** 278 * Return the list of symbol library file names without path and extension. 279 * 280 * @param aSorted sort the list of name if true. Otherwise use the library load order. 281 * @return the list of library names. 282 */ 283 wxArrayString GetLibraryNames( bool aSorted = true ); 284 285 /** 286 * Search all libraries in the list for a symbol. 287 * 288 * A symbol object will always be returned. If the entry found 289 * is an alias. The root symbol will be found and returned. 290 * 291 * @param aLibId is the #LIB_ID of the symbol to search for. 292 * @param aLibraryName is the name of the library to search for symbol. 293 * @return the symbol object if found, otherwise NULL. 294 */ 295 LIB_SYMBOL* FindLibSymbol( const LIB_ID& aLibId, const wxString& aLibraryName = wxEmptyString ); 296 297 /** 298 * Search all libraries in the list for a #LIB_SYMBOL using a case insensitive comparison. 299 * 300 * Helper function used in dialog to find all candidates. 301 * During a long time, eeschema was using a case insensitive search. 302 * Therefore, for old schematics (<= 2013), or libs, for some symbols, 303 * the chip name (name of alias in lib) can be broken. 304 * This function can be used to display a list of candidates, in symbol properties dialog. 305 * 306 * @param aEntryName is the name of entries to search for (case insensitive). 307 * @param aLibraryName is the name of the library to search. 308 * @param aCandidates is a std::vector to store candidates. 309 */ 310 void FindLibraryNearEntries( std::vector<LIB_SYMBOL*>& aCandidates, const wxString& aEntryName, 311 const wxString& aLibraryName = wxEmptyString ); 312 GetLibraryCount()313 int GetLibraryCount() { return size(); } 314 }; 315 316 317 /** 318 * Object used to load, save, search, and otherwise manipulate symbol library files. 319 * 320 * @warning This code is obsolete with the exception of the cache library. All other 321 * symbol library I/O is managed by the #SCH_IO_MGR object. 322 */ 323 class SYMBOL_LIB 324 { 325 public: 326 SYMBOL_LIB( SCH_LIB_TYPE aType, const wxString& aFileName, 327 SCH_IO_MGR::SCH_FILE_T aPluginType = SCH_IO_MGR::SCH_LEGACY ); 328 ~SYMBOL_LIB(); 329 330 /** 331 * @return a magic number that changes if the library has changed 332 */ GetModHash()333 int GetModHash() const { return m_mod_hash; } 334 GetPluginType()335 SCH_IO_MGR::SCH_FILE_T GetPluginType() const { return m_pluginType; } 336 337 void SetPluginType( SCH_IO_MGR::SCH_FILE_T aPluginType ); 338 339 void Create( const wxString& aFileName = wxEmptyString ); 340 SetFileName(const wxString & aFileName)341 void SetFileName( const wxString& aFileName ) { fileName = aFileName; } 342 IsModified()343 bool IsModified() const 344 { 345 return isModified; 346 } 347 348 bool IsCache() const; 349 350 void SetCache(); 351 352 bool IsBuffering() const; 353 354 void EnableBuffering( bool aEnable = true ); 355 356 void Save( bool aSaveDocFile = true ); 357 358 /** 359 * @return true if current user does not have write access to the library file. 360 */ IsReadOnly()361 bool IsReadOnly() const { return !fileName.IsFileWritable(); } 362 363 /** 364 * Load a string array with the names of all the entries in this library. 365 * 366 * @param aNames is the array to place entry names into. 367 */ 368 void GetSymbolNames( wxArrayString& aNames ) const; 369 370 /** 371 * Load a vector with all the entries in this library. 372 * 373 * @param aSymbols is a vector to receive the aliases. 374 */ 375 void GetSymbols( std::vector<LIB_SYMBOL*>& aSymbols ) const; 376 377 /** 378 * Find #LIB_SYMBOL by \a aName. 379 * 380 * @param aName is the name of the symbol, case sensitive. 381 * @return LIB_SYMBOL pointer symbol if found, else NULL. 382 */ 383 LIB_SYMBOL* FindSymbol( const wxString& aName ) const; 384 385 LIB_SYMBOL* FindSymbol( const LIB_ID& aLibId ) const; 386 387 /** 388 * Add \a aSymbol entry to library. 389 * 390 * @note A #LIB_SYMBOL can have an alias list so these alias will be added in library. 391 * and the any existing duplicate aliases will be removed from the library. 392 * 393 * @param aSymbol is the symbol to add, caller retains ownership, a clone is added. 394 */ 395 void AddSymbol( LIB_SYMBOL* aSymbol ); 396 397 /** 398 * Safely remove \a aEntry from the library and return the next entry. 399 * 400 * The next entry returned depends on the entry being removed. If the entry being 401 * remove also removes the symbol, then the next entry from the list is returned. 402 * If the entry being used only removes an alias from a symbol, then the next alias 403 * of the symbol is returned. 404 * 405 * @param aEntry is the entry to remove from library. 406 * @return The next entry in the library or NULL if the library is empty. 407 */ 408 LIB_SYMBOL* RemoveSymbol( LIB_SYMBOL* aEntry ); 409 410 /** 411 * Replace an existing symbol entry in the library. 412 * 413 * @note A symbol can have an alias list so these aliases will be added in library and 414 * previously existing alias removed. 415 * 416 * @param aOldSymbol is the symbol to replace. 417 * @param aNewSymbol is the new symbol. 418 */ 419 LIB_SYMBOL* ReplaceSymbol( LIB_SYMBOL* aOldSymbol, LIB_SYMBOL* aNewSymbol ); 420 421 /** 422 * Return the file name without path or extension. 423 * 424 * @return the name of library file. 425 */ GetName()426 const wxString GetName() const { return fileName.GetName(); } 427 428 /** 429 * Return the full file library name with path and extension. 430 * 431 * @return the full library file name with path and extension. 432 */ GetFullFileName()433 wxString GetFullFileName() const { return fileName.GetFullPath(); } 434 435 /** 436 * Return the logical name of the library. 437 * 438 * @return The logical name of this library. 439 */ GetLogicalName()440 const wxString GetLogicalName() const 441 { 442 /* for now is the filename without path or extension. 443 444 Technically the library should not know its logical name! 445 This will eventually come out of a pair of lookup tables using a 446 reverse lookup using the full name or library pointer as a key. 447 Search will be by project lookup table and then user lookup table if 448 not found. 449 */ 450 return fileName.GetName(); 451 } 452 453 454 /** 455 * Allocate and load a symbol library file. 456 * 457 * @param aFileName is the file name of the symbol library to load. 458 * @return SYMBOL_LIB* is the allocated and loaded SYMBOL_LIB, which is owned by the caller. 459 * @throw IO_ERROR if there's any problem loading the library. 460 */ 461 static SYMBOL_LIB* LoadLibrary( const wxString& aFileName ); 462 463 private: 464 SCH_LIB_TYPE type; ///< Library type indicator. 465 wxFileName fileName; ///< Library file name. 466 wxDateTime timeStamp; ///< Library save time and date. 467 int versionMajor; ///< Library major version number. 468 int versionMinor; ///< Library minor version number. 469 wxString header; ///< first line of loaded library. 470 bool isModified; ///< Library modification status. 471 int m_mod_hash; ///< incremented each time library is changed. 472 473 SCH_IO_MGR::SCH_FILE_T m_pluginType; 474 std::unique_ptr< SCH_PLUGIN > m_plugin; 475 std::unique_ptr< PROPERTIES > m_properties; ///< Library properties 476 }; 477 478 479 /** 480 * Case insensitive library name comparison. 481 */ 482 bool operator==( const SYMBOL_LIB& aLibrary, const wxString& aName ); 483 bool operator!=( const SYMBOL_LIB& aLibrary, const wxString& aName ); 484 485 #endif // SYMBOL_LIBRARY_H 486