Store parsed dialogue blocks in a ptr_vector

This eliminates the need to explicitly delete the parsed blocks.

Also go ahead and remove AssDialogue::Blocks since it's really not a
very good idea in general.
This commit is contained in:
Thomas Goyne 2012-12-02 10:24:49 -08:00
parent 67d796731a
commit 1c176e8568
15 changed files with 169 additions and 232 deletions

View File

@ -69,6 +69,7 @@
#include <sys/param.h>
#endif
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/reversed.hpp>

View File

@ -35,7 +35,6 @@
#include <fstream>
#include <list>
#include <vector>
#include <wx/regex.h>
#include <wx/tokenzr.h>
@ -46,6 +45,8 @@
#include "subtitle_format.h"
#include "utils.h"
#include <libaegisub/of_type_adaptor.h>
AssDialogue::AssDialogue()
: AssEntry(wxString())
, Comment(false)
@ -84,11 +85,6 @@ AssDialogue::AssDialogue(wxString const& data)
}
AssDialogue::~AssDialogue () {
delete_clear(Blocks);
}
void AssDialogue::ClearBlocks() {
delete_clear(Blocks);
}
bool AssDialogue::Parse(wxString const& rawData) {
@ -189,17 +185,17 @@ const wxString AssDialogue::GetEntryData() const {
return GetData(false);
}
wxString AssDialogue::GetSSAText () const {
wxString AssDialogue::GetSSAText() const {
return GetData(true);
}
std::vector<AssDialogueBlock*> AssDialogue::ParseTags() const {
std::vector<AssDialogueBlock*> Blocks;
std::auto_ptr<boost::ptr_vector<AssDialogueBlock>> AssDialogue::ParseTags() const {
boost::ptr_vector<AssDialogueBlock> Blocks;
// Empty line, make an empty block
if (Text.empty()) {
Blocks.push_back(new AssDialogueBlockPlain);
return Blocks;
return Blocks.release();
}
int drawingLevel = 0;
@ -260,54 +256,46 @@ plain:
Blocks.push_back(new AssDialogueBlockDrawing(work, drawingLevel));
}
return Blocks;
return Blocks.release();
}
void AssDialogue::ParseAssTags() {
ClearBlocks();
Blocks = ParseTags();
}
void AssDialogue::StripTags () {
void AssDialogue::StripTags() {
Text = GetStrippedText();
}
void AssDialogue::StripTag (wxString tagName) {
ParseAssTags();
wxString final;
void AssDialogue::StripTag(wxString const& tag_name) {
boost::ptr_vector<AssDialogueBlock> blocks(ParseTags());
Text.clear();
// Look for blocks
for (auto block : Blocks) {
if (block->GetType() != BLOCK_OVERRIDE) {
final += block->GetText();
for (auto& block : blocks) {
if (block.GetType() != BLOCK_OVERRIDE) {
Text += block.GetText();
continue;
}
AssDialogueBlockOverride *over = static_cast<AssDialogueBlockOverride*>(block);
AssDialogueBlockOverride *over = static_cast<AssDialogueBlockOverride*>(&block);
wxString temp;
for (auto tag : over->Tags) {
if (tag->Name != tagName)
if (tag->Name != tag_name)
temp += *tag;
}
if (!temp.empty())
final += "{" + temp + "}";
Text += "{" + temp + "}";
}
ClearBlocks();
Text = final;
}
void AssDialogue::UpdateText () {
if (Blocks.empty()) return;
void AssDialogue::UpdateText(boost::ptr_vector<AssDialogueBlock>& blocks) {
if (blocks.empty()) return;
Text.clear();
for (auto block : Blocks) {
if (block->GetType() == BLOCK_OVERRIDE) {
for (auto& block : blocks) {
if (block.GetType() == BLOCK_OVERRIDE) {
Text += "{";
Text += block->GetText();
Text += block.GetText();
Text += "}";
}
else Text += block->GetText();
else Text += block.GetText();
}
}
@ -336,25 +324,17 @@ wxString AssDialogue::GetMarginString(int which) const {
return wxString::Format("%d", Margin[which]);
}
void AssDialogue::ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData) {
// Apply for all override blocks
for (auto block : Blocks) {
if (block->GetType() == BLOCK_OVERRIDE) {
static_cast<AssDialogueBlockOverride*>(block)->ProcessParameters(callback, userData);
}
}
}
bool AssDialogue::CollidesWith(const AssDialogue *target) const {
if (!target) return false;
return ((Start < target->Start) ? (target->Start < End) : (Start < target->End));
}
wxString AssDialogue::GetStrippedText() const {
static const wxRegEx reg("\\{[^\\{]*\\}", wxRE_ADVANCED);
wxString txt(Text);
reg.Replace(&txt, "");
return txt;
wxString ret;
boost::ptr_vector<AssDialogueBlock> blocks(ParseTags());
for (auto block : blocks | agi::of_type<AssDialogueBlockPlain>())
ret += block->GetText();
return ret;
}
AssEntry *AssDialogue::Clone() const {

View File

@ -32,13 +32,14 @@
/// @ingroup subs_storage
///
#include <vector>
#include "ass_entry.h"
#include "ass_time.h"
#include <libaegisub/exception.h>
#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>
enum AssBlockType {
BLOCK_BASE,
BLOCK_PLAIN,
@ -101,7 +102,7 @@ public:
AssDialogueBlockOverride(wxString const& text = wxString()) : AssDialogueBlock(text) { }
~AssDialogueBlockOverride();
std::vector<AssOverrideTag*> Tags;
std::vector<AssOverrideTag *> Tags;
AssBlockType GetType() const override { return BLOCK_OVERRIDE; }
wxString GetText() override;
@ -119,9 +120,6 @@ public:
class AssDialogue : public AssEntry {
wxString GetData(bool ssa) const;
public:
/// Contains information about each block of text
std::vector<AssDialogueBlock*> Blocks;
/// Is this a comment line?
bool Comment;
/// Layer number
@ -148,28 +146,19 @@ public:
/// @return Did it successfully parse?
bool Parse(wxString const& data);
/// Parse text as ASS to generate block information
void ParseAssTags();
/// Parse text as ASS and return block information
std::vector<AssDialogueBlock*> ParseTags() const;
std::auto_ptr<boost::ptr_vector<AssDialogueBlock>> ParseTags() const;
/// Clear all blocks, ALWAYS call this after you're done processing tags
void ClearBlocks();
/// @brief Process parameters via callback
/// @param callback The callback function to call per tag parameter
/// @param userData User data to pass to callback function
void ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData=nullptr);
/// Strip all ASS tags from the text
void StripTags();
/// Strip a specific ASS tag from the text
void StripTag(wxString tagName);
/// @param tag_name Tag to strip, with leading slash
void StripTag(wxString const& tag_name);
/// Get text without tags
wxString GetStrippedText() const;
/// If blocks have been parsed, update the text from their current value
void UpdateText();
/// Update the text of the line from parsed blocks
void UpdateText(boost::ptr_vector<AssDialogueBlock>& blocks);
const wxString GetEntryData() const override;
/// Do nothing
void SetEntryData(wxString const&) override { }

View File

@ -101,24 +101,24 @@ void AssKaraoke::SetLine(AssDialogue *line, bool auto_split, bool normalize) {
}
void AssKaraoke::ParseSyllables(AssDialogue *line, Syllable &syl) {
line->ParseAssTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
for (auto block : line->Blocks) {
wxString text = block->GetText();
for (auto& block : blocks) {
wxString text = block.GetText();
if (dynamic_cast<AssDialogueBlockPlain*>(block)) {
if (dynamic_cast<AssDialogueBlockPlain*>(&block)) {
// treat comments as overrides rather than dialogue
if (text.size() && text[0] == '{')
syl.ovr_tags[syl.text.size()] += text;
else
syl.text += text;
}
else if (dynamic_cast<AssDialogueBlockDrawing*>(block)) {
else if (dynamic_cast<AssDialogueBlockDrawing*>(&block)) {
// drawings aren't override tags but they shouldn't show up in the
// stripped text so pretend they are
syl.ovr_tags[syl.text.size()] += text;
}
else if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(block)) {
else if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(&block)) {
bool in_tag = false;
for (auto tag : ovr->Tags) {
if (tag->IsValid() && tag->Name.Left(2).Lower() == "\\k") {
@ -161,8 +161,6 @@ void AssKaraoke::ParseSyllables(AssDialogue *line, Syllable &syl) {
}
syls.push_back(syl);
line->ClearBlocks();
}
wxString AssKaraoke::GetText() const {

View File

@ -61,10 +61,12 @@
#include "../video_context.h"
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <libaegisub/of_type_adaptor.h>
namespace {
using namespace boost::adaptors;
using cmd::Command;
/// @defgroup cmd-edit Editing commands.
/// @{
@ -164,9 +166,9 @@ void paste_lines(agi::Context *c, bool paste_over) {
}
template<class T>
T get_value(AssDialogue const& line, int blockn, T initial, wxString const& tag_name, wxString alt = wxString()) {
for (auto ovr : line.Blocks | boost::adaptors::reversed | agi::of_type<AssDialogueBlockOverride>()) {
for (auto tag : ovr->Tags | boost::adaptors::reversed) {
T get_value(boost::ptr_vector<AssDialogueBlock> const& blocks, int blockn, T initial, wxString const& tag_name, wxString alt = wxString()) {
for (auto ovr : blocks | sliced(0, blockn + 1) | reversed | agi::of_type<AssDialogueBlockOverride>()) {
for (auto tag : ovr->Tags | reversed) {
if (tag->Name == tag_name || tag->Name == alt)
return tag->Params[0]->Get<T>(initial);
}
@ -188,10 +190,9 @@ int block_at_pos(wxString const& text, int pos) {
return n;
}
void set_tag(const agi::Context *c, wxString const& tag, wxString const& value, int &sel_start, int &sel_end, bool at_end = false) {
AssDialogue * const line = c->selectionController->GetActiveLine();
if (line->Blocks.empty())
line->ParseAssTags();
void set_tag(AssDialogue *line, boost::ptr_vector<AssDialogueBlock> &blocks, wxString const& tag, wxString const& value, int &sel_start, int &sel_end, bool at_end = false) {
if (blocks.empty())
blocks = line->ParseTags();
int start = at_end ? sel_end : sel_start;
int blockn = block_at_pos(line->Text, start);
@ -199,7 +200,7 @@ void set_tag(const agi::Context *c, wxString const& tag, wxString const& value,
AssDialogueBlockPlain *plain = 0;
AssDialogueBlockOverride *ovr = 0;
while (blockn >= 0) {
AssDialogueBlock *block = line->Blocks[blockn];
AssDialogueBlock *block = &blocks[blockn];
if (dynamic_cast<AssDialogueBlockDrawing*>(block))
--blockn;
else if ((plain = dynamic_cast<AssDialogueBlockPlain*>(block))) {
@ -228,9 +229,9 @@ void set_tag(const agi::Context *c, wxString const& tag, wxString const& value,
if (plain || blockn < 0) {
line->Text = line->Text.Left(start) + "{" + insert + "}" + line->Text.Mid(start);
shift += 2;
line->ParseAssTags();
blocks = line->ParseTags();
}
else if(ovr) {
else if (ovr) {
wxString alt;
if (tag == "\\c") alt = "\\1c";
// Remove old of same
@ -254,7 +255,7 @@ void set_tag(const agi::Context *c, wxString const& tag, wxString const& value,
if (!found)
ovr->AddTag(insert);
line->UpdateText();
line->UpdateText(blocks);
}
else
assert(false);
@ -265,14 +266,11 @@ void set_tag(const agi::Context *c, wxString const& tag, wxString const& value,
}
}
void set_text(AssDialogue *line, wxString const& value) {
line->Text = value;
}
void commit_text(agi::Context const * const c, wxString const& desc, int sel_start = -1, int sel_end = -1, int *commit_id = 0) {
SubtitleSelection const& sel = c->selectionController->GetSelectedSet();
for_each(sel.begin(), sel.end(),
std::bind(set_text, std::placeholders::_1, c->selectionController->GetActiveLine()->Text));
wxString text = c->selectionController->GetActiveLine()->Text;
for_each(sel.begin(), sel.end(), [&](AssDialogue *d) { d->Text = text; });
int new_commit_id = c->ass->Commit(desc, AssFile::COMMIT_DIAG_TEXT, commit_id ? *commit_id : -1, sel.size() == 1 ? *sel.begin() : 0);
if (commit_id)
*commit_id = new_commit_id;
@ -285,48 +283,42 @@ void toggle_override_tag(const agi::Context *c, bool (AssStyle::*field), const c
AssStyle const* const style = c->ass->GetStyle(line->Style);
bool state = style ? style->*field : AssStyle().*field;
line->ParseAssTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
int sel_start = c->textSelectionController->GetSelectionStart();
int sel_end = c->textSelectionController->GetSelectionEnd();
int blockn = block_at_pos(line->Text, sel_start);
state = get_value(*line, blockn, state, tag);
state = get_value(blocks, blockn, state, tag);
set_tag(c, tag, state ? "0" : "1", sel_start, sel_end);
set_tag(line, blocks, tag, state ? "0" : "1", sel_start, sel_end);
if (sel_start != sel_end)
set_tag(c, tag, state ? "1" : "0", sel_start, sel_end, true);
set_tag(line, blocks, tag, state ? "1" : "0", sel_start, sel_end, true);
line->ClearBlocks();
commit_text(c, undo_msg, sel_start, sel_end);
}
void got_color(const agi::Context *c, const char *tag, int *commit_id, agi::Color new_color) {
int sel_start = c->textSelectionController->GetSelectionStart();
int sel_end = c->textSelectionController->GetSelectionEnd();
set_tag(c, tag, new_color.GetAssOverrideFormatted(), sel_start, sel_end);
commit_text(c, _("set color"), sel_start, sel_end, commit_id);
}
void show_color_picker(const agi::Context *c, agi::Color (AssStyle::*field), const char *tag, const char *alt) {
AssDialogue *const line = c->selectionController->GetActiveLine();
AssStyle const* const style = c->ass->GetStyle(line->Style);
agi::Color color = (style ? style->*field : AssStyle().*field);
line->ParseAssTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
int sel_start = c->textSelectionController->GetSelectionStart();
int sel_end = c->textSelectionController->GetSelectionEnd();
int blockn = block_at_pos(line->Text, sel_start);
int initial_sel_start = sel_start, initial_sel_end = sel_end;
color = get_value(*line, blockn, color, tag, alt);
color = get_value(blocks, blockn, color, tag, alt);
int commit_id = -1;
bool ok = GetColorFromUser(c->parent, color, std::bind(got_color, c, tag, &commit_id, std::placeholders::_1));
line->ClearBlocks();
bool ok = GetColorFromUser(c->parent, color, [&](agi::Color new_color) {
set_tag(line, blocks, tag, new_color.GetAssOverrideFormatted(), sel_start, sel_end);
commit_text(c, _("set color"), sel_start, sel_end, &commit_id);
});
commit_text(c, _("set color"), -1, -1, &commit_id);
if (!ok) {
c->ass->Undo();
c->textSelectionController->SetSelection(sel_start, sel_end);
c->textSelectionController->SetSelection(initial_sel_start, initial_sel_end);
}
}
@ -426,7 +418,7 @@ struct edit_font : public Command {
void operator()(agi::Context *c) {
AssDialogue *const line = c->selectionController->GetActiveLine();
line->ParseAssTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
const int blockn = block_at_pos(line->Text, c->textSelectionController->GetInsertionPoint());
const AssStyle *style = c->ass->GetStyle(line->Style);
@ -438,31 +430,27 @@ struct edit_font : public Command {
int sel_end = c->textSelectionController->GetSelectionEnd();
const wxFont startfont(
get_value(*line, blockn, (int)style->fontsize, "\\fs"),
get_value(blocks, blockn, (int)style->fontsize, "\\fs"),
wxFONTFAMILY_DEFAULT,
get_value(*line, blockn, style->italic, "\\i") ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
get_value(*line, blockn, style->bold, "\\b") ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL,
get_value(*line, blockn, style->underline, "\\u"),
get_value(*line, blockn, style->font, "\\fn"));
get_value(blocks, blockn, style->italic, "\\i") ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
get_value(blocks, blockn, style->bold, "\\b") ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL,
get_value(blocks, blockn, style->underline, "\\u"),
get_value(blocks, blockn, style->font, "\\fn"));
const wxFont font = wxGetFontFromUser(c->parent, startfont);
if (!font.Ok() || font == startfont) {
line->ClearBlocks();
return;
}
if (!font.Ok() || font == startfont) return;
if (font.GetFaceName() != startfont.GetFaceName())
set_tag(c, "\\fn", font.GetFaceName(), sel_start, sel_end);
set_tag(line, blocks, "\\fn", font.GetFaceName(), sel_start, sel_end);
if (font.GetPointSize() != startfont.GetPointSize())
set_tag(c, "\\fs", wxString::Format("%d", font.GetPointSize()), sel_start, sel_end);
set_tag(line, blocks, "\\fs", wxString::Format("%d", font.GetPointSize()), sel_start, sel_end);
if (font.GetWeight() != startfont.GetWeight())
set_tag(c, "\\b", wxString::Format("%d", font.GetWeight() == wxFONTWEIGHT_BOLD), sel_start, sel_end);
set_tag(line, blocks, "\\b", wxString::Format("%d", font.GetWeight() == wxFONTWEIGHT_BOLD), sel_start, sel_end);
if (font.GetStyle() != startfont.GetStyle())
set_tag(c, "\\i", wxString::Format("%d", font.GetStyle() == wxFONTSTYLE_ITALIC), sel_start, sel_end);
set_tag(line, blocks, "\\i", wxString::Format("%d", font.GetStyle() == wxFONTSTYLE_ITALIC), sel_start, sel_end);
if (font.GetUnderlined() != startfont.GetUnderlined())
set_tag(c, "\\i", wxString::Format("%d", font.GetUnderlined()), sel_start, sel_end);
set_tag(line, blocks, "\\i", wxString::Format("%d", font.GetUnderlined()), sel_start, sel_end);
line->ClearBlocks();
commit_text(c, _("set font"), sel_start, sel_end);
}
};

View File

@ -203,17 +203,18 @@ namespace {
void resample_line(resample_state *state, AssEntry &line) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&line);
if (diag && !(diag->Comment && (diag->Effect.StartsWith("template") || diag->Effect.StartsWith("code")))) {
diag->ParseAssTags();
diag->ProcessParameters(resample_tags, state);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
for (auto drawing : diag->Blocks | agi::of_type<AssDialogueBlockDrawing>())
for (auto block : blocks | agi::of_type<AssDialogueBlockOverride>())
block->ProcessParameters(resample_tags, state);
for (auto drawing : blocks | agi::of_type<AssDialogueBlockDrawing>())
drawing->TransformCoords(state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
for (size_t i = 0; i < 3; ++i)
diag->Margin[i] = int((diag->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
diag->UpdateText();
diag->ClearBlocks();
diag->UpdateText(blocks);
}
else if (AssStyle *style = dynamic_cast<AssStyle*>(&line)) {
style->fontsize = int(style->fontsize * state->ry + 0.5);

View File

@ -96,11 +96,11 @@ class StyleRenamer {
found_any = true;
}
diag->ParseAssTags();
diag->ProcessParameters(&StyleRenamer::ProcessTag, this);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
for (auto block : blocks | agi::of_type<AssDialogueBlockOverride>())
block->ProcessParameters(&StyleRenamer::ProcessTag, this);
if (replace)
diag->UpdateText();
diag->ClearBlocks();
diag->UpdateText(blocks);
if (found_any) return;
}

View File

@ -51,9 +51,9 @@ static void add_hotkey(wxSizer *sizer, wxWindow *parent, const char *command, wx
}
// Skip over override blocks, comments, and whitespace between blocks
static bool bad_block(AssDialogueBlock *block) {
if (block->GetType() != BLOCK_PLAIN) return true;
wxString text = block->GetText();
static bool bad_block(AssDialogueBlock &block) {
if (block.GetType() != BLOCK_PLAIN) return true;
wxString text = block.GetText();
if (text.Trim().Trim(false).empty()) return true;
if (text[0] == '{' && text.Last() == '}') return true;
return false;
@ -157,8 +157,8 @@ DialogTranslation::DialogTranslation(agi::Context *c)
Bind(wxEVT_KEY_DOWN, &DialogTranslation::OnKeyDown, this);
active_line->ParseAssTags();
if (bad_block(active_line->Blocks[0])) {
blocks = active_line->ParseTags();
if (bad_block(blocks[0])) {
if (!NextBlock())
throw NothingToTranslate(STD_STR(_("There is nothing to translate in the file.")));
}
@ -173,11 +173,11 @@ void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) {
if (switching_lines) return;
active_line = new_line;
active_line->ParseAssTags();
blocks = active_line->ParseTags();
cur_block = 0;
line_number = count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*new_line), cast<AssDialogue*>()) + 1;
if (bad_block(active_line->Blocks[cur_block]) && !NextBlock()) {
if (bad_block(blocks[cur_block]) && !NextBlock()) {
wxMessageBox(_("No more lines to translate."));
EndModal(1);
}
@ -196,20 +196,19 @@ void DialogTranslation::OnExternalCommit(int commit_type) {
bool DialogTranslation::NextBlock() {
switching_lines = true;
do {
if (cur_block == active_line->Blocks.size() - 1) {
if (cur_block == blocks.size() - 1) {
c->selectionController->NextLine();
AssDialogue *new_line = c->selectionController->GetActiveLine();
if (active_line == new_line || !new_line) return false;
active_line->ClearBlocks();
active_line = new_line;
active_line->ParseAssTags();
blocks = active_line->ParseTags();
cur_block = 0;
++line_number;
}
else
++cur_block;
} while (bad_block(active_line->Blocks[cur_block]));
} while (bad_block(blocks[cur_block]));
switching_lines = false;
UpdateDisplay();
@ -224,15 +223,14 @@ bool DialogTranslation::PrevBlock() {
AssDialogue *new_line = c->selectionController->GetActiveLine();
if (active_line == new_line || !new_line) return false;
active_line->ClearBlocks();
active_line = new_line;
active_line->ParseAssTags();
cur_block = active_line->Blocks.size() - 1;
blocks = active_line->ParseTags();
cur_block = blocks.size() - 1;
--line_number;
}
else
--cur_block;
} while (bad_block(active_line->Blocks[cur_block]));
} while (bad_block(blocks[cur_block]));
switching_lines = false;
UpdateDisplay();
@ -246,17 +244,17 @@ void DialogTranslation::UpdateDisplay() {
original_text->ClearAll();
size_t i = 0;
for (auto block : active_line->Blocks) {
if (block->GetType() == BLOCK_PLAIN) {
for (auto& block : blocks) {
if (block.GetType() == BLOCK_PLAIN) {
int cur_size = original_text->GetReverseUnicodePosition(original_text->GetLength());
original_text->AppendText(block->GetText());
original_text->AppendText(block.GetText());
if (i == cur_block) {
original_text->StartUnicodeStyling(cur_size);
original_text->SetUnicodeStyling(cur_size, block->GetText().size(), 1);
original_text->SetUnicodeStyling(cur_size, block.GetText().size(), 1);
}
}
else if (block->GetType() == BLOCK_OVERRIDE)
original_text->AppendText("{" + block->GetText() + "}");
else if (block.GetType() == BLOCK_OVERRIDE)
original_text->AppendText("{" + block.GetText() + "}");
++i;
}
@ -273,8 +271,8 @@ void DialogTranslation::Commit(bool next) {
new_value.Replace("\r\n", "\\N");
new_value.Replace("\r", "\\N");
new_value.Replace("\n", "\\N");
*active_line->Blocks[cur_block] = AssDialogueBlockPlain(new_value);
active_line->UpdateText();
blocks[cur_block] = AssDialogueBlockPlain(new_value);
active_line->UpdateText(blocks);
file_change_connection.Block();
c->ass->Commit(_("translation assistant"), AssFile::COMMIT_DIAG_TEXT);
@ -292,7 +290,7 @@ void DialogTranslation::Commit(bool next) {
}
void DialogTranslation::InsertOriginal() {
translated_text->AddText(active_line->Blocks[cur_block]->GetText());
translated_text->AddText(blocks[cur_block].GetText());
}

View File

@ -24,8 +24,11 @@
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h>
#include <boost/ptr_container/ptr_vector.hpp>
namespace agi { struct Context; }
class AssDialogue;
class AssDialogueBlock;
class PersistLocation;
class ScintillaTextCtrl;
class SubsTextEditCtrl;
@ -44,6 +47,8 @@ class DialogTranslation : public wxDialog {
/// The active line
AssDialogue *active_line;
/// The parsed dialogue blocks for the active line
boost::ptr_vector<AssDialogueBlock> blocks;
/// Which dialogue block in the active line is currently being translated
size_t cur_block;

View File

@ -216,12 +216,12 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) {
newEnd = trunc_cs(ConvertTime(curDialogue->End) + 9);
// Process stuff
curDialogue->ParseAssTags();
curDialogue->ProcessParameters(TransformTimeTags, this);
boost::ptr_vector<AssDialogueBlock> blocks;
for (auto block : blocks | agi::of_type<AssDialogueBlockOverride>())
block->ProcessParameters(TransformTimeTags, this);
curDialogue->Start = newStart;
curDialogue->End = newEnd;
curDialogue->UpdateText();
curDialogue->ClearBlocks();
curDialogue->UpdateText(blocks);
}
}

View File

@ -48,14 +48,14 @@ FontCollector::FontCollector(FontCollectorStatusCallback status_callback, FontFi
void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) {
if (line->Comment) return;
std::vector<AssDialogueBlock*> blocks = line->ParseTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
StyleInfo style = styles[line->Style];
StyleInfo initial = style;
bool overriden = false;
for (auto block : blocks) {
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(block)) {
for (auto& block : blocks) {
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(&block)) {
for (auto tag : ovr->Tags) {
wxString name = tag->Name;
@ -77,7 +77,7 @@ void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) {
}
}
}
else if (AssDialogueBlockPlain *txt = dynamic_cast<AssDialogueBlockPlain *>(block)) {
else if (AssDialogueBlockPlain *txt = dynamic_cast<AssDialogueBlockPlain *>(&block)) {
wxString text = txt->GetText();
if (text.empty() || (text.size() >= 2 && text.StartsWith("{") && text.EndsWith("}")))
@ -102,7 +102,6 @@ void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) {
}
// Do nothing with drawing blocks
}
delete_clear(blocks);
}
void FontCollector::ProcessChunk(std::pair<StyleInfo, UsageData> const& style) {

View File

@ -266,7 +266,7 @@ namespace
// Helper for finding special characters
wxRegEx special_char_search("\\\\[nN]| ", wxRE_ADVANCED);
line->ParseAssTags();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
text_rows.clear();
text_rows.emplace_back();
@ -279,14 +279,14 @@ namespace
bool underline = style_underline, italic = style_italic;
for (auto b : line->Blocks)
for (auto& b : blocks)
{
switch (b->GetType())
switch (b.GetType())
{
case BLOCK_PLAIN:
// find special characters and convert them
{
wxString text = b->GetText();
wxString text = b.GetText();
// Skip comments
if (text.size() > 1 && text[0] =='{' && text.Last() == '}')
@ -332,7 +332,7 @@ namespace
case BLOCK_OVERRIDE:
// find relevant tags and process them
{
AssDialogueBlockOverride *ob = static_cast<AssDialogueBlockOverride*>(b);
AssDialogueBlockOverride *ob = static_cast<AssDialogueBlockOverride*>(&b);
ob->ParseTags();
ProcessOverrides(ob, underline, italic, align, style_underline, style_italic);
@ -360,7 +360,6 @@ namespace
}
}
line->ClearBlocks();
SetAlignment(align);
}
};

View File

@ -534,17 +534,14 @@ bool SRTSubtitleFormat::CanSave(const AssFile *file) const {
// Check dialogue
if (const AssDialogue *curdiag = dynamic_cast<const AssDialogue*>(&line)) {
std::vector<AssDialogueBlock*> blocks = curdiag->ParseTags();
boost::ptr_vector<AssDialogueBlock> blocks(curdiag->ParseTags());
for (auto ovr : blocks | agi::of_type<AssDialogueBlockOverride>()) {
// Verify that all overrides used are supported
for (auto tag : ovr->Tags) {
if (!std::binary_search(supported_tags, std::end(supported_tags), tag->Name)) {
delete_clear(blocks);
if (!std::binary_search(supported_tags, std::end(supported_tags), tag->Name))
return false;
}
}
}
delete_clear(blocks);
}
}
@ -559,10 +556,10 @@ wxString SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
tag_states['u'] = false;
tag_states['s'] = false;
std::vector<AssDialogueBlock *> blocks = diag->ParseTags();
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
for (auto block : blocks) {
if (AssDialogueBlockOverride* ovr = dynamic_cast<AssDialogueBlockOverride*>(block)) {
for (auto& block : blocks) {
if (AssDialogueBlockOverride* ovr = dynamic_cast<AssDialogueBlockOverride*>(&block)) {
// Iterate through overrides
for (auto tag : ovr->Tags) {
if (tag->IsValid() && tag->Name.size() == 2) {
@ -579,7 +576,7 @@ wxString SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
}
}
// Plain text
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(block)) {
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(&block)) {
final += plain->GetText();
}
}
@ -591,7 +588,5 @@ wxString SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
final += wxString::Format("</%c>", it.first);
}
delete_clear(blocks);
return final;
}

View File

@ -156,16 +156,7 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename,
if (write_actors)
out_line += dia->Actor + ": ";
wxString out_text;
if (strip_formatting) {
std::vector<AssDialogueBlock*> blocks = dia->ParseTags();
for (auto block : blocks | agi::of_type<AssDialogueBlockPlain>())
out_text += block->GetText();
delete_clear(blocks);
}
else {
out_text = dia->Text;
}
wxString out_text = strip_formatting ? dia->GetStrippedText() : dia->Text;
out_line += out_text;
if (!out_text.empty())

View File

@ -357,16 +357,9 @@ void VisualTool<FeatureType>::RemoveSelection(feature_iterator feat) {
typedef const std::vector<AssOverrideParameter*> * param_vec;
// Parse line on creation and unparse at the end of scope
struct scoped_tag_parse {
AssDialogue *diag;
scoped_tag_parse(AssDialogue *diag) : diag(diag) { diag->ParseAssTags(); }
~scoped_tag_parse() { diag->ClearBlocks(); }
};
// Find a tag's parameters in a line or return nullptr if it's not found
static param_vec find_tag(const AssDialogue *line, wxString tag_name) {
for (auto ovr : line->Blocks | agi::of_type<AssDialogueBlockOverride>()) {
static param_vec find_tag(boost::ptr_vector<AssDialogueBlock>& blocks, wxString tag_name) {
for (auto ovr : blocks | agi::of_type<AssDialogueBlockOverride>()) {
for (auto tag : ovr->Tags) {
if (tag->Name == tag_name)
return &tag->Params;
@ -389,10 +382,10 @@ static Vector2D vec_or_bad(param_vec tag, size_t x_idx, size_t y_idx) {
}
Vector2D VisualToolBase::GetLinePosition(AssDialogue *diag) {
scoped_tag_parse parse(diag);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
if (Vector2D ret = vec_or_bad(find_tag(diag, "\\pos"), 0, 1)) return ret;
if (Vector2D ret = vec_or_bad(find_tag(diag, "\\move"), 0, 1)) return ret;
if (Vector2D ret = vec_or_bad(find_tag(blocks, "\\pos"), 0, 1)) return ret;
if (Vector2D ret = vec_or_bad(find_tag(blocks, "\\move"), 0, 1)) return ret;
// Get default position
int margin[3];
@ -409,9 +402,9 @@ Vector2D VisualToolBase::GetLinePosition(AssDialogue *diag) {
param_vec align_tag;
int ovr_align = 0;
if ((align_tag = find_tag(diag, "\\an")) && !(*align_tag)[0]->omitted)
if ((align_tag = find_tag(blocks, "\\an")) && !(*align_tag)[0]->omitted)
ovr_align = (*align_tag)[0]->Get<int>();
else if ((align_tag = find_tag(diag, "\\a")))
else if ((align_tag = find_tag(blocks, "\\a")))
ovr_align = AssStyle::SsaToAss((*align_tag)[0]->Get<int>(2));
if (ovr_align > 0 && ovr_align <= 9)
@ -441,14 +434,14 @@ Vector2D VisualToolBase::GetLinePosition(AssDialogue *diag) {
}
Vector2D VisualToolBase::GetLineOrigin(AssDialogue *diag) {
scoped_tag_parse parse(diag);
return vec_or_bad(find_tag(diag, "\\org"), 0, 1);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
return vec_or_bad(find_tag(blocks, "\\org"), 0, 1);
}
bool VisualToolBase::GetLineMove(AssDialogue *diag, Vector2D &p1, Vector2D &p2, int &t1, int &t2) {
scoped_tag_parse parse(diag);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
param_vec tag = find_tag(diag, "\\move");
param_vec tag = find_tag(blocks, "\\move");
if (!tag)
return false;
@ -467,15 +460,15 @@ void VisualToolBase::GetLineRotation(AssDialogue *diag, float &rx, float &ry, fl
if (AssStyle *style = c->ass->GetStyle(diag->Style))
rz = style->angle;
scoped_tag_parse parse(diag);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
if (param_vec tag = find_tag(diag, "\\frx"))
if (param_vec tag = find_tag(blocks, "\\frx"))
rx = tag->front()->Get<float>(rx);
if (param_vec tag = find_tag(diag, "\\fry"))
if (param_vec tag = find_tag(blocks, "\\fry"))
ry = tag->front()->Get<float>(ry);
if (param_vec tag = find_tag(diag, "\\frz"))
if (param_vec tag = find_tag(blocks, "\\frz"))
rz = tag->front()->Get<float>(rz);
else if ((tag = find_tag(diag, "\\fr")))
else if ((tag = find_tag(blocks, "\\fr")))
rz = tag->front()->Get<float>(rz);
}
@ -487,11 +480,11 @@ void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) {
y = style->scaley;
}
scoped_tag_parse parse(diag);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
if (param_vec tag = find_tag(diag, "\\fscx"))
if (param_vec tag = find_tag(blocks, "\\fscx"))
x = tag->front()->Get<float>(x);
if (param_vec tag = find_tag(diag, "\\fscy"))
if (param_vec tag = find_tag(blocks, "\\fscy"))
y = tag->front()->Get<float>(y);
scale = Vector2D(x, y);
@ -500,12 +493,12 @@ void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) {
void VisualToolBase::GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2, bool &inverse) {
inverse = false;
scoped_tag_parse parse(diag);
param_vec tag = find_tag(diag, "\\iclip");
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
param_vec tag = find_tag(blocks, "\\iclip");
if (tag)
inverse = true;
else
tag = find_tag(diag, "\\clip");
tag = find_tag(blocks, "\\clip");
if (tag && tag->size() == 4) {
p1 = vec_or_bad(tag, 0, 1);
@ -518,16 +511,16 @@ void VisualToolBase::GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2,
}
wxString VisualToolBase::GetLineVectorClip(AssDialogue *diag, int &scale, bool &inverse) {
scoped_tag_parse parse(diag);
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
scale = 1;
inverse = false;
param_vec tag = find_tag(diag, "\\iclip");
param_vec tag = find_tag(blocks, "\\iclip");
if (tag)
inverse = true;
else
tag = find_tag(diag, "\\clip");
tag = find_tag(blocks, "\\clip");
if (tag && tag->size() == 4) {
return wxString::Format("m %d %d l %d %d %d %d %d %d",
@ -563,8 +556,8 @@ void VisualToolBase::SetOverride(AssDialogue* line, wxString const& tag, wxStrin
wxString insert = tag + value;
// Get block at start
line->ParseAssTags();
AssDialogueBlock *block = line->Blocks.front();
boost::ptr_vector<AssDialogueBlock> blocks(line->ParseTags());
AssDialogueBlock *block = &blocks.front();
// Get current block as plain or override
assert(dynamic_cast<AssDialogueBlockDrawing*>(block) == nullptr);
@ -574,7 +567,7 @@ void VisualToolBase::SetOverride(AssDialogue* line, wxString const& tag, wxStrin
else if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(block)) {
// Remove old of same
for (size_t i = 0; i < ovr->Tags.size(); i++) {
wxString name = ovr->Tags[i]->Name;
wxString const& name = ovr->Tags[i]->Name;
if (tag == name || removeTag == name) {
delete ovr->Tags[i];
ovr->Tags.erase(ovr->Tags.begin() + i);
@ -583,7 +576,7 @@ void VisualToolBase::SetOverride(AssDialogue* line, wxString const& tag, wxStrin
}
ovr->AddTag(insert);
line->UpdateText();
line->UpdateText(blocks);
}
}