122 wxString rootElementName = aLibraryFileName.GetName().Lower();
123 std::vector<wxString> uniqueAscNameKeys;
125 std::function<void(
const wxString& )> collectHierarchy;
126 collectHierarchy = [&](
const wxString& aAscNameKey )
128 uniqueAscNameKeys.push_back( aAscNameKey );
132 aReporter->
Report( wxString::Format(
_(
"Missing '%s' schematic file" ), aAscNameKey + wxS(
".asc" ) ),
142 for(
LTSPICE_FILE& newSubSchematicElement : newSubSchematicElements )
149 if( asyKey.IsEmpty() )
156 collectHierarchy( asyKey );
160 collectHierarchy( rootElementName );
163 std::map<wxString, SCH_SCREEN*> mapOfScreens;
166 for(
const wxString& elementName : uniqueAscNameKeys )
170 if( elementName == rootElementName )
177 mapOfScreens[elementName] = screen;
181 for(
const wxString& elementName : uniqueAscNameKeys )
192 SCH_SCREEN* screen = mapOfScreens[elementName];
195 const int margin =
grid * 10;
219 parser.
CreateItems( ascFile, screen, uniqueAscNameKeys, mapOfScreens, originOffset );
228 std::set<SCH_SCREEN*> visitedScreens;
230 std::function<void(
SCH_SCREEN*, std::map<wxString, wxString> )> fixLabelCase;
231 fixLabelCase = [&](
SCH_SCREEN* aScreen, std::map<wxString, wxString> aLabelMap )
238 wxString lower = lbl->GetText().Lower();
240 if( !aLabelMap.contains( lower ) && lbl->GetText() != lower )
241 aLabelMap[lower] = lbl->GetText();
250 wxString lower = lbl->GetText().Lower();
252 if( aLabelMap.contains( lower ) )
253 lbl->SetText( aLabelMap.at( lower ) );
259 if( visitedScreens.contains( sheetScreen ) )
262 visitedScreens.insert( sheetScreen );
264 std::map<wxString, wxString> childLabelMap;
267 childLabelMap[
pin->GetText().Lower()] =
pin->GetText();
269 fixLabelCase( sheetScreen, childLabelMap );
274 fixLabelCase( aRootSheet->
GetScreen(), {} );
279 std::sort( sheets.begin(), sheets.end(),
282 size_t len = std::min( a.size(), b.size() );
284 for( size_t i = 0; i < len; ++i )
286 SCH_SHEET* sheetA = a.at( i );
287 SCH_SHEET* sheetB = b.at( i );
289 if( sheetA->m_Uuid == sheetB->m_Uuid )
292 const SCH_FIELD* fieldA = sheetA->GetField( SCH_IO_LTSPICE_PARSER::LT_INSTNAME_FIELD );
293 const SCH_FIELD* fieldB = sheetB->GetField( SCH_IO_LTSPICE_PARSER::LT_INSTNAME_FIELD );
294 int cmp = StrNumCmp( fieldA ? fieldA->GetText() : wxString(),
295 fieldB ? fieldB->GetText() : wxString(), true );
300 return sheetA->m_Uuid < sheetB->m_Uuid;
308 sheets.SortByHierarchicalPageNumbers(
true );
309 sheets.CheckForMissingSymbolInstances( aSchematic->Project().GetProjectName() );
314 if(
path.size() <= 1 )
319 for(
size_t i = 1; i <
path.size(); ++i )
321 suffix += wxS(
"_" );
324 suffix += instNameField->GetText();
342 path.UpdateAllScreenReferences();
345 aSchematic->FixupJunctionsAfterImport();
350 std::map<wxString, wxString>& aMapOfAscFiles,
351 std::map<wxString, wxString>& aMapOfAsyFiles,
352 const std::vector<wxString>& aBaseDirs )
356 if( !aDir.IsOpened() )
359 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
363 wxFileName
path( aDir.GetName(), filename );
366 [&]( std::map<wxString, wxString>& aMapToLogTo,
const wxString& aKey )
368 if( aMapToLogTo.count( aKey ) )
372 m_reporter->Report( wxString::Format(
_(
"File at '%s' was ignored. Using previously "
373 "found file at '%s' instead." ),
380 aMapToLogTo.emplace( aKey,
path.GetFullPath() );
385 wxString extension =
path.GetExt().Lower();
387 for(
size_t i = 0; i < aBaseDirs.size() + 1; i++ )
391 for(
size_t j = i; j < aBaseDirs.size(); j++ )
392 alias << aBaseDirs[j].Lower() <<
'/';
394 alias <<
path.GetName().Lower();
396 if( extension == wxS(
"asc" ) )
397 logToMap( aMapOfAscFiles, alias );
398 else if( extension == wxS(
"asy" ) )
399 logToMap( aMapOfAsyFiles, alias );
402 cont = aDir.GetNext( &filename );
407 cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
411 wxFileName
path( aDir.GetName(), filename );
412 wxDir subDir(
path.GetFullPath() );
414 std::vector<wxString> newBase = aBaseDirs;
415 newBase.push_back( filename );
419 cont = aDir.GetNext( &filename );
661 const wxString& aAsyFileContent,
LT_ASC& aAscFile )
666 lt_symbol.
Name = aSymbolName;
670 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
674 wxArrayString tokens = wxSplit( line,
' ' );
676 if( tokens.IsEmpty() )
679 wxString element = tokens[0].Upper();
681 if( element ==
"LINE" )
685 wxString lineWidth = tokens[1];
686 wxString startPointX = tokens[2];
687 wxString startPointY = tokens[3];
688 wxString endPointX = tokens[4];
689 wxString endPointY = tokens[5];
693 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aSymbolName );
694 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aSymbolName );
696 int lineStyleNumber = 0;
698 if( tokens.size() == 7 )
700 wxString lineStyle = tokens[6];
701 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aSymbolName );
706 lt_symbol.
Lines.push_back( lt_line );
708 else if( element ==
"RECTANGLE" )
712 wxString lineWidth = tokens[1];
713 wxString botRightX = tokens[2];
714 wxString botRightY = tokens[3];
715 wxString topLeftX = tokens[4];
716 wxString topRightY = tokens[5];
723 int lineStyleNumber = 0;
725 if( tokens.size() == 7 )
727 wxString lineStyle = tokens[6];
728 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aSymbolName );
735 else if( element ==
"CIRCLE" )
743 wxString lineWidth = tokens[1];
744 wxString botRightX = tokens[2];
745 wxString botRightY = tokens[3];
746 wxString topLeftX = tokens[4];
747 wxString topRightY = tokens[5];
751 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aSymbolName );
752 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aSymbolName );
754 int lineStyleNumber = 0;
756 if( tokens.size() == 7 )
758 wxString lineStyle = tokens[6];
759 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aSymbolName );
766 else if( element ==
"ARC" )
775 wxString lineWidth = tokens[1];
776 wxString botRightX = tokens[2];
777 wxString botRightY = tokens[3];
778 wxString topLeftX = tokens[4];
779 wxString topRightY = tokens[5];
780 wxString arcStartPointX = tokens[6];
781 wxString arcStartPointY = tokens[7];
782 wxString arcEndPointX = tokens[8];
783 wxString arcEndPointY = tokens[9];
790 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aSymbolName );
792 int lineStyleNumber = 0;
794 if( tokens.size() == 11 )
796 wxString lineStyle = tokens[10];
797 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aSymbolName );
802 lt_symbol.
Arcs.push_back( arc );
804 else if( element ==
"WINDOW" )
808 wxString number = tokens[1];
809 wxString windowPosX = tokens[2];
810 wxString windowPosY = tokens[3];
811 wxString justification = tokens[4];
812 wxString fontSize = tokens[5];
824 lt_symbol.
Windows.push_back( window );
826 else if( element ==
"TEXT" )
832 wxString positionX = tokens[1];
833 wxString positionY = tokens[2];
834 wxString justification = tokens[3];
835 wxString fontSize = tokens[4];
836 wxString value = tokens[5];
839 text.Offset =
pointCheck( positionX, positionY, lineNumber, aSymbolName );
844 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
848 else if( element ==
"SYMATTR" )
854 wxString key = tokens[1];
855 wxString value = tokens[2];
857 if( value == wxS(
"\"\"" ) )
858 value = wxEmptyString;
862 else if( element ==
"PIN" )
866 wxString pinLocationX = tokens[1];
867 wxString pinLocationY = tokens[2];
868 wxString Justification = tokens[3];
869 wxString nameOffSet = tokens[4];
872 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aSymbolName );
876 lt_symbol.
Pins.push_back(
pin );
878 else if( element ==
"PINATTR" )
884 wxString
name = tokens[1];
885 wxString Value = tokens[2];
887 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
889 else if( element ==
"SYMBOLTYPE" )
893 wxString symbolType = tokens[1];
930 std::map<wxString, LT_ASC> ascFiles;
932 for(
const auto& [ fileName, contents ] : aAscFilesContent )
935 std::vector<LT_SYMBOL> symbolArray;
945 for( wxString line : wxSplit( contents,
'\n' ) )
949 wxArrayString tokens = wxSplit( line,
' ' );
951 if( tokens.IsEmpty() )
954 wxString element = tokens[0].Upper();
956 if( element ==
"SHEET" )
960 wxString sheetNumber = tokens[1];
961 wxString sheetWidth = tokens[2];
962 wxString sheetHeight = tokens[3];
967 else if( element ==
"SYMBOL" )
971 wxString symbolName = tokens[1];
972 wxString posX = tokens[2];
973 wxString posY = tokens[3];
974 wxString rotate_mirror_option = tokens[4];
976 symbolName.Replace(
'\\',
'/' );
984 wxString fullName = wxFileName( fileName ).GetFullName();
987 wxString::Format(
_(
"Missing symbol file '%s.asy', referenced from '%s' at line %d" ),
988 symbolName, fullName, lineNumber ) );
1001 ascFile.
Symbols.push_back( lt_symbol );
1014 ascFile.
Symbols.push_back( lt_symbol );
1018 else if( element ==
"WIRE" )
1022 wxString startPointX = tokens[1];
1023 wxString startPointY = tokens[2];
1024 wxString endPointX = tokens[3];
1025 wxString endPointY = tokens[4];
1028 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1029 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1031 ascFile.
Wires.push_back( wire );
1035 else if( element ==
"FLAG" )
1039 wxString posX = tokens[1];
1040 wxString posY = tokens[2];
1041 wxString
name = tokens[3];
1051 else if( element ==
"DATAFLAG" )
1055 wxString posX = tokens[1];
1056 wxString posY = tokens[2];
1057 wxString expression = tokens[3];
1061 flag.Expression = expression;
1067 else if( element ==
"WINDOW" )
1071 wxString number = tokens[1];
1072 wxString windowPosX = tokens[2];
1073 wxString windowPosY = tokens[3];
1074 wxString justification = tokens[4];
1075 wxString fontSize = tokens[5];
1079 int windowNumber =
integerCheck( number, lineNumber, fileName );
1086 window = &candidate;
1094 window = &symbol->
Windows.back();
1104 else if( element ==
"SYMATTR" )
1110 wxString
name = tokens[1];
1111 wxString value = tokens[2];
1113 if( value == wxS(
"\"\"" ) )
1114 value = wxEmptyString;
1116 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
1118 else if( element ==
"LINE" )
1122 wxString lineWidth = tokens[1];
1123 wxString startPointX = tokens[2];
1124 wxString startPointY = tokens[3];
1125 wxString endPointX = tokens[4];
1126 wxString endPointY = tokens[5];
1130 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1131 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1133 int lineStyleNumber = 0;
1135 if( tokens.size() == 7 )
1137 wxString lineStyle = tokens[6];
1138 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1143 ascFile.
Lines.push_back( lt_line );
1147 else if( element ==
"RECTANGLE" )
1152 wxString botRightX = tokens[2];
1153 wxString botRightY = tokens[3];
1154 wxString topLeftX = tokens[4];
1155 wxString topRightY = tokens[5];
1162 int lineStyleNumber = 0;
1164 if( tokens.size() == 7 )
1166 wxString lineStyle = tokens[6];
1167 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1176 else if( element ==
"CIRCLE" )
1180 wxString lineWidth = tokens[1];
1181 wxString botRightX = tokens[2];
1182 wxString botRightY = tokens[3];
1183 wxString topLeftX = tokens[4];
1184 wxString topRightY = tokens[5];
1188 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1191 int lineStyleNumber = 0;
1193 if( tokens.size() == 7 )
1195 wxString lineStyle = tokens[6];
1196 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1205 else if( element ==
"ARC" )
1214 wxString lineWidth = tokens[1];
1215 wxString botRightX = tokens[2];
1216 wxString botRightY = tokens[3];
1217 wxString topLeftX = tokens[4];
1218 wxString topRightY = tokens[5];
1219 wxString arcStartPointX = tokens[6];
1220 wxString arcStartPointY = tokens[7];
1221 wxString arcEndPointX = tokens[8];
1222 wxString arcEndPointY = tokens[9];
1228 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1231 int lineStyleNumber = 0;
1233 if( tokens.size() == 11 )
1235 wxString lineStyle = tokens[10];
1236 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1241 ascFile.
Arcs.push_back( arc );
1245 else if( element ==
"IOPIN" )
1249 wxString pinLocationX = tokens[1];
1250 wxString pinLocationY = tokens[2];
1251 wxString pinPolarity = tokens[3];
1257 ascFile.
Iopins.push_back( iopin );
1260 else if( element ==
"TEXT" )
1266 wxString positionX = tokens[1];
1267 wxString positionY = tokens[2];
1268 wxString justification = tokens[3];
1269 wxString fontSize = tokens[4];
1270 wxString value = tokens[5];
1273 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1277 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1278 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1279 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1280 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1284 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1289 else if( element ==
"BUSTAP" )
1293 wxString startPointX = tokens[1];
1294 wxString startPointY = tokens[2];
1295 wxString endPointX = tokens[3];
1296 wxString endPointY = tokens[4];
1299 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1300 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1302 ascFile.
Bustap.push_back( bustap );
1306 else if( element ==
"VERSION" )
1308 wxString versionNumber = tokens[1];
1309 if( versionNumber.Contains(
'.' ) )
1311 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1312 wxString minorStr = versionNumber.AfterFirst(
'.' );
1325 ascFiles[fileName] = std::move( ascFile );