Ensure that loaded files always have a style and dialogue line

Fixes crashes and general brokenness when opening invalid files.

Originally committed to SVN as r6479.
This commit is contained in:
Thomas Goyne 2012-02-16 21:21:35 +00:00
parent fc64bcaa36
commit e5e2b84b15
3 changed files with 48 additions and 28 deletions

View file

@ -89,6 +89,24 @@ void AssFile::Load(const wxString &_filename, wxString charset, bool addToRecent
AssFile temp; AssFile temp;
reader->ReadFile(&temp, _filename, charset); reader->ReadFile(&temp, _filename, charset);
bool found_style = false;
bool found_dialogue = false;
// Check if the file has at least one style and at least one dialogue line
for (entryIter it = temp.Line.begin(); it != temp.Line.end(); ++it) {
ASS_EntryType type = (*it)->GetType();
if (type == ENTRY_STYLE) found_style = true;
if (type == ENTRY_DIALOGUE) found_dialogue = true;
if (found_style && found_dialogue) break;
}
// And if it doesn't add defaults for each
if (!found_style)
temp.InsertStyle(new AssStyle);
if (!found_dialogue)
temp.InsertDialogue(new AssDialogue);
swap(temp); swap(temp);
} }
catch (agi::UserCancelException const&) { catch (agi::UserCancelException const&) {
@ -399,14 +417,14 @@ void AssFile::LoadDefault(bool defline) {
AddLine(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), &version, &attach); AddLine(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), &version, &attach);
AddLine(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), &version, &attach); AddLine(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), &version, &attach);
} }
AddLine("[V4+ Styles]", &version, &attach);
AddLine("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", &version, &attach); InsertStyle(new AssStyle);
AddLine(AssStyle().GetEntryData(), &version, &attach);
AddLine("[Events]", &version, &attach); AddLine("[Events]", &version, &attach);
AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", &version, &attach); AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", &version, &attach);
if (defline) if (defline)
AddLine(AssDialogue().GetEntryData(), &version, &attach); Line.push_back(new AssDialogue);
autosavedCommitId = savedCommitId = commitId + 1; autosavedCommitId = savedCommitId = commitId + 1;
Commit("", COMMIT_NEW); Commit("", COMMIT_NEW);
@ -436,16 +454,24 @@ AssFile& AssFile::operator=(AssFile from) {
return *this; return *this;
} }
void AssFile::InsertStyle(AssStyle *style) { static bool try_insert(std::list<AssEntry*> &lines, AssEntry *entry) {
if (lines.empty()) return false;
// Search for insertion point // Search for insertion point
std::list<AssEntry*>::iterator it = Line.end(); std::list<AssEntry*>::iterator it = lines.end();
do { do {
--it; --it;
if ((*it)->group == style->group) { if ((*it)->group == entry->group) {
Line.insert(++it, style); lines.insert(++it, entry);
return; return true;
} }
} while (it != Line.begin()); } while (it != lines.begin());
return false;
}
void AssFile::InsertStyle(AssStyle *style) {
if (try_insert(Line, style)) return;
// No styles found, add them // No styles found, add them
Line.push_back(new AssEntry("[V4+ Styles]", "[V4+ Styles]")); Line.push_back(new AssEntry("[V4+ Styles]", "[V4+ Styles]"));
@ -454,15 +480,7 @@ void AssFile::InsertStyle(AssStyle *style) {
} }
void AssFile::InsertAttachment(AssAttachment *attach) { void AssFile::InsertAttachment(AssAttachment *attach) {
// Search for insertion point if (try_insert(Line, attach)) return;
std::list<AssEntry*>::iterator it = Line.end();
do {
--it;
if ((*it)->group == attach->group) {
Line.insert(++it, attach);
return;
}
} while (it != Line.begin());
// Didn't find a group of the appropriate type so create it // Didn't find a group of the appropriate type so create it
Line.push_back(new AssEntry(attach->group, attach->group)); Line.push_back(new AssEntry(attach->group, attach->group));
@ -482,6 +500,15 @@ void AssFile::InsertAttachment(wxString filename) {
InsertAttachment(newAttach.release()); InsertAttachment(newAttach.release());
} }
void AssFile::InsertDialogue(AssDialogue *diag) {
if (try_insert(Line, diag)) return;
// Didn't find a group of the appropriate type so create it
Line.push_back(new AssEntry("[Events]", "[Events]"));
Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]"));
Line.push_back(diag);
}
wxString AssFile::GetScriptInfo(wxString key) { wxString AssFile::GetScriptInfo(wxString key) {
key.MakeLower(); key.MakeLower();
key += ":"; key += ":";

View file

@ -111,6 +111,8 @@ public:
void InsertAttachment(AssAttachment *attach); void InsertAttachment(AssAttachment *attach);
/// Attach a file to the ass file /// Attach a file to the ass file
void InsertAttachment(wxString filename); void InsertAttachment(wxString filename);
/// Add a dialogue line to the file
void InsertDialogue(AssDialogue *diag);
/// Get the names of all of the styles available /// Get the names of all of the styles available
wxArrayString GetStyles(); wxArrayString GetStyles();
/// @brief Get a style by name /// @brief Get a style by name

View file

@ -79,7 +79,6 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
wxString actor; wxString actor;
wxString separator = lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString()); wxString separator = lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString());
wxString comment = lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString()); wxString comment = lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString());
int lines = 0;
// Parse file // Parse file
while (file.HasMoreLines()) { while (file.HasMoreLines()) {
@ -125,14 +124,6 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
// Adds line // Adds line
target->Line.push_back(line); target->Line.push_back(line);
lines++;
}
// No lines?
if (lines == 0) {
AssDialogue *line = new AssDialogue;
line->End = OPT_GET("Timing/Default Duration")->GetInt();
target->Line.push_back(line);
} }
} }