diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj
index 35be6eb9c370fe8fdfdfcb1b309aa9d2d234cdf5..742f085a30e872996fe3076aa665cc5ead805371 100644
--- a/aegilib/aegilib.vcproj
+++ b/aegilib/aegilib.vcproj
@@ -199,6 +199,22 @@
 				RelativePath=".\include\aegilib\notification.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\aegilib\section.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\aegilib\section_entry.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\aegilib\section_entry_dialogue.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\aegilib\time.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\aegilib\view.h"
 				>
@@ -268,6 +284,10 @@
 				RelativePath=".\src\prec.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\section.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\src\text_file_reader.cpp"
 				>
diff --git a/aegilib/include/aegilib/aegilib.h b/aegilib/include/aegilib/aegilib.h
index b666ef2ac5de296182d29cbcfc7c47e5d6086cd7..56642a8644382f3899c8f3a845bb558eb3b0b32c 100644
--- a/aegilib/include/aegilib/aegilib.h
+++ b/aegilib/include/aegilib/aegilib.h
@@ -34,6 +34,7 @@
 //
 
 #pragma once
+#include "exception.h"
 #include "model.h"
 #include "view.h"
 #include "controller.h"
@@ -43,4 +44,5 @@
 #include "format_handler.h"
 #include "format_manager.h"
 #include "manipulator.h"
-#include "exception.h"
+#include "section.h"
+#include "section_entry_dialogue.h"
diff --git a/aegilib/include/aegilib/aegistring.h b/aegilib/include/aegilib/aegistring.h
index 0e893a5bfe11c906b81b36d04b45a44308a32caf..c9e8f6980d87c1eb1b5a83b8cf35b79660bd75d1 100644
--- a/aegilib/include/aegilib/aegistring.h
+++ b/aegilib/include/aegilib/aegistring.h
@@ -36,11 +36,13 @@
 #pragma once
 
 #include <wx/string.h>
+#include <vector>
 
 namespace Aegilib {
 
 	// Define the string type used throughout this library
 	//typedef std::basic_string<wchar_t> String;
 	typedef wxString String;
+	typedef std::vector<String> StringArray;
 
 };
diff --git a/aegilib/include/aegilib/exception.h b/aegilib/include/aegilib/exception.h
index dd05e4a28984fa72137f24593c3142a2c854b6f3..436ecff8a734f9756fbd5413fdd139f923ee01ff 100644
--- a/aegilib/include/aegilib/exception.h
+++ b/aegilib/include/aegilib/exception.h
@@ -35,7 +35,7 @@
 
 #pragma once
 
-#include "aegilib.h"
+#include "aegistring.h"
 
 namespace Aegilib {
 
@@ -45,7 +45,11 @@ namespace Aegilib {
 		enum ExceptionList {
 			Unknown,
 			No_Format_Handler,
-			Invalid_Manipulator
+			Invalid_Manipulator,
+			Section_Already_Exists,
+			Unknown_Format,
+			Parse_Error,
+			Unsupported_Format_Feature
 		};
 
 		Exception(ExceptionList code);
diff --git a/aegilib/include/aegilib/format.h b/aegilib/include/aegilib/format.h
index 1ade114511668f2f4d04ba04d639a60839e6d47a..53b512a40fa558cbfed27f82a1135d3c3fcc61b0 100644
--- a/aegilib/include/aegilib/format.h
+++ b/aegilib/include/aegilib/format.h
@@ -47,8 +47,9 @@ namespace Aegilib {
 		virtual ~Format() {}
 
 		virtual String GetName() const = 0;
-		virtual String GetExtension() const = 0;
-		virtual FormatHandler* GetHandler(const Model &model) const = 0;
+		virtual StringArray GetReadExtensions() const = 0;
+		virtual StringArray GetWriteExtensions() const = 0;
+		virtual FormatHandler* GetHandler(Model &model) const = 0;
 
 		virtual bool CanStoreText() const { return false; }
 		virtual bool CanStoreImages() const { return false; }
diff --git a/aegilib/include/aegilib/format_manager.h b/aegilib/include/aegilib/format_manager.h
index 5893253ec53449ebe28eed04d8f0e64f7d3803a4..556e25feb0d68ac234bc570d3632c112a2efa194 100644
--- a/aegilib/include/aegilib/format_manager.h
+++ b/aegilib/include/aegilib/format_manager.h
@@ -51,7 +51,7 @@ namespace Aegilib {
 
 		static int GetFormatCount();
 		static const Format* GetFormatByIndex(const int index);
-		static const Format* GetFormatFromFilename(const String &filename);
+		static const Format* GetFormatFromFilename(const String &filename,bool read);
 		static const Format* GetFormatFromName(const String &name);
 	};
 
diff --git a/aegilib/include/aegilib/model.h b/aegilib/include/aegilib/model.h
index d1fa87627dc5fd971518c914f543fcee6a3d9bcc..efbfaf57975d34a83f06114617cb901512e52e56 100644
--- a/aegilib/include/aegilib/model.h
+++ b/aegilib/include/aegilib/model.h
@@ -37,8 +37,10 @@
 #include <list>
 #include <wx/stream.h>
 #include "manipulator.h"
+#include "section.h"
 
 namespace Aegilib {
+
 	// Prototypes
 	class View;
 	class Notification;
@@ -52,6 +54,7 @@ namespace Aegilib {
 		typedef std::list<const Manipulator> ActionStack;
 
 	private:
+		std::list<Section*> sections;
 		ActionStack undoStack;
 		ActionStack redoStack;
 		ViewList listeners;
@@ -68,6 +71,9 @@ namespace Aegilib {
 		void LoadFile(wxInputStream &input,const Format *format=NULL,const String encoding=L"");
 		void SaveFile(wxOutputStream &output,const Format *format=NULL,const String encoding=L"UTF-8");
 
+		Section* GetSection(String name) const;
+		void AddSection(String name);
+
 		bool CanUndo(const String owner=L"") const;
 		bool CanRedo(const String owner=L"") const;
 		bool Undo(const String owner=L"");
diff --git a/aegilib/include/aegilib/section.h b/aegilib/include/aegilib/section.h
new file mode 100644
index 0000000000000000000000000000000000000000..128b7b808bad3c492186fb2d3f6700b55ad45e9a
--- /dev/null
+++ b/aegilib/include/aegilib/section.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * 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.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+#pragma once
+#include "aegistring.h"
+#include "section_entry.h"
+#include <list>
+
+namespace Aegilib {
+
+	// Section class
+	class Section {
+	private:
+		std::list<SectionEntry*> entries;
+		String name;
+
+	public:
+		Section(String name);
+		~Section();
+
+		String GetName() const { return name; }
+		String SetName(String newName) { name = newName; }
+
+		void AddEntry(SectionEntry *entry);
+	};
+
+};
diff --git a/aegilib/include/aegilib/section_entry.h b/aegilib/include/aegilib/section_entry.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc8c95aa7f575376fd04f8aa2ae16c6853654d62
--- /dev/null
+++ b/aegilib/include/aegilib/section_entry.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * 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.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+#pragma once
+
+namespace Aegilib {
+
+	// Types
+	enum SectionEntryType {
+		SECTION_ENTRY_PLAIN,
+		SECTION_ENTRY_DIALOGUE,
+		SECTION_ENTRY_STYLE,
+		SECTION_ENTRY_FILE,
+		SECTION_ENTRY_RAW
+	};
+
+	// Prototypes
+	class SectionEntryPlain;
+	class SectionEntryDialogue;
+	class SectionEntryStyle;
+	class SectionEntryFile;
+	class SectionEntryRaw;
+
+	// Section entry class
+	class SectionEntry {
+	private:
+
+	public:
+		virtual ~SectionEntry() {}
+
+		virtual SectionEntryType GetType() const =0;
+		virtual SectionEntryPlain *GetAsPlain() { return NULL; }
+		virtual SectionEntryDialogue *GetAsDialogue() { return NULL; }
+		virtual SectionEntryStyle *GetAsStyle() { return NULL; }
+		virtual SectionEntryFile *GetAsFile() { return NULL; }
+		virtual SectionEntryRaw *GetAsRaw() { return NULL; }
+	};
+
+};
diff --git a/aegilib/include/aegilib/section_entry_dialogue.h b/aegilib/include/aegilib/section_entry_dialogue.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbbe4ae1dd04e1f774b2299f7ffda49c06526153
--- /dev/null
+++ b/aegilib/include/aegilib/section_entry_dialogue.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * 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.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+
+#pragma once
+#include "exception.h"
+#include "section_entry.h"
+#include "time.h"
+
+
+namespace Aegilib {
+
+	// Dialogue class
+	class SectionEntryDialogue : public SectionEntry {
+	private:
+		void ThrowUnsupported() const { throw Exception(Exception::Unsupported_Format_Feature); }
+
+	public:
+		// Destructor
+		virtual ~SectionEntryDialogue() {}
+
+		// Type
+		SectionEntryType GetType() const { return SECTION_ENTRY_DIALOGUE; }
+		SectionEntryDialogue *GetAsDialogue() { return this; }
+
+		// Capabilities
+		virtual bool HasText() const { return false; }
+		virtual bool HasImage() const { return false; }
+		virtual bool HasTime() const { return false; }
+		virtual bool HasFrame() const { return false; }
+		virtual bool HasStyle() const { return false; }
+		virtual bool HasMargins() const { return false; }
+
+		// Read accessors
+		virtual String GetText() const { ThrowUnsupported(); return L""; }
+		virtual Time GetStartTime() const { ThrowUnsupported(); return 0; }
+		virtual Time GetEndTime() const { ThrowUnsupported(); return 0; }
+		virtual int GetStartFrame() const { ThrowUnsupported(); return 0; }
+		virtual int GetEndFrame() const { ThrowUnsupported(); return 0; }
+
+		// Write acessors
+		virtual void SetText(String text) { (void) text; ThrowUnsupported(); }
+		virtual void SetStartTime(Time start) { (void) start; ThrowUnsupported(); }
+		virtual void SetEndTime(Time end) { (void) end; ThrowUnsupported(); }
+		virtual void SetStartFrame(int start) { (void) start; ThrowUnsupported(); }
+		virtual void SetEndFrame(int end) { (void) end; ThrowUnsupported(); }
+	};
+
+};
diff --git a/aegilib/include/aegilib/time.h b/aegilib/include/aegilib/time.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca59747035cd153673f62b987fb6c707d1c4e5ac
--- /dev/null
+++ b/aegilib/include/aegilib/time.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * 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.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+#pragma once
+
+namespace Aegilib {
+
+	// Time class
+	class Time {
+	private:
+		int ms;
+
+	public:
+		Time() { ms = 0; }
+		Time(int ms) { (void)ms; }
+	};
+
+};
diff --git a/aegilib/src/exception.cpp b/aegilib/src/exception.cpp
index 8685cc72c597e1e4f60dbc6ae75a0a0752cfb4ac..2620b1f1c8f800c55736bc7dc07dd35b34372944 100644
--- a/aegilib/src/exception.cpp
+++ b/aegilib/src/exception.cpp
@@ -53,6 +53,10 @@ String Exception::GetMessage()
 		case Unknown: return L"Unknown.";
 		case No_Format_Handler: return L"Could not find a suitable format handler.";
 		case Invalid_Manipulator: return L"Invalid manipulator.";
+		case Section_Already_Exists: return L"The specified section already exists in this model.";
+		case Unknown_Format: return L"The specified file format is unknown.";
+		case Parse_Error: return L"Parse error.";
+		case Unsupported_Format_Feature: return L"This feature is not supported by this format.";
 	}
 	return L"Invalid code.";
 }
diff --git a/aegilib/src/format_manager.cpp b/aegilib/src/format_manager.cpp
index f6a35ab76b860bce6ef9194a2aecd2fcb478f681..84c9fb7d5f73c82545c566fc85214e125548a86e 100644
--- a/aegilib/src/format_manager.cpp
+++ b/aegilib/src/format_manager.cpp
@@ -91,11 +91,17 @@ const Format* FormatManager::GetFormatByIndex(const int index)
 
 ///////////////
 // By filename
-const Format* FormatManager::GetFormatFromFilename(const String &filename)
+const Format* FormatManager::GetFormatFromFilename(const String &filename,bool read)
 {
 	size_t len = formats.size();
 	for (size_t i=0;i<len;i++) {
-		if (filename.EndsWith(formats[i]->GetExtension())) return formats[i];
+		StringArray exts;
+		if (read) exts = formats[i]->GetReadExtensions();
+		else exts = formats[i]->GetWriteExtensions();
+		size_t extn = exts.size();
+		for (size_t j=0;j<extn;j++) {
+			if (filename.EndsWith(exts[j])) return formats[i];
+		}
 	}
 	return NULL;
 }
diff --git a/aegilib/src/formats/format_ass.cpp b/aegilib/src/formats/format_ass.cpp
index f1f346669577c3f7bb6cdd933f1f5049bd24c28a..2b1f54f42ae25cacee88d637a6dca79d2c6949e5 100644
--- a/aegilib/src/formats/format_ass.cpp
+++ b/aegilib/src/formats/format_ass.cpp
@@ -37,14 +37,30 @@
 #include "format_ass.h"
 #include "../text_file_reader.h"
 #include <iostream>
+#include <wx/tokenzr.h>
 using namespace Aegilib;
 
 
+//////////////
+// Extensions
+StringArray FormatASS::GetReadExtensions() const
+{
+	StringArray final;
+	final.push_back(L".ass");
+	final.push_back(L".ssa");
+	return final;
+}
+StringArray FormatASS::GetWriteExtensions() const
+{
+	return GetReadExtensions();
+}
+
+
 ///////////////
 // Constructor
-FormatHandlerASS::FormatHandlerASS(const Model &model)
+FormatHandlerASS::FormatHandlerASS(Model &_model)
+: model(_model)
 {
-	(void) model;
 }
 
 
@@ -61,11 +77,288 @@ 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"-";
+	wxString prevGroup = L"-";
+	Section *section = NULL;
+
+	// Read file
 	while (reader.HasMoreLines()) {
+		// Read a line
 		wxString cur = reader.ReadLineFromFile();
-		cout << cur.mb_str(wxConvUTF8) << endl;
+
+		// Process group
+		prevGroup = curGroup;
+		ProcessGroup(cur,curGroup,version);
+
+		// Insert group if it doesn't already exist
+		if (prevGroup != curGroup) section = model.GetSection(curGroup);
+		if (!section) {
+			model.AddSection(curGroup);
+			section = model.GetSection(curGroup);
+		}
+
+		// Skip [] lines
+		if (cur[0] == L'[') continue;
+
+		// Create and insert line
+		SectionEntry *entry = MakeEntry(cur,curGroup,version);
+		//if (!entry) throw Exception(Exception::Parse_Error);
+		section->AddEntry(entry);
+	}
+
+	// Debug
+	cout << "\nFinished reading file with version=" << version << ".\n\n";
+}
+
+
+///////////////
+// Create line
+SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
+{
+	// Variables
+	SectionEntry *final = NULL;
+
+	// Attachments
+	if (group == _T("Fonts") || group == _T("Graphics")) {
+		// TODO
+	}
+
+	// Events
+	else if (group == _T("Events")) {
+		// Dialogue lines
+		if ((data.Left(9) == _T("Dialogue:") || data.Left(8) == _T("Comment:"))) {
+			DialogueASS *diag = new DialogueASS(data,version);
+			final = diag;
+
+			// Debug
+			std::cout << "[" << group.mb_str(wxConvUTF8) << "] " << diag->GetText().mb_str(wxConvUTF8) << std::endl;
+		}
+
+		// Format lines
+		else if (data.Left(7) == _T("Format:")) {
+			// TODO
+			//entry = new AssEntry(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"));
+		}
+
+		// Garbage
+		else {
+			// TODO
+		}
+	}
+
+	// Styles
+	else if (group == _T("V4+ Styles")) {
+		// TODO
 	}
+
+	// Script info
+	else if (group == _T("Script Info")) {
+		// TODO
+	}
+
+	// Return entry
+	return final;
+}
+
+
+//////////////////////
+// Process group data
+void FormatHandlerASS::ProcessGroup(String cur,String &curGroup,int &version) {
+	// Style conversion
+	if (!cur.IsEmpty() && cur[0] == '[') {
+		wxString low = cur.Lower();
+		bool changed = true;
+
+		// SSA file
+		if (low == _T("[v4 styles]")) {
+			cur = _T("[V4+ Styles]");
+			curGroup = cur;
+			version = 0;
+		}
+
+		// ASS file
+		else if (low == _T("[v4+ styles]")) {
+			curGroup = cur;
+			version = 1;
+		}
+
+		// ASS2 file
+		else if (low == _T("[v4++ styles]")) {
+			cur = _T("[V4+ Styles]");
+			curGroup = cur;
+			version = 2;
+		}
+
+		// Other groups
+		else {
+			wxString temp = cur;
+			temp.Trim(true).Trim(false);
+			if (temp[temp.Length()-1] == ']') curGroup = cur;
+			else changed = false;
+		}
+
+		// Normalize group name
+		if (changed) {
+			// Get rid of []
+			curGroup = curGroup.Mid(1,curGroup.Length()-2);
+			
+			// Normalize case
+			curGroup.MakeLower();
+			wxString upper = curGroup.Upper();
+			bool raise = true;
+			size_t len = curGroup.Length();
+			for (size_t i=0;i<len;i++) {
+				if (raise) {
+					curGroup[i] = upper[i];
+					raise = false;
+				}
+				if (curGroup[i] == L' ') raise = true;
+			}
+		}
+	}
+
+	// Update version with version line
+	if (curGroup == _T("Script Info")) {
+		if (cur.Left(11).Lower() == _T("scripttype:")) {
+			wxString versionString = cur.Mid(11);
+			versionString.Trim(true);
+			versionString.Trim(false);
+			versionString.MakeLower();
+			int trueVersion;
+			if (versionString == _T("v4.00")) trueVersion = 0;
+			else if (versionString == _T("v4.00+")) trueVersion = 1;
+			else if (versionString == _T("v4.00++")) trueVersion = 2;
+			else throw Exception(Exception::Unknown_Format);
+			if (trueVersion != version) {
+				// TODO: issue warning?
+				version = trueVersion;
+			}
+		}
+	}
+}
+
+
+////////////////////////////
+// ASS dialogue constructor
+DialogueASS::DialogueASS(String data,int version)
+{
+	// Try parsing with all different versions
+	bool valid = false;
+	for (int count=0;!valid && count < 3;count++) {
+		valid = Parse(data,version);
+		version++;
+		if (version > 2) version = 0;
+	}
+}
+
+
+//////////////////
+// Parse ASS Data
+bool DialogueASS::Parse(wxString rawData, int version)
+{
+	size_t pos = 0;
+	wxString temp;
+
+	// Get type
+	if (rawData.StartsWith(_T("Dialogue:"))) {
+		comment = false;
+		pos = 10;
+	}
+	else if (rawData.StartsWith(_T("Comment:"))) {
+		comment = true;
+		pos = 9;
+	}
+	else return false;
+
+	wxStringTokenizer tkn(rawData.Mid(pos),_T(","),wxTOKEN_RET_EMPTY_ALL);
+	if (!tkn.HasMoreTokens()) return false;
+
+	// Get first token and see if it has "Marked=" in it
+	temp = tkn.GetNextToken().Trim(false).Trim(true);
+	if (temp.Lower().StartsWith(_T("marked="))) version = 0;
+	else if (version == 0) version = 1;
+
+	// Get layer number
+	if (version == 0) layer = 0;
+	else {
+		long templ;
+		temp.ToLong(&templ);
+		layer = templ;
+	}
+
+	// Get start time
+	if (!tkn.HasMoreTokens()) return false;
+	start = ParseTime(tkn.GetNextToken());
+
+	// Get end time
+	if (!tkn.HasMoreTokens()) return false;
+	end = ParseTime(tkn.GetNextToken());
+
+	// Get style
+	if (!tkn.HasMoreTokens()) return false;
+	style = tkn.GetNextToken();
+	style.Trim(true);
+	style.Trim(false);
+
+	// Get actor
+	if (!tkn.HasMoreTokens()) return false;
+	actor = tkn.GetNextToken();
+	actor.Trim(true);
+	actor.Trim(false);
+
+	// Get margins
+	for (int i=0;i<3;i++) {
+		if (!tkn.HasMoreTokens()) return false;
+		long templ;
+		tkn.GetNextToken().Trim(false).Trim(true).ToLong(&templ);
+		margin[i] = templ;
+	}
+
+	// Get bottom margin
+	if (version == 1) margin[3] = margin[2];
+	bool rollBack = false;
+	if (version == 2) {
+		if (!tkn.HasMoreTokens()) return false;
+		wxString oldTemp = temp;
+		temp = tkn.GetNextToken().Trim(false).Trim(true);
+		if (!temp.IsNumber()) {
+			version = 1;
+			rollBack = true;
+		}
+		else {
+			long templ;
+			temp.ToLong(&templ);
+			margin[3] = templ;
+		}
+	}
+
+	// Get effect
+	if (!rollBack) {
+		if (!tkn.HasMoreTokens()) return false;
+		temp = tkn.GetNextToken();
+	}
+	effect = temp;
+	effect.Trim(true);
+	effect.Trim(false);
+
+	// Get text
+	text = rawData.Mid(pos+tkn.GetPosition());
+
+	return true;
+}
+
+
+/////////////////////
+// Parse time string
+Time DialogueASS::ParseTime(String time)
+{
+	(void) time;
+	return 0;
 }
diff --git a/aegilib/src/formats/format_ass.h b/aegilib/src/formats/format_ass.h
index de97952539920d8c80174eb1ba89e0598ed37cab..16dac9de772178077edf2bb7bfb1e1c673a81a39 100644
--- a/aegilib/src/formats/format_ass.h
+++ b/aegilib/src/formats/format_ass.h
@@ -36,6 +36,8 @@
 #pragma once
 #include "format.h"
 #include "format_handler.h"
+#include "section.h"
+#include "section_entry_dialogue.h"
 
 namespace Aegilib {
 
@@ -44,8 +46,13 @@ namespace Aegilib {
 
 	// Advanced Substation Alpha format handler
 	class FormatHandlerASS : public FormatHandler {
+	private:
+		SectionEntry *MakeEntry(String data,String group,int version);
+		void ProcessGroup(String cur,String &curGroup,int &version);
+		Model &model;
+
 	public:
-		FormatHandlerASS(const Model &model);
+		FormatHandlerASS(Model &model);
 		~FormatHandlerASS();
 
 		void Load(wxInputStream &file,const String encoding);
@@ -55,8 +62,9 @@ namespace Aegilib {
 	class FormatASS : public Format {
 	public:
 		String GetName() const { return L"Advanced Substation Alpha"; }
-		String GetExtension() const { return L".ass"; }
-		FormatHandler* GetHandler(const Model &model) const { return new FormatHandlerASS(model); }
+		StringArray GetReadExtensions() const;
+		StringArray GetWriteExtensions() const;
+		FormatHandler* GetHandler(Model &model) const { return new FormatHandlerASS(model); }
 
 		bool CanStoreText() const { return true; }
 		bool CanUseTime() const { return true; }
@@ -66,4 +74,41 @@ namespace Aegilib {
 		bool HasActors() const { return true; }
 	};
 
+	// Dialogue
+	class DialogueASS : public SectionEntryDialogue {
+	private:
+		String text;
+		String style;
+		String effect;
+		String actor;
+		Time start,end;
+		int margin[4];
+		int layer;
+		bool comment;
+
+		bool Parse(String data,int version);
+		Time ParseTime(String data);
+
+	public:
+		// Constructors
+		DialogueASS() {}
+		DialogueASS(String data,int version);
+
+		// Capabilities
+		bool HasText() const { return true; }
+		bool HasTime() const { return true; }
+		bool HasStyle() const { return true; }
+		bool HasMargins() const { return true; }
+
+		// Read accessors
+		String GetText() const { return text; }
+		Time GetStartTime() const { return start; }
+		Time GetEndTime() const { return end; }
+
+		// Write acessors
+		void SetText(String setText) { text = setText; }
+		void SetStartTime(Time setStart) { start = setStart; }
+		void SetEndTime(Time setEnd) { end = setEnd; }
+	};
+
 };
diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp
index df2aaa8891f9ec17f0617deeb5cc64d0342dc669..4b5f8685f5ea6e57c1b7c475c9127d0e70ad971d 100644
--- a/aegilib/src/model.cpp
+++ b/aegilib/src/model.cpp
@@ -117,3 +117,25 @@ void Model::SaveFile(wxOutputStream &output,const Format *format,const String en
 	(void) encoding;
 	// TODO
 }
+
+
+//////////////////
+// Gets a section
+Section* Model::GetSection(String name) const
+{
+	std::list<Section*>::const_iterator cur;
+	for (cur=sections.begin();cur!=sections.end();cur++) {
+		if ((*cur)->GetName() == name) return *cur;
+	}
+	return NULL;
+}
+
+
+/////////////////////////
+// Inserts a new section
+void Model::AddSection(String name)
+{
+	Section *prev = GetSection(name);
+	if (prev) throw Exception(Exception::Section_Already_Exists);
+	sections.push_back(new Section(name));
+}
diff --git a/aegilib/src/section.cpp b/aegilib/src/section.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eda6f86fb694a6b15e58f96df0abcedd2199f556
--- /dev/null
+++ b/aegilib/src/section.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * 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.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+
+#include "section.h"
+using namespace Aegilib;
+
+
+///////////////
+// Constructor
+Section::Section(String _name)
+{
+	name = _name;
+}
+
+
+//////////////
+// Destructor
+Section::~Section()
+{
+}
+
+
+///////////////////
+// Append an entry
+void Section::AddEntry(SectionEntry *entry)
+{
+	entries.push_back(entry);
+}
diff --git a/aegilib/test/src/main.cpp b/aegilib/test/src/main.cpp
index 54e946c7d977be1ca1baae77fb463573297fc5f2..8dfdbde5d57d661af072189f015f2b5df04265de 100644
--- a/aegilib/test/src/main.cpp
+++ b/aegilib/test/src/main.cpp
@@ -55,8 +55,8 @@ int main () {
 		// Load subtitles
 		cout << "Loading file... ";
 		String filename = L"subs_in.ass";
-		const Format *handler = FormatManager::GetFormatFromFilename(filename);
-		subs.LoadFile(wxFileInputStream(filename),handler);
+		const Format *handler = FormatManager::GetFormatFromFilename(filename,true);
+		subs.LoadFile(wxFileInputStream(filename),handler,L"UTF-8");
 		cout << "Done.\n";
 
 		// Modify subtitles
@@ -66,7 +66,7 @@ int main () {
 		// Save subtitles
 		cout << "Saving file... ";
 		filename = L"subs_out.ass";
-		handler = FormatManager::GetFormatFromFilename(filename);
+		handler = FormatManager::GetFormatFromFilename(filename,false);
 		subs.SaveFile(wxFileOutputStream(filename),handler);
 		cout << "Done.\n";
 	}
diff --git a/build/aegisub_vs2005/aegisub_vs2005.vcproj b/build/aegisub_vs2005/aegisub_vs2005.vcproj
index 1c2368239a4765e9397cc661a8e147480a26185a..cfa4d72bb0a7117671c2434b63bc2910fc06d4b0 100644
--- a/build/aegisub_vs2005/aegisub_vs2005.vcproj
+++ b/build/aegisub_vs2005/aegisub_vs2005.vcproj
@@ -487,122 +487,6 @@
 				RelativePath="..\..\aegisub\audio_karaoke.h"
 				>
 			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_alsa.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_alsa.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_dsound.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_dsound.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_manager.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_openal.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_openal.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_portaudio.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_portaudio.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_pulse.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_player_pulse.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_avs.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_avs.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_convert.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_convert.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_dummy.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_dummy.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_hd.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_hd.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_lavc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_lavc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_pcm.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_pcm.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_ram.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_ram.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_stream.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\audio_provider_stream.h"
-				>
-			</File>
 			<File
 				RelativePath="..\..\aegisub\audio_spectrum.cpp"
 				>
@@ -611,6 +495,130 @@
 				RelativePath="..\..\aegisub\audio_spectrum.h"
 				>
 			</File>
+			<Filter
+				Name="Providers"
+				>
+				<File
+					RelativePath="..\..\aegisub\audio_provider.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_avs.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_avs.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_convert.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_convert.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_dummy.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_dummy.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_hd.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_hd.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_lavc.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_lavc.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_pcm.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_pcm.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_ram.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_ram.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_stream.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_provider_stream.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Players"
+				>
+				<File
+					RelativePath="..\..\aegisub\audio_player.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_alsa.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_alsa.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_dsound.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_dsound.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_manager.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_openal.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_openal.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_portaudio.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_portaudio.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_pulse.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\audio_player_pulse.h"
+					>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="Automation"
@@ -1603,42 +1611,6 @@
 				RelativePath="..\..\aegisub\video_frame.h"
 				>
 			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_avs.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_cache.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_cache.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_dshow.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_dummy.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_dummy.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_lavc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\aegisub\video_provider_manager.cpp"
-				>
-			</File>
 			<File
 				RelativePath="..\..\aegisub\video_slider.cpp"
 				>
@@ -1647,6 +1619,54 @@
 				RelativePath="..\..\aegisub\video_slider.h"
 				>
 			</File>
+			<Filter
+				Name="Providers"
+				>
+				<File
+					RelativePath="..\..\aegisub\video_provider_avs.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_avs.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_cache.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_cache.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_dshow.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_dummy.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_dummy.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_lavc.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_lavc.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_manager.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\aegisub\video_provider_manager.h"
+					>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="Spellchecking"
@@ -1656,11 +1676,11 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\aegisub\spellchecker.h"
+				RelativePath="..\..\aegisub\spellchecker_hunspell.cpp"
 				>
 			</File>
 			<File
-				RelativePath="..\..\aegisub\spellchecker_hunspell.cpp"
+				RelativePath="..\..\aegisub\spellchecker_hunspell.h"
 				>
 			</File>
 			<File
@@ -1772,17 +1792,25 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\aegisub\subtitles_provider.h"
+				RelativePath="..\..\aegisub\subtitles_provider_csri.cpp"
 				>
 			</File>
 			<File
-				RelativePath="..\..\aegisub\subtitles_provider_csri.cpp"
+				RelativePath="..\..\aegisub\subtitles_provider_csri.h"
 				>
 			</File>
 			<File
 				RelativePath="..\..\aegisub\subtitles_provider_libass.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\aegisub\subtitles_provider_libass.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\aegisub\subtitles_provider_manager.h"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Visual Tools"