forked from mia/Aegisub
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:
parent
28175aadbe
commit
83761d881a
53 changed files with 384 additions and 422 deletions
|
@ -21,6 +21,7 @@
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
ConfigurationType="1"
|
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"
|
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"
|
CharacterSet="1"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalOptions="/Zm130"
|
AdditionalOptions="/Zm150"
|
||||||
Optimization="3"
|
Optimization="3"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="2"
|
FavorSizeOrSpeed="2"
|
||||||
|
|
|
@ -71,9 +71,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -82,6 +80,9 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/indirected.hpp>
|
||||||
|
#include <boost/range/algorithm_ext.hpp>
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// wxWidgets headers
|
// wxWidgets headers
|
||||||
#include <wx/wxprec.h> // Leave this first.
|
#include <wx/wxprec.h> // Leave this first.
|
||||||
|
|
|
@ -32,13 +32,14 @@
|
||||||
/// @ingroup subs_storage
|
/// @ingroup subs_storage
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/intrusive/list_hook.hpp>
|
||||||
|
|
||||||
enum AssEntryType {
|
enum AssEntryType {
|
||||||
ENTRY_BASE,
|
ENTRY_BASE,
|
||||||
ENTRY_DIALOGUE,
|
ENTRY_DIALOGUE,
|
||||||
|
@ -46,7 +47,7 @@ enum AssEntryType {
|
||||||
ENTRY_ATTACHMENT
|
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)
|
/// 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;
|
wxString data;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_export_filter.h"
|
#include "ass_export_filter.h"
|
||||||
#include "ass_file.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
AssExportFilter::AssExportFilter(wxString const& name, wxString const& description, int priority, bool auto_apply)
|
AssExportFilter::AssExportFilter(wxString const& name, wxString const& description, int priority, bool auto_apply)
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "ass_file.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -46,7 +48,6 @@
|
||||||
|
|
||||||
#include "ass_attachment.h"
|
#include "ass_attachment.h"
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
|
||||||
#include "ass_override.h"
|
#include "ass_override.h"
|
||||||
#include "ass_style.h"
|
#include "ass_style.h"
|
||||||
#include "compat.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
|
// 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) {
|
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_STYLE) found_style = true;
|
||||||
if (type == ENTRY_DIALOGUE) found_dialogue = true;
|
if (type == ENTRY_DIALOGUE) found_dialogue = true;
|
||||||
if (found_style && found_dialogue) break;
|
if (found_style && found_dialogue) break;
|
||||||
|
@ -180,7 +181,7 @@ void AssFile::SaveMemory(std::vector<char> &dst) {
|
||||||
|
|
||||||
// Write file
|
// Write file
|
||||||
for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) {
|
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));
|
copy(buffer.data(), buffer.data() + buffer.length(), back_inserter(dst));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,25 +209,25 @@ void AssFile::LoadDefault(bool defline) {
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// Write headers
|
// Write headers
|
||||||
Line.push_back(new AssEntry("[Script Info]", "[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("Title: Default Aegisub file", "[Script Info]"));
|
||||||
Line.push_back(new AssEntry("ScriptType: v4.00+", "[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("WrapStyle: 0", "[Script Info]"));
|
||||||
Line.push_back(new AssEntry("ScaledBorderAndShadow: yes", "[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("Collisions: Normal", "[Script Info]"));
|
||||||
if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) {
|
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("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("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);
|
InsertStyle(new AssStyle);
|
||||||
|
|
||||||
Line.push_back(new AssEntry("[Events]", "[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]"));
|
Line.push_back(*new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]"));
|
||||||
|
|
||||||
if (defline)
|
if (defline)
|
||||||
Line.push_back(new AssDialogue);
|
Line.push_back(*new AssDialogue);
|
||||||
|
|
||||||
autosavedCommitId = savedCommitId = commitId + 1;
|
autosavedCommitId = savedCommitId = commitId + 1;
|
||||||
Commit("", COMMIT_NEW);
|
Commit("", COMMIT_NEW);
|
||||||
|
@ -237,10 +238,11 @@ void AssFile::LoadDefault(bool defline) {
|
||||||
|
|
||||||
void AssFile::swap(AssFile &that) throw() {
|
void AssFile::swap(AssFile &that) throw() {
|
||||||
// Intentionally does not swap undo stack related things
|
// Intentionally does not swap undo stack related things
|
||||||
std::swap(loaded, that.loaded);
|
using std::swap;
|
||||||
std::swap(commitId, that.commitId);
|
swap(loaded, that.loaded);
|
||||||
std::swap(undoDescription, that.undoDescription);
|
swap(commitId, that.commitId);
|
||||||
std::swap(Line, that.Line);
|
swap(undoDescription, that.undoDescription);
|
||||||
|
swap(Line, that.Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssFile::AssFile(const AssFile &from)
|
AssFile::AssFile(const AssFile &from)
|
||||||
|
@ -249,22 +251,22 @@ AssFile::AssFile(const AssFile &from)
|
||||||
, filename(from.filename)
|
, filename(from.filename)
|
||||||
, loaded(from.loaded)
|
, 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) {
|
AssFile& AssFile::operator=(AssFile from) {
|
||||||
std::swap(*this, from);
|
std::swap(*this, from);
|
||||||
return *this;
|
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;
|
if (lines.empty()) return false;
|
||||||
|
|
||||||
// Search for insertion point
|
// Search for insertion point
|
||||||
std::list<AssEntry*>::iterator it = lines.end();
|
entryIter it = lines.end();
|
||||||
do {
|
do {
|
||||||
--it;
|
--it;
|
||||||
if ((*it)->group == entry->group) {
|
if (it->group == entry->group) {
|
||||||
lines.insert(++it, entry);
|
lines.insert(++it, *entry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} while (it != lines.begin());
|
} while (it != lines.begin());
|
||||||
|
@ -276,17 +278,17 @@ void AssFile::InsertStyle(AssStyle *style) {
|
||||||
if (try_insert(Line, style)) return;
|
if (try_insert(Line, style)) return;
|
||||||
|
|
||||||
// No styles found, add them
|
// No styles found, add them
|
||||||
Line.push_back(new AssEntry("[V4+ Styles]", "[V4+ Styles]"));
|
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(*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(*style);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssFile::InsertAttachment(AssAttachment *attach) {
|
void AssFile::InsertAttachment(AssAttachment *attach) {
|
||||||
if (try_insert(Line, attach)) return;
|
if (try_insert(Line, attach)) return;
|
||||||
|
|
||||||
// Didn't find a group of the appropriate type so create it
|
// Didn't find a group of the appropriate type so create it
|
||||||
Line.push_back(new AssEntry(attach->group, attach->group));
|
Line.push_back(*new AssEntry(attach->group, attach->group));
|
||||||
Line.push_back(attach);
|
Line.push_back(*attach);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssFile::InsertAttachment(wxString filename) {
|
void AssFile::InsertAttachment(wxString filename) {
|
||||||
|
@ -306,9 +308,9 @@ void AssFile::InsertDialogue(AssDialogue *diag) {
|
||||||
if (try_insert(Line, diag)) return;
|
if (try_insert(Line, diag)) return;
|
||||||
|
|
||||||
// Didn't find a group of the appropriate type so create it
|
// Didn't find a group of the appropriate type so create it
|
||||||
Line.push_back(new AssEntry("[Events]", "[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]"));
|
Line.push_back(*new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]"));
|
||||||
Line.push_back(diag);
|
Line.push_back(*diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString AssFile::GetScriptInfo(wxString key) const {
|
wxString AssFile::GetScriptInfo(wxString key) const {
|
||||||
|
@ -316,10 +318,10 @@ wxString AssFile::GetScriptInfo(wxString key) const {
|
||||||
key += ":";
|
key += ":";
|
||||||
bool GotIn = false;
|
bool GotIn = false;
|
||||||
|
|
||||||
for (std::list<AssEntry*>::const_iterator cur = Line.begin(); cur != Line.end(); ++cur) {
|
for (constEntryIter cur = Line.begin(); cur != Line.end(); ++cur) {
|
||||||
if ((*cur)->group == "[Script Info]") {
|
if (cur->group == "[Script Info]") {
|
||||||
GotIn = true;
|
GotIn = true;
|
||||||
wxString curText = (*cur)->GetEntryData();
|
wxString curText = cur->GetEntryData();
|
||||||
if (curText.Lower().StartsWith(key))
|
if (curText.Lower().StartsWith(key))
|
||||||
return curText.Mid(key.size()).Trim(true).Trim(false);
|
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) {
|
void AssFile::SetScriptInfo(wxString const& key, wxString const& value) {
|
||||||
wxString search_key = key.Lower() + ":";
|
wxString search_key = key.Lower() + ":";
|
||||||
size_t key_size = search_key.size();
|
size_t key_size = search_key.size();
|
||||||
std::list<AssEntry*>::iterator script_info_end;
|
entryIter script_info_end;
|
||||||
bool found_script_info = false;
|
bool found_script_info = false;
|
||||||
|
|
||||||
for (std::list<AssEntry*>::iterator cur = Line.begin(); cur != Line.end(); ++cur) {
|
for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) {
|
||||||
if ((*cur)->group == "[Script Info]") {
|
if (cur->group == "[Script Info]") {
|
||||||
found_script_info = true;
|
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 (cur_text == search_key) {
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
delete *cur;
|
delete &*cur;
|
||||||
Line.erase(cur);
|
Line.erase(cur);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(*cur)->SetEntryData(key + ": " + value);
|
cur->SetEntryData(key + ": " + value);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +362,7 @@ void AssFile::SetScriptInfo(wxString const& key, wxString const& value) {
|
||||||
}
|
}
|
||||||
else if (found_script_info) {
|
else if (found_script_info) {
|
||||||
if (value.size())
|
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;
|
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,
|
// Found a script info section, but not this key or anything after it,
|
||||||
// so add it at the end of the file
|
// so add it at the end of the file
|
||||||
if (found_script_info)
|
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
|
// Script info section not found, so add it at the beginning of the file
|
||||||
else {
|
else {
|
||||||
Line.push_front(new AssEntry(key + ": " + value, "[Script Info]"));
|
Line.push_front(*new AssEntry(key + ": " + value, "[Script Info]"));
|
||||||
Line.push_front(new AssEntry("[Script Info]", "[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 AssFile::GetStyles() const {
|
||||||
wxArrayString styles;
|
wxArrayString styles;
|
||||||
for (std::list<AssEntry*>::const_iterator cur = Line.begin(); cur != Line.end(); ++cur) {
|
for (constEntryIter cur = Line.begin(); cur != Line.end(); ++cur) {
|
||||||
if (AssStyle *curstyle = dynamic_cast<AssStyle*>(*cur))
|
if (const AssStyle *curstyle = dynamic_cast<const AssStyle*>(&*cur))
|
||||||
styles.Add(curstyle->name);
|
styles.Add(curstyle->name);
|
||||||
}
|
}
|
||||||
return styles;
|
return styles;
|
||||||
|
@ -409,7 +411,7 @@ wxArrayString AssFile::GetStyles() const {
|
||||||
|
|
||||||
AssStyle *AssFile::GetStyle(wxString const& name) {
|
AssStyle *AssFile::GetStyle(wxString const& name) {
|
||||||
for (entryIter cur = Line.begin(); cur != Line.end(); ++cur) {
|
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)
|
if (curstyle && curstyle->name == name)
|
||||||
return curstyle;
|
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 only one line changed just modify it instead of copying the file
|
||||||
if (single_line) {
|
if (single_line) {
|
||||||
entryIter this_it = Line.begin(), undo_it = UndoStack.back().Line.begin();
|
entryIter this_it = Line.begin(), undo_it = UndoStack.back().Line.begin();
|
||||||
while (*this_it != single_line) {
|
while (&*this_it != single_line) {
|
||||||
++this_it;
|
++this_it;
|
||||||
++undo_it;
|
++undo_it;
|
||||||
}
|
}
|
||||||
delete *undo_it;
|
UndoStack.back().Line.insert(undo_it, *single_line->Clone());
|
||||||
*undo_it = single_line->Clone();
|
delete &*undo_it;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UndoStack.back() = *this;
|
UndoStack.back() = *this;
|
||||||
|
@ -467,7 +469,7 @@ void AssFile::Undo() {
|
||||||
if (UndoStack.size() <= 1) return;
|
if (UndoStack.size() <= 1) return;
|
||||||
|
|
||||||
RedoStack.push_back(AssFile());
|
RedoStack.push_back(AssFile());
|
||||||
std::swap(RedoStack.back(), *this);
|
swap(RedoStack.back());
|
||||||
UndoStack.pop_back();
|
UndoStack.pop_back();
|
||||||
*this = UndoStack.back();
|
*this = UndoStack.back();
|
||||||
|
|
||||||
|
@ -477,7 +479,7 @@ void AssFile::Undo() {
|
||||||
void AssFile::Redo() {
|
void AssFile::Redo() {
|
||||||
if (RedoStack.empty()) return;
|
if (RedoStack.empty()) return;
|
||||||
|
|
||||||
std::swap(*this, RedoStack.back());
|
swap(RedoStack.back());
|
||||||
UndoStack.push_back(*this);
|
UndoStack.push_back(*this);
|
||||||
RedoStack.pop_back();
|
RedoStack.pop_back();
|
||||||
|
|
||||||
|
@ -515,10 +517,10 @@ void AssFile::Sort(CompFunc comp, std::set<AssDialogue*> const& limit) {
|
||||||
Sort(Line, comp, limit);
|
Sort(Line, comp, limit);
|
||||||
}
|
}
|
||||||
namespace {
|
namespace {
|
||||||
struct AssEntryComp : public std::binary_function<const AssEntry*, const AssEntry*, bool> {
|
struct AssEntryComp : public std::binary_function<AssEntry, AssEntry, bool> {
|
||||||
AssFile::CompFunc comp;
|
AssFile::CompFunc comp;
|
||||||
bool operator()(const AssEntry* a, const AssEntry* b) const {
|
bool operator()(AssEntry const&a, AssEntry const&b) const {
|
||||||
return comp(static_cast<const AssDialogue*>(a), static_cast<const AssDialogue*>(b));
|
return comp(static_cast<const AssDialogue*>(&a), static_cast<const AssDialogue*>(&b));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -527,17 +529,18 @@ namespace {
|
||||||
return d && (limit.empty() || limit.count(d));
|
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;
|
AssEntryComp compE;
|
||||||
compE.comp = comp;
|
compE.comp = comp;
|
||||||
// Sort each block of AssDialogues separately, leaving everything else untouched
|
// Sort each block of AssDialogues separately, leaving everything else untouched
|
||||||
for (entryIter begin = lst.begin(); begin != lst.end(); ++begin) {
|
for (entryIter begin = lst.begin(); begin != lst.end(); ++begin) {
|
||||||
if (!is_dialogue(*begin, limit)) continue;
|
if (!is_dialogue(&*begin, limit)) continue;
|
||||||
entryIter end = begin;
|
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
|
// used instead of std::list::sort for partial list sorting
|
||||||
std::list<AssEntry*> tmp;
|
EntryList tmp;
|
||||||
tmp.splice(tmp.begin(), lst, begin, end);
|
tmp.splice(tmp.begin(), lst, begin, end);
|
||||||
tmp.sort(compE);
|
tmp.sort(compE);
|
||||||
lst.splice(end, tmp);
|
lst.splice(end, tmp);
|
||||||
|
@ -545,8 +548,5 @@ void AssFile::Sort(std::list<AssEntry*> &lst, CompFunc comp, std::set<AssDialogu
|
||||||
begin = --end;
|
begin = --end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void AssFile::Sort(std::list<AssDialogue*> &lst, CompFunc comp) {
|
|
||||||
lst.sort(comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssFile *AssFile::top;
|
AssFile *AssFile::top;
|
||||||
|
|
|
@ -41,14 +41,19 @@
|
||||||
#include <wx/arrstr.h>
|
#include <wx/arrstr.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/intrusive/list.hpp>
|
||||||
|
|
||||||
#include <libaegisub/signal.h>
|
#include <libaegisub/signal.h>
|
||||||
|
|
||||||
|
#include "ass_entry.h"
|
||||||
|
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
class AssStyle;
|
class AssStyle;
|
||||||
class AssAttachment;
|
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
|
/// DOCME
|
||||||
/// @class AssFile
|
/// @class AssFile
|
||||||
|
@ -78,7 +83,7 @@ class AssFile {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The lines in the file
|
/// The lines in the file
|
||||||
std::list<AssEntry*> Line;
|
EntryList Line;
|
||||||
/// The filename of this file, if any
|
/// The filename of this file, if any
|
||||||
wxString filename;
|
wxString filename;
|
||||||
/// Is the file loaded?
|
/// Is the file loaded?
|
||||||
|
@ -229,8 +234,5 @@ public:
|
||||||
/// @brief Sort the dialogue lines in the given list
|
/// @brief Sort the dialogue lines in the given list
|
||||||
/// @param comp Comparison function to use. Defaults to sorting by start time.
|
/// @param comp Comparison function to use. Defaults to sorting by start time.
|
||||||
/// @param limit If non-empty, only lines in this set are sorted
|
/// @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*>());
|
static void Sort(EntryList& 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);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -291,8 +291,8 @@ void AssKaraoke::SplitLines(std::set<AssDialogue*> const& lines, agi::Context *c
|
||||||
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
||||||
|
|
||||||
bool did_split = false;
|
bool did_split = false;
|
||||||
for (std::list<AssEntry*>::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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 || !lines.count(diag)) continue;
|
if (!diag || !lines.count(diag)) continue;
|
||||||
|
|
||||||
kara.SetLine(diag);
|
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->End = kit->start_time + kit->duration;
|
||||||
new_line->Text = kit->GetText(false);
|
new_line->Text = kit->GetText(false);
|
||||||
|
|
||||||
c->ass->Line.insert(it, new_line);
|
c->ass->Line.insert(it, *new_line);
|
||||||
|
|
||||||
if (in_sel)
|
if (in_sel)
|
||||||
sel.insert(new_line);
|
sel.insert(new_line);
|
||||||
|
|
|
@ -51,7 +51,7 @@ void AssParser::ParseAttachmentLine(wxString const& data) {
|
||||||
// Data is over, add attachment to the file
|
// Data is over, add attachment to the file
|
||||||
if (!valid_data || is_filename) {
|
if (!valid_data || is_filename) {
|
||||||
attach->Finish();
|
attach->Finish();
|
||||||
target->Line.push_back(attach.release());
|
target->Line.push_back(*attach.release());
|
||||||
AddLine(data);
|
AddLine(data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -60,7 +60,7 @@ void AssParser::ParseAttachmentLine(wxString const& data) {
|
||||||
// Done building
|
// Done building
|
||||||
if (data.Length() < 80) {
|
if (data.Length() < 80) {
|
||||||
attach->Finish();
|
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) {
|
void AssParser::ParseScriptInfoLine(wxString const& data) {
|
||||||
// If the first nonblank line isn't a header pretend it starts with [Script Info]
|
// If the first nonblank line isn't a header pretend it starts with [Script Info]
|
||||||
if (target->Line.empty())
|
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(";")) {
|
if (data.StartsWith(";")) {
|
||||||
// Skip stupid comments added by other programs
|
// 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) {
|
void AssParser::ParseEventLine(wxString const& data) {
|
||||||
if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:"))
|
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:"))
|
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) {
|
void AssParser::ParseStyleLine(wxString const& data) {
|
||||||
if (data.StartsWith("Style:"))
|
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:"))
|
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) {
|
void AssParser::ParseFontLine(wxString const& data) {
|
||||||
|
@ -121,7 +121,7 @@ void AssParser::ParseGraphicsLine(wxString const& data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssParser::AppendUnknownLine(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) {
|
void AssParser::AddLine(wxString const& data) {
|
||||||
|
@ -166,7 +166,7 @@ void AssParser::AddLine(wxString const& data) {
|
||||||
state = &AssParser::AppendUnknownLine;
|
state = &AssParser::AppendUnknownLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->Line.push_back(new AssEntry(header, header));
|
target->Line.push_back(*new AssEntry(header, header));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -720,21 +720,21 @@ void AudioTimingControllerDialogue::SetMarkers(std::vector<AudioMarker*> const&
|
||||||
AnnounceMarkerMoved();
|
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 !diag->Comment;
|
||||||
return false;
|
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()
|
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();
|
bool was_empty = inactive_lines.empty();
|
||||||
inactive_lines.clear();
|
inactive_lines.clear();
|
||||||
|
@ -747,32 +747,31 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
|
||||||
case 2: // Previous and next lines
|
case 2: // Previous and next lines
|
||||||
if (AssDialogue *line = context->selectionController->GetActiveLine())
|
if (AssDialogue *line = context->selectionController->GetActiveLine())
|
||||||
{
|
{
|
||||||
std::list<AssEntry*>::iterator current_line =
|
entryIter current_line = context->ass->Line.iterator_to(*line);
|
||||||
find(context->ass->Line.begin(), context->ass->Line.end(), line);
|
|
||||||
if (current_line == context->ass->Line.end())
|
if (current_line == context->ass->Line.end())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
std::list<AssEntry*>::iterator prev = current_line;
|
entryIter prev = current_line;
|
||||||
while (--prev != context->ass->Line.begin() && !predicate(*prev)) ;
|
while (--prev != context->ass->Line.begin() && !predicate(*prev)) ;
|
||||||
if (prev != context->ass->Line.begin())
|
if (prev != context->ass->Line.begin())
|
||||||
AddInactiveLine(sel, static_cast<AssDialogue*>(*prev));
|
AddInactiveLine(sel, static_cast<AssDialogue*>(&*prev));
|
||||||
|
|
||||||
if (mode == 2)
|
if (mode == 2)
|
||||||
{
|
{
|
||||||
std::list<AssEntry*>::iterator next =
|
entryIter next =
|
||||||
find_if(++current_line, context->ass->Line.end(), predicate);
|
find_if(++current_line, context->ass->Line.end(), predicate);
|
||||||
if (next != context->ass->Line.end())
|
if (next != context->ass->Line.end())
|
||||||
AddInactiveLine(sel, static_cast<AssDialogue*>(*next));
|
AddInactiveLine(sel, static_cast<AssDialogue*>(&*next));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: // All inactive lines
|
case 3: // All inactive lines
|
||||||
{
|
{
|
||||||
AssDialogue *active_line = context->selectionController->GetActiveLine();
|
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))
|
if (&*it != active_line && predicate(*it))
|
||||||
AddInactiveLine(sel, static_cast<AssDialogue*>(*it));
|
AddInactiveLine(sel, static_cast<AssDialogue*>(&*it));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -843,7 +843,7 @@ namespace Automation4 {
|
||||||
int row = 1;
|
int row = 1;
|
||||||
int idx = 1;
|
int idx = 1;
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it, ++row) {
|
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) continue;
|
||||||
|
|
||||||
if (diag == active_line) active_idx = row;
|
if (diag == active_line) active_idx = row;
|
||||||
|
@ -935,7 +935,7 @@ namespace Automation4 {
|
||||||
|
|
||||||
advance(it, cur - last_idx);
|
advance(it, cur - last_idx);
|
||||||
|
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
|
||||||
if (!diag) {
|
if (!diag) {
|
||||||
wxLogError("Selected row %d is not a dialogue line", cur);
|
wxLogError("Selected row %d is not a dialogue line", cur);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/range/adaptor/indirected.hpp>
|
||||||
|
#include <boost/range/algorithm_ext.hpp>
|
||||||
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -660,14 +662,14 @@ namespace Automation4 {
|
||||||
// Apply any pending commits
|
// Apply any pending commits
|
||||||
for (std::deque<PendingCommit>::iterator it = pending_commits.begin(); it != pending_commits.end(); ++it) {
|
for (std::deque<PendingCommit>::iterator it = pending_commits.begin(); it != pending_commits.end(); ++it) {
|
||||||
ass->Line.clear();
|
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);
|
ass->Commit(it->mesage, it->modification_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit any changes after the last undo point was set
|
// Commit any changes after the last undo point was set
|
||||||
if (modification_type) {
|
if (modification_type) {
|
||||||
ass->Line.clear();
|
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())
|
if (modification_type && can_set_undo && !undo_description.empty())
|
||||||
ass->Commit(undo_description, modification_type);
|
ass->Commit(undo_description, modification_type);
|
||||||
|
@ -691,8 +693,10 @@ namespace Automation4 {
|
||||||
, can_set_undo(can_set_undo)
|
, can_set_undo(can_set_undo)
|
||||||
, modification_type(0)
|
, modification_type(0)
|
||||||
, references(2)
|
, 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
|
// prepare userdata object
|
||||||
*static_cast<LuaAssFile**>(lua_newuserdata(L, sizeof(LuaAssFile*))) = this;
|
*static_cast<LuaAssFile**>(lua_newuserdata(L, sizeof(LuaAssFile*))) = this;
|
||||||
|
|
||||||
|
|
|
@ -279,7 +279,7 @@ void BaseGrid::UpdateMaps(bool preserve_selected_rows) {
|
||||||
line_index_map.clear();
|
line_index_map.clear();
|
||||||
|
|
||||||
for (entryIter cur = context->ass->Line.begin(); cur != context->ass->Line.end(); ++cur) {
|
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();
|
line_index_map[curdiag] = (int)index_line_map.size();
|
||||||
index_line_map.push_back(curdiag);
|
index_line_map.push_back(curdiag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ void paste_lines(agi::Context *c, bool paste_over) {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
AssDialogue *rel_line = c->selectionController->GetActiveLine();
|
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;
|
AssDialogue *first = 0;
|
||||||
SubtitleSelection newsel;
|
SubtitleSelection newsel;
|
||||||
|
@ -118,7 +118,7 @@ void paste_lines(agi::Context *c, bool paste_over) {
|
||||||
|
|
||||||
if (!paste_over) {
|
if (!paste_over) {
|
||||||
newsel.insert(curdiag);
|
newsel.insert(curdiag);
|
||||||
c->ass->Line.insert(pos, curdiag);
|
c->ass->Line.insert(pos, *curdiag);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Get list of options to paste over, if not asked yet
|
// 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();
|
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[0]) line->Layer = curdiag->Layer;
|
||||||
if (pasteOverOptions[1]) line->Start = curdiag->Start;
|
if (pasteOverOptions[1]) line->Start = curdiag->Start;
|
||||||
if (pasteOverOptions[2]) line->End = curdiag->End;
|
if (pasteOverOptions[2]) line->End = curdiag->End;
|
||||||
|
@ -147,7 +147,7 @@ void paste_lines(agi::Context *c, bool paste_over) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
++pos;
|
++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())
|
if (pos == c->ass->Line.end())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,7 @@ static void copy_lines(agi::Context *c) {
|
||||||
wxString data;
|
wxString data;
|
||||||
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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 (diag && sel.count(diag)) {
|
||||||
if (!data.empty())
|
if (!data.empty())
|
||||||
data += "\r\n";
|
data += "\r\n";
|
||||||
|
@ -508,7 +508,7 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) {
|
||||||
bool hit_active = false;
|
bool hit_active = false;
|
||||||
|
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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) continue;
|
||||||
|
|
||||||
if (diag == active) {
|
if (diag == active) {
|
||||||
|
@ -524,10 +524,8 @@ static void delete_lines(agi::Context *c, wxString const& commit_message) {
|
||||||
|
|
||||||
// Delete selected lines
|
// Delete selected lines
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) {
|
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ) {
|
||||||
if (sel.count(static_cast<AssDialogue*>(*it))) {
|
if (sel.count(static_cast<AssDialogue*>(&*it)))
|
||||||
delete *it;
|
delete &*it++;
|
||||||
c->ass->Line.erase(it++);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
++it;
|
++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;
|
SubtitleSelectionController::Selection const& sel;
|
||||||
in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { }
|
in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { }
|
||||||
bool operator()(AssEntry *e) const {
|
bool operator()(AssEntry const& e) const {
|
||||||
AssDialogue *d = dynamic_cast<AssDialogue*>(e);
|
const AssDialogue *d = dynamic_cast<const AssDialogue*>(&e);
|
||||||
return d && sel.count(d);
|
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;
|
SubtitleSelectionController::Selection new_sel;
|
||||||
AssDialogue *new_active = 0;
|
AssDialogue *new_active = 0;
|
||||||
|
|
||||||
std::list<AssEntry*>::iterator start = c->ass->Line.begin();
|
entryIter start = c->ass->Line.begin();
|
||||||
std::list<AssEntry*>::iterator end = c->ass->Line.end();
|
entryIter end = c->ass->Line.end();
|
||||||
while (start != end) {
|
while (start != end) {
|
||||||
// Find the first line in the selection
|
// Find the first line in the selection
|
||||||
start = find_if(start, end, sel);
|
start = find_if(start, end, sel);
|
||||||
if (start == end) break;
|
if (start == end) break;
|
||||||
|
|
||||||
// And the last line in this contiguous selection
|
// And the last line in this contiguous selection
|
||||||
std::list<AssEntry*>::iterator insert_pos = find_if(start, end, std::not1(sel));
|
entryIter insert_pos = find_if(start, end, std::not1(sel));
|
||||||
std::list<AssEntry*>::iterator last = insert_pos;
|
entryIter last = insert_pos;
|
||||||
--last;
|
--last;
|
||||||
|
|
||||||
// Duplicate each of the selected lines, inserting them in a block
|
// Duplicate each of the selected lines, inserting them in a block
|
||||||
// after the selected block
|
// after the selected block
|
||||||
do {
|
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);
|
new_sel.insert(new_diag);
|
||||||
if (!new_active)
|
if (!new_active)
|
||||||
new_active = new_diag;
|
new_active = new_diag;
|
||||||
|
@ -686,26 +684,20 @@ static void combine_lines(agi::Context *c, void (*combiner)(AssDialogue *, AssDi
|
||||||
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
||||||
|
|
||||||
AssDialogue *first = 0;
|
AssDialogue *first = 0;
|
||||||
entryIter out = c->ass->Line.begin();
|
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.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 || !sel.count(diag))
|
||||||
if (!diag || !sel.count(diag)) {
|
|
||||||
*out++ = *it;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
first = diag;
|
first = diag;
|
||||||
*out++ = *it;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
combiner(first, diag);
|
combiner(first, diag);
|
||||||
|
|
||||||
first->End = std::max(first->End, diag->End);
|
first->End = std::max(first->End, diag->End);
|
||||||
delete diag;
|
delete diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->ass->Line.erase(out, c->ass->Line.end());
|
|
||||||
sel.clear();
|
sel.clear();
|
||||||
sel.insert(first);
|
sel.insert(first);
|
||||||
c->selectionController->SetSelectionAndActive(sel, first);
|
c->selectionController->SetSelectionAndActive(sel, first);
|
||||||
|
|
|
@ -85,8 +85,8 @@ struct grid_line_next_create : public Command {
|
||||||
newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt();
|
newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt();
|
||||||
newline->Style = cur->Style;
|
newline->Style = cur->Style;
|
||||||
|
|
||||||
entryIter pos = find(c->ass->Line.begin(), c->ass->Line.end(), cur);
|
entryIter pos = c->ass->Line.iterator_to(*cur);
|
||||||
c->ass->Line.insert(++pos, newline);
|
c->ass->Line.insert(++pos, *newline);
|
||||||
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
|
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
|
||||||
c->selectionController->NextLine();
|
c->selectionController->NextLine();
|
||||||
}
|
}
|
||||||
|
@ -353,13 +353,12 @@ static bool move_one(T begin, T end, U const& value) {
|
||||||
size_t move_count = 0;
|
size_t move_count = 0;
|
||||||
T prev = end;
|
T prev = end;
|
||||||
for (; begin != end; ++begin) {
|
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);
|
bool in_set = !!value.count(cur);
|
||||||
if (!in_set && cur)
|
if (!in_set && cur)
|
||||||
prev = begin;
|
prev = begin;
|
||||||
else if (in_set && prev != end) {
|
else if (in_set && prev != end) {
|
||||||
using std::swap;
|
begin->swap_nodes(*prev);
|
||||||
swap(*begin, *prev);
|
|
||||||
prev = begin;
|
prev = begin;
|
||||||
if (++move_count == value.size())
|
if (++move_count == value.size())
|
||||||
break;
|
break;
|
||||||
|
@ -420,11 +419,7 @@ struct grid_swap : public Command {
|
||||||
void operator()(agi::Context *c) {
|
void operator()(agi::Context *c) {
|
||||||
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
||||||
if (sel.size() == 2) {
|
if (sel.size() == 2) {
|
||||||
entryIter a = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.begin());
|
(*sel.begin())->swap_nodes(**sel.rbegin());
|
||||||
entryIter b = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.rbegin());
|
|
||||||
|
|
||||||
using std::swap;
|
|
||||||
swap(*a, *b);
|
|
||||||
c->ass->Commit(_("swap lines"), AssFile::COMMIT_ORDER);
|
c->ass->Commit(_("swap lines"), AssFile::COMMIT_ORDER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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->End = video_ms + OPT_GET("Timing/Default Duration")->GetInt();
|
||||||
def->Style = c->selectionController->GetActiveLine()->Style;
|
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;
|
if (after) ++pos;
|
||||||
|
|
||||||
c->ass->Line.insert(pos, def);
|
c->ass->Line.insert(pos, *def);
|
||||||
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
|
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
|
||||||
|
|
||||||
SubtitleSelection sel;
|
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();
|
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) {
|
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
|
// Limit the line to the available time
|
||||||
if (diag && diag->Start >= new_line->Start)
|
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 we just hit the active line, insert the new line after it
|
||||||
if (diag == active_line) {
|
if (diag == active_line) {
|
||||||
++it;
|
++it;
|
||||||
c->ass->Line.insert(it, new_line);
|
c->ass->Line.insert(it, *new_line);
|
||||||
--it;
|
--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();
|
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) {
|
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
|
// Limit the line to the available time
|
||||||
if (diag && diag->End <= new_line->End)
|
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 we just hit the active line, insert the new line before it
|
||||||
if (diag == active_line)
|
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);
|
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
|
||||||
|
@ -408,7 +408,7 @@ struct subtitle_select_visible : public Command {
|
||||||
int frame = c->videoController->GetFrameN();
|
int frame = c->videoController->GetFrameN();
|
||||||
|
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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 &&
|
if (diag &&
|
||||||
c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame &&
|
c->videoController->FrameAtTime(diag->Start, agi::vfr::START) <= frame &&
|
||||||
c->videoController->FrameAtTime(diag->End, agi::vfr::END) >= frame)
|
c->videoController->FrameAtTime(diag->End, agi::vfr::END) >= frame)
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace {
|
||||||
|
|
||||||
size_t found = 0;
|
size_t found = 0;
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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) continue;
|
||||||
|
|
||||||
if (sel.count(diag)) {
|
if (sel.count(diag)) {
|
||||||
|
|
|
@ -102,10 +102,8 @@ void DialogAttachments::UpdateList() {
|
||||||
listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100);
|
listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100);
|
||||||
|
|
||||||
// Fill list
|
// Fill list
|
||||||
AssAttachment *attach;
|
for (entryIter cur = ass->Line.begin();cur != ass->Line.end();cur++) {
|
||||||
for (std::list<AssEntry*>::iterator cur = ass->Line.begin();cur != ass->Line.end();cur++) {
|
if (AssAttachment *attach = dynamic_cast<AssAttachment*>(&*cur)) {
|
||||||
attach = dynamic_cast<AssAttachment*>(*cur);
|
|
||||||
if (attach) {
|
|
||||||
// Add item
|
// Add item
|
||||||
int row = listView->GetItemCount();
|
int row = listView->GetItemCount();
|
||||||
listView->InsertItem(row,attach->GetFileName(true));
|
listView->InsertItem(row,attach->GetFileName(true));
|
||||||
|
@ -210,19 +208,19 @@ void DialogAttachments::OnDelete(wxCommandEvent &) {
|
||||||
if (i == -1) return;
|
if (i == -1) return;
|
||||||
|
|
||||||
while (i != -1) {
|
while (i != -1) {
|
||||||
ass->Line.remove((AssEntry*)wxUIntToPtr(listView->GetItemData(i)));
|
delete (AssEntry*)wxUIntToPtr(listView->GetItemData(i));
|
||||||
i = listView->GetNextSelected(i);
|
i = listView->GetNextSelected(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove empty attachment sections in the file
|
// Remove empty attachment sections in the file
|
||||||
for (std::list<AssEntry*>::iterator it = ass->Line.begin(); it != ass->Line.end(); ) {
|
for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ) {
|
||||||
if ((*it)->GetType() == ENTRY_BASE && ((*it)->group == "[Fonts]" || (*it)->group == "[Graphics]")) {
|
if (it->GetType() == ENTRY_BASE && (it->group == "[Fonts]" || it->group == "[Graphics]")) {
|
||||||
wxString group = (*it)->group;
|
wxString group = it->group;
|
||||||
std::list<AssEntry*>::iterator header = it;
|
entryIter header = it;
|
||||||
|
|
||||||
bool has_attachments = false;
|
bool has_attachments = false;
|
||||||
for (++it; it != ass->Line.end() && (*it)->group == group; ++it) {
|
for (++it; it != ass->Line.end() && it->group == group; ++it) {
|
||||||
if ((*it)->GetType() == ENTRY_ATTACHMENT) {
|
if (it->GetType() == ENTRY_ATTACHMENT) {
|
||||||
has_attachments = true;
|
has_attachments = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -230,10 +228,8 @@ void DialogAttachments::OnDelete(wxCommandEvent &) {
|
||||||
|
|
||||||
// Empty group found, delete it
|
// Empty group found, delete it
|
||||||
if (!has_attachments) {
|
if (!has_attachments) {
|
||||||
while (header != it) {
|
while (header != it)
|
||||||
delete *header;
|
delete &*header++;
|
||||||
ass->Line.erase(header++);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -88,7 +88,7 @@ class FontsCollectorThread : public wxThread {
|
||||||
std::vector<wxString> GetFontPaths(wxString const&, int, bool, std::set<wxUniChar> const&) { return std::vector<wxString>(); }
|
std::vector<wxString> GetFontPaths(wxString const&, int, bool, std::set<wxUniChar> const&) { return std::vector<wxString>(); }
|
||||||
} lister;
|
} lister;
|
||||||
#endif
|
#endif
|
||||||
std::vector<wxString> paths = FontCollector(callback, lister).GetFontPaths(subs->Line);
|
std::vector<wxString> paths = FontCollector(callback, lister).GetFontPaths(subs);
|
||||||
if (paths.empty()) return;
|
if (paths.empty()) return;
|
||||||
|
|
||||||
// Copy fonts
|
// Copy fonts
|
||||||
|
|
|
@ -629,15 +629,13 @@ bool KaraokeLineMatchDisplay::UndoMatch()
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogKanjiTimer::DialogKanjiTimer(agi::Context *c)
|
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));
|
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 *DisplayBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Text"));
|
||||||
wxSizer *StylesBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Styles"));
|
wxSizer *StylesBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Styles"));
|
||||||
wxFlexGridSizer *StylesGridSizer = new wxFlexGridSizer(2, 2, 6, 6);
|
wxFlexGridSizer *StylesGridSizer = new wxFlexGridSizer(2, 2, 6, 6);
|
||||||
|
@ -744,8 +742,8 @@ void DialogKanjiTimer::OnStart(wxCommandEvent &) {
|
||||||
else if (SourceStyle->GetValue() == DestStyle->GetValue())
|
else if (SourceStyle->GetValue() == DestStyle->GetValue())
|
||||||
wxMessageBox(_("The source and destination styles must be different."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
wxMessageBox(_("The source and destination styles must be different."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
||||||
else {
|
else {
|
||||||
currentSourceLine = FindNextStyleMatch(subs->Line.begin(), SourceStyle->GetValue());
|
currentSourceLine = FindNextStyleMatch(&*subs->Line.begin(), SourceStyle->GetValue());
|
||||||
currentDestinationLine = FindNextStyleMatch(subs->Line.begin(), DestStyle->GetValue());
|
currentDestinationLine = FindNextStyleMatch(&*subs->Line.begin(), DestStyle->GetValue());
|
||||||
ResetForNewLine();
|
ResetForNewLine();
|
||||||
}
|
}
|
||||||
LinesToChange.clear();
|
LinesToChange.clear();
|
||||||
|
@ -784,11 +782,11 @@ void DialogKanjiTimer::OnGoBack(wxCommandEvent &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogKanjiTimer::OnAccept(wxCommandEvent &) {
|
void DialogKanjiTimer::OnAccept(wxCommandEvent &) {
|
||||||
if (currentDestinationLine == subs->Line.end()) return;
|
if (!currentDestinationLine) return;
|
||||||
|
|
||||||
if (display->GetRemainingSource() > 0)
|
if (display->GetRemainingSource() > 0)
|
||||||
wxMessageBox(_("Group all of the source text."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
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()));
|
LinesToChange.push_back(std::make_pair(destLine, display->GetOutputLine()));
|
||||||
|
|
||||||
currentSourceLine = FindNextStyleMatch(currentSourceLine, SourceStyle->GetValue());
|
currentSourceLine = FindNextStyleMatch(currentSourceLine, SourceStyle->GetValue());
|
||||||
|
@ -834,10 +832,10 @@ void DialogKanjiTimer::ResetForNewLine()
|
||||||
AssDialogue *src = 0;
|
AssDialogue *src = 0;
|
||||||
AssDialogue *dst = 0;
|
AssDialogue *dst = 0;
|
||||||
|
|
||||||
if (currentSourceLine != subs->Line.end())
|
if (currentSourceLine)
|
||||||
src = dynamic_cast<AssDialogue*>(*currentSourceLine);
|
src = dynamic_cast<AssDialogue*>(currentSourceLine);
|
||||||
if (currentDestinationLine != subs->Line.end())
|
if (currentDestinationLine)
|
||||||
dst = dynamic_cast<AssDialogue*>(*currentDestinationLine);
|
dst = dynamic_cast<AssDialogue*>(currentDestinationLine);
|
||||||
|
|
||||||
if (src == 0 || dst == 0)
|
if (src == 0 || dst == 0)
|
||||||
{
|
{
|
||||||
|
@ -858,30 +856,30 @@ void DialogKanjiTimer::TryAutoMatch()
|
||||||
display->AutoMatchJapanese();
|
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)
|
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)
|
if (dlg && dlg->Style == search_style)
|
||||||
break;
|
return dlg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return search_from;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,32 +53,17 @@ class wxCheckBox;
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class DialogKanjiTimer : public wxDialog {
|
class DialogKanjiTimer : public wxDialog {
|
||||||
typedef std::list<AssEntry*>::iterator entryIter;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
AssFile *subs;
|
AssFile *subs;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
KaraokeLineMatchDisplay *display;
|
KaraokeLineMatchDisplay *display;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxComboBox *SourceStyle, *DestStyle;
|
wxComboBox *SourceStyle, *DestStyle;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxCheckBox *Interpolate;
|
wxCheckBox *Interpolate;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
std::vector<std::pair<AssDialogue*, wxString> > LinesToChange;
|
std::vector<std::pair<AssDialogue*, wxString> > LinesToChange;
|
||||||
|
|
||||||
/// DOCME
|
AssEntry *currentSourceLine;
|
||||||
entryIter currentSourceLine;
|
AssEntry *currentDestinationLine;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
entryIter currentDestinationLine;
|
|
||||||
|
|
||||||
void OnClose(wxCommandEvent &event);
|
void OnClose(wxCommandEvent &event);
|
||||||
void OnStart(wxCommandEvent &event);
|
void OnStart(wxCommandEvent &event);
|
||||||
|
@ -93,8 +78,8 @@ class DialogKanjiTimer : public wxDialog {
|
||||||
void ResetForNewLine();
|
void ResetForNewLine();
|
||||||
void TryAutoMatch();
|
void TryAutoMatch();
|
||||||
|
|
||||||
entryIter FindNextStyleMatch(entryIter search_from, const wxString &search_style);
|
AssEntry *FindNextStyleMatch(AssEntry *search_from, const wxString &search_style);
|
||||||
entryIter FindPrevStyleMatch(entryIter search_from, const wxString &search_style);
|
AssEntry *FindPrevStyleMatch(AssEntry *search_from, const wxString &search_style);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DialogKanjiTimer(agi::Context *context);
|
DialogKanjiTimer(agi::Context *context);
|
||||||
|
|
|
@ -200,8 +200,8 @@ namespace {
|
||||||
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
|
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resample_line(resample_state *state, AssEntry *line) {
|
void resample_line(resample_state *state, AssEntry &line) {
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(line);
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&line);
|
||||||
if (diag && !(diag->Comment && (diag->Effect.StartsWith("template") || diag->Effect.StartsWith("code")))) {
|
if (diag && !(diag->Comment && (diag->Effect.StartsWith("template") || diag->Effect.StartsWith("code")))) {
|
||||||
diag->ParseAssTags();
|
diag->ParseAssTags();
|
||||||
diag->ProcessParameters(resample_tags, state);
|
diag->ProcessParameters(resample_tags, state);
|
||||||
|
@ -217,7 +217,7 @@ namespace {
|
||||||
diag->UpdateText();
|
diag->UpdateText();
|
||||||
diag->ClearBlocks();
|
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->fontsize = int(style->fontsize * state->ry + 0.5);
|
||||||
style->outline_w *= state->ry;
|
style->outline_w *= state->ry;
|
||||||
style->shadow_w *= state->ry;
|
style->shadow_w *= state->ry;
|
||||||
|
|
|
@ -379,8 +379,8 @@ void SearchReplaceEngine::ReplaceAll() {
|
||||||
bool inSel = affect == 1;
|
bool inSel = affect == 1;
|
||||||
|
|
||||||
// Scan
|
// Scan
|
||||||
for (std::list<AssEntry*>::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) {
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
|
||||||
if (!diag) continue;
|
if (!diag) continue;
|
||||||
|
|
||||||
// Check if row is selected
|
// Check if row is selected
|
||||||
|
|
|
@ -114,7 +114,7 @@ static std::set<AssDialogue*> process(wxString match_text, bool match_case, int
|
||||||
|
|
||||||
std::set<AssDialogue*> matches;
|
std::set<AssDialogue*> matches;
|
||||||
for (entryIter it = ass->Line.begin(); it != ass->Line.end(); ++it) {
|
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) continue;
|
||||||
if (diag->Comment && !comments) continue;
|
if (diag->Comment && !comments) continue;
|
||||||
if (!diag->Comment && !dialogue) continue;
|
if (!diag->Comment && !dialogue) continue;
|
||||||
|
|
|
@ -353,7 +353,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
|
||||||
json::Array shifted_blocks;
|
json::Array shifted_blocks;
|
||||||
|
|
||||||
for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) {
|
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;
|
if (!line) continue;
|
||||||
++row_number;
|
++row_number;
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ bool DialogSpellChecker::FindNext() {
|
||||||
if (CheckLine(active_line, start_pos, &commit_id))
|
if (CheckLine(active_line, start_pos, &commit_id))
|
||||||
return true;
|
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
|
// 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
|
// 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();
|
it = context->ass->Line.begin();
|
||||||
has_looped = true;
|
has_looped = true;
|
||||||
}
|
}
|
||||||
} while (!(active_line = dynamic_cast<AssDialogue*>(*it)));
|
} while (!(active_line = dynamic_cast<AssDialogue*>(&*it)));
|
||||||
|
|
||||||
if (CheckLine(active_line, 0, &commit_id))
|
if (CheckLine(active_line, 0, &commit_id))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -88,7 +88,7 @@ class StyleRenamer {
|
||||||
do_replace = replace;
|
do_replace = replace;
|
||||||
|
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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) continue;
|
||||||
|
|
||||||
if (diag->Style == source_name) {
|
if (diag->Style == source_name) {
|
||||||
|
|
|
@ -275,7 +275,7 @@ void DialogStyleManager::LoadCurrentStyles(int commit_type) {
|
||||||
styleMap.clear();
|
styleMap.clear();
|
||||||
|
|
||||||
for (entryIter cur = c->ass->Line.begin(); cur != c->ass->Line.end(); ++cur) {
|
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);
|
CurrentList->Append(style->name);
|
||||||
styleMap.push_back(style);
|
styleMap.push_back(style);
|
||||||
}
|
}
|
||||||
|
@ -562,10 +562,8 @@ void DialogStyleManager::OnCurrentDelete() {
|
||||||
int n = CurrentList->GetSelections(selections);
|
int n = CurrentList->GetSelections(selections);
|
||||||
|
|
||||||
if (confirm_delete(n, this, _("Confirm delete from current")) == wxYES) {
|
if (confirm_delete(n, this, _("Confirm delete from current")) == wxYES) {
|
||||||
for (int i=0;i<n;i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
AssStyle *temp = styleMap.at(selections[i]);
|
delete styleMap.at(selections[i]);
|
||||||
c->ass->Line.remove(temp);
|
|
||||||
delete temp;
|
|
||||||
}
|
}
|
||||||
c->ass->Commit(_("style delete"), AssFile::COMMIT_STYLES);
|
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) {
|
for (entryIter cur = c->ass->Line.begin(); cur != c->ass->Line.end(); cur = next) {
|
||||||
next = cur;
|
next = cur;
|
||||||
next++;
|
next++;
|
||||||
if (dynamic_cast<AssStyle*>(*cur)) {
|
if (dynamic_cast<AssStyle*>(&*cur)) {
|
||||||
c->ass->Line.insert(cur, styleMap[curn]);
|
c->ass->Line.insert(cur, *styleMap[curn]);
|
||||||
c->ass->Line.erase(cur);
|
c->ass->Line.erase(cur);
|
||||||
curn++;
|
curn++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,6 @@ std::vector<AssDialogue*> DialogTimingProcessor::SortDialogues() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AssDialogue*> sorted;
|
std::vector<AssDialogue*> sorted;
|
||||||
sorted.reserve(c->ass->Line.size());
|
|
||||||
|
|
||||||
if (onlySelection->IsChecked()) {
|
if (onlySelection->IsChecked()) {
|
||||||
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
SubtitleSelection sel = c->selectionController->GetSelectedSet();
|
||||||
|
|
|
@ -69,7 +69,7 @@ DialogTranslation::DialogTranslation(agi::Context *c)
|
||||||
, active_line(c->selectionController->GetActiveLine())
|
, active_line(c->selectionController->GetActiveLine())
|
||||||
, cur_block(0)
|
, cur_block(0)
|
||||||
, line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast<AssDialogue*>()))
|
, 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)
|
, switching_lines(false)
|
||||||
{
|
{
|
||||||
SetIcon(GETICON(translation_toolbutton_16));
|
SetIcon(GETICON(translation_toolbutton_16));
|
||||||
|
@ -177,7 +177,7 @@ void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) {
|
||||||
active_line = new_line;
|
active_line = new_line;
|
||||||
active_line->ParseAssTags();
|
active_line->ParseAssTags();
|
||||||
cur_block = 0;
|
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()) {
|
if (bad_block(active_line->Blocks[cur_block]) && !NextBlock()) {
|
||||||
wxMessageBox(_("No more lines to translate."));
|
wxMessageBox(_("No more lines to translate."));
|
||||||
|
|
|
@ -54,7 +54,7 @@ void AssFixStylesFilter::ProcessSubs(AssFile *subs, wxWindow *) {
|
||||||
styles.Sort();
|
styles.Sort();
|
||||||
|
|
||||||
for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) {
|
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())) {
|
if (!std::binary_search(styles.begin(), styles.end(), diag->Style.Lower())) {
|
||||||
diag->Style = "Default";
|
diag->Style = "Default";
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,7 @@ void AssTransformFramerateFilter::TransformTimeTags(wxString name,int n,AssOverr
|
||||||
void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) {
|
void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) {
|
||||||
if (!Input->IsLoaded() || !Output->IsLoaded()) return;
|
if (!Input->IsLoaded() || !Output->IsLoaded()) return;
|
||||||
for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) {
|
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) {
|
if (curDialogue) {
|
||||||
line = curDialogue;
|
line = curDialogue;
|
||||||
|
|
|
@ -24,9 +24,10 @@
|
||||||
#include "font_file_lister.h"
|
#include "font_file_lister.h"
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
|
#include "ass_file.h"
|
||||||
#include "ass_override.h"
|
#include "ass_override.h"
|
||||||
#include "ass_style.h"
|
#include "ass_style.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <algorithm>
|
#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;
|
if (line->Comment) return;
|
||||||
|
|
||||||
line->ParseAssTags();
|
std::vector<AssDialogueBlock*> blocks = line->ParseTags();
|
||||||
StyleInfo style = styles[line->Style];
|
StyleInfo style = styles[line->Style];
|
||||||
StyleInfo initial = style;
|
StyleInfo initial = style;
|
||||||
|
|
||||||
bool overriden = false;
|
bool overriden = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < line->Blocks.size(); ++i) {
|
for (size_t i = 0; i < blocks.size(); ++i) {
|
||||||
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(line->Blocks[i])) {
|
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(blocks[i])) {
|
||||||
for (size_t j = 0; j < ovr->Tags.size(); ++j) {
|
for (size_t j = 0; j < ovr->Tags.size(); ++j) {
|
||||||
AssOverrideTag *tag = ovr->Tags[j];
|
AssOverrideTag *tag = ovr->Tags[j];
|
||||||
wxString name = tag->Name;
|
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();
|
wxString text = txt->GetText();
|
||||||
|
|
||||||
if (text.empty() || (text.size() >= 2 && text.StartsWith("{") && text.EndsWith("}")))
|
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
|
// Do nothing with drawing blocks
|
||||||
}
|
}
|
||||||
line->ClearBlocks();
|
delete_clear(blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontCollector::ProcessChunk(std::pair<StyleInfo, UsageData> const& style) {
|
void FontCollector::ProcessChunk(std::pair<StyleInfo, UsageData> const& style) {
|
||||||
|
@ -148,22 +149,22 @@ void FontCollector::PrintUsage(UsageData const& data) {
|
||||||
status_callback("\n", 2);
|
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 = 0;
|
||||||
missing_glyphs = 0;
|
missing_glyphs = 0;
|
||||||
|
|
||||||
status_callback(_("Parsing file\n"), 0);
|
status_callback(_("Parsing file\n"), 0);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (std::list<AssEntry*>::const_iterator cur = file.begin(); cur != file.end(); ++cur) {
|
for (constEntryIter cur = file->Line.begin(); cur != file->Line.end(); ++cur) {
|
||||||
if (AssStyle *style = dynamic_cast<AssStyle*>(*cur)) {
|
if (const AssStyle *style = dynamic_cast<const AssStyle*>(&*cur)) {
|
||||||
StyleInfo &info = styles[style->name];
|
StyleInfo &info = styles[style->name];
|
||||||
info.facename = style->font;
|
info.facename = style->font;
|
||||||
info.bold = style->bold;
|
info.bold = style->bold;
|
||||||
info.italic = style->italic;
|
info.italic = style->italic;
|
||||||
used_styles[info].styles.insert(style->name);
|
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);
|
ProcessDialogueLine(diag, ++index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class AssEntry;
|
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
|
class AssFile;
|
||||||
|
|
||||||
typedef std::tr1::function<void (wxString, int)> FontCollectorStatusCallback;
|
typedef std::tr1::function<void (wxString, int)> FontCollectorStatusCallback;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ class FontCollector {
|
||||||
int missing_glyphs;
|
int missing_glyphs;
|
||||||
|
|
||||||
/// Gather all of the unique styles with text on a line
|
/// 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
|
/// Get the font for a single style
|
||||||
void ProcessChunk(std::pair<StyleInfo, UsageData> const& style);
|
void ProcessChunk(std::pair<StyleInfo, UsageData> const& style);
|
||||||
|
@ -109,5 +109,5 @@ public:
|
||||||
/// @param file Lines in the subtitle file to check
|
/// @param file Lines in the subtitle file to check
|
||||||
/// @param status Callback function for messages
|
/// @param status Callback function for messages
|
||||||
/// @return List of paths to fonts
|
/// @return List of paths to fonts
|
||||||
std::vector<wxString> GetFontPaths(std::list<AssEntry*> const& file);
|
std::vector<wxString> GetFontPaths(const AssFile *file);
|
||||||
};
|
};
|
||||||
|
|
|
@ -316,7 +316,7 @@ void SubsEditBox::PopulateList(wxComboBox *combo, wxString AssDialogue::*field)
|
||||||
|
|
||||||
std::set<wxString> values;
|
std::set<wxString> values;
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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.insert(diag->*field);
|
||||||
}
|
}
|
||||||
values.erase("");
|
values.erase("");
|
||||||
|
|
|
@ -853,7 +853,7 @@ void SubsTextEditCtrl::SplitLine(bool estimateTimes) {
|
||||||
|
|
||||||
AssDialogue *n1 = context->selectionController->GetActiveLine();
|
AssDialogue *n1 = context->selectionController->GetActiveLine();
|
||||||
AssDialogue *n2 = new AssDialogue(*n1);
|
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;
|
wxString orig = n1->Text;
|
||||||
n1->Text = orig.Left(from).Trim(true); // Trim off trailing whitespace
|
n1->Text = orig.Left(from).Trim(true); // Trim off trailing whitespace
|
||||||
|
|
|
@ -91,20 +91,17 @@ void SubtitlesGrid::RecombineLines() {
|
||||||
// 1, 1+2 (or 2+1), 2 gets turned into 1, 2, 2 so kill the duplicate
|
// 1, 1+2 (or 2+1), 2 gets turned into 1, 2, 2 so kill the duplicate
|
||||||
if (d1->Text == (*d2)->Text) {
|
if (d1->Text == (*d2)->Text) {
|
||||||
expand_times(d1, *d2);
|
expand_times(d1, *d2);
|
||||||
context->ass->Line.remove(d1);
|
|
||||||
delete d1;
|
delete d1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1, 1+2, 1 turns into 1, 2, [empty]
|
// 1, 1+2, 1 turns into 1, 2, [empty]
|
||||||
if (d1->Text.empty()) {
|
if (d1->Text.empty()) {
|
||||||
context->ass->Line.remove(d1);
|
|
||||||
delete d1;
|
delete d1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// If d2 is the last line in the selection it'll never hit the above test
|
// If d2 is the last line in the selection it'll never hit the above test
|
||||||
if (d2 == end && (*d2)->Text.empty()) {
|
if (d2 == end && (*d2)->Text.empty()) {
|
||||||
context->ass->Line.remove(*d2);
|
|
||||||
delete *d2;
|
delete *d2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ SubtitlesPreview::SubtitlesPreview(wxWindow *parent, wxSize size, int winStyle,
|
||||||
|
|
||||||
subFile->LoadDefault();
|
subFile->LoadDefault();
|
||||||
subFile->InsertStyle(style);
|
subFile->InsertStyle(style);
|
||||||
subFile->Line.push_back(line);
|
subFile->Line.push_back(*line);
|
||||||
|
|
||||||
SetSizeHints(size.GetWidth(), size.GetHeight(), -1, -1);
|
SetSizeHints(size.GetWidth(), size.GetHeight(), -1, -1);
|
||||||
wxSizeEvent evt(size);
|
wxSizeEvent evt(size);
|
||||||
|
|
|
@ -79,18 +79,18 @@ bool SubtitleFormat::CanWriteFile(wxString const& filename) const {
|
||||||
|
|
||||||
bool SubtitleFormat::CanSave(const AssFile *subs) const {
|
bool SubtitleFormat::CanSave(const AssFile *subs) const {
|
||||||
AssStyle defstyle;
|
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
|
// 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())
|
if (curstyle->GetEntryData() != defstyle.GetEntryData())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for attachments, if any is found, 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
|
// 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)
|
if (curdiag->GetStrippedText() != curdiag->Text)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -163,17 +163,17 @@ agi::vfr::Framerate SubtitleFormat::AskForFPS(bool allow_vfr, bool show_smpte) {
|
||||||
return Framerate();
|
return Framerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitleFormat::StripTags(LineList &lines) {
|
void SubtitleFormat::StripTags(AssFile &file) {
|
||||||
for (LineList::iterator cur = lines.begin(); cur != lines.end(); ++cur) {
|
for (entryIter cur = file.Line.begin(); cur != file.Line.end(); ++cur) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (AssDialogue *current = dynamic_cast<AssDialogue*>(&*cur)) {
|
||||||
current->StripTags();
|
current->StripTags();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitleFormat::ConvertNewlines(LineList &lines, wxString const& newline, bool mergeLineBreaks) {
|
void SubtitleFormat::ConvertNewlines(AssFile &file, wxString const& newline, bool mergeLineBreaks) {
|
||||||
for (LineList::iterator cur = lines.begin(); cur != lines.end(); ++cur) {
|
for (entryIter cur = file.Line.begin(); cur != file.Line.end(); ++cur) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (AssDialogue *current = dynamic_cast<AssDialogue*>(&*cur)) {
|
||||||
current->Text.Replace("\\h", " ");
|
current->Text.Replace("\\h", " ");
|
||||||
current->Text.Replace("\\n", newline);
|
current->Text.Replace("\\n", newline);
|
||||||
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) {
|
void SubtitleFormat::StripComments(AssFile &file) {
|
||||||
for (LineList::iterator it = lines.begin(); it != lines.end(); ) {
|
for (entryIter it = file.Line.begin(); it != file.Line.end(); ) {
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
|
||||||
if (!diag || (!diag->Comment && diag->Text.size()))
|
if (!diag || (!diag->Comment && diag->Text.size()))
|
||||||
++it;
|
++it;
|
||||||
else {
|
else {
|
||||||
delete *it;
|
delete &*it++;
|
||||||
lines.erase(it++);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitleFormat::StripNonDialogue(LineList &lines) {
|
void SubtitleFormat::StripNonDialogue(AssFile &file) {
|
||||||
for (LineList::iterator it = lines.begin(); it != lines.end(); ) {
|
for (entryIter it = file.Line.begin(); it != file.Line.end(); ) {
|
||||||
if (dynamic_cast<AssDialogue*>(*it))
|
if (dynamic_cast<AssDialogue*>(&*it))
|
||||||
++it;
|
++it;
|
||||||
else {
|
else {
|
||||||
delete *it;
|
delete &*it++;
|
||||||
lines.erase(it++);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dialog_start_lt(AssEntry *pos, AssDialogue *to_insert) {
|
static bool dialog_start_lt(AssEntry &pos, AssDialogue *to_insert) {
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(pos);
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&pos);
|
||||||
return diag && diag->Start > to_insert->Start;
|
return diag && diag->Start > to_insert->Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Split and merge lines so there are no overlapping lines
|
/// @brief Split and merge lines so there are no overlapping lines
|
||||||
///
|
///
|
||||||
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
||||||
void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
void SubtitleFormat::RecombineOverlaps(AssFile &file) {
|
||||||
LineList::iterator cur, next = lines.begin();
|
entryIter cur, next = file.Line.begin();
|
||||||
cur = next++;
|
cur = next++;
|
||||||
|
|
||||||
for (; next != lines.end(); cur = next++) {
|
for (; next != file.Line.end(); cur = next++) {
|
||||||
AssDialogue *prevdlg = dynamic_cast<AssDialogue*>(*cur);
|
AssDialogue *prevdlg = dynamic_cast<AssDialogue*>(&*cur);
|
||||||
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(*next);
|
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(&*next);
|
||||||
|
|
||||||
if (!curdlg || !prevdlg) continue;
|
if (!curdlg || !prevdlg) continue;
|
||||||
if (prevdlg->End <= curdlg->Start) continue;
|
if (prevdlg->End <= curdlg->Start) continue;
|
||||||
|
|
||||||
// Use names like in the algorithm description and prepare for erasing
|
// Use names like in the algorithm description and prepare for erasing
|
||||||
// old dialogues from the list
|
// old dialogues from the list
|
||||||
LineList::iterator prev = cur;
|
entryIter prev = cur;
|
||||||
cur = next;
|
cur = next;
|
||||||
next++;
|
next++;
|
||||||
|
|
||||||
// std::list::insert() inserts items before the given iterator, so
|
// std::list::insert() inserts items before the given iterator, so
|
||||||
// we need 'next' for inserting. 'prev' and 'cur' can safely be erased
|
// we need 'next' for inserting. 'prev' and 'cur' can safely be erased
|
||||||
// from the list now.
|
// from the list now.
|
||||||
lines.erase(prev);
|
file.Line.erase(prev);
|
||||||
lines.erase(cur);
|
file.Line.erase(cur);
|
||||||
|
|
||||||
//Is there an A part before the overlap?
|
//Is there an A part before the overlap?
|
||||||
if (curdlg->Start > prevdlg->Start) {
|
if (curdlg->Start > prevdlg->Start) {
|
||||||
|
@ -246,7 +244,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
||||||
newdlg->End = curdlg->Start;
|
newdlg->End = curdlg->Start;
|
||||||
newdlg->Text = prevdlg->Text;
|
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
|
// Overlapping A+B part
|
||||||
|
@ -257,7 +255,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
||||||
// Put an ASS format hard linewrap between lines
|
// Put an ASS format hard linewrap between lines
|
||||||
newdlg->Text = curdlg->Text + "\\N" + prevdlg->Text;
|
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?
|
// Is there an A part after the overlap?
|
||||||
|
@ -268,7 +266,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
||||||
newdlg->End = prevdlg->End;
|
newdlg->End = prevdlg->End;
|
||||||
newdlg->Text = prevdlg->Text;
|
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?
|
// Is there a B part after the overlap?
|
||||||
|
@ -279,7 +277,7 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
||||||
newdlg->End = curdlg->End;
|
newdlg->End = curdlg->End;
|
||||||
newdlg->Text = curdlg->Text;
|
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--;
|
next--;
|
||||||
|
@ -287,13 +285,13 @@ void SubtitleFormat::RecombineOverlaps(LineList &lines) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Merge identical lines that follow each other
|
/// @brief Merge identical lines that follow each other
|
||||||
void SubtitleFormat::MergeIdentical(LineList &lines) {
|
void SubtitleFormat::MergeIdentical(AssFile &file) {
|
||||||
LineList::iterator cur, next = lines.begin();
|
entryIter cur, next = file.Line.begin();
|
||||||
cur = next++;
|
cur = next++;
|
||||||
|
|
||||||
for (; next != lines.end(); cur = next++) {
|
for (; next != file.Line.end(); cur = next++) {
|
||||||
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(*cur);
|
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(&*cur);
|
||||||
AssDialogue *nextdlg = dynamic_cast<AssDialogue*>(*next);
|
AssDialogue *nextdlg = dynamic_cast<AssDialogue*>(&*next);
|
||||||
|
|
||||||
if (curdlg && nextdlg && curdlg->End == nextdlg->Start && curdlg->Text == nextdlg->Text) {
|
if (curdlg && nextdlg && curdlg->End == nextdlg->Start && curdlg->Text == nextdlg->Text) {
|
||||||
// Merge timing
|
// Merge timing
|
||||||
|
@ -301,8 +299,7 @@ void SubtitleFormat::MergeIdentical(LineList &lines) {
|
||||||
nextdlg->End = std::max(nextdlg->End, curdlg->End);
|
nextdlg->End = std::max(nextdlg->End, curdlg->End);
|
||||||
|
|
||||||
// Remove duplicate line
|
// Remove duplicate line
|
||||||
delete *cur;
|
delete curdlg;
|
||||||
lines.erase(cur);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,24 +64,22 @@ class SubtitleFormat {
|
||||||
static std::list<SubtitleFormat*> formats;
|
static std::list<SubtitleFormat*> formats;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::list<AssEntry*> LineList;
|
|
||||||
|
|
||||||
/// Strip override tags
|
/// Strip override tags
|
||||||
static void StripTags(LineList &lines);
|
static void StripTags(AssFile &file);
|
||||||
/// Convert newlines to the specified character(s)
|
/// Convert newlines to the specified character(s)
|
||||||
/// @param lineEnd newline character(s)
|
/// @param lineEnd newline character(s)
|
||||||
/// @param mergeLineBreaks Should multiple consecutive line breaks be merged into one?
|
/// @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
|
/// Remove All commented and empty lines
|
||||||
static void StripComments(LineList &lines);
|
static void StripComments(AssFile &file);
|
||||||
/// Remove everything but the dialogue lines
|
/// 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
|
/// @brief Split and merge lines so there are no overlapping lines
|
||||||
///
|
///
|
||||||
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
||||||
static void RecombineOverlaps(LineList &lines);
|
static void RecombineOverlaps(AssFile &file);
|
||||||
/// Merge sequential identical lines
|
/// Merge sequential identical lines
|
||||||
static void MergeIdentical(LineList &lines);
|
static void MergeIdentical(AssFile &file);
|
||||||
|
|
||||||
/// Prompt the user for a frame rate to use
|
/// Prompt the user for a frame rate to use
|
||||||
/// @param allow_vfr Include video frame rate as an option even if it's vfr
|
/// @param allow_vfr Include video frame rate as an option even if it's vfr
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
|
|
||||||
#include "subtitle_format_ass.h"
|
#include "subtitle_format_ass.h"
|
||||||
|
|
||||||
#include "ass_entry.h"
|
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_parser.h"
|
#include "ass_parser.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
@ -92,14 +91,14 @@ void AssSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename,
|
||||||
|
|
||||||
bool ssa = filename.Right(4).Lower() == ".ssa";
|
bool ssa = filename.Right(4).Lower() == ".ssa";
|
||||||
|
|
||||||
wxString group = src->Line.front()->group;
|
wxString group = src->Line.front().group;
|
||||||
for (LineList::const_iterator cur = src->Line.begin(); cur != src->Line.end(); ++cur) {
|
for (constEntryIter cur = src->Line.begin(); cur != src->Line.end(); ++cur) {
|
||||||
// Add a blank line between each group
|
// Add a blank line between each group
|
||||||
if ((*cur)->group != group) {
|
if (cur->group != group) {
|
||||||
file.WriteLineToFile("");
|
file.WriteLineToFile("");
|
||||||
group = (*cur)->group;
|
group = cur->group;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.WriteLineToFile(ssa ? (*cur)->GetSSAText() : (*cur)->GetEntryData(), true);
|
file.WriteLineToFile(ssa ? cur->GetSSAText() : cur->GetEntryData(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,10 +370,10 @@ namespace
|
||||||
|
|
||||||
std::vector<EbuSubtitle> convert_subtitles(AssFile ©, EbuExportSettings const& export_settings)
|
std::vector<EbuSubtitle> convert_subtitles(AssFile ©, EbuExportSettings const& export_settings)
|
||||||
{
|
{
|
||||||
SubtitleFormat::StripComments(copy.Line);
|
SubtitleFormat::StripComments(copy);
|
||||||
copy.Sort();
|
copy.Sort();
|
||||||
SubtitleFormat::RecombineOverlaps(copy.Line);
|
SubtitleFormat::RecombineOverlaps(copy);
|
||||||
SubtitleFormat::MergeIdentical(copy.Line);
|
SubtitleFormat::MergeIdentical(copy);
|
||||||
|
|
||||||
int line_wrap_type = copy.GetScriptInfoAsInt("WrapStyle");
|
int line_wrap_type = copy.GetScriptInfoAsInt("WrapStyle");
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ namespace
|
||||||
// convert to intermediate format
|
// convert to intermediate format
|
||||||
for (entryIter orgline = copy.Line.begin(); orgline != copy.Line.end(); ++orgline)
|
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;
|
if (!line) continue;
|
||||||
|
|
||||||
// add a new subtitle and work on it
|
// add a new subtitle and work on it
|
||||||
|
|
|
@ -62,11 +62,11 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, wxString const& filenam
|
||||||
// Convert to encore
|
// Convert to encore
|
||||||
AssFile copy(*src);
|
AssFile copy(*src);
|
||||||
copy.Sort();
|
copy.Sort();
|
||||||
StripComments(copy.Line);
|
StripComments(copy);
|
||||||
RecombineOverlaps(copy.Line);
|
RecombineOverlaps(copy);
|
||||||
MergeIdentical(copy.Line);
|
MergeIdentical(copy);
|
||||||
StripTags(copy.Line);
|
StripTags(copy);
|
||||||
ConvertNewlines(copy.Line, "\r\n");
|
ConvertNewlines(copy, "\r\n");
|
||||||
|
|
||||||
|
|
||||||
// Encode wants ; for NTSC and : for PAL
|
// Encode wants ; for NTSC and : for PAL
|
||||||
|
@ -77,8 +77,8 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, wxString const& filenam
|
||||||
// Write lines
|
// Write lines
|
||||||
int i = 0;
|
int i = 0;
|
||||||
TextFileWriter file(filename, "UTF-8");
|
TextFileWriter file(filename, "UTF-8");
|
||||||
for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur)) {
|
||||||
++i;
|
++i;
|
||||||
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.ToSMPTE(current->Start), ft.ToSMPTE(current->End), current->Text));
|
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.ToSMPTE(current->Start), ft.ToSMPTE(current->End), current->Text));
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ void MicroDVDSubtitleFormat::ReadFile(AssFile *target, wxString const& filename,
|
||||||
diag->Start = fps.TimeAtFrame(f1, agi::vfr::START);
|
diag->Start = fps.TimeAtFrame(f1, agi::vfr::START);
|
||||||
diag->End = fps.TimeAtFrame(f2, agi::vfr::END);
|
diag->End = fps.TimeAtFrame(f2, agi::vfr::END);
|
||||||
diag->Text = text;
|
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);
|
AssFile copy(*src);
|
||||||
copy.Sort();
|
copy.Sort();
|
||||||
StripComments(copy.Line);
|
StripComments(copy);
|
||||||
RecombineOverlaps(copy.Line);
|
RecombineOverlaps(copy);
|
||||||
MergeIdentical(copy.Line);
|
MergeIdentical(copy);
|
||||||
StripTags(copy.Line);
|
StripTags(copy);
|
||||||
ConvertNewlines(copy.Line, "|");
|
ConvertNewlines(copy, "|");
|
||||||
|
|
||||||
TextFileWriter file(filename, encoding);
|
TextFileWriter file(filename, encoding);
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ void MicroDVDSubtitleFormat::WriteFile(const AssFile *src, wxString const& filen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write lines
|
// Write lines
|
||||||
for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur)) {
|
||||||
int start = fps.FrameAtTime(current->Start, agi::vfr::START);
|
int start = fps.FrameAtTime(current->Start, agi::vfr::START);
|
||||||
int end = fps.FrameAtTime(current->End, agi::vfr::END);
|
int end = fps.FrameAtTime(current->End, agi::vfr::END);
|
||||||
|
|
||||||
|
|
|
@ -431,7 +431,7 @@ found_timestamps:
|
||||||
line->Start = ReadSRTTime(timestamp_regex.GetMatch(text_line, 1));
|
line->Start = ReadSRTTime(timestamp_regex.GetMatch(text_line, 1));
|
||||||
line->End = ReadSRTTime(timestamp_regex.GetMatch(text_line, 2));
|
line->End = ReadSRTTime(timestamp_regex.GetMatch(text_line, 2));
|
||||||
// store pointer to subtitle, we'll continue working on it
|
// 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
|
// next we're reading the text
|
||||||
state = 3;
|
state = 3;
|
||||||
break;
|
break;
|
||||||
|
@ -500,19 +500,19 @@ void SRTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename,
|
||||||
// Convert to SRT
|
// Convert to SRT
|
||||||
AssFile copy(*src);
|
AssFile copy(*src);
|
||||||
copy.Sort();
|
copy.Sort();
|
||||||
StripComments(copy.Line);
|
StripComments(copy);
|
||||||
RecombineOverlaps(copy.Line);
|
RecombineOverlaps(copy);
|
||||||
MergeIdentical(copy.Line);
|
MergeIdentical(copy);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ConvertNewlines(copy.Line, "\r\n", false);
|
ConvertNewlines(copy, "\r\n", false);
|
||||||
#else
|
#else
|
||||||
ConvertNewlines(copy.Line, "\n", false);
|
ConvertNewlines(copy, "\n", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Write lines
|
// Write lines
|
||||||
int i=1;
|
int i=1;
|
||||||
for (LineList::const_iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur)) {
|
||||||
file.WriteLineToFile(wxString::Format("%d", i++));
|
file.WriteLineToFile(wxString::Format("%d", i++));
|
||||||
file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End));
|
file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End));
|
||||||
file.WriteLineToFile(ConvertTags(current));
|
file.WriteLineToFile(ConvertTags(current));
|
||||||
|
@ -525,18 +525,18 @@ bool SRTSubtitleFormat::CanSave(const AssFile *file) const {
|
||||||
wxString supported_tags[] = { "\\b", "\\i", "\\s", "\\u" };
|
wxString supported_tags[] = { "\\b", "\\i", "\\s", "\\u" };
|
||||||
|
|
||||||
AssStyle defstyle;
|
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
|
// 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())
|
if (curstyle->GetEntryData() != defstyle.GetEntryData())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for attachments, if any is found, 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
|
// 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();
|
std::vector<AssDialogueBlock*> blocks = curdiag->ParseTags();
|
||||||
for (size_t i = 0; i < blocks.size(); ++i) {
|
for (size_t i = 0; i < blocks.size(); ++i) {
|
||||||
AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(blocks[i]);
|
AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride*>(blocks[i]);
|
||||||
|
@ -557,7 +557,7 @@ bool SRTSubtitleFormat::CanSave(const AssFile *file) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const {
|
wxString SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
|
||||||
wxString final;
|
wxString final;
|
||||||
std::map<char, bool> tag_states;
|
std::map<char, bool> tag_states;
|
||||||
tag_states['i'] = false;
|
tag_states['i'] = false;
|
||||||
|
@ -565,10 +565,10 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const {
|
||||||
tag_states['u'] = false;
|
tag_states['u'] = false;
|
||||||
tag_states['s'] = false;
|
tag_states['s'] = false;
|
||||||
|
|
||||||
diag->ParseAssTags();
|
std::vector<AssDialogueBlock *> blocks = diag->ParseTags();
|
||||||
|
|
||||||
for (size_t i = 0; i < diag->Blocks.size(); ++i) {
|
for (size_t i = 0; i < blocks.size(); ++i) {
|
||||||
if (AssDialogueBlockOverride* block = dynamic_cast<AssDialogueBlockOverride*>(diag->Blocks[i])) {
|
if (AssDialogueBlockOverride* block = dynamic_cast<AssDialogueBlockOverride*>(blocks[i])) {
|
||||||
// Iterate through overrides
|
// Iterate through overrides
|
||||||
for (size_t j = 0; j < block->Tags.size(); j++) {
|
for (size_t j = 0; j < block->Tags.size(); j++) {
|
||||||
AssOverrideTag *tag = block->Tags[j];
|
AssOverrideTag *tag = block->Tags[j];
|
||||||
|
@ -586,7 +586,7 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Plain text
|
// Plain text
|
||||||
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(diag->Blocks[i])) {
|
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(blocks[i])) {
|
||||||
final += plain->GetText();
|
final += plain->GetText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,7 @@ wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) const {
|
||||||
final += wxString::Format("</%c>", it->first);
|
final += wxString::Format("</%c>", it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
diag->ClearBlocks();
|
delete_clear(blocks);
|
||||||
|
|
||||||
return final;
|
return final;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class AssDialogue;
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class SRTSubtitleFormat : public SubtitleFormat {
|
class SRTSubtitleFormat : public SubtitleFormat {
|
||||||
wxString ConvertTags(AssDialogue *diag) const;
|
wxString ConvertTags(const AssDialogue *diag) const;
|
||||||
public:
|
public:
|
||||||
SRTSubtitleFormat();
|
SRTSubtitleFormat();
|
||||||
wxArrayString GetReadWildcards() const;
|
wxArrayString GetReadWildcards() const;
|
||||||
|
|
|
@ -68,15 +68,15 @@ void TranStationSubtitleFormat::WriteFile(const AssFile *src, wxString const& fi
|
||||||
// Convert to TranStation
|
// Convert to TranStation
|
||||||
AssFile copy(*src);
|
AssFile copy(*src);
|
||||||
copy.Sort();
|
copy.Sort();
|
||||||
StripComments(copy.Line);
|
StripComments(copy);
|
||||||
RecombineOverlaps(copy.Line);
|
RecombineOverlaps(copy);
|
||||||
MergeIdentical(copy.Line);
|
MergeIdentical(copy);
|
||||||
|
|
||||||
SmpteFormatter ft(fps);
|
SmpteFormatter ft(fps);
|
||||||
TextFileWriter file(filename, encoding);
|
TextFileWriter file(filename, encoding);
|
||||||
AssDialogue *prev = 0;
|
AssDialogue *prev = 0;
|
||||||
for (std::list<AssEntry*>::iterator it = copy.Line.begin(); it != copy.Line.end(); ++it) {
|
for (entryIter it = copy.Line.begin(); it != copy.Line.end(); ++it) {
|
||||||
AssDialogue *cur = dynamic_cast<AssDialogue*>(*it);
|
AssDialogue *cur = dynamic_cast<AssDialogue*>(&*it);
|
||||||
|
|
||||||
if (prev && cur) {
|
if (prev && cur) {
|
||||||
file.WriteLineToFile(ConvertLine(©, prev, fps, ft, cur->Start));
|
file.WriteLineToFile(ConvertLine(©, prev, fps, ft, cur->Start));
|
||||||
|
|
|
@ -91,7 +91,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxS
|
||||||
if (child->GetName() == "TextSample") {
|
if (child->GetName() == "TextSample") {
|
||||||
if ((diag = ProcessLine(child, diag, version))) {
|
if ((diag = ProcessLine(child, diag, version))) {
|
||||||
lines++;
|
lines++;
|
||||||
target->Line.push_back(diag);
|
target->Line.push_back(*diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Header
|
// Header
|
||||||
|
@ -102,7 +102,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxS
|
||||||
|
|
||||||
// No lines?
|
// No lines?
|
||||||
if (lines == 0)
|
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 {
|
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);
|
WriteHeader(root);
|
||||||
|
|
||||||
// Create lines
|
// Create lines
|
||||||
AssDialogue *prev = 0;
|
const AssDialogue *prev = 0;
|
||||||
for (LineList::iterator cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
for (constEntryIter cur = copy.Line.begin(); cur != copy.Line.end(); ++cur) {
|
||||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
const AssDialogue *current = dynamic_cast<const AssDialogue*>(&*cur);
|
||||||
if (current && !current->Comment) {
|
if (current && !current->Comment) {
|
||||||
WriteLine(root, prev, current);
|
WriteLine(root, prev, current);
|
||||||
prev = current;
|
prev = current;
|
||||||
|
@ -240,7 +240,7 @@ void TTXTSubtitleFormat::WriteHeader(wxXmlNode *root) const {
|
||||||
root->AddChild(node);
|
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 it doesn't start at the end of previous, add blank
|
||||||
if (prev && prev->End != line->Start) {
|
if (prev && prev->End != line->Start) {
|
||||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample");
|
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 {
|
void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const {
|
||||||
file.Sort();
|
file.Sort();
|
||||||
StripComments(file.Line);
|
StripComments(file);
|
||||||
RecombineOverlaps(file.Line);
|
RecombineOverlaps(file);
|
||||||
MergeIdentical(file.Line);
|
MergeIdentical(file);
|
||||||
StripTags(file.Line);
|
StripTags(file);
|
||||||
ConvertNewlines(file.Line, "\r\n");
|
ConvertNewlines(file, "\r\n");
|
||||||
|
|
||||||
// Find last line
|
// Find last line
|
||||||
AssTime lastTime;
|
AssTime lastTime;
|
||||||
for (LineList::reverse_iterator cur = file.Line.rbegin(); cur != file.Line.rend(); ++cur) {
|
for (EntryList::reverse_iterator cur = file.Line.rbegin(); cur != file.Line.rend(); ++cur) {
|
||||||
if (AssDialogue *prev = dynamic_cast<AssDialogue*>(*cur)) {
|
if (AssDialogue *prev = dynamic_cast<AssDialogue*>(&*cur)) {
|
||||||
lastTime = prev->End;
|
lastTime = prev->End;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -279,5 +279,5 @@ void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const {
|
||||||
AssDialogue *diag = new AssDialogue;
|
AssDialogue *diag = new AssDialogue;
|
||||||
diag->Start = lastTime;
|
diag->Start = lastTime;
|
||||||
diag->End = lastTime+OPT_GET("Timing/Default Duration")->GetInt();
|
diag->End = lastTime+OPT_GET("Timing/Default Duration")->GetInt();
|
||||||
file.Line.push_back(diag);
|
file.Line.push_back(*diag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ class TTXTSubtitleFormat : public SubtitleFormat {
|
||||||
void ProcessHeader(wxXmlNode *node) const;
|
void ProcessHeader(wxXmlNode *node) const;
|
||||||
|
|
||||||
void WriteHeader(wxXmlNode *root) 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;
|
void ConvertToTTXT(AssFile &file) const;
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "text_file_reader.h"
|
#include "text_file_reader.h"
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
TXTSubtitleFormat::TXTSubtitleFormat()
|
TXTSubtitleFormat::TXTSubtitleFormat()
|
||||||
: SubtitleFormat("Plain-Text")
|
: SubtitleFormat("Plain-Text")
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,7 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
|
||||||
line->End = 0;
|
line->End = 0;
|
||||||
|
|
||||||
// Adds line
|
// 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;
|
size_t num_actor_names = 0, num_dialogue_lines = 0;
|
||||||
|
|
||||||
// Detect number of lines with Actor field filled out
|
// Detect number of lines with Actor field filled out
|
||||||
for (LineList::const_iterator l = src->Line.begin(); l != src->Line.end(); ++l) {
|
for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) {
|
||||||
AssDialogue *dia = dynamic_cast<AssDialogue*>(*l);
|
const AssDialogue *dia = dynamic_cast<const AssDialogue*>(&*l);
|
||||||
if (dia && !dia->Comment) {
|
if (dia && !dia->Comment) {
|
||||||
num_dialogue_lines++;
|
num_dialogue_lines++;
|
||||||
if (!dia->Actor.empty())
|
if (!dia->Actor.empty())
|
||||||
|
@ -146,43 +146,34 @@ void TXTSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename,
|
||||||
file.WriteLineToFile(wxString("# Exported by Aegisub ") + GetAegisubShortVersionString());
|
file.WriteLineToFile(wxString("# Exported by Aegisub ") + GetAegisubShortVersionString());
|
||||||
|
|
||||||
// Write the file
|
// Write the file
|
||||||
for (LineList::const_iterator l = src->Line.begin(); l != src->Line.end(); ++l) {
|
for (constEntryIter l = src->Line.begin(); l != src->Line.end(); ++l) {
|
||||||
AssDialogue *dia = dynamic_cast<AssDialogue*>(*l);
|
const AssDialogue *dia = dynamic_cast<const AssDialogue*>(&*l);
|
||||||
|
if (!dia) continue;
|
||||||
|
|
||||||
if (dia) {
|
wxString out_line;
|
||||||
wxString out_line;
|
|
||||||
|
|
||||||
if (dia->Comment) {
|
if (dia->Comment)
|
||||||
out_line = "# ";
|
out_line = "# ";
|
||||||
}
|
|
||||||
|
|
||||||
if (write_actors) {
|
if (write_actors)
|
||||||
out_line += dia->Actor + ": ";
|
out_line += dia->Actor + ": ";
|
||||||
}
|
|
||||||
|
|
||||||
wxString out_text;
|
wxString out_text;
|
||||||
if (strip_formatting) {
|
if (strip_formatting) {
|
||||||
dia->ParseAssTags();
|
std::vector<AssDialogueBlock*> blocks = dia->ParseTags();
|
||||||
for (std::vector<AssDialogueBlock*>::iterator block = dia->Blocks.begin(); block != dia->Blocks.end(); ++block) {
|
for (std::vector<AssDialogueBlock*>::iterator block = blocks.begin(); block != blocks.end(); ++block) {
|
||||||
if ((*block)->GetType() == BLOCK_PLAIN) {
|
if ((*block)->GetType() == BLOCK_PLAIN) {
|
||||||
out_text += (*block)->GetText();
|
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 {
|
else {
|
||||||
// Not a dialogue line
|
out_text = dia->Text;
|
||||||
// TODO: should any non-dia lines cause blank lines in output?
|
|
||||||
//file.WriteLineToFile("");
|
|
||||||
}
|
}
|
||||||
|
out_line += out_text;
|
||||||
|
|
||||||
|
if (!out_text.empty())
|
||||||
|
file.WriteLineToFile(out_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,10 @@
|
||||||
#include "threaded_frame_source.h"
|
#include "threaded_frame_source.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <iterator>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/indirected.hpp>
|
||||||
|
#include <boost/range/algorithm_ext.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
|
@ -49,11 +51,11 @@
|
||||||
#include "video_provider_manager.h"
|
#include "video_provider_manager.h"
|
||||||
|
|
||||||
// Test if a line is a dialogue line which is not visible at the given time
|
// 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;
|
double time;
|
||||||
invisible_line(double time) : time(time * 1000.) { }
|
invisible_line(double time) : time(time * 1000.) { }
|
||||||
bool operator()(const AssEntry *entry) const {
|
bool operator()(AssEntry const& entry) const {
|
||||||
const AssDialogue *diag = dynamic_cast<const AssDialogue*>(entry);
|
const AssDialogue *diag = dynamic_cast<const AssDialogue*>(&entry);
|
||||||
return diag && (diag->Start > time || diag->End <= time);
|
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
|
// Copying a nontrivially sized AssFile is fairly slow, so
|
||||||
// instead muck around with its innards to just temporarily
|
// instead muck around with its innards to just temporarily
|
||||||
// remove the non-visible lines without deleting them
|
// remove the non-visible lines without deleting them
|
||||||
std::list<AssEntry*> visible;
|
std::deque<AssEntry*> full;
|
||||||
std::remove_copy_if(subs->Line.begin(), subs->Line.end(),
|
for (entryIter it = subs->Line.begin(); it != subs->Line.end(); ++it)
|
||||||
std::back_inserter(visible),
|
full.push_back(&*it);
|
||||||
invisible_line(time));
|
subs->Line.remove_if(invisible_line(time));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::swap(subs->Line, visible);
|
|
||||||
provider->LoadSubtitles(subs.get());
|
provider->LoadSubtitles(subs.get());
|
||||||
std::swap(subs->Line, visible);
|
|
||||||
|
subs->Line.clear();
|
||||||
|
boost::push_back(subs->Line, full | boost::adaptors::indirected);
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
std::swap(subs->Line, visible);
|
subs->Line.clear();
|
||||||
|
boost::push_back(subs->Line, full | boost::adaptors::indirected);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,7 @@ void SetClipboard(wxBitmap const& new_value);
|
||||||
|
|
||||||
/// Polymorphic delete functor
|
/// Polymorphic delete functor
|
||||||
struct delete_ptr {
|
struct delete_ptr {
|
||||||
template<class T>
|
template<class T> void operator()(T* ptr) const {
|
||||||
void operator()(T* ptr) const {
|
|
||||||
delete ptr;
|
delete ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -158,7 +157,7 @@ template<class Container>
|
||||||
class BackgroundDeleter : public wxThread {
|
class BackgroundDeleter : public wxThread {
|
||||||
Container cont;
|
Container cont;
|
||||||
wxThread::ExitCode Entry() {
|
wxThread::ExitCode Entry() {
|
||||||
delete_clear(cont);
|
cont.clear_and_dispose(delete_ptr());
|
||||||
return (wxThread::ExitCode)0;
|
return (wxThread::ExitCode)0;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
@ -186,7 +185,12 @@ void background_delete_clear(T& container) {
|
||||||
template<class Out>
|
template<class Out>
|
||||||
struct cast {
|
struct cast {
|
||||||
template<class In>
|
template<class In>
|
||||||
Out operator()(In in) const {
|
Out operator()(In *in) const {
|
||||||
return dynamic_cast<Out>(in);
|
return dynamic_cast<Out>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class In>
|
||||||
|
Out operator()(In &in) const {
|
||||||
|
return dynamic_cast<Out>(&in);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -116,7 +116,7 @@ void VisualToolDrag::OnFileChanged() {
|
||||||
active_feature = features.end();
|
active_feature = features.end();
|
||||||
|
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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))
|
if (diag && IsDisplayed(diag))
|
||||||
MakeFeatures(diag);
|
MakeFeatures(diag);
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ void VisualToolDrag::OnFrameChanged() {
|
||||||
feature_iterator end = features.end();
|
feature_iterator end = features.end();
|
||||||
|
|
||||||
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {
|
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) continue;
|
||||||
|
|
||||||
if (IsDisplayed(diag)) {
|
if (IsDisplayed(diag)) {
|
||||||
|
|
Loading…
Reference in a new issue