From 805481315ea4cfda5167352872e0908d543e22c7 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 7 Mar 2014 09:02:24 -0800 Subject: [PATCH] Split AssFile into separate lists for each section --- aegisub/src/ass_file.cpp | 87 ++++++++------------- aegisub/src/ass_file.h | 7 +- aegisub/src/ass_karaoke.cpp | 4 +- aegisub/src/ass_parser.cpp | 20 ++--- aegisub/src/ass_parser.h | 5 -- aegisub/src/audio_timing_dialogue.cpp | 14 ++-- aegisub/src/auto4_lua.cpp | 26 +++--- aegisub/src/auto4_lua.h | 2 +- aegisub/src/auto4_lua_assfile.cpp | 40 +++++++--- aegisub/src/base_grid.cpp | 2 +- aegisub/src/command/edit.cpp | 36 ++++----- aegisub/src/command/grid.cpp | 8 +- aegisub/src/command/subtitle.cpp | 29 ++++--- aegisub/src/command/time.cpp | 4 +- aegisub/src/dialog_attachments.cpp | 2 +- aegisub/src/dialog_kara_timing_copy.cpp | 8 +- aegisub/src/dialog_selection.cpp | 2 +- aegisub/src/dialog_shift_times.cpp | 2 +- aegisub/src/dialog_spellchecker.cpp | 6 +- aegisub/src/dialog_style_editor.cpp | 4 +- aegisub/src/dialog_style_manager.cpp | 12 +-- aegisub/src/dialog_timing_processor.cpp | 4 +- aegisub/src/dialog_translation.cpp | 8 +- aegisub/src/export_fixstyle.cpp | 2 +- aegisub/src/export_framerate.cpp | 2 +- aegisub/src/font_file_lister.cpp | 4 +- aegisub/src/resolution_resampler.cpp | 4 +- aegisub/src/search_replace_engine.cpp | 8 +- aegisub/src/subs_controller.cpp | 72 ++++++----------- aegisub/src/subs_edit_box.cpp | 7 +- aegisub/src/subs_edit_box.h | 5 +- aegisub/src/subs_preview.cpp | 4 +- aegisub/src/subtitle_format.cpp | 57 ++++++-------- aegisub/src/subtitle_format.h | 2 - aegisub/src/subtitle_format_ass.cpp | 25 +++--- aegisub/src/subtitle_format_ebu3264.cpp | 4 +- aegisub/src/subtitle_format_encore.cpp | 2 +- aegisub/src/subtitle_format_microdvd.cpp | 4 +- aegisub/src/subtitle_format_srt.cpp | 37 ++++----- aegisub/src/subtitle_format_transtation.cpp | 2 +- aegisub/src/subtitle_format_ttxt.cpp | 10 +-- aegisub/src/subtitle_format_txt.cpp | 6 +- aegisub/src/subtitles_provider_libass.cpp | 18 +++-- aegisub/src/threaded_frame_source.cpp | 18 ++--- aegisub/src/visual_tool_drag.cpp | 4 +- 45 files changed, 288 insertions(+), 341 deletions(-) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index 025b86441..90671e469 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -42,78 +42,55 @@ #include "options.h" #include "utils.h" -#include #include #include #include #include -namespace std { - template<> - void swap(AssFile &lft, AssFile &rgt) { - lft.swap(rgt); - } -} - AssFile::~AssFile() { - auto copy = new EntryList; - copy->swap(Line); - agi::dispatch::Background().Async([=]{ - copy->clear_and_dispose([](AssEntry *e) { delete e; }); - delete copy; - }); + Info.clear_and_dispose([](AssEntry *e) { delete e; }); + Styles.clear_and_dispose([](AssEntry *e) { delete e; }); + Events.clear_and_dispose([](AssEntry *e) { delete e; }); + Attachments.clear_and_dispose([](AssEntry *e) { delete e; }); } void AssFile::LoadDefault(bool defline) { - Line.push_back(*new AssInfo("Title", "Default Aegisub file")); - Line.push_back(*new AssInfo("ScriptType", "v4.00+")); - Line.push_back(*new AssInfo("WrapStyle", "0")); - Line.push_back(*new AssInfo("ScaledBorderAndShadow", "yes")); + Info.push_back(*new AssInfo("Title", "Default Aegisub file")); + Info.push_back(*new AssInfo("ScriptType", "v4.00+")); + Info.push_back(*new AssInfo("WrapStyle", "0")); + Info.push_back(*new AssInfo("ScaledBorderAndShadow", "yes")); if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) { - Line.push_back(*new AssInfo("PlayResX", std::to_string(OPT_GET("Subtitle/Default Resolution/Width")->GetInt()))); - Line.push_back(*new AssInfo("PlayResY", std::to_string(OPT_GET("Subtitle/Default Resolution/Height")->GetInt()))); + Info.push_back(*new AssInfo("PlayResX", std::to_string(OPT_GET("Subtitle/Default Resolution/Width")->GetInt()))); + Info.push_back(*new AssInfo("PlayResY", std::to_string(OPT_GET("Subtitle/Default Resolution/Height")->GetInt()))); } - Line.push_back(*new AssInfo("YCbCr Matrix", "None")); + Info.push_back(*new AssInfo("YCbCr Matrix", "None")); - Line.push_back(*new AssStyle); + Styles.push_back(*new AssStyle); if (defline) - Line.push_back(*new AssDialogue); -} - -void AssFile::swap(AssFile &that) throw() { - Line.swap(that.Line); + Events.push_back(*new AssDialogue); } AssFile::AssFile(const AssFile &from) { - Line.clone_from(from.Line, std::mem_fun_ref(&AssEntry::Clone), [](AssEntry *e) { delete e; }); + Info.clone_from(from.Info, std::mem_fun_ref(&AssEntry::Clone), [](AssEntry *e) { delete e; }); + Styles.clone_from(from.Styles, std::mem_fun_ref(&AssEntry::Clone), [](AssEntry *e) { delete e; }); + Events.clone_from(from.Events, std::mem_fun_ref(&AssEntry::Clone), [](AssEntry *e) { delete e; }); + Attachments.clone_from(from.Attachments, std::mem_fun_ref(&AssEntry::Clone), [](AssEntry *e) { delete e; }); +} + +void AssFile::swap(AssFile& from) throw() { + Info.swap(from.Info); + Styles.swap(from.Styles); + Events.swap(from.Events); + Attachments.swap(from.Attachments); } AssFile& AssFile::operator=(AssFile from) { - std::swap(*this, from); + swap(from); return *this; } -void AssFile::InsertLine(AssEntry *entry) { - if (Line.empty()) { - Line.push_back(*entry); - return; - } - - // Search for insertion point - entryIter it = Line.end(); - do { - --it; - if (it->Group() <= entry->Group()) { - Line.insert(++it, *entry); - return; - } - } while (it != Line.begin()); - - Line.push_front(*entry); -} - void AssFile::InsertAttachment(agi::fs::path const& filename) { AssEntryGroup group = AssEntryGroup::GRAPHIC; @@ -121,11 +98,11 @@ void AssFile::InsertAttachment(agi::fs::path const& filename) { if (ext == ".ttf" || ext == ".ttc" || ext == ".pfb") group = AssEntryGroup::FONT; - InsertLine(new AssAttachment(filename, group)); + Attachments.push_back(*new AssAttachment(filename, group)); } std::string AssFile::GetScriptInfo(std::string const& key) const { - for (const auto info : Line | agi::of_type()) { + for (const auto info : Info | agi::of_type()) { if (boost::iequals(key, info->Key())) return info->Value(); } @@ -154,7 +131,7 @@ void AssFile::SaveUIState(std::string const& key, std::string const& value) { } void AssFile::SetScriptInfo(std::string const& key, std::string const& value) { - for (auto info : Line | agi::of_type()) { + for (auto info : Info | agi::of_type()) { if (boost::iequals(key, info->Key())) { if (value.empty()) delete info; @@ -165,7 +142,7 @@ void AssFile::SetScriptInfo(std::string const& key, std::string const& value) { } if (!value.empty()) - InsertLine(new AssInfo(key, value)); + Info.push_back(*new AssInfo(key, value)); } void AssFile::GetResolution(int &sw,int &sh) const { @@ -192,13 +169,13 @@ void AssFile::GetResolution(int &sw,int &sh) const { std::vector AssFile::GetStyles() const { std::vector styles; - for (auto style : Line | agi::of_type()) + for (auto style : Styles | agi::of_type()) styles.push_back(style->name); return styles; } AssStyle *AssFile::GetStyle(std::string const& name) { - for (auto style : Line | agi::of_type()) { + for (auto style : Styles | agi::of_type()) { if (boost::iequals(style->name, name)) return style; } @@ -237,7 +214,7 @@ bool AssFile::CompLayer(const AssDialogue* lft, const AssDialogue* rgt) { } void AssFile::Sort(CompFunc comp, std::set const& limit) { - Sort(Line, comp, limit); + Sort(Events, comp, limit); } namespace { inline bool is_dialogue(AssEntry *e, std::set const& limit) { diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index c37fc6b54..dd36272e5 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -62,7 +62,10 @@ class AssFile { agi::signal::Signal PushState; public: /// The lines in the file - EntryList Line; + EntryList Info; + EntryList Styles; + EntryList Events; + EntryList Attachments; AssFile() { } AssFile(const AssFile &from); @@ -72,8 +75,6 @@ public: /// @brief Load default file /// @param defline Add a blank line to the file void LoadDefault(bool defline=true); - /// Add a line to the file at the end of the appropriate section - void InsertLine(AssEntry *line); /// Attach a file to the ass file void InsertAttachment(agi::fs::path const& filename); /// Get the names of all of the styles available diff --git a/aegisub/src/ass_karaoke.cpp b/aegisub/src/ass_karaoke.cpp index b22b9e48f..9181d78e0 100644 --- a/aegisub/src/ass_karaoke.cpp +++ b/aegisub/src/ass_karaoke.cpp @@ -280,7 +280,7 @@ void AssKaraoke::SplitLines(std::set const& lines, agi::Context *c SubtitleSelection sel = c->selectionController->GetSelectedSet(); bool did_split = false; - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { + for (entryIter it = c->ass->Events.begin(); it != c->ass->Events.end(); ++it) { AssDialogue *diag = dynamic_cast(&*it); if (!diag || !lines.count(diag)) continue; @@ -298,7 +298,7 @@ void AssKaraoke::SplitLines(std::set const& lines, agi::Context *c new_line->End = syl.start_time + syl.duration; new_line->Text = syl.GetText(false); - c->ass->Line.insert(it, *new_line); + c->ass->Events.insert(it, *new_line); if (in_sel) sel.insert(new_line); diff --git a/aegisub/src/ass_parser.cpp b/aegisub/src/ass_parser.cpp index d58627675..262db94af 100644 --- a/aegisub/src/ass_parser.cpp +++ b/aegisub/src/ass_parser.cpp @@ -33,7 +33,6 @@ AssParser::AssParser(AssFile *target, int version) , version(version) , state(&AssParser::ParseScriptInfoLine) { - std::fill(begin(insertion_positions), end(insertion_positions), nullptr); } AssParser::~AssParser() { @@ -52,7 +51,7 @@ void AssParser::ParseAttachmentLine(std::string const& data) { // Data is over, add attachment to the file if (!valid_data || is_filename) { - InsertLine(attach.release()); + target->Attachments.push_back(*attach.release()); AddLine(data); } else { @@ -60,7 +59,7 @@ void AssParser::ParseAttachmentLine(std::string const& data) { // Done building if (data.size() < 80) - InsertLine(attach.release()); + target->Attachments.push_back(*attach.release()); } } @@ -91,17 +90,17 @@ void AssParser::ParseScriptInfoLine(std::string const& data) { size_t pos = data.find(':'); if (pos == data.npos) return; - InsertLine(new AssInfo(data.substr(0, pos), boost::trim_left_copy(data.substr(pos + 1)))); + target->Info.push_back(*new AssInfo(data.substr(0, pos), boost::trim_left_copy(data.substr(pos + 1)))); } void AssParser::ParseEventLine(std::string const& data) { if (boost::starts_with(data, "Dialogue:") || boost::starts_with(data, "Comment:")) - InsertLine(new AssDialogue(data)); + target->Events.push_back(*new AssDialogue(data)); } void AssParser::ParseStyleLine(std::string const& data) { if (boost::starts_with(data, "Style:")) - InsertLine(new AssStyle(data, version)); + target->Styles.push_back(*new AssStyle(data, version)); } void AssParser::ParseFontLine(std::string const& data) { @@ -152,12 +151,3 @@ void AssParser::AddLine(std::string const& data) { (this->*state)(data); } - -void AssParser::InsertLine(AssEntry *entry) { - AssEntry *position = insertion_positions[(size_t)entry->Group()]; - if (position) - target->Line.insert(++target->Line.iterator_to(*position), *entry); - else - target->Line.push_back(*entry); - insertion_positions[(size_t)entry->Group()] = entry; -} diff --git a/aegisub/src/ass_parser.h b/aegisub/src/ass_parser.h index 820638a8d..b97bba766 100644 --- a/aegisub/src/ass_parser.h +++ b/aegisub/src/ass_parser.h @@ -16,8 +16,6 @@ #include #include -#include "ass_entry.h" - class AssAttachment; class AssFile; @@ -26,9 +24,6 @@ class AssParser { int version; std::unique_ptr attach; void (AssParser::*state)(std::string const&); - std::array insertion_positions; - - void InsertLine(AssEntry *entry); void ParseAttachmentLine(std::string const& data); void ParseEventLine(std::string const& data); diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp index 7944f2f50..f29ea64d1 100644 --- a/aegisub/src/audio_timing_dialogue.cpp +++ b/aegisub/src/audio_timing_dialogue.cpp @@ -742,20 +742,20 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines() case 2: // Previous and next lines if (AssDialogue *line = context->selectionController->GetActiveLine()) { - entryIter current_line = context->ass->Line.iterator_to(*line); - if (current_line == context->ass->Line.end()) + entryIter current_line = context->ass->Events.iterator_to(*line); + if (current_line == context->ass->Events.end()) break; entryIter prev = current_line; - while (--prev != context->ass->Line.begin() && !predicate(*prev)) ; - if (prev != context->ass->Line.begin()) + while (--prev != context->ass->Events.begin() && !predicate(*prev)) ; + if (prev != context->ass->Events.begin()) AddInactiveLine(sel, static_cast(&*prev)); if (mode == 2) { entryIter next = - find_if(++current_line, context->ass->Line.end(), predicate); - if (next != context->ass->Line.end()) + find_if(++current_line, context->ass->Events.end(), predicate); + if (next != context->ass->Events.end()) AddInactiveLine(sel, static_cast(&*next)); } } @@ -763,7 +763,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines() case 3: // All inactive lines { AssDialogue *active_line = context->selectionController->GetActiveLine(); - for (auto& line : context->ass->Line) + for (auto& line : context->ass->Events) { if (&line != active_line && predicate(line)) AddInactiveLine(sel, static_cast(&line)); diff --git a/aegisub/src/auto4_lua.cpp b/aegisub/src/auto4_lua.cpp index 268f49d92..6ba8f4123 100644 --- a/aegisub/src/auto4_lua.cpp +++ b/aegisub/src/auto4_lua.cpp @@ -37,6 +37,7 @@ #include "auto4_lua.h" #include "auto4_lua_utils.h" +#include "ass_attachment.h" #include "ass_dialogue.h" #include "ass_file.h" #include "ass_style.h" @@ -838,13 +839,11 @@ namespace Automation4 { lua_newtable(L); int active_idx = -1; - int row = 0; + int row = c->ass->Info.size() + c->ass->Styles.size(); int idx = 1; - for (auto& line : c->ass->Line) { + for (auto& line : c->ass->Events) { ++row; - AssDialogue *diag = dynamic_cast(&line); - if (!diag) continue; - + auto diag = static_cast(&line); if (diag == active_line) active_idx = row; if (sel.count(diag)) { push_value(L, row); @@ -901,7 +900,7 @@ namespace Automation4 { try { LuaThreadedCall(L, 3, 2, from_wx(StrDisplay(c)), c->parent, true); - subsobj->ProcessingComplete(StrDisplay(c)); + auto lines = subsobj->ProcessingComplete(StrDisplay(c)); AssDialogue *active_line = nullptr; int active_idx = 0; @@ -909,8 +908,8 @@ namespace Automation4 { // Check for a new active row if (lua_isnumber(L, -1)) { active_idx = lua_tointeger(L, -1); - if (active_idx < 1 || active_idx > (int)c->ass->Line.size()) { - wxLogError("Active row %d is out of bounds (must be 1-%u)", active_idx, c->ass->Line.size()); + if (active_idx < 1 || active_idx > (int)lines.size()) { + wxLogError("Active row %d is out of bounds (must be 1-%u)", active_idx, lines.size()); active_idx = 0; } } @@ -921,26 +920,21 @@ namespace Automation4 { // top of stack will be selected lines array, if any was returned if (lua_istable(L, -1)) { std::set sel; - entryIter it = c->ass->Line.begin(); - int last_idx = 1; lua_for_each(L, [&] { if (lua_isnumber(L, -1)) { int cur = lua_tointeger(L, -1); - if (cur < 1 || cur > (int)c->ass->Line.size()) { - wxLogError("Selected row %d is out of bounds (must be 1-%u)", cur, c->ass->Line.size()); + if (cur < 1 || cur > (int)lines.size()) { + wxLogError("Selected row %d is out of bounds (must be 1-%u)", cur, lines.size()); throw LuaForEachBreak(); } - advance(it, cur - last_idx); - - AssDialogue *diag = dynamic_cast(&*it); + AssDialogue *diag = dynamic_cast(lines[cur - 1]); if (!diag) { wxLogError("Selected row %d is not a dialogue line", cur); throw LuaForEachBreak(); } sel.insert(diag); - last_idx = cur; if (!active_line || active_idx == cur) active_line = diag; } diff --git a/aegisub/src/auto4_lua.h b/aegisub/src/auto4_lua.h index d0e743dc9..fe0fdbb85 100644 --- a/aegisub/src/auto4_lua.h +++ b/aegisub/src/auto4_lua.h @@ -115,7 +115,7 @@ namespace Automation4 { /// @param set_undo If there's any uncommitted changes to the file, /// they will be automatically committed with this /// description - void ProcessingComplete(wxString const& undo_description = wxString()); + std::vector ProcessingComplete(wxString const& undo_description = wxString()); /// End processing without applying any changes made void Cancel(); diff --git a/aegisub/src/auto4_lua_assfile.cpp b/aegisub/src/auto4_lua_assfile.cpp index 7f18265bf..87350f3e3 100644 --- a/aegisub/src/auto4_lua_assfile.cpp +++ b/aegisub/src/auto4_lua_assfile.cpp @@ -121,9 +121,7 @@ namespace { { case AssEntryGroup::DIALOGUE: return AssFile::COMMIT_DIAG_ADDREM; case AssEntryGroup::STYLE: return AssFile::COMMIT_STYLES; - case AssEntryGroup::FONT: return AssFile::COMMIT_ATTACHMENT; - case AssEntryGroup::GRAPHIC: return AssFile::COMMIT_ATTACHMENT; - default: return AssFile::COMMIT_SCRIPTINFO; + default: return AssFile::COMMIT_SCRIPTINFO; } } } @@ -217,8 +215,7 @@ namespace Automation4 { set_field(L, "class", "style"); } else { - // Attachments - set_field(L, "class", "unknown"); + assert(false); } } @@ -593,27 +590,40 @@ namespace Automation4 { return *((LuaAssFile**)ud); } - void LuaAssFile::ProcessingComplete(wxString const& undo_description) + std::vector LuaAssFile::ProcessingComplete(wxString const& undo_description) { + auto apply_lines = [&](std::vector const& lines) { + ass->Info.clear(); + ass->Styles.clear(); + ass->Events.clear(); + + for (auto line : lines) { + switch (line->Group()) { + case AssEntryGroup::INFO: ass->Info.push_back(*static_cast(line)); break; + case AssEntryGroup::STYLE: ass->Styles.push_back(*static_cast(line)); break; + case AssEntryGroup::DIALOGUE: ass->Events.push_back(*static_cast(line)); break; + default: break; + } + } + }; // Apply any pending commits for (auto const& pc : pending_commits) { - ass->Line.clear(); - boost::push_back(ass->Line, pc.lines | boost::adaptors::indirected); + apply_lines(pc.lines); ass->Commit(pc.mesage, pc.modification_type); } // Commit any changes after the last undo point was set - if (modification_type) { - ass->Line.clear(); - boost::push_back(ass->Line, lines | boost::adaptors::indirected); - } + if (modification_type) + apply_lines(lines); if (modification_type && can_set_undo && !undo_description.empty()) ass->Commit(undo_description, modification_type); lines_to_delete.clear(); + auto ret = std::move(lines); references--; if (!references) delete this; + return ret; } void LuaAssFile::Cancel() @@ -631,7 +641,11 @@ namespace Automation4 { , modification_type(0) , references(2) { - for (auto& line : ass->Line) + for (auto& line : ass->Info) + lines.push_back(&line); + for (auto& line : ass->Styles) + lines.push_back(&line); + for (auto& line : ass->Events) lines.push_back(&line); // prepare userdata object diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index 5d1091018..0e00ff47a 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -265,7 +265,7 @@ void BaseGrid::UpdateMaps() { index_line_map.clear(); line_index_map.clear(); - for (auto curdiag : context->ass->Line | agi::of_type()) { + for (auto curdiag : context->ass->Events | agi::of_type()) { line_index_map[curdiag] = (int)index_line_map.size(); index_line_map.push_back(curdiag); } diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index cdbd65130..a85e4e96c 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -488,7 +488,7 @@ struct edit_find_replace : public Command { static std::string get_entry_data(AssDialogue *d) { return d->GetEntryData(); } static void copy_lines(agi::Context *c) { SubtitleSelection sel = c->selectionController->GetSelectedSet(); - SetClipboard(join(c->ass->Line + SetClipboard(join(c->ass->Events | agi::of_type() | filtered([&](AssDialogue *d) { return sel.count(d); }) | transformed(get_entry_data), @@ -503,7 +503,7 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) { AssDialogue *post_sel = nullptr; bool hit_selection = false; - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { if (sel.count(diag)) hit_selection = true; else if (hit_selection && !post_sel) { @@ -519,7 +519,7 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) { // need to create a new dialogue line for it, and we can't select dialogue // lines until after they're committed. std::vector> to_delete; - c->ass->Line.remove_and_dispose_if([&sel](AssEntry const& e) { + c->ass->Events.remove_and_dispose_if([&sel](AssEntry const& e) { return sel.count(const_cast(static_cast(&e))); }, [&](AssEntry *e) { to_delete.emplace_back(e); @@ -532,7 +532,7 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) { // lines, so make a new one if (!new_active) { new_active = new AssDialogue; - c->ass->InsertLine(new_active); + c->ass->Events.push_back(*new_active); } c->ass->Commit(commit_message, AssFile::COMMIT_DIAG_ADDREM); @@ -605,8 +605,8 @@ static void duplicate_lines(agi::Context *c, int shift) { SubtitleSelectionController::Selection new_sel; AssDialogue *new_active = nullptr; - entryIter start = c->ass->Line.begin(); - entryIter end = c->ass->Line.end(); + entryIter start = c->ass->Events.begin(); + entryIter end = c->ass->Events.end(); while (start != end) { // Find the first line in the selection start = find_if(start, end, sel); @@ -622,7 +622,7 @@ static void duplicate_lines(agi::Context *c, int shift) { auto old_diag = static_cast(&*start); auto new_diag = new AssDialogue(*old_diag); - c->ass->Line.insert(insert_pos, *new_diag); + c->ass->Events.insert(insert_pos, *new_diag); new_sel.insert(new_diag); if (!new_active) new_active = new_diag; @@ -703,7 +703,7 @@ static void combine_lines(agi::Context *c, void (*combiner)(AssDialogue *, AssDi SubtitleSelection sel = c->selectionController->GetSelectedSet(); AssDialogue *first = nullptr; - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) { + for (entryIter it = c->ass->Events.begin(); it != c->ass->Events.end(); ) { AssDialogue *diag = dynamic_cast(&*it++); if (!diag || !sel.count(diag)) continue; @@ -790,8 +790,8 @@ static bool try_paste_lines(agi::Context *c) { for (auto& line : parsed) new_selection.insert(static_cast(&line)); - auto pos = c->ass->Line.iterator_to(*c->selectionController->GetActiveLine()); - c->ass->Line.splice(pos, parsed, parsed.begin(), parsed.end()); + auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); + c->ass->Events.splice(pos, parsed, parsed.begin(), parsed.end()); c->ass->Commit(_("paste"), AssFile::COMMIT_DIAG_ADDREM); c->selectionController->SetSelectionAndActive(new_selection, new_active); @@ -821,9 +821,9 @@ struct edit_line_paste : public Command { ctrl->Paste(); } else { - auto pos = c->ass->Line.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); paste_lines(c, false, [=](AssDialogue *new_line) -> AssDialogue * { - c->ass->Line.insert(pos, *new_line); + c->ass->Events.insert(pos, *new_line); return new_line; }); } @@ -852,15 +852,15 @@ struct edit_line_paste_over : public Command { // Only one line selected, so paste over downwards from the active line if (sel.size() < 2) { - auto pos = c->ass->Line.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); paste_lines(c, true, [&](AssDialogue *new_line) -> AssDialogue * { std::unique_ptr deleter(new_line); - if (pos == c->ass->Line.end()) return nullptr; + if (pos == c->ass->Events.end()) return nullptr; AssDialogue *ret = paste_over(c->parent, pasteOverOptions, new_line, static_cast(&*pos)); if (ret) - pos = find_if(next(pos), c->ass->Line.end(), cast()); + pos = find_if(next(pos), c->ass->Events.end(), cast()); return ret; }); } @@ -870,7 +870,7 @@ struct edit_line_paste_over : public Command { // Sort the selection by grid order std::vector sorted_selection; sorted_selection.reserve(sel.size()); - for (auto& line : c->ass->Line) { + for (auto& line : c->ass->Events) { if (sel.count(static_cast(&line))) sorted_selection.push_back(static_cast(&line)); } @@ -983,7 +983,7 @@ struct edit_line_recombine : public validate_sel_multiple { // Remove now non-existent lines from the selection SubtitleSelection lines, new_sel; - boost::copy(c->ass->Line | agi::of_type(), inserter(lines, lines.begin())); + boost::copy(c->ass->Events | agi::of_type(), inserter(lines, lines.begin())); boost::set_intersection(lines, sel_set, inserter(new_sel, new_sel.begin())); if (new_sel.empty()) @@ -1015,7 +1015,7 @@ void split_lines(agi::Context *c, Func&& set_time) { AssDialogue *n1 = c->selectionController->GetActiveLine(); auto n2 = new AssDialogue(*n1); - c->ass->Line.insert(++c->ass->Line.iterator_to(*n1), *n2); + c->ass->Events.insert(++c->ass->Events.iterator_to(*n1), *n2); std::string orig = n1->Text; n1->Text = boost::trim_right_copy(orig.substr(0, pos)); diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp index 2378718c6..b51043c63 100644 --- a/aegisub/src/command/grid.cpp +++ b/aegisub/src/command/grid.cpp @@ -79,8 +79,8 @@ struct grid_line_next_create : public Command { newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt(); newline->Style = cur->Style; - entryIter pos = c->ass->Line.iterator_to(*cur); - c->ass->Line.insert(++pos, *newline); + entryIter pos = c->ass->Events.iterator_to(*cur); + c->ass->Events.insert(++pos, *newline); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); c->selectionController->NextLine(); } @@ -356,7 +356,7 @@ struct grid_move_up : public Command { } void operator()(agi::Context *c) override { - if (move_one(c->ass->Line.begin(), c->ass->Line.end(), c->selectionController->GetSelectedSet(), 1)) + if (move_one(c->ass->Events.begin(), c->ass->Events.end(), c->selectionController->GetSelectedSet(), 1)) c->ass->Commit(_("move lines"), AssFile::COMMIT_ORDER); } }; @@ -373,7 +373,7 @@ struct grid_move_down : public Command { } void operator()(agi::Context *c) override { - if (move_one(--c->ass->Line.end(), c->ass->Line.begin(), c->selectionController->GetSelectedSet(), -1)) + if (move_one(--c->ass->Events.end(), c->ass->Events.begin(), c->selectionController->GetSelectedSet(), -1)) c->ass->Commit(_("move lines"), AssFile::COMMIT_ORDER); } }; diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp index 8cdebfe8c..89ee24ef6 100644 --- a/aegisub/src/command/subtitle.cpp +++ b/aegisub/src/command/subtitle.cpp @@ -54,6 +54,7 @@ #include "../video_context.h" #include +#include #include #include @@ -123,10 +124,10 @@ static void insert_subtitle_at_video(agi::Context *c, bool after) { def->End = video_ms + OPT_GET("Timing/Default Duration")->GetInt(); def->Style = c->selectionController->GetActiveLine()->Style; - entryIter pos = c->ass->Line.iterator_to(*c->selectionController->GetActiveLine()); + entryIter pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); if (after) ++pos; - c->ass->Line.insert(pos, *def); + c->ass->Events.insert(pos, *def); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); c->selectionController->SetSelectionAndActive({ def }, def); @@ -146,17 +147,17 @@ struct subtitle_insert_after : public validate_nonempty_selection { new_line->Start = active_line->End; new_line->End = new_line->Start + OPT_GET("Timing/Default Duration")->GetInt(); - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(&*it); + for (entryIter it = c->ass->Events.begin(); it != c->ass->Events.end(); ++it) { + AssDialogue *diag = static_cast(&*it); // Limit the line to the available time - if (diag && diag->Start >= new_line->Start) + if (diag->Start >= new_line->Start) new_line->End = std::min(new_line->End, diag->Start); // If we just hit the active line, insert the new line after it if (diag == active_line) { ++it; - c->ass->Line.insert(it, *new_line); + c->ass->Events.insert(it, *new_line); --it; } } @@ -191,16 +192,16 @@ struct subtitle_insert_before : public validate_nonempty_selection { new_line->End = active_line->Start; new_line->Start = new_line->End - OPT_GET("Timing/Default Duration")->GetInt(); - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(&*it); + for (entryIter it = c->ass->Events.begin(); it != c->ass->Events.end(); ++it) { + auto diag = static_cast(&*it); // Limit the line to the available time - if (diag && diag->End <= new_line->End) + if (diag->End <= new_line->End) new_line->Start = std::max(new_line->Start, diag->End); // If we just hit the active line, insert the new line before it if (diag == active_line) - c->ass->Line.insert(it, *new_line); + c->ass->Events.insert(it, *new_line); } c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); @@ -371,7 +372,7 @@ struct subtitle_select_all : public Command { void operator()(agi::Context *c) override { SubtitleSelection sel; - transform(c->ass->Line.begin(), c->ass->Line.end(), + transform(c->ass->Events.begin(), c->ass->Events.end(), inserter(sel, sel.begin()), cast()); sel.erase(nullptr); c->selectionController->SetSelectedSet(sel); @@ -393,10 +394,8 @@ struct subtitle_select_visible : public Command { SubtitleSelectionController::Selection new_selection; int frame = c->videoController->GetFrameN(); - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(&*it); - if (diag && - c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame && + for (auto diag : c->ass->Events | agi::of_type()) { + if (c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame && c->videoController->FrameAtTime(diag->End, agi::vfr::END) >= frame) { if (new_selection.empty()) diff --git a/aegisub/src/command/time.cpp b/aegisub/src/command/time.cpp index cdd2b423f..5bceb7155 100644 --- a/aegisub/src/command/time.cpp +++ b/aegisub/src/command/time.cpp @@ -67,7 +67,7 @@ namespace { if (sel.size() < 2) return !sel.empty(); size_t found = 0; - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { if (sel.count(diag)) { if (++found == sel.size()) return true; @@ -84,7 +84,7 @@ static void adjoin_lines(agi::Context *c, bool set_start) { AssDialogue *prev = nullptr; size_t seen = 0; bool prev_sel = false; - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { bool cur_sel = !!sel.count(diag); if (prev) { // One row selections act as if the previous or next line was selected diff --git a/aegisub/src/dialog_attachments.cpp b/aegisub/src/dialog_attachments.cpp index 2ff696e47..dc4de6e18 100644 --- a/aegisub/src/dialog_attachments.cpp +++ b/aegisub/src/dialog_attachments.cpp @@ -99,7 +99,7 @@ void DialogAttachments::UpdateList() { listView->InsertColumn(1, _("Size"), wxLIST_FORMAT_LEFT, 100); listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100); - for (auto attach : ass->Line | agi::of_type()) { + for (auto attach : ass->Attachments | agi::of_type()) { int row = listView->GetItemCount(); listView->InsertItem(row, to_wx(attach->GetFileName(true))); listView->SetItem(row, 1, PrettySize(attach->GetSize())); diff --git a/aegisub/src/dialog_kara_timing_copy.cpp b/aegisub/src/dialog_kara_timing_copy.cpp index b0217b005..135cca6ee 100644 --- a/aegisub/src/dialog_kara_timing_copy.cpp +++ b/aegisub/src/dialog_kara_timing_copy.cpp @@ -557,8 +557,8 @@ void DialogKanjiTimer::OnStart(wxCommandEvent &) { else if (SourceStyle->GetValue() == DestStyle->GetValue()) wxMessageBox(_("The source and destination styles must be different."),_("Error"),wxICON_EXCLAMATION | wxOK); else { - currentSourceLine = FindNextStyleMatch(&*subs->Line.begin(), from_wx(SourceStyle->GetValue())); - currentDestinationLine = FindNextStyleMatch(&*subs->Line.begin(), from_wx(DestStyle->GetValue())); + currentSourceLine = FindNextStyleMatch(&*subs->Events.begin(), from_wx(SourceStyle->GetValue())); + currentDestinationLine = FindNextStyleMatch(&*subs->Events.begin(), from_wx(DestStyle->GetValue())); ResetForNewLine(); } LinesToChange.clear(); @@ -686,11 +686,11 @@ static AssEntry *find_next(Iterator from, Iterator to, std::string const& style_ AssEntry *DialogKanjiTimer::FindNextStyleMatch(AssEntry *search_from, const std::string &search_style) { if (!search_from) return search_from; - return find_next(++subs->Line.iterator_to(*search_from), subs->Line.end(), search_style); + return find_next(++subs->Events.iterator_to(*search_from), subs->Events.end(), search_style); } AssEntry *DialogKanjiTimer::FindPrevStyleMatch(AssEntry *search_from, const std::string &search_style) { if (!search_from) return search_from; - return find_next(EntryList::reverse_iterator(subs->Line.iterator_to(*search_from)), subs->Line.rend(), search_style); + return find_next(EntryList::reverse_iterator(subs->Events.iterator_to(*search_from)), subs->Events.rend(), search_style); } diff --git a/aegisub/src/dialog_selection.cpp b/aegisub/src/dialog_selection.cpp index 34d4c4ed3..fdc29027e 100644 --- a/aegisub/src/dialog_selection.cpp +++ b/aegisub/src/dialog_selection.cpp @@ -77,7 +77,7 @@ static std::set process(std::string const& match_text, bool match_ auto predicate = SearchReplaceEngine::GetMatcher(settings); std::set matches; - for (auto diag : ass->Line | agi::of_type()) { + for (auto diag : ass->Events | agi::of_type()) { if (diag->Comment && !comments) continue; if (!diag->Comment && !dialogue) continue; diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp index 01b0d6272..42f3cea2b 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -354,7 +354,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) { int block_start = 0; json::Array shifted_blocks; - for (auto line : context->ass->Line | agi::of_type()) { + for (auto line : context->ass->Events | agi::of_type()) { ++row_number; if (!sel.count(line)) { diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp index 9ef34e7f2..541e5d2f9 100644 --- a/aegisub/src/dialog_spellchecker.cpp +++ b/aegisub/src/dialog_spellchecker.cpp @@ -212,7 +212,7 @@ bool DialogSpellChecker::FindNext() { if (CheckLine(active_line, start_pos, &commit_id)) return true; - entryIter it = context->ass->Line.iterator_to(*active_line); + entryIter it = context->ass->Events.iterator_to(*active_line); // Note that it is deliberate that the start line is checked twice, as if // the cursor is past the first misspelled word in the current line, that @@ -220,8 +220,8 @@ bool DialogSpellChecker::FindNext() { while(!has_looped || active_line != start_line) { do { // Wrap around to the beginning if we hit the end - if (++it == context->ass->Line.end()) { - it = context->ass->Line.begin(); + if (++it == context->ass->Events.end()) { + it = context->ass->Events.begin(); has_looped = true; } } while (!(active_line = dynamic_cast(&*it))); diff --git a/aegisub/src/dialog_style_editor.cpp b/aegisub/src/dialog_style_editor.cpp index fc8c5cb66..bc5bdfefd 100644 --- a/aegisub/src/dialog_style_editor.cpp +++ b/aegisub/src/dialog_style_editor.cpp @@ -86,7 +86,7 @@ class StyleRenamer { found_any = false; do_replace = replace; - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { if (diag->Style == source_name) { if (replace) diag->Style = new_name; @@ -437,7 +437,7 @@ void DialogStyleEditor::Apply(bool apply, bool close) { if (store) store->push_back(std::unique_ptr(style)); else - c->ass->InsertLine(style); + c->ass->Styles.push_back(*style); is_new = false; } if (!store) diff --git a/aegisub/src/dialog_style_manager.cpp b/aegisub/src/dialog_style_manager.cpp index 0b466dba9..8737a6a1b 100644 --- a/aegisub/src/dialog_style_manager.cpp +++ b/aegisub/src/dialog_style_manager.cpp @@ -288,7 +288,7 @@ void DialogStyleManager::LoadCurrentStyles(int commit_type) { CurrentList->Clear(); styleMap.clear(); - for (auto style : c->ass->Line | agi::of_type()) { + for (auto style : c->ass->Styles | agi::of_type()) { CurrentList->Append(to_wx(style->name)); styleMap.push_back(style); } @@ -448,7 +448,7 @@ void DialogStyleManager::OnCopyToCurrent() { } } else { - c->ass->InsertLine(new AssStyle(*Store[selections[i]])); + c->ass->Styles.push_back(*new AssStyle(*Store[selections[i]])); copied.push_back(styleName); } } @@ -480,7 +480,7 @@ void DialogStyleManager::CopyToClipboard(wxListBox *list, T const& v) { void DialogStyleManager::PasteToCurrent() { add_styles( std::bind(&AssFile::GetStyle, c->ass, _1), - std::bind(&AssFile::InsertLine, c->ass, _1)); + [=](AssStyle *s) { c->ass->Styles.push_back(*s); }); c->ass->Commit(_("style paste"), AssFile::COMMIT_STYLES); } @@ -630,7 +630,7 @@ void DialogStyleManager::OnCurrentImport() { // Copy modified = true; - c->ass->InsertLine(temp.GetStyle(styles[sel])->Clone()); + c->ass->Styles.push_back(*temp.GetStyle(styles[sel])->Clone()); } // Update @@ -779,10 +779,10 @@ void DialogStyleManager::MoveStyles(bool storage, int type) { // Replace styles size_t curn = 0; - for (auto it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { + for (auto it = c->ass->Styles.begin(); it != c->ass->Styles.end(); ++it) { if (!dynamic_cast(&*it)) continue; - auto new_style_at_pos = c->ass->Line.iterator_to(*styleMap[curn]); + auto new_style_at_pos = c->ass->Styles.iterator_to(*styleMap[curn]); EntryList::node_algorithms::swap_nodes(it.pointed_node(), new_style_at_pos.pointed_node()); if (++curn == styleMap.size()) break; it = new_style_at_pos; diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index a9c4e8042..2c83d9046 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -307,14 +307,14 @@ std::vector DialogTimingProcessor::SortDialogues() { [&](AssDialogue *d) { return !d->Comment && styles.count(d->Style); }); } else { - transform(c->ass->Line.begin(), c->ass->Line.end(), back_inserter(sorted), cast()); + transform(c->ass->Events.begin(), c->ass->Events.end(), back_inserter(sorted), cast()); sorted.erase(boost::remove_if(sorted, bind(bad_line, &styles, _1)), sorted.end()); } // Check if rows are valid for (auto diag : sorted) { if (diag->Start > diag->End) { - int line = count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*diag), cast()); + int line = distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*diag)); wxMessageBox( wxString::Format(_("One of the lines in the file (%i) has negative duration. Aborting."), line), _("Invalid script"), diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index 60a70357c..64652e54f 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -66,8 +66,8 @@ DialogTranslation::DialogTranslation(agi::Context *c) , file_change_connection(c->ass->AddCommitListener(&DialogTranslation::OnExternalCommit, this)) , active_line_connection(c->selectionController->AddActiveLineListener(&DialogTranslation::OnActiveLineChanged, this)) , active_line(c->selectionController->GetActiveLine()) -, line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast())) -, line_number(count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*active_line), cast()) + 1) +, line_count(c->ass->Events.size()) +, line_number(distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*active_line)) + 1) { SetIcon(GETICON(translation_toolbutton_16)); @@ -175,7 +175,7 @@ void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) { active_line = new_line; blocks = active_line->ParseTags(); cur_block = 0; - line_number = count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*new_line), cast()) + 1; + line_number = distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*new_line)) + 1; if (bad_block(blocks[cur_block]) && !NextBlock()) { wxMessageBox(_("No more lines to translate.")); @@ -185,7 +185,7 @@ void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) { void DialogTranslation::OnExternalCommit(int commit_type) { if (commit_type == AssFile::COMMIT_NEW || commit_type & AssFile::COMMIT_DIAG_ADDREM) { - line_count = count_if(c->ass->Line.begin(), c->ass->Line.end(), cast()); + line_count = c->ass->Events.size(); line_number_display->SetLabel(wxString::Format(_("Current line: %d/%d"), (int)line_number, (int)line_count)); } diff --git a/aegisub/src/export_fixstyle.cpp b/aegisub/src/export_fixstyle.cpp index de613258f..04a71c672 100644 --- a/aegisub/src/export_fixstyle.cpp +++ b/aegisub/src/export_fixstyle.cpp @@ -57,7 +57,7 @@ void AssFixStylesFilter::ProcessSubs(AssFile *subs, wxWindow *) { for_each(begin(styles), end(styles), [](std::string& str) { boost::to_lower(str); }); sort(begin(styles), end(styles)); - for (auto diag : subs->Line | agi::of_type()) { + for (auto diag : subs->Events | agi::of_type()) { if (!binary_search(begin(styles), end(styles), boost::to_lower_copy(diag->Style.get()))) diag->Style = "Default"; } diff --git a/aegisub/src/export_framerate.cpp b/aegisub/src/export_framerate.cpp index 8cd265454..a827479fd 100644 --- a/aegisub/src/export_framerate.cpp +++ b/aegisub/src/export_framerate.cpp @@ -201,7 +201,7 @@ void AssTransformFramerateFilter::TransformTimeTags(std::string const& name, Ass void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { if (!Input->IsLoaded() || !Output->IsLoaded()) return; - for (auto curDialogue : subs->Line | agi::of_type()) { + for (auto curDialogue : subs->Events | agi::of_type()) { line = curDialogue; newK = 0; oldK = 0; diff --git a/aegisub/src/font_file_lister.cpp b/aegisub/src/font_file_lister.cpp index 9a7316e8d..f6d57d932 100644 --- a/aegisub/src/font_file_lister.cpp +++ b/aegisub/src/font_file_lister.cpp @@ -182,7 +182,7 @@ std::vector FontCollector::GetFontPaths(const AssFile *file) { status_callback(_("Parsing file\n"), 0); - for (auto style : file->Line | agi::of_type()) { + for (auto style : file->Styles | agi::of_type()) { StyleInfo &info = styles[style->name]; info.facename = style->font; info.bold = style->bold; @@ -191,7 +191,7 @@ std::vector FontCollector::GetFontPaths(const AssFile *file) { } int index = 0; - for (auto diag : file->Line | agi::of_type()) + for (auto diag : file->Events | agi::of_type()) ProcessDialogueLine(diag, ++index); status_callback(_("Searching for font files\n"), 0); diff --git a/aegisub/src/resolution_resampler.cpp b/aegisub/src/resolution_resampler.cpp index fbc179963..069e0f7be 100644 --- a/aegisub/src/resolution_resampler.cpp +++ b/aegisub/src/resolution_resampler.cpp @@ -172,7 +172,9 @@ void ResampleResolution(AssFile *ass, ResampleSettings const& settings) { if (settings.change_ar) state.ar = state.rx / state.ry; - for (auto& line : ass->Line) + for (auto& line : ass->Styles) + resample_line(&state, line); + for (auto& line : ass->Events) resample_line(&state, line); ass->SetScriptInfo("PlayResX", std::to_string(settings.script_x)); diff --git a/aegisub/src/search_replace_engine.cpp b/aegisub/src/search_replace_engine.cpp index 53a50e7cb..b821e08dd 100644 --- a/aegisub/src/search_replace_engine.cpp +++ b/aegisub/src/search_replace_engine.cpp @@ -230,7 +230,7 @@ bool SearchReplaceEngine::FindReplace(bool replace) { auto matches = GetMatcher(settings); AssDialogue *line = context->selectionController->GetActiveLine(); - auto it = context->ass->Line.iterator_to(*line); + auto it = context->ass->Events.iterator_to(*line); size_t pos = 0; MatchState replace_ms; @@ -263,7 +263,7 @@ bool SearchReplaceEngine::FindReplace(bool replace) { // For non-text fields we just look for matching lines rather than each // match within the line, so move to the next line else if (settings.field != SearchReplaceSettings::Field::TEXT) - it = circular_next(it, context->ass->Line); + it = circular_next(it, context->ass->Events); auto const& sel = context->selectionController->GetSelectedSet(); bool selection_only = sel.size() > 1 && settings.limit_to == SearchReplaceSettings::Limit::SELECTED; @@ -286,7 +286,7 @@ bool SearchReplaceEngine::FindReplace(bool replace) { return true; } - } while (pos = 0, &*(it = circular_next(it, context->ass->Line)) != line); + } while (pos = 0, &*(it = circular_next(it, context->ass->Events)) != line); // Replaced something and didn't find another match, so select the newly // inserted text @@ -307,7 +307,7 @@ bool SearchReplaceEngine::ReplaceAll() { SubtitleSelection const& sel = context->selectionController->GetSelectedSet(); bool selection_only = settings.limit_to == SearchReplaceSettings::Limit::SELECTED; - for (auto diag : context->ass->Line | agi::of_type()) { + for (auto diag : context->ass->Events | agi::of_type()) { if (selection_only && !sel.count(diag)) continue; if (settings.ignore_comments && diag->Comment) continue; diff --git a/aegisub/src/subs_controller.cpp b/aegisub/src/subs_controller.cpp index c176c8f66..d1835f9b6 100644 --- a/aegisub/src/subs_controller.cpp +++ b/aegisub/src/subs_controller.cpp @@ -69,35 +69,22 @@ struct SubsController::UndoInfo { UndoInfo(const agi::Context *c, wxString const& d, int commit_id) : undo_description(d), commit_id(commit_id) { - size_t info_count = 0, style_count = 0, event_count = 0, font_count = 0, graphics_count = 0; - for (auto const& line : c->ass->Line) { - switch (line.Group()) { - case AssEntryGroup::DIALOGUE: ++event_count; break; - case AssEntryGroup::INFO: ++info_count; break; - case AssEntryGroup::STYLE: ++style_count; break; - case AssEntryGroup::FONT: ++font_count; break; - case AssEntryGroup::GRAPHIC: ++graphics_count; break; - default: assert(false); break; - } + script_info.reserve(c->ass->Info.size()); + for (auto const& line : c->ass->Info) { + auto info = static_cast(&line); + script_info.emplace_back(info->Key(), info->Value()); } - script_info.reserve(info_count); - styles.reserve(style_count); - events.reserve(event_count); + styles.reserve(c->ass->Styles.size()); + for (auto const& line : c->ass->Styles) + styles.push_back(static_cast(line)); - for (auto const& line : c->ass->Line) { + events.reserve(c->ass->Events.size()); + for (auto const& line : c->ass->Events) + events.push_back(static_cast(line)); + + for (auto const& line : c->ass->Attachments) { switch (line.Group()) { - case AssEntryGroup::DIALOGUE: - events.push_back(static_cast(line)); - break; - case AssEntryGroup::INFO: { - auto info = static_cast(&line); - script_info.emplace_back(info->Key(), info->Value()); - break; - } - case AssEntryGroup::STYLE: - styles.push_back(static_cast(line)); - break; case AssEntryGroup::FONT: fonts.push_back(static_cast(line)); break; @@ -125,16 +112,16 @@ struct SubsController::UndoInfo { SubtitleSelection new_sel; for (auto const& info : script_info) - c->ass->Line.push_back(*new AssInfo(info.first, info.second)); + c->ass->Info.push_back(*new AssInfo(info.first, info.second)); for (auto const& style : styles) - c->ass->Line.push_back(*new AssStyle(style)); + c->ass->Styles.push_back(*new AssStyle(style)); for (auto const& attachment : fonts) - c->ass->Line.push_back(*new AssAttachment(attachment)); + c->ass->Attachments.push_back(*new AssAttachment(attachment)); for (auto const& attachment : graphics) - c->ass->Line.push_back(*new AssAttachment(attachment)); + c->ass->Attachments.push_back(*new AssAttachment(attachment)); for (auto const& event : events) { auto copy = new AssDialogue(event); - c->ass->Line.push_back(*copy); + c->ass->Events.push_back(*copy); if (copy->Id == active_line_id) active_line = copy; if (binary_search(begin(selection), end(selection), copy->Id)) @@ -142,7 +129,7 @@ struct SubsController::UndoInfo { } c->subsGrid->BeginBatch(); - c->selectionController->SetSelectedSet({ }); + c->selectionController->SetSelectedSet(std::set{}); c->ass->Commit("", AssFile::COMMIT_NEW); c->selectionController->SetSelectionAndActive(new_sel, active_line); c->subsGrid->EndBatch(); @@ -222,22 +209,11 @@ void SubsController::Load(agi::fs::path const& filename, std::string charset) { 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 (auto const& line : temp.Line) { - AssEntryGroup type = line.Group(); - if (type == AssEntryGroup::STYLE) found_style = true; - if (type == AssEntryGroup::DIALOGUE) found_dialogue = true; - if (found_style && found_dialogue) break; - } - - // And if it doesn't add defaults for each - if (!found_style) - temp.InsertLine(new AssStyle); - if (!found_dialogue) - temp.InsertLine(new AssDialogue); + // Make sure the file has at least one style and one dialogue line + if (temp.Styles.empty()) + temp.Styles.push_back(*new AssStyle); + if (temp.Events.empty()) + temp.Events.push_back(*new AssDialogue); context->ass->swap(temp); } @@ -318,7 +294,7 @@ void SubsController::Close() { autosaved_commit_id = saved_commit_id = commit_id + 1; filename.clear(); AssFile blank; - swap(blank.Line, context->ass->Line); + blank.swap(*context->ass); context->ass->LoadDefault(); context->ass->Commit("", AssFile::COMMIT_NEW); } diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 4d0ccfc68..e365b7a20 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -343,8 +343,7 @@ void SubsEditBox::PopulateList(wxComboBox *combo, boost::flyweight wxEventBlocker blocker(this); std::unordered_set values; - for (auto const& line : c->ass->Line) { - if (line.Group() != AssEntryGroup::DIALOGUE) continue; + for (auto const& line : c->ass->Events) { auto const& value = static_cast(&line)->*field; if (!value.get().empty()) values.insert(value); @@ -435,12 +434,12 @@ void SubsEditBox::SetSelectedRows(setter set, wxString const& desc, int type, bo } template -void SubsEditBox::SetSelectedRows(T AssDialogue::*field, T value, wxString const& desc, int type, bool amend) { +void SubsEditBox::SetSelectedRows(T AssDialogueBase::*field, T value, wxString const& desc, int type, bool amend) { SetSelectedRows([&](AssDialogue *d) { d->*field = value; }, desc, type, amend); } template -void SubsEditBox::SetSelectedRows(T AssDialogue::*field, wxString const& value, wxString const& desc, int type, bool amend) { +void SubsEditBox::SetSelectedRows(T AssDialogueBase::*field, wxString const& value, wxString const& desc, int type, bool amend) { boost::flyweight conv_value(from_wx(value)); SetSelectedRows([&](AssDialogue *d) { d->*field = conv_value; }, desc, type, amend); } diff --git a/aegisub/src/subs_edit_box.h b/aegisub/src/subs_edit_box.h index a0e3d2f77..47b5661d5 100644 --- a/aegisub/src/subs_edit_box.h +++ b/aegisub/src/subs_edit_box.h @@ -62,6 +62,7 @@ class wxSpinCtrl; class wxStyledTextCtrl; class wxStyledTextEvent; class wxTextCtrl; +struct AssDialogueBase; template class Placeholder; @@ -177,10 +178,10 @@ class SubsEditBox : public wxPanel { /// @param type Commit type to use /// @param amend Coalesce sequences of commits of the same type template - void SetSelectedRows(T AssDialogue::*field, T value, wxString const& desc, int type, bool amend = false); + void SetSelectedRows(T AssDialogueBase::*field, T value, wxString const& desc, int type, bool amend = false); template - void SetSelectedRows(T AssDialogue::*field, wxString const& value, wxString const& desc, int type, bool amend = false); + void SetSelectedRows(T AssDialogueBase::*field, wxString const& value, wxString const& desc, int type, bool amend = false); /// @brief Reload the current line from the file /// @param type AssFile::COMMITType diff --git a/aegisub/src/subs_preview.cpp b/aegisub/src/subs_preview.cpp index ab1d1a87a..33d62ab46 100644 --- a/aegisub/src/subs_preview.cpp +++ b/aegisub/src/subs_preview.cpp @@ -60,8 +60,8 @@ SubtitlesPreview::SubtitlesPreview(wxWindow *parent, wxSize size, int winStyle, SetStyle(*style); sub_file->LoadDefault(); - sub_file->InsertLine(style); - sub_file->Line.push_back(*line); + sub_file->Styles.push_back(*style); + sub_file->Events.push_back(*line); SetSizeHints(size.GetWidth(), size.GetHeight(), -1, -1); wxSizeEvent evt(size); diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index 0c64b1670..ec599d648 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -89,22 +89,19 @@ bool SubtitleFormat::CanWriteFile(agi::fs::path const& filename) const { } bool SubtitleFormat::CanSave(const AssFile *subs) const { - AssStyle defstyle; - for (auto const& line : subs->Line) { - // Check style, if anything non-default is found, return false - if (const AssStyle *curstyle = dynamic_cast(&line)) { - if (curstyle->GetEntryData() != defstyle.GetEntryData()) - return false; - } + if (!subs->Attachments.empty()) + return false; - // Check for attachments, if any is found, return false - if (dynamic_cast(&line)) return false; + std::string defstyle = AssStyle().GetEntryData(); + for (auto const& line : subs->Styles) { + if (static_cast(&line)->GetEntryData() != defstyle) + return false; + } - // Check dialog - if (const AssDialogue *curdiag = dynamic_cast(&line)) { - if (curdiag->GetStrippedText() != curdiag->Text) - return false; - } + for (auto const& line : subs->Events) { + auto diag = static_cast(&line); + if (diag->GetStrippedText() != diag->Text) + return false; } return true; @@ -176,12 +173,12 @@ agi::vfr::Framerate SubtitleFormat::AskForFPS(bool allow_vfr, bool show_smpte) { } void SubtitleFormat::StripTags(AssFile &file) { - for (auto current : file.Line | agi::of_type()) + for (auto current : file.Events | agi::of_type()) current->StripTags(); } void SubtitleFormat::ConvertNewlines(AssFile &file, std::string const& newline, bool mergeLineBreaks) { - for (auto current : file.Line | agi::of_type()) { + for (auto current : file.Events | agi::of_type()) { std::string repl = current->Text; boost::replace_all(repl, "\\h", " "); boost::ireplace_all(repl, "\\n", newline); @@ -196,18 +193,12 @@ void SubtitleFormat::ConvertNewlines(AssFile &file, std::string const& newline, } void SubtitleFormat::StripComments(AssFile &file) { - file.Line.remove_and_dispose_if([](AssEntry const& e) { + file.Events.remove_and_dispose_if([](AssEntry const& e) { const AssDialogue *diag = dynamic_cast(&e); return diag && (diag->Comment || diag->Text.get().empty()); }, [](AssEntry *e) { delete e; }); } -void SubtitleFormat::StripNonDialogue(AssFile &file) { - file.Line.remove_and_dispose_if([](AssEntry const& e) { - return e.Group() != AssEntryGroup::DIALOGUE; - }, [](AssEntry *e) { delete e; }); -} - static bool dialog_start_lt(AssEntry &pos, AssDialogue *to_insert) { AssDialogue *diag = dynamic_cast(&pos); return diag && diag->Start > to_insert->Start; @@ -217,10 +208,10 @@ static bool dialog_start_lt(AssEntry &pos, AssDialogue *to_insert) { /// /// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge void SubtitleFormat::RecombineOverlaps(AssFile &file) { - entryIter cur, next = file.Line.begin(); + entryIter cur, next = file.Events.begin(); cur = next++; - for (; next != file.Line.end(); cur = next++) { + for (; next != file.Events.end(); cur = next++) { AssDialogue *prevdlg = dynamic_cast(&*cur); AssDialogue *curdlg = dynamic_cast(&*next); @@ -236,8 +227,8 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { // std::list::insert() inserts items before the given iterator, so // we need 'next' for inserting. 'prev' and 'cur' can safely be erased // from the list now. - file.Line.erase(prev); - file.Line.erase(cur); + file.Events.erase(prev); + file.Events.erase(cur); //Is there an A part before the overlap? if (curdlg->Start > prevdlg->Start) { @@ -247,7 +238,7 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { newdlg->End = curdlg->Start; newdlg->Text = prevdlg->Text; - file.Line.insert(find_if(next, file.Line.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); + file.Events.insert(find_if(next, file.Events.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Overlapping A+B part @@ -258,7 +249,7 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { // Put an ASS format hard linewrap between lines newdlg->Text = curdlg->Text.get() + "\\N" + prevdlg->Text.get(); - file.Line.insert(find_if(next, file.Line.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); + file.Events.insert(find_if(next, file.Events.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Is there an A part after the overlap? @@ -269,7 +260,7 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { newdlg->End = prevdlg->End; newdlg->Text = prevdlg->Text; - file.Line.insert(find_if(next, file.Line.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); + file.Events.insert(find_if(next, file.Events.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Is there a B part after the overlap? @@ -280,7 +271,7 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { newdlg->End = curdlg->End; newdlg->Text = curdlg->Text; - file.Line.insert(find_if(next, file.Line.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); + file.Events.insert(find_if(next, file.Events.end(), std::bind(dialog_start_lt, _1, newdlg)), *newdlg); } next--; @@ -289,10 +280,10 @@ void SubtitleFormat::RecombineOverlaps(AssFile &file) { /// @brief Merge identical lines that follow each other void SubtitleFormat::MergeIdentical(AssFile &file) { - entryIter cur, next = file.Line.begin(); + entryIter cur, next = file.Events.begin(); cur = next++; - for (; next != file.Line.end(); cur = next++) { + for (; next != file.Events.end(); cur = next++) { AssDialogue *curdlg = dynamic_cast(&*cur); AssDialogue *nextdlg = dynamic_cast(&*next); diff --git a/aegisub/src/subtitle_format.h b/aegisub/src/subtitle_format.h index 9036ce4cf..3a66f93a8 100644 --- a/aegisub/src/subtitle_format.h +++ b/aegisub/src/subtitle_format.h @@ -64,8 +64,6 @@ public: static void ConvertNewlines(AssFile &file, std::string const& newline, bool mergeLineBreaks = true); /// Remove All commented and empty lines static void StripComments(AssFile &file); - /// Remove everything but the dialogue lines - static void StripNonDialogue(AssFile &file); /// @brief Split and merge lines so there are no overlapping lines /// /// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge diff --git a/aegisub/src/subtitle_format_ass.cpp b/aegisub/src/subtitle_format_ass.cpp index 4c9201cc3..898573037 100644 --- a/aegisub/src/subtitle_format_ass.cpp +++ b/aegisub/src/subtitle_format_ass.cpp @@ -115,17 +115,24 @@ void AssSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen bool ssa = agi::fs::HasExtension(filename, "ssa"); AssEntryGroup group = AssEntryGroup::INFO; - for (auto const& line : src->Line) { - if (line.Group() != group) { - // Add a blank line between each group - file.WriteLineToFile(""); + auto write = [&](EntryList const& list) { + for (auto const& line : list) { + if (line.Group() != group) { + // Add a blank line between each group + file.WriteLineToFile(""); - file.WriteLineToFile(line.GroupHeader(ssa)); - file.WriteLineToFile(format(line.Group(), ssa), false); + file.WriteLineToFile(line.GroupHeader(ssa)); + file.WriteLineToFile(format(line.Group(), ssa), false); - group = line.Group(); + group = line.Group(); + } + + file.WriteLineToFile(ssa ? line.GetSSAText() : line.GetEntryData()); } + }; - file.WriteLineToFile(ssa ? line.GetSSAText() : line.GetEntryData()); - } + write(src->Info); + write(src->Styles); + write(src->Attachments); + write(src->Events); } diff --git a/aegisub/src/subtitle_format_ebu3264.cpp b/aegisub/src/subtitle_format_ebu3264.cpp index 30913febc..79411960f 100644 --- a/aegisub/src/subtitle_format_ebu3264.cpp +++ b/aegisub/src/subtitle_format_ebu3264.cpp @@ -370,10 +370,10 @@ namespace AssStyle default_style; std::vector subs_list; - subs_list.reserve(copy.Line.size()); + subs_list.reserve(copy.Events.size()); // convert to intermediate format - for (auto line : copy.Line | agi::of_type()) + for (auto line : copy.Events | agi::of_type()) { // add a new subtitle and work on it subs_list.emplace_back(); diff --git a/aegisub/src/subtitle_format_encore.cpp b/aegisub/src/subtitle_format_encore.cpp index 08f5e325e..d710345bc 100644 --- a/aegisub/src/subtitle_format_encore.cpp +++ b/aegisub/src/subtitle_format_encore.cpp @@ -77,6 +77,6 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& fi // Write lines int i = 0; TextFileWriter file(filename, "UTF-8"); - for (auto current : copy.Line | agi::of_type()) + for (auto current : copy.Events | agi::of_type()) file.WriteLineToFile(str(boost::format("%i %s %s %s") % ++i % ft.ToSMPTE(current->Start) % ft.ToSMPTE(current->End) % current->Text)); } diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index 916b7d4c2..c14553da0 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -120,7 +120,7 @@ void MicroDVDSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& file diag->Start = fps.TimeAtFrame(f1, agi::vfr::START); diag->End = fps.TimeAtFrame(f2, agi::vfr::END); diag->Text = text; - target->Line.push_back(*diag); + target->Events.push_back(*diag); } } @@ -143,7 +143,7 @@ void MicroDVDSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& file.WriteLineToFile(str(boost::format("{1}{1}%.6f") % fps.FPS())); // Write lines - for (auto current : copy.Line | agi::of_type()) { + for (auto current : copy.Events | agi::of_type()) { int start = fps.FrameAtTime(current->Start, agi::vfr::START); int end = fps.FrameAtTime(current->End, agi::vfr::END); diff --git a/aegisub/src/subtitle_format_srt.cpp b/aegisub/src/subtitle_format_srt.cpp index c1a3206ef..c5078b4eb 100644 --- a/aegisub/src/subtitle_format_srt.cpp +++ b/aegisub/src/subtitle_format_srt.cpp @@ -404,7 +404,7 @@ found_timestamps: line->Start = ReadSRTTime(timestamp_match.str(1)); line->End = ReadSRTTime(timestamp_match.str(2)); // store pointer to subtitle, we'll continue working on it - target->Line.push_back(*line); + target->Events.push_back(*line); // next we're reading the text state = STATE_FIRST_LINE_OF_BODY; break; @@ -480,7 +480,7 @@ void SRTSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen // Write lines int i=0; - for (auto current : copy.Line | agi::of_type()) { + for (auto current : copy.Events | agi::of_type()) { file.WriteLineToFile(std::to_string(++i)); file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End)); file.WriteLineToFile(ConvertTags(current)); @@ -491,26 +491,23 @@ void SRTSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen bool SRTSubtitleFormat::CanSave(const AssFile *file) const { std::string supported_tags[] = { "\\b", "\\i", "\\s", "\\u" }; - AssStyle defstyle; - for (auto const& line : file->Line) { - // Check style, if anything non-default is found, return false - if (const AssStyle *curstyle = dynamic_cast(&line)) { - if (curstyle->GetEntryData() != defstyle.GetEntryData()) - return false; - } + if (!file->Attachments.empty()) + return false; - // Check for attachments, if any is found, return false - if (dynamic_cast(&line)) return false; + std::string defstyle = AssStyle().GetEntryData(); + for (auto const& line : file->Styles) { + if (static_cast(&line)->GetEntryData() != defstyle) + return false; + } - // Check dialogue - if (const AssDialogue *curdiag = dynamic_cast(&line)) { - boost::ptr_vector blocks(curdiag->ParseTags()); - for (auto ovr : blocks | agi::of_type()) { - // Verify that all overrides used are supported - for (auto const& tag : ovr->Tags) { - if (!std::binary_search(supported_tags, std::end(supported_tags), tag.Name)) - return false; - } + for (auto const& line : file->Events) { + auto diag = static_cast(&line); + boost::ptr_vector blocks(diag->ParseTags()); + for (auto ovr : blocks | agi::of_type()) { + // Verify that all overrides used are supported + for (auto const& tag : ovr->Tags) { + if (!std::binary_search(supported_tags, std::end(supported_tags), tag.Name)) + return false; } } } diff --git a/aegisub/src/subtitle_format_transtation.cpp b/aegisub/src/subtitle_format_transtation.cpp index eee8c1937..4cb3d58aa 100644 --- a/aegisub/src/subtitle_format_transtation.cpp +++ b/aegisub/src/subtitle_format_transtation.cpp @@ -77,7 +77,7 @@ void TranStationSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path cons SmpteFormatter ft(fps); TextFileWriter file(filename, encoding); AssDialogue *prev = nullptr; - for (auto cur : copy.Line | agi::of_type()) { + for (auto cur : copy.Events | agi::of_type()) { if (prev) { file.WriteLineToFile(ConvertLine(©, prev, fps, ft, cur->Start)); file.WriteLineToFile(""); diff --git a/aegisub/src/subtitle_format_ttxt.cpp b/aegisub/src/subtitle_format_ttxt.cpp index 96c7b23d8..28a293d98 100644 --- a/aegisub/src/subtitle_format_ttxt.cpp +++ b/aegisub/src/subtitle_format_ttxt.cpp @@ -92,7 +92,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename if (child->GetName() == "TextSample") { if ((diag = ProcessLine(child, diag, version))) { lines++; - target->Line.push_back(*diag); + target->Events.push_back(*diag); } } // Header @@ -103,7 +103,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename // No lines? if (lines == 0) - target->Line.push_back(*new AssDialogue); + target->Events.push_back(*new AssDialogue); } AssDialogue *TTXTSubtitleFormat::ProcessLine(wxXmlNode *node, AssDialogue *prev, int version) const { @@ -177,7 +177,7 @@ void TTXTSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& file // Create lines const AssDialogue *prev = nullptr; - for (auto current : copy.Line | agi::of_type()) { + for (auto current : copy.Events | agi::of_type()) { WriteLine(root, prev, current); prev = current; } @@ -264,7 +264,7 @@ void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const { // Find last line AssTime lastTime; - for (auto line : file.Line | boost::adaptors::reversed | agi::of_type()) { + for (auto line : file.Events | boost::adaptors::reversed | agi::of_type()) { lastTime = line->End; break; } @@ -273,5 +273,5 @@ void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const { auto diag = new AssDialogue; diag->Start = lastTime; diag->End = lastTime+OPT_GET("Timing/Default Duration")->GetInt(); - file.Line.push_back(*diag); + file.Events.push_back(*diag); } diff --git a/aegisub/src/subtitle_format_txt.cpp b/aegisub/src/subtitle_format_txt.cpp index 2b4985672..3ced45aec 100644 --- a/aegisub/src/subtitle_format_txt.cpp +++ b/aegisub/src/subtitle_format_txt.cpp @@ -123,7 +123,7 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename, line->Text = value; line->End = 0; - target->Line.push_back(*line); + target->Events.push_back(*line); } } @@ -131,7 +131,7 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen size_t num_actor_names = 0, num_dialogue_lines = 0; // Detect number of lines with Actor field filled out - for (auto dia : src->Line | agi::of_type()) { + for (auto dia : src->Events | agi::of_type()) { if (!dia->Comment) { num_dialogue_lines++; if (!dia->Actor.get().empty()) @@ -147,7 +147,7 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen file.WriteLineToFile(std::string("# Exported by Aegisub ") + GetAegisubShortVersionString()); // Write the file - for (auto dia : src->Line | agi::of_type()) { + for (auto dia : src->Events | agi::of_type()) { std::string out_line; if (dia->Comment) diff --git a/aegisub/src/subtitles_provider_libass.cpp b/aegisub/src/subtitles_provider_libass.cpp index 8c7152990..2e4e66008 100644 --- a/aegisub/src/subtitles_provider_libass.cpp +++ b/aegisub/src/subtitles_provider_libass.cpp @@ -118,13 +118,19 @@ void LibassSubtitlesProvider::LoadSubtitles(AssFile *subs) { data.reserve(0x4000); AssEntryGroup group = AssEntryGroup::GROUP_MAX; - for (auto const& line : subs->Line) { - if (group != line.Group()) { - group = line.Group(); - boost::push_back(data, line.GroupHeader() + "\r\n"); + auto write_group = [&](EntryList const& list) { + for (auto const& line : list) { + if (group != line.Group()) { + group = line.Group(); + boost::push_back(data, line.GroupHeader() + "\r\n"); + } + boost::push_back(data, line.GetEntryData() + "\r\n"); } - boost::push_back(data, line.GetEntryData() + "\r\n"); - } + }; + + write_group(subs->Info); + write_group(subs->Styles); + write_group(subs->Events); if (ass_track) ass_free_track(ass_track); ass_track = ass_read_memory(library, &data[0], data.size(), nullptr); diff --git a/aegisub/src/threaded_frame_source.cpp b/aegisub/src/threaded_frame_source.cpp index 9cf073376..87b37a297 100644 --- a/aegisub/src/threaded_frame_source.cpp +++ b/aegisub/src/threaded_frame_source.cpp @@ -71,9 +71,9 @@ std::shared_ptr ThreadedFrameSource::ProcFrame(int frame_number, dou // instead muck around with its innards to just temporarily // remove the non-visible lines without deleting them std::deque full; - for (auto& line : subs->Line) + for (auto& line : subs->Events) full.push_back(&line); - subs->Line.remove_if([=](AssEntry const& e) -> bool { + subs->Events.remove_if([=](AssEntry const& e) -> bool { const AssDialogue *diag = dynamic_cast(&e); return diag && (diag->Start > time || diag->End <= time); }); @@ -81,12 +81,12 @@ std::shared_ptr ThreadedFrameSource::ProcFrame(int frame_number, dou try { subs_provider->LoadSubtitles(subs.get()); - subs->Line.clear(); - boost::push_back(subs->Line, full | boost::adaptors::indirected); + subs->Events.clear(); + boost::push_back(subs->Events, full | boost::adaptors::indirected); } catch (...) { - subs->Line.clear(); - boost::push_back(subs->Line, full | boost::adaptors::indirected); + subs->Events.clear(); + boost::push_back(subs->Events, full | boost::adaptors::indirected); throw; } } @@ -140,7 +140,7 @@ void ThreadedFrameSource::UpdateSubtitles(const AssFile *new_subs, std::set> changed; size_t i = 0; - for (auto const& e : new_subs->Line) { + for (auto const& e : new_subs->Events) { if (changes.count(&e)) changed.emplace_back(i, e.Clone()); ++i; @@ -148,11 +148,11 @@ void ThreadedFrameSource::UpdateSubtitles(const AssFile *new_subs, std::setAsync([=]{ size_t i = 0; - auto it = subs->Line.begin(); + auto it = subs->Events.begin(); for (auto& update : changed) { advance(it, update.first - i); i = update.first; - subs->Line.insert(it, *update.second); + subs->Events.insert(it, *update.second); delete &*it--; } diff --git a/aegisub/src/visual_tool_drag.cpp b/aegisub/src/visual_tool_drag.cpp index 4f8c75e84..3dd7b49c4 100644 --- a/aegisub/src/visual_tool_drag.cpp +++ b/aegisub/src/visual_tool_drag.cpp @@ -115,7 +115,7 @@ void VisualToolDrag::OnFileChanged() { primary = nullptr; active_feature = nullptr; - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { if (IsDisplayed(diag)) MakeFeatures(diag); } @@ -130,7 +130,7 @@ void VisualToolDrag::OnFrameChanged() { auto feat = features.begin(); auto end = features.end(); - for (auto diag : c->ass->Line | agi::of_type()) { + for (auto diag : c->ass->Events | agi::of_type()) { if (IsDisplayed(diag)) { // Features don't exist and should if (feat == end || feat->line != diag)