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.
This commit is contained in:
Thomas Goyne 2012-10-12 10:16:39 -07:00
parent 28175aadbe
commit 83761d881a
53 changed files with 384 additions and 422 deletions

View File

@ -21,6 +21,7 @@
<Configurations>
<Configuration
Name="Debug|Win32"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_debug32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"

View File

@ -6,7 +6,7 @@
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Zm130"
AdditionalOptions="/Zm150"
Optimization="3"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"

View File

@ -71,9 +71,7 @@
#include <windows.h>
#include <objbase.h>
#include <mmsystem.h>
#else
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
@ -82,6 +80,9 @@
#include <unistd.h>
#endif
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm_ext.hpp>
/////////////////////
// wxWidgets headers
#include <wx/wxprec.h> // Leave this first.

View File

@ -32,13 +32,14 @@
/// @ingroup subs_storage
///
#pragma once
#ifndef AGI_PRE
#include <wx/string.h>
#endif
#include <boost/intrusive/list_hook.hpp>
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<boost::intrusive::link_mode<boost::intrusive::auto_unlink> >::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;

View File

@ -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)

View File

@ -33,6 +33,8 @@
#include "config.h"
#include "ass_file.h"
#ifndef AGI_PRE
#include <algorithm>
#include <fstream>
@ -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<char> &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<AssEntry*> &lines, AssEntry *entry) {
static bool try_insert(EntryList &lines, AssEntry *entry) {
if (lines.empty()) return false;
// Search for insertion point
std::list<AssEntry*>::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<AssEntry*>::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<AssEntry*>::iterator script_info_end;
entryIter script_info_end;
bool found_script_info = false;
for (std::list<AssEntry*>::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<AssEntry*>::const_iterator cur = Line.begin(); cur != Line.end(); ++cur) {
if (AssStyle *curstyle = dynamic_cast<AssStyle*>(*cur))
for (constEntryIter cur = Line.begin(); cur != Line.end(); ++cur) {
if (const AssStyle *curstyle = dynamic_cast<const AssStyle*>(&*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<AssStyle*>(*cur);
AssStyle *curstyle = dynamic_cast<AssStyle*>(&*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<AssDialogue*> const& limit) {
Sort(Line, comp, limit);
}
namespace {
struct AssEntryComp : public std::binary_function<const AssEntry*, const AssEntry*, bool> {
struct AssEntryComp : public std::binary_function<AssEntry, AssEntry, bool> {
AssFile::CompFunc comp;
bool operator()(const AssEntry* a, const AssEntry* b) const {
return comp(static_cast<const AssDialogue*>(a), static_cast<const AssDialogue*>(b));
bool operator()(AssEntry const&a, AssEntry const&b) const {
return comp(static_cast<const AssDialogue*>(&a), static_cast<const AssDialogue*>(&b));
}
};
@ -527,17 +529,18 @@ namespace {
return d && (limit.empty() || limit.count(d));
}
}
void AssFile::Sort(std::list<AssEntry*> &lst, CompFunc comp, std::set<AssDialogue*> const& limit) {
void AssFile::Sort(EntryList &lst, CompFunc comp, std::set<AssDialogue*> 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<AssEntry*> 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<AssEntry*> &lst, CompFunc comp, std::set<AssDialogu
begin = --end;
}
}
void AssFile::Sort(std::list<AssDialogue*> &lst, CompFunc comp) {
lst.sort(comp);
}
AssFile *AssFile::top;

View File

@ -41,14 +41,19 @@
#include <wx/arrstr.h>
#endif
#include <boost/intrusive/list.hpp>
#include <libaegisub/signal.h>
#include "ass_entry.h"
class AssDialogue;
class AssStyle;
class AssAttachment;
class AssEntry;
typedef std::list<AssEntry*>::iterator entryIter;
typedef boost::intrusive::make_list<AssEntry, boost::intrusive::constant_time_size<false> >::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<AssEntry*> 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<AssEntry*>& lst, CompFunc comp = CompStart, std::set<AssDialogue*> const& limit = std::set<AssDialogue*>());
/// @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<AssDialogue*>& lst, CompFunc comp = CompStart);
static void Sort(EntryList& lst, CompFunc comp = CompStart, std::set<AssDialogue*> const& limit = std::set<AssDialogue*>());
};

View File

@ -291,8 +291,8 @@ void AssKaraoke::SplitLines(std::set<AssDialogue*> const& lines, agi::Context *c
SubtitleSelection sel = c->selectionController->GetSelectedSet();
bool did_split = false;
for (std::list<AssEntry*>::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag || !lines.count(diag)) continue;
kara.SetLine(diag);
@ -311,7 +311,7 @@ void AssKaraoke::SplitLines(std::set<AssDialogue*> 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);

View File

@ -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;
}

View File

@ -720,21 +720,21 @@ void AudioTimingControllerDialogue::SetMarkers(std::vector<AudioMarker*> const&
AnnounceMarkerMoved();
}
static bool noncomment_dialogue(AssEntry *e)
static bool noncomment_dialogue(AssEntry const& e)
{
if (AssDialogue *diag = dynamic_cast<AssDialogue*>(e))
if (const AssDialogue *diag = dynamic_cast<const AssDialogue*>(&e))
return !diag->Comment;
return false;
}
static bool dialogue(AssEntry *e)
static bool dialogue(AssEntry const& e)
{
return !!dynamic_cast<AssDialogue*>(e);
return !!dynamic_cast<const AssDialogue*>(&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<AssEntry*>::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<AssEntry*>::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<AssDialogue*>(*prev));
AddInactiveLine(sel, static_cast<AssDialogue*>(&*prev));
if (mode == 2)
{
std::list<AssEntry*>::iterator next =
entryIter next =
find_if(++current_line, context->ass->Line.end(), predicate);
if (next != context->ass->Line.end())
AddInactiveLine(sel, static_cast<AssDialogue*>(*next));
AddInactiveLine(sel, static_cast<AssDialogue*>(&*next));
}
}
break;
case 3: // All inactive lines
{
AssDialogue *active_line = context->selectionController->GetActiveLine();
for (std::list<AssEntry*>::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<AssDialogue*>(*it));
if (&*it != active_line && predicate(*it))
AddInactiveLine(sel, static_cast<AssDialogue*>(&*it));
}
break;
}

View File

@ -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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) {
wxLogError("Selected row %d is not a dialogue line", cur);
break;

View File

@ -40,6 +40,8 @@
#include <assert.h>
#include <algorithm>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <wx/log.h>
#endif
@ -660,14 +662,14 @@ namespace Automation4 {
// Apply any pending commits
for (std::deque<PendingCommit>::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<LuaAssFile**>(lua_newuserdata(L, sizeof(LuaAssFile*))) = this;

View File

@ -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<AssDialogue*>(*cur)) {
if (AssDialogue *curdiag = dynamic_cast<AssDialogue*>(&*cur)) {
line_index_map[curdiag] = (int)index_line_map.size();
index_line_map.push_back(curdiag);
}

View File

@ -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<AssDialogue *>(*pos);
AssDialogue *line = static_cast<AssDialogue *>(&*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<AssDialogue*>(*pos));
} while (pos != c->ass->Line.end() && !dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it))) {
delete *it;
c->ass->Line.erase(it++);
}
if (sel.count(static_cast<AssDialogue*>(&*it)))
delete &*it++;
else
++it;
}
@ -598,12 +596,12 @@ struct edit_line_delete : public validate_sel_nonempty {
}
};
struct in_selection : public std::unary_function<AssEntry*, bool> {
struct in_selection : public std::unary_function<AssEntry, bool> {
SubtitleSelectionController::Selection const& sel;
in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { }
bool operator()(AssEntry *e) const {
AssDialogue *d = dynamic_cast<AssDialogue*>(e);
return d && sel.count(d);
bool operator()(AssEntry const& e) const {
const AssDialogue *d = dynamic_cast<const AssDialogue*>(&e);
return d && sel.count(const_cast<AssDialogue *>(d));
}
};
@ -612,24 +610,24 @@ static void duplicate_lines(agi::Context *c, bool shift) {
SubtitleSelectionController::Selection new_sel;
AssDialogue *new_active = 0;
std::list<AssEntry*>::iterator start = c->ass->Line.begin();
std::list<AssEntry*>::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<AssEntry*>::iterator insert_pos = find_if(start, end, std::not1(sel));
std::list<AssEntry*>::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<AssDialogue*>((*start)->Clone());
AssDialogue *new_diag = static_cast<AssDialogue*>(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<AssDialogue*>(*it);
if (!diag || !sel.count(diag)) {
*out++ = *it;
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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);

View File

@ -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<typename U::key_type>(*begin);
typename U::key_type cur = dynamic_cast<typename U::key_type>(&*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);
}
}

View File

@ -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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (diag &&
c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame &&
c->videoController->FrameAtTime(diag->End, agi::vfr::END) >= frame)

View File

@ -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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) continue;
if (sel.count(diag)) {

View File

@ -102,10 +102,8 @@ void DialogAttachments::UpdateList() {
listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100);
// Fill list
AssAttachment *attach;
for (std::list<AssEntry*>::iterator cur = ass->Line.begin();cur != ass->Line.end();cur++) {
attach = dynamic_cast<AssAttachment*>(*cur);
if (attach) {
for (entryIter cur = ass->Line.begin();cur != ass->Line.end();cur++) {
if (AssAttachment *attach = dynamic_cast<AssAttachment*>(&*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<AssEntry*>::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<AssEntry*>::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

View File

@ -88,7 +88,7 @@ class FontsCollectorThread : public wxThread {
std::vector<wxString> GetFontPaths(wxString const&, int, bool, std::set<wxUniChar> const&) { return std::vector<wxString>(); }
} lister;
#endif
std::vector<wxString> paths = FontCollector(callback, lister).GetFontPaths(subs->Line);
std::vector<wxString> paths = FontCollector(callback, lister).GetFontPaths(subs);
if (paths.empty()) return;
// Copy fonts

View File

@ -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<AssDialogue*>(*currentDestinationLine)) {
else if (AssDialogue *destLine = dynamic_cast<AssDialogue*>(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<AssDialogue*>(*currentSourceLine);
if (currentDestinationLine != subs->Line.end())
dst = dynamic_cast<AssDialogue*>(*currentDestinationLine);
if (currentSourceLine)
src = dynamic_cast<AssDialogue*>(currentSourceLine);
if (currentDestinationLine)
dst = dynamic_cast<AssDialogue*>(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<AssDialogue*>(*search_from);
AssDialogue *dlg = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*search_from);
AssDialogue *dlg = dynamic_cast<AssDialogue*>(&*it);
if (dlg && dlg->Style == search_style)
break;
return dlg;
}
return search_from;
return 0;
}

View File

@ -53,32 +53,17 @@ class wxCheckBox;
///
/// DOCME
class DialogKanjiTimer : public wxDialog {
typedef std::list<AssEntry*>::iterator entryIter;
/// DOCME
AssFile *subs;
/// DOCME
KaraokeLineMatchDisplay *display;
/// DOCME
/// DOCME
wxComboBox *SourceStyle, *DestStyle;
/// DOCME
wxCheckBox *Interpolate;
/// DOCME
std::vector<std::pair<AssDialogue*, wxString> > 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);

View File

@ -200,8 +200,8 @@ namespace {
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
}
void resample_line(resample_state *state, AssEntry *line) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(line);
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);
@ -217,7 +217,7 @@ namespace {
diag->UpdateText();
diag->ClearBlocks();
}
else if (AssStyle *style = dynamic_cast<AssStyle*>(line)) {
else if (AssStyle *style = dynamic_cast<AssStyle*>(&line)) {
style->fontsize = int(style->fontsize * state->ry + 0.5);
style->outline_w *= state->ry;
style->shadow_w *= state->ry;

View File

@ -379,8 +379,8 @@ void SearchReplaceEngine::ReplaceAll() {
bool inSel = affect == 1;
// Scan
for (std::list<AssEntry*>::iterator it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) continue;
// Check if row is selected

View File

@ -114,7 +114,7 @@ static std::set<AssDialogue*> process(wxString match_text, bool match_case, int
std::set<AssDialogue*> matches;
for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ++it) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) continue;
if (diag->Comment && !comments) continue;
if (!diag->Comment && !dialogue) continue;

View File

@ -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<AssDialogue*>(*it);
AssDialogue *line = dynamic_cast<AssDialogue*>(&*it);
if (!line) continue;
++row_number;

View File

@ -213,7 +213,7 @@ bool DialogSpellChecker::FindNext() {
if (CheckLine(active_line, start_pos, &commit_id))
return true;
std::list<AssEntry*>::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<AssDialogue*>(*it)));
} while (!(active_line = dynamic_cast<AssDialogue*>(&*it)));
if (CheckLine(active_line, 0, &commit_id))
return true;

View File

@ -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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) continue;
if (diag->Style == source_name) {

View File

@ -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<AssStyle*>(*cur)) {
if (AssStyle *style = dynamic_cast<AssStyle*>(&*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;i<n;i++) {
AssStyle *temp = styleMap.at(selections[i]);
c->ass->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<AssStyle*>(*cur)) {
c->ass->Line.insert(cur, styleMap[curn]);
if (dynamic_cast<AssStyle*>(&*cur)) {
c->ass->Line.insert(cur, *styleMap[curn]);
c->ass->Line.erase(cur);
curn++;
}

View File

@ -304,7 +304,6 @@ std::vector<AssDialogue*> DialogTimingProcessor::SortDialogues() {
}
std::vector<AssDialogue*> sorted;
sorted.reserve(c->ass->Line.size());
if (onlySelection->IsChecked()) {
SubtitleSelection sel = c->selectionController->GetSelectedSet();

View File

@ -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<AssDialogue*>()))
, line_number(count_if(c->ass->Line.begin(), find(c->ass->Line.begin(), c->ass->Line.end(), active_line), cast<AssDialogue*>()) + 1)
, line_number(count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*active_line), cast<AssDialogue*>()) + 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<AssDialogue*>()) + 1;
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()) {
wxMessageBox(_("No more lines to translate."));

View File

@ -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<AssDialogue*>(*cur)) {
if (AssDialogue *diag = dynamic_cast<AssDialogue*>(&*cur)) {
if (!std::binary_search(styles.begin(), styles.end(), diag->Style.Lower())) {
diag->Style = "Default";
}

View File

@ -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<AssDialogue*>(*cur);
AssDialogue *curDialogue = dynamic_cast<AssDialogue*>(&*cur);
if (curDialogue) {
line = curDialogue;

View File

@ -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 <algorithm>
@ -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<AssDialogueBlock*> 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<AssDialogueBlockOverride *>(line->Blocks[i])) {
for (size_t i = 0; i < blocks.size(); ++i) {
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(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<AssDialogueBlockPlain *>(line->Blocks[i])) {
else if (AssDialogueBlockPlain *txt = dynamic_cast<AssDialogueBlockPlain *>(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<StyleInfo, UsageData> const& style) {
@ -148,22 +149,22 @@ void FontCollector::PrintUsage(UsageData const& data) {
status_callback("\n", 2);
}
std::vector<wxString> FontCollector::GetFontPaths(std::list<AssEntry*> const& file) {
std::vector<wxString> FontCollector::GetFontPaths(const AssFile *file) {
missing = 0;
missing_glyphs = 0;
status_callback(_("Parsing file\n"), 0);
int index = 0;
for (std::list<AssEntry*>::const_iterator cur = file.begin(); cur != file.end(); ++cur) {
if (AssStyle *style = dynamic_cast<AssStyle*>(*cur)) {
for (constEntryIter cur = file->Line.begin(); cur != file->Line.end(); ++cur) {
if (const AssStyle *style = dynamic_cast<const AssStyle*>(&*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<AssDialogue*>(*cur))
else if (const AssDialogue *diag = dynamic_cast<const AssDialogue*>(&*cur))
ProcessDialogueLine(diag, ++index);
}

View File

@ -31,8 +31,8 @@
#include <wx/string.h>
#endif
class AssEntry;
class AssDialogue;
class AssFile;
typedef std::tr1::function<void (wxString, int)> 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<StyleInfo, UsageData> 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<wxString> GetFontPaths(std::list<AssEntry*> const& file);
std::vector<wxString> GetFontPaths(const AssFile *file);
};

View File

@ -316,7 +316,7 @@ void SubsEditBox::PopulateList(wxComboBox *combo, wxString AssDialogue::*field)
std::set<wxString> values;
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
if (AssDialogue *diag = dynamic_cast<AssDialogue*>(*it))
if (AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it))
values.insert(diag->*field);
}
values.erase("");

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -79,18 +79,18 @@ bool SubtitleFormat::CanWriteFile(wxString const& filename) const {
bool SubtitleFormat::CanSave(const AssFile *subs) const {
AssStyle defstyle;
for (std::list<AssEntry*>::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<const AssStyle*>(*cur)) {
if (const AssStyle *curstyle = dynamic_cast<const AssStyle*>(&*cur)) {
if (curstyle->GetEntryData() != defstyle.GetEntryData())
return false;
}
// Check for attachments, if any is found, return false
if (dynamic_cast<const AssAttachment*>(*cur)) return false;
if (dynamic_cast<const AssAttachment*>(&*cur)) return false;
// Check dialog
if (const AssDialogue *curdiag = dynamic_cast<const AssDialogue*>(*cur)) {
if (const AssDialogue *curdiag = dynamic_cast<const AssDialogue*>(&*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<AssDialogue*>(*cur)) {
void SubtitleFormat::StripTags(AssFile &file) {
for (entryIter cur = file.Line.begin(); cur != file.Line.end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*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<AssDialogue*>(&*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<AssDialogue*>(*it);
void SubtitleFormat::StripComments(AssFile &file) {
for (entryIter it = file.Line.begin(); it != file.Line.end(); ) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it))
void SubtitleFormat::StripNonDialogue(AssFile &file) {
for (entryIter it = file.Line.begin(); it != file.Line.end(); ) {
if (dynamic_cast<AssDialogue*>(&*it))
++it;
else {
delete *it;
lines.erase(it++);
delete &*it++;
}
}
}
static bool dialog_start_lt(AssEntry *pos, AssDialogue *to_insert) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(pos);
static bool dialog_start_lt(AssEntry &pos, AssDialogue *to_insert) {
AssDialogue *diag = dynamic_cast<AssDialogue*>(&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<AssDialogue*>(*cur);
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(*next);
for (; next != file.Line.end(); cur = next++) {
AssDialogue *prevdlg = dynamic_cast<AssDialogue*>(&*cur);
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*cur);
AssDialogue *nextdlg = dynamic_cast<AssDialogue*>(*next);
for (; next != file.Line.end(); cur = next++) {
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(&*cur);
AssDialogue *nextdlg = dynamic_cast<AssDialogue*>(&*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;
}
}
}

View File

@ -64,24 +64,22 @@ class SubtitleFormat {
static std::list<SubtitleFormat*> formats;
public:
typedef std::list<AssEntry*> 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

View File

@ -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);
}
}

View File

@ -370,10 +370,10 @@ namespace
std::vector<EbuSubtitle> convert_subtitles(AssFile &copy, 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<AssDialogue*>(*orgline);
AssDialogue *line = dynamic_cast<AssDialogue*>(&*orgline);
if (!line) continue;
// add a new subtitle and work on it

View File

@ -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<AssDialogue*>(*cur)) {
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur)) {
++i;
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.ToSMPTE(current->Start), ft.ToSMPTE(current->End), current->Text));
}

View File

@ -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<AssDialogue*>(*cur)) {
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur)) {
int start = fps.FrameAtTime(current->Start, agi::vfr::START);
int end = fps.FrameAtTime(current->End, agi::vfr::END);

View File

@ -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<AssDialogue*>(*cur)) {
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*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<AssEntry*>::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<const AssStyle*>(*cur)) {
if (const AssStyle *curstyle = dynamic_cast<const AssStyle*>(&*cur)) {
if (curstyle->GetEntryData() != defstyle.GetEntryData())
return false;
}
// Check for attachments, if any is found, return false
if (dynamic_cast<const AssAttachment*>(*cur)) return false;
if (dynamic_cast<const AssAttachment*>(&*cur)) return false;
// Check dialogue
if (const AssDialogue *curdiag = dynamic_cast<const AssDialogue*>(*cur)) {
if (const AssDialogue *curdiag = dynamic_cast<const AssDialogue*>(&*cur)) {
std::vector<AssDialogueBlock*> blocks = curdiag->ParseTags();
for (size_t i = 0; i < blocks.size(); ++i) {
AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(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<char, bool> 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<AssDialogueBlock *> blocks = diag->ParseTags();
for (size_t i = 0; i < diag->Blocks.size(); ++i) {
if (AssDialogueBlockOverride* block = dynamic_cast<AssDialogueBlockOverride*>(diag->Blocks[i])) {
for (size_t i = 0; i < blocks.size(); ++i) {
if (AssDialogueBlockOverride* block = dynamic_cast<AssDialogueBlockOverride*>(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<AssDialogueBlockPlain*>(diag->Blocks[i])) {
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(blocks[i])) {
final += plain->GetText();
}
}
@ -598,7 +598,7 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const {
final += wxString::Format("</%c>", it->first);
}
diag->ClearBlocks();
delete_clear(blocks);
return final;
}

View File

@ -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;

View File

@ -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<AssEntry*>::iterator it = copy.Line.begin(); it != copy.Line.end(); ++it) {
AssDialogue *cur = dynamic_cast<AssDialogue*>(*it);
for (entryIter it = copy.Line.begin(); it != copy.Line.end(); ++it) {
AssDialogue *cur = dynamic_cast<AssDialogue*>(&*it);
if (prev && cur) {
file.WriteLineToFile(ConvertLine(&copy, prev, fps, ft, cur->Start));

View File

@ -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<AssDialogue*>(*cur);
const AssDialogue *prev = 0;
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*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<AssDialogue*>(*cur)) {
for (EntryList::reverse_iterator cur = file.Line.rbegin(); cur != file.Line.rend(); ++cur) {
if (AssDialogue *prev = dynamic_cast<AssDialogue*>(&*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);
}

View File

@ -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;

View File

@ -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<AssDialogue*>(*l);
for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) {
const AssDialogue *dia = dynamic_cast<const AssDialogue*>(&*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<AssDialogue*>(*l);
for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) {
const AssDialogue *dia = dynamic_cast<const AssDialogue*>(&*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<AssDialogueBlock*>::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<AssDialogueBlock*> blocks = dia->ParseTags();
for (std::vector<AssDialogueBlock*>::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);
}
}

View File

@ -35,8 +35,10 @@
#include "threaded_frame_source.h"
#ifndef AGI_PRE
#include <iterator>
#include <functional>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm_ext.hpp>
#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<const AssEntry*, bool> {
struct invisible_line : public std::unary_function<AssEntry const&, bool> {
double time;
invisible_line(double time) : time(time * 1000.) { }
bool operator()(const AssEntry *entry) const {
const AssDialogue *diag = dynamic_cast<const AssDialogue*>(entry);
bool operator()(AssEntry const& entry) const {
const AssDialogue *diag = dynamic_cast<const AssDialogue*>(&entry);
return diag && (diag->Start > time || diag->End <= time);
}
};
@ -101,17 +103,20 @@ std::tr1::shared_ptr<AegiVideoFrame> 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<AssEntry*> visible;
std::remove_copy_if(subs->Line.begin(), subs->Line.end(),
std::back_inserter(visible),
invisible_line(time));
std::deque<AssEntry*> 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;
}
}

View File

@ -138,8 +138,7 @@ void SetClipboard(wxBitmap const& new_value);
/// Polymorphic delete functor
struct delete_ptr {
template<class T>
void operator()(T* ptr) const {
template<class T> void operator()(T* ptr) const {
delete ptr;
}
};
@ -158,7 +157,7 @@ template<class Container>
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<class Out>
struct cast {
template<class In>
Out operator()(In in) const {
Out operator()(In *in) const {
return dynamic_cast<Out>(in);
}
template<class In>
Out operator()(In &in) const {
return dynamic_cast<Out>(&in);
}
};

View File

@ -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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*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<AssDialogue*>(*it);
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
if (!diag) continue;
if (IsDisplayed(diag)) {