Index: common/FileReader.cpp
===================================================================
--- common/FileReader.cpp	(revision 13999)
+++ common/FileReader.cpp	(working copy)
@@ -45,7 +45,7 @@
 
 #ifdef MPT_ONDISKFILEWRAPPER_NO_CREATEFILE
 
-			mpt::ofstream f(tempName, std::ios::binary);
+			std::ofstream f(tempName, std::ios::binary);
 			if(!f)
 			{
 				throw std::runtime_error("Error creating temporary file.");
Index: common/Logging.cpp
===================================================================
--- common/Logging.cpp	(revision 13999)
+++ common/Logging.cpp	(working copy)
@@ -125,7 +125,7 @@
 #endif
 		if(mpt::log::FileEnabled)
 		{
-			static std::optional<mpt::ofstream> s_logfile;
+			static std::optional<std::ofstream> s_logfile;
 			if(!s_logfile)
 			{
 				s_logfile.emplace(P_("mptrack.log"), std::ios::app);
@@ -315,7 +315,7 @@
 	// sort according to index in case of overflows
 	std::stable_sort(Entries.begin(), Entries.end());
 
-	mpt::ofstream f(filename);
+	std::ofstream f(filename);
 
 	f << "Build: OpenMPT " << mpt::ToCharset(mpt::CharsetLogfile, Build::GetVersionStringExtended()) << std::endl;
 
Index: common/mptFileIO.cpp
===================================================================
--- common/mptFileIO.cpp	(revision 13999)
+++ common/mptFileIO.cpp	(working copy)
@@ -34,18 +34,6 @@
 
 
 
-#if !defined(MPT_BUILD_SILENCE_LIBOPENMPT_CONFIGURATION_WARNINGS)
-
-#if defined(MPT_FSTREAM_NO_WCHAR)
-#if MPT_GCC_BEFORE(9,1,0)
-MPT_WARNING("Warning: MinGW with GCC earlier than 9.1 detected. Standard library does neither provide std::fstream wchar_t overloads nor std::filesystem with wchar_t support. Unicode filename support is thus unavailable.")
-#endif // MPT_GCC_AT_LEAST(9,1,0)
-#endif // MPT_FSTREAM_NO_WCHAR
-
-#endif // !MPT_BUILD_SILENCE_LIBOPENMPT_CONFIGURATION_WARNINGS
-
-
-
 #ifdef MODPLUG_TRACKER
 #if MPT_OS_WINDOWS
 bool SetFilesystemCompression(HANDLE hFile)
@@ -287,7 +275,7 @@
 
 LazyFileRef & LazyFileRef::operator = (const std::vector<std::byte> &data)
 {
-	mpt::ofstream file(m_Filename, std::ios::binary);
+	std::ofstream file(m_Filename, std::ios::binary);
 	file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
 	mpt::IO::WriteRaw(file, mpt::as_span(data));
 	mpt::IO::Flush(file);
@@ -296,7 +284,7 @@
 
 LazyFileRef & LazyFileRef::operator = (const std::vector<char> &data)
 {
-	mpt::ofstream file(m_Filename, std::ios::binary);
+	std::ofstream file(m_Filename, std::ios::binary);
 	file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
 	mpt::IO::WriteRaw(file, mpt::as_span(data));
 	mpt::IO::Flush(file);
@@ -305,7 +293,7 @@
 
 LazyFileRef & LazyFileRef::operator = (const std::string &data)
 {
-	mpt::ofstream file(m_Filename, std::ios::binary);
+	std::ofstream file(m_Filename, std::ios::binary);
 	file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
 	mpt::IO::WriteRaw(file, mpt::as_span(data));
 	mpt::IO::Flush(file);
@@ -314,7 +302,7 @@
 
 LazyFileRef::operator std::vector<std::byte> () const
 {
-	mpt::ifstream file(m_Filename, std::ios::binary);
+	std::ifstream file(m_Filename, std::ios::binary);
 	if(!mpt::IO::IsValid(file))
 	{
 		return std::vector<std::byte>();
@@ -329,7 +317,7 @@
 
 LazyFileRef::operator std::vector<char> () const
 {
-	mpt::ifstream file(m_Filename, std::ios::binary);
+	std::ifstream file(m_Filename, std::ios::binary);
 	if(!mpt::IO::IsValid(file))
 	{
 		return std::vector<char>();
@@ -344,7 +332,7 @@
 
 LazyFileRef::operator std::string () const
 {
-	mpt::ifstream file(m_Filename, std::ios::binary);
+	std::ifstream file(m_Filename, std::ios::binary);
 	if(!mpt::IO::IsValid(file))
 	{
 		return std::string();
Index: common/mptFileIO.h
===================================================================
--- common/mptFileIO.h	(revision 13999)
+++ common/mptFileIO.h	(working copy)
@@ -17,11 +17,6 @@
 #include "../common/mptPathString.h"
 #include "../common/mptIO.h"
 
-#if defined(MPT_FSTREAM_NO_WCHAR)
-#if MPT_GCC_AT_LEAST(9,1,0)
-#include <filesystem>
-#endif // MPT_GCC_AT_LEAST(9,1,0)
-#endif // MPT_FSTREAM_NO_WCHAR
 #include <fstream>
 #include <ios>
 #include <ostream>
@@ -63,117 +58,6 @@
 namespace mpt
 {
 
-namespace detail
-{
-
-template<typename Tbase>
-inline void fstream_open(Tbase & base, const mpt::PathString & filename, std::ios_base::openmode mode)
-{
-	#if defined(MPT_FSTREAM_NO_WCHAR)
-		#if MPT_GCC_AT_LEAST(9,1,0)
-			base.open(static_cast<std::filesystem::path>(filename.AsNative()), mode);
-		#else // !MPT_GCC_AT_LEAST(9,1,0)
-			// Warning: MinGW with GCC earlier than 9.1 detected. Standard library does neither provide std::fstream wchar_t overloads nor std::filesystem with wchar_t support. Unicode filename support is thus unavailable.
-			base.open(mpt::ToCharset(mpt::Charset::Locale, filename.AsNative()).c_str(), mode);
-		#endif // MPT_GCC_AT_LEAST(9,1,0)
-	#else // !MPT_FSTREAM_NO_WCHAR
-		base.open(filename.AsNativePrefixed().c_str(), mode);
-	#endif // MPT_FSTREAM_NO_WCHAR
-}
-
-} // namespace detail
-
-class SafeOutputFile;
-
-// We cannot rely on implicit conversion of mpt::PathString to std::filesystem::path when constructing std::fstream
-// because of broken overload implementation in GCC libstdc++ 8, 9, 10.
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95642
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90704
-
-class fstream
-	: public std::fstream
-{
-private:
-	typedef std::fstream Tbase;
-public:
-	friend SafeOutputFile;
-public:
-	fstream() {}
-	fstream(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-	void open(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-	void open(const char * filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) = delete;
-	void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) = delete;
-#if MPT_OS_WINDOWS
-	void open(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) = delete;
-	void open(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) = delete;
-#endif
-};
-
-class ifstream
-	: public std::ifstream
-{
-private:
-	typedef std::ifstream Tbase;
-public:
-	friend SafeOutputFile;
-public:
-	ifstream() {}
-	ifstream(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::in)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-	void open(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::in)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-	void open(const char * filename, std::ios_base::openmode mode = std::ios_base::in) = delete;
-	void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in) = delete;
-#if MPT_OS_WINDOWS
-	void open(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::in) = delete;
-	void open(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::in) = delete;
-#endif
-};
-
-class ofstream
-	: public std::ofstream
-{
-private:
-	typedef std::ofstream Tbase;
-public:
-	friend SafeOutputFile;
-public:
-	ofstream() {}
-	ofstream(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::out)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-#if MPT_COMPILER_MSVC
-protected:
-	ofstream(FILE * file)
-		: std::ofstream(file)
-	{
-	}
-
-#endif // MPT_COMPILER_MSVC
-public:
-	void open(const mpt::PathString & filename, std::ios_base::openmode mode = std::ios_base::out)
-	{
-		detail::fstream_open<Tbase>(*this, filename, mode);
-	}
-	void open(const char * filename, std::ios_base::openmode mode = std::ios_base::out) = delete;
-	void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::out) = delete;
-#if MPT_OS_WINDOWS
-	void open(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::out) = delete;
-	void open(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::out) = delete;
-#endif
-};
-
 enum class FlushMode
 {
 	None   = 0,  // no explicit flushes at all
@@ -195,7 +79,7 @@
 #if MPT_COMPILER_MSVC
 	std::FILE *m_f = nullptr;
 #endif // MPT_COMPILER_MSVC
-	mpt::ofstream m_s;
+	std::ofstream m_s;
 #if MPT_COMPILER_MSVC
 	static mpt::tstring convert_mode(std::ios_base::openmode mode, FlushMode flushMode);
 	std::FILE * internal_fopen(const mpt::PathString &filename, std::ios_base::openmode mode, FlushMode flushMode);
@@ -212,22 +96,22 @@
 	{
 		if(!stream().is_open())
 		{
-			stream().setstate(mpt::ofstream::failbit);
+			stream().setstate(std::ofstream::failbit);
 		}
 	}
-	mpt::ofstream& stream()
+	std::ofstream& stream()
 	{
 		return m_s;
 	}
-	operator mpt::ofstream& ()
+	operator std::ofstream& ()
 	{
 		return stream();
 	}
-	const mpt::ofstream& stream() const
+	const std::ofstream& stream() const
 	{
 		return m_s;
 	}
-	operator const mpt::ofstream& () const
+	operator const std::ofstream& () const
 	{
 		return stream();
 	}
@@ -279,7 +163,7 @@
 {
 private:
 	mpt::PathString m_Filename;
-	mpt::ifstream m_File;
+	std::ifstream m_File;
 	bool m_IsValid;
 	bool m_IsCached;
 	std::vector<std::byte> m_Cache;
Index: common/mptPathString.cpp
===================================================================
--- common/mptPathString.cpp	(revision 13999)
+++ common/mptPathString.cpp	(working copy)
@@ -34,8 +34,17 @@
 #endif
 #endif
 
+
 OPENMPT_NAMESPACE_BEGIN
 
+
+#if !defined(MPT_BUILD_SILENCE_LIBOPENMPT_CONFIGURATION_WARNINGS)
+#if MPT_GCC_BEFORE(9,1,0) && MPT_OS_WINDOWS && defined(UNICODE) && defined(MPT_FSTREAM_NO_WCHAR)
+MPT_WARNING("Warning: MinGW with GCC earlier than 9.1 detected. Standard library does neither provide std::fstream wchar_t overloads nor std::filesystem with wchar_t support. Unicode filename support is thus unavailable.")
+#endif
+#endif // !MPT_BUILD_SILENCE_LIBOPENMPT_CONFIGURATION_WARNINGS
+
+
 #if MPT_OS_WINDOWS
 
 namespace mpt
Index: common/mptPathString.h
===================================================================
--- common/mptPathString.h	(revision 13999)
+++ common/mptPathString.h	(working copy)
@@ -12,6 +12,9 @@
 
 #include "BuildSettings.h"
 
+#if !MPT_GCC_BEFORE(9,1,0)
+#include <filesystem>
+#endif
 #include <vector>
 
 #include "FlagSet.h"
@@ -28,6 +31,8 @@
 namespace mpt
 {
 
+
+
 #if MPT_OS_WINDOWS
 typedef mpt::winstring RawPathString;
 #else // !MPT_OS_WINDOWS
@@ -103,8 +108,62 @@
 
 	std::size_t Length() const { return path.size(); }
 
+#if MPT_GCC_BEFORE(9,1,0)
 
+	// GCC before 9.1.0 has experimental std::filesystem, which requires linking an additional library.
+	// Avoid it.
 
+#if MPT_OS_WINDOWS
+#if defined(UNICODE) && !defined(MPT_FSTREAM_NO_WCHAR)
+	operator std::wstring() const
+	{
+		return ToWide();	
+	}
+#else
+	operator std::string() const
+	{
+		return ToLocale();	
+	}
+#endif
+#else // !MPT_OS_WINDOWS
+	operator mpt::RawPathString() const
+	{
+		return AsNative();
+	}
+#endif // MPT_OS_WINDOWS
+
+#else // GCC >= 9.1.0 || other
+
+	operator std::filesystem::path() const
+	{
+		return std::filesystem::path{path};	
+	}
+
+	// work-around for GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95642 / https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90704
+	// include work-around also for other compilers.
+	mpt::PathString & make_preferred()
+	{
+		*this = mpt::PathString::FromFsPath(std::filesystem::path{path}.make_preferred());
+		return *this;
+	}
+	mpt::PathString filename() const
+	{
+		return mpt::PathString::FromFsPath(std::filesystem::path{path}.filename());
+	}
+	std::filesystem::path c_str() const
+	{
+		return std::filesystem::path{path};	
+	}
+
+#endif // GCC < 9.1.0
+
+#if MPT_OS_WINDOWS
+	static PathString FromFsPath(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::Locale, path)); }
+	static PathString FromFsPath(const std::wstring &path) { return PathString(mpt::ToWin(path)); }
+#else // !MPT_OS_WINDOWS
+	static PathString FromFsPath(const std::string &path) { return PathString(path); }
+#endif // MPT_OS_WINDOWS
+
 public:
 
 #if MPT_OS_WINDOWS
Index: installer/signtool/signtool.cpp
===================================================================
--- installer/signtool/signtool.cpp	(revision 13999)
+++ installer/signtool/signtool.cpp	(working copy)
@@ -100,7 +100,7 @@
 			mpt::crypto::keystore keystore(mpt::crypto::keystore::domain::user);
 			mpt::crypto::asymmetric::rsassa_pss<>::managed_private_key key(keystore, keyname);
 			mpt::SafeOutputFile sfo(mpt::PathString::FromUnicode(filename));
-			mpt::ofstream & fo = sfo.stream();
+			std::ofstream & fo = sfo.stream();
 			mpt::IO::WriteText(fo, mpt::ToCharset(mpt::Charset::UTF8, key.get_public_key_data().as_jwk()));
 			fo.flush();
 		} else if(args[1] == U_("sign"))
@@ -117,7 +117,7 @@
 			mpt::crypto::asymmetric::rsassa_pss<>::managed_private_key key(keystore, keyname);
 			std::vector<std::byte> data;
 			{
-				mpt::ifstream fi(mpt::PathString::FromUnicode(inputfilename));
+				std::ifstream fi(mpt::PathString::FromUnicode(inputfilename));
 				fi.imbue(std::locale::classic());
 				fi.exceptions(std::ios::badbit);
 				while(!mpt::IO::IsEof(fi))
@@ -133,7 +133,7 @@
 			{
 				std::vector<std::byte> signature = key.sign(mpt::as_span(data));
 				mpt::SafeOutputFile sfo(mpt::PathString::FromUnicode(outputfilename));
-				mpt::ofstream & fo = sfo.stream();
+				std::ofstream & fo = sfo.stream();
 				mpt::IO::WriteRaw(fo, mpt::as_span(signature));
 				fo.flush();
 			} else if(mode == U_("jws_compact"))
@@ -140,7 +140,7 @@
 			{
 				mpt::ustring signature = key.jws_compact_sign(mpt::as_span(data));
 				mpt::SafeOutputFile sfo(mpt::PathString::FromUnicode(outputfilename));
-				mpt::ofstream & fo = sfo.stream();
+				std::ofstream & fo = sfo.stream();
 				mpt::IO::WriteText(fo, mpt::ToCharset(mpt::Charset::UTF8, signature));
 				fo.flush();
 			} else if(mode == U_("jws"))
@@ -147,7 +147,7 @@
 			{
 				mpt::ustring signature = key.jws_sign(mpt::as_span(data));
 				mpt::SafeOutputFile sfo(mpt::PathString::FromUnicode(outputfilename));
-				mpt::ofstream & fo = sfo.stream();
+				std::ofstream & fo = sfo.stream();
 				mpt::IO::WriteText(fo, mpt::ToCharset(mpt::Charset::UTF8, signature));
 				fo.flush();
 			} else
Index: misc/mptWine.cpp
===================================================================
--- misc/mptWine.cpp	(revision 13999)
+++ misc/mptWine.cpp	(working copy)
@@ -260,7 +260,7 @@
 	// write the script to disk
 	mpt::PathString scriptFilenameWindows = dirWindows + P_("script.sh");
 	{
-		mpt::ofstream tempfile(scriptFilenameWindows, std::ios::binary);
+		std::ofstream tempfile(scriptFilenameWindows, std::ios::binary);
 		tempfile << script;
 		tempfile.flush();
 		if(!tempfile)
@@ -280,7 +280,7 @@
 	// create a wrapper that will call the script and gather result.
 	mpt::PathString wrapperstarterFilenameWindows = dirWindows + P_("wrapperstarter.sh");
 	{
-		mpt::ofstream tempfile(wrapperstarterFilenameWindows, std::ios::binary);
+		std::ofstream tempfile(wrapperstarterFilenameWindows, std::ios::binary);
 		std::string wrapperstarterscript;
 		wrapperstarterscript += std::string() + "#!/usr/bin/env sh" "\n";
 		wrapperstarterscript += std::string() + "exec /usr/bin/env sh " + dirPosixEscape + "wrapper.sh" "\n";
@@ -294,7 +294,7 @@
 	mpt::PathString wrapperFilenameWindows = dirWindows + P_("wrapper.sh");
 	std::string cleanupscript;
 	{
-		mpt::ofstream tempfile(wrapperFilenameWindows, std::ios::binary);
+		std::ofstream tempfile(wrapperFilenameWindows, std::ios::binary);
 		std::string wrapperscript;
 		if(!flags[ExecFlagSilent])
 		{
@@ -387,7 +387,7 @@
 	// create a wrapper that will find a suitable terminal and run the wrapper script in the terminal window.
 	mpt::PathString terminalWrapperFilenameWindows = dirWindows + P_("terminal.sh");
 	{
-		mpt::ofstream tempfile(terminalWrapperFilenameWindows, std::ios::binary);
+		std::ofstream tempfile(terminalWrapperFilenameWindows, std::ios::binary);
 		// NOTE:
 		// Modern terminals detach themselves from the invoking shell if another instance is already present.
 		// This means we cannot rely on terminal invocation being syncronous.
@@ -589,7 +589,7 @@
 
 	int exitCode = 0;
 	{
-		mpt::ifstream exitFile(dirWindows + P_("exit"), std::ios::binary);
+		std::ifstream exitFile(dirWindows + P_("exit"), std::ios::binary);
 		if(!exitFile)
 		{
 			throw mpt::Wine::Exception("Script .exit file not found.");
@@ -608,7 +608,7 @@
 	std::string outputString;
 	if(!flags[ExecFlagInteractive])
 	{
-		mpt::ifstream outputFile(dirWindows + P_("out"), std::ios::binary);
+		std::ifstream outputFile(dirWindows + P_("out"), std::ios::binary);
 		if(outputFile)
 		{
 			outputFile.seekg(0, std::ios::end);
@@ -625,7 +625,7 @@
 	std::string errorString;
 	if(flags[ExecFlagSplitOutput])
 	{
-		mpt::ifstream errorFile(dirWindows + P_("err"), std::ios::binary);
+		std::ifstream errorFile(dirWindows + P_("err"), std::ios::binary);
 		if(errorFile)
 		{
 			errorFile.seekg(0, std::ios::end);
Index: mptrack/AutoSaver.cpp
===================================================================
--- mptrack/AutoSaver.cpp	(revision 13999)
+++ mptrack/AutoSaver.cpp	(working copy)
@@ -159,7 +159,7 @@
 	ScopedLogCapturer logcapturer(modDoc, _T(""), nullptr, false);
 
 	bool success = false;
-	mpt::ofstream f(fileName, std::ios::binary);
+	std::ofstream f(fileName, std::ios::binary);
 	if(f)
 	{
 		switch(modDoc.GetSoundFile().GetBestSaveFormat())
@@ -196,7 +196,7 @@
 		path = GetPath();
 	}
 
-	std::vector<mpt::RawPathString> foundfiles;
+	std::vector<mpt::winstring> foundfiles;
 	mpt::PathString searchPattern = path + mpt::PathString::FromCString(modDoc.GetTitle()).SanitizeComponent() + P_(".AutoSave.*");
 
 	// Find all autosave files for this document, and delete the oldest ones if there are more than the user wants.
@@ -209,7 +209,7 @@
 		{
 			if(!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
 			{
-				foundfiles.push_back(findData.cFileName);
+				foundfiles.push_back(mpt::String::ReadWinBuf(findData.cFileName));
 			}
 		} while(FindNextFile(hFindFile, &findData));
 		FindClose(hFindFile);
Index: mptrack/CommandSet.cpp
===================================================================
--- mptrack/CommandSet.cpp	(revision 13999)
+++ mptrack/CommandSet.cpp	(working copy)
@@ -1497,7 +1497,7 @@
 */
 
 	mpt::SafeOutputFile sf(filename, std::ios::out, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-	mpt::ofstream& f = sf;
+	std::ofstream& f = sf;
 	if(!f)
 	{
 		ErrorBox(IDS_CANT_OPEN_FILE_FOR_WRITING);
@@ -1710,7 +1710,7 @@
 
 bool CCommandSet::LoadFile(const mpt::PathString &filename)
 {
-	mpt::ifstream fin(filename);
+	std::ifstream fin(filename);
 	if(fin.fail())
 	{
 		Reporting::Warning(MPT_TFORMAT("Can't open key bindings file {} for reading. Default key bindings will be used.")(filename));
Index: mptrack/Ctrl_ins.cpp
===================================================================
--- mptrack/Ctrl_ins.cpp	(revision 13999)
+++ mptrack/Ctrl_ins.cpp	(working copy)
@@ -2088,7 +2088,7 @@
 			{
 				ScopedLogCapturer logcapturer(m_modDoc);
 				mpt::SafeOutputFile sf(fileName, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-				mpt::ofstream &f = sf;
+				std::ofstream &f = sf;
 				if(!f)
 				{
 					ok = false;
Index: mptrack/Ctrl_smp.cpp
===================================================================
--- mptrack/Ctrl_smp.cpp	(revision 13999)
+++ mptrack/Ctrl_smp.cpp	(working copy)
@@ -1500,7 +1500,7 @@
 			try
 			{
 				mpt::SafeOutputFile sf(fileName, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-				mpt::ofstream &f = sf;
+				std::ofstream &f = sf;
 				if(!f)
 				{
 					ok = false;
Index: mptrack/ExceptionHandler.cpp
===================================================================
--- mptrack/ExceptionHandler.cpp	(revision 13999)
+++ mptrack/ExceptionHandler.cpp	(working copy)
@@ -314,7 +314,7 @@
 
 	{
 		mpt::SafeOutputFile sf(crashDirectory.path + P_("error.txt"), std::ios::binary, mpt::FlushMode::Full);
-		mpt::ofstream& f = sf;
+		std::ofstream& f = sf;
 		f.imbue(std::locale::classic());
 		f << mpt::String::Replace(mpt::ToCharset(mpt::Charset::UTF8, errorMessage), "\n", "\r\n");
 	}
@@ -321,7 +321,7 @@
 
 	{
 		mpt::SafeOutputFile sf(crashDirectory.path + P_("threads.txt"), std::ios::binary, mpt::FlushMode::Full);
-		mpt::ofstream& f = sf;
+		std::ofstream& f = sf;
 		f.imbue(std::locale::classic());
 		f << MPT_FORMAT("current : {}")(mpt::fmt::hex0<8>(GetCurrentThreadId())) << "\r\n";
 		f << MPT_FORMAT("GUI     : {}")(mpt::fmt::hex0<8>(mpt::log::Trace::GetThreadId(mpt::log::Trace::ThreadKindGUI))) << "\r\n";
@@ -338,7 +338,7 @@
 
 	{
 		mpt::SafeOutputFile sf(crashDirectory.path + P_("active-settings.txt"), std::ios::binary, mpt::FlushMode::Full);
-		mpt::ofstream& f = sf;
+		std::ofstream& f = sf;
 		f.imbue(std::locale::classic());
 		if(theApp.GetpSettings())
 		{
@@ -403,7 +403,7 @@
 
 	{
 		mpt::SafeOutputFile sf(crashDirectory.path + P_("about-openmpt.txt"), std::ios::binary, mpt::FlushMode::Full);
-		mpt::ofstream& f = sf;
+		std::ofstream& f = sf;
 		f.imbue(std::locale::classic());
 		f << mpt::ToCharset(mpt::Charset::UTF8, CAboutDlg::GetTabText(0));
 	}
@@ -410,7 +410,7 @@
 
 	{
 		mpt::SafeOutputFile sf(crashDirectory.path + P_("about-components.txt"), std::ios::binary, mpt::FlushMode::Full);
-		mpt::ofstream& f = sf;
+		std::ofstream& f = sf;
 		f.imbue(std::locale::classic());
 		f << mpt::ToCharset(mpt::Charset::UTF8, CAboutDlg::GetTabText(1));
 	}
Index: mptrack/FileDialog.h
===================================================================
--- mptrack/FileDialog.h	(revision 13999)
+++ mptrack/FileDialog.h	(working copy)
@@ -23,12 +23,12 @@
 	using PathList = std::vector<mpt::PathString>;
 
 protected:
-	mpt::RawPathString m_defaultExtension;
-	mpt::RawPathString m_defaultFilename;
-	mpt::RawPathString m_extFilter;
-	mpt::RawPathString m_lastPreviewFile;
-	mpt::RawPathString m_workingDirectory;
-	mpt::RawPathString m_extension;
+	mpt::winstring m_defaultExtension;
+	mpt::winstring m_defaultFilename;
+	mpt::winstring m_extFilter;
+	mpt::winstring m_lastPreviewFile;
+	mpt::winstring m_workingDirectory;
+	mpt::winstring m_extension;
 	PathList m_filenames;
 	PathList m_places;
 	int *m_filterIndex = nullptr;
Index: mptrack/GeneralConfigDlg.cpp
===================================================================
--- mptrack/GeneralConfigDlg.cpp	(revision 13999)
+++ mptrack/GeneralConfigDlg.cpp	(working copy)
@@ -116,7 +116,7 @@
 	mpt::PathString file;
 	while(scanner.Next(file))
 	{
-		mpt::RawPathString fileW = file.AsNative();
+		mpt::winstring fileW = file.AsNative();
 		fileW = fileW.substr(basePath.Length());
 		::SendMessage(m_defaultTemplate.m_hWnd, CB_ADDSTRING, 0, (LPARAM)fileW.c_str());
 	}
@@ -203,7 +203,7 @@
 		dlg.WorkingDirectory(basePath);
 	} else
 	{
-		if(defaultFile.AsNative().find_first_of(_T("/\\")) == mpt::RawPathString::npos)
+		if(defaultFile.AsNative().find_first_of(_T("/\\")) == mpt::winstring::npos)
 		{
 			// Relative path
 			defaultFile = basePath + defaultFile;
Index: mptrack/mod2midi.cpp
===================================================================
--- mptrack/mod2midi.cpp	(revision 13999)
+++ mptrack/mod2midi.cpp	(working copy)
@@ -368,11 +368,11 @@
 		SNDMIXPLUGIN tempoTrackPlugin;
 		VSTPluginLib m_plugFactory;
 		CSoundFile &m_sndFile;
-		mpt::ofstream &m_file;
+		std::ofstream &m_file;
 		const bool m_wasInstrumentMode;
 
 	public:
-		Conversion(CSoundFile &sndFile, const InstrMap &instrMap, mpt::ofstream &file, bool overlappingInstruments)
+		Conversion(CSoundFile &sndFile, const InstrMap &instrMap, std::ofstream &file, bool overlappingInstruments)
 			: m_oldInstruments(sndFile.GetNumInstruments())
 			, m_plugFactory(nullptr, true, {}, {}, {})
 			, m_sndFile(sndFile)
Index: mptrack/mod2midi.h
===================================================================
--- mptrack/mod2midi.h	(revision 13999)
+++ mptrack/mod2midi.h	(working copy)
@@ -62,11 +62,11 @@
 {
 public:
 	CSoundFile &m_sndFile;
-	mpt::ofstream &m_file;
+	std::ofstream &m_file;
 	const MidiExport::InstrMap &m_instrMap;
 
 public:
-	CDoMidiConvert(CSoundFile &sndFile, mpt::ofstream &f, const MidiExport::InstrMap &instrMap, CWnd *parent = nullptr)
+	CDoMidiConvert(CSoundFile &sndFile, std::ofstream &f, const MidiExport::InstrMap &instrMap, CWnd *parent = nullptr)
 		: CProgressDialog(parent)
 		, m_sndFile(sndFile)
 		, m_file(f)
Index: mptrack/Mod2wave.cpp
===================================================================
--- mptrack/Mod2wave.cpp	(revision 13999)
+++ mptrack/Mod2wave.cpp	(working copy)
@@ -1018,7 +1018,7 @@
 
 	float normalizePeak = 0.0f;
 	const mpt::PathString normalizeFileName = mpt::CreateTempFileName(P_("OpenMPT"));
-	std::optional<mpt::fstream> normalizeFile;
+	std::optional<std::fstream> normalizeFile;
 	if(m_Settings.normalize)
 	{
 		// Ensure this temporary file is marked as temporary in the file system, to increase the chance it will never be written to disk
Index: mptrack/mod2wave.h
===================================================================
--- mptrack/mod2wave.h	(revision 13999)
+++ mptrack/mod2wave.h	(working copy)
@@ -119,13 +119,13 @@
 public:
 	const CWaveConvertSettings &m_Settings;
 	CSoundFile &m_SndFile;
-	mpt::ofstream &fileStream;
+	std::ofstream &fileStream;
 	const CString &caption;
 	uint64 m_dwSongLimit;
 	bool m_bGivePlugsIdleTime;
 
 public:
-	CDoWaveConvert(CSoundFile &sndFile, mpt::ofstream &f, const CString &caption, const CWaveConvertSettings &settings, CWnd *parent = NULL)
+	CDoWaveConvert(CSoundFile &sndFile, std::ofstream &f, const CString &caption, const CWaveConvertSettings &settings, CWnd *parent = NULL)
 		: CProgressDialog(parent)
 		, m_Settings(settings)
 		, m_SndFile(sndFile)
Index: mptrack/Moddoc.cpp
===================================================================
--- mptrack/Moddoc.cpp	(revision 13999)
+++ mptrack/Moddoc.cpp	(working copy)
@@ -300,7 +300,7 @@
 	try
 	{
 		mpt::SafeOutputFile sf(filename, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-		mpt::ofstream &f = sf;
+		std::ofstream &f = sf;
 		if(f)
 		{
 			f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
@@ -1764,7 +1764,7 @@
 			try
 			{
 				mpt::SafeOutputFile safeFileStream(thisName, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-				mpt::ofstream &f = safeFileStream;
+				std::ofstream &f = safeFileStream;
 				f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
 
 				if(!f)
@@ -1915,7 +1915,7 @@
 		try
 		{
 			mpt::SafeOutputFile sf(dlg.GetFirstFile(), std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-			mpt::ofstream &f = sf;
+			std::ofstream &f = sf;
 			f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
 
 			if(!f.good())
@@ -1994,7 +1994,7 @@
 	try
 	{
 		mpt::SafeOutputFile sf(filename, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-		mpt::ofstream &f = sf;
+		std::ofstream &f = sf;
 		if(f)
 		{
 			f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
Index: mptrack/Modedit.cpp
===================================================================
--- mptrack/Modedit.cpp	(revision 13999)
+++ mptrack/Modedit.cpp	(working copy)
@@ -1148,7 +1148,7 @@
 	try
 	{
 		mpt::SafeOutputFile sf(fileName, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-		mpt::ofstream &f = sf;
+		std::ofstream &f = sf;
 		f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
 		if(f)
 			ok = mpt::IO::WriteRaw(f, s.GetString(), s.GetLength());
Index: mptrack/MPTrackWine.cpp
===================================================================
--- mptrack/MPTrackWine.cpp	(revision 13999)
+++ mptrack/MPTrackWine.cpp	(working copy)
@@ -699,7 +699,7 @@
 
 		{
 			std::string fn = "libopenmpt_native_support.so";
-			mpt::ofstream f(wine.PathToWindows(nativeSearchPath) + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
+			std::ofstream f(wine.PathToWindows(nativeSearchPath) + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
 			f.write(&result.filetree[fn][0], result.filetree[fn].size());
 			f.flush();
 			if(!f)
@@ -709,7 +709,7 @@
 		}
 		{
 			std::string fn = "openmpt_wine_wrapper.dll";
-			mpt::ofstream f(paths.AppData_Wine_WineVersion_OpenMPTVersion + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
+			std::ofstream f(paths.AppData_Wine_WineVersion_OpenMPTVersion + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
 			f.write(&result.filetree[fn][0], result.filetree[fn].size());
 			f.flush();
 			if(!f)
@@ -719,7 +719,7 @@
 		}
 		{
 			std::string fn = "success.txt";
-			mpt::ofstream f(paths.AppData_Wine_WineVersion_OpenMPTVersion + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
+			std::ofstream f(paths.AppData_Wine_WineVersion_OpenMPTVersion + P_("\\") + mpt::PathString::FromUTF8(fn), std::ios::binary);
 			f.imbue(std::locale::classic());
 			f << std::string("1");
 			f.flush();
Index: mptrack/Settings.cpp
===================================================================
--- mptrack/Settings.cpp	(revision 13999)
+++ mptrack/Settings.cpp	(working copy)
@@ -412,7 +412,7 @@
 
 static std::vector<char> ReadFile(const mpt::PathString &filename)
 {
-	mpt::ifstream s(filename, std::ios::binary);
+	std::ifstream s(filename, std::ios::binary);
 	std::vector<char> result;
 	while(s)
 	{
@@ -428,7 +428,7 @@
 {
 	static_assert(sizeof(wchar_t) == 2);
 	mpt::SafeOutputFile sinifile(filename, std::ios::binary, mpt::FlushMode::Full);
-	mpt::ofstream& inifile = sinifile;
+	std::ofstream& inifile = sinifile;
 	const uint8 UTF16LE_BOM[] = { 0xff, 0xfe };
 	inifile.write(reinterpret_cast<const char*>(UTF16LE_BOM), 2);
 	inifile.write(reinterpret_cast<const char*>(str.c_str()), str.length() * sizeof(std::wstring::value_type));
Index: mptrack/TrackerSettings.cpp
===================================================================
--- mptrack/TrackerSettings.cpp	(revision 13999)
+++ mptrack/TrackerSettings.cpp	(working copy)
@@ -837,7 +837,7 @@
 std::unique_ptr<CTuningCollection> TrackerSettings::LoadLocalTunings()
 {
 	std::unique_ptr<CTuningCollection> s_pTuningsSharedLocal = std::make_unique<CTuningCollection>();
-	mpt::ifstream f(
+	std::ifstream f(
 			PathTunings.GetDefaultDir()
 			+ P_("local_tunings")
 			+ mpt::PathString::FromUTF8(CTuningCollection::s_FileExtension)
Index: mptrack/TuningDialog.cpp
===================================================================
--- mptrack/TuningDialog.cpp	(revision 13999)
+++ mptrack/TuningDialog.cpp	(working copy)
@@ -616,7 +616,7 @@
 		try
 		{
 			mpt::SafeOutputFile sfout(dlg.GetFirstFile(), std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-			mpt::ofstream &fout = sfout;
+			std::ofstream &fout = sfout;
 			fout.exceptions(fout.exceptions() | std::ios::badbit | std::ios::failbit);
 
 			if(tuningFilter != -1 && filterIndex == tuningFilter)
@@ -696,7 +696,7 @@
 			try
 			{
 				mpt::SafeOutputFile sfout(fileName, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-				mpt::ofstream &fout = sfout;
+				std::ofstream &fout = sfout;
 				fout.exceptions(fout.exceptions() | std::ios::badbit | std::ios::failbit);
 				if(tuning.Serialize(fout) != Tuning::SerializationResult::Success)
 				{
@@ -789,7 +789,7 @@
 		const bool bIsScl = (mpt::PathString::CompareNoCase(fileExt, P_(".scl")) == 0);
 		const bool bIsTc = (mpt::PathString::CompareNoCase(fileExt, mpt::PathString::FromUTF8(CTuningCollection::s_FileExtension)) == 0);
 
-		mpt::ifstream fin(file, std::ios::binary);
+		std::ifstream fin(file, std::ios::binary);
 
 		// "HSCT", 0x01, 0x00, 0x00, 0x00
 		const uint8 magicTColdV1 [] = {  'H', 'S', 'C', 'T',0x01,0x00,0x00,0x00                          };
@@ -1554,7 +1554,7 @@
 {
 	MPT_ASSERT(result == nullptr);
 	result = nullptr;
-	mpt::ifstream iStrm(filename, std::ios::in | std::ios::binary);
+	std::ifstream iStrm(filename, std::ios::in | std::ios::binary);
 	if(!iStrm)
 	{
 		return enSclImportFailUnableToOpenFile;
Index: mptrack/UpdateCheck.cpp
===================================================================
--- mptrack/UpdateCheck.cpp	(revision 13999)
+++ mptrack/UpdateCheck.cpp	(working copy)
@@ -1314,7 +1314,7 @@
 					std::array<std::byte, 512/8> expected;
 					std::copy(binhash.begin(), binhash.end(), expected.begin());
 					mpt::crypto::hash::SHA512 hash;
-					mpt::ifstream f(updateFilename, std::ios::binary);
+					std::ifstream f(updateFilename, std::ios::binary);
 					f.imbue(std::locale::classic());
 					f.exceptions(std::ios::badbit);
 					while(!mpt::IO::IsEof(f))
Index: pluginBridge/BridgeWrapper.cpp
===================================================================
--- pluginBridge/BridgeWrapper.cpp	(revision 13999)
+++ pluginBridge/BridgeWrapper.cpp	(working copy)
@@ -188,7 +188,7 @@
 PluginArch BridgeWrapper::GetPluginBinaryType(const mpt::PathString &pluginPath)
 {
 	PluginArch type = PluginArch_unknown;
-	mpt::ifstream file(pluginPath, std::ios::in | std::ios::binary);
+	std::ifstream file(pluginPath, std::ios::in | std::ios::binary);
 	if(file.is_open())
 	{
 		IMAGE_DOS_HEADER dosHeader;
Index: soundlib/Dlsbank.cpp
===================================================================
--- soundlib/Dlsbank.cpp	(revision 13999)
+++ soundlib/Dlsbank.cpp	(working copy)
@@ -533,7 +533,7 @@
 {
 	RIFFCHUNKID riff;
 	if(filename.empty()) return false;
-	mpt::ifstream f(filename, std::ios::binary);
+	std::ifstream f(filename, std::ios::binary);
 	if(!f)
 	{
 		return false;
@@ -1532,7 +1532,7 @@
 		return false;
 	}
 
-	mpt::ifstream f(m_szFileName, std::ios::binary);
+	std::ifstream f(m_szFileName, std::ios::binary);
 	if(!f)
 	{
 		return false;
Index: soundlib/plugins/PlugInterface.cpp
===================================================================
--- soundlib/plugins/PlugInterface.cpp	(revision 13999)
+++ soundlib/plugins/PlugInterface.cpp	(working copy)
@@ -655,7 +655,7 @@
 	try
 	{
 		mpt::SafeOutputFile sf(dlg.GetFirstFile(), std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave));
-		mpt::ofstream &f = sf;
+		std::ofstream &f = sf;
 		f.exceptions(f.exceptions() | std::ios::badbit | std::ios::failbit);
 		if(f.good() && VSTPresets::SaveFile(f, *this, isBank))
 			return true;
Index: soundlib/SampleFormatFLAC.cpp
===================================================================
--- soundlib/SampleFormatFLAC.cpp	(revision 13999)
+++ soundlib/SampleFormatFLAC.cpp	(working copy)
@@ -485,7 +485,7 @@
 
 	static FLAC__StreamEncoderWriteStatus StreamEncoderWriteCallback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data)
 	{
-		mpt::ofstream & file = *reinterpret_cast<mpt::ofstream*>(client_data);
+		std::ofstream & file = *reinterpret_cast<std::ofstream*>(client_data);
 		MPT_UNUSED_VARIABLE(encoder);
 		MPT_UNUSED_VARIABLE(samples);
 		MPT_UNUSED_VARIABLE(current_frame);
@@ -497,7 +497,7 @@
 	}
 	static FLAC__StreamEncoderSeekStatus StreamEncoderSeekCallback(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
 	{
-		mpt::ofstream & file = *reinterpret_cast<mpt::ofstream*>(client_data);
+		std::ofstream & file = *reinterpret_cast<std::ofstream*>(client_data);
 		MPT_UNUSED_VARIABLE(encoder);
 		if(!mpt::in_range<mpt::IO::Offset>(absolute_byte_offset))
 		{
@@ -511,7 +511,7 @@
 	}
 	static FLAC__StreamEncoderTellStatus StreamEncoderTellCallback(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
 	{
-		mpt::ofstream & file = *reinterpret_cast<mpt::ofstream*>(client_data);
+		std::ofstream & file = *reinterpret_cast<std::ofstream*>(client_data);
 		MPT_UNUSED_VARIABLE(encoder);
 		mpt::IO::Offset pos = mpt::IO::TellWrite(file);
 		if(pos < 0)
Index: test/test.cpp
===================================================================
--- test/test.cpp	(revision 13999)
+++ test/test.cpp	(working copy)
@@ -365,7 +365,7 @@
 #if MPT_TEST_HAS_FILESYSTEM
 #if !MPT_OS_DJGPP
 	mpt::PathString version_mk = GetPathPrefix() + P_("libopenmpt/libopenmpt_version.mk");
-	mpt::ifstream f(version_mk, std::ios::in);
+	std::ifstream f(version_mk, std::ios::in);
 	VERIFY_EQUAL(f ? true : false, true);
 	std::map<std::string, std::string> fields;
 	std::string line;
@@ -4143,7 +4143,7 @@
 
 static TSoundFileContainer CreateSoundFileContainer(const mpt::PathString &filename)
 {
-	mpt::ifstream stream(filename, std::ios::binary);
+	std::ifstream stream(filename, std::ios::binary);
 	FileReader file = make_FileReader(&stream);
 	std::shared_ptr<CSoundFile> pSndFile = std::make_shared<CSoundFile>();
 	pSndFile->Create(file, CSoundFile::loadCompleteModule);
@@ -4159,19 +4159,19 @@
 
 static void SaveIT(const TSoundFileContainer &sndFile, const mpt::PathString &filename)
 {
-	mpt::ofstream f(filename, std::ios::binary);
+	std::ofstream f(filename, std::ios::binary);
 	sndFile->SaveIT(f, filename, false);
 }
 
 static void SaveXM(const TSoundFileContainer &sndFile, const mpt::PathString &filename)
 {
-	mpt::ofstream f(filename, std::ios::binary);
+	std::ofstream f(filename, std::ios::binary);
 	sndFile->SaveXM(f, false);
 }
 
 static void SaveS3M(const TSoundFileContainer &sndFile, const mpt::PathString &filename)
 {
-	mpt::ofstream f(filename, std::ios::binary);
+	std::ofstream f(filename, std::ios::binary);
 	sndFile->SaveS3M(f);
 }
 
