Rework how sorting works and add sorting by style

Rather than going through a ton of work to ensure that every AssEvent
has a sensible start time that happens to leave it in the right place
after sorting, simply sort only consecutive blocks of AssDialogues and
leave everything else untouched. Note that this results in different
behavior when there are multiple [Events] sections in a file -- rather
than moving lines between sections and keeping the number of lines per
section constant, each section keeps the lines it had.

As it's now easy to do, also add sorting by style name and end time.

Closes #614.

Originally committed to SVN as r4307.
This commit is contained in:
Thomas Goyne 2010-05-19 00:44:44 +00:00
parent a573b0897b
commit 2124a1dbd3
24 changed files with 220 additions and 529 deletions

View file

@ -32,8 +32,6 @@
/// @file ass_dialogue.cpp
/// @brief Class for dialogue lines in subtitles
/// @ingroup subs_storage
///
////////////
// Includes
@ -51,38 +49,40 @@
#include "utils.h"
#include "vfr.h"
/// @brief Constructs AssDialogue AssDialogue //////////////////////
///
AssDialogue::AssDialogue() {
group = _T("[Events]");
/// @brief Constructs AssDialogue
AssDialogue::AssDialogue()
: Comment(false)
, Layer(0)
, Start(0)
, End(5000)
, Style(L"Default")
, Actor(L"")
, Effect(L"")
, Text(L"")
{
group = L"[Events]";
Valid = true;
SetStartMS(0);
SetEndMS(5000);
Layer = 0;
for (int i=0;i<4;i++) Margin[i] = 0;
Text = _T("");
Style = _T("Default");
Actor = _T("");
Effect = _T("");
Comment = false;
UpdateData();
}
/// @brief DOCME
/// @param _data
/// @param version
///
AssDialogue::AssDialogue(wxString _data,int version) {
// Set group
group = _T("[Events]");
AssDialogue::AssDialogue(wxString _data,int version)
: Comment(false)
, Layer(0)
, Start(0)
, End(5000)
, Style(L"Default")
, Actor(L"")
, Effect(L"")
, Text(L"")
{
group = L"[Events]";
Valid = false;
// Try parsing in different ways
int count = 0;
Valid = false;
while (!Valid && count < 3) {
Valid = Parse(_data,version);
count++;
@ -95,30 +95,20 @@ AssDialogue::AssDialogue(wxString _data,int version) {
throw _T("Failed parsing line.");
}
// update
UpdateData();
}
/// @brief Destructor
///
AssDialogue::~AssDialogue () {
Clear();
}
/// @brief Clear
///
void AssDialogue::Clear () {
ClearBlocks();
}
/// @brief Clear blocks
///
void AssDialogue::ClearBlocks() {
using std::vector;
for (vector<AssDialogueBlock*>::iterator cur=Blocks.begin();cur!=Blocks.end();cur++) {
@ -127,13 +117,10 @@ void AssDialogue::ClearBlocks() {
Blocks.clear();
}
/// @brief Parse ASS Data
/// @param rawData
/// @param version
/// @return
///
bool AssDialogue::Parse(wxString rawData, int version) {
size_t pos = 0;
wxString temp;
@ -168,7 +155,6 @@ bool AssDialogue::Parse(wxString rawData, int version) {
// Get start time
if (!tkn.HasMoreTokens()) return false;
Start.ParseASS(tkn.GetNextToken());
FixStartMS();
// Get end time
if (!tkn.HasMoreTokens()) return false;
@ -227,11 +213,8 @@ bool AssDialogue::Parse(wxString rawData, int version) {
return true;
}
/// @brief Make data
/// @return
///
wxString AssDialogue::MakeData() {
// Prepare
static wxString final = _T("");
@ -270,35 +253,23 @@ wxString AssDialogue::MakeData() {
return final;
}
/// @brief Update AssDialogue's data line
///
void AssDialogue::UpdateData () {
}
/// @brief Get entry data
/// @return
///
const wxString AssDialogue::GetEntryData() {
return MakeData();
}
/// @brief Set entry data
/// @param newData
///
void AssDialogue::SetEntryData(wxString newData) {
}
/// @brief Get SSA version of Dialogue
/// @return
///
wxString AssDialogue::GetSSAText () {
// Prepare
wxString work = _T("");
@ -331,10 +302,7 @@ wxString AssDialogue::GetSSAText () {
return work;
}
/// @brief Yea, I convert to ASS tags, then parse that. So sue me. -------------- Parse SRT tags
///
void AssDialogue::ParseSRTTags () {
// Search and replace
size_t total = 0;
@ -470,10 +438,7 @@ void AssDialogue::ParseSRTTags () {
UpdateData();
}
/// @brief Parse ASS tags
///
void AssDialogue::ParseASSTags () {
// Clear blocks
ClearBlocks();
@ -567,20 +532,14 @@ void AssDialogue::ParseASSTags () {
}
}
/// @brief Strip tags
///
void AssDialogue::StripTags () {
static wxRegEx reg(_T("\\{[^\\{]*\\}"),wxRE_ADVANCED);
reg.Replace(&Text,_T(""));
}
/// @brief Strip a specific tag
/// @param tagName
///
void AssDialogue::StripTag (wxString tagName) {
// Parse
using std::list;
@ -609,10 +568,7 @@ void AssDialogue::StripTag (wxString tagName) {
UpdateData();
}
/// @brief TODO: Improve this code ------------------- Convert tags to SRT
///
void AssDialogue::ConvertTagsToSRT () {
// Setup
using std::list;
@ -712,10 +668,7 @@ void AssDialogue::ConvertTagsToSRT () {
ClearBlocks();
}
/// @brief Updates text from tags
///
void AssDialogue::UpdateText () {
using std::vector;
Text = _T("");
@ -729,12 +682,9 @@ void AssDialogue::UpdateText () {
}
}
/// @brief Sets margin from a string
/// @param origvalue
/// @param which
///
void AssDialogue::SetMarginString(const wxString origvalue,int which) {
// Make it numeric
wxString strvalue = origvalue;
@ -760,13 +710,10 @@ void AssDialogue::SetMarginString(const wxString origvalue,int which) {
Margin[which] = value;
}
/// @brief Gets string for margin
/// @param which
/// @param pad
/// @return
///
wxString AssDialogue::GetMarginString(int which,bool pad) {
if (which < 0 || which >= 4) throw Aegisub::InvalidMarginIdError();
int value = Margin[which];
@ -774,8 +721,6 @@ wxString AssDialogue::GetMarginString(int which,bool pad) {
else return wxString::Format(_T("%i"),value);
}
void AssDialogue::ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData) {
// Apply for all override blocks
AssDialogueBlockOverride *curBlock;
@ -789,12 +734,9 @@ void AssDialogue::ProcessParameters(AssDialogueBlockOverride::ProcessParametersC
//ClearBlocks();
}
/// @brief Checks if two lines collide
/// @param target
/// @return
///
bool AssDialogue::CollidesWith(AssDialogue *target) {
if (!target) return false;
int a = Start.GetMS();
@ -804,11 +746,8 @@ bool AssDialogue::CollidesWith(AssDialogue *target) {
return ((a < c) ? (c < b) : (a < d));
}
/// @brief Return just the text without any overrides
/// @return
///
wxString AssDialogue::GetStrippedText() const {
wxString justtext = wxString(_T(""));
bool inCode = false;
@ -823,7 +762,6 @@ wxString AssDialogue::GetStrippedText() const {
/// @brief Clone
/// @return
///
AssEntry *AssDialogue::Clone() const {
// Create clone
AssDialogue *final = new AssDialogue();
@ -836,37 +774,26 @@ AssEntry *AssDialogue::Clone() const {
final->Effect = Effect;
final->Layer = Layer;
for (int i=0;i<4;i++) final->Margin[i] = Margin[i];
final->SetStartMS(GetStartMS());
final->SetEndMS(GetEndMS());
final->Start = Start;
final->End = End;
final->Style = Style;
final->Text = Text;
//final->SetEntryData(GetEntryData());
// Return
return final;
}
/// @brief Constructor AssDialogueBlock //////////////////////
///
/// @brief Constructor AssDialogueBlock
AssDialogueBlock::AssDialogueBlock () {
}
/// @brief Destructor
/// @return
///
AssDialogueBlock::~AssDialogueBlock () {
}
/// @brief If it isn't a plain block, returns NULL ---------------------- Returns as a plain block
/// @param base
/// @return
///
AssDialogueBlockPlain *AssDialogueBlock::GetAsPlain(AssDialogueBlock *base) {
if (!base) return NULL;
if (base->GetType() == BLOCK_PLAIN) {
@ -875,12 +802,9 @@ AssDialogueBlockPlain *AssDialogueBlock::GetAsPlain(AssDialogueBlock *base) {
return NULL;
}
/// @brief If it isn't an override block, returns NULL ---------------------------- Returns as an override block
/// @param base
/// @return
///
AssDialogueBlockOverride *AssDialogueBlock::GetAsOverride(AssDialogueBlock *base) {
if (!base) return NULL;
if (base->GetType() == BLOCK_OVERRIDE) {
@ -889,12 +813,9 @@ AssDialogueBlockOverride *AssDialogueBlock::GetAsOverride(AssDialogueBlock *base
return NULL;
}
/// @brief If it isn't an drawing block, returns NULL ---------------------------- Returns as a drawing block
/// @param base
/// @return
///
AssDialogueBlockDrawing *AssDialogueBlock::GetAsDrawing(AssDialogueBlock *base) {
if (!base) return NULL;
if (base->GetType() == BLOCK_DRAWING) {
@ -903,28 +824,19 @@ AssDialogueBlockDrawing *AssDialogueBlock::GetAsDrawing(AssDialogueBlock *base)
return NULL;
}
/// @brief Constructor AssDialogueBlockPlain //////////////////////
///
AssDialogueBlockPlain::AssDialogueBlockPlain () {
}
/// @brief Constructor AssDialogueBlockDrawing //////////////////////
///
AssDialogueBlockDrawing::AssDialogueBlockDrawing () {
}
/// @brief Multiply coordinates
/// @param mx
/// @param my
/// @param x
/// @param y
///
void AssDialogueBlockDrawing::TransformCoords(int mx,int my,double x,double y) {
// HACK: Implement a proper parser ffs!!
wxStringTokenizer tkn(GetText(),_T(" "),wxTOKEN_DEFAULT);
@ -963,7 +875,3 @@ void AssDialogueBlockDrawing::TransformCoords(int mx,int my,double x,double y) {
text = final;
}

View file

@ -202,36 +202,28 @@ private:
public:
/// DOCME
std::vector<AssDialogueBlock*> Blocks; // Contains information about each block of text
/// Contains information about each block of text
std::vector<AssDialogueBlock*> Blocks;
/// DOCME
bool Comment; // Is this a comment line?
/// DOCME
int Layer; // Layer number
/// DOCME
int Margin[4]; // Margins: 0 = Left, 1 = Right, 2 = Top (Vertical), 3 = Bottom
/// DOCME
AssTime Start; // Starting time
/// DOCME
AssTime End; // Ending time
/// DOCME
wxString Style; // Style name
/// DOCME
wxString Actor; // Actor name
/// DOCME
wxString Effect; // Effect name
/// DOCME
wxString Text; // Raw text data
/// Is this a comment line?
bool Comment;
/// Layer number
int Layer;
/// Margins: 0 = Left, 1 = Right, 2 = Top (Vertical), 3 = Bottom
int Margin[4];
/// Starting time
AssTime Start;
/// Ending time
AssTime End;
/// Style name
wxString Style;
/// Actor name
wxString Actor;
/// Effect name
wxString Effect;
/// Raw text data
wxString Text;
/// @brief DOCME
@ -260,30 +252,6 @@ public:
void Clear(); // Wipes all data
/// @brief DOCME
/// @return
///
virtual int GetStartMS() const { return Start.GetMS(); }
/// @brief DOCME
/// @return
///
virtual int GetEndMS() const { return End.GetMS(); }
/// @brief DOCME
/// @param newStart
///
virtual void SetStartMS(const int newStart) { AssEntry::SetStartMS(newStart); Start.SetMS(newStart); }
/// @brief DOCME
/// @param newEnd
///
virtual void SetEndMS(const int newEnd) { End.SetMS(newEnd); }
/// @brief DOCME
///
void FixStartMS() { AssEntry::SetStartMS(Start.GetMS()); } // Update StartMS in AssEntry from the Start value here
void SetMarginString(const wxString value,int which); // Set string to a margin value (0 = left, 1 = right, 2 = vertical/top, 3 = bottom)
wxString GetMarginString(int which,bool pad=true); // Returns the string of a margin value (0 = left, 1 = right, 2 = vertical/top, 3 = bottom)
wxString GetSSAText();

View file

@ -45,13 +45,11 @@
#include "ass_style.h"
/// @brief Constructs AssEntry AssEntry //////////////////////
///
/// @brief Constructs AssEntry
AssEntry::AssEntry() {
Valid = true;
}
/// @brief DOCME
/// @param _data
///
@ -60,26 +58,11 @@ AssEntry::AssEntry(wxString _data) {
Valid = true;
}
/// @brief Destructor for AssEntry
///
AssEntry::~AssEntry() {
}
/// @brief Comparison for STL Sort
/// @param t1
/// @param t2
/// @return
///
bool operator < (const AssEntry &t1, const AssEntry &t2) {
return (t1.GetStartMS() < t2.GetStartMS());
}
/// @brief Returns an entry as dialogue if possible, else, returns NULL
/// @param base
/// @return
@ -92,8 +75,6 @@ AssDialogue *AssEntry::GetAsDialogue(AssEntry *base) {
return NULL;
}
/// @brief Returns an entry as style if possible, else, returns NULL
/// @param base
/// @return
@ -106,8 +87,6 @@ AssStyle *AssEntry::GetAsStyle(AssEntry *base) {
return NULL;
}
/// @brief Returns an entry as attachment if possible, else, returns NULL
/// @param base
/// @return
@ -120,8 +99,6 @@ AssAttachment *AssEntry::GetAsAttachment(AssEntry *base) {
return NULL;
}
/// @brief Get SSA conversion
/// @return
///
@ -136,8 +113,6 @@ wxString AssEntry::GetSSAText() {
return GetEntryData();
}
/// @brief Clone
///
AssEntry *AssEntry::Clone() const {
@ -147,11 +122,8 @@ AssEntry *AssEntry::Clone() const {
// Copy data
final->data = data;
final->group = group;
final->StartMS = StartMS;
final->Valid = Valid;
// Return
return final;
}

View file

@ -109,9 +109,6 @@ private:
/// DOCME
wxString data; // Raw data, exactly the same line that appears on the .ass (note that this will be in ass even if source wasn't)
/// DOCME
int StartMS; // This is only stored for sorting issues, in order to keep non-dialogue lines aligned
public:
/// DOCME
@ -126,29 +123,6 @@ public:
virtual AssEntry *Clone() const;
/// @brief DOCME
/// @return
///
virtual int GetStartMS() const { return StartMS; }
/// @brief DOCME
/// @return
///
virtual int GetEndMS() const { return StartMS; }
/// @brief DOCME
/// @param newStart
///
virtual void SetStartMS(const int newStart) { StartMS = newStart; }
/// @brief DOCME
/// @param newEnd
/// @return
///
virtual void SetEndMS(const int newEnd) { /* do nothing */ (void)newEnd; }
/// @brief DOCME
/// @return
///
@ -169,8 +143,3 @@ public:
static AssStyle *GetAsStyle(AssEntry *base); // Returns an entry base as a style if it is valid, null otherwise
static AssAttachment *GetAsAttachment(AssEntry *base);// Returns an entry base as an attachment if it is valid, null otherwise
};
// This operator is for sorting
bool operator < (const AssEntry &t1, const AssEntry &t2);

View file

@ -32,11 +32,7 @@
/// @file ass_file.cpp
/// @brief Overall storage of subtitle files, undo management and more
/// @ingroup subs_storage
///
////////////
// Includes
#include "config.h"
#ifndef AGI_PRE
@ -61,28 +57,21 @@
#include "version.h"
#include "vfr.h"
/// @brief AssFile constructor AssFile //////////////////////
///
/// @brief AssFile constructor
AssFile::AssFile () {
AssOverrideTagProto::LoadProtos();
Clear();
}
/// @brief AssFile destructor
///
AssFile::~AssFile() {
Clear();
}
/// @brief Load generic subs
/// @param file
/// @param charset
/// @param addToRecent
///
void AssFile::Load (const wxString _filename,const wxString charset,bool addToRecent) {
bool ok = true;
@ -153,14 +142,11 @@ void AssFile::Load (const wxString _filename,const wxString charset,bool addToRe
if (addToRecent) AddToRecent(_filename);
}
/// @brief Save a file to Hard Disk
/// @param _filename
/// @param setfilename
/// @param addToRecent
/// @param encoding
///
void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) {
// Finds last dot
int i = 0;
@ -192,12 +178,9 @@ void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wx
}
}
/// @brief Saves a file to a ram vector
/// @param dst
/// @param encoding
///
void AssFile::SaveMemory(std::vector<char> &dst,const wxString encoding) {
// Set encoding
wxString enc = encoding;
@ -240,22 +223,16 @@ void AssFile::SaveMemory(std::vector<char> &dst,const wxString encoding) {
}
}
/// @brief Exports file with proper transformations
/// @param _filename
///
void AssFile::Export(wxString _filename) {
AssExporter exporter(this);
exporter.AddAutoFilters();
exporter.Export(_filename,_T("UTF-8"));
}
/// @brief Can save file?
/// @return
///
bool AssFile::CanSave() {
// ASS format?
wxString ext = filename.Lower().Right(4);
@ -307,25 +284,6 @@ bool AssFile::CanSave() {
return true;
}
////////////////////////////////////
// Returns script as a single string
//wxString AssFile::GetString() {
// using std::list;
// wxString ret;
// AssEntry *entry;
// ret += 0xfeff;
// for (list<AssEntry*>::iterator cur=Line.begin();cur!=Line.end();) {
// entry = *cur;
// ret += entry->GetEntryData();
// ret += L"\n";
// cur++;
// }
// return ret;
//}
/// @brief even moving things out of order might break ASS parsing - AMZ. I strongly advice you against touching this function unless you know what you're doing; ------------------- Appends line to Ass
/// @param data
/// @param group
@ -333,8 +291,7 @@ bool AssFile::CanSave() {
/// @param version
/// @param outGroup
/// @return
///
int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxString *outGroup) {
void AssFile::AddLine (wxString data,wxString group,int &version,wxString *outGroup) {
// Group
AssEntry *entry = NULL;
wxString origGroup = group;
@ -372,10 +329,9 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
// Create attachment if needed
if (isFilename) {
attach = new AssAttachment(data.Mid(10));
attach->SetStartMS(lasttime);
attach->group = group;
keepGroup = group;
return lasttime;
return;
}
// Valid data?
@ -395,7 +351,7 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
// Not done
else {
return lasttime;
return;
}
}
}
@ -404,15 +360,12 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
if (lowGroup == _T("[events]")) {
if ((data.Left(9) == _T("Dialogue:") || data.Left(8) == _T("Comment:"))) {
AssDialogue *diag = new AssDialogue(data,version);
lasttime = diag->GetStartMS();
//diag->ParseASSTags();
entry = diag;
entry->SetStartMS(lasttime);
entry->group = group;
}
if (data.Left(7) == _T("Format:")) {
entry = new AssEntry(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"));
entry->SetStartMS(lasttime);
entry->group = group;
}
}
@ -422,12 +375,10 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
if (data.Left(6) == _T("Style:")) {
AssStyle *style = new AssStyle(data,version);
entry = style;
entry->SetStartMS(lasttime);
entry->group = group;
}
if (data.Left(7) == _T("Format:")) {
entry = new AssEntry(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"));
entry->SetStartMS(lasttime);
entry->group = group;
}
}
@ -438,7 +389,7 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
if (data.Left(1) == _T(";")) {
// Skip stupid comments added by other programs
// Of course, we'll add our own in place later... ;)
return lasttime;
return;
}
// Version
@ -460,26 +411,21 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS
// Everything
entry = new AssEntry(data);
entry->SetStartMS(lasttime);
entry->group = group;
}
// Common entry
if (entry == NULL) {
entry = new AssEntry(data);
entry->SetStartMS(lasttime);
entry->group = group;
}
// Insert the line
Line.push_back(entry);
return lasttime;
return;
}
/// @brief Clears contents of assfile
///
void AssFile::Clear () {
for (std::list<AssEntry*>::iterator cur=Line.begin();cur != Line.end();cur++) {
if (*cur) delete *cur;
@ -491,11 +437,8 @@ void AssFile::Clear () {
Modified = false;
}
/// @brief Loads default subs
/// @param defline
///
void AssFile::LoadDefault (bool defline) {
// Clear first
Clear();
@ -503,34 +446,31 @@ void AssFile::LoadDefault (bool defline) {
// Write headers
AssStyle defstyle;
int version = 1;
AddLine(_T("[Script Info]"),_T("[Script Info]"),-1,version);
AddLine(_T("Title: Default Aegisub file"),_T("[Script Info]"),-1,version);
AddLine(_T("ScriptType: v4.00+"),_T("[Script Info]"),-1,version);
AddLine(_T("WrapStyle: 0"), _T("[Script Info]"),-1,version);
AddLine(_T("PlayResX: 640"),_T("[Script Info]"),-1,version);
AddLine(_T("PlayResY: 480"),_T("[Script Info]"),-1,version);
AddLine(_T("ScaledBorderAndShadow: yes"),_T("[Script Info]"),-1,version);
AddLine(_T(""),_T("[Script Info]"),-1,version);
AddLine(_T("[V4+ Styles]"),_T("[V4+ Styles]"),-1,version);
AddLine(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"),_T("[V4+ Styles]"),-1,version);
AddLine(defstyle.GetEntryData(),_T("[V4+ Styles]"),-1,version);
AddLine(_T(""),_T("[V4+ Styles]"),-1,version);
AddLine(_T("[Events]"),_T("[Events]"),-1,version);
AddLine(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"),_T("[Events]"),-1,version);
AddLine(_T("[Script Info]"),_T("[Script Info]"),version);
AddLine(_T("Title: Default Aegisub file"),_T("[Script Info]"),version);
AddLine(_T("ScriptType: v4.00+"),_T("[Script Info]"),version);
AddLine(_T("WrapStyle: 0"), _T("[Script Info]"),version);
AddLine(_T("PlayResX: 640"),_T("[Script Info]"),version);
AddLine(_T("PlayResY: 480"),_T("[Script Info]"),version);
AddLine(_T("ScaledBorderAndShadow: yes"),_T("[Script Info]"),version);
AddLine(_T(""),_T("[Script Info]"),version);
AddLine(_T("[V4+ Styles]"),_T("[V4+ Styles]"),version);
AddLine(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"),_T("[V4+ Styles]"),version);
AddLine(defstyle.GetEntryData(),_T("[V4+ Styles]"),version);
AddLine(_T(""),_T("[V4+ Styles]"),version);
AddLine(_T("[Events]"),_T("[Events]"),version);
AddLine(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"),_T("[Events]"),version);
if (defline) {
AssDialogue def;
AddLine(def.GetEntryData(),_T("[Events]"),0,version);
AddLine(def.GetEntryData(),_T("[Events]"),version);
}
loaded = true;
}
/// @brief Copy constructor
/// @param from
///
AssFile::AssFile (AssFile &from) {
using std::list;
@ -545,11 +485,8 @@ AssFile::AssFile (AssFile &from) {
}
}
/// @brief Insert a new style
/// @param style
///
void AssFile::InsertStyle (AssStyle *style) {
// Variables
using std::list;
@ -565,7 +502,6 @@ void AssFile::InsertStyle (AssStyle *style) {
if (curEntry->GetType() == ENTRY_STYLE || (lastGroup == _T("[V4+ Styles]") && curEntry->GetEntryData().substr(0,7) == _T("Format:"))) {
lastStyle = cur;
}
lasttime = curEntry->GetStartMS();
lastGroup = curEntry->group;
}
@ -574,24 +510,20 @@ void AssFile::InsertStyle (AssStyle *style) {
// Add space
curEntry = new AssEntry(_T(""));
curEntry->group = lastGroup;
curEntry->SetStartMS(lasttime);
Line.push_back(curEntry);
// Add header
curEntry = new AssEntry(_T("[V4+ Styles]"));
curEntry->group = _T("[V4+ Styles]");
curEntry->SetStartMS(lasttime);
Line.push_back(curEntry);
// Add format line
curEntry = new AssEntry(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"));
curEntry->group = _T("[V4+ Styles]");
curEntry->SetStartMS(lasttime);
Line.push_back(curEntry);
// Add style
style->group = _T("[V4+ Styles]");
style->SetStartMS(lasttime);
Line.push_back(style);
}
@ -599,16 +531,12 @@ void AssFile::InsertStyle (AssStyle *style) {
else {
lastStyle++;
style->group = (*lastStyle)->group;
style->SetStartMS(lasttime);
Line.insert(lastStyle,style);
}
}
/// @brief Insert attachment
/// @param attach
///
void AssFile::InsertAttachment (AssAttachment *attach) {
// Search for insertion point
std::list<AssEntry*>::iterator insPoint=Line.end(),cur;
@ -629,27 +557,21 @@ void AssFile::InsertAttachment (AssAttachment *attach) {
// Found point, insert there
if (insPoint != Line.end()) {
insPoint++;
attach->SetStartMS((*insPoint)->GetStartMS());
Line.insert(insPoint,attach);
}
// Otherwise, create the [Fonts] group and insert
else {
int version=1;
int StartMS = Line.back()->GetStartMS();
AddLine(_T(""),Line.back()->group,StartMS,version);
AddLine(attach->group,attach->group,StartMS,version);
attach->SetStartMS(StartMS);
AddLine(_T(""),Line.back()->group,version);
AddLine(attach->group,attach->group,version);
Line.push_back(attach);
AddLine(_T(""),attach->group,StartMS,version);
AddLine(_T(""),attach->group,version);
}
}
/// @brief Insert attachment from file
/// @param filename
///
void AssFile::InsertAttachment (wxString filename) {
// Get name
wxFileName fname(filename);
@ -673,12 +595,9 @@ void AssFile::InsertAttachment (wxString filename) {
InsertAttachment(newAttach);
}
/// @brief Gets script info
/// @param _key
/// @return
///
wxString AssFile::GetScriptInfo(const wxString _key) {
// Prepare
wxString key = _key;;
@ -709,12 +628,9 @@ wxString AssFile::GetScriptInfo(const wxString _key) {
return _T("");
}
/// @brief Get script info as int
/// @param key
/// @return
///
int AssFile::GetScriptInfoAsInt(const wxString key) {
long temp = 0;
try {
@ -726,13 +642,10 @@ int AssFile::GetScriptInfoAsInt(const wxString key) {
return temp;
}
/// @brief Set a script info line
/// @param _key
/// @param value
/// @return
///
void AssFile::SetScriptInfo(const wxString _key,const wxString value) {
// Prepare
wxString key = _key;;
@ -778,7 +691,6 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) {
result += value;
AssEntry *entry = new AssEntry(result);
entry->group = (*prev)->group;
entry->SetStartMS((*prev)->GetStartMS());
Line.insert(++prev,entry);
}
return;
@ -786,12 +698,9 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) {
}
}
/// @brief Get resolution
/// @param sw
/// @param sh
///
void AssFile::GetResolution(int &sw,int &sh) {
// Height
wxString temp = GetScriptInfo(_T("PlayResY"));
@ -832,11 +741,8 @@ void AssFile::GetResolution(int &sw,int &sh) {
}
}
/// @brief Adds a comment to [Script Info]
/// @param _comment
///
void AssFile::AddComment(const wxString _comment) {
wxString comment = _T("; ");
comment += _comment;
@ -853,18 +759,14 @@ void AssFile::AddComment(const wxString _comment) {
AssEntry *prev = *cur;
AssEntry *comm = new AssEntry(comment);
comm->group = prev->group;
comm->SetStartMS(prev->GetStartMS());
Line.insert(cur,comm);
break;
}
}
}
/// @brief Get list of styles
/// @return
///
wxArrayString AssFile::GetStyles() {
wxArrayString styles;
AssStyle *curstyle;
@ -877,12 +779,9 @@ wxArrayString AssFile::GetStyles() {
return styles;
}
/// @brief Gets style of specific name
/// @param name
/// @return
///
AssStyle *AssFile::GetStyle(wxString name) {
AssStyle *curstyle;
for (entryIter cur=Line.begin();cur!=Line.end();cur++) {
@ -894,38 +793,24 @@ AssStyle *AssFile::GetStyle(wxString name) {
return NULL;
}
/// @brief Adds file name to list of recent
/// @param file
///
void AssFile::AddToRecent(wxString file) {
Options.AddToRecentList(file,_T("Recent sub"));
}
/// @brief List of supported wildcards
/// @param mode
/// @return
///
wxString AssFile::GetWildcardList(int mode) {
//if (mode == 0) return _T("All Supported Types (*.ass,*.ssa,*.srt,*.txt,*.mkv,*.mks,*.mka)|*.ass;*.ssa;*.srt;*.txt;*.mkv;*.mks;*.mka|Advanced Substation Alpha (*.ass)|*.ass|Substation Alpha (*.ssa)|*.ssa|SubRip (*.srt)|*.srt|Plain-text (*.txt)|*.txt|Matroska (*.mkv,*.mks,*.mka)|*.mkv;*.mks;*.mka");
//else if (mode == 1) return _T("Advanced Substation Alpha (*.ass)|*.ass");
//else if (mode == 2) return _T("All Supported Types (*.ass,*.ssa,*.srt,*.txt,*.mkv,*.mks,*.mka)|*.ass;*.ssa;*.srt;*.txt|Advanced Substation Alpha (*.ass)|*.ass|Substation Alpha (*.ssa)|*.ssa|SubRip (*.srt)|*.srt|Plain-text (*.txt)|*.txt");
//else return _T("");
if (mode == 0) return SubtitleFormat::GetWildcards(0);
else if (mode == 1) return _T("Advanced Substation Alpha (*.ass)|*.ass");
else if (mode == 2) return SubtitleFormat::GetWildcards(1);
else return _T("");
}
/// @brief Compress/decompress for storage on stack
/// @param compress
///
void AssFile::CompressForStack(bool compress) {
AssDialogue *diag;
for (entryIter cur=Line.begin();cur!=Line.end();cur++) {
@ -940,20 +825,14 @@ void AssFile::CompressForStack(bool compress) {
}
}
/// @brief Checks if file is modified
/// @return
///
bool AssFile::IsModified() {
return Modified;
}
/// @brief Flag file as modified
/// @param desc
///
void AssFile::FlagAsModified(wxString desc) {
// Clear redo
if (!RedoStack.empty()) {
@ -969,11 +848,8 @@ void AssFile::FlagAsModified(wxString desc) {
StackPush(desc);
}
/// @brief Stack push
/// @param desc
///
void AssFile::StackPush(wxString desc) {
// Places copy on stack
AssFile *curcopy = new AssFile(*top);
@ -995,10 +871,7 @@ void AssFile::StackPush(wxString desc) {
}
}
/// @brief Stack pop
///
void AssFile::StackPop() {
bool addcopy = false;
wxString undodesc=_T("");
@ -1029,10 +902,7 @@ void AssFile::StackPop() {
}
}
/// @brief Stack redo
///
void AssFile::StackRedo() {
bool addcopy = false;
@ -1058,10 +928,7 @@ void AssFile::StackRedo() {
}
}
/// @brief Stack clear
///
void AssFile::StackClear() {
// Clear undo
for (std::list<AssFile*>::iterator cur=UndoStack.begin();cur!=UndoStack.end();cur++) {
@ -1078,11 +945,8 @@ void AssFile::StackClear() {
Popping = false;
}
/// @brief Stack reset
/// @return
///
void AssFile::StackReset() {
StackClear();
delete top;
@ -1090,42 +954,73 @@ void AssFile::StackReset() {
StackModified = false;
}
/// @brief Returns if undo stack is empty
/// @return
///
bool AssFile::IsUndoStackEmpty() {
if (StackModified) return (UndoStack.size() <= 1);
else return UndoStack.empty();
}
/// @brief Returns if redo stack is empty
/// @return
///
bool AssFile::IsRedoStackEmpty() {
return RedoStack.empty();
}
/// @brief DOCME
/// @return
///
wxString AssFile::GetUndoDescription() {
return (IsUndoStackEmpty())?_T(""):(UndoStack.back())->undodescription;
}
/// @brief DOCME
/// @return
///
wxString AssFile::GetRedoDescription() {
return (IsRedoStackEmpty())?_T(""):(RedoStack.back())->undodescription;
}
bool AssFile::CompStart(const AssDialogue* lft, const AssDialogue* rgt) {
return lft->Start < rgt->Start;
}
bool AssFile::CompEnd(const AssDialogue* lft, const AssDialogue* rgt) {
return lft->End < rgt->End;
}
bool AssFile::CompStyle(const AssDialogue* lft, const AssDialogue* rgt) {
return lft->Style < rgt->Style;
}
void AssFile::Sort(CompFunc comp) {
Sort(Line, comp);
}
void AssFile::Sort(std::list<AssEntry*> &lst, CompFunc comp) {
// uguu c++ closures uguu
struct : public std::binary_function<const AssEntry*, const AssEntry*, bool> {
CompFunc comp;
bool operator()(const AssEntry* a, const AssEntry* b) const {
return comp(static_cast<const AssDialogue*>(a), static_cast<const AssDialogue*>(b));
}
} compE;
compE.comp = comp;
// Sort each block of AssDialogues separately, leaving everything else untouched
for (entryIter begin = lst.begin(); begin != lst.end(); ++begin) {
if (!dynamic_cast<AssDialogue*>(*begin)) continue;
entryIter end = begin;
while (end != lst.end() && dynamic_cast<AssDialogue*>(*end)) ++end;
// std::list::sort doesn't support sorting only part of the list, but
// splice is constant-time, so just sort a temp list with only the part we
// want sorted
std::list<AssEntry*> tmp;
tmp.splice(tmp.begin(), lst, begin, end);
tmp.sort(compE);
lst.splice(end, tmp);
begin = --end;
}
}
void AssFile::Sort(std::list<AssDialogue*> &lst, CompFunc comp) {
lst.sort(comp);
}
/// DOCME
AssFile *AssFile::top;
@ -1141,9 +1036,3 @@ bool AssFile::Popping;
/// DOCME
bool AssFile::StackModified;

View file

@ -37,9 +37,6 @@
#pragma once
///////////
// Headers
#ifndef AGI_PRE
#include <fstream>
#include <list>
@ -48,9 +45,6 @@
#include <wx/arrstr.h>
#endif
//////////////
// Prototypes
class FrameRate;
class AssDialogue;
class AssStyle;
@ -60,7 +54,7 @@ class AssDialogueBlockOverride;
class AssDialogueBlockPlain;
class AssEntry;
typedef std::list<AssEntry*>::iterator entryIter;
/// DOCME
/// @class AssFile
@ -128,7 +122,7 @@ public:
wxString GetScriptInfo(const wxString key); // Returns the value in a [Script Info] key as string.
void SetScriptInfo(const wxString key,const wxString value); // Sets the value of a [Script Info] key. Adds it if it doesn't exist.
void AddComment(const wxString comment); // Adds a ";" comment under [Script Info].
int AddLine(wxString data,wxString group,int lasttime,int &version,wxString *outGroup=NULL);
void AddLine(wxString data,wxString group,int &version,wxString *outGroup=NULL);
static void StackPop(); // Pop subs from stack and sets 'top' to it
static void StackRedo(); // Redoes action on stack
@ -144,33 +138,24 @@ public:
/// DOCME
static AssFile *top; // Current script file. It is "above" the stack.
/// Comparison function for use when sorting
typedef bool (*CompFunc)(const AssDialogue* lft, const AssDialogue* rgt);
/// @brief Compare based on start time
static bool CompStart(const AssDialogue* lft, const AssDialogue* rgt);
/// @brief Compare based on end time
static bool CompEnd(const AssDialogue* lft, const AssDialogue* rgt);
/// @brief Compare based on end time
static bool CompStyle(const AssDialogue* lft, const AssDialogue* rgt);
/// @brief Sort the dialogue lines in this file
/// @param comp Comparison function to use. Defaults to sorting by start time.
void Sort(CompFunc comp = CompStart);
/// @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<AssEntry*>& lst, CompFunc comp = CompStart);