diff --git a/athenasub/athenasub_2008.vcproj b/athenasub/athenasub_2008.vcproj
index e23a03936ead346372763c70040642558e106d9a..9bc5a25467298f3251734652b2e3e498dbaa0bd8 100644
--- a/athenasub/athenasub_2008.vcproj
+++ b/athenasub/athenasub_2008.vcproj
@@ -467,6 +467,22 @@
 				RelativePath=".\src\text_file_writer.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\text_reader.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\text_reader.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\text_writer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\text_writer.h"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>
diff --git a/athenasub/src/formats/format_ass.cpp b/athenasub/src/formats/format_ass.cpp
index 8c9f06b704816b9ef4f1618228c50d484b98f786..9a99aecb4256edc2de7bece23ebcd1d73542be86 100644
--- a/athenasub/src/formats/format_ass.cpp
+++ b/athenasub/src/formats/format_ass.cpp
@@ -38,8 +38,8 @@
 #include "format_ass.h"
 #include "format_ass_plain.h"
 #include "version.h"
-#include "../text_file_reader.h"
-#include "../text_file_writer.h"
+#include "../text_reader.h"
+#include "../text_writer.h"
 #include <iostream>
 #include <algorithm>
 #include <wx/tokenzr.h>
@@ -108,7 +108,7 @@ FormatHandlerASS::~FormatHandlerASS()
 void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encoding)
 {
 	// Make text file reader
-	TextFileReader reader(file,encoding);
+	shared_ptr<TextReader> reader = TextReader::GetReader(file,encoding);
 
 	// Variables
 	int version = 1;
@@ -117,9 +117,9 @@ void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encod
 	Section section = Section();
 
 	// Read file
-	while (reader.HasMoreLines()) {
+	while (reader->HasMoreLines()) {
 		// Read a line
-		String cur = reader.ReadLineFromFile();
+		String cur = reader->ReadLineFromFile();
 		if (cur.IsEmpty()) continue;
 
 		// Process group
@@ -151,7 +151,7 @@ void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encod
 void FormatHandlerASS::Save(const IModel& model,wxOutputStream &file,const String encoding) const
 {
 	// Make text file writer
-	TextFileWriter writer(file,encoding);
+	shared_ptr<TextWriter> writer = TextWriter::GetWriter(file,encoding);
 
 	// Set up list of sections to write
 	StringArray sections;
@@ -178,7 +178,7 @@ void FormatHandlerASS::Save(const IModel& model,wxOutputStream &file,const Strin
 		ConstSection section = GetSection(model,sections[i]);
 		if (section) {
 			// Add a spacer
-			if (i != 0) writer.WriteLineToFile("");
+			if (i != 0) writer->WriteLineToFile("");
 
 			// Write the section
 			WriteSection(writer,section);
@@ -334,11 +334,11 @@ void FormatHandlerASS::ProcessGroup(String cur,String &curGroup,int &version) {
 
 ///////////////////////////////
 // Write a section to the file
-void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section) const
+void FormatHandlerASS::WriteSection(shared_ptr<TextWriter> writer,ConstSection section) const
 {
 	// Write name
 	String name = section->GetName();
-	writer.WriteLineToFile("[" + name + "]");
+	writer->WriteLineToFile("[" + name + "]");
 
 	// Write program and library credits
 	if (name == "Script Info") {
@@ -346,17 +346,17 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section)
 		String programURL = GetHostApplicationURL();
 		String libVersion = GetLibraryVersionString();
 		String libURL = GetLibraryURL();
-		writer.WriteLineToFile("; Script generated by " + programName);
-		if (!programURL.IsEmpty()) writer.WriteLineToFile("; " + programURL);
-		writer.WriteLineToFile("; With " + libVersion);
-		if (programURL != libURL) writer.WriteLineToFile("; " + libURL);
+		writer->WriteLineToFile("; Script generated by " + programName);
+		if (!programURL.IsEmpty()) writer->WriteLineToFile("; " + programURL);
+		writer->WriteLineToFile("; With " + libVersion);
+		if (programURL != libURL) writer->WriteLineToFile("; " + libURL);
 	}
 
 	// Write properties
 	size_t props = section->GetPropertyCount();
 	for (size_t i=0;i<props;i++) {
 		String propName = section->GetPropertyName(i);
-		writer.WriteLineToFile(propName + ": " + section->GetProperty(propName));
+		writer->WriteLineToFile(propName + ": " + section->GetProperty(propName));
 	}
 
 	// Write contents
@@ -364,7 +364,7 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section)
 	for (size_t i=0;i<entries;i++) {
 		ConstEntry entry = section->GetEntry(i);
 		shared_ptr<const SerializeText> serial = dynamic_pointer_cast<const SerializeText>(entry);
-		writer.WriteLineToFile(serial->ToText(formatVersion));
+		writer->WriteLineToFile(serial->ToText(formatVersion));
 	}
 }
 
diff --git a/athenasub/src/formats/format_ass.h b/athenasub/src/formats/format_ass.h
index f89be1d38c6c1f53336e3488c7706bb6b01a97f3..374a842209220012f7c0c4999f58d40d6c315cfc 100644
--- a/athenasub/src/formats/format_ass.h
+++ b/athenasub/src/formats/format_ass.h
@@ -46,7 +46,7 @@ namespace Athenasub {
 
 	// Prototypes
 	class CModel;
-	class TextFileWriter;
+	class TextWriter;
 
 	// Advanced Substation Alpha format handler
 	class FormatHandlerASS : public CFormatHandler {
@@ -55,7 +55,7 @@ namespace Athenasub {
 
 		Entry MakeEntry(const String &data,Section section,int version);
 		void ProcessGroup(String cur,String &curGroup,int &version);
-		void WriteSection(TextFileWriter &writer,ConstSection section) const;
+		void WriteSection(shared_ptr<TextWriter> writer,ConstSection section) const;
 		void MakeValid(IModel &model);
 
 	public:
diff --git a/athenasub/src/text_file_reader.cpp b/athenasub/src/text_file_reader.cpp
index f5fb59bedfb8c4176b39262b7181742ad798fd3a..128f9b75516a5197606c708cf5e29e0dd5b01463 100644
--- a/athenasub/src/text_file_reader.cpp
+++ b/athenasub/src/text_file_reader.cpp
@@ -49,13 +49,11 @@ using namespace Athenasub;
 
 ///////////////
 // Constructor
-TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim,bool prefetch)
+TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim)
 : file(stream)
 {
 	// Setup
 	trim = _trim;
-	threaded = prefetch && false;
-	thread = NULL;
 
 	// Set encoding
 	encoding = enc.GetWxString();
@@ -68,8 +66,6 @@ TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim,bool
 // Destructor
 TextFileReader::~TextFileReader()
 {
-	wxCriticalSectionLocker locker(mutex);
-	if (thread) thread->Delete();
 }
 
 
@@ -191,7 +187,7 @@ void ParseLine(FastBuffer<T> &_buffer,wxInputStream &file,String &stringBuffer,s
 
 //////////////////////////
 // Reads a line from file
-Athenasub::String TextFileReader::ActuallyReadLine()
+Athenasub::String TextFileReader::ReadLineFromFile()
 {
 	String stringBuffer;
 	size_t bufAlloc = 1024;
@@ -225,8 +221,6 @@ Athenasub::String TextFileReader::ActuallyReadLine()
 // Checks if there's more to read
 bool TextFileReader::HasMoreLines()
 {
-	if (cache.size()) return true;
-	wxCriticalSectionLocker locker(mutex);
 	return (!file.Eof() || buffer1.GetSize() || buffer2.GetSize());
 }
 
@@ -252,68 +246,9 @@ String TextFileReader::GetCurrentEncoding()
 }
 
 
-///////////////////////////
-// Reads a line from cache
-String TextFileReader::ReadLineFromFile()
-{
-	// Not threaded, just return it
-	if (!threaded) return ActuallyReadLine();
-
-	// Load into cache if needed
-	String final;
-	{
-		wxCriticalSectionLocker locker(mutex);
-		if (cache.size() == 0) {
-			cache.push_back(ActuallyReadLine());
-		}
-	}
-
-	{
-		// Retrieve from cache
-		wxCriticalSectionLocker locker(mutex);
-		if (cache.size()) {
-			final = cache.front();
-			cache.pop_front();
-		}
-
-		// Start the thread to prefetch more
-		if (cache.size() < 3 && thread == NULL) {
-			thread = new PrefetchThread(this);
-			thread->Create();
-			thread->Run();
-		}
-	}
-
-	return final;
-}
-
-
-////////////////
-// Thread entry
-wxThread::ExitCode PrefetchThread::Entry()
+///////////////////
+// Rewind the file
+void TextFileReader::Rewind()
 {
-	// Lock
-	bool run = true;
-	while (run) {
-		if (TestDestroy()) {
-			parent->thread = NULL;
-			return 0;
-		}
-		{
-			wxCriticalSectionLocker locker(parent->mutex);
-			if (parent->cache.size() < 6) {
-				if (!parent->file.Eof()) {
-					// Get line
-					parent->cache.push_back(parent->ActuallyReadLine());
-				}
-				else run = false;
-			}
-		}
-		Sleep(50);
-	}
 
-	// Die
-	wxCriticalSectionLocker locker(parent->mutex);
-	parent->thread = NULL;
-	return 0;
 }
diff --git a/athenasub/src/text_file_reader.h b/athenasub/src/text_file_reader.h
index 7fe784d8a1b6b641dba9573b6c67c5ab1a086845..5139c7c8cb563a49ad0caf37b394c941985dec60 100644
--- a/athenasub/src/text_file_reader.h
+++ b/athenasub/src/text_file_reader.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2005, Rodrigo Braz Monteiro
+// Copyright (c) 2008, Rodrigo Braz Monteiro
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -39,19 +39,15 @@
 
 // Headers
 #include "athenasub.h"
+#include "text_reader.h"
 #include "fastbuffer.h"
-#include <wx/stream.h>
 
 
 namespace Athenasub {
 
 	// Text file reader
-	class TextFileReader {
-		friend class PrefetchThread;
+	class TextFileReader : public TextReader {
 	private:
-		wxCriticalSection mutex;
-
-		std::list<String> cache;
 		FastBuffer<char> buffer1;
 		FastBuffer<wchar_t> buffer2;
 
@@ -62,33 +58,21 @@ namespace Athenasub {
 		bool isUtf8;
 		bool swap;
 		bool trim;
-		bool threaded;
-		wxThread *thread;
 
 		void SetEncodingConfiguration();
-		String ActuallyReadLine();
 
 	public:
-		TextFileReader(wxInputStream &stream,String encoding="",bool trim=true,bool prefetch=true);
+		TextFileReader(wxInputStream &stream,String encoding="",bool trim=true);
 		~TextFileReader();
 
 		String ReadLineFromFile();
 		bool HasMoreLines();
+		void Rewind();
 
 		static void EnsureValid(const String encoding);
 		String GetCurrentEncoding();
 		static String GetEncoding(const String filename);
 	};
 
-	// Prefetch thread
-	class PrefetchThread : public wxThread {
-	private:
-		TextFileReader *parent;
-
-	public:
-		wxThread::ExitCode Entry();
-		PrefetchThread(TextFileReader *_parent) : parent(_parent) {}
-	};
-
 }
 
diff --git a/athenasub/src/text_file_writer.h b/athenasub/src/text_file_writer.h
index 45606f644d177cbf0bdf8ed97343366306849fcf..30d6650a0fccbe0c5d272d671d18860ec84bd556 100644
--- a/athenasub/src/text_file_writer.h
+++ b/athenasub/src/text_file_writer.h
@@ -35,12 +35,13 @@
 
 
 #pragma once
-#include "Athenasub.h"
+#include "athenasub.h"
+#include "text_writer.h"
 #include <wx/stream.h>
 
 
 namespace Athenasub {
-	class TextFileWriter {
+	class TextFileWriter : public TextWriter {
 	private:
 		wxString encoding;
 		wxOutputStream &file;
diff --git a/athenasub/src/text_reader.cpp b/athenasub/src/text_reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6dc0888fc543507ba0ef2314b5c195492393d28
--- /dev/null
+++ b/athenasub/src/text_reader.cpp
@@ -0,0 +1,45 @@
+// 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
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+// Headers
+#include "text_reader.h"
+#include "text_file_reader.h"
+using namespace Athenasub;
+
+shared_ptr<TextReader> TextReader::GetReader(wxInputStream &stream,String encoding)
+{
+	return shared_ptr<TextReader>(new TextFileReader(stream,encoding));
+}
\ No newline at end of file
diff --git a/athenasub/src/text_reader.h b/athenasub/src/text_reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..952697ea87d8ef401e5fa959c590f9cb6f855a1a
--- /dev/null
+++ b/athenasub/src/text_reader.h
@@ -0,0 +1,55 @@
+// 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
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#pragma once
+
+
+// Headers
+#include "athenasub.h"
+
+
+namespace Athenasub {
+	class TextReader {
+	public:
+		virtual ~TextReader() {}
+
+		virtual String ReadLineFromFile() = 0;
+		virtual bool HasMoreLines() = 0;
+		virtual void Rewind() = 0;
+
+		static shared_ptr<TextReader> GetReader(wxInputStream &stream,String encoding);
+	};
+}
diff --git a/athenasub/src/text_writer.cpp b/athenasub/src/text_writer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..08b1048cc615d3ef1d04ad7119aa3ce144ea3577
--- /dev/null
+++ b/athenasub/src/text_writer.cpp
@@ -0,0 +1,45 @@
+// 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
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+// Headers
+#include "text_writer.h"
+#include "text_file_writer.h"
+using namespace Athenasub;
+
+shared_ptr<TextWriter> TextWriter::GetWriter(wxOutputStream &stream,String encoding)
+{
+	return shared_ptr<TextWriter>(new TextFileWriter(stream,encoding));
+}
\ No newline at end of file
diff --git a/athenasub/src/text_writer.h b/athenasub/src/text_writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..43dac49dd06f9863adb66db160a3b25927c86757
--- /dev/null
+++ b/athenasub/src/text_writer.h
@@ -0,0 +1,53 @@
+// 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
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#pragma once
+
+
+// Headers
+#include "athenasub.h"
+
+
+namespace Athenasub {
+	class TextWriter {
+	public:
+		virtual ~TextWriter() {}
+
+		virtual void WriteLineToFile(String line,bool addLineBreak=true) = 0;
+
+		static shared_ptr<TextWriter> GetWriter(wxOutputStream &stream,String encoding);
+	};
+}