diff --git a/aegisub/src/browse_button.cpp b/aegisub/src/browse_button.cpp
index cc04c325caf51faa82eaa4944281a0364ad2cd77..5e35bd5b1bdfaf2cf39d50d2aa81e801f00c8227 100644
--- a/aegisub/src/browse_button.cpp
+++ b/aegisub/src/browse_button.cpp
@@ -72,10 +72,10 @@ void BrowseButton::OnPressed(wxCommandEvent &event) {
 	if (type == BROWSE_FOLDER) {
 		// For some reason I can't make this work on Mac... -jfs
 #ifndef __WXMAC__
-		wxString def = DecodeRelativePath(ctrl[0]->GetValue(),StandardPaths::DecodePath(_T("?user/")));
+		wxString def = StandardPaths::DecodePathMaybeRelative(ctrl[0]->GetValue(), _T("?user/"));
 		wxDirDialog dlg(0, _("Please choose the folder:"), def);
 		if (dlg.ShowModal() == wxID_OK) {
-			wxString dir = MakeRelativePath(dlg.GetPath(),StandardPaths::DecodePath(_T("?user/")));
+			wxString dir = StandardPaths::EncodePath(dlg.GetPath());
 			if (dir != _T("")) ctrl[0]->SetValue(dir);
 		}
 #endif
diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp
index 4375808908eb11a3ab0c19b3fbc4998f7e723cf6..fc104474abc49e8a9037d57040ba3e891a67629f 100644
--- a/aegisub/src/frame_main.cpp
+++ b/aegisub/src/frame_main.cpp
@@ -718,7 +718,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
 		wxString path = Options.AsText(_T("Auto backup path"));
 		if (path.IsEmpty()) path = origfile.GetPath();
 		wxFileName dstpath(path);
-		if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePath(_T("?user/") + path);
+		if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
 		path += _T("/");
 		dstpath.Assign(path);
 		if (!dstpath.DirExists()) wxMkdir(path);
diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp
index 0cb9cba1db600a457d22bb6620a5b55300bcb679..f672df3cee0e8f59ead15f357f4c163a46d3f701 100644
--- a/aegisub/src/frame_main_events.cpp
+++ b/aegisub/src/frame_main_events.cpp
@@ -1519,7 +1519,7 @@ void FrameMain::OnAutoSave(wxTimerEvent &event) {
 			wxString path = Options.AsText(_T("Auto save path"));
 			if (path.IsEmpty()) path = origfile.GetPath();
 			wxFileName dstpath(path);
-			if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePath(_T("?user/") + path);
+			if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
 			path += _T("/");
 			dstpath.Assign(path);
 			if (!dstpath.DirExists()) wxMkdir(path);
diff --git a/aegisub/src/help_button.cpp b/aegisub/src/help_button.cpp
index 12e58fda8f67e9a9b91b65e455652ef625997bcf..8a01f526e156ae8fe7e67d698cb70b4bbb16fc5b 100644
--- a/aegisub/src/help_button.cpp
+++ b/aegisub/src/help_button.cpp
@@ -88,7 +88,7 @@ void HelpButton::OpenPage(const wxString pageID) {
 		docsPath.Replace(_T("\\"),_T("/"));
 		docsPath = _T("/") + docsPath;
 #endif
-		wxString path = StandardPaths::DecodePath(wxString::Format(_T("file://%s/%s.html"),docsPath.c_str(),page.c_str()));
+		wxString path = wxString::Format(_T("file://%s/%s.html"),docsPath.c_str(),page.c_str());
 		wxLaunchDefaultBrowser(path);
 	}
 }
diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp
index 10175b4edb4a8ba586cd0111707a8edb2114ce43..75556b2f64b19447c91c1d90c338c34b5ccaa5fc 100644
--- a/aegisub/src/main.cpp
+++ b/aegisub/src/main.cpp
@@ -162,6 +162,12 @@ bool AegisubApp::OnInit() {
 			wxRemoveFile(StandardPaths::DecodePath(_T("?data/config.dat")));
 #endif
 		}
+#ifdef __WXMSW__
+		// Change ?user to point to ?data if we have local config
+		if (Options.AsBool(_T("Local config"))) {
+			StandardPaths::SetPathValue(_T("?user"), StandardPaths::DecodePath(_T("?data")));
+		}
+#endif
 		StartupLog(_T("Store options back"));
 		Options.SetInt(_T("Last Version"),GetSVNRevision());
 		Options.LoadDefaults(false,true);	// Override options based on version number
@@ -260,7 +266,7 @@ void AegisubApp::OnUnhandledException() {
 	wxString path = Options.AsText(_T("Auto recovery path"));
 	if (path.IsEmpty()) path = StandardPaths::DecodePath(_T("?user/"));
 	wxFileName dstpath(path);
-	if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePath(_T("?user/")) + path;
+	if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
 	path += _T("/");
 	dstpath.Assign(path);
 	if (!dstpath.DirExists()) wxMkdir(path);
@@ -280,7 +286,7 @@ void AegisubApp::OnFatalException() {
 	wxString path = Options.AsText(_T("Auto recovery path"));
 	if (path.IsEmpty()) path = StandardPaths::DecodePath(_T("?user/"));
 	wxFileName dstpath(path);
-	if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePath(_T("?user/")) + path;
+	if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
 	path += _T("/");
 	dstpath.Assign(path);
 	if (!dstpath.DirExists()) wxMkdir(path);
diff --git a/aegisub/src/options.cpp b/aegisub/src/options.cpp
index 15e156d4ce5eeabfc3c848e01b52266cfa35dba9..f03093c38615036f155cb078438776db1c55444f 100644
--- a/aegisub/src/options.cpp
+++ b/aegisub/src/options.cpp
@@ -106,10 +106,10 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) {
 	SetModificationType(MOD_RESTART);
 	SetInt(_T("Auto save every seconds"),60); // FIXME: this shouldn't need to require a restart
 	SetModificationType(MOD_AUTOMATIC);
-	SetText(_T("Auto save path"),_T("autosave")); // what does this mean on linux? actually this should be under $HOME on any OS
+	SetText(_T("Auto save path"),_T("?user/autosave"));
 	SetBool(_T("Auto backup"),true);
-	SetText(_T("Auto backup path"),_T("autoback"));
-	SetText(_T("Auto recovery path"),_T("recovered"));
+	SetText(_T("Auto backup path"),_T("?user/autoback"));
+	SetText(_T("Auto recovery path"),_T("?user/recovered"));
 	SetInt(_T("Autoload linked files"),2);
 	SetText(_T("Text actor separator"),_T(":"));
 	SetText(_T("Text comment starter"),_T("#"));
@@ -119,7 +119,7 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) {
 
 	// Edit Box
 	SetModificationType(MOD_RESTART);
-	SetText(_T("Dictionaries path"),_T("dictionaries"));
+	SetText(_T("Dictionaries path"),_T("?data/dictionaries"));
 	SetText(_T("Spell Checker"),_T("hunspell"));
 	SetModificationType(MOD_AUTOMATIC);
 	SetBool(_T("Link time boxes commit"),true);
diff --git a/aegisub/src/spellchecker_hunspell.cpp b/aegisub/src/spellchecker_hunspell.cpp
index 163fe3438149570ce53be9f95641a69aa04c4d08..acecf88c79767c510737a4c5afdeddc324717024 100644
--- a/aegisub/src/spellchecker_hunspell.cpp
+++ b/aegisub/src/spellchecker_hunspell.cpp
@@ -202,7 +202,7 @@ wxArrayString HunspellSpellChecker::GetSuggestions(wxString word) {
 // Get list of available dictionaries
 wxArrayString HunspellSpellChecker::GetLanguageList() {
 	// Get dir name
-	wxString path = DecodeRelativePath(Options.AsText(_T("Dictionaries path")),StandardPaths::DecodePath(_T("?data/"))) + _T("/");
+	wxString path = StandardPaths::DecodePathMaybeRelative(Options.AsText(_T("Dictionaries path")), _T("?data")) + _T("/");
 	wxArrayString list;
 	wxFileName folder(path);
 	if (!folder.DirExists()) return list;
@@ -240,7 +240,7 @@ void HunspellSpellChecker::SetLanguage(wxString language) {
 
 	// Get dir name
 	//FIXME: this should use ?user instead of ?data; however, since it apparently works already on win32, I'm not gonna mess with it right now :p
-	wxString path = DecodeRelativePath(Options.AsText(_T("Dictionaries path")),StandardPaths::DecodePath(_T("?data/"))) + _T("/");
+	wxString path = StandardPaths::DecodePathMaybeRelative(Options.AsText(_T("Dictionaries path")), _T("?data")) + _T("/");
 	wxString userPath = StandardPaths::DecodePath(_T("?user/dictionaries/user_"));
 
 	// Get affix and dictionary paths
diff --git a/aegisub/src/standard_paths.cpp b/aegisub/src/standard_paths.cpp
index 934edf7c1ddc81105db4128f7305592f27f3fa4f..11c23a76688f10cd40e75f5f8e64e6da4f7c1995 100644
--- a/aegisub/src/standard_paths.cpp
+++ b/aegisub/src/standard_paths.cpp
@@ -119,7 +119,7 @@ wxString StandardPaths::DoDecodePath(wxString path) {
 
 ///////////////
 // Encode path
-wxString StandardPaths::DoEncodePath(wxString path) {
+wxString StandardPaths::DoEncodePath(const wxString &path) {
 	// TODO
 	return path;
 }
@@ -127,6 +127,16 @@ wxString StandardPaths::DoEncodePath(wxString path) {
 
 /////////////////////////
 // Set value of a ? path
-void StandardPaths::DoSetPathValue(wxString path,wxString value) {
+void StandardPaths::DoSetPathValue(const wxString &path, const wxString &value) {
 	paths[path] = value;
 }
+
+
+///////////////////////////////////////////////////////////////////////////
+// Decode a path that for legacy reasons might be relative to another path
+wxString StandardPaths::DecodePathMaybeRelative(const wxString &path, const wxString &relativeTo) {
+	wxFileName res(DecodePath(path));
+	if (res.IsRelative())
+		res.Assign(DecodePath(relativeTo + _T("/") + path));
+	return res.GetFullPath();
+}
diff --git a/aegisub/src/standard_paths.h b/aegisub/src/standard_paths.h
index 8438c154d35297703364076e7f499d7e18c30e1c..5cfd39f4d50c767b73e05ba167d9a03bb881c05a 100644
--- a/aegisub/src/standard_paths.h
+++ b/aegisub/src/standard_paths.h
@@ -56,11 +56,12 @@ private:
 	StandardPaths& operator=(StandardPaths const&);
 
 	wxString DoDecodePath(wxString path);
-	wxString DoEncodePath(wxString path);
-	void DoSetPathValue(wxString path,wxString value);
+	wxString DoEncodePath(const wxString &path);
+	void DoSetPathValue(const wxString &path, const wxString &value);
 
 public:
-	static wxString DecodePath(wxString path) { return GetInstance().DoDecodePath(path); }
-	static wxString EncodePath(wxString path) { return GetInstance().DoEncodePath(path); }
-	static void SetPathValue(wxString path,wxString value) { GetInstance().DoSetPathValue(path,value); }
+	static wxString DecodePath(const wxString &path) { return GetInstance().DoDecodePath(path); }
+	static wxString DecodePathMaybeRelative(const wxString &path, const wxString &relativeTo);
+	static wxString EncodePath(const wxString &path) { return GetInstance().DoEncodePath(path); }
+	static void SetPathValue(const wxString &path, const wxString &value) { GetInstance().DoSetPathValue(path,value); }
 };
diff --git a/aegisub/src/thesaurus_myspell.cpp b/aegisub/src/thesaurus_myspell.cpp
index 59ea17e8c08d3bc084f7b14f72e05ef72ea9fb23..32bc6fc5665e17b611a9b126a79f876315283b58 100644
--- a/aegisub/src/thesaurus_myspell.cpp
+++ b/aegisub/src/thesaurus_myspell.cpp
@@ -96,7 +96,7 @@ void MySpellThesaurus::Lookup(wxString word,ThesaurusEntryArray &result) {
 // Get language list
 wxArrayString MySpellThesaurus::GetLanguageList() {
 	// Get dir name
-	wxString path = DecodeRelativePath(Options.AsText(_T("Dictionaries path")),StandardPaths::DecodePath(_T("?data/"))) + _T("/");
+	wxString path = StandardPaths::DecodePathMaybeRelative(Options.AsText(_T("Dictionaries path")), _T("?data")) + _T("/");
 	wxArrayString list;
 	wxFileName folder(path);
 	if (!folder.DirExists()) return list;
@@ -140,7 +140,7 @@ void MySpellThesaurus::SetLanguage(wxString language) {
 	if (language.IsEmpty()) return;
 
 	// Get dir name
-	wxString path = DecodeRelativePath(Options.AsText(_T("Dictionaries path")),StandardPaths::DecodePath(_T("?data/"))) + _T("/");
+	wxString path = StandardPaths::DecodePathMaybeRelative(Options.AsText(_T("Dictionaries path")), _T("?data")) + _T("/");
 
 	// Get affix and dictionary paths
 	wxString idxpath = path + _T("th_") + language + _T(".idx");