190 if (obj == null) |
190 if (obj == null) |
191 continue; |
191 continue; |
192 |
192 |
193 LDSubfilePtr ref = obj.toStrongRef().dynamicCast<LDSubfile>(); |
193 LDSubfilePtr ref = obj.toStrongRef().dynamicCast<LDSubfile>(); |
194 |
194 |
195 if (ref != null && ref->fileInfo() == self()) |
195 if (ref != null and ref->fileInfo() == self()) |
196 count++; |
196 count++; |
197 } |
197 } |
198 } |
198 } |
199 |
199 |
200 if (g_win != null) |
200 if (g_win != null) |
201 g_win->updateDocumentList(); |
201 g_win->updateDocumentList(); |
202 |
202 |
203 // If the current document just became implicit (e.g. it was 'closed'), |
203 // If the current document just became implicit (e.g. it was 'closed'), |
204 // we need to get a new current document. |
204 // we need to get a new current document. |
205 if (current() == self() && isImplicit()) |
205 if (current() == self() and isImplicit()) |
206 { |
206 { |
207 if (explicitDocuments().isEmpty()) |
207 if (explicitDocuments().isEmpty()) |
208 newFile(); |
208 newFile(); |
209 else |
209 else |
210 setCurrent (explicitDocuments().first()); |
210 setCurrent (explicitDocuments().first()); |
223 // |
223 // |
224 LDDocumentPtr findDocument (QString name) |
224 LDDocumentPtr findDocument (QString name) |
225 { |
225 { |
226 for (LDDocumentWeakPtr file : g_allDocuments) |
226 for (LDDocumentWeakPtr file : g_allDocuments) |
227 { |
227 { |
228 if (file != null && file.toStrongRef()->name() == name) |
228 if (file != null and file.toStrongRef()->name() == name) |
229 return file.toStrongRef(); |
229 return file.toStrongRef(); |
230 } |
230 } |
231 |
231 |
232 return LDDocumentPtr(); |
232 return LDDocumentPtr(); |
233 } |
233 } |
406 } |
406 } |
407 |
407 |
408 // Parse up to 300 lines per iteration |
408 // Parse up to 300 lines per iteration |
409 int max = i + 300; |
409 int max = i + 300; |
410 |
410 |
411 for (; i < max && i < (int) lines().size(); ++i) |
411 for (; i < max and i < (int) lines().size(); ++i) |
412 { |
412 { |
413 QString line = lines()[i]; |
413 QString line = lines()[i]; |
414 |
414 |
415 // Trim the trailing newline |
415 // Trim the trailing newline |
416 QChar c; |
416 QChar c; |
417 |
417 |
418 while (line.endsWith ("\n") || line.endsWith ("\r")) |
418 while (line.endsWith ("\n") or line.endsWith ("\r")) |
419 line.chop (1); |
419 line.chop (1); |
420 |
420 |
421 LDObjectPtr obj = parseLine (line); |
421 LDObjectPtr obj = parseLine (line); |
422 |
422 |
423 // Check for parse errors and warn about tthem |
423 // Check for parse errors and warn about tthem |
697 } |
697 } |
698 } |
698 } |
699 |
699 |
700 // We cannot open this file if the document this would replace is not |
700 // We cannot open this file if the document this would replace is not |
701 // safe to close. |
701 // safe to close. |
702 if (documentToReplace != null && not documentToReplace->isSafeToClose()) |
702 if (documentToReplace != null and not documentToReplace->isSafeToClose()) |
703 return; |
703 return; |
704 |
704 |
705 g_loadingMainFile = true; |
705 g_loadingMainFile = true; |
706 |
706 |
707 // If we're replacing an existing document, clear the document and |
707 // If we're replacing an existing document, clear the document and |
753 path = fullPath(); |
753 path = fullPath(); |
754 |
754 |
755 // If the second object in the list holds the file name, update that now. |
755 // If the second object in the list holds the file name, update that now. |
756 LDObjectPtr nameObject = getObject (1); |
756 LDObjectPtr nameObject = getObject (1); |
757 |
757 |
758 if (nameObject != null && nameObject->type() == OBJ_Comment) |
758 if (nameObject != null and nameObject->type() == OBJ_Comment) |
759 { |
759 { |
760 LDCommentPtr nameComment = nameObject.staticCast<LDComment>(); |
760 LDCommentPtr nameComment = nameObject.staticCast<LDComment>(); |
761 |
761 |
762 if (nameComment->text().left (6) == "Name: ") |
762 if (nameComment->text().left (6) == "Name: ") |
763 { |
763 { |
836 { |
836 { |
837 // Check for floating point |
837 // Check for floating point |
838 tokens[i].toDouble (&ok); |
838 tokens[i].toDouble (&ok); |
839 |
839 |
840 // Also check scientific notation, e.g. 7.99361e-15 |
840 // Also check scientific notation, e.g. 7.99361e-15 |
841 if (not ok && not scient.exactMatch (tokens[i])) |
841 if (not ok and not scient.exactMatch (tokens[i])) |
842 { |
842 { |
843 throw QString (format ("Token #%1 was `%2`, expected a number (matched length: %3)", |
843 throw QString (format ("Token #%1 was `%2`, expected a number (matched length: %3)", |
844 (i + 1), tokens[i], scient.matchedLength())); |
844 (i + 1), tokens[i], scient.matchedLength())); |
845 } |
845 } |
846 } |
846 } |
885 { |
885 { |
886 // Line was empty, or only consisted of whitespace |
886 // Line was empty, or only consisted of whitespace |
887 return spawn<LDEmpty>(); |
887 return spawn<LDEmpty>(); |
888 } |
888 } |
889 |
889 |
890 if (tokens[0].length() != 1 || not tokens[0][0].isDigit()) |
890 if (tokens[0].length() != 1 or not tokens[0][0].isDigit()) |
891 throw QString ("Illogical line code"); |
891 throw QString ("Illogical line code"); |
892 |
892 |
893 int num = tokens[0][0].digitValue(); |
893 int num = tokens[0][0].digitValue(); |
894 |
894 |
895 switch (num) |
895 switch (num) |
899 // Comment |
899 // Comment |
900 QString commentText (line.mid (line.indexOf ("0") + 2)); |
900 QString commentText (line.mid (line.indexOf ("0") + 2)); |
901 QString commentTextSimplified (commentText.simplified()); |
901 QString commentTextSimplified (commentText.simplified()); |
902 |
902 |
903 // Handle BFC statements |
903 // Handle BFC statements |
904 if (tokens.size() > 2 && tokens[1] == "BFC") |
904 if (tokens.size() > 2 and tokens[1] == "BFC") |
905 { |
905 { |
906 for (int i = 0; i < LDBFC::NumStatements; ++i) |
906 for (int i = 0; i < LDBFC::NumStatements; ++i) |
907 if (commentTextSimplified == format ("BFC %1", LDBFC::k_statementStrings [i])) |
907 if (commentTextSimplified == format ("BFC %1", LDBFC::k_statementStrings [i])) |
908 return spawn<LDBFC> ((LDBFC::Statement) i); |
908 return spawn<LDBFC> ((LDBFC::Statement) i); |
909 |
909 |
916 return spawn<LDBFC> (LDBFC::Clip); |
916 return spawn<LDBFC> (LDBFC::Clip); |
917 elif (commentTextSimplified == "BFC CERTIFY NOCLIP") |
917 elif (commentTextSimplified == "BFC CERTIFY NOCLIP") |
918 return spawn<LDBFC> (LDBFC::NoClip); |
918 return spawn<LDBFC> (LDBFC::NoClip); |
919 } |
919 } |
920 |
920 |
921 if (tokens.size() > 2 && tokens[1] == "!LDFORGE") |
921 if (tokens.size() > 2 and tokens[1] == "!LDFORGE") |
922 { |
922 { |
923 // Handle LDForge-specific types, they're embedded into comments too |
923 // Handle LDForge-specific types, they're embedded into comments too |
924 if (tokens[2] == "VERTEX") |
924 if (tokens[2] == "VERTEX") |
925 { |
925 { |
926 // Vertex (0 !LDFORGE VERTEX) |
926 // Vertex (0 !LDFORGE VERTEX) |
1161 { |
1161 { |
1162 int idx = obj->lineNumber(); |
1162 int idx = obj->lineNumber(); |
1163 obj->deselect(); |
1163 obj->deselect(); |
1164 assert (m_objects[idx] == obj); |
1164 assert (m_objects[idx] == obj); |
1165 |
1165 |
1166 if (not isImplicit() && not (flags() & DOCF_IsBeingDestroyed)) |
1166 if (not isImplicit() and not (flags() & DOCF_IsBeingDestroyed)) |
1167 { |
1167 { |
1168 history()->add (new DelHistory (idx, obj)); |
1168 history()->add (new DelHistory (idx, obj)); |
1169 _objectVertices.remove (obj); |
1169 _objectVertices.remove (obj); |
1170 } |
1170 } |
1171 |
1171 |
1188 |
1188 |
1189 // ============================================================================= |
1189 // ============================================================================= |
1190 // |
1190 // |
1191 void LDDocument::setObject (int idx, LDObjectPtr obj) |
1191 void LDDocument::setObject (int idx, LDObjectPtr obj) |
1192 { |
1192 { |
1193 assert (idx >= 0 && idx < m_objects.size()); |
1193 assert (idx >= 0 and idx < m_objects.size()); |
1194 |
1194 |
1195 // Mark this change to history |
1195 // Mark this change to history |
1196 if (not m_history->isIgnoring()) |
1196 if (not m_history->isIgnoring()) |
1197 { |
1197 { |
1198 QString oldcode = getObject (idx)->asText(); |
1198 QString oldcode = getObject (idx)->asText(); |
1229 |
1229 |
1230 // ============================================================================= |
1230 // ============================================================================= |
1231 // |
1231 // |
1232 bool LDDocument::hasUnsavedChanges() const |
1232 bool LDDocument::hasUnsavedChanges() const |
1233 { |
1233 { |
1234 return not isImplicit() && history()->position() != savePosition(); |
1234 return not isImplicit() and history()->position() != savePosition(); |
1235 } |
1235 } |
1236 |
1236 |
1237 // ============================================================================= |
1237 // ============================================================================= |
1238 // |
1238 // |
1239 QString LDDocument::getDisplayName() |
1239 QString LDDocument::getDisplayName() |
1311 LDObjectList LDDocument::inlineContents (bool deep, bool renderinline) |
1311 LDObjectList LDDocument::inlineContents (bool deep, bool renderinline) |
1312 { |
1312 { |
1313 // Possibly substitute with logoed studs: |
1313 // Possibly substitute with logoed studs: |
1314 // stud.dat -> stud-logo.dat |
1314 // stud.dat -> stud-logo.dat |
1315 // stud2.dat -> stud-logo2.dat |
1315 // stud2.dat -> stud-logo2.dat |
1316 if (cfg::useLogoStuds && renderinline) |
1316 if (cfg::useLogoStuds and renderinline) |
1317 { |
1317 { |
1318 // Ensure logoed studs are loaded first |
1318 // Ensure logoed studs are loaded first |
1319 loadLogoedStuds(); |
1319 loadLogoedStuds(); |
1320 |
1320 |
1321 if (name() == "stud.dat" && g_logoedStud != null) |
1321 if (name() == "stud.dat" and g_logoedStud != null) |
1322 return g_logoedStud->inlineContents (deep, renderinline); |
1322 return g_logoedStud->inlineContents (deep, renderinline); |
1323 elif (name() == "stud2.dat" && g_logoedStud2 != null) |
1323 elif (name() == "stud2.dat" and g_logoedStud2 != null) |
1324 return g_logoedStud2->inlineContents (deep, renderinline); |
1324 return g_logoedStud2->inlineContents (deep, renderinline); |
1325 } |
1325 } |
1326 |
1326 |
1327 LDObjectList objs, objcache; |
1327 LDObjectList objs, objcache; |
1328 |
1328 |
1332 if (not obj->isScemantic()) |
1332 if (not obj->isScemantic()) |
1333 continue; |
1333 continue; |
1334 |
1334 |
1335 // Got another sub-file reference, inline it if we're deep-inlining. If not, |
1335 // Got another sub-file reference, inline it if we're deep-inlining. If not, |
1336 // just add it into the objects normally. Yay, recursion! |
1336 // just add it into the objects normally. Yay, recursion! |
1337 if (deep == true && obj->type() == OBJ_Subfile) |
1337 if (deep == true and obj->type() == OBJ_Subfile) |
1338 { |
1338 { |
1339 for (LDObjectPtr otherobj : obj.staticCast<LDSubfile>()->inlineContents (deep, renderinline)) |
1339 for (LDObjectPtr otherobj : obj.staticCast<LDSubfile>()->inlineContents (deep, renderinline)) |
1340 objs << otherobj; |
1340 objs << otherobj; |
1341 } |
1341 } |
1342 else |
1342 else |
1361 // ============================================================================= |
1361 // ============================================================================= |
1362 void LDDocument::setCurrent (LDDocumentPtr f) |
1362 void LDDocument::setCurrent (LDDocumentPtr f) |
1363 { |
1363 { |
1364 // Implicit files were loaded for caching purposes and must never be set |
1364 // Implicit files were loaded for caching purposes and must never be set |
1365 // current. |
1365 // current. |
1366 if (f != null && f->isImplicit()) |
1366 if (f != null and f->isImplicit()) |
1367 return; |
1367 return; |
1368 |
1368 |
1369 g_currentDocument = f; |
1369 g_currentDocument = f; |
1370 |
1370 |
1371 if (g_win && f) |
1371 if (g_win and f) |
1372 { |
1372 { |
1373 // A ton of stuff needs to be updated |
1373 // A ton of stuff needs to be updated |
1374 g_win->updateDocumentListItem (f); |
1374 g_win->updateDocumentListItem (f); |
1375 g_win->buildObjList(); |
1375 g_win->buildObjList(); |
1376 g_win->updateTitle(); |
1376 g_win->updateTitle(); |
1391 // This little beauty closes the initial file that was open at first when opening |
1391 // This little beauty closes the initial file that was open at first when opening |
1392 // a new file over it. |
1392 // a new file over it. |
1393 // ============================================================================= |
1393 // ============================================================================= |
1394 void LDDocument::closeInitialFile() |
1394 void LDDocument::closeInitialFile() |
1395 { |
1395 { |
1396 if (g_explicitDocuments.size() == 2 && |
1396 if (g_explicitDocuments.size() == 2 and |
1397 g_explicitDocuments[0]->name().isEmpty() && |
1397 g_explicitDocuments[0]->name().isEmpty() and |
1398 not g_explicitDocuments[1]->name().isEmpty() && |
1398 not g_explicitDocuments[1]->name().isEmpty() and |
1399 not g_explicitDocuments[0]->hasUnsavedChanges()) |
1399 not g_explicitDocuments[0]->hasUnsavedChanges()) |
1400 { |
1400 { |
1401 g_explicitDocuments[0]->dismiss(); |
1401 g_explicitDocuments[0]->dismiss(); |
1402 } |
1402 } |
1403 } |
1403 } |
1404 |
1404 |
1405 // ============================================================================= |
1405 // ============================================================================= |
1406 // |
1406 // |
1407 void loadLogoedStuds() |
1407 void loadLogoedStuds() |
1408 { |
1408 { |
1409 if (g_logoedStud && g_logoedStud2) |
1409 if (g_logoedStud and g_logoedStud2) |
1410 return; |
1410 return; |
1411 |
1411 |
1412 g_logoedStud = openDocument ("stud-logo.dat", true, true); |
1412 g_logoedStud = openDocument ("stud-logo.dat", true, true); |
1413 g_logoedStud2 = openDocument ("stud2-logo.dat", true, true); |
1413 g_logoedStud2 = openDocument ("stud2-logo.dat", true, true); |
1414 |
1414 |
1462 // |
1462 // |
1463 void LDDocument::swapObjects (LDObjectPtr one, LDObjectPtr other) |
1463 void LDDocument::swapObjects (LDObjectPtr one, LDObjectPtr other) |
1464 { |
1464 { |
1465 int a = m_objects.indexOf (one); |
1465 int a = m_objects.indexOf (one); |
1466 int b = m_objects.indexOf (other); |
1466 int b = m_objects.indexOf (other); |
1467 assert (a != b && a != -1 && b != -1); |
1467 assert (a != b and a != -1 and b != -1); |
1468 m_objects[b] = one; |
1468 m_objects[b] = one; |
1469 m_objects[a] = other; |
1469 m_objects[a] = other; |
1470 addToHistory (new SwapHistory (one->id(), other->id())); |
1470 addToHistory (new SwapHistory (one->id(), other->id())); |
1471 } |
1471 } |
1472 |
1472 |