mirror of https://github.com/odrling/Aegisub
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.
This commit is contained in:
parent
9c4574ed34
commit
df762b5b99
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,12 @@ AssFile& AssFile::operator=(AssFile from) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
EntryList<AssDialogue>::iterator AssFile::iterator_to(AssDialogue& line) {
|
||||
using l = EntryList<AssDialogue>;
|
||||
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;
|
||||
|
||||
|
|
|
@ -72,6 +72,8 @@ public:
|
|||
AssFile& operator=(AssFile from);
|
||||
~AssFile();
|
||||
|
||||
EntryList<AssDialogue>::iterator iterator_to(AssDialogue& line);
|
||||
|
||||
/// @brief Load default file
|
||||
/// @param defline Add a blank line to the file
|
||||
void LoadDefault(bool defline=true);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<AssDialogue> 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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<AssDialogue>::reverse_iterator(subs->Events.iterator_to(*search_from)), subs->Events.rend(), search_style);
|
||||
return find_next(EntryList<AssDialogue>::reverse_iterator(subs->iterator_to(*search_from)), subs->Events.rend(), search_style);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -311,7 +311,7 @@ std::vector<AssDialogue*> 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"),
|
||||
|
|
|
@ -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."));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue