From e5e2b84b15f0e5b7aff432f6377b262a79909ae2 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 16 Feb 2012 21:21:35 +0000 Subject: [PATCH] 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. --- aegisub/src/ass_file.cpp | 65 ++++++++++++++++++++--------- aegisub/src/ass_file.h | 2 + aegisub/src/subtitle_format_txt.cpp | 9 ---- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index ca3cd6cc3..4437ab9c3 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -89,6 +89,24 @@ void AssFile::Load(const wxString &_filename, wxString charset, bool addToRecent AssFile temp; 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); } 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("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); - AddLine(AssStyle().GetEntryData(), &version, &attach); + + InsertStyle(new AssStyle); + AddLine("[Events]", &version, &attach); AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", &version, &attach); if (defline) - AddLine(AssDialogue().GetEntryData(), &version, &attach); + Line.push_back(new AssDialogue); autosavedCommitId = savedCommitId = commitId + 1; Commit("", COMMIT_NEW); @@ -436,16 +454,24 @@ AssFile& AssFile::operator=(AssFile from) { return *this; } -void AssFile::InsertStyle(AssStyle *style) { +static bool try_insert(std::list &lines, AssEntry *entry) { + if (lines.empty()) return false; + // Search for insertion point - std::list::iterator it = Line.end(); + std::list::iterator it = lines.end(); do { --it; - if ((*it)->group == style->group) { - Line.insert(++it, style); - return; + if ((*it)->group == entry->group) { + lines.insert(++it, entry); + 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 Line.push_back(new AssEntry("[V4+ Styles]", "[V4+ Styles]")); @@ -454,15 +480,7 @@ void AssFile::InsertStyle(AssStyle *style) { } void AssFile::InsertAttachment(AssAttachment *attach) { - // Search for insertion point - std::list::iterator it = Line.end(); - do { - --it; - if ((*it)->group == attach->group) { - Line.insert(++it, attach); - return; - } - } while (it != Line.begin()); + if (try_insert(Line, attach)) return; // Didn't find a group of the appropriate type so create it Line.push_back(new AssEntry(attach->group, attach->group)); @@ -482,6 +500,15 @@ void AssFile::InsertAttachment(wxString filename) { 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) { key.MakeLower(); key += ":"; diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index 112ae1003..53b179f6d 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -111,6 +111,8 @@ public: void InsertAttachment(AssAttachment *attach); /// Attach a file to the ass file void InsertAttachment(wxString filename); + /// Add a dialogue line to the file + void InsertDialogue(AssDialogue *diag); /// Get the names of all of the styles available wxArrayString GetStyles(); /// @brief Get a style by name diff --git a/aegisub/src/subtitle_format_txt.cpp b/aegisub/src/subtitle_format_txt.cpp index 445547c03..5ae728053 100644 --- a/aegisub/src/subtitle_format_txt.cpp +++ b/aegisub/src/subtitle_format_txt.cpp @@ -79,7 +79,6 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt wxString actor; wxString separator = lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString()); wxString comment = lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString()); - int lines = 0; // Parse file while (file.HasMoreLines()) { @@ -125,14 +124,6 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt // Adds 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); } }