From 83761d881a64785421cb8051975f3ca3040f023b Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 12 Oct 2012 10:16:39 -0700 Subject: [PATCH] Convert AssFile::Line to an intrusive list Gives O(1) pointer -> iterator conversions, better memory usage, better performance, and overall slightly simplifies the code using it. --- .../aegisub_vs2008/aegisub_vs2008.vcproj | 1 + .../aegisub_vs2008/compiler_options.vsprops | 2 +- aegisub/src/agi_pre.h | 5 +- aegisub/src/ass_entry.h | 5 +- aegisub/src/ass_export_filter.cpp | 1 - aegisub/src/ass_file.cpp | 126 +++++++++--------- aegisub/src/ass_file.h | 16 ++- aegisub/src/ass_karaoke.cpp | 6 +- aegisub/src/ass_parser.cpp | 20 +-- aegisub/src/audio_timing_dialogue.cpp | 27 ++-- aegisub/src/auto4_lua.cpp | 4 +- aegisub/src/auto4_lua_assfile.cpp | 10 +- aegisub/src/base_grid.cpp | 2 +- aegisub/src/command/edit.cpp | 50 +++---- aegisub/src/command/grid.cpp | 15 +-- aegisub/src/command/subtitle.cpp | 14 +- aegisub/src/command/time.cpp | 2 +- aegisub/src/dialog_attachments.cpp | 26 ++-- aegisub/src/dialog_fonts_collector.cpp | 2 +- aegisub/src/dialog_kara_timing_copy.cpp | 50 ++++--- aegisub/src/dialog_kara_timing_copy.h | 23 +--- aegisub/src/dialog_resample.cpp | 6 +- aegisub/src/dialog_search_replace.cpp | 4 +- aegisub/src/dialog_selection.cpp | 2 +- aegisub/src/dialog_shift_times.cpp | 2 +- aegisub/src/dialog_spellchecker.cpp | 4 +- aegisub/src/dialog_style_editor.cpp | 2 +- aegisub/src/dialog_style_manager.cpp | 12 +- aegisub/src/dialog_timing_processor.cpp | 1 - aegisub/src/dialog_translation.cpp | 4 +- aegisub/src/export_fixstyle.cpp | 2 +- aegisub/src/export_framerate.cpp | 2 +- aegisub/src/font_file_lister.cpp | 23 ++-- aegisub/src/font_file_lister.h | 6 +- aegisub/src/subs_edit_box.cpp | 2 +- aegisub/src/subs_edit_ctrl.cpp | 2 +- aegisub/src/subs_grid.cpp | 3 - aegisub/src/subs_preview.cpp | 2 +- aegisub/src/subtitle_format.cpp | 79 ++++++----- aegisub/src/subtitle_format.h | 14 +- aegisub/src/subtitle_format_ass.cpp | 11 +- aegisub/src/subtitle_format_ebu3264.cpp | 8 +- aegisub/src/subtitle_format_encore.cpp | 14 +- aegisub/src/subtitle_format_microdvd.cpp | 16 +-- aegisub/src/subtitle_format_srt.cpp | 36 ++--- aegisub/src/subtitle_format_srt.h | 2 +- aegisub/src/subtitle_format_transtation.cpp | 10 +- aegisub/src/subtitle_format_ttxt.cpp | 28 ++-- aegisub/src/subtitle_format_ttxt.h | 2 +- aegisub/src/subtitle_format_txt.cpp | 57 ++++---- aegisub/src/threaded_frame_source.cpp | 27 ++-- aegisub/src/utils.h | 12 +- aegisub/src/visual_tool_drag.cpp | 4 +- 53 files changed, 384 insertions(+), 422 deletions(-) diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj index e27157b09..f64dd3386 100644 --- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj +++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj @@ -21,6 +21,7 @@ #include #include - #else - #include #include #include @@ -82,6 +80,9 @@ #include #endif +#include +#include + ///////////////////// // wxWidgets headers #include // Leave this first. diff --git a/aegisub/src/ass_entry.h b/aegisub/src/ass_entry.h index 51ae4ecb4..f2c3d5adc 100644 --- a/aegisub/src/ass_entry.h +++ b/aegisub/src/ass_entry.h @@ -32,13 +32,14 @@ /// @ingroup subs_storage /// - #pragma once #ifndef AGI_PRE #include #endif +#include + enum AssEntryType { ENTRY_BASE, ENTRY_DIALOGUE, @@ -46,7 +47,7 @@ enum AssEntryType { ENTRY_ATTACHMENT }; -class AssEntry { +class AssEntry : public boost::intrusive::make_list_base_hook >::type { /// Raw data, exactly the same line that appears on the .ass (note that this will be in ass even if source wasn't) wxString data; diff --git a/aegisub/src/ass_export_filter.cpp b/aegisub/src/ass_export_filter.cpp index 1f9b6c9f5..d32769fb1 100644 --- a/aegisub/src/ass_export_filter.cpp +++ b/aegisub/src/ass_export_filter.cpp @@ -39,7 +39,6 @@ #endif #include "ass_export_filter.h" -#include "ass_file.h" #include "utils.h" AssExportFilter::AssExportFilter(wxString const& name, wxString const& description, int priority, bool auto_apply) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index 005915d76..95dc0e713 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -33,6 +33,8 @@ #include "config.h" +#include "ass_file.h" + #ifndef AGI_PRE #include #include @@ -46,7 +48,6 @@ #include "ass_attachment.h" #include "ass_dialogue.h" -#include "ass_file.h" #include "ass_override.h" #include "ass_style.h" #include "compat.h" @@ -87,7 +88,7 @@ void AssFile::Load(const wxString &_filename, wxString const& charset) { // 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) { - AssEntryType type = (*it)->GetType(); + AssEntryType type = it->GetType(); if (type == ENTRY_STYLE) found_style = true; if (type == ENTRY_DIALOGUE) found_dialogue = true; if (found_style && found_dialogue) break; @@ -180,7 +181,7 @@ void AssFile::SaveMemory(std::vector &dst) { // Write file for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) { - wxCharBuffer buffer = ((*cur)->GetEntryData() + "\r\n").utf8_str(); + wxCharBuffer buffer = (cur->GetEntryData() + "\r\n").utf8_str(); copy(buffer.data(), buffer.data() + buffer.length(), back_inserter(dst)); } } @@ -208,25 +209,25 @@ void AssFile::LoadDefault(bool defline) { Clear(); // Write headers - Line.push_back(new AssEntry("[Script Info]", "[Script Info]")); - Line.push_back(new AssEntry("Title: Default Aegisub file", "[Script Info]")); - Line.push_back(new AssEntry("ScriptType: v4.00+", "[Script Info]")); - Line.push_back(new AssEntry("WrapStyle: 0", "[Script Info]")); - Line.push_back(new AssEntry("ScaledBorderAndShadow: yes", "[Script Info]")); - Line.push_back(new AssEntry("Collisions: Normal", "[Script Info]")); + Line.push_back(*new AssEntry("[Script Info]", "[Script Info]")); + Line.push_back(*new AssEntry("Title: Default Aegisub file", "[Script Info]")); + Line.push_back(*new AssEntry("ScriptType: v4.00+", "[Script Info]")); + Line.push_back(*new AssEntry("WrapStyle: 0", "[Script Info]")); + Line.push_back(*new AssEntry("ScaledBorderAndShadow: yes", "[Script Info]")); + Line.push_back(*new AssEntry("Collisions: Normal", "[Script Info]")); if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) { - Line.push_back(new AssEntry(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), "[Script Info]")); - Line.push_back(new AssEntry(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), "[Script Info]")); + Line.push_back(*new AssEntry(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), "[Script Info]")); + Line.push_back(*new AssEntry(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), "[Script Info]")); } - Line.push_back(new AssEntry("YCbCr Matrix: None", "[Script Info]")); + Line.push_back(*new AssEntry("YCbCr Matrix: None", "[Script Info]")); InsertStyle(new AssStyle); - 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(*new AssEntry("[Events]", "[Events]")); + Line.push_back(*new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]")); if (defline) - Line.push_back(new AssDialogue); + Line.push_back(*new AssDialogue); autosavedCommitId = savedCommitId = commitId + 1; Commit("", COMMIT_NEW); @@ -237,10 +238,11 @@ void AssFile::LoadDefault(bool defline) { void AssFile::swap(AssFile &that) throw() { // Intentionally does not swap undo stack related things - std::swap(loaded, that.loaded); - std::swap(commitId, that.commitId); - std::swap(undoDescription, that.undoDescription); - std::swap(Line, that.Line); + using std::swap; + swap(loaded, that.loaded); + swap(commitId, that.commitId); + swap(undoDescription, that.undoDescription); + swap(Line, that.Line); } AssFile::AssFile(const AssFile &from) @@ -249,22 +251,22 @@ AssFile::AssFile(const AssFile &from) , filename(from.filename) , loaded(from.loaded) { - std::transform(from.Line.begin(), from.Line.end(), std::back_inserter(Line), std::mem_fun(&AssEntry::Clone)); + Line.clone_from(from.Line, std::mem_fun_ref(&AssEntry::Clone), delete_ptr()); } AssFile& AssFile::operator=(AssFile from) { std::swap(*this, from); return *this; } -static bool try_insert(std::list &lines, AssEntry *entry) { +static bool try_insert(EntryList &lines, AssEntry *entry) { if (lines.empty()) return false; // Search for insertion point - std::list::iterator it = lines.end(); + entryIter it = lines.end(); do { --it; - if ((*it)->group == entry->group) { - lines.insert(++it, entry); + if (it->group == entry->group) { + lines.insert(++it, *entry); return true; } } while (it != lines.begin()); @@ -276,17 +278,17 @@ 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]")); - Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "[V4+ Styles]")); - Line.push_back(style); + Line.push_back(*new AssEntry("[V4+ Styles]", "[V4+ Styles]")); + Line.push_back(*new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "[V4+ Styles]")); + Line.push_back(*style); } void AssFile::InsertAttachment(AssAttachment *attach) { 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)); - Line.push_back(attach); + Line.push_back(*new AssEntry(attach->group, attach->group)); + Line.push_back(*attach); } void AssFile::InsertAttachment(wxString filename) { @@ -306,9 +308,9 @@ 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); + 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) const { @@ -316,10 +318,10 @@ wxString AssFile::GetScriptInfo(wxString key) const { key += ":"; bool GotIn = false; - for (std::list::const_iterator cur = Line.begin(); cur != Line.end(); ++cur) { - if ((*cur)->group == "[Script Info]") { + for (constEntryIter cur = Line.begin(); cur != Line.end(); ++cur) { + if (cur->group == "[Script Info]") { GotIn = true; - wxString curText = (*cur)->GetEntryData(); + wxString curText = cur->GetEntryData(); if (curText.Lower().StartsWith(key)) return curText.Mid(key.size()).Trim(true).Trim(false); } @@ -338,21 +340,21 @@ int AssFile::GetScriptInfoAsInt(wxString const& key) const { void AssFile::SetScriptInfo(wxString const& key, wxString const& value) { wxString search_key = key.Lower() + ":"; size_t key_size = search_key.size(); - std::list::iterator script_info_end; + entryIter script_info_end; bool found_script_info = false; - for (std::list::iterator cur = Line.begin(); cur != Line.end(); ++cur) { - if ((*cur)->group == "[Script Info]") { + for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) { + if (cur->group == "[Script Info]") { found_script_info = true; - wxString cur_text = (*cur)->GetEntryData().Left(key_size).Lower(); + wxString cur_text = cur->GetEntryData().Left(key_size).Lower(); if (cur_text == search_key) { if (value.empty()) { - delete *cur; + delete &*cur; Line.erase(cur); } else { - (*cur)->SetEntryData(key + ": " + value); + cur->SetEntryData(key + ": " + value); } return; } @@ -360,7 +362,7 @@ void AssFile::SetScriptInfo(wxString const& key, wxString const& value) { } else if (found_script_info) { if (value.size()) - Line.insert(script_info_end, new AssEntry(key + ": " + value, "[Script Info]")); + Line.insert(script_info_end, *new AssEntry(key + ": " + value, "[Script Info]")); return; } } @@ -368,11 +370,11 @@ void AssFile::SetScriptInfo(wxString const& key, wxString const& value) { // Found a script info section, but not this key or anything after it, // so add it at the end of the file if (found_script_info) - Line.push_back(new AssEntry(key + ": " + value, "[Script Info]")); + Line.push_back(*new AssEntry(key + ": " + value, "[Script Info]")); // Script info section not found, so add it at the beginning of the file else { - Line.push_front(new AssEntry(key + ": " + value, "[Script Info]")); - Line.push_front(new AssEntry("[Script Info]", "[Script Info]")); + Line.push_front(*new AssEntry(key + ": " + value, "[Script Info]")); + Line.push_front(*new AssEntry("[Script Info]", "[Script Info]")); } } @@ -400,8 +402,8 @@ void AssFile::GetResolution(int &sw,int &sh) const { wxArrayString AssFile::GetStyles() const { wxArrayString styles; - for (std::list::const_iterator cur = Line.begin(); cur != Line.end(); ++cur) { - if (AssStyle *curstyle = dynamic_cast(*cur)) + for (constEntryIter cur = Line.begin(); cur != Line.end(); ++cur) { + if (const AssStyle *curstyle = dynamic_cast(&*cur)) styles.Add(curstyle->name); } return styles; @@ -409,7 +411,7 @@ wxArrayString AssFile::GetStyles() const { AssStyle *AssFile::GetStyle(wxString const& name) { for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) { - AssStyle *curstyle = dynamic_cast(*cur); + AssStyle *curstyle = dynamic_cast(&*cur); if (curstyle && curstyle->name == name) return curstyle; } @@ -430,12 +432,12 @@ int AssFile::Commit(wxString const& desc, int type, int amendId, AssEntry *singl // If only one line changed just modify it instead of copying the file if (single_line) { entryIter this_it = Line.begin(), undo_it = UndoStack.back().Line.begin(); - while (*this_it != single_line) { + while (&*this_it != single_line) { ++this_it; ++undo_it; } - delete *undo_it; - *undo_it = single_line->Clone(); + UndoStack.back().Line.insert(undo_it, *single_line->Clone()); + delete &*undo_it; } else { UndoStack.back() = *this; @@ -467,7 +469,7 @@ void AssFile::Undo() { if (UndoStack.size() <= 1) return; RedoStack.push_back(AssFile()); - std::swap(RedoStack.back(), *this); + swap(RedoStack.back()); UndoStack.pop_back(); *this = UndoStack.back(); @@ -477,7 +479,7 @@ void AssFile::Undo() { void AssFile::Redo() { if (RedoStack.empty()) return; - std::swap(*this, RedoStack.back()); + swap(RedoStack.back()); UndoStack.push_back(*this); RedoStack.pop_back(); @@ -515,10 +517,10 @@ void AssFile::Sort(CompFunc comp, std::set const& limit) { Sort(Line, comp, limit); } namespace { - struct AssEntryComp : public std::binary_function { + struct AssEntryComp : public std::binary_function { AssFile::CompFunc comp; - bool operator()(const AssEntry* a, const AssEntry* b) const { - return comp(static_cast(a), static_cast(b)); + bool operator()(AssEntry const&a, AssEntry const&b) const { + return comp(static_cast(&a), static_cast(&b)); } }; @@ -527,17 +529,18 @@ namespace { return d && (limit.empty() || limit.count(d)); } } -void AssFile::Sort(std::list &lst, CompFunc comp, std::set const& limit) { + +void AssFile::Sort(EntryList &lst, CompFunc comp, std::set const& limit) { AssEntryComp compE; compE.comp = comp; // Sort each block of AssDialogues separately, leaving everything else untouched for (entryIter begin = lst.begin(); begin != lst.end(); ++begin) { - if (!is_dialogue(*begin, limit)) continue; + if (!is_dialogue(&*begin, limit)) continue; entryIter end = begin; - while (end != lst.end() && is_dialogue(*end, limit)) ++end; + while (end != lst.end() && is_dialogue(&*end, limit)) ++end; // used instead of std::list::sort for partial list sorting - std::list tmp; + EntryList tmp; tmp.splice(tmp.begin(), lst, begin, end); tmp.sort(compE); lst.splice(end, tmp); @@ -545,8 +548,5 @@ void AssFile::Sort(std::list &lst, CompFunc comp, std::set &lst, CompFunc comp) { - lst.sort(comp); -} AssFile *AssFile::top; diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index baf3e1929..8d15d41da 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -41,14 +41,19 @@ #include #endif +#include + #include +#include "ass_entry.h" + class AssDialogue; class AssStyle; class AssAttachment; -class AssEntry; -typedef std::list::iterator entryIter; +typedef boost::intrusive::make_list >::type EntryList; +typedef EntryList::iterator entryIter; +typedef EntryList::const_iterator constEntryIter; /// DOCME /// @class AssFile @@ -78,7 +83,7 @@ class AssFile { public: /// The lines in the file - std::list Line; + EntryList Line; /// The filename of this file, if any wxString filename; /// Is the file loaded? @@ -229,8 +234,5 @@ public: /// @brief Sort the dialogue lines in the given list /// @param comp Comparison function to use. Defaults to sorting by start time. /// @param limit If non-empty, only lines in this set are sorted - static void Sort(std::list& lst, CompFunc comp = CompStart, std::set const& limit = std::set()); - /// @brief Sort the dialogue lines in the given list - /// @param comp Comparison function to use. Defaults to sorting by start time. - static void Sort(std::list& lst, CompFunc comp = CompStart); + static void Sort(EntryList& lst, CompFunc comp = CompStart, std::set const& limit = std::set()); }; diff --git a/aegisub/src/ass_karaoke.cpp b/aegisub/src/ass_karaoke.cpp index 00300d417..ec2ca9da0 100644 --- a/aegisub/src/ass_karaoke.cpp +++ b/aegisub/src/ass_karaoke.cpp @@ -291,8 +291,8 @@ void AssKaraoke::SplitLines(std::set const& lines, agi::Context *c SubtitleSelection sel = c->selectionController->GetSelectedSet(); bool did_split = false; - for (std::list::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { + AssDialogue *diag = dynamic_cast(&*it); if (!diag || !lines.count(diag)) continue; kara.SetLine(diag); @@ -311,7 +311,7 @@ void AssKaraoke::SplitLines(std::set const& lines, agi::Context *c new_line->End = kit->start_time + kit->duration; new_line->Text = kit->GetText(false); - c->ass->Line.insert(it, new_line); + c->ass->Line.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 24903ae17..b1c23b43a 100644 --- a/aegisub/src/ass_parser.cpp +++ b/aegisub/src/ass_parser.cpp @@ -51,7 +51,7 @@ void AssParser::ParseAttachmentLine(wxString const& data) { // Data is over, add attachment to the file if (!valid_data || is_filename) { attach->Finish(); - target->Line.push_back(attach.release()); + target->Line.push_back(*attach.release()); AddLine(data); } else { @@ -60,7 +60,7 @@ void AssParser::ParseAttachmentLine(wxString const& data) { // Done building if (data.Length() < 80) { attach->Finish(); - target->Line.push_back(attach.release()); + target->Line.push_back(*attach.release()); } } } @@ -68,7 +68,7 @@ void AssParser::ParseAttachmentLine(wxString const& data) { void AssParser::ParseScriptInfoLine(wxString const& data) { // If the first nonblank line isn't a header pretend it starts with [Script Info] if (target->Line.empty()) - target->Line.push_back(new AssEntry("[Script Info]", "[Script Info]")); + target->Line.push_back(*new AssEntry("[Script Info]", "[Script Info]")); if (data.StartsWith(";")) { // Skip stupid comments added by other programs @@ -91,21 +91,21 @@ void AssParser::ParseScriptInfoLine(wxString const& data) { } } - target->Line.push_back(new AssEntry(data, "[Script Info]")); + target->Line.push_back(*new AssEntry(data, "[Script Info]")); } void AssParser::ParseEventLine(wxString const& data) { if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:")) - target->Line.push_back(new AssDialogue(data)); + target->Line.push_back(*new AssDialogue(data)); else if (data.StartsWith("Format:")) - target->Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]")); + target->Line.push_back(*new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]")); } void AssParser::ParseStyleLine(wxString const& data) { if (data.StartsWith("Style:")) - target->Line.push_back(new AssStyle(data, version)); + target->Line.push_back(*new AssStyle(data, version)); else if (data.StartsWith("Format:")) - target->Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "[V4+ Styles]")); + target->Line.push_back(*new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "[V4+ Styles]")); } void AssParser::ParseFontLine(wxString const& data) { @@ -121,7 +121,7 @@ void AssParser::ParseGraphicsLine(wxString const& data) { } void AssParser::AppendUnknownLine(wxString const& data) { - target->Line.push_back(new AssEntry(data, target->Line.back()->group)); + target->Line.push_back(*new AssEntry(data, target->Line.back().group)); } void AssParser::AddLine(wxString const& data) { @@ -166,7 +166,7 @@ void AssParser::AddLine(wxString const& data) { state = &AssParser::AppendUnknownLine; } - target->Line.push_back(new AssEntry(header, header)); + target->Line.push_back(*new AssEntry(header, header)); return; } diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp index 7e37d0255..c82329b74 100644 --- a/aegisub/src/audio_timing_dialogue.cpp +++ b/aegisub/src/audio_timing_dialogue.cpp @@ -720,21 +720,21 @@ void AudioTimingControllerDialogue::SetMarkers(std::vector const& AnnounceMarkerMoved(); } -static bool noncomment_dialogue(AssEntry *e) +static bool noncomment_dialogue(AssEntry const& e) { - if (AssDialogue *diag = dynamic_cast(e)) + if (const AssDialogue *diag = dynamic_cast(&e)) return !diag->Comment; return false; } -static bool dialogue(AssEntry *e) +static bool dialogue(AssEntry const& e) { - return !!dynamic_cast(e); + return !!dynamic_cast(&e); } void AudioTimingControllerDialogue::RegenerateInactiveLines() { - bool (*predicate)(AssEntry*) = inactive_line_comments->GetBool() ? dialogue : noncomment_dialogue; + bool (*predicate)(AssEntry const&) = inactive_line_comments->GetBool() ? dialogue : noncomment_dialogue; bool was_empty = inactive_lines.empty(); inactive_lines.clear(); @@ -747,32 +747,31 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines() case 2: // Previous and next lines if (AssDialogue *line = context->selectionController->GetActiveLine()) { - std::list::iterator current_line = - find(context->ass->Line.begin(), context->ass->Line.end(), line); + entryIter current_line = context->ass->Line.iterator_to(*line); if (current_line == context->ass->Line.end()) break; - std::list::iterator prev = current_line; + entryIter prev = current_line; while (--prev != context->ass->Line.begin() && !predicate(*prev)) ; if (prev != context->ass->Line.begin()) - AddInactiveLine(sel, static_cast(*prev)); + AddInactiveLine(sel, static_cast(&*prev)); if (mode == 2) { - std::list::iterator next = + entryIter next = find_if(++current_line, context->ass->Line.end(), predicate); if (next != context->ass->Line.end()) - AddInactiveLine(sel, static_cast(*next)); + AddInactiveLine(sel, static_cast(&*next)); } } break; case 3: // All inactive lines { AssDialogue *active_line = context->selectionController->GetActiveLine(); - for (std::list::const_iterator it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) + for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) { - if (*it != active_line && predicate(*it)) - AddInactiveLine(sel, static_cast(*it)); + if (&*it != active_line && predicate(*it)) + AddInactiveLine(sel, static_cast(&*it)); } break; } diff --git a/aegisub/src/auto4_lua.cpp b/aegisub/src/auto4_lua.cpp index 4d111aa44..67f2d66b4 100644 --- a/aegisub/src/auto4_lua.cpp +++ b/aegisub/src/auto4_lua.cpp @@ -843,7 +843,7 @@ namespace Automation4 { int row = 1; int idx = 1; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it, ++row) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; if (diag == active_line) active_idx = row; @@ -935,7 +935,7 @@ namespace Automation4 { advance(it, cur - last_idx); - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) { wxLogError("Selected row %d is not a dialogue line", cur); break; diff --git a/aegisub/src/auto4_lua_assfile.cpp b/aegisub/src/auto4_lua_assfile.cpp index 7ddacc04e..3a4a13fa7 100644 --- a/aegisub/src/auto4_lua_assfile.cpp +++ b/aegisub/src/auto4_lua_assfile.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include #endif @@ -660,14 +662,14 @@ namespace Automation4 { // Apply any pending commits for (std::deque::iterator it = pending_commits.begin(); it != pending_commits.end(); ++it) { ass->Line.clear(); - ass->Line.insert(ass->Line.end(), it->lines.begin(), it->lines.end()); + boost::push_back(ass->Line, it->lines | boost::adaptors::indirected); ass->Commit(it->mesage, it->modification_type); } // Commit any changes after the last undo point was set if (modification_type) { ass->Line.clear(); - ass->Line.insert(ass->Line.end(), lines.begin(), lines.end()); + boost::push_back(ass->Line, lines | boost::adaptors::indirected); } if (modification_type && can_set_undo && !undo_description.empty()) ass->Commit(undo_description, modification_type); @@ -691,8 +693,10 @@ namespace Automation4 { , can_set_undo(can_set_undo) , modification_type(0) , references(2) - , lines(ass->Line.begin(), ass->Line.end()) { + for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ++it) + lines.push_back(&*it); + // prepare userdata object *static_cast(lua_newuserdata(L, sizeof(LuaAssFile*))) = this; diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index 6a942c6ed..648267b69 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -279,7 +279,7 @@ void BaseGrid::UpdateMaps(bool preserve_selected_rows) { line_index_map.clear(); for (entryIter cur = context->ass->Line.begin(); cur != context->ass->Line.end(); ++cur) { - if (AssDialogue *curdiag = dynamic_cast(*cur)) { + if (AssDialogue *curdiag = dynamic_cast(&*cur)) { 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 29016246a..d61c61ada 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -86,7 +86,7 @@ void paste_lines(agi::Context *c, bool paste_over) { if (!data) return; AssDialogue *rel_line = c->selectionController->GetActiveLine(); - entryIter pos = find(c->ass->Line.begin(), c->ass->Line.end(), rel_line); + entryIter pos = c->ass->Line.iterator_to(*rel_line); AssDialogue *first = 0; SubtitleSelection newsel; @@ -118,7 +118,7 @@ void paste_lines(agi::Context *c, bool paste_over) { if (!paste_over) { newsel.insert(curdiag); - c->ass->Line.insert(pos, curdiag); + c->ass->Line.insert(pos, *curdiag); } else { // Get list of options to paste over, if not asked yet @@ -131,7 +131,7 @@ void paste_lines(agi::Context *c, bool paste_over) { pasteOverOptions = OPT_GET("Tool/Paste Lines Over/Fields")->GetListBool(); } - AssDialogue *line = static_cast(*pos); + AssDialogue *line = static_cast(&*pos); if (pasteOverOptions[0]) line->Layer = curdiag->Layer; if (pasteOverOptions[1]) line->Start = curdiag->Start; if (pasteOverOptions[2]) line->End = curdiag->End; @@ -147,7 +147,7 @@ void paste_lines(agi::Context *c, bool paste_over) { do { ++pos; - } while (pos != c->ass->Line.end() && !dynamic_cast(*pos)); + } while (pos != c->ass->Line.end() && !dynamic_cast(&*pos)); if (pos == c->ass->Line.end()) break; } @@ -488,7 +488,7 @@ static void copy_lines(agi::Context *c) { wxString data; SubtitleSelection sel = c->selectionController->GetSelectedSet(); for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (diag && sel.count(diag)) { if (!data.empty()) data += "\r\n"; @@ -508,7 +508,7 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) { bool hit_active = false; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; if (diag == active) { @@ -524,10 +524,8 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) { // Delete selected lines for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) { - if (sel.count(static_cast(*it))) { - delete *it; - c->ass->Line.erase(it++); - } + if (sel.count(static_cast(&*it))) + delete &*it++; else ++it; } @@ -598,12 +596,12 @@ struct edit_line_delete : public validate_sel_nonempty { } }; -struct in_selection : public std::unary_function { +struct in_selection : public std::unary_function { SubtitleSelectionController::Selection const& sel; in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { } - bool operator()(AssEntry *e) const { - AssDialogue *d = dynamic_cast(e); - return d && sel.count(d); + bool operator()(AssEntry const& e) const { + const AssDialogue *d = dynamic_cast(&e); + return d && sel.count(const_cast(d)); } }; @@ -612,24 +610,24 @@ static void duplicate_lines(agi::Context *c, bool shift) { SubtitleSelectionController::Selection new_sel; AssDialogue *new_active = 0; - std::list::iterator start = c->ass->Line.begin(); - std::list::iterator end = c->ass->Line.end(); + entryIter start = c->ass->Line.begin(); + entryIter end = c->ass->Line.end(); while (start != end) { // Find the first line in the selection start = find_if(start, end, sel); if (start == end) break; // And the last line in this contiguous selection - std::list::iterator insert_pos = find_if(start, end, std::not1(sel)); - std::list::iterator last = insert_pos; + entryIter insert_pos = find_if(start, end, std::not1(sel)); + entryIter last = insert_pos; --last; // Duplicate each of the selected lines, inserting them in a block // after the selected block do { - AssDialogue *new_diag = static_cast((*start)->Clone()); + AssDialogue *new_diag = static_cast(start->Clone()); - c->ass->Line.insert(insert_pos, new_diag); + c->ass->Line.insert(insert_pos, *new_diag); new_sel.insert(new_diag); if (!new_active) new_active = new_diag; @@ -686,26 +684,20 @@ static void combine_lines(agi::Context *c, void (*combiner)(AssDialogue *, AssDi SubtitleSelection sel = c->selectionController->GetSelectedSet(); AssDialogue *first = 0; - entryIter out = c->ass->Line.begin(); - for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); - if (!diag || !sel.count(diag)) { - *out++ = *it; + for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) { + AssDialogue *diag = dynamic_cast(&*it++); + if (!diag || !sel.count(diag)) continue; - } if (!first) { first = diag; - *out++ = *it; continue; } combiner(first, diag); - first->End = std::max(first->End, diag->End); delete diag; } - c->ass->Line.erase(out, c->ass->Line.end()); sel.clear(); sel.insert(first); c->selectionController->SetSelectionAndActive(sel, first); diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp index 83a261bb2..d0600e8d8 100644 --- a/aegisub/src/command/grid.cpp +++ b/aegisub/src/command/grid.cpp @@ -85,8 +85,8 @@ struct grid_line_next_create : public Command { newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt(); newline->Style = cur->Style; - entryIter pos = find(c->ass->Line.begin(), c->ass->Line.end(), cur); - c->ass->Line.insert(++pos, newline); + entryIter pos = c->ass->Line.iterator_to(*cur); + c->ass->Line.insert(++pos, *newline); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); c->selectionController->NextLine(); } @@ -353,13 +353,12 @@ static bool move_one(T begin, T end, U const& value) { size_t move_count = 0; T prev = end; for (; begin != end; ++begin) { - typename U::key_type cur = dynamic_cast(*begin); + typename U::key_type cur = dynamic_cast(&*begin); bool in_set = !!value.count(cur); if (!in_set && cur) prev = begin; else if (in_set && prev != end) { - using std::swap; - swap(*begin, *prev); + begin->swap_nodes(*prev); prev = begin; if (++move_count == value.size()) break; @@ -420,11 +419,7 @@ struct grid_swap : public Command { void operator()(agi::Context *c) { SubtitleSelection sel = c->selectionController->GetSelectedSet(); if (sel.size() == 2) { - entryIter a = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.begin()); - entryIter b = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.rbegin()); - - using std::swap; - swap(*a, *b); + (*sel.begin())->swap_nodes(**sel.rbegin()); c->ass->Commit(_("swap lines"), AssFile::COMMIT_ORDER); } } diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp index 253660532..449d16838 100644 --- a/aegisub/src/command/subtitle.cpp +++ b/aegisub/src/command/subtitle.cpp @@ -129,10 +129,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 = find(c->ass->Line.begin(), c->ass->Line.end(), c->selectionController->GetActiveLine()); + entryIter pos = c->ass->Line.iterator_to(*c->selectionController->GetActiveLine()); if (after) ++pos; - c->ass->Line.insert(pos, def); + c->ass->Line.insert(pos, *def); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); SubtitleSelection sel; @@ -156,7 +156,7 @@ struct subtitle_insert_after : public validate_nonempty_selection { 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); + AssDialogue *diag = dynamic_cast(&*it); // Limit the line to the available time if (diag && diag->Start >= new_line->Start) @@ -165,7 +165,7 @@ struct subtitle_insert_after : public validate_nonempty_selection { // 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->Line.insert(it, *new_line); --it; } } @@ -206,7 +206,7 @@ struct subtitle_insert_before : public validate_nonempty_selection { 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); + AssDialogue *diag = dynamic_cast(&*it); // Limit the line to the available time if (diag && diag->End <= new_line->End) @@ -214,7 +214,7 @@ struct subtitle_insert_before : public validate_nonempty_selection { // 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->Line.insert(it, *new_line); } c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); @@ -408,7 +408,7 @@ struct subtitle_select_visible : public Command { int frame = c->videoController->GetFrameN(); for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (diag && c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame && c->videoController->FrameAtTime(diag->End, agi::vfr::END) >= frame) diff --git a/aegisub/src/command/time.cpp b/aegisub/src/command/time.cpp index d18be7d14..249df269f 100644 --- a/aegisub/src/command/time.cpp +++ b/aegisub/src/command/time.cpp @@ -72,7 +72,7 @@ namespace { size_t found = 0; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; if (sel.count(diag)) { diff --git a/aegisub/src/dialog_attachments.cpp b/aegisub/src/dialog_attachments.cpp index 237198410..e649f5bca 100644 --- a/aegisub/src/dialog_attachments.cpp +++ b/aegisub/src/dialog_attachments.cpp @@ -102,10 +102,8 @@ void DialogAttachments::UpdateList() { listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100); // Fill list - AssAttachment *attach; - for (std::list::iterator cur = ass->Line.begin();cur != ass->Line.end();cur++) { - attach = dynamic_cast(*cur); - if (attach) { + for (entryIter cur = ass->Line.begin();cur != ass->Line.end();cur++) { + if (AssAttachment *attach = dynamic_cast(&*cur)) { // Add item int row = listView->GetItemCount(); listView->InsertItem(row,attach->GetFileName(true)); @@ -210,19 +208,19 @@ void DialogAttachments::OnDelete(wxCommandEvent &) { if (i == -1) return; while (i != -1) { - ass->Line.remove((AssEntry*)wxUIntToPtr(listView->GetItemData(i))); + delete (AssEntry*)wxUIntToPtr(listView->GetItemData(i)); i = listView->GetNextSelected(i); } // Remove empty attachment sections in the file - for (std::list::iterator it = ass->Line.begin(); it != ass->Line.end(); ) { - if ((*it)->GetType() == ENTRY_BASE && ((*it)->group == "[Fonts]" || (*it)->group == "[Graphics]")) { - wxString group = (*it)->group; - std::list::iterator header = it; + for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ) { + if (it->GetType() == ENTRY_BASE && (it->group == "[Fonts]" || it->group == "[Graphics]")) { + wxString group = it->group; + entryIter header = it; bool has_attachments = false; - for (++it; it != ass->Line.end() && (*it)->group == group; ++it) { - if ((*it)->GetType() == ENTRY_ATTACHMENT) { + for (++it; it != ass->Line.end() && it->group == group; ++it) { + if (it->GetType() == ENTRY_ATTACHMENT) { has_attachments = true; break; } @@ -230,10 +228,8 @@ void DialogAttachments::OnDelete(wxCommandEvent &) { // Empty group found, delete it if (!has_attachments) { - while (header != it) { - delete *header; - ass->Line.erase(header++); - } + while (header != it) + delete &*header++; } } else diff --git a/aegisub/src/dialog_fonts_collector.cpp b/aegisub/src/dialog_fonts_collector.cpp index 95b24cc91..921cd1b22 100644 --- a/aegisub/src/dialog_fonts_collector.cpp +++ b/aegisub/src/dialog_fonts_collector.cpp @@ -88,7 +88,7 @@ class FontsCollectorThread : public wxThread { std::vector GetFontPaths(wxString const&, int, bool, std::set const&) { return std::vector(); } } lister; #endif - std::vector paths = FontCollector(callback, lister).GetFontPaths(subs->Line); + std::vector paths = FontCollector(callback, lister).GetFontPaths(subs); if (paths.empty()) return; // Copy fonts diff --git a/aegisub/src/dialog_kara_timing_copy.cpp b/aegisub/src/dialog_kara_timing_copy.cpp index e50f6fcb9..1e38cc236 100644 --- a/aegisub/src/dialog_kara_timing_copy.cpp +++ b/aegisub/src/dialog_kara_timing_copy.cpp @@ -629,15 +629,13 @@ bool KaraokeLineMatchDisplay::UndoMatch() } DialogKanjiTimer::DialogKanjiTimer(agi::Context *c) -: wxDialog(c->parent,-1,_("Kanji timing"),wxDefaultPosition) +: wxDialog(c->parent, -1, _("Kanji timing")) +, subs(c->ass) +, currentSourceLine(0) +, currentDestinationLine(0) { SetIcon(GETICON(kara_timing_copier_16)); - subs = c->ass; - currentSourceLine = subs->Line.begin(); - currentDestinationLine = subs->Line.begin(); - - //Sizers wxSizer *DisplayBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Text")); wxSizer *StylesBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Styles")); wxFlexGridSizer *StylesGridSizer = new wxFlexGridSizer(2, 2, 6, 6); @@ -744,8 +742,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(), SourceStyle->GetValue()); - currentDestinationLine = FindNextStyleMatch(subs->Line.begin(), DestStyle->GetValue()); + currentSourceLine = FindNextStyleMatch(&*subs->Line.begin(), SourceStyle->GetValue()); + currentDestinationLine = FindNextStyleMatch(&*subs->Line.begin(), DestStyle->GetValue()); ResetForNewLine(); } LinesToChange.clear(); @@ -784,11 +782,11 @@ void DialogKanjiTimer::OnGoBack(wxCommandEvent &) { } void DialogKanjiTimer::OnAccept(wxCommandEvent &) { - if (currentDestinationLine == subs->Line.end()) return; + if (!currentDestinationLine) return; if (display->GetRemainingSource() > 0) wxMessageBox(_("Group all of the source text."),_("Error"),wxICON_EXCLAMATION | wxOK); - else if (AssDialogue *destLine = dynamic_cast(*currentDestinationLine)) { + else if (AssDialogue *destLine = dynamic_cast(currentDestinationLine)) { LinesToChange.push_back(std::make_pair(destLine, display->GetOutputLine())); currentSourceLine = FindNextStyleMatch(currentSourceLine, SourceStyle->GetValue()); @@ -834,10 +832,10 @@ void DialogKanjiTimer::ResetForNewLine() AssDialogue *src = 0; AssDialogue *dst = 0; - if (currentSourceLine != subs->Line.end()) - src = dynamic_cast(*currentSourceLine); - if (currentDestinationLine != subs->Line.end()) - dst = dynamic_cast(*currentDestinationLine); + if (currentSourceLine) + src = dynamic_cast(currentSourceLine); + if (currentDestinationLine) + dst = dynamic_cast(currentDestinationLine); if (src == 0 || dst == 0) { @@ -858,30 +856,30 @@ void DialogKanjiTimer::TryAutoMatch() display->AutoMatchJapanese(); } -entryIter DialogKanjiTimer::FindNextStyleMatch(entryIter search_from, const wxString &search_style) +AssEntry *DialogKanjiTimer::FindNextStyleMatch(AssEntry *search_from, const wxString &search_style) { - if (search_from == subs->Line.end()) return search_from; + if (!search_from) return search_from; - while (++search_from != subs->Line.end()) + for (entryIter it = subs->Line.iterator_to(*search_from); it != subs->Line.end(); ++it) { - AssDialogue *dlg = dynamic_cast(*search_from); + AssDialogue *dlg = dynamic_cast(&*it); if (dlg && dlg->Style == search_style) - break; + return dlg; } - return search_from; + return 0; } -entryIter DialogKanjiTimer::FindPrevStyleMatch(entryIter search_from, const wxString &search_style) +AssEntry *DialogKanjiTimer::FindPrevStyleMatch(AssEntry *search_from, const wxString &search_style) { - if (search_from == subs->Line.begin()) return search_from; + if (!search_from) return search_from; - while (--search_from != subs->Line.begin()) + for (EntryList::reverse_iterator it = EntryList::reverse_iterator(subs->Line.iterator_to(*search_from)); it != subs->Line.rend(); ++it) { - AssDialogue *dlg = dynamic_cast(*search_from); + AssDialogue *dlg = dynamic_cast(&*it); if (dlg && dlg->Style == search_style) - break; + return dlg; } - return search_from; + return 0; } diff --git a/aegisub/src/dialog_kara_timing_copy.h b/aegisub/src/dialog_kara_timing_copy.h index ecbbf6c41..ff435eef6 100644 --- a/aegisub/src/dialog_kara_timing_copy.h +++ b/aegisub/src/dialog_kara_timing_copy.h @@ -53,32 +53,17 @@ class wxCheckBox; /// /// DOCME class DialogKanjiTimer : public wxDialog { - typedef std::list::iterator entryIter; - - /// DOCME AssFile *subs; - - /// DOCME KaraokeLineMatchDisplay *display; - /// DOCME - - /// DOCME wxComboBox *SourceStyle, *DestStyle; - - /// DOCME wxCheckBox *Interpolate; - - /// DOCME std::vector > LinesToChange; - /// DOCME - entryIter currentSourceLine; - - /// DOCME - entryIter currentDestinationLine; + AssEntry *currentSourceLine; + AssEntry *currentDestinationLine; void OnClose(wxCommandEvent &event); void OnStart(wxCommandEvent &event); @@ -93,8 +78,8 @@ class DialogKanjiTimer : public wxDialog { void ResetForNewLine(); void TryAutoMatch(); - entryIter FindNextStyleMatch(entryIter search_from, const wxString &search_style); - entryIter FindPrevStyleMatch(entryIter search_from, const wxString &search_style); + AssEntry *FindNextStyleMatch(AssEntry *search_from, const wxString &search_style); + AssEntry *FindPrevStyleMatch(AssEntry *search_from, const wxString &search_style); public: DialogKanjiTimer(agi::Context *context); diff --git a/aegisub/src/dialog_resample.cpp b/aegisub/src/dialog_resample.cpp index aa5eaf47b..c8845f989 100644 --- a/aegisub/src/dialog_resample.cpp +++ b/aegisub/src/dialog_resample.cpp @@ -200,8 +200,8 @@ namespace { cur->Set((cur->Get() + shift) * resizer + 0.5); } - void resample_line(resample_state *state, AssEntry *line) { - AssDialogue *diag = dynamic_cast(line); + void resample_line(resample_state *state, AssEntry &line) { + AssDialogue *diag = dynamic_cast(&line); if (diag && !(diag->Comment && (diag->Effect.StartsWith("template") || diag->Effect.StartsWith("code")))) { diag->ParseAssTags(); diag->ProcessParameters(resample_tags, state); @@ -217,7 +217,7 @@ namespace { diag->UpdateText(); diag->ClearBlocks(); } - else if (AssStyle *style = dynamic_cast(line)) { + else if (AssStyle *style = dynamic_cast(&line)) { style->fontsize = int(style->fontsize * state->ry + 0.5); style->outline_w *= state->ry; style->shadow_w *= state->ry; diff --git a/aegisub/src/dialog_search_replace.cpp b/aegisub/src/dialog_search_replace.cpp index 5c689f53c..5d69f16b7 100644 --- a/aegisub/src/dialog_search_replace.cpp +++ b/aegisub/src/dialog_search_replace.cpp @@ -379,8 +379,8 @@ void SearchReplaceEngine::ReplaceAll() { bool inSel = affect == 1; // Scan - for (std::list::iterator it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) { + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; // Check if row is selected diff --git a/aegisub/src/dialog_selection.cpp b/aegisub/src/dialog_selection.cpp index b2b10a1ba..902ebb545 100644 --- a/aegisub/src/dialog_selection.cpp +++ b/aegisub/src/dialog_selection.cpp @@ -114,7 +114,7 @@ static std::set process(wxString match_text, bool match_case, int std::set matches; for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; 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 b6f6fd6e2..4a8395c9f 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -353,7 +353,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) { json::Array shifted_blocks; for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) { - AssDialogue *line = dynamic_cast(*it); + AssDialogue *line = dynamic_cast(&*it); if (!line) continue; ++row_number; diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp index 1654ea753..b3d696e53 100644 --- a/aegisub/src/dialog_spellchecker.cpp +++ b/aegisub/src/dialog_spellchecker.cpp @@ -213,7 +213,7 @@ bool DialogSpellChecker::FindNext() { if (CheckLine(active_line, start_pos, &commit_id)) return true; - std::list::iterator it = find(context->ass->Line.begin(), context->ass->Line.end(), active_line); + entryIter it = context->ass->Line.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 @@ -225,7 +225,7 @@ bool DialogSpellChecker::FindNext() { it = context->ass->Line.begin(); has_looped = true; } - } while (!(active_line = dynamic_cast(*it))); + } while (!(active_line = dynamic_cast(&*it))); if (CheckLine(active_line, 0, &commit_id)) return true; diff --git a/aegisub/src/dialog_style_editor.cpp b/aegisub/src/dialog_style_editor.cpp index e5264c811..4c623b3ca 100644 --- a/aegisub/src/dialog_style_editor.cpp +++ b/aegisub/src/dialog_style_editor.cpp @@ -88,7 +88,7 @@ class StyleRenamer { do_replace = replace; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; if (diag->Style == source_name) { diff --git a/aegisub/src/dialog_style_manager.cpp b/aegisub/src/dialog_style_manager.cpp index b16817d6c..02cca8797 100644 --- a/aegisub/src/dialog_style_manager.cpp +++ b/aegisub/src/dialog_style_manager.cpp @@ -275,7 +275,7 @@ void DialogStyleManager::LoadCurrentStyles(int commit_type) { styleMap.clear(); for (entryIter cur = c->ass->Line.begin(); cur != c->ass->Line.end(); ++cur) { - if (AssStyle *style = dynamic_cast(*cur)) { + if (AssStyle *style = dynamic_cast(&*cur)) { CurrentList->Append(style->name); styleMap.push_back(style); } @@ -562,10 +562,8 @@ void DialogStyleManager::OnCurrentDelete() { int n = CurrentList->GetSelections(selections); if (confirm_delete(n, this, _("Confirm delete from current")) == wxYES) { - for (int i=0;iass->Line.remove(temp); - delete temp; + for (int i = 0; i < n; i++) { + delete styleMap.at(selections[i]); } c->ass->Commit(_("style delete"), AssFile::COMMIT_STYLES); } @@ -780,8 +778,8 @@ void DialogStyleManager::MoveStyles(bool storage, int type) { for (entryIter cur = c->ass->Line.begin(); cur != c->ass->Line.end(); cur = next) { next = cur; next++; - if (dynamic_cast(*cur)) { - c->ass->Line.insert(cur, styleMap[curn]); + if (dynamic_cast(&*cur)) { + c->ass->Line.insert(cur, *styleMap[curn]); c->ass->Line.erase(cur); curn++; } diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index cbf9beb07..2c1096346 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -304,7 +304,6 @@ std::vector DialogTimingProcessor::SortDialogues() { } std::vector sorted; - sorted.reserve(c->ass->Line.size()); if (onlySelection->IsChecked()) { SubtitleSelection sel = c->selectionController->GetSelectedSet(); diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index 8d2d9773c..b5bf94561 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -69,7 +69,7 @@ DialogTranslation::DialogTranslation(agi::Context *c) , active_line(c->selectionController->GetActiveLine()) , cur_block(0) , line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast())) -, line_number(count_if(c->ass->Line.begin(), find(c->ass->Line.begin(), c->ass->Line.end(), active_line), cast()) + 1) +, line_number(count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*active_line), cast()) + 1) , switching_lines(false) { SetIcon(GETICON(translation_toolbutton_16)); @@ -177,7 +177,7 @@ void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) { active_line = new_line; active_line->ParseAssTags(); cur_block = 0; - line_number = count_if(c->ass->Line.begin(), find(c->ass->Line.begin(), c->ass->Line.end(), active_line), cast()) + 1; + line_number = count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*new_line), cast()) + 1; if (bad_block(active_line->Blocks[cur_block]) && !NextBlock()) { wxMessageBox(_("No more lines to translate.")); diff --git a/aegisub/src/export_fixstyle.cpp b/aegisub/src/export_fixstyle.cpp index 472fc45b6..7e3fd7d23 100644 --- a/aegisub/src/export_fixstyle.cpp +++ b/aegisub/src/export_fixstyle.cpp @@ -54,7 +54,7 @@ void AssFixStylesFilter::ProcessSubs(AssFile *subs, wxWindow *) { styles.Sort(); for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) { - if (AssDialogue *diag = dynamic_cast(*cur)) { + if (AssDialogue *diag = dynamic_cast(&*cur)) { if (!std::binary_search(styles.begin(), styles.end(), diag->Style.Lower())) { diag->Style = "Default"; } diff --git a/aegisub/src/export_framerate.cpp b/aegisub/src/export_framerate.cpp index e24471744..00f0287a0 100644 --- a/aegisub/src/export_framerate.cpp +++ b/aegisub/src/export_framerate.cpp @@ -209,7 +209,7 @@ void AssTransformFramerateFilter::TransformTimeTags(wxString name,int n,AssOverr void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { if (!Input->IsLoaded() || !Output->IsLoaded()) return; for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) { - AssDialogue *curDialogue = dynamic_cast(*cur); + AssDialogue *curDialogue = dynamic_cast(&*cur); if (curDialogue) { line = curDialogue; diff --git a/aegisub/src/font_file_lister.cpp b/aegisub/src/font_file_lister.cpp index 181bf61da..c6209366a 100644 --- a/aegisub/src/font_file_lister.cpp +++ b/aegisub/src/font_file_lister.cpp @@ -24,9 +24,10 @@ #include "font_file_lister.h" #include "ass_dialogue.h" +#include "ass_file.h" #include "ass_override.h" #include "ass_style.h" - +#include "utils.h" #ifndef AGI_PRE #include @@ -44,17 +45,17 @@ FontCollector::FontCollector(FontCollectorStatusCallback status_callback, FontFi { } -void FontCollector::ProcessDialogueLine(AssDialogue *line, int index) { +void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) { if (line->Comment) return; - line->ParseAssTags(); + std::vector blocks = line->ParseTags(); StyleInfo style = styles[line->Style]; StyleInfo initial = style; bool overriden = false; - for (size_t i = 0; i < line->Blocks.size(); ++i) { - if (AssDialogueBlockOverride *ovr = dynamic_cast(line->Blocks[i])) { + for (size_t i = 0; i < blocks.size(); ++i) { + if (AssDialogueBlockOverride *ovr = dynamic_cast(blocks[i])) { for (size_t j = 0; j < ovr->Tags.size(); ++j) { AssOverrideTag *tag = ovr->Tags[j]; wxString name = tag->Name; @@ -77,7 +78,7 @@ void FontCollector::ProcessDialogueLine(AssDialogue *line, int index) { } } } - else if (AssDialogueBlockPlain *txt = dynamic_cast(line->Blocks[i])) { + else if (AssDialogueBlockPlain *txt = dynamic_cast(blocks[i])) { wxString text = txt->GetText(); if (text.empty() || (text.size() >= 2 && text.StartsWith("{") && text.EndsWith("}"))) @@ -102,7 +103,7 @@ void FontCollector::ProcessDialogueLine(AssDialogue *line, int index) { } // Do nothing with drawing blocks } - line->ClearBlocks(); + delete_clear(blocks); } void FontCollector::ProcessChunk(std::pair const& style) { @@ -148,22 +149,22 @@ void FontCollector::PrintUsage(UsageData const& data) { status_callback("\n", 2); } -std::vector FontCollector::GetFontPaths(std::list const& file) { +std::vector FontCollector::GetFontPaths(const AssFile *file) { missing = 0; missing_glyphs = 0; status_callback(_("Parsing file\n"), 0); int index = 0; - for (std::list::const_iterator cur = file.begin(); cur != file.end(); ++cur) { - if (AssStyle *style = dynamic_cast(*cur)) { + for (constEntryIter cur = file->Line.begin(); cur != file->Line.end(); ++cur) { + if (const AssStyle *style = dynamic_cast(&*cur)) { StyleInfo &info = styles[style->name]; info.facename = style->font; info.bold = style->bold; info.italic = style->italic; used_styles[info].styles.insert(style->name); } - else if (AssDialogue *diag = dynamic_cast(*cur)) + else if (const AssDialogue *diag = dynamic_cast(&*cur)) ProcessDialogueLine(diag, ++index); } diff --git a/aegisub/src/font_file_lister.h b/aegisub/src/font_file_lister.h index 7449e8b83..5582ea66a 100644 --- a/aegisub/src/font_file_lister.h +++ b/aegisub/src/font_file_lister.h @@ -31,8 +31,8 @@ #include #endif -class AssEntry; class AssDialogue; +class AssFile; typedef std::tr1::function FontCollectorStatusCallback; @@ -91,7 +91,7 @@ class FontCollector { int missing_glyphs; /// Gather all of the unique styles with text on a line - void ProcessDialogueLine(AssDialogue *line, int index); + void ProcessDialogueLine(const AssDialogue *line, int index); /// Get the font for a single style void ProcessChunk(std::pair const& style); @@ -109,5 +109,5 @@ public: /// @param file Lines in the subtitle file to check /// @param status Callback function for messages /// @return List of paths to fonts - std::vector GetFontPaths(std::list const& file); + std::vector GetFontPaths(const AssFile *file); }; diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 96e110c4d..48fae1fa0 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -316,7 +316,7 @@ void SubsEditBox::PopulateList(wxComboBox *combo, wxString AssDialogue::*field) std::set values; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - if (AssDialogue *diag = dynamic_cast(*it)) + if (AssDialogue *diag = dynamic_cast(&*it)) values.insert(diag->*field); } values.erase(""); diff --git a/aegisub/src/subs_edit_ctrl.cpp b/aegisub/src/subs_edit_ctrl.cpp index e11d6ba31..8a45a0d87 100644 --- a/aegisub/src/subs_edit_ctrl.cpp +++ b/aegisub/src/subs_edit_ctrl.cpp @@ -853,7 +853,7 @@ void SubsTextEditCtrl::SplitLine(bool estimateTimes) { AssDialogue *n1 = context->selectionController->GetActiveLine(); AssDialogue *n2 = new AssDialogue(*n1); - context->ass->Line.insert(++find(context->ass->Line.begin(), context->ass->Line.end(), n1), n2); + context->ass->Line.insert(++context->ass->Line.iterator_to(*n1), *n2); wxString orig = n1->Text; n1->Text = orig.Left(from).Trim(true); // Trim off trailing whitespace diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index 42461c1e6..327b8ebb5 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -91,20 +91,17 @@ void SubtitlesGrid::RecombineLines() { // 1, 1+2 (or 2+1), 2 gets turned into 1, 2, 2 so kill the duplicate if (d1->Text == (*d2)->Text) { expand_times(d1, *d2); - context->ass->Line.remove(d1); delete d1; continue; } // 1, 1+2, 1 turns into 1, 2, [empty] if (d1->Text.empty()) { - context->ass->Line.remove(d1); delete d1; continue; } // If d2 is the last line in the selection it'll never hit the above test if (d2 == end && (*d2)->Text.empty()) { - context->ass->Line.remove(*d2); delete *d2; continue; } diff --git a/aegisub/src/subs_preview.cpp b/aegisub/src/subs_preview.cpp index 13534a5ab..e8e4c34d3 100644 --- a/aegisub/src/subs_preview.cpp +++ b/aegisub/src/subs_preview.cpp @@ -61,7 +61,7 @@ SubtitlesPreview::SubtitlesPreview(wxWindow *parent, wxSize size, int winStyle, subFile->LoadDefault(); subFile->InsertStyle(style); - subFile->Line.push_back(line); + subFile->Line.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 49bfd7a13..07eda799c 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -79,18 +79,18 @@ bool SubtitleFormat::CanWriteFile(wxString const& filename) const { bool SubtitleFormat::CanSave(const AssFile *subs) const { AssStyle defstyle; - for (std::list::const_iterator cur = subs->Line.begin(); cur != subs->Line.end(); ++cur) { + for (constEntryIter cur = subs->Line.begin(); cur != subs->Line.end(); ++cur) { // Check style, if anything non-default is found, return false - if (const AssStyle *curstyle = dynamic_cast(*cur)) { + if (const AssStyle *curstyle = dynamic_cast(&*cur)) { if (curstyle->GetEntryData() != defstyle.GetEntryData()) return false; } // Check for attachments, if any is found, return false - if (dynamic_cast(*cur)) return false; + if (dynamic_cast(&*cur)) return false; // Check dialog - if (const AssDialogue *curdiag = dynamic_cast(*cur)) { + if (const AssDialogue *curdiag = dynamic_cast(&*cur)) { if (curdiag->GetStrippedText() != curdiag->Text) return false; } @@ -163,17 +163,17 @@ agi::vfr::Framerate SubtitleFormat::AskForFPS(bool allow_vfr, bool show_smpte) { return Framerate(); } -void SubtitleFormat::StripTags(LineList &lines) { - for (LineList::iterator cur = lines.begin(); cur != lines.end(); ++cur) { - if (AssDialogue *current = dynamic_cast(*cur)) { +void SubtitleFormat::StripTags(AssFile &file) { + for (entryIter cur = file.Line.begin(); cur != file.Line.end(); ++cur) { + if (AssDialogue *current = dynamic_cast(&*cur)) { current->StripTags(); } } } -void SubtitleFormat::ConvertNewlines(LineList &lines, wxString const& newline, bool mergeLineBreaks) { - for (LineList::iterator cur = lines.begin(); cur != lines.end(); ++cur) { - if (AssDialogue *current = dynamic_cast(*cur)) { +void SubtitleFormat::ConvertNewlines(AssFile &file, wxString const& newline, bool mergeLineBreaks) { + for (entryIter cur = file.Line.begin(); cur != file.Line.end(); ++cur) { + if (AssDialogue *current = dynamic_cast(&*cur)) { current->Text.Replace("\\h", " "); current->Text.Replace("\\n", newline); current->Text.Replace("\\N", newline); @@ -184,59 +184,57 @@ void SubtitleFormat::ConvertNewlines(LineList &lines, wxString const& newline, b } } -void SubtitleFormat::StripComments(LineList &lines) { - for (LineList::iterator it = lines.begin(); it != lines.end(); ) { - AssDialogue *diag = dynamic_cast(*it); +void SubtitleFormat::StripComments(AssFile &file) { + for (entryIter it = file.Line.begin(); it != file.Line.end(); ) { + AssDialogue *diag = dynamic_cast(&*it); if (!diag || (!diag->Comment && diag->Text.size())) ++it; else { - delete *it; - lines.erase(it++); + delete &*it++; } } } -void SubtitleFormat::StripNonDialogue(LineList &lines) { - for (LineList::iterator it = lines.begin(); it != lines.end(); ) { - if (dynamic_cast(*it)) +void SubtitleFormat::StripNonDialogue(AssFile &file) { + for (entryIter it = file.Line.begin(); it != file.Line.end(); ) { + if (dynamic_cast(&*it)) ++it; else { - delete *it; - lines.erase(it++); + delete &*it++; } } } -static bool dialog_start_lt(AssEntry *pos, AssDialogue *to_insert) { - AssDialogue *diag = dynamic_cast(pos); +static bool dialog_start_lt(AssEntry &pos, AssDialogue *to_insert) { + AssDialogue *diag = dynamic_cast(&pos); return diag && diag->Start > to_insert->Start; } /// @brief Split and merge lines so there are no overlapping lines /// /// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge -void SubtitleFormat::RecombineOverlaps(LineList &lines) { - LineList::iterator cur, next = lines.begin(); +void SubtitleFormat::RecombineOverlaps(AssFile &file) { + entryIter cur, next = file.Line.begin(); cur = next++; - for (; next != lines.end(); cur = next++) { - AssDialogue *prevdlg = dynamic_cast(*cur); - AssDialogue *curdlg = dynamic_cast(*next); + for (; next != file.Line.end(); cur = next++) { + AssDialogue *prevdlg = dynamic_cast(&*cur); + AssDialogue *curdlg = dynamic_cast(&*next); if (!curdlg || !prevdlg) continue; if (prevdlg->End <= curdlg->Start) continue; // Use names like in the algorithm description and prepare for erasing // old dialogues from the list - LineList::iterator prev = cur; + entryIter prev = cur; cur = next; next++; // 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. - lines.erase(prev); - lines.erase(cur); + file.Line.erase(prev); + file.Line.erase(cur); //Is there an A part before the overlap? if (curdlg->Start > prevdlg->Start) { @@ -246,7 +244,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) { newdlg->End = curdlg->Start; newdlg->Text = prevdlg->Text; - lines.insert(find_if(next, lines.end(), bind(dialog_start_lt, _1, newdlg)), newdlg); + file.Line.insert(find_if(next, file.Line.end(), bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Overlapping A+B part @@ -257,7 +255,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) { // Put an ASS format hard linewrap between lines newdlg->Text = curdlg->Text + "\\N" + prevdlg->Text; - lines.insert(find_if(next, lines.end(), bind(dialog_start_lt, _1, newdlg)), newdlg); + file.Line.insert(find_if(next, file.Line.end(), bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Is there an A part after the overlap? @@ -268,7 +266,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) { newdlg->End = prevdlg->End; newdlg->Text = prevdlg->Text; - lines.insert(find_if(next, lines.end(), bind(dialog_start_lt, _1, newdlg)), newdlg); + file.Line.insert(find_if(next, file.Line.end(), bind(dialog_start_lt, _1, newdlg)), *newdlg); } // Is there a B part after the overlap? @@ -279,7 +277,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) { newdlg->End = curdlg->End; newdlg->Text = curdlg->Text; - lines.insert(find_if(next, lines.end(), bind(dialog_start_lt, _1, newdlg)), newdlg); + file.Line.insert(find_if(next, file.Line.end(), bind(dialog_start_lt, _1, newdlg)), *newdlg); } next--; @@ -287,13 +285,13 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) { } /// @brief Merge identical lines that follow each other -void SubtitleFormat::MergeIdentical(LineList &lines) { - LineList::iterator cur, next = lines.begin(); +void SubtitleFormat::MergeIdentical(AssFile &file) { + entryIter cur, next = file.Line.begin(); cur = next++; - for (; next != lines.end(); cur = next++) { - AssDialogue *curdlg = dynamic_cast(*cur); - AssDialogue *nextdlg = dynamic_cast(*next); + for (; next != file.Line.end(); cur = next++) { + AssDialogue *curdlg = dynamic_cast(&*cur); + AssDialogue *nextdlg = dynamic_cast(&*next); if (curdlg && nextdlg && curdlg->End == nextdlg->Start && curdlg->Text == nextdlg->Text) { // Merge timing @@ -301,8 +299,7 @@ void SubtitleFormat::MergeIdentical(LineList &lines) { nextdlg->End = std::max(nextdlg->End, curdlg->End); // Remove duplicate line - delete *cur; - lines.erase(cur); + delete curdlg; } } } diff --git a/aegisub/src/subtitle_format.h b/aegisub/src/subtitle_format.h index c235ec3e1..b35f5f47d 100644 --- a/aegisub/src/subtitle_format.h +++ b/aegisub/src/subtitle_format.h @@ -64,24 +64,22 @@ class SubtitleFormat { static std::list formats; public: - typedef std::list LineList; - /// Strip override tags - static void StripTags(LineList &lines); + static void StripTags(AssFile &file); /// Convert newlines to the specified character(s) /// @param lineEnd newline character(s) /// @param mergeLineBreaks Should multiple consecutive line breaks be merged into one? - static void ConvertNewlines(LineList &lines, wxString const& newline, bool mergeLineBreaks = true); + static void ConvertNewlines(AssFile &file, wxString const& newline, bool mergeLineBreaks = true); /// Remove All commented and empty lines - static void StripComments(LineList &lines); + static void StripComments(AssFile &file); /// Remove everything but the dialogue lines - static void StripNonDialogue(LineList &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 - static void RecombineOverlaps(LineList &lines); + static void RecombineOverlaps(AssFile &file); /// Merge sequential identical lines - static void MergeIdentical(LineList &lines); + static void MergeIdentical(AssFile &file); /// Prompt the user for a frame rate to use /// @param allow_vfr Include video frame rate as an option even if it's vfr diff --git a/aegisub/src/subtitle_format_ass.cpp b/aegisub/src/subtitle_format_ass.cpp index 431246301..903f15b94 100644 --- a/aegisub/src/subtitle_format_ass.cpp +++ b/aegisub/src/subtitle_format_ass.cpp @@ -36,7 +36,6 @@ #include "subtitle_format_ass.h" -#include "ass_entry.h" #include "ass_file.h" #include "ass_parser.h" #include "compat.h" @@ -92,14 +91,14 @@ void AssSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, bool ssa = filename.Right(4).Lower() == ".ssa"; - wxString group = src->Line.front()->group; - for (LineList::const_iterator cur = src->Line.begin(); cur != src->Line.end(); ++cur) { + wxString group = src->Line.front().group; + for (constEntryIter cur = src->Line.begin(); cur != src->Line.end(); ++cur) { // Add a blank line between each group - if ((*cur)->group != group) { + if (cur->group != group) { file.WriteLineToFile(""); - group = (*cur)->group; + group = cur->group; } - file.WriteLineToFile(ssa ? (*cur)->GetSSAText() : (*cur)->GetEntryData(), true); + file.WriteLineToFile(ssa ? cur->GetSSAText() : cur->GetEntryData(), true); } } diff --git a/aegisub/src/subtitle_format_ebu3264.cpp b/aegisub/src/subtitle_format_ebu3264.cpp index 0d60481d0..190236184 100644 --- a/aegisub/src/subtitle_format_ebu3264.cpp +++ b/aegisub/src/subtitle_format_ebu3264.cpp @@ -370,10 +370,10 @@ namespace std::vector convert_subtitles(AssFile ©, EbuExportSettings const& export_settings) { - SubtitleFormat::StripComments(copy.Line); + SubtitleFormat::StripComments(copy); copy.Sort(); - SubtitleFormat::RecombineOverlaps(copy.Line); - SubtitleFormat::MergeIdentical(copy.Line); + SubtitleFormat::RecombineOverlaps(copy); + SubtitleFormat::MergeIdentical(copy); int line_wrap_type = copy.GetScriptInfoAsInt("WrapStyle"); @@ -388,7 +388,7 @@ namespace // convert to intermediate format for (entryIter orgline = copy.Line.begin(); orgline != copy.Line.end(); ++orgline) { - AssDialogue *line = dynamic_cast(*orgline); + AssDialogue *line = dynamic_cast(&*orgline); if (!line) continue; // add a new subtitle and work on it diff --git a/aegisub/src/subtitle_format_encore.cpp b/aegisub/src/subtitle_format_encore.cpp index 1c3295ca8..c36809d90 100644 --- a/aegisub/src/subtitle_format_encore.cpp +++ b/aegisub/src/subtitle_format_encore.cpp @@ -62,11 +62,11 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, wxString const& filenam // Convert to encore AssFile copy(*src); copy.Sort(); - StripComments(copy.Line); - RecombineOverlaps(copy.Line); - MergeIdentical(copy.Line); - StripTags(copy.Line); - ConvertNewlines(copy.Line, "\r\n"); + StripComments(copy); + RecombineOverlaps(copy); + MergeIdentical(copy); + StripTags(copy); + ConvertNewlines(copy, "\r\n"); // Encode wants ; for NTSC and : for PAL @@ -77,8 +77,8 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, wxString const& filenam // Write lines int i = 0; TextFileWriter file(filename, "UTF-8"); - for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { - if (AssDialogue *current = dynamic_cast(*cur)) { + for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { + if (const AssDialogue *current = dynamic_cast(&*cur)) { ++i; file.WriteLineToFile(wxString::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 2d4b7c1b6..1415b0e25 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -117,7 +117,7 @@ void MicroDVDSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, 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->Line.push_back(*diag); } } } @@ -128,11 +128,11 @@ void MicroDVDSubtitleFormat::WriteFile(const AssFile *src, wxString const& filen AssFile copy(*src); copy.Sort(); - StripComments(copy.Line); - RecombineOverlaps(copy.Line); - MergeIdentical(copy.Line); - StripTags(copy.Line); - ConvertNewlines(copy.Line, "|"); + StripComments(copy); + RecombineOverlaps(copy); + MergeIdentical(copy); + StripTags(copy); + ConvertNewlines(copy, "|"); TextFileWriter file(filename, encoding); @@ -142,8 +142,8 @@ void MicroDVDSubtitleFormat::WriteFile(const AssFile *src, wxString const& filen } // Write lines - for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { - if (AssDialogue *current = dynamic_cast(*cur)) { + for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { + if (const AssDialogue *current = dynamic_cast(&*cur)) { 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 be67c7202..67ca25bed 100644 --- a/aegisub/src/subtitle_format_srt.cpp +++ b/aegisub/src/subtitle_format_srt.cpp @@ -431,7 +431,7 @@ found_timestamps: line->Start = ReadSRTTime(timestamp_regex.GetMatch(text_line, 1)); line->End = ReadSRTTime(timestamp_regex.GetMatch(text_line, 2)); // store pointer to subtitle, we'll continue working on it - target->Line.push_back(line); + target->Line.push_back(*line); // next we're reading the text state = 3; break; @@ -500,19 +500,19 @@ void SRTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, // Convert to SRT AssFile copy(*src); copy.Sort(); - StripComments(copy.Line); - RecombineOverlaps(copy.Line); - MergeIdentical(copy.Line); + StripComments(copy); + RecombineOverlaps(copy); + MergeIdentical(copy); #ifdef _WIN32 - ConvertNewlines(copy.Line, "\r\n", false); + ConvertNewlines(copy, "\r\n", false); #else - ConvertNewlines(copy.Line, "\n", false); + ConvertNewlines(copy, "\n", false); #endif // Write lines int i=1; - for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { - if (AssDialogue *current = dynamic_cast(*cur)) { + for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { + if (const AssDialogue *current = dynamic_cast(&*cur)) { file.WriteLineToFile(wxString::Format("%d", i++)); file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End)); file.WriteLineToFile(ConvertTags(current)); @@ -525,18 +525,18 @@ bool SRTSubtitleFormat::CanSave(const AssFile *file) const { wxString supported_tags[] = { "\\b", "\\i", "\\s", "\\u" }; AssStyle defstyle; - for (std::list::const_iterator cur = file->Line.begin(); cur != file->Line.end(); ++cur) { + for (constEntryIter cur = file->Line.begin(); cur != file->Line.end(); ++cur) { // Check style, if anything non-default is found, return false - if (const AssStyle *curstyle = dynamic_cast(*cur)) { + if (const AssStyle *curstyle = dynamic_cast(&*cur)) { if (curstyle->GetEntryData() != defstyle.GetEntryData()) return false; } // Check for attachments, if any is found, return false - if (dynamic_cast(*cur)) return false; + if (dynamic_cast(&*cur)) return false; // Check dialogue - if (const AssDialogue *curdiag = dynamic_cast(*cur)) { + if (const AssDialogue *curdiag = dynamic_cast(&*cur)) { std::vector blocks = curdiag->ParseTags(); for (size_t i = 0; i < blocks.size(); ++i) { AssDialogueBlockOverride *ovr = dynamic_cast(blocks[i]); @@ -557,7 +557,7 @@ bool SRTSubtitleFormat::CanSave(const AssFile *file) const { return true; } -wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const { +wxString SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const { wxString final; std::map tag_states; tag_states['i'] = false; @@ -565,10 +565,10 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const { tag_states['u'] = false; tag_states['s'] = false; - diag->ParseAssTags(); + std::vector blocks = diag->ParseTags(); - for (size_t i = 0; i < diag->Blocks.size(); ++i) { - if (AssDialogueBlockOverride* block = dynamic_cast(diag->Blocks[i])) { + for (size_t i = 0; i < blocks.size(); ++i) { + if (AssDialogueBlockOverride* block = dynamic_cast(blocks[i])) { // Iterate through overrides for (size_t j = 0; j < block->Tags.size(); j++) { AssOverrideTag *tag = block->Tags[j]; @@ -586,7 +586,7 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const { } } // Plain text - else if (AssDialogueBlockPlain *plain = dynamic_cast(diag->Blocks[i])) { + else if (AssDialogueBlockPlain *plain = dynamic_cast(blocks[i])) { final += plain->GetText(); } } @@ -598,7 +598,7 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const { final += wxString::Format("", it->first); } - diag->ClearBlocks(); + delete_clear(blocks); return final; } diff --git a/aegisub/src/subtitle_format_srt.h b/aegisub/src/subtitle_format_srt.h index 8ab43c793..1f8fdebd0 100644 --- a/aegisub/src/subtitle_format_srt.h +++ b/aegisub/src/subtitle_format_srt.h @@ -42,7 +42,7 @@ class AssDialogue; /// /// DOCME class SRTSubtitleFormat : public SubtitleFormat { - wxString ConvertTags(AssDialogue *diag) const; + wxString ConvertTags(const AssDialogue *diag) const; public: SRTSubtitleFormat(); wxArrayString GetReadWildcards() const; diff --git a/aegisub/src/subtitle_format_transtation.cpp b/aegisub/src/subtitle_format_transtation.cpp index 5c06f2fd1..ea3b608bd 100644 --- a/aegisub/src/subtitle_format_transtation.cpp +++ b/aegisub/src/subtitle_format_transtation.cpp @@ -68,15 +68,15 @@ void TranStationSubtitleFormat::WriteFile(const AssFile *src, wxString const& fi // Convert to TranStation AssFile copy(*src); copy.Sort(); - StripComments(copy.Line); - RecombineOverlaps(copy.Line); - MergeIdentical(copy.Line); + StripComments(copy); + RecombineOverlaps(copy); + MergeIdentical(copy); SmpteFormatter ft(fps); TextFileWriter file(filename, encoding); AssDialogue *prev = 0; - for (std::list::iterator it = copy.Line.begin(); it != copy.Line.end(); ++it) { - AssDialogue *cur = dynamic_cast(*it); + for (entryIter it = copy.Line.begin(); it != copy.Line.end(); ++it) { + AssDialogue *cur = dynamic_cast(&*it); if (prev && cur) { file.WriteLineToFile(ConvertLine(©, prev, fps, ft, cur->Start)); diff --git a/aegisub/src/subtitle_format_ttxt.cpp b/aegisub/src/subtitle_format_ttxt.cpp index d981d2f67..bb19ce9fc 100644 --- a/aegisub/src/subtitle_format_ttxt.cpp +++ b/aegisub/src/subtitle_format_ttxt.cpp @@ -91,7 +91,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxS if (child->GetName() == "TextSample") { if ((diag = ProcessLine(child, diag, version))) { lines++; - target->Line.push_back(diag); + target->Line.push_back(*diag); } } // Header @@ -102,7 +102,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxS // No lines? if (lines == 0) - target->Line.push_back(new AssDialogue); + target->Line.push_back(*new AssDialogue); } AssDialogue *TTXTSubtitleFormat::ProcessLine(wxXmlNode *node, AssDialogue *prev, int version) const { @@ -175,9 +175,9 @@ void TTXTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, WriteHeader(root); // Create lines - AssDialogue *prev = 0; - for (LineList::iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { - AssDialogue *current = dynamic_cast(*cur); + const AssDialogue *prev = 0; + for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) { + const AssDialogue *current = dynamic_cast(&*cur); if (current && !current->Comment) { WriteLine(root, prev, current); prev = current; @@ -240,7 +240,7 @@ void TTXTSubtitleFormat::WriteHeader(wxXmlNode *root) const { root->AddChild(node); } -void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *prev, AssDialogue *line) const { +void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, const AssDialogue *prev, const AssDialogue *line) const { // If it doesn't start at the end of previous, add blank if (prev && prev->End != line->Start) { wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample"); @@ -260,16 +260,16 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *prev, AssDialog void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const { file.Sort(); - StripComments(file.Line); - RecombineOverlaps(file.Line); - MergeIdentical(file.Line); - StripTags(file.Line); - ConvertNewlines(file.Line, "\r\n"); + StripComments(file); + RecombineOverlaps(file); + MergeIdentical(file); + StripTags(file); + ConvertNewlines(file, "\r\n"); // Find last line AssTime lastTime; - for (LineList::reverse_iterator cur = file.Line.rbegin(); cur != file.Line.rend(); ++cur) { - if (AssDialogue *prev = dynamic_cast(*cur)) { + for (EntryList::reverse_iterator cur = file.Line.rbegin(); cur != file.Line.rend(); ++cur) { + if (AssDialogue *prev = dynamic_cast(&*cur)) { lastTime = prev->End; break; } @@ -279,5 +279,5 @@ void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const { AssDialogue *diag = new AssDialogue; diag->Start = lastTime; diag->End = lastTime+OPT_GET("Timing/Default Duration")->GetInt(); - file.Line.push_back(diag); + file.Line.push_back(*diag); } diff --git a/aegisub/src/subtitle_format_ttxt.h b/aegisub/src/subtitle_format_ttxt.h index f7db9b85c..22cd3578e 100644 --- a/aegisub/src/subtitle_format_ttxt.h +++ b/aegisub/src/subtitle_format_ttxt.h @@ -47,7 +47,7 @@ class TTXTSubtitleFormat : public SubtitleFormat { void ProcessHeader(wxXmlNode *node) const; void WriteHeader(wxXmlNode *root) const; - void WriteLine(wxXmlNode *root, AssDialogue *prev, AssDialogue *line) const; + void WriteLine(wxXmlNode *root, const AssDialogue *prev, const AssDialogue *line) const; void ConvertToTTXT(AssFile &file) const; diff --git a/aegisub/src/subtitle_format_txt.cpp b/aegisub/src/subtitle_format_txt.cpp index 2bfb6bd33..b134e912a 100644 --- a/aegisub/src/subtitle_format_txt.cpp +++ b/aegisub/src/subtitle_format_txt.cpp @@ -43,9 +43,9 @@ #include "main.h" #include "text_file_reader.h" #include "text_file_writer.h" +#include "utils.h" #include "version.h" - TXTSubtitleFormat::TXTSubtitleFormat() : SubtitleFormat("Plain-Text") { @@ -121,7 +121,7 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt line->End = 0; // Adds line - target->Line.push_back(line); + target->Line.push_back(*line); } } @@ -129,8 +129,8 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, size_t num_actor_names = 0, num_dialogue_lines = 0; // Detect number of lines with Actor field filled out - for (LineList::const_iterator l = src->Line.begin(); l != src->Line.end(); ++l) { - AssDialogue *dia = dynamic_cast(*l); + for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) { + const AssDialogue *dia = dynamic_cast(&*l); if (dia && !dia->Comment) { num_dialogue_lines++; if (!dia->Actor.empty()) @@ -146,43 +146,34 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, file.WriteLineToFile(wxString("# Exported by Aegisub ") + GetAegisubShortVersionString()); // Write the file - for (LineList::const_iterator l = src->Line.begin(); l != src->Line.end(); ++l) { - AssDialogue *dia = dynamic_cast(*l); + for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) { + const AssDialogue *dia = dynamic_cast(&*l); + if (!dia) continue; - if (dia) { - wxString out_line; + wxString out_line; - if (dia->Comment) { - out_line = "# "; - } + if (dia->Comment) + out_line = "# "; - if (write_actors) { - out_line += dia->Actor + ": "; - } + if (write_actors) + out_line += dia->Actor + ": "; - wxString out_text; - if (strip_formatting) { - dia->ParseAssTags(); - for (std::vector::iterator block = dia->Blocks.begin(); block != dia->Blocks.end(); ++block) { - if ((*block)->GetType() == BLOCK_PLAIN) { - out_text += (*block)->GetText(); - } + wxString out_text; + if (strip_formatting) { + std::vector blocks = dia->ParseTags(); + for (std::vector::iterator block = blocks.begin(); block != blocks.end(); ++block) { + if ((*block)->GetType() == BLOCK_PLAIN) { + out_text += (*block)->GetText(); } - dia->ClearBlocks(); - } - else { - out_text = dia->Text; - } - out_line += out_text; - - if (!out_text.empty()) { - file.WriteLineToFile(out_line); } + delete_clear(blocks); } else { - // Not a dialogue line - // TODO: should any non-dia lines cause blank lines in output? - //file.WriteLineToFile(""); + out_text = dia->Text; } + out_line += out_text; + + if (!out_text.empty()) + file.WriteLineToFile(out_line); } } diff --git a/aegisub/src/threaded_frame_source.cpp b/aegisub/src/threaded_frame_source.cpp index e94baaa48..36f98c892 100644 --- a/aegisub/src/threaded_frame_source.cpp +++ b/aegisub/src/threaded_frame_source.cpp @@ -35,8 +35,10 @@ #include "threaded_frame_source.h" #ifndef AGI_PRE -#include #include + +#include +#include #endif #include "ass_dialogue.h" @@ -49,11 +51,11 @@ #include "video_provider_manager.h" // Test if a line is a dialogue line which is not visible at the given time -struct invisible_line : public std::unary_function { +struct invisible_line : public std::unary_function { double time; invisible_line(double time) : time(time * 1000.) { } - bool operator()(const AssEntry *entry) const { - const AssDialogue *diag = dynamic_cast(entry); + bool operator()(AssEntry const& entry) const { + const AssDialogue *diag = dynamic_cast(&entry); return diag && (diag->Start > time || diag->End <= time); } }; @@ -101,17 +103,20 @@ std::tr1::shared_ptr ThreadedFrameSource::ProcFrame(int frameNum // Copying a nontrivially sized AssFile is fairly slow, so // instead muck around with its innards to just temporarily // remove the non-visible lines without deleting them - std::list visible; - std::remove_copy_if(subs->Line.begin(), subs->Line.end(), - std::back_inserter(visible), - invisible_line(time)); + std::deque full; + for (entryIter it = subs->Line.begin(); it != subs->Line.end(); ++it) + full.push_back(&*it); + subs->Line.remove_if(invisible_line(time)); + try { - std::swap(subs->Line, visible); provider->LoadSubtitles(subs.get()); - std::swap(subs->Line, visible); + + subs->Line.clear(); + boost::push_back(subs->Line, full | boost::adaptors::indirected); } catch(...) { - std::swap(subs->Line, visible); + subs->Line.clear(); + boost::push_back(subs->Line, full | boost::adaptors::indirected); throw; } } diff --git a/aegisub/src/utils.h b/aegisub/src/utils.h index 75dc7017f..7f686ac3c 100644 --- a/aegisub/src/utils.h +++ b/aegisub/src/utils.h @@ -138,8 +138,7 @@ void SetClipboard(wxBitmap const& new_value); /// Polymorphic delete functor struct delete_ptr { - template - void operator()(T* ptr) const { + template void operator()(T* ptr) const { delete ptr; } }; @@ -158,7 +157,7 @@ template class BackgroundDeleter : public wxThread { Container cont; wxThread::ExitCode Entry() { - delete_clear(cont); + cont.clear_and_dispose(delete_ptr()); return (wxThread::ExitCode)0; } public: @@ -186,7 +185,12 @@ void background_delete_clear(T& container) { template struct cast { template - Out operator()(In in) const { + Out operator()(In *in) const { return dynamic_cast(in); } + + template + Out operator()(In &in) const { + return dynamic_cast(&in); + } }; diff --git a/aegisub/src/visual_tool_drag.cpp b/aegisub/src/visual_tool_drag.cpp index 77c8b9215..4b0dbaf6a 100644 --- a/aegisub/src/visual_tool_drag.cpp +++ b/aegisub/src/visual_tool_drag.cpp @@ -116,7 +116,7 @@ void VisualToolDrag::OnFileChanged() { active_feature = features.end(); for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (diag && IsDisplayed(diag)) MakeFeatures(diag); } @@ -132,7 +132,7 @@ void VisualToolDrag::OnFrameChanged() { feature_iterator end = features.end(); for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { - AssDialogue *diag = dynamic_cast(*it); + AssDialogue *diag = dynamic_cast(&*it); if (!diag) continue; if (IsDisplayed(diag)) {