diff --git a/aegisub/build/Aegisub/Aegisub.vcxproj b/aegisub/build/Aegisub/Aegisub.vcxproj
index a3e0bf1a2..e0a060076 100644
--- a/aegisub/build/Aegisub/Aegisub.vcxproj
+++ b/aegisub/build/Aegisub/Aegisub.vcxproj
@@ -256,6 +256,7 @@
+
diff --git a/aegisub/build/Aegisub/Aegisub.vcxproj.filters b/aegisub/build/Aegisub/Aegisub.vcxproj.filters
index 7a6fdb691..ef0128fb1 100644
--- a/aegisub/build/Aegisub/Aegisub.vcxproj.filters
+++ b/aegisub/build/Aegisub/Aegisub.vcxproj.filters
@@ -684,6 +684,10 @@
Features\Autosave
+
+
+ ASS
+
diff --git a/aegisub/src/ass_attachment.cpp b/aegisub/src/ass_attachment.cpp
index 91edd812e..a5d43fd0b 100644
--- a/aegisub/src/ass_attachment.cpp
+++ b/aegisub/src/ass_attachment.cpp
@@ -46,8 +46,7 @@
#include
AssAttachment::AssAttachment(wxString const& name, AssEntryGroup group)
-: AssEntry(wxString())
-, data(new std::vector)
+: data(new std::vector)
, filename(name)
, group(group)
{
diff --git a/aegisub/src/ass_dialogue.cpp b/aegisub/src/ass_dialogue.cpp
index 77b3463f6..caa664ba6 100644
--- a/aegisub/src/ass_dialogue.cpp
+++ b/aegisub/src/ass_dialogue.cpp
@@ -55,8 +55,7 @@ std::size_t hash_value(wxString const& s) {
}
AssDialogue::AssDialogue()
-: AssEntry(wxString())
-, Comment(false)
+: Comment(false)
, Layer(0)
, Start(0)
, End(5000)
@@ -66,8 +65,7 @@ AssDialogue::AssDialogue()
}
AssDialogue::AssDialogue(AssDialogue const& that)
-: AssEntry(wxString())
-, Comment(that.Comment)
+: Comment(that.Comment)
, Layer(that.Layer)
, Start(that.Start)
, End(that.End)
@@ -80,8 +78,7 @@ AssDialogue::AssDialogue(AssDialogue const& that)
}
AssDialogue::AssDialogue(wxString const& data)
-: AssEntry(wxString())
-, Comment(false)
+: Comment(false)
, Layer(0)
, Start(0)
, End(5000)
diff --git a/aegisub/src/ass_dialogue.h b/aegisub/src/ass_dialogue.h
index 1d2099887..b9cf98fab 100644
--- a/aegisub/src/ass_dialogue.h
+++ b/aegisub/src/ass_dialogue.h
@@ -163,8 +163,6 @@ public:
/// Update the text of the line from parsed blocks
void UpdateText(boost::ptr_vector& blocks);
const wxString GetEntryData() const override;
- /// Do nothing
- void SetEntryData(wxString const&) override { }
template
void SetMarginString(wxString const& value) { SetMarginString(value, which);}
diff --git a/aegisub/src/ass_entry.cpp b/aegisub/src/ass_entry.cpp
index c90bd13a6..8eb684594 100644
--- a/aegisub/src/ass_entry.cpp
+++ b/aegisub/src/ass_entry.cpp
@@ -1,29 +1,16 @@
-// Copyright (c) 2005, Rodrigo Braz Monteiro
-// All rights reserved.
+// Copyright (c) 2012, Thomas Goyne
//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
@@ -36,15 +23,6 @@
#include "ass_entry.h"
-wxString AssEntry::GetSSAText() const {
- if (data.Lower() == "scripttype: v4.00+") return "ScriptType: v4.00";
- return GetEntryData();
-}
-
-AssEntry *AssEntry::Clone() const {
- return new AssEntry(data);
-}
-
wxString const& AssEntry::GroupHeader(bool ssa) const {
static wxString ass_headers[] = {
"[Script Info]",
diff --git a/aegisub/src/ass_entry.h b/aegisub/src/ass_entry.h
index 3e837bad1..a24c045d9 100644
--- a/aegisub/src/ass_entry.h
+++ b/aegisub/src/ass_entry.h
@@ -48,29 +48,21 @@ enum AssEntryGroup {
};
class AssEntry : public boost::intrusive::make_list_base_hook >::type {
- /// Raw data, exactly the same line that appears on the .ass (note that this will be in ass even if source wasn't)
- wxString data;
-
public:
- AssEntry(wxString const& data) : data(data) { }
virtual ~AssEntry() { }
/// Create a copy of this entry
- virtual AssEntry *Clone() const;
+ virtual AssEntry *Clone() const=0;
/// Section of the file this entry belongs to
- virtual AssEntryGroup Group() const { return ENTRY_INFO; }
+ virtual AssEntryGroup Group() const=0;
/// ASS or SSA Section header for this entry's group
wxString const& GroupHeader(bool ssa=false) const;
/// @brief Get this line's raw entry data in ASS format
- virtual const wxString GetEntryData() const { return data; }
-
- /// @brief Set this line's raw entry data
- /// @param newData New raw entry data
- virtual void SetEntryData(wxString const& newData) { data = newData; }
+ virtual const wxString GetEntryData() const=0;
/// Get this line in SSA format
- virtual wxString GetSSAText() const;
+ virtual wxString GetSSAText() const { return GetEntryData(); }
};
diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp
index 276f6154c..2ba29a9cc 100644
--- a/aegisub/src/ass_file.cpp
+++ b/aegisub/src/ass_file.cpp
@@ -46,6 +46,7 @@
#include "ass_attachment.h"
#include "ass_dialogue.h"
+#include "ass_info.h"
#include "ass_override.h"
#include "ass_style.h"
#include "compat.h"
@@ -218,16 +219,16 @@ void AssFile::LoadDefault(bool defline) {
Clear();
// Write headers
- Line.push_back(*new AssEntry("Title: Default Aegisub file"));
- Line.push_back(*new AssEntry("ScriptType: v4.00+"));
- Line.push_back(*new AssEntry("WrapStyle: 0"));
- Line.push_back(*new AssEntry("ScaledBorderAndShadow: yes"));
- Line.push_back(*new AssEntry("Collisions: Normal"));
+ Line.push_back(*new AssInfo("Title", "Default Aegisub file"));
+ Line.push_back(*new AssInfo("ScriptType", "v4.00+"));
+ Line.push_back(*new AssInfo("WrapStyle", "0"));
+ Line.push_back(*new AssInfo("ScaledBorderAndShadow", "yes"));
+ Line.push_back(*new AssInfo("Collisions", "Normal"));
if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) {
- Line.push_back(*new AssEntry(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt())));
- Line.push_back(*new AssEntry(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt())));
+ Line.push_back(*new AssInfo("PlayResX", wxString::Format("%" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt())));
+ Line.push_back(*new AssInfo("PlayResY", wxString::Format("%" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt())));
}
- Line.push_back(*new AssEntry("YCbCr Matrix: None"));
+ Line.push_back(*new AssInfo("YCbCr Matrix", "None"));
Line.push_back(*new AssStyle);
@@ -263,7 +264,7 @@ AssFile& AssFile::operator=(AssFile from) {
return *this;
}
-void AssFile::InsertLine( AssEntry *entry) {
+void AssFile::InsertLine(AssEntry *entry) {
if (Line.empty()) {
Line.push_back(*entry);
return;
@@ -297,17 +298,10 @@ void AssFile::InsertAttachment(wxString filename) {
wxString AssFile::GetScriptInfo(wxString key) const {
key.MakeLower();
- key += ":";
- bool GotIn = false;
- for (auto const& line : Line) {
- if (line.Group() == ENTRY_INFO) {
- GotIn = true;
- wxString curText = line.GetEntryData();
- if (curText.Lower().StartsWith(key))
- return curText.Mid(key.size()).Trim(true).Trim(false);
- }
- else if (GotIn) return "";
+ for (const auto info : Line | agi::of_type()) {
+ if (key == info->Key().Lower())
+ return info->Value();
}
return "";
@@ -320,40 +314,18 @@ int AssFile::GetScriptInfoAsInt(wxString const& key) const {
}
void AssFile::SetScriptInfo(wxString const& key, wxString const& value) {
- wxString search_key = key.Lower() + ":";
- size_t key_size = search_key.size();
- entryIter script_info_end;
- bool found_script_info = false;
-
- for (auto& line : Line) {
- if (line.Group() == ENTRY_INFO) {
- found_script_info = true;
- wxString cur_text = line.GetEntryData().Left(key_size).Lower();
-
- if (cur_text == search_key) {
- if (value.empty())
- delete &line;
- else
- line.SetEntryData(key + ": " + value);
- return;
- }
- script_info_end = Line.iterator_to(line);
- }
- else if (found_script_info) {
- if (value.size())
- Line.insert(script_info_end, *new AssEntry(key + ": " + value));
+ wxString lower_key = key.Lower();
+ for (auto info : Line | agi::of_type()) {
+ if (lower_key == info->Key().Lower()) {
+ if (value.empty())
+ delete info;
+ else
+ info->SetValue(value);
return;
}
}
- // Found a script info section, but not this key or anything after it,
- // so add it at the end of the file
- if (found_script_info)
- Line.push_back(*new AssEntry(key + ": " + value));
- // Script info section not found, so add it at the beginning of the file
- else {
- Line.push_front(*new AssEntry(key + ": " + value));
- }
+ InsertLine(new AssInfo(key, value));
}
void AssFile::GetResolution(int &sw,int &sh) const {
diff --git a/aegisub/src/ass_info.h b/aegisub/src/ass_info.h
new file mode 100644
index 000000000..8601984f6
--- /dev/null
+++ b/aegisub/src/ass_info.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include "ass_entry.h"
+
+class AssInfo : public AssEntry {
+ wxString key;
+ wxString value;
+
+public:
+ AssInfo(AssInfo const& o) : key(o.key), value(o.value) { }
+ AssInfo(wxString const& line) : key(line.BeforeFirst(':').Trim()), value(line.AfterFirst(':').Trim(false)) { }
+ AssInfo(wxString const& key, wxString const& value) : key(key), value(value) { }
+
+ AssEntry *Clone() const override { return new AssInfo(*this); }
+ AssEntryGroup Group() const override { return ENTRY_INFO; }
+ const wxString GetEntryData() const override { return key + ":" + value; }
+ wxString GetSSAText() const override { return key.Lower() == "scripttype: v4.00+" ? "ScriptType: v4.00" : GetEntryData(); }
+
+ wxString Key() const { return key; }
+ wxString Value() const { return value; }
+ void SetValue(wxString const& new_value) { value = new_value; }
+};
diff --git a/aegisub/src/ass_parser.cpp b/aegisub/src/ass_parser.cpp
index e06b08c58..5bbc266f0 100644
--- a/aegisub/src/ass_parser.cpp
+++ b/aegisub/src/ass_parser.cpp
@@ -19,6 +19,7 @@
#include "ass_attachment.h"
#include "ass_dialogue.h"
#include "ass_file.h"
+#include "ass_info.h"
#include "ass_style.h"
#include "subtitle_format.h"
@@ -88,7 +89,7 @@ void AssParser::ParseScriptInfoLine(wxString const& data) {
}
}
- InsertLine(new AssEntry(data));
+ InsertLine(new AssInfo(data));
}
void AssParser::ParseEventLine(wxString const& data) {
diff --git a/aegisub/src/ass_style.cpp b/aegisub/src/ass_style.cpp
index cf0dfd2e8..939ea60c0 100644
--- a/aegisub/src/ass_style.cpp
+++ b/aegisub/src/ass_style.cpp
@@ -45,8 +45,7 @@
#include "utils.h"
AssStyle::AssStyle()
-: AssEntry(wxString())
-, name("Default")
+: name("Default")
, font("Arial")
, fontsize(20.)
, primary(255, 255, 255)
@@ -89,9 +88,7 @@ static double get_next_double(wxStringTokenizer &tok) {
return temp;
}
-AssStyle::AssStyle(wxString rawData, int version)
-: AssEntry(wxString())
-{
+AssStyle::AssStyle(wxString rawData, int version) {
wxStringTokenizer tkn(rawData.Trim(false).Mid(6), ",", wxTOKEN_RET_EMPTY_ALL);
name = get_next_string(tkn).Trim(true).Trim(false);
@@ -173,7 +170,7 @@ void AssStyle::UpdateData() {
name.Replace(",", ";");
font.Replace(",", ";");
- SetEntryData(wxString::Format("Style: %s,%s,%g,%s,%s,%s,%s,%d,%d,%d,%d,%g,%g,%g,%g,%d,%g,%g,%i,%i,%i,%i,%i",
+ data = wxString::Format("Style: %s,%s,%g,%s,%s,%s,%s,%d,%d,%d,%d,%g,%g,%g,%g,%d,%g,%g,%i,%i,%i,%i,%i",
name, font, fontsize,
primary.GetAssStyleFormatted(),
secondary.GetAssStyleFormatted(),
@@ -183,7 +180,7 @@ void AssStyle::UpdateData() {
(underline?-1:0),(strikeout?-1:0),
scalex,scaley,spacing,angle,
borderstyle,outline_w,shadow_w,alignment,
- Margin[0],Margin[1],Margin[2],encoding));
+ Margin[0],Margin[1],Margin[2],encoding);
}
wxString AssStyle::GetSSAText() const {
diff --git a/aegisub/src/ass_style.h b/aegisub/src/ass_style.h
index 395bddfef..bb5c14a5c 100644
--- a/aegisub/src/ass_style.h
+++ b/aegisub/src/ass_style.h
@@ -41,6 +41,8 @@
#include
class AssStyle : public AssEntry {
+ wxString data;
+
public:
wxString name; ///< Name of the style; must be case-insensitively unique within a file despite being case-sensitive
wxString font; ///< Font face name
@@ -76,6 +78,7 @@ public:
AssStyle();
AssStyle(wxString data, int version=1);
+ const wxString GetEntryData() const override { return data; }
wxString GetSSAText() const override;
AssEntryGroup Group() const override { return ENTRY_STYLE; }
AssEntry *Clone() const override;
diff --git a/aegisub/src/auto4_lua_assfile.cpp b/aegisub/src/auto4_lua_assfile.cpp
index b2ac57753..e0d90af83 100644
--- a/aegisub/src/auto4_lua_assfile.cpp
+++ b/aegisub/src/auto4_lua_assfile.cpp
@@ -49,6 +49,7 @@
#include
#include "ass_dialogue.h"
+#include "ass_info.h"
#include "ass_file.h"
#include "ass_karaoke.h"
#include "ass_override.h"
@@ -203,9 +204,9 @@ namespace Automation4 {
set_field(L, "section", e->GroupHeader());
set_field(L, "raw", raw);
- if (e->Group() == ENTRY_INFO) {
- set_field(L, "key", raw.BeforeFirst(':'));
- set_field(L, "value", raw.AfterFirst(':'));
+ if (AssInfo *info = dynamic_cast(e)) {
+ set_field(L, "key", info->Key());
+ set_field(L, "value", info->Value());
set_field(L, "class", "info");
}
else if (AssDialogue *dia = dynamic_cast(e)) {
@@ -297,7 +298,7 @@ namespace Automation4 {
wxString section = get_wxstring_field(L, "section", "common");
if (lclass == "info") {
- result = new AssEntry(wxString::Format("%s: %s", get_wxstring_field(L, "key", "info"), get_wxstring_field(L, "value", "info")));
+ result = new AssInfo(get_wxstring_field(L, "key", "info"), get_wxstring_field(L, "value", "info"));
}
else if (lclass == "style") {
AssStyle *sty = new AssStyle;