diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj index b63836671..d1213ac3a 100644 --- a/aegilib/aegilib.vcproj +++ b/aegilib/aegilib.vcproj @@ -324,6 +324,14 @@ RelativePath=".\src\text_file_reader.h" > + + + + diff --git a/aegilib/include/aegilib/format_handler.h b/aegilib/include/aegilib/format_handler.h index 2ad27b56f..f24424e74 100644 --- a/aegilib/include/aegilib/format_handler.h +++ b/aegilib/include/aegilib/format_handler.h @@ -46,6 +46,7 @@ namespace Aegilib { public: virtual void Load(wxInputStream &file,const String encoding) = 0; + virtual void Save(wxOutputStream &file,const String encoding) = 0; }; typedef shared_ptr FormatHandlerPtr; diff --git a/aegilib/include/aegilib/model.h b/aegilib/include/aegilib/model.h index c28a178f6..500dae3d7 100644 --- a/aegilib/include/aegilib/model.h +++ b/aegilib/include/aegilib/model.h @@ -35,6 +35,7 @@ #pragma once #include +#include #include #include "manipulator.h" #include "section.h" @@ -56,7 +57,7 @@ namespace Aegilib { typedef shared_ptr FormatPtr; private: - std::list sections; + std::vector sections; ActionStack undoStack; ActionStack redoStack; ViewList listeners; @@ -75,8 +76,10 @@ namespace Aegilib { void LoadFile(const String filename,const String encoding=L""); void SaveFile(const String filename,const String encoding=L"UTF-8"); - SectionPtr GetSection(String name) const; void AddSection(String name); + SectionPtr GetSection(String name) const; + SectionPtr GetSectionByIndex(size_t index) const; + size_t GetSectionCount() const; bool CanUndo(const String owner=L"") const; bool CanRedo(const String owner=L"") const; diff --git a/aegilib/include/aegilib/section.h b/aegilib/include/aegilib/section.h index de952667b..d51eb6fe0 100644 --- a/aegilib/include/aegilib/section.h +++ b/aegilib/include/aegilib/section.h @@ -44,9 +44,8 @@ namespace Aegilib { // Section class class Section { - friend class shared_ptr
; private: - std::list entries; + std::vector entries; std::map properties; String name; @@ -54,17 +53,24 @@ namespace Aegilib { Section(String name); ~Section() {} - const String& GetName() const { return name; } + // Section name String SetName(const String& newName) { name = newName; } + const String& GetName() const { return name; } + // Script properties void SetProperty(const String &key,const String &value); void UnsetProperty(const String &key); String GetProperty(const String &key) const; bool HasProperty(const String &key) const; - size_t PropertyCount() const; + size_t GetPropertyCount() const; String GetPropertyName(size_t index) const; + // Entries void AddEntry(SectionEntryPtr entry); + void RemoveEntryByIndex(size_t index); + void RemoveEntry(SectionEntryPtr entry); + SectionEntryConstPtr GetEntry(size_t index) const; + size_t GetEntryCount() const; }; typedef shared_ptr
SectionPtr; diff --git a/aegilib/include/aegilib/section_entry.h b/aegilib/include/aegilib/section_entry.h index ec6a54921..6451765e5 100644 --- a/aegilib/include/aegilib/section_entry.h +++ b/aegilib/include/aegilib/section_entry.h @@ -49,18 +49,24 @@ namespace Aegilib { }; // Prototypes - class SectionEntryPlain; - typedef shared_ptr SectionEntryPlainPtr; - class SectionEntryDialogue; - typedef shared_ptr SectionEntryDialoguePtr; - class SectionEntryStyle; - typedef shared_ptr SectionEntryStylePtr; - class SectionEntryFile; - typedef shared_ptr SectionEntryFilePtr; - class SectionEntryRaw; - typedef shared_ptr SectionEntryRawPtr; class SectionEntry; + class SectionEntryPlain; + class SectionEntryDialogue; + class SectionEntryStyle; + class SectionEntryFile; + class SectionEntryRaw; typedef shared_ptr SectionEntryPtr; + typedef shared_ptr SectionEntryPlainPtr; + typedef shared_ptr SectionEntryDialoguePtr; + typedef shared_ptr SectionEntryStylePtr; + typedef shared_ptr SectionEntryFilePtr; + typedef shared_ptr SectionEntryRawPtr; + typedef shared_ptr SectionEntryConstPtr; + typedef shared_ptr SectionEntryPlainConstPtr; + typedef shared_ptr SectionEntryDialogueConstPtr; + typedef shared_ptr SectionEntryStyleConstPtr; + typedef shared_ptr SectionEntryFileConstPtr; + typedef shared_ptr SectionEntryRawConstPtr; // Section entry class class SectionEntry { @@ -72,6 +78,7 @@ namespace Aegilib { virtual SectionEntryType GetType() const =0; static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr); static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr); + static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr); static const SectionEntryStylePtr GetAsStyle(const SectionEntryPtr &ptr); static const SectionEntryFilePtr GetAsFile(const SectionEntryPtr &ptr); static const SectionEntryRawPtr GetAsRaw(const SectionEntryPtr &ptr); diff --git a/aegilib/src/formats/format_ass.cpp b/aegilib/src/formats/format_ass.cpp index 79c8bf60f..a79ab6936 100644 --- a/aegilib/src/formats/format_ass.cpp +++ b/aegilib/src/formats/format_ass.cpp @@ -33,9 +33,11 @@ // Contact: mailto:amz@aegisub.net // +#include "section.h" #include "model.h" #include "format_ass.h" #include "../text_file_reader.h" +#include "../text_file_writer.h" #include #include using namespace Aegilib; @@ -78,10 +80,6 @@ void FormatHandlerASS::Load(wxInputStream &file,const String encoding) // Make text file reader TextFileReader reader(file,encoding); - // Debug - using namespace std; - cout << endl << "Dumping file:" << endl; - // Variables int version = 1; wxString curGroup = L"-"; @@ -111,17 +109,44 @@ void FormatHandlerASS::Load(wxInputStream &file,const String encoding) SectionEntryPtr entry = MakeEntry(cur,section,version); if (entry) section->AddEntry(entry); } +} - // Debug - cout << "\nFinished reading file with version=" << version << ".\n"; - cout << "Dumping properties:\n"; - section = model.GetSection(_T("Script Info")); - size_t n = section->PropertyCount(); - for (size_t i=0;iGetPropertyName(i); - cout << name.mb_str(wxConvUTF8) << "=" << section->GetProperty(name).mb_str(wxConvUTF8) << endl; + +///////////////////// +// Save file to disc +void FormatHandlerASS::Save(wxOutputStream &file,const String encoding) +{ + // Make text file writer + TextFileWriter writer(file,encoding); + + // Set up list of sections to write + wxArrayString sections; + sections.Add(L"Script Info"); + sections.Add(L"V4+ Styles"); + sections.Add(L"Events"); + sections.Add(L"Fonts"); + sections.Add(L"Graphics"); + + // Look for remaining sections + size_t totalSections = model.GetSectionCount(); + for (size_t i=0;iGetName(); + if (sections.Index(name,false,false) == wxNOT_FOUND) sections.Add(name); + } + + // Write sections + size_t len = sections.size(); + for (size_t i=0;iGetName() + _T("]")); + + // Write properties + size_t props = section->GetPropertyCount(); + for (size_t i=0;iGetPropertyName(i); + writer.WriteLineToFile(name + _T(": ") + section->GetProperty(name)); + } + + // Write contents + size_t entries = section->GetEntryCount(); + for (size_t i=0;iGetEntry(i); + shared_ptr serial = dynamic_pointer_cast(entry); + writer.WriteLineToFile(serial->ToText()); + } +} diff --git a/aegilib/src/formats/format_ass.h b/aegilib/src/formats/format_ass.h index e229bb617..f7cd072c7 100644 --- a/aegilib/src/formats/format_ass.h +++ b/aegilib/src/formats/format_ass.h @@ -44,19 +44,29 @@ namespace Aegilib { // Prototypes class Model; + class TextFileWriter; + + class SerializeText { + public: + virtual ~SerializeText(){} + virtual String ToText() const=0; + }; // Advanced Substation Alpha format handler class FormatHandlerASS : public FormatHandler { private: + Model &model; + SectionEntryPtr MakeEntry(const String &data,SectionPtr section,int version); void ProcessGroup(String cur,String &curGroup,int &version); - Model &model; + void WriteSection(TextFileWriter &writer,SectionPtr section); public: FormatHandlerASS(Model &model); ~FormatHandlerASS(); void Load(wxInputStream &file,const String encoding); + void Save(wxOutputStream &file,const String encoding); }; // Advanced Substation Alpha format @@ -76,7 +86,7 @@ namespace Aegilib { }; // Dialogue - class DialogueASS : public SectionEntryDialogue { + class DialogueASS : public SectionEntryDialogue, public SerializeText { private: String text; String style; @@ -88,6 +98,7 @@ namespace Aegilib { bool isComment; bool Parse(String data,int version); + String ToText() const; public: // Constructors @@ -123,7 +134,7 @@ namespace Aegilib { }; // Style - class StyleASS : public SectionEntryStyle { + class StyleASS : public SectionEntryStyle, public SerializeText { private: String name; String font; @@ -152,6 +163,7 @@ namespace Aegilib { bool Parse(String data,int version); int AlignSSAtoASS(int ssaAlignment); int AlignASStoSSA(int assAlignment); + String ToText() const; public: // Constructors diff --git a/aegilib/src/formats/format_ass_dialogue.cpp b/aegilib/src/formats/format_ass_dialogue.cpp index 476ec2519..3131da4d9 100644 --- a/aegilib/src/formats/format_ass_dialogue.cpp +++ b/aegilib/src/formats/format_ass_dialogue.cpp @@ -134,3 +134,12 @@ bool DialogueASS::Parse(wxString rawData, int version) return true; } + + +///////////// +// Serialize +String DialogueASS::ToText() const +{ + String final = L"Dialogue"; + return final; +} diff --git a/aegilib/src/formats/format_ass_style.cpp b/aegilib/src/formats/format_ass_style.cpp index 50ac442e4..26016e728 100644 --- a/aegilib/src/formats/format_ass_style.cpp +++ b/aegilib/src/formats/format_ass_style.cpp @@ -163,3 +163,12 @@ int StyleASS::AlignASStoSSA(int assAlignment) // TODO return assAlignment; } + + +///////////// +// Serialize +String StyleASS::ToText() const +{ + String final = L"Style"; + return final; +} diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp index ef6fbe472..5b5381fa4 100644 --- a/aegilib/src/model.cpp +++ b/aegilib/src/model.cpp @@ -109,10 +109,20 @@ void Model::Load(wxInputStream &input,const FormatPtr format,const String encodi // Save subtitles void Model::Save(wxOutputStream &output,const FormatPtr format,const String encoding) { - (void) output; - (void) format; - (void) encoding; - // TODO + // Autodetect format + if (format == NULL) { + // TODO + + // No format found + throw Exception(Exception::No_Format_Handler); + } + + // Get handler + FormatHandlerPtr handler = format->GetHandler(*this); + if (!handler) throw Exception(Exception::No_Format_Handler); + + // Load + handler->Save(output,encoding); } @@ -136,18 +146,6 @@ void Model::SaveFile(const String filename,const String encoding) } -////////////////// -// Gets a section -SectionPtr Model::GetSection(String name) const -{ - std::list::const_iterator cur; - for (cur=sections.begin();cur!=sections.end();cur++) { - if ((*cur)->GetName() == name) return *cur; - } - return SectionPtr(); -} - - ///////////////////////// // Inserts a new section void Model::AddSection(String name) @@ -156,3 +154,31 @@ void Model::AddSection(String name) if (prev) throw Exception(Exception::Section_Already_Exists); sections.push_back(SectionPtr(new Section(name))); } + + +////////////////// +// Gets a section +SectionPtr Model::GetSection(String name) const +{ + size_t len = sections.size(); + for (size_t i=0;iGetName() == name) return sections[i]; + } + return SectionPtr(); +} + + +//////////////////////// +// Get section by index +SectionPtr Model::GetSectionByIndex(size_t index) const +{ + return sections.at(index); +} + + +///////////////////// +// Get section count +size_t Model::GetSectionCount() const +{ + return sections.size(); +} diff --git a/aegilib/src/section.cpp b/aegilib/src/section.cpp index 7eeff08b7..d0b80d38e 100644 --- a/aegilib/src/section.cpp +++ b/aegilib/src/section.cpp @@ -53,6 +53,32 @@ void Section::AddEntry(SectionEntryPtr entry) entries.push_back(entry); } +void Section::RemoveEntryByIndex(size_t index) +{ + entries.erase(entries.begin()+index); +} + +void Section::RemoveEntry(SectionEntryPtr entry) +{ + size_t len = entries.size(); + for (size_t i=0;i(ptr); } +const SectionEntryDialogueConstPtr SectionEntry::GetAsDialogue(const SectionEntryConstPtr &ptr) +{ + return dynamic_pointer_cast(ptr); +} const SectionEntryStylePtr SectionEntry::GetAsStyle(const SectionEntryPtr &ptr) { return dynamic_pointer_cast(ptr); diff --git a/aegilib/src/text_file_writer.cpp b/aegilib/src/text_file_writer.cpp index a838abbe7..575881080 100644 --- a/aegilib/src/text_file_writer.cpp +++ b/aegilib/src/text_file_writer.cpp @@ -38,76 +38,38 @@ // Headers #include #include "text_file_writer.h" +using namespace Aegilib; /////////////// // Constructor -TextFileWriter::TextFileWriter(Aegilib::String _filename,Aegilib::String enc) { +TextFileWriter::TextFileWriter(wxOutputStream &stream,String enc) +: file(stream) +{ // Setup - open = false; - customConv = false; IsFirst = true; - filename = _filename; // Set encoding encoding = enc; - if (encoding == _T("Local")) conv = &wxConvLocal; + if (encoding == _T("Local")) conv = shared_ptr (wxConvCurrent,NullDeleter()); else { if (encoding.IsEmpty()) encoding = _T("UTF-8"); if (encoding == _T("US-ASCII")) encoding = _T("ISO-8859-1"); - conv = new wxCSConv(encoding); - customConv = true; + conv = shared_ptr (new wxCSConv(encoding)); IsUnicode = encoding.Left(3) == _T("UTF"); } - - // Open file - Open(); } ////////////// // Destructor TextFileWriter::~TextFileWriter() { - Close(); -} - - -///////////// -// Open file -void TextFileWriter::Open() { - // Open file - if (open) return; -#ifdef WIN32 - file.open(filename.wc_str(),std::ios::out | std::ios::binary | std::ios::trunc); -#else - file.open(wxFNCONV(filename),std::ios::out | std::ios::binary | std::ios::trunc); -#endif - if (!file.is_open()) { - throw _T("Failed opening file for writing."); - } - open = true; - - // Set encoding - SetEncoding(); -} - - -////////////// -// Close file -void TextFileWriter::Close() { - if (!open) return; - file.close(); - open = false; - if (customConv) delete conv; } ///////////////// // Write to file void TextFileWriter::WriteLineToFile(Aegilib::String line,bool addLineBreak) { - // Make sure it's loaded - if (!open) Open(); - // Add line break wxString temp = line; if (addLineBreak) temp += _T("\r\n"); @@ -125,7 +87,7 @@ void TextFileWriter::WriteLineToFile(Aegilib::String line,bool addLineBreak) { if (!buf.data()) return; size_t len = wcslen(buf.data()); - file.write((const char*)buf.data(),(std::streamsize)len*sizeof(wchar_t)); + file.Write((const char*)buf.data(),(std::streamsize)len*sizeof(wchar_t)); } // 8-bit @@ -134,7 +96,7 @@ void TextFileWriter::WriteLineToFile(Aegilib::String line,bool addLineBreak) { if (!buf.data()) return; size_t len = strlen(buf.data()); - file.write(buf.data(),(std::streamsize)len); + file.Write(buf.data(),(std::streamsize)len); } } diff --git a/aegilib/src/text_file_writer.h b/aegilib/src/text_file_writer.h index c1d156cac..8d24562ba 100644 --- a/aegilib/src/text_file_writer.h +++ b/aegilib/src/text_file_writer.h @@ -34,42 +34,28 @@ // -#ifndef TEXT_FILE_WRITER_H -#define TEXT_FILE_WRITER_H +#pragma once +#include "aegilib.h" +#include -/////////// -// Headers -#include -#include -#include +namespace Aegilib { + class TextFileWriter { + private: + wxString encoding; + wxOutputStream &file; + shared_ptr conv; + bool Is16; + bool IsFirst; + bool IsUnicode; -///////// -// Class -class TextFileWriter { -private: - wxString filename; - wxString encoding; - std::ofstream file; + void SetEncoding(); - wxMBConv *conv; - bool customConv; - bool open; - bool Is16; - bool IsFirst; - bool IsUnicode; + public: + TextFileWriter(wxOutputStream &stream,String encoding=_T("")); + ~TextFileWriter(); - void Open(); - void Close(); - void SetEncoding(); - -public: - TextFileWriter(Aegilib::String filename,Aegilib::String encoding=_T("")); - ~TextFileWriter(); - - void WriteLineToFile(Aegilib::String line,bool addLineBreak=true); + void WriteLineToFile(Aegilib::String line,bool addLineBreak=true); + }; }; - - -#endif