From df762b5b99b2c9a24ff4980fef07eac711b19e8c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 4 Apr 2014 08:11:09 -0700 Subject: [PATCH] Add a checked iterator_to() to AssFile iterator_to requires that the object be in the list, which is sometimes not the case when processing a commit which removed the active line or a selected line. To handle this, add a checked version that returns Events.end() when it is not in the list rather than crashing. --- src/ass_dialogue.cpp | 5 ++++- src/ass_file.cpp | 6 ++++++ src/ass_file.h | 2 ++ src/audio_timing_dialogue.cpp | 2 +- src/command/edit.cpp | 8 ++++---- src/command/grid.cpp | 2 +- src/command/subtitle.cpp | 2 +- src/dialog_kara_timing_copy.cpp | 4 ++-- src/dialog_spellchecker.cpp | 2 +- src/dialog_timing_processor.cpp | 2 +- src/dialog_translation.cpp | 4 ++-- src/search_replace_engine.cpp | 2 +- src/selection_controller.cpp | 6 +++--- 13 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/ass_dialogue.cpp b/src/ass_dialogue.cpp index 4918143c6..6f1f4236c 100644 --- a/src/ass_dialogue.cpp +++ b/src/ass_dialogue.cpp @@ -57,7 +57,10 @@ AssDialogue::AssDialogue() { Id = ++next_id; } -AssDialogue::AssDialogue(AssDialogue const& that) : AssDialogueBase(that) { +AssDialogue::AssDialogue(AssDialogue const& that) +: AssDialogueBase(that) +, AssEntryListHook(that) +{ Id = ++next_id; } diff --git a/src/ass_file.cpp b/src/ass_file.cpp index e3b217c7c..122deb3ef 100644 --- a/src/ass_file.cpp +++ b/src/ass_file.cpp @@ -77,6 +77,12 @@ AssFile& AssFile::operator=(AssFile from) { return *this; } +EntryList::iterator AssFile::iterator_to(AssDialogue& line) { + using l = EntryList; + bool in_list = !l::node_algorithms::inited(l::value_traits::to_node_ptr(line)); + return in_list ? Events.iterator_to(line) : Events.end(); +} + void AssFile::InsertAttachment(agi::fs::path const& filename) { AssEntryGroup group = AssEntryGroup::GRAPHIC; diff --git a/src/ass_file.h b/src/ass_file.h index b24a68238..7ed814e5e 100644 --- a/src/ass_file.h +++ b/src/ass_file.h @@ -72,6 +72,8 @@ public: AssFile& operator=(AssFile from); ~AssFile(); + EntryList::iterator iterator_to(AssDialogue& line); + /// @brief Load default file /// @param defline Add a blank line to the file void LoadDefault(bool defline=true); diff --git a/src/audio_timing_dialogue.cpp b/src/audio_timing_dialogue.cpp index 1fd7a689b..cebc3ada1 100644 --- a/src/audio_timing_dialogue.cpp +++ b/src/audio_timing_dialogue.cpp @@ -735,7 +735,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines() case 2: // Previous and next lines if (AssDialogue *line = context->selectionController->GetActiveLine()) { - auto current_line = context->ass->Events.iterator_to(*line); + auto current_line = context->ass->iterator_to(*line); if (current_line == context->ass->Events.end()) break; diff --git a/src/command/edit.cpp b/src/command/edit.cpp index 8d1611796..815634e4d 100644 --- a/src/command/edit.cpp +++ b/src/command/edit.cpp @@ -780,7 +780,7 @@ static bool try_paste_lines(agi::Context *c) { for (auto& line : parsed) new_selection.insert(&line); - auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->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(std::move(new_selection), new_active); @@ -811,7 +811,7 @@ struct edit_line_paste final : public Command { ctrl->Paste(); } else { - auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->iterator_to(*c->selectionController->GetActiveLine()); paste_lines(c, false, [=](AssDialogue *new_line) -> AssDialogue * { c->ass->Events.insert(pos, *new_line); return new_line; @@ -842,7 +842,7 @@ struct edit_line_paste_over final : public Command { // Only one line selected, so paste over downwards from the active line if (sel.size() < 2) { - auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->iterator_to(*c->selectionController->GetActiveLine()); paste_lines(c, true, [&](AssDialogue *new_line) -> AssDialogue * { std::unique_ptr deleter(new_line); @@ -1008,7 +1008,7 @@ void split_lines(agi::Context *c, Func&& set_time) { AssDialogue *n1 = c->selectionController->GetActiveLine(); auto n2 = new AssDialogue(*n1); - c->ass->Events.insert(++c->ass->Events.iterator_to(*n1), *n2); + c->ass->Events.insert(++c->ass->iterator_to(*n1), *n2); std::string orig = n1->Text; n1->Text = boost::trim_right_copy(orig.substr(0, pos)); diff --git a/src/command/grid.cpp b/src/command/grid.cpp index af6fb3690..b5fd5b8aa 100644 --- a/src/command/grid.cpp +++ b/src/command/grid.cpp @@ -80,7 +80,7 @@ struct grid_line_next_create final : public Command { newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt(); newline->Style = cur->Style; - auto pos = c->ass->Events.iterator_to(*cur); + auto pos = c->ass->iterator_to(*cur); c->ass->Events.insert(++pos, *newline); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); c->selectionController->NextLine(); diff --git a/src/command/subtitle.cpp b/src/command/subtitle.cpp index af7a6562a..c7524c4df 100644 --- a/src/command/subtitle.cpp +++ b/src/command/subtitle.cpp @@ -124,7 +124,7 @@ 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; - auto pos = c->ass->Events.iterator_to(*c->selectionController->GetActiveLine()); + auto pos = c->ass->iterator_to(*c->selectionController->GetActiveLine()); if (after) ++pos; c->ass->Events.insert(pos, *def); diff --git a/src/dialog_kara_timing_copy.cpp b/src/dialog_kara_timing_copy.cpp index 74598e337..e71bb6c16 100644 --- a/src/dialog_kara_timing_copy.cpp +++ b/src/dialog_kara_timing_copy.cpp @@ -682,11 +682,11 @@ static AssDialogue *find_next(Iterator from, Iterator to, std::string const& sty AssDialogue *DialogKanjiTimer::FindNextStyleMatch(AssDialogue *search_from, const std::string &search_style) { if (!search_from) return search_from; - return find_next(++subs->Events.iterator_to(*search_from), subs->Events.end(), search_style); + return find_next(++subs->iterator_to(*search_from), subs->Events.end(), search_style); } AssDialogue *DialogKanjiTimer::FindPrevStyleMatch(AssDialogue *search_from, const std::string &search_style) { if (!search_from) return search_from; - return find_next(EntryList::reverse_iterator(subs->Events.iterator_to(*search_from)), subs->Events.rend(), search_style); + return find_next(EntryList::reverse_iterator(subs->iterator_to(*search_from)), subs->Events.rend(), search_style); } diff --git a/src/dialog_spellchecker.cpp b/src/dialog_spellchecker.cpp index 2d89e63c4..7d3ffb201 100644 --- a/src/dialog_spellchecker.cpp +++ b/src/dialog_spellchecker.cpp @@ -212,7 +212,7 @@ bool DialogSpellChecker::FindNext() { if (CheckLine(active_line, start_pos, &commit_id)) return true; - auto it = context->ass->Events.iterator_to(*active_line); + auto it = context->ass->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 diff --git a/src/dialog_timing_processor.cpp b/src/dialog_timing_processor.cpp index 84beb9be2..9e5215ac5 100644 --- a/src/dialog_timing_processor.cpp +++ b/src/dialog_timing_processor.cpp @@ -311,7 +311,7 @@ std::vector DialogTimingProcessor::SortDialogues() { // Check if rows are valid for (auto diag : sorted) { if (diag->Start > diag->End) { - int line = std::distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*diag)); + int line = std::distance(c->ass->Events.begin(), c->ass->iterator_to(*diag)); wxMessageBox( wxString::Format(_("One of the lines in the file (%i) has negative duration. Aborting."), line), _("Invalid script"), diff --git a/src/dialog_translation.cpp b/src/dialog_translation.cpp index 62920a24e..357092385 100644 --- a/src/dialog_translation.cpp +++ b/src/dialog_translation.cpp @@ -67,7 +67,7 @@ DialogTranslation::DialogTranslation(agi::Context *c) , active_line_connection(c->selectionController->AddActiveLineListener(&DialogTranslation::OnActiveLineChanged, this)) , active_line(c->selectionController->GetActiveLine()) , line_count(c->ass->Events.size()) -, line_number(std::distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*active_line)) + 1) +, line_number(std::distance(c->ass->Events.begin(), c->ass->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 = std::distance(c->ass->Events.begin(), c->ass->Events.iterator_to(*new_line)) + 1; + line_number = std::distance(c->ass->Events.begin(), c->ass->iterator_to(*new_line)) + 1; if (bad_block(blocks[cur_block]) && !NextBlock()) { wxMessageBox(_("No more lines to translate.")); diff --git a/src/search_replace_engine.cpp b/src/search_replace_engine.cpp index e24f5d64a..137a4693b 100644 --- a/src/search_replace_engine.cpp +++ b/src/search_replace_engine.cpp @@ -229,7 +229,7 @@ bool SearchReplaceEngine::FindReplace(bool replace) { auto matches = GetMatcher(settings); AssDialogue *line = context->selectionController->GetActiveLine(); - auto it = context->ass->Events.iterator_to(*line); + auto it = context->ass->iterator_to(*line); size_t pos = 0; MatchState replace_ms; diff --git a/src/selection_controller.cpp b/src/selection_controller.cpp index 93c1d289e..34ea04347 100644 --- a/src/selection_controller.cpp +++ b/src/selection_controller.cpp @@ -46,7 +46,7 @@ void SelectionController::OnSubtitlesOpen() { void SelectionController::OnSubtitlesSave() { if (active_line) context->ass->SaveUIState("Active Line", std::to_string(std::distance( - context->ass->Events.begin(), context->ass->Events.iterator_to(*active_line)))); + context->ass->Events.begin(), context->ass->iterator_to(*active_line)))); } void SelectionController::SetSelectedSet(Selection new_selection) { @@ -68,7 +68,7 @@ void SelectionController::SetSelectionAndActive(Selection new_selection, AssDial void SelectionController::PrevLine() { if (!active_line) return; - auto it = context->ass->Events.iterator_to(*active_line); + auto it = context->ass->iterator_to(*active_line); if (it != context->ass->Events.begin()) { --it; SetSelectionAndActive({&*it}, &*it); @@ -77,7 +77,7 @@ void SelectionController::PrevLine() { void SelectionController::NextLine() { if (!active_line) return; - auto it = context->ass->Events.iterator_to(*active_line); + auto it = context->ass->iterator_to(*active_line); if (++it != context->ass->Events.end()) SetSelectionAndActive({&*it}, &*it); }