37#include <wx/translation.h>
39#include <compoundfilereader.h>
64 std::string
name = aName;
65 std::replace(
name.begin(),
name.end(),
'\x02',
'/' );
66 std::replace(
name.begin(),
name.end(),
'\x03',
':' );
74std::vector<char> readStream(
const ALTIUM_COMPOUND_FILE& aFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry )
79 uint64_t size = reader.GetStreamSize( aEntry );
81 if( size > reader.GetBufferLen() )
84 std::vector<char> data(
static_cast<size_t>( size ) );
87 reader.ReadFile( aEntry, 0, data.data(), data.size() );
93bool isLongFramedPackageStream(
const std::vector<char>& aData )
95 if( aData.size() < 11 )
101 uint32_t bodyLength = stream.ReadU32();
103 return stream.ReadU32() == 0 && bodyLength <= aData.size() - 11;
108std::vector<std::pair<std::string, const CFB::COMPOUND_FILE_ENTRY*>>
109enumChildren(
const ALTIUM_COMPOUND_FILE& aFile,
const CFB::COMPOUND_FILE_ENTRY* aParent,
bool aStreams )
111 std::vector<std::pair<std::string, const CFB::COMPOUND_FILE_ENTRY*>> out;
115 reader.EnumFiles( aParent, 1,
116 [&](
const CFB::COMPOUND_FILE_ENTRY* aEntry,
const CFB::utf16string&,
int ) ->
int
118 if( reader.IsStream( aEntry ) == aStreams )
128void collectPartOccurrences(
const ORCAD_OCC_SCOPE& aScope, std::multimap<uint32_t, uint32_t>& aOccurrences )
131 aOccurrences.emplace( dbId, occurrence );
134 collectPartOccurrences( block.
scope, aOccurrences );
146 const CFB::COMPOUND_FILE_ENTRY* variantStore = aFile.
FindStreamSingleLevel( cisStorage,
"VariantStore",
false );
151 const CFB::COMPOUND_FILE_ENTRY* bomStorage = aFile.
FindStreamSingleLevel( variantStore,
"BOM",
false );
156 const CFB::COMPOUND_FILE_ENTRY* bomData = aFile.
FindStreamSingleLevel( bomStorage,
"BOMDataStream",
true );
162 std::optional<std::string> requested;
166 auto request = aProperties->find(
"orcad_cis_variant" );
168 if( request != aProperties->end() )
169 requested = request->second;
174 if( selected.empty() )
178 auto applyVariantName = [&]( std::vector<ORCAD_RAW_PAGE>& aPages )
180 constexpr std::string_view placeholder =
"<Core Design>";
181 constexpr std::string_view variantVar =
"${VARIANT}";
187 for(
auto& [
name, value] : titleBlock.
props )
191 while( ( offset = value.find( placeholder, offset ) ) != std::string::npos )
193 value.replace( offset, placeholder.size(), variantVar );
194 offset += variantVar.size();
201 applyVariantName( aDesign.
pages );
204 applyVariantName( pages );
207 applyVariantName( pages );
211 const CFB::COMPOUND_FILE_ENTRY* membership =
nullptr;
212 const CFB::COMPOUND_FILE_ENTRY* updates =
nullptr;
213 std::string schematicName;
217 std::map<std::string, CIS_GROUP> groups;
219 if(
const CFB::COMPOUND_FILE_ENTRY* groupsStorage =
222 for(
const auto& [groupName, groupEntry] : enumChildren( aFile, groupsStorage,
false ) )
228 for(
const auto& [subgroupName, subgroupEntry] : enumChildren( aFile, groupEntry,
false ) )
230 groups[groupName +
"_" + subgroupName] = {
233 groupName +
"-" + subgroupName
244 for(
const auto& [folderName, folderEntry] : enumChildren( aFile, viewsStorage,
false ) )
246 const CFB::COMPOUND_FILE_ENTRY* cisSchematic =
252 const CFB::COMPOUND_FILE_ENTRY* infoStorage =
258 for(
const auto& [streamName, streamEntry] : enumChildren( aFile, infoStorage,
true ) )
260 if( streamName ==
"SchematicInfoStream" )
265 for(
auto& [groupName, occurrences] : pageInfo )
267 auto& target = schematicInfo[groupName];
269 for(
auto& [occurrence, properties] : occurrences )
270 target.insert_or_assign( occurrence, std::move( properties ) );
277 std::multimap<uint32_t, uint32_t> partOccurrences;
278 collectPartOccurrences( aDesign.
occurrenceRoot, partOccurrences );
280 std::map<std::string, const CFB::COMPOUND_FILE_ENTRY*> variantEntries;
282 for(
const auto& [
name, entry] : enumChildren( aFile, bomStorage,
false ) )
283 variantEntries.emplace(
name, entry );
285 for(
const std::string&
name : names )
295 for(
const auto& [property, value] : aProperties )
297 auto existing = std::find_if( target.begin(), target.end(),
298 [&](
const auto& aExisting )
300 return OrcadIEquals( aExisting.first, property );
303 if( existing != target.end() )
304 target.erase( existing );
306 target.emplace( property, value );
310 auto entry = variantEntries.find(
name );
311 const CFB::COMPOUND_FILE_ENTRY* definition =
315 THROW_IO_ERROR( wxString::Format(
_(
"The OrCAD CIS variant '%s' has no definition stream." ),
316 wxString::FromUTF8(
name ) ) );
321 auto group = groups.find( groupName );
323 if(
group == groups.end() )
325 if( groupName ==
"Common" || groupName ==
"CommonNI" )
328 THROW_IO_ERROR( wxString::Format(
_(
"The OrCAD CIS variant '%s' references an unknown "
330 wxString::FromUTF8(
name ) ) );
333 if(
group->second.membership )
335 for(
const auto& [occurrence, installed] :
338 variant.
installed[occurrence] = installed;
342 if(
group->second.updates )
344 for(
const auto& [occurrence, properties] :
347 overlay( occurrence, properties );
351 auto info = schematicInfo.find(
group->second.schematicName );
353 if(
info == schematicInfo.end() )
356 for(
const auto& [dbId, properties] :
info->second )
358 auto [first, last] = partOccurrences.equal_range( dbId );
360 for(
auto it = first; it != last; ++it )
361 overlay( it->second, properties );
365 aDesign.
cisVariants.push_back( std::move( variant ) );
372 aReporter->
Report( wxString::Format(
_(
"Using OrCAD CIS variant '%s'." ), wxString::FromUTF8( selected ) ),
394 const CFB::COMPOUND_FILE_ENTRY* root = reader.GetRootEntry();
409 catch(
const CFB::CFBException& )
413 catch(
const std::exception& )
432 const CFB::COMPOUND_FILE_ENTRY* root = reader.GetRootEntry();
436 catch(
const std::exception& )
444 const std::map<std::string, UTF8>* aProperties )
446 wxASSERT( !aFileName.IsEmpty() && aSchematic );
449 if( aProperties && aProperties->count(
"hierarchical_sheet_load" ) )
451 THROW_IO_ERROR( wxString::Format(
_(
"'%s' contains a complete OrCAD Capture design and cannot be "
452 "loaded as a hierarchical sheet. Use File > Import > "
453 "Non-KiCad Schematic... instead." ),
462 std::string sourceId( sourceHash->ToUTF8() );
468 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr, wxS(
"Can't append to a schematic with no root!" ) );
469 rootSheet = aAppendToMe;
511 const CFB::COMPOUND_FILE_ENTRY* root = reader.GetRootEntry();
514 const CFB::COMPOUND_FILE_ENTRY* libraryEntry = cfbFile.
FindStreamSingleLevel( root,
"Library",
true );
518 THROW_IO_ERROR(
_(
"The file does not contain the 'Library' stream of an OrCAD "
519 "Capture design." ) );
530 if(
const CFB::COMPOUND_FILE_ENTRY* cacheEntry = cfbFile.
FindStreamSingleLevel( root,
"Cache",
true ) )
537 warnFn(
_(
"The design has no 'Cache' stream; placeholder symbols will be "
538 "synthesized for all parts." ) );
542 if(
const CFB::COMPOUND_FILE_ENTRY* packagesStorage =
545 for(
const auto& [streamName, entry] : enumChildren( cfbFile, packagesStorage,
true ) )
547 std::map<std::string, ORCAD_SYMBOL_DEF> extraSymbols;
548 std::map<std::string, ORCAD_PACKAGE> extraPackages;
552 std::vector<char> data = readStream( cfbFile, entry );
555 ORCAD_DIALECT packageDialect{ isV2 || !isLongFramedPackageStream( data ),
556 dialect.shortDisplayProp };
564 warnFn( wxString::Format(
_(
"Package stream '%s' could not be parsed: %s" ),
565 wxString::FromUTF8( streamName ), e.
What() ) );
573 std::move( extraPackages ) );
578 const CFB::COMPOUND_FILE_ENTRY* viewsStorage = cfbFile.
FindStreamSingleLevel( root,
"Views",
false );
582 THROW_IO_ERROR(
_(
"The file does not contain a 'Views' storage; it is not a "
583 "supported OrCAD Capture design." ) );
586 std::vector<std::string> folders;
587 std::map<std::string, const CFB::COMPOUND_FILE_ENTRY*> folderEntries;
589 for(
const auto& [folderName, entry] : enumChildren( cfbFile, viewsStorage,
false ) )
591 if( folderEntries.emplace( folderName, entry ).second )
592 folders.push_back( folderName );
595 if(
const CFB::COMPOUND_FILE_ENTRY* directoryEntry =
600 std::vector<std::string> visibleFolders;
606 if( folderEntries.count( folder )
607 && std::find( visibleFolders.begin(), visibleFolders.end(), folder ) == visibleFolders.end() )
609 visibleFolders.push_back( std::move( folder ) );
613 folders = std::move( visibleFolders );
617 warnFn( wxString::Format(
_(
"The schematic folder directory could not be read (%s); all stored "
618 "folders are imported." ),
620 std::sort( folders.begin(), folders.end() );
625 std::sort( folders.begin(), folders.end() );
628 if( folders.empty() )
633 std::string rootFolder;
636 if( !schematicName.empty() )
638 for(
const std::string& folder : folders )
648 if( rootFolder.empty() )
653 warnFn(
_(
"The design does not name its root schematic; the first schematic "
654 "folder is used instead." ) );
658 warnFn( wxString::Format(
_(
"The design names '%s' as its root schematic, but no such "
659 "folder is present; the first schematic folder is used "
664 rootFolder = folders.front();
670 std::map<uint32_t, std::string> hierarchyLinks;
672 auto parseFolderPages = [&](
const std::string& aFolderName,
const CFB::COMPOUND_FILE_ENTRY* aFolderEntry,
673 std::vector<ORCAD_RAW_PAGE>& aOutPages )
675 const CFB::COMPOUND_FILE_ENTRY* pagesStorage =
678 std::vector<std::string> available;
679 std::map<std::string, const CFB::COMPOUND_FILE_ENTRY*> pageEntries;
683 for(
const auto& [pageName, entry] : enumChildren( cfbFile, pagesStorage,
true ) )
685 if( pageEntries.emplace( pageName, entry ).second )
686 available.push_back( pageName );
691 std::vector<std::string> ordered;
692 bool orderKnown =
false;
694 if(
const CFB::COMPOUND_FILE_ENTRY* orderEntry =
699 std::vector<char> orderData = readStream( cfbFile, orderEntry );
703 if( pageEntries.count( pageName )
704 && std::find( ordered.begin(), ordered.end(), pageName ) == ordered.end() )
706 ordered.push_back( pageName );
714 warnFn( wxString::Format(
_(
"The page display order for schematic folder '%s' could not be "
715 "read (%s); pages are imported in name order." ),
716 wxString::FromUTF8( aFolderName ), e.
What() ) );
723 for(
const std::string& pageName : available )
725 if( std::find( ordered.begin(), ordered.end(), pageName ) == ordered.end() )
726 ordered.push_back( pageName );
732 std::sort( ordered.begin(), ordered.end() );
735 for(
size_t pageIndex = 0; pageIndex < ordered.size(); ++pageIndex )
737 const std::string& pageName = ordered[pageIndex];
741 std::vector<char> pageData = readStream( cfbFile, pageEntries[pageName] );
745 aOutPages.push_back( std::move( page ) );
749 warnFn( wxString::Format(
_(
"Page '%s' could not be parsed and was "
751 wxString::FromUTF8( pageName ), e.
What() ) );
756 parseFolderPages( rootFolder, folderEntries[rootFolder], design.
pages );
759 if(
const CFB::COMPOUND_FILE_ENTRY* hierarchyEntry =
760 cfbFile.
FindStream( folderEntries[rootFolder], {
"Hierarchy",
"Hierarchy" } ) )
762 std::vector<char> hierarchyData = readStream( cfbFile, hierarchyEntry );
772 collectLinks( block.
scope );
780 if( design.
pages.empty() )
781 THROW_IO_ERROR(
_(
"No schematic pages could be read from the design." ) );
785 std::map<std::string, std::string> folderByLowerName;
787 for(
const auto& folderEntry : folderEntries )
788 folderByLowerName.emplace(
OrcadLower( folderEntry.first ), folderEntry.first );
790 for(
const auto& [dbId, childName] : hierarchyLinks )
797 auto childIt = folderByLowerName.find( key );
799 if( childIt != folderByLowerName.end() )
800 parseFolderPages( childIt->second, folderEntries[childIt->second], design.
childFolderPages[key] );
803 for(
const std::string& folder : folders )
811 parseFolderPages( folder, folderEntries[folder], pages );
826 auto it = hierarchyLinks.find( block.
dbId );
828 if( it != hierarchyLinks.end() )
834 readCisVariants( cfbFile, root, aProperties, design,
m_reporter );
836 catch(
const CFB::CFBException& e )
843 converter.
Convert( rootSheet );
883 const CFB::COMPOUND_FILE_ENTRY* root = reader.GetRootEntry();
885 const CFB::COMPOUND_FILE_ENTRY* libraryEntry = cfbFile.
FindStreamSingleLevel( root,
"Library",
true );
888 THROW_IO_ERROR(
_(
"The file is not an OrCAD Capture library (no 'Library' stream)." ) );
898 auto parseStream = [&](
const CFB::COMPOUND_FILE_ENTRY* aEntry,
const std::string& aStreamName,
899 bool aIsPackage,
bool aIsCache = false )
901 std::map<std::string, ORCAD_SYMBOL_DEF> extraSymbols;
902 std::map<std::string, ORCAD_PACKAGE> extraPackages;
906 std::vector<char> data = readStream( cfbFile, aEntry );
910 ORCAD_DIALECT packageDialect{ isV2 || !isLongFramedPackageStream( data ),
911 dialect.shortDisplayProp };
925 catch(
const std::exception& e )
929 warnFn( wxString::Format(
_(
"The library stream '%s' could not be read and was skipped (%s)." ),
930 wxString::FromUTF8( aStreamName ), wxString::FromUTF8( e.what() ) ) );
935 std::move( extraPackages ) );
941 if(
const CFB::COMPOUND_FILE_ENTRY* cacheEntry = cfbFile.
FindStreamSingleLevel( root,
"Cache",
true ) )
943 parseStream( cacheEntry,
"Cache",
false,
true );
948 for(
const char* storageName : {
"Symbols",
"Packages" } )
950 bool isPackage = std::string( storageName ) ==
"Packages";
956 for(
const auto& [streamName, entry] : enumChildren( cfbFile, storage,
true ) )
959 if( !streamName.empty() && streamName.front() ==
'$' )
962 parseStream( entry, streamName, isPackage );
967 catch(
const CFB::CFBException& e )
976 catch(
const std::exception& e )
979 warnFn( wxString::Format(
_(
"The OrCAD library could not be fully parsed (%s); some "
980 "symbols may be missing." ),
981 wxString::FromUTF8( e.what() ) ) );
987 std::vector<std::unique_ptr<LIB_SYMBOL>> built;
990 built.emplace_back( symbol );
992 return m_libCache[aLibraryPath] = std::move( built );
997 const std::map<std::string, UTF8>* )
999 for(
const std::unique_ptr<LIB_SYMBOL>& symbol :
loadOlbSymbols( aLibraryPath ) )
1000 aSymbolNameList.Add( symbol->GetName() );
1005 const std::map<std::string, UTF8>* )
1007 for(
const std::unique_ptr<LIB_SYMBOL>& symbol :
loadOlbSymbols( aLibraryPath ) )
1008 aSymbolList.push_back( symbol.get() );
1013 const std::map<std::string, UTF8>* )
1015 for(
const std::unique_ptr<LIB_SYMBOL>& symbol :
loadOlbSymbols( aLibraryPath ) )
1017 if( symbol->GetName() == aAliasName )
1018 return symbol.get();
const CFB::CompoundFileReader & GetCompoundFileReader() const
const CFB::COMPOUND_FILE_ENTRY * FindStreamSingleLevel(const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::string aName, const bool aIsStream) const
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
Define a library symbol object.
SCH_SHEET * Convert(SCH_SHEET *aRootSheet)
aRootSheet must have a screen and be registered on the schematic.
std::vector< LIB_SYMBOL * > BuildSymbolLibrary()
The caller owns the returned library symbols.
The caller owns the buffer.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
double m_DashedLineGapRatio
double m_DashedLineDashRatio
Holds all the data relating to one schematic.
void SetCurrentVariant(const wxString &aVariantName)
void AddVariant(const wxString &aVariantName)
SCHEMATIC_SETTINGS & Settings() const
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
Replace the top level sheets, rebuilding the hierarchy and connectivity around them.
SCH_SHEET_PATH & CurrentSheet() const
const std::vector< std::unique_ptr< LIB_SYMBOL > > & loadOlbSymbols(const wxString &aLibraryPath)
Parse an .OLB and build its KiCad library symbols, cached by library path.
std::map< wxString, std::vector< std::unique_ptr< LIB_SYMBOL > > > m_libCache
bool CanReadSchematicFile(const wxString &aFileName) const override
The .dsn extension also identifies SPECCTRA files.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
virtual bool CanReadSchematicFile(const wxString &aFileName) const
Checks if this SCH_IO can read the specified schematic file.
const KIID & GetUuid() const
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void SetFileName(const wxString &aFilename)
void SyncUuidToScreen()
Take the identity of the screen this sheet owns.
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_CANCELLED()
std::optional< wxString > fileHashMMH3(const wxString &aFilePath)
Calculates an MMH3 hash of a given file.
const std::vector< uint8_t > COMPOUND_FILE_HEADER
bool fileHasBinaryHeader(const wxString &aFilePath, const std::vector< uint8_t > &aHeader, size_t aOffset)
Check if a file starts with a defined binary header.
void OrcadMergeSymbolGeneralProperties(std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, const std::map< std::string, ORCAD_SYMBOL_DEF > &aMetadataSymbols)
void OrcadMergeCacheStreams(std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages, std::map< std::string, ORCAD_SYMBOL_DEF > &&aExtraSymbols, std::map< std::string, ORCAD_PACKAGE > &&aExtraPackages)
Merge the results of a 'Packages/<name>' stream (locally modified parts) into the main cache maps: a ...
void OrcadParseSymbolStream(const std::vector< char > &aData, const std::vector< std::string > &aStrings, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, ORCAD_DIALECT aDialect)
Throws IO_ERROR for invalid framing or trailing bytes.
void OrcadParseCache(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages, ORCAD_DIALECT aDialect)
The first entry is the default; later entries become variants.
void OrcadParsePackageStream(const std::vector< char > &aData, const std::vector< std::string > &aStrings, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages, ORCAD_DIALECT aDialect)
Package streams contain counted PartCells and LibraryParts, followed by one Package.
Parsers for the DSN 'Cache' stream and the 'Packages/<name>' streams: symbol definitions with graphic...
std::map< uint32_t, ORCAD_CIS_PROPERTIES > OrcadCisParsePropertyUpdates(const std::vector< char > &aData)
Occurrence id -> property overrides.
std::map< uint32_t, bool > OrcadCisParseMemberships(const std::vector< char > &aData)
Occurrence id -> installed state of each part in a group.
std::string OrcadCisSelectVariant(const std::vector< std::string > &aNames, const std::optional< std::string > &aRequested)
ORCAD_CIS_SCHEMATIC_INFO OrcadCisParseSchematicInfo(const std::vector< char > &aData)
std::vector< std::string > OrcadCisParseCountedList(const std::vector< char > &aData, uint8_t aSeparator)
std::map< std::string, std::map< uint32_t, ORCAD_CIS_PROPERTIES > > ORCAD_CIS_SCHEMATIC_INFO
std::map< std::string, std::string > ORCAD_CIS_PROPERTIES
std::pair< double, double > OrcadDashRatios(int aFormatVersionMajor)
ORCAD_LIBRARY_INFO OrcadParseLibrary(const std::vector< char > &aData)
The Library version selects the string-count width.
ORCAD_OCC_SCOPE OrcadReadOccurrenceTree(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn, ORCAD_DIALECT aDialect)
Returns occurrence references and child scopes.
ORCAD_RAW_PAGE OrcadParsePage(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn, ORCAD_DIALECT aDialect)
A modern body failure skips that structure.
std::vector< std::string > OrcadParseSchematicFolderOrder(const std::vector< char > &aData)
Unlisted Views storages can be stale.
std::vector< std::string > OrcadParsePageOrder(const std::vector< char > &aData, ORCAD_DIALECT aDialect)
Returns display order.
bool OrcadPageHasHierarchyBlocks(const ORCAD_RAW_PAGE &aPage)
True when the page contains hierarchical block instances (DrawnInstance, type 12).
std::function< void(const wxString &aMsg)> ORCAD_WARN_FN
Coordinates use DBU with Y down.
std::string OrcadLower(std::string_view aText)
Fold ASCII letters only.
wxString FromOrcadString(const std::string &aText)
Use an 8-bit fallback if Windows-1252 decoding fails.
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
std::string OrcadNormalizeCfbName(const std::string &aName)
std::string OrcadNormalizeCfbName(const std::string &aName)
A CIS BOM variant, keyed by part occurrence id.
std::map< uint32_t, bool > installed
std::map< uint32_t, std::map< std::string, std::string > > props
Child-folder pages are instantiated for each occurrence, with that occurrence's references.
std::vector< ORCAD_CIS_VARIANT > cisVariants
ORCAD_LIBRARY_INFO library
std::string sourceId
stable checksum of the input file
ORCAD_OCC_SCOPE occurrenceRoot
Occurrence references distinguish repeated placements of a child schematic.
std::map< std::string, ORCAD_SYMBOL_DEF > symbols
cache, keyed by cache name
std::map< std::string, std::vector< ORCAD_RAW_PAGE > > unreferencedFolderPages
Schematic folder pages not instantiated by the active hierarchy.
std::map< std::string, ORCAD_PACKAGE > packages
keyed by package name
std::string name
design (root schematic) name
std::map< std::string, std::vector< ORCAD_RAW_PAGE > > childFolderPages
Child schematic folder pages, keyed by lower-cased folder name; instantiated once per hierarchical bl...
std::string cisCurrentVariant
CIS variant selected for the import.
std::vector< ORCAD_RAW_PAGE > pages
root schematic folder pages
Legacy (pre-v3) files have short prefixes only, u16 string indices with a 0xFFFF sentinel and nested ...
The inline LibraryPart defines the block interface; placed pin records supply absolute positions.
std::string childName
child folder, when embedded
Free graphics use nested primitive coordinates.
std::map< std::string, std::string > props
std::vector< std::string > strings
global string table
std::string schematicName
root schematic folder name
Repeated child folders have separate scopes and reference designators.
uint32_t targetDbId
type-12 drawn-instance dbId on the parent page
ORCAD_OCC_SCOPE scope
the child's occurrences under this path
std::string childFolder
child schematic folder name
Each scope holds the references and child blocks for one instantiation path.
std::vector< ORCAD_OCC_BLOCK > blocks
hierarchical block occurrences
std::map< uint32_t, uint32_t > partOccurrenceIds
dbId -> part occurrence id
One parsed 'Views/<folder>/Pages/<page>' stream, raw structure lists in stream order.
size_t sourcePageCount
pages in the OrCAD folder
size_t sourcePageNumber
1-based within the OrCAD folder
std::vector< ORCAD_DRAWN_INSTANCE > blocks
hierarchical blocks (detection only)