diff --git a/aegisub/src/ass_attachment.cpp b/aegisub/src/ass_attachment.cpp
index a5d43fd0bb5c37b15dd6ee355470d756c2605e9c..1fb02a66362547fbfd266f6cbacf7a93e71cc919 100644
--- a/aegisub/src/ass_attachment.cpp
+++ b/aegisub/src/ass_attachment.cpp
@@ -112,11 +112,11 @@ const wxString AssAttachment::GetEntryData() const {
 }
 
 void AssAttachment::Extract(wxString const& filename) const {
-	agi::io::Save(STD_STR(filename), true).Get().write(&(*data)[0], data->size());
+	agi::io::Save(from_wx(filename), true).Get().write(&(*data)[0], data->size());
 }
 
 void AssAttachment::Import(wxString const& filename) {
-	agi::scoped_ptr<std::istream> file(agi::io::Open(STD_STR(filename), true));
+	agi::scoped_ptr<std::istream> file(agi::io::Open(from_wx(filename), true));
 	file->seekg(0, std::ios::end);
 	data->resize(file->tellg());
 	file->seekg(0, std::ios::beg);
diff --git a/aegisub/src/ass_dialogue.cpp b/aegisub/src/ass_dialogue.cpp
index 24de9ff74d24a768707b70205962881535529d37..b8ee3dd793d618dc8a68557d1716efe9c0a6f3ef 100644
--- a/aegisub/src/ass_dialogue.cpp
+++ b/aegisub/src/ass_dialogue.cpp
@@ -84,7 +84,7 @@ AssDialogue::AssDialogue(wxString const& data)
 , Style("Default")
 {
 	if (!Parse(data))
-		throw SubtitleFormatParseError(STD_STR("Failed parsing line: " + data), 0);
+		throw SubtitleFormatParseError(from_wx("Failed parsing line: " + data), 0);
 }
 
 AssDialogue::~AssDialogue () {
diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp
index 7cdb1741e6044a693e9d08d4b2cee2c20e6cc808..ad47ea8dd75cbd141b4c107a21f903e395e75370 100644
--- a/aegisub/src/ass_file.cpp
+++ b/aegisub/src/ass_file.cpp
@@ -148,7 +148,7 @@ wxString AssFile::AutoSave() {
 		return "";
 
 	wxFileName origfile(filename);
-	wxString path = lagi_wxString(OPT_GET("Path/Auto/Save")->GetString());
+	wxString path = to_wx(OPT_GET("Path/Auto/Save")->GetString());
 	if (!path)
 		path = origfile.GetPath();
 	path = StandardPaths::DecodePath(path + "/");
@@ -366,9 +366,9 @@ AssStyle *AssFile::GetStyle(wxString const& name) {
 }
 
 void AssFile::AddToRecent(wxString const& file) const {
-	config::mru->Add("Subtitle", STD_STR(file));
+	config::mru->Add("Subtitle", from_wx(file));
 	wxFileName filepath(file);
-	OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
+	OPT_SET("Path/Last/Subtitles")->SetString(from_wx(filepath.GetPath()));
 }
 
 int AssFile::Commit(wxString const& desc, int type, int amendId, AssEntry *single_line) {
diff --git a/aegisub/src/audio_controller.cpp b/aegisub/src/audio_controller.cpp
index 06294b765bb3de781fb69a3055b3f5771f28e161..b3fa9c03f104807a99c12e15946d72321c0f489e 100644
--- a/aegisub/src/audio_controller.cpp
+++ b/aegisub/src/audio_controller.cpp
@@ -172,7 +172,7 @@ void AudioController::OpenAudio(const wxString &url)
 		throw;
 	}
 	catch (...) {
-		config::mru->Remove("Audio", STD_STR(url));
+		config::mru->Remove("Audio", from_wx(url));
 		throw;
 	}
 
@@ -192,7 +192,7 @@ void AudioController::OpenAudio(const wxString &url)
 
 	audio_url = url;
 
-	config::mru->Add("Audio", STD_STR(url));
+	config::mru->Add("Audio", from_wx(url));
 
 	try
 	{
@@ -408,7 +408,7 @@ void AudioController::SaveClip(wxString const& filename, TimeRange const& range)
 	int64_t end_sample = SamplesFromMilliseconds(range.end());
 	if (filename.empty() || start_sample > provider->GetNumSamples() || range.length() == 0) return;
 
-	agi::io::Save outfile(STD_STR(filename), true);
+	agi::io::Save outfile(from_wx(filename), true);
 	std::ofstream& out(outfile.Get());
 
 	size_t bytes_per_sample = provider->GetBytesPerSample() * provider->GetChannels();
diff --git a/aegisub/src/audio_player_alsa.cpp b/aegisub/src/audio_player_alsa.cpp
index 95a71a89a0035716e09c10aebe7eea92401bb427..b142cbdafeb39aa4f51eac9917b7fa55fb46e486 100644
--- a/aegisub/src/audio_player_alsa.cpp
+++ b/aegisub/src/audio_player_alsa.cpp
@@ -369,7 +369,7 @@ AlsaPlayer::AlsaPlayer(AudioProvider *provider)
 {
 	ps->provider = provider;
 
-	wxString device_name = lagi_wxString(OPT_GET("Player/Audio/ALSA/Device")->GetString());
+	wxString device_name = to_wx(OPT_GET("Player/Audio/ALSA/Device")->GetString());
 	ps->device_name = std::string(device_name.utf8_str());
 
 	if (pthread_create(&thread, 0, &playback_thread, ps.get()) != 0)
diff --git a/aegisub/src/audio_player_oss.cpp b/aegisub/src/audio_player_oss.cpp
index 1de35781115af1efabe8dc61f9efbcd155973a71..165d4d7b62de3534f1dec1a4c124a439e134d035 100644
--- a/aegisub/src/audio_player_oss.cpp
+++ b/aegisub/src/audio_player_oss.cpp
@@ -74,7 +74,7 @@ void OSSPlayer::OpenStream()
     bpf = provider->GetChannels() * provider->GetBytesPerSample();
 
     // Open device
-    wxString device = lagi_wxString(OPT_GET("Player/Audio/OSS/Device")->GetString());
+    wxString device = to_wx(OPT_GET("Player/Audio/OSS/Device")->GetString());
     dspdev = ::open(device.mb_str(wxConvUTF8), O_WRONLY, 0);
     if (dspdev < 0) {
         throw OSSError("OSS player: opening device failed", 0);
diff --git a/aegisub/src/audio_player_portaudio.cpp b/aegisub/src/audio_player_portaudio.cpp
index c692cf3e353cf944d0bb729ef60def700af7a100..fc40ebda57a5665577c0129826d7551ec6caae28 100644
--- a/aegisub/src/audio_player_portaudio.cpp
+++ b/aegisub/src/audio_player_portaudio.cpp
@@ -276,7 +276,7 @@ wxArrayString PortAudioPlayer::GetOutputDevices() {
 		PortAudioPlayer player(0);
 
 		for (std::map<std::string, DeviceVec>::iterator it = player.devices.begin(); it != player.devices.end(); ++it)
-			list.push_back(lagi_wxString(it->first));
+			list.push_back(to_wx(it->first));
 	}
 	catch (PortAudioError const&) {
 		// No output devices, just return the list with only Default
diff --git a/aegisub/src/audio_provider_ffmpegsource.cpp b/aegisub/src/audio_provider_ffmpegsource.cpp
index baea1904516f81c6d9dfaf0c2f04536c55bb81f5..930b9ad7bd833901c17bb790870ffd39a6859329 100644
--- a/aegisub/src/audio_provider_ffmpegsource.cpp
+++ b/aegisub/src/audio_provider_ffmpegsource.cpp
@@ -62,7 +62,7 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) try
 	LoadAudio(filename);
 }
 catch (wxString const& err) {
-	throw agi::AudioProviderOpenError(STD_STR(err), 0);
+	throw agi::AudioProviderOpenError(from_wx(err), 0);
 }
 catch (const char *err) {
 	throw agi::AudioProviderOpenError(err, 0);
diff --git a/aegisub/src/audio_provider_hd.cpp b/aegisub/src/audio_provider_hd.cpp
index db0f53d8ab87cf47c32592a996e955a1ba9299ba..72fce2df654ce819ec77612e2b416ed4e2b770ca 100644
--- a/aegisub/src/audio_provider_hd.cpp
+++ b/aegisub/src/audio_provider_hd.cpp
@@ -34,14 +34,14 @@
 
 #include "config.h"
 
+#include "audio_provider_hd.h"
+
 #include <wx/filefn.h>
 #include <wx/filename.h>
 
 #include <libaegisub/background_runner.h>
 #include <libaegisub/io.h>
 
-#include "audio_provider_hd.h"
-
 #include "audio_controller.h"
 #include "audio_provider_pcm.h"
 #include "compat.h"
@@ -51,7 +51,7 @@
 
 namespace {
 wxString cache_dir() {
-	wxString path = lagi_wxString(OPT_GET("Audio/Cache/HD/Location")->GetString());
+	wxString path = to_wx(OPT_GET("Audio/Cache/HD/Location")->GetString());
 	if (path == "default")
 		path = "?temp/";
 
@@ -59,7 +59,7 @@ wxString cache_dir() {
 }
 
 wxString cache_path() {
-	wxString pattern = lagi_wxString(OPT_GET("Audio/Cache/HD/Name")->GetString());
+	wxString pattern = to_wx(OPT_GET("Audio/Cache/HD/Name")->GetString());
 	if (pattern.Find("%02i") == wxNOT_FOUND) pattern = "audio%02i.tmp";
 
 	// Try from 00 to 99
@@ -113,14 +113,14 @@ HDAudioProvider::HDAudioProvider(AudioProvider *src, agi::BackgroundRunner *br)
 	wxDiskspaceSize_t freespace;
 	if (wxGetDiskSpace(cache_dir(), 0, &freespace)) {
 		if (num_samples * channels * bytes_per_sample > freespace)
-			throw agi::AudioCacheOpenError("Not enough free disk space in " + STD_STR(cache_dir()) + " to cache the audio", 0);
+			throw agi::AudioCacheOpenError("Not enough free disk space in " + from_wx(cache_dir()) + " to cache the audio", 0);
 	}
 
 	diskCacheFilename = cache_path();
 
 	try {
 		{
-			agi::io::Save out(STD_STR(diskCacheFilename), true);
+			agi::io::Save out(from_wx(diskCacheFilename), true);
 			br->Run(bind(&HDAudioProvider::FillCache, this, src, &out.Get(), std::placeholders::_1));
 		}
 		cache_provider.reset(new RawAudioProvider(diskCacheFilename, src));
@@ -141,7 +141,7 @@ void HDAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const
 }
 
 void HDAudioProvider::FillCache(AudioProvider *src, std::ofstream *out, agi::ProgressSink *ps) {
-	ps->SetMessage(STD_STR(_("Reading to Hard Disk cache")));
+	ps->SetMessage(from_wx(_("Reading to Hard Disk cache")));
 
 	int64_t block = 65536;
 	std::vector<char> read_buf;
diff --git a/aegisub/src/audio_provider_pcm.cpp b/aegisub/src/audio_provider_pcm.cpp
index 7de12992ce8e11d5b7f13037322d4dcc8fbc570d..59a35c81b0335e4acb112a8ab60ad63e7a105020 100644
--- a/aegisub/src/audio_provider_pcm.cpp
+++ b/aegisub/src/audio_provider_pcm.cpp
@@ -73,7 +73,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
 		0);
 
 	if (file_handle == INVALID_HANDLE_VALUE)
-		throw agi::FileNotFoundError(STD_STR(filename));
+		throw agi::FileNotFoundError(from_wx(filename));
 
 	LARGE_INTEGER li_file_size = {0};
 	if (!GetFileSizeEx(file_handle, &li_file_size))
@@ -94,7 +94,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
 , file_handle(open(filename.mb_str(*wxConvFileName), O_RDONLY), close)
 {
 	if (file_handle == -1)
-		throw agi::FileNotFoundError(STD_STR(filename));
+		throw agi::FileNotFoundError(from_wx(filename));
 
 	struct stat filestats;
 	memset(&filestats, 0, sizeof(filestats));
diff --git a/aegisub/src/audio_provider_ram.cpp b/aegisub/src/audio_provider_ram.cpp
index 6a90ca143028a815fe80c94a6bd2db1ef7741721..e7952462ffdeaa1c6f88af7e36b5d3e72e8e44ef 100644
--- a/aegisub/src/audio_provider_ram.cpp
+++ b/aegisub/src/audio_provider_ram.cpp
@@ -71,7 +71,7 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br
 }
 
 void RAMAudioProvider::FillCache(AudioProvider *source, agi::ProgressSink *ps) {
-	ps->SetMessage(STD_STR(_("Reading into RAM")));
+	ps->SetMessage(from_wx(_("Reading into RAM")));
 
 	int64_t readsize = CacheBlockSize / source->GetBytesPerSample();
 	for (size_t i = 0; i < blockcache.size(); i++) {
diff --git a/aegisub/src/auto4_base.cpp b/aegisub/src/auto4_base.cpp
index 38a9b14f1c98e0b2785d912543b794434e894628..7118d673ffa76e32bed47ce26d421905724d937e 100644
--- a/aegisub/src/auto4_base.cpp
+++ b/aegisub/src/auto4_base.cpp
@@ -289,7 +289,7 @@ namespace Automation4 {
 		// copied from auto3
 		include_path.clear();
 		include_path.EnsureFileAccessible(filename);
-		wxStringTokenizer toker(lagi_wxString(OPT_GET("Path/Automation/Include")->GetString()), "|", wxTOKEN_STRTOK);
+		wxStringTokenizer toker(to_wx(OPT_GET("Path/Automation/Include")->GetString()), "|", wxTOKEN_STRTOK);
 		while (toker.HasMoreTokens()) {
 			// todo? make some error reporting here
 			wxFileName path(StandardPaths::DecodePath(toker.GetNextToken()));
@@ -421,7 +421,7 @@ namespace Automation4 {
 
 		wxStringTokenizer tok(local_scripts, "|", wxTOKEN_STRTOK);
 		wxFileName assfn(context->ass->filename);
-		wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString()));
+		wxString autobasefn(to_wx(OPT_GET("Path/Automation/Base")->GetString()));
 		while (tok.HasMoreTokens()) {
 			wxString trimmed = tok.GetNextToken().Trim(true).Trim(false);
 			char first_char = trimmed[0];
@@ -461,7 +461,7 @@ namespace Automation4 {
 		// 3. If step 2 failed, or absolute path is shorter than path relative to ass, use absolute path ("/")
 		// 4. Otherwise, use path relative to ass ("~")
 		wxString scripts_string;
-		wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString()));
+		wxString autobasefn(to_wx(OPT_GET("Path/Automation/Base")->GetString()));
 
 		for (auto script : GetScripts()) {
 			if (!scripts_string.empty())
diff --git a/aegisub/src/auto4_lua.cpp b/aegisub/src/auto4_lua.cpp
index d1c3a361a141fe92738fb9203049a789b6641262..68310032d9a79be35efc2a2c9eae853c23398bf2 100644
--- a/aegisub/src/auto4_lua.cpp
+++ b/aegisub/src/auto4_lua.cpp
@@ -461,7 +461,7 @@ namespace Automation4 {
 			if (lua_load(L, script_reader.reader_func, &script_reader, GetPrettyFilename().utf8_str())) {
 				wxString err = wxString::Format("Error loading Lua script \"%s\":\n\n%s", GetPrettyFilename(), get_wxstring(L, -1));
 				lua_pop(L, 1);
-				throw ScriptLoadError(STD_STR(err));
+				throw ScriptLoadError(from_wx(err));
 			}
 			_stackcheck.check_stack(1);
 
@@ -472,7 +472,7 @@ namespace Automation4 {
 				// error occurred, assumed to be on top of Lua stack
 				wxString err = wxString::Format("Error initialising Lua script \"%s\":\n\n%s", GetPrettyFilename(), get_wxstring(L, -1));
 				lua_pop(L, 1);
-				throw ScriptLoadError(STD_STR(err));
+				throw ScriptLoadError(from_wx(err));
 			}
 			_stackcheck.check_stack(0);
 
@@ -786,7 +786,7 @@ namespace Automation4 {
 	, cmd_type(cmd::COMMAND_NORMAL)
 	{
 		lua_getfield(L, LUA_REGISTRYINDEX, "filename");
-		cmd_name = STD_STR(wxString::Format("automation/lua/%s/%s", get_wxstring(L, -1), check_wxstring(L, 1)));
+		cmd_name = from_wx(wxString::Format("automation/lua/%s/%s", get_wxstring(L, -1), check_wxstring(L, 1)));
 
 		if (!lua_isfunction(L, 3))
 			luaL_error(L, "The macro processing function must be a function");
diff --git a/aegisub/src/auto4_lua_dialog.cpp b/aegisub/src/auto4_lua_dialog.cpp
index eca10d94180a98672f013a737221b91940284a41..65a82f88b8854492d7b001d202d306b4f667b099 100644
--- a/aegisub/src/auto4_lua_dialog.cpp
+++ b/aegisub/src/auto4_lua_dialog.cpp
@@ -135,7 +135,7 @@ namespace Automation4 {
 	, width(get_field(L, "width", 1))
 	, height(get_field(L, "height", 1))
 	{
-		LOG_D("automation/lua/dialog") << "created control: '" << STD_STR(name) << "', (" << x << "," << y << ")(" << width << "," << height << "), "<< STD_STR(hint);
+		LOG_D("automation/lua/dialog") << "created control: '" << from_wx(name) << "', (" << x << "," << y << ")(" << width << "," << height << "), "<< from_wx(hint);
 	}
 
 	namespace LuaControl {
@@ -566,7 +566,7 @@ namespace Automation4 {
 			if (buttons.size() > 0) {
 				LOG_D("automation/lua/dialog") << "creating user buttons";
 				for (size_t i = 0; i < buttons.size(); ++i) {
-					LOG_D("automation/lua/dialog") << "button '" << STD_STR(buttons[i]) << "' gets id " << 1001+(wxWindowID)i;
+					LOG_D("automation/lua/dialog") << "button '" << from_wx(buttons[i]) << "' gets id " << 1001+(wxWindowID)i;
 
 					bs->Add(new wxButton(window, 1001+(wxWindowID)i, buttons[i]));
 				}
@@ -604,7 +604,7 @@ namespace Automation4 {
 				LOG_D("automation/lua/dialog") << "default buttons, button 1 bushed, Ok button";
 				lua_pushboolean(L, 1);
 			} else {
-				LOG_D("automation/lua/dialog") << "user button: " << STD_STR(buttons.at(btn-1));
+				LOG_D("automation/lua/dialog") << "user button: " << from_wx(buttons.at(btn-1));
 				// button_pushed is index+1 to reserve 0 for Cancel
 				lua_pushstring(L, buttons.at(btn-1).utf8_str());
 			}
diff --git a/aegisub/src/auto4_lua_scriptreader.cpp b/aegisub/src/auto4_lua_scriptreader.cpp
index ec3bfa9f66d9cf03d3a101d20132d18768595eee..4580f7cb0c250751b4acd5de8d62c8c08918a5c3 100644
--- a/aegisub/src/auto4_lua_scriptreader.cpp
+++ b/aegisub/src/auto4_lua_scriptreader.cpp
@@ -32,7 +32,7 @@
 namespace Automation4 {
 	LuaScriptReader::LuaScriptReader(wxString const& filename)
 	: conv(new agi::charset::IconvWrapper(CharSetDetect::GetEncoding(filename).c_str(), "utf-8", false))
-	, file(agi::io::Open(STD_STR(filename)))
+	, file(agi::io::Open(from_wx(filename)))
 	{
 	}
 
diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp
index 6366ae4ccd21eae77226a9a5b7b30bca2f399d0d..6270aefc81876fc155f25667a484e26254a00ff6 100644
--- a/aegisub/src/base_grid.cpp
+++ b/aegisub/src/base_grid.cpp
@@ -216,7 +216,7 @@ void BaseGrid::OnHighlightVisibleChange(agi::OptionValue const& opt) {
 }
 
 void BaseGrid::UpdateStyle() {
-	wxString fontname = lagi_wxString(OPT_GET("Subtitle/Grid/Font Face")->GetString());
+	wxString fontname = to_wx(OPT_GET("Subtitle/Grid/Font Face")->GetString());
 	if (fontname.empty()) fontname = "Tahoma";
 	font.SetFaceName(fontname);
 	font.SetPointSize(OPT_GET("Subtitle/Grid/Font Size")->GetInt());
@@ -492,7 +492,7 @@ void BaseGrid::DrawImage(wxDC &dc, bool paint_columns[]) {
 	int override_mode = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt();
 	wxString replace_char;
 	if (override_mode == 1)
-		replace_char = lagi_wxString(OPT_GET("Subtitle/Grid/Hide Overrides Char")->GetString());
+		replace_char = to_wx(OPT_GET("Subtitle/Grid/Hide Overrides Char")->GetString());
 
 	for (int i = 0; i < nDraw + 1; i++) {
 		int curRow = i + yPos - 1;
diff --git a/aegisub/src/command/app.cpp b/aegisub/src/command/app.cpp
index 5819f1a29d605590156293062cd4953a7c954322..dc52271799d921726dafc45cc59c79fbfe7fe708 100644
--- a/aegisub/src/command/app.cpp
+++ b/aegisub/src/command/app.cpp
@@ -185,7 +185,7 @@ struct app_language : public Command {
 		wxString new_language = wxGetApp().locale.PickLanguage();
 		if (!new_language) return;
 
-		OPT_SET("App/Language")->SetString(STD_STR(new_language));
+		OPT_SET("App/Language")->SetString(from_wx(new_language));
 
 		// Ask to restart program
 		int result = wxMessageBox("Aegisub needs to be restarted so that the new language can be applied. Restart now?", "Restart Aegisub?", wxYES_NO | wxICON_QUESTION |  wxCENTER);
diff --git a/aegisub/src/command/audio.cpp b/aegisub/src/command/audio.cpp
index 4e70b5b969dd69fdf561738a94311430d8ce451e..107514cd95045734bc81a02b143dfa8a683284b4 100644
--- a/aegisub/src/command/audio.cpp
+++ b/aegisub/src/command/audio.cpp
@@ -88,19 +88,19 @@ struct audio_open : public Command {
 
 	void operator()(agi::Context *c) {
 		try {
-			wxString path = lagi_wxString(OPT_GET("Path/Last/Audio")->GetString());
+			wxString path = to_wx(OPT_GET("Path/Last/Audio")->GetString());
 			wxString str = _("Audio Formats") + " (*.aac,*.ac3,*.ape,*.dts,*.flac,*.m4a,*.mka,*.mp3,*.mp4,*.ogg,*.w64,*.wav,*.wma)|*.aac;*.ac3;*.ape;*.dts;*.flac;*.m4a;*.mka;*.mp3;*.mp4;*.ogg;*.w64;*.wav;*.wma|"
 						+ _("Video Formats") + " (*.asf,*.avi,*.avs,*.d2v,*.m2ts,*.m4v,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.webm,*.wmv,*.ts)|*.asf;*.avi;*.avs;*.d2v;*.m2ts;*.m4v;*.mkv;*.mov;*.mp4;*.mpeg;*.mpg;*.ogm;*.webm;*.wmv;*.ts|"
 						+ _("All Files") + " (*.*)|*.*";
 			wxString filename = wxFileSelector(_("Open Audio File"),path,"","",str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
 			if (!filename.empty()) {
 				c->audioController->OpenAudio(filename);
-				OPT_SET("Path/Last/Audio")->SetString(STD_STR(wxFileName(filename).GetPath()));
+				OPT_SET("Path/Last/Audio")->SetString(from_wx(wxFileName(filename).GetPath()));
 			}
 		}
 		catch (agi::UserCancelException const&) { }
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+			wxMessageBox(to_wx(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 		}
 	}
 };
@@ -118,7 +118,7 @@ struct audio_open_blank : public Command {
 			c->audioController->OpenAudio("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000");
 		}
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+			wxMessageBox(to_wx(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 		}
 	}
 };
@@ -136,7 +136,7 @@ struct audio_open_noise : public Command {
 			c->audioController->OpenAudio("dummy-audio:noise?sr=44100&bd=16&ch=1&ln=396900000");
 		}
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+			wxMessageBox(to_wx(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 		}
 	}
 };
@@ -160,7 +160,7 @@ struct audio_open_video : public Command {
 		}
 		catch (agi::UserCancelException const&) { }
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+			wxMessageBox(to_wx(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 		}
 	}
 };
diff --git a/aegisub/src/command/command.cpp b/aegisub/src/command/command.cpp
index f470d9d5589655cde23ad2ba48168e67e2cb4b80..d0decba62db3022571ad65a5839a58edae6b33c2 100644
--- a/aegisub/src/command/command.cpp
+++ b/aegisub/src/command/command.cpp
@@ -32,7 +32,7 @@ namespace cmd {
 	static iterator find_command(std::string const& name) {
 		iterator it = cmd_map.find(name);
 		if (it == cmd_map.end())
-			throw CommandNotFound(STD_STR(wxString::Format(_("'%s' is not a valid command name"), lagi_wxString(name))));
+			throw CommandNotFound(from_wx(wxString::Format(_("'%s' is not a valid command name"), to_wx(name))));
 		return it;
 	}
 
diff --git a/aegisub/src/command/keyframe.cpp b/aegisub/src/command/keyframe.cpp
index 51c8eee71f07617a1ba89fb4b611cd90aa07f1a2..9245ae6fc3ec70e8b7108082bb951bae2b79eecb 100644
--- a/aegisub/src/command/keyframe.cpp
+++ b/aegisub/src/command/keyframe.cpp
@@ -78,7 +78,7 @@ struct keyframe_open : public Command {
 	STR_HELP("Opens a keyframe list file")
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Keyframes")->GetString());
 		wxString filename = wxFileSelector(
 			_("Open keyframes file"),
 			path,
@@ -88,7 +88,7 @@ struct keyframe_open : public Command {
 			wxFD_FILE_MUST_EXIST | wxFD_OPEN);
 
 		if (filename.empty()) return;
-		OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(wxFileName(filename).GetPath()));
+		OPT_SET("Path/Last/Keyframes")->SetString(from_wx(wxFileName(filename).GetPath()));
 		c->videoController->LoadKeyframes(filename);
 	}
 };
@@ -107,10 +107,10 @@ struct keyframe_save : public Command {
 	}
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Keyframes")->GetString());
 		wxString filename = wxFileSelector(_("Save keyframes file"),path,"","*.key.txt","Text files (*.txt)|*.txt",wxFD_OVERWRITE_PROMPT | wxFD_SAVE);
 		if (filename.empty()) return;
-		OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(wxFileName(filename).GetPath()));
+		OPT_SET("Path/Last/Keyframes")->SetString(from_wx(wxFileName(filename).GetPath()));
 		c->videoController->SaveKeyframes(filename);
 	}
 };
diff --git a/aegisub/src/command/recent.cpp b/aegisub/src/command/recent.cpp
index 546e98e21378400ea09de4f51c01dc56c0a38913..1cf54983b0f71aed0ae4b9bed2054145d0fedbd8 100644
--- a/aegisub/src/command/recent.cpp
+++ b/aegisub/src/command/recent.cpp
@@ -67,11 +67,11 @@ struct recent_audio_entry : public Command {
 
 	void operator()(agi::Context *c, int id) {
 		try {
-			c->audioController->OpenAudio(lagi_wxString(config::mru->GetEntry("Audio", id)));
+			c->audioController->OpenAudio(to_wx(config::mru->GetEntry("Audio", id)));
 		}
 		catch (agi::UserCancelException const&) { }
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+			wxMessageBox(to_wx(e.GetChainedMessage()), "Error loading file", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 		}
 	}
 };
@@ -83,7 +83,7 @@ struct recent_keyframes_entry : public Command {
 	STR_HELP("Open recent keyframes")
 
 	void operator()(agi::Context *c, int id) {
-		c->videoController->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", id)));
+		c->videoController->LoadKeyframes(to_wx(config::mru->GetEntry("Keyframes", id)));
 	}
 };
 
@@ -94,7 +94,7 @@ struct recent_subtitle_entry : public Command {
 	STR_HELP("Open recent subtitles")
 
 	void operator()(agi::Context *c, int id) {
-		wxGetApp().frame->LoadSubtitles(lagi_wxString(config::mru->GetEntry("Subtitle", id)));
+		wxGetApp().frame->LoadSubtitles(to_wx(config::mru->GetEntry("Subtitle", id)));
 	}
 };
 
@@ -105,7 +105,7 @@ struct recent_timecodes_entry : public Command {
 	STR_HELP("Open recent timecodes")
 
 	void operator()(agi::Context *c, int id) {
-		c->videoController->LoadTimecodes(lagi_wxString(config::mru->GetEntry("Timecodes", id)));
+		c->videoController->LoadTimecodes(to_wx(config::mru->GetEntry("Timecodes", id)));
 	}
 };
 
@@ -116,7 +116,7 @@ struct recent_video_entry : public Command {
 	STR_HELP("Open recent videos")
 
 	void operator()(agi::Context *c, int id) {
-		c->videoController->SetVideo(lagi_wxString(config::mru->GetEntry("Video", id)));
+		c->videoController->SetVideo(to_wx(config::mru->GetEntry("Video", id)));
 	}
 };
 
diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp
index 064a67a8570edaa15daf0ea05e6286552693ac50..a802e10365f9e4e99cd2923603a50deea8185cce 100644
--- a/aegisub/src/command/subtitle.cpp
+++ b/aegisub/src/command/subtitle.cpp
@@ -260,7 +260,7 @@ struct subtitle_open : public Command {
 	STR_HELP("Opens a subtitles file")
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Subtitles")->GetString());
 		wxString filename = wxFileSelector(_("Open subtitles file"),path,"","",SubtitleFormat::GetWildcards(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
 		if (!filename.empty()) {
 			wxGetApp().frame->LoadSubtitles(filename);
@@ -291,7 +291,7 @@ struct subtitle_open_charset : public Command {
 
 	void operator()(agi::Context *c) {
 		// Initialize charsets
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Subtitles")->GetString());
 
 		// Get options and load
 		wxString filename = wxFileSelector(_("Open subtitles file"),path,"","",SubtitleFormat::GetWildcards(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@@ -339,7 +339,7 @@ struct subtitle_properties : public Command {
 static void save_subtitles(agi::Context *c, wxString filename) {
 	if (filename.empty()) {
 		c->videoController->Stop();
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Subtitles")->GetString());
 		wxFileName origPath(c->ass->filename);
 		filename = wxFileSelector(_("Save subtitles file"), path, origPath.GetName() + ".ass", "ass", "Advanced Substation Alpha (*.ass)|*.ass", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, c->parent);
 		if (filename.empty()) return;
@@ -349,7 +349,7 @@ static void save_subtitles(agi::Context *c, wxString filename) {
 		c->ass->Save(filename, true, true);
 	}
 	catch (const agi::Exception& err) {
-		wxMessageBox(lagi_wxString(err.GetMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, c->parent);
+		wxMessageBox(to_wx(err.GetMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, c->parent);
 	}
 	catch (const char *err) {
 		wxMessageBox(err, "Error", wxOK | wxICON_ERROR | wxCENTER, c->parent);
diff --git a/aegisub/src/command/timecode.cpp b/aegisub/src/command/timecode.cpp
index d838be449760a9aeb2f2f1fa8450d93d8a1808c9..bf937278d85b01dd556a47adeec4da34b699d432 100644
--- a/aegisub/src/command/timecode.cpp
+++ b/aegisub/src/command/timecode.cpp
@@ -77,12 +77,12 @@ struct timecode_open : public Command {
 	STR_HELP("Opens a VFR timecodes v1 or v2 file")
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Timecodes")->GetString());
 		wxString str = _("All Supported Formats") + " (*.txt)|*.txt|" + _("All Files") + " (*.*)|*.*";
 		wxString filename = wxFileSelector(_("Open Timecodes File"),path,"","",str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
 		if (!filename.empty()) {
 			c->videoController->LoadTimecodes(filename);
-			OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(wxFileName(filename).GetPath()));
+			OPT_SET("Path/Last/Timecodes")->SetString(from_wx(wxFileName(filename).GetPath()));
 		}
 	}
 };
@@ -101,12 +101,12 @@ struct timecode_save : public Command {
 	}
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Timecodes")->GetString());
 		wxString str = _("All Supported Formats") + " (*.txt)|*.txt|" + _("All Files") + " (*.*)|*.*";
 		wxString filename = wxFileSelector(_("Save Timecodes File"),path,"","",str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
 		if (!filename.empty()) {
 			c->videoController->SaveTimecodes(filename);
-			OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(wxFileName(filename).GetPath()));
+			OPT_SET("Path/Last/Timecodes")->SetString(from_wx(wxFileName(filename).GetPath()));
 		}
 	}
 };
diff --git a/aegisub/src/command/tool.cpp b/aegisub/src/command/tool.cpp
index 8151bac0545fe2f77dc1f171dc0c1ed2f3233467..a72d97e3591226870aab045d02180aad79f1b591 100644
--- a/aegisub/src/command/tool.cpp
+++ b/aegisub/src/command/tool.cpp
@@ -228,7 +228,7 @@ struct tool_translation_assistant : public Command {
 			c->dialog->ShowModal<DialogTranslation>(c);
 		}
 		catch (agi::Exception const& e) {
-			wxMessageBox(lagi_wxString(e.GetChainedMessage()));
+			wxMessageBox(to_wx(e.GetChainedMessage()));
 		}
 	}
 };
diff --git a/aegisub/src/command/video.cpp b/aegisub/src/command/video.cpp
index 8c0cda8faea19b092e84c2a34eb1ce03c5974bc2..21f232e56b90451d8bf9e310053c8e3954531368 100644
--- a/aegisub/src/command/video.cpp
+++ b/aegisub/src/command/video.cpp
@@ -473,7 +473,7 @@ struct video_frame_prev_large : public validator_video_loaded {
 
 static void save_snapshot(agi::Context *c, bool raw) {
 	static const agi::OptionValue* ssPath = OPT_GET("Path/Screenshot");
-	wxString option = lagi_wxString(ssPath->GetString());
+	wxString option = to_wx(ssPath->GetString());
 	wxFileName videoFile(c->videoController->GetVideoName());
 	wxString basepath;
 
@@ -582,13 +582,13 @@ struct video_open : public Command {
 	STR_HELP("Opens a video file")
 
 	void operator()(agi::Context *c) {
-		wxString path = lagi_wxString(OPT_GET("Path/Last/Video")->GetString());
+		wxString path = to_wx(OPT_GET("Path/Last/Video")->GetString());
 		wxString str = _("Video Formats") + " (*.asf,*.avi,*.avs,*.d2v,*.m2ts,*.m4v,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.webm,*.wmv,*.ts,*.y4m,*.yuv)|*.asf;*.avi;*.avs;*.d2v;*.m2ts;*.m4v;*.mkv;*.mov;*.mp4;*.mpeg;*.mpg;*.ogm;*.webm;*.wmv;*.ts;*.y4m;*.yuv|"
 					 + _("All Files") + " (*.*)|*.*";
 		wxString filename = wxFileSelector(_("Open video file"),path,"","",str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
 		if (!filename.empty()) {
 			c->videoController->SetVideo(filename);
-			OPT_SET("Path/Last/Video")->SetString(STD_STR(wxFileName(filename).GetPath()));
+			OPT_SET("Path/Last/Video")->SetString(from_wx(wxFileName(filename).GetPath()));
 		}
 	}
 };
diff --git a/aegisub/src/compat.cpp b/aegisub/src/compat.cpp
index 7b2c104f454cfc9d84b5df0a0acaae5b7f7db9fa..b9ddd1e3c457371a3938a1a3d9528c6500f46a35 100644
--- a/aegisub/src/compat.cpp
+++ b/aegisub/src/compat.cpp
@@ -3,17 +3,18 @@
 
 #include <algorithm>
 
+template<typename T>
+wxArrayString to_wxAS(T const& src) {
+	wxArrayString ret;
+	ret.reserve(src.size());
+	transform(src.begin(), src.end(), std::back_inserter(ret), (wxString (*)(std::string const&))to_wx);
+	return ret;
+}
+
 wxArrayString lagi_MRU_wxAS(const wxString &list) {
-	const agi::MRUManager::MRUListMap *map = config::mru->Get(STD_STR(list));
-	wxArrayString work;
-	work.reserve(map->size());
-	transform(map->begin(), map->end(), std::back_inserter(work), lagi_wxString);
-	return work;
+	return to_wxAS(*config::mru->Get(from_wx(list)));
 }
 
 wxArrayString to_wx(std::vector<std::string> const& vec) {
-	wxArrayString ret;
-	ret.reserve(vec.size());
-	transform(vec.begin(), vec.end(), std::back_inserter(ret), lagi_wxString);
-	return ret;
+	return to_wxAS(vec);
 }
diff --git a/aegisub/src/compat.h b/aegisub/src/compat.h
index 88c3f39c78761f3602bb47289a705577b2375692..b4a179aba2c7757a877761e92328734deaac7723 100644
--- a/aegisub/src/compat.h
+++ b/aegisub/src/compat.h
@@ -7,8 +7,6 @@
 
 #include <libaegisub/color.h>
 
-#define STD_STR(x) std::string((x).utf8_str())
-
 inline wxColour to_wx(agi::Color color) { return wxColour(color.r, color.g, color.b, 255 - color.a); }
 inline wxString to_wx(std::string const& str) { return wxString(str.c_str(), wxConvUTF8); }
 wxArrayString to_wx(std::vector<std::string> const& vec);
@@ -16,5 +14,4 @@ wxArrayString to_wx(std::vector<std::string> const& vec);
 inline agi::Color from_wx(wxColour color) { return agi::Color(color.Red(), color.Green(), color.Blue(), 255 - color.Alpha()); }
 inline std::string from_wx(wxString const& str) { return std::string(str.utf8_str()); }
 
-inline wxString lagi_wxString(const std::string &str) { return wxString(str.c_str(), wxConvUTF8); }
 wxArrayString lagi_MRU_wxAS(const wxString &list);
diff --git a/aegisub/src/dialog_attachments.cpp b/aegisub/src/dialog_attachments.cpp
index 7b800bd45cd0b2573ed0ec6fe03239fad93a42cf..9c5b1358ce1066d342b652db620ff60125f6e33e 100644
--- a/aegisub/src/dialog_attachments.cpp
+++ b/aegisub/src/dialog_attachments.cpp
@@ -151,7 +151,7 @@ void DialogAttachments::AttachFile(wxFileDialog &diag, AssEntryGroup group, wxSt
 void DialogAttachments::OnAttachFont(wxCommandEvent &) {
 	wxFileDialog diag(this,
 		_("Choose file to be attached"),
-		lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString()), "", "Font Files (*.ttf)|*.ttf",
+		to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString()), "", "Font Files (*.ttf)|*.ttf",
 		wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
 
 	AttachFile(diag, ENTRY_FONT, _("attach font file"));
@@ -176,13 +176,13 @@ void DialogAttachments::OnExtract(wxCommandEvent &) {
 
 	// Multiple or single?
 	if (listView->GetNextSelected(i) != -1)
-		path = wxDirSelector(_("Select the path to save the files to:"),lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString())) + "/";
+		path = wxDirSelector(_("Select the path to save the files to:"),to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString())) + "/";
 	else {
 		// Default path
 		wxString defPath = ((AssAttachment*)wxUIntToPtr(listView->GetItemData(i)))->GetFileName();
 		path = wxFileSelector(
 			_("Select the path to save the file to:"),
-			lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString()),
+			to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString()),
 			defPath,
 			".ttf",
 			"Font Files (*.ttf)|*.ttf",
diff --git a/aegisub/src/dialog_automation.cpp b/aegisub/src/dialog_automation.cpp
index f3799b978415d5f4ff513bdf3654fd497b6cad88..164b1b8f865ea06b4483669a3a1a4b6b05261d99 100644
--- a/aegisub/src/dialog_automation.cpp
+++ b/aegisub/src/dialog_automation.cpp
@@ -187,7 +187,7 @@ void DialogAutomation::OnAdd(wxCommandEvent &)
 {
 	wxFileDialog diag(this,
 		_("Add Automation script"),
-		lagi_wxString(OPT_GET("Path/Last/Automation")->GetString()),
+		to_wx(OPT_GET("Path/Last/Automation")->GetString()),
 		"",
 		Automation4::ScriptFactory::GetWildcardStr(),
 		wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
@@ -199,7 +199,7 @@ void DialogAutomation::OnAdd(wxCommandEvent &)
 
 	for (auto const& fname : fnames) {
 		wxFileName fnpath(fname);
-		OPT_SET("Path/Last/Automation")->SetString(STD_STR(fnpath.GetPath()));
+		OPT_SET("Path/Last/Automation")->SetString(from_wx(fnpath.GetPath()));
 
 		if (has_file(local_manager->GetScripts(), fnpath) || has_file(global_manager->GetScripts(), fnpath)) {
 			wxLogError("Script '%s' is already loaded", fname);
diff --git a/aegisub/src/dialog_fonts_collector.cpp b/aegisub/src/dialog_fonts_collector.cpp
index 2dfd8b36138d86b2f693cd480f59ea7e85bb4ac1..6fd88e0c6d0a6b2b7a6519d30fd7ba21f6a66c11 100644
--- a/aegisub/src/dialog_fonts_collector.cpp
+++ b/aegisub/src/dialog_fonts_collector.cpp
@@ -228,7 +228,7 @@ DialogFontsCollector::DialogFontsCollector(agi::Context *c)
 	wxStaticBoxSizer *destination_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Destination"));
 
 	dest_label = new wxStaticText(this, -1, " ");
-	dest_ctrl = new wxTextCtrl(this, -1, StandardPaths::DecodePath(lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString())));
+	dest_ctrl = new wxTextCtrl(this, -1, StandardPaths::DecodePath(to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString())));
 	dest_browse_button = new wxButton(this, -1, _("&Browse..."));
 
 	wxSizer *dest_browse_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -313,7 +313,7 @@ void DialogFontsCollector::OnStart(wxCommandEvent &) {
 	}
 
 	if (action != CheckFontsOnly)
-		OPT_SET("Path/Fonts Collector Destination")->SetString(STD_STR(dest));
+		OPT_SET("Path/Fonts Collector Destination")->SetString(from_wx(dest));
 
 	// Disable the UI while it runs as we don't support canceling
 	EnableCloseButton(false);
diff --git a/aegisub/src/dialog_search_replace.cpp b/aegisub/src/dialog_search_replace.cpp
index e7d21e89822d8954f7e9c8999c544e5836324837..d146062450229ce5ada65d43f10575f09f70e6a3 100644
--- a/aegisub/src/dialog_search_replace.cpp
+++ b/aegisub/src/dialog_search_replace.cpp
@@ -184,7 +184,7 @@ void DialogSearchReplace::FindReplace(int mode) {
 		if (hasReplace) {
 			wxString ReplaceWith = ReplaceEdit->GetValue();
 			Search.ReplaceWith = ReplaceWith;
-			config::mru->Add("Replace", STD_STR(ReplaceWith));
+			config::mru->Add("Replace", from_wx(ReplaceWith));
 		}
 	}
 
@@ -194,11 +194,11 @@ void DialogSearchReplace::FindReplace(int mode) {
 		Search.ReplaceWith = ReplaceWith;
 		if (mode == 1) Search.ReplaceNext();
 		else Search.ReplaceAll();
-		config::mru->Add("Replace", STD_STR(ReplaceWith));
+		config::mru->Add("Replace", from_wx(ReplaceWith));
 	}
 
 	// Add to history
-	config::mru->Add("Find", STD_STR(LookFor));
+	config::mru->Add("Find", from_wx(LookFor));
 	UpdateDropDowns();
 }
 
diff --git a/aegisub/src/dialog_selection.cpp b/aegisub/src/dialog_selection.cpp
index 46e30441f5c3d320f9380fcc590d987baaa35a2d..6562295becf3212be9f7fca16fb9b860a114a388 100644
--- a/aegisub/src/dialog_selection.cpp
+++ b/aegisub/src/dialog_selection.cpp
@@ -145,7 +145,7 @@ wxDialog (c->parent, -1, _("Select"), wxDefaultPosition, wxDefaultSize, wxCAPTIO
 			match_radio_line->Add(case_sensitive = new wxCheckBox(this, -1, _("Match c&ase")), radio_flags);
 			match_sizer->Add(match_radio_line);
 		}
-		match_sizer->Add(match_text = new wxTextCtrl(this, -1, lagi_wxString(OPT_GET("Tool/Select Lines/Text")->GetString())), main_flags);
+		match_sizer->Add(match_text = new wxTextCtrl(this, -1, to_wx(OPT_GET("Tool/Select Lines/Text")->GetString())), main_flags);
 
 		main_sizer->Add(match_sizer, main_flags);
 	}
@@ -193,7 +193,7 @@ wxDialog (c->parent, -1, _("Select"), wxDefaultPosition, wxDefaultSize, wxCAPTIO
 }
 
 DialogSelection::~DialogSelection() {
-	OPT_SET("Tool/Select Lines/Text")->SetString(STD_STR(match_text->GetValue()));
+	OPT_SET("Tool/Select Lines/Text")->SetString(from_wx(match_text->GetValue()));
 	OPT_SET("Tool/Select Lines/Condition")->SetInt(select_unmatching_lines->GetValue());
 	OPT_SET("Tool/Select Lines/Field")->SetInt(dialogue_field->GetSelection());
 	OPT_SET("Tool/Select Lines/Action")->SetInt(selection_change_type->GetSelection());
diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp
index 54b71af63187c2ebad61de19fed049ecab78812c..5da7a7250fd54b7819c0ac5ff898fb17512dec17 100644
--- a/aegisub/src/dialog_shift_times.cpp
+++ b/aegisub/src/dialog_shift_times.cpp
@@ -55,11 +55,11 @@
 #include "video_context.h"
 
 static wxString get_history_string(json::Object &obj) {
-	wxString filename = lagi_wxString(obj["filename"]);
+	wxString filename = to_wx(obj["filename"]);
 	if (filename.empty())
 		filename = _("unsaved");
 
-	wxString shift_amount(lagi_wxString(obj["amount"]));
+	wxString shift_amount(to_wx(obj["amount"]));
 	if (!obj["is by time"])
 		shift_amount = wxString::Format(_("%s frames"), shift_amount);
 
@@ -99,7 +99,7 @@ static wxString get_history_string(json::Object &obj) {
 DialogShiftTimes::DialogShiftTimes(agi::Context *context)
 : wxDialog(context->parent, -1, _("Shift Times"))
 , context(context)
-, history_filename(STD_STR(StandardPaths::DecodePath("?user/shift_history.json")))
+, history_filename(from_wx(StandardPaths::DecodePath("?user/shift_history.json")))
 , history(new json::Array)
 , timecodes_loaded_slot(context->videoController->AddTimecodesListener(&DialogShiftTimes::OnTimecodesLoaded, this))
 , selected_set_changed_slot(context->selectionController->AddSelectionListener(&DialogShiftTimes::OnSelectedSetChanged, this))
@@ -235,7 +235,7 @@ void DialogShiftTimes::OnSelectedSetChanged() {
 
 
 void DialogShiftTimes::OnClear(wxCommandEvent &) {
-	wxRemoveFile(lagi_wxString(history_filename));
+	wxRemoveFile(to_wx(history_filename));
 	history_box->Clear();
 	history->clear();
 }
@@ -256,12 +256,12 @@ void DialogShiftTimes::OnHistoryClick(wxCommandEvent &evt) {
 
 	json::Object& obj = (*history)[entry];
 	if (obj["is by time"]) {
-		shift_time->SetTime(AssTime(lagi_wxString(obj["amount"])));
+		shift_time->SetTime(AssTime(to_wx(obj["amount"])));
 		shift_by_time->SetValue(true);
 		OnByTime(evt);
 	}
 	else {
-		shift_frames->SetValue(lagi_wxString(obj["amount"]));
+		shift_frames->SetValue(to_wx(obj["amount"]));
 		if (shift_by_frames->IsEnabled()) {
 			shift_by_frames->SetValue(true);
 			OnByFrames(evt);
@@ -279,10 +279,10 @@ void DialogShiftTimes::OnHistoryClick(wxCommandEvent &evt) {
 
 void DialogShiftTimes::SaveHistory(json::Array const& shifted_blocks) {
 	json::Object new_entry;
-	new_entry["filename"] = STD_STR(wxFileName(context->ass->filename).GetFullName());
+	new_entry["filename"] = from_wx(wxFileName(context->ass->filename).GetFullName());
 	new_entry["is by time"] = shift_by_time->GetValue();
 	new_entry["is backward"] = shift_backward->GetValue();
-	new_entry["amount"] = STD_STR(shift_by_time->GetValue() ? shift_time->GetValue() : shift_frames->GetValue());
+	new_entry["amount"] = from_wx(shift_by_time->GetValue() ? shift_time->GetValue() : shift_frames->GetValue());
 	new_entry["fields"] = time_fields->GetSelection();
 	new_entry["mode"] = selection_mode->GetSelection();
 	new_entry["selection"] = shifted_blocks;
diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp
index 9922300b656edb3eeef53f216874a040c9d04cac..77e87229860ccd21ff4e647c4110edd3db8ff543 100644
--- a/aegisub/src/dialog_spellchecker.cpp
+++ b/aegisub/src/dialog_spellchecker.cpp
@@ -110,7 +110,7 @@ DialogSpellChecker::DialogSpellChecker(agi::Context *context)
 		}
 
 		language = new wxComboBox(this, -1, "", wxDefaultPosition, wxDefaultSize, language_names, wxCB_DROPDOWN | wxCB_READONLY);
-		wxString cur_lang = lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString());
+		wxString cur_lang = to_wx(OPT_GET("Tool/Spell Checker/Language")->GetString());
 		int cur_lang_index = dictionary_lang_codes.Index(cur_lang);
 		if (cur_lang_index == wxNOT_FOUND) cur_lang_index = dictionary_lang_codes.Index("en");
 		if (cur_lang_index == wxNOT_FOUND) cur_lang_index = dictionary_lang_codes.Index("en_US");
@@ -185,7 +185,7 @@ void DialogSpellChecker::OnReplace(wxCommandEvent&) {
 
 void DialogSpellChecker::OnChangeLanguage(wxCommandEvent&) {
 	wxString code = dictionary_lang_codes[language->GetSelection()];
-	OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(code));
+	OPT_SET("Tool/Spell Checker/Language")->SetString(from_wx(code));
 
 	FindNext();
 }
diff --git a/aegisub/src/dialog_style_editor.cpp b/aegisub/src/dialog_style_editor.cpp
index 5a3b9ca5b6fcebdf8f3fb5d15135c21cd86d8059..42360bdc5660cd3a8e15fa8412be95bb9dbf3cf1 100644
--- a/aegisub/src/dialog_style_editor.cpp
+++ b/aegisub/src/dialog_style_editor.cpp
@@ -326,7 +326,7 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
 	PreviewText = nullptr;
 	ColourButton *previewButton = 0;
 	if (!SubtitlesProviderFactory::GetClasses().empty()) {
-		PreviewText = new wxTextCtrl(this, -1, lagi_wxString(OPT_GET("Tool/Style Editor/Preview Text")->GetString()));
+		PreviewText = new wxTextCtrl(this, -1, to_wx(OPT_GET("Tool/Style Editor/Preview Text")->GetString()));
 		previewButton = new ColourButton(this, -1, wxSize(45, 16), OPT_GET("Colour/Style Editor/Background/Preview")->GetColor());
 		SubsPreview = new SubtitlesPreview(this, wxSize(100, 60), wxSUNKEN_BORDER, OPT_GET("Colour/Style Editor/Background/Preview")->GetColor());
 
@@ -476,7 +476,7 @@ void DialogStyleEditor::Apply(bool apply, bool close) {
 	if (close) {
 		EndModal(apply);
 		if (PreviewText)
-			OPT_SET("Tool/Style Editor/Preview Text")->SetString(STD_STR(PreviewText->GetValue()));
+			OPT_SET("Tool/Style Editor/Preview Text")->SetString(from_wx(PreviewText->GetValue()));
 	}
 }
 
diff --git a/aegisub/src/dialog_style_manager.cpp b/aegisub/src/dialog_style_manager.cpp
index 680f09cb344d61277c415fa3e9e94951350f5817..ed9b77769cbc6a4304d8d6b01c23fc66ba8e5e83 100644
--- a/aegisub/src/dialog_style_manager.cpp
+++ b/aegisub/src/dialog_style_manager.cpp
@@ -571,18 +571,18 @@ void DialogStyleManager::OnCurrentDelete() {
 
 void DialogStyleManager::OnCurrentImport() {
 	// Get file name
-	wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
+	wxString path = to_wx(OPT_GET("Path/Last/Subtitles")->GetString());
 	wxString filename = wxFileSelector(_("Open subtitles file"),path,"","",SubtitleFormat::GetWildcards(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
 	if (!filename) return;
 
-	OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(wxFileName(filename).GetPath()));
+	OPT_SET("Path/Last/Subtitles")->SetString(from_wx(wxFileName(filename).GetPath()));
 
 	AssFile temp;
 	try {
 		temp.Load(filename);
 	}
 	catch (agi::Exception const& err) {
-		wxMessageBox(lagi_wxString(err.GetChainedMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
+		wxMessageBox(to_wx(err.GetChainedMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
 	}
 	catch (...) {
 		wxMessageBox("Unknown error", "Error", wxOK | wxICON_ERROR | wxCENTER, this);
diff --git a/aegisub/src/dialog_text_import.cpp b/aegisub/src/dialog_text_import.cpp
index 99396e7e29c7994ca6687684e8fabd84c1b80457..a6d4dfc533528875ede50b1fde7e93d99fea9871 100644
--- a/aegisub/src/dialog_text_import.cpp
+++ b/aegisub/src/dialog_text_import.cpp
@@ -49,8 +49,8 @@ DialogTextImport::DialogTextImport()
 	// Main controls
 	wxFlexGridSizer *fg = new wxFlexGridSizer(2, 5, 5);
 	wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
-	edit_separator = new wxTextCtrl(this, -1, lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString()));
-	edit_comment = new wxTextCtrl(this, -1, lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString()));
+	edit_separator = new wxTextCtrl(this, -1, to_wx(OPT_GET("Tool/Import/Text/Actor Separator")->GetString()));
+	edit_comment = new wxTextCtrl(this, -1, to_wx(OPT_GET("Tool/Import/Text/Comment Starter")->GetString()));
 
 	// Dialog layout
 	fg->Add(new wxStaticText(this, -1, _("Actor separator:")), 0, wxALIGN_CENTRE_VERTICAL);
@@ -66,8 +66,8 @@ DialogTextImport::DialogTextImport()
 }
 
 void DialogTextImport::OnOK(wxCommandEvent &) {
-	OPT_SET("Tool/Import/Text/Actor Separator")->SetString(STD_STR(edit_separator->GetValue()));
-	OPT_SET("Tool/Import/Text/Comment Starter")->SetString(STD_STR(edit_comment->GetValue()));
+	OPT_SET("Tool/Import/Text/Actor Separator")->SetString(from_wx(edit_separator->GetValue()));
+	OPT_SET("Tool/Import/Text/Comment Starter")->SetString(from_wx(edit_comment->GetValue()));
 
 	EndModal(wxID_OK);
 }
diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp
index 146f2541f396bfa811b66558781592d392b40431..d6ae0bab5f9036c3c00ee6e6a3cb2c18879d2e30 100644
--- a/aegisub/src/dialog_translation.cpp
+++ b/aegisub/src/dialog_translation.cpp
@@ -160,7 +160,7 @@ DialogTranslation::DialogTranslation(agi::Context *c)
 	blocks = active_line->ParseTags();
 	if (bad_block(blocks[0])) {
 		if (!NextBlock())
-			throw NothingToTranslate(STD_STR(_("There is nothing to translate in the file.")));
+			throw NothingToTranslate(from_wx(_("There is nothing to translate in the file.")));
 	}
 	else
 		UpdateDisplay();
diff --git a/aegisub/src/dialog_version_check.cpp b/aegisub/src/dialog_version_check.cpp
index 9d73b66bc5f9eeb1ab63933d69d5a07d40785b0f..8677118186858df8c8551276e11b1bc3a2b66de9 100644
--- a/aegisub/src/dialog_version_check.cpp
+++ b/aegisub/src/dialog_version_check.cpp
@@ -325,7 +325,7 @@ static wxString GetSystemLanguage()
 
 static wxString GetAegisubLanguage()
 {
-	return lagi_wxString(OPT_GET("App/Language")->GetString());
+	return to_wx(OPT_GET("App/Language")->GetString());
 }
 
 template<class OutIter>
@@ -375,11 +375,11 @@ void AegisubVersionCheckerThread::DoCheck()
 			break;
 		case 6:
 		case 7:
-			throw VersionCheckError(STD_STR(_("Could not connect to updates server.")));
+			throw VersionCheckError(from_wx(_("Could not connect to updates server.")));
 		case 22:
-			throw VersionCheckError(STD_STR(_("Could not download from updates server.")));
+			throw VersionCheckError(from_wx(_("Could not download from updates server.")));
 		default:
-			throw VersionCheckError(STD_STR(wxString::Format("curl failed with error code %d", ret)));
+			throw VersionCheckError(from_wx(wxString::Format("curl failed with error code %d", ret)));
 	}
 
 	agi::scoped_ptr<wxStringInputStream> stream(new wxStringInputStream(update_str));
@@ -399,14 +399,14 @@ void AegisubVersionCheckerThread::DoCheck()
 	http.SetFlags(wxSOCKET_WAITALL | wxSOCKET_BLOCK);
 
 	if (!http.Connect(UPDATE_CHECKER_SERVER))
-		throw VersionCheckError(STD_STR(_("Could not connect to updates server.")));
+		throw VersionCheckError(from_wx(_("Could not connect to updates server.")));
 
 	agi::scoped_ptr<wxInputStream> stream(http.GetInputStream(path));
 	if (!stream) // check for null-pointer
-		throw VersionCheckError(STD_STR(_("Could not download from updates server.")));
+		throw VersionCheckError(from_wx(_("Could not download from updates server.")));
 
 	if (http.GetResponse() < 200 || http.GetResponse() >= 300) {
-		throw VersionCheckError(STD_STR(wxString::Format(_("HTTP request failed, got HTTP response %d."), http.GetResponse())));
+		throw VersionCheckError(from_wx(wxString::Format(_("HTTP request failed, got HTTP response %d."), http.GetResponse())));
 	}
 #endif
 	wxTextInputStream text(*stream);
diff --git a/aegisub/src/ffmpegsource_common.cpp b/aegisub/src/ffmpegsource_common.cpp
index f89a383dc324ab8f9fa2d4d1348b60530b74398f..736c5783aacaba48f216296b8c50facf3365d29b 100644
--- a/aegisub/src/ffmpegsource_common.cpp
+++ b/aegisub/src/ffmpegsource_common.cpp
@@ -175,7 +175,7 @@ int FFmpegSourceProvider::AskForTrackSelection(const std::map<int,wxString> &Tra
 
 /// @brief Set ffms2 log level according to setting in config.dat
 void FFmpegSourceProvider::SetLogLevel() {
-	wxString LogLevel = lagi_wxString(OPT_GET("Provider/FFmpegSource/Log Level")->GetString());
+	wxString LogLevel = to_wx(OPT_GET("Provider/FFmpegSource/Log Level")->GetString());
 
 	if (!LogLevel.CmpNoCase("panic"))
 		FFMS_SetLogLevel(FFMS_LOG_PANIC);
@@ -197,7 +197,7 @@ void FFmpegSourceProvider::SetLogLevel() {
 
 
 FFMS_IndexErrorHandling FFmpegSourceProvider::GetErrorHandlingMode() {
-	wxString Mode = lagi_wxString(OPT_GET("Provider/Audio/FFmpegSource/Decode Error Handling")->GetString());
+	wxString Mode = to_wx(OPT_GET("Provider/Audio/FFmpegSource/Decode Error Handling")->GetString());
 
 	if (!Mode.CmpNoCase("ignore"))
 		return FFMS_IEH_IGNORE;
diff --git a/aegisub/src/font_file_lister_fontconfig.cpp b/aegisub/src/font_file_lister_fontconfig.cpp
index b383bdf2e778c728adc63debc11a5df704a72c53..209123ae8204a0679e1f59667204063cca569dfe 100644
--- a/aegisub/src/font_file_lister_fontconfig.cpp
+++ b/aegisub/src/font_file_lister_fontconfig.cpp
@@ -91,7 +91,7 @@ FontConfigFontFileLister::FontConfigFontFileLister(FontCollectorStatusCallback c
 FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(wxString const& facename, int bold, bool italic, std::set<wxUniChar> const& characters) {
 	CollectionResult ret;
 
-	std::string family = STD_STR(facename);
+	std::string family = from_wx(facename);
 	if (family[0] == '@')
 		family.erase(0, 1);
 	boost::to_lower(family);
diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp
index 972947df11695cbfa72c175d54f95db825fdff7e..f10bcd0c614efa83fd2bfa69ce7164a502ac3562 100644
--- a/aegisub/src/frame_main.cpp
+++ b/aegisub/src/frame_main.cpp
@@ -429,13 +429,13 @@ void FrameMain::LoadSubtitles(wxString const& filename, wxString const& charset)
 
 		wxFileName file(filename);
 		StandardPaths::SetPathValue("?script", file.GetPath());
-		config::mru->Add("Subtitle", STD_STR(filename));
-		OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(file.GetPath()));
+		config::mru->Add("Subtitle", from_wx(filename));
+		OPT_SET("Path/Last/Subtitles")->SetString(from_wx(file.GetPath()));
 
 		// Save backup of file
 		if (context->ass->CanSave() && OPT_GET("App/Auto/Backup")->GetBool()) {
 			if (file.FileExists()) {
-				wxString path = lagi_wxString(OPT_GET("Path/Auto/Backup")->GetString());
+				wxString path = to_wx(OPT_GET("Path/Auto/Backup")->GetString());
 				if (path.empty()) path = file.GetPath();
 				wxFileName dstpath(StandardPaths::DecodePath(path + "/"));
 				if (!dstpath.DirExists())
@@ -449,11 +449,11 @@ void FrameMain::LoadSubtitles(wxString const& filename, wxString const& charset)
 	}
 	catch (agi::FileNotFoundError const&) {
 		wxMessageBox(filename + " not found.", "Error", wxOK | wxICON_ERROR | wxCENTER, this);
-		config::mru->Remove("Subtitle", STD_STR(filename));
+		config::mru->Remove("Subtitle", from_wx(filename));
 		return;
 	}
 	catch (agi::Exception const& err) {
-		wxMessageBox(lagi_wxString(err.GetChainedMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
+		wxMessageBox(to_wx(err.GetChainedMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
 	}
 	catch (...) {
 		wxMessageBox("Unknown error", "Error", wxOK | wxICON_ERROR | wxCENTER, this);
@@ -566,7 +566,7 @@ void FrameMain::OnVideoOpen() {
 			LOG_D("video/open/audio") << "File " << context->videoController->GetVideoName() << " has no audio data: " << e.GetChainedMessage();
 		}
 		catch (agi::AudioOpenError const& err) {
-			wxMessageBox(lagi_wxString(err.GetMessage()), "Error loading audio", wxOK | wxICON_ERROR | wxCENTER);
+			wxMessageBox(to_wx(err.GetMessage()), "Error loading audio", wxOK | wxICON_ERROR | wxCENTER);
 		}
 	}
 }
@@ -663,7 +663,7 @@ void FrameMain::OnAutoSave(wxTimerEvent &) try {
 		StatusTimeout(wxString::Format(_("File backup saved as \"%s\"."), fn));
 }
 catch (const agi::Exception& err) {
-	StatusTimeout(lagi_wxString("Exception when attempting to autosave file: " + err.GetMessage()));
+	StatusTimeout(to_wx("Exception when attempting to autosave file: " + err.GetMessage()));
 }
 catch (wxString err) {
 	StatusTimeout("Exception when attempting to autosave file: " + err);
@@ -759,8 +759,8 @@ void FrameMain::OnSubtitlesOpen() {
 		}
 		catch (agi::UserCancelException const&) { }
 		catch (agi::FileNotAccessibleError const& err) {
-			config::mru->Remove("Audio", STD_STR(curSubsAudio));
-			wxMessageBox(lagi_wxString(err.GetMessage()), "Error opening audio", wxOK | wxICON_ERROR | wxCENTER, this);
+			config::mru->Remove("Audio", from_wx(curSubsAudio));
+			wxMessageBox(to_wx(err.GetMessage()), "Error opening audio", wxOK | wxICON_ERROR | wxCENTER, this);
 		}
 	}
 
diff --git a/aegisub/src/hotkey.cpp b/aegisub/src/hotkey.cpp
index 6f1ce77ad13b0c7f04e59c318d4d715847165f4f..50fec7a1cd3ef5ec6cfddb4db160145155aede21 100644
--- a/aegisub/src/hotkey.cpp
+++ b/aegisub/src/hotkey.cpp
@@ -124,7 +124,7 @@ namespace hotkey {
 agi::hotkey::Hotkey *inst = 0;
 void init() {
 	inst = new agi::hotkey::Hotkey(
-		STD_STR(StandardPaths::DecodePath("?user/hotkey.json")),
+		from_wx(StandardPaths::DecodePath("?user/hotkey.json")),
 		GET_DEFAULT_CONFIG(default_hotkey));
 
 	int last_version = OPT_GET("Version/Last Version")->GetInt();
diff --git a/aegisub/src/hotkey_data_view_model.cpp b/aegisub/src/hotkey_data_view_model.cpp
index ee21543e2c620431243b3eb10629daed8a32161f..f72e3b3424c52ee07a2f60c4c1672a2c3a745616 100644
--- a/aegisub/src/hotkey_data_view_model.cpp
+++ b/aegisub/src/hotkey_data_view_model.cpp
@@ -70,8 +70,8 @@ public:
 	HotkeyModelCombo(HotkeyModelCategory *parent, Combo const& combo)
 	: parent(parent)
 	, combo(combo)
-	, cmd_name(lagi_wxString(combo.CmdName()))
-	, cmd_str(lagi_wxString(combo.Str()))
+	, cmd_name(to_wx(combo.CmdName()))
+	, cmd_str(to_wx(combo.Str()))
 	{
 	}
 
@@ -103,7 +103,7 @@ public:
 				variant = cmd::get(combo.CmdName())->StrHelp();
 			}
 			catch (agi::Exception const& e) {
-				variant = lagi_wxString(e.GetChainedMessage());
+				variant = to_wx(e.GetChainedMessage());
 			}
 		}
 		else
@@ -123,7 +123,7 @@ public:
 		else if (col == 1) {
 			wxDataViewIconText text;
 			text << variant;
-			combo = Combo(combo.Context(), STD_STR(text.GetText()), combo.Get());
+			combo = Combo(combo.Context(), from_wx(text.GetText()), combo.Get());
 			cmd_name = text.GetText();
 			return true;
 		}
@@ -316,7 +316,7 @@ wxDataViewItem HotkeyDataViewModel::New(wxDataViewItem item) {
 	HotkeyModelCategory *ctx = static_cast<HotkeyModelCategory*>(item.GetID());
 	wxVariant name;
 	ctx->GetValue(name, 0);
-	return ctx->AddChild(Combo(STD_STR(name.GetString()), "", std::vector<std::string>()));
+	return ctx->AddChild(Combo(from_wx(name.GetString()), "", std::vector<std::string>()));
 }
 
 void HotkeyDataViewModel::Delete(wxDataViewItem const& item) {
diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp
index df78850eb606b5cc467cf5fbb78e3fdae295a519..861dfc10cdcfda9316dc6178129c2b04f523e4ab 100644
--- a/aegisub/src/main.cpp
+++ b/aegisub/src/main.cpp
@@ -157,7 +157,7 @@ bool AegisubApp::OnInit() {
 #ifdef __WXMSW__
 	// Try loading configuration from the install dir if one exists there
 	try {
-		std::string conf_local(STD_STR(StandardPaths::DecodePath("?data/config.json")));
+		std::string conf_local(from_wx(StandardPaths::DecodePath("?data/config.json")));
 		agi::scoped_ptr<std::istream> localConfig(agi::io::Open(conf_local));
 		config::opt = new agi::Options(conf_local, GET_DEFAULT_CONFIG(default_config));
 
@@ -173,13 +173,13 @@ bool AegisubApp::OnInit() {
 	StartupLog("Create log writer");
 	wxString path_log = StandardPaths::DecodePath("?user/log/");
 	wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL);
-	agi::log::log->Subscribe(new agi::log::JsonEmitter(STD_STR(path_log), agi::log::log));
+	agi::log::log->Subscribe(new agi::log::JsonEmitter(from_wx(path_log), agi::log::log));
 	CleanCache(path_log, "*.json", 10, 100);
 
 	StartupLog("Load user configuration");
 	try {
 		if (!config::opt)
-			config::opt = new agi::Options(STD_STR(StandardPaths::DecodePath("?user/config.json")), GET_DEFAULT_CONFIG(default_config));
+			config::opt = new agi::Options(from_wx(StandardPaths::DecodePath("?user/config.json")), GET_DEFAULT_CONFIG(default_config));
 		std::istringstream stream(GET_DEFAULT_CONFIG(default_config_platform));
 		config::opt->ConfigNext(stream);
 	} catch (agi::Exception& e) {
@@ -190,7 +190,7 @@ bool AegisubApp::OnInit() {
 		config::opt->ConfigUser();
 	}
 	catch (agi::Exception const& err) {
-		wxMessageBox("Configuration file is invalid. Error reported:\n" + lagi_wxString(err.GetMessage()), "Error");
+		wxMessageBox("Configuration file is invalid. Error reported:\n" + to_wx(err.GetMessage()), "Error");
 	}
 
 	// Init commands.
@@ -203,7 +203,7 @@ bool AegisubApp::OnInit() {
 	icon::icon_init();
 
 	StartupLog("Load MRU");
-	config::mru = new agi::MRUManager(STD_STR(StandardPaths::DecodePath("?user/mru.json")), GET_DEFAULT_CONFIG(default_mru), config::opt);
+	config::mru = new agi::MRUManager(from_wx(StandardPaths::DecodePath("?user/mru.json")), GET_DEFAULT_CONFIG(default_mru), config::opt);
 
 #ifdef __VISUALC__
 	SetThreadName((DWORD) -1,"AegiMain");
@@ -233,10 +233,10 @@ bool AegisubApp::OnInit() {
 		StartupLog("Initialize final locale");
 
 		// Set locale
-		wxString lang = lagi_wxString(OPT_GET("App/Language")->GetString());
+		wxString lang = to_wx(OPT_GET("App/Language")->GetString());
 		if (!lang) {
 			lang = locale.PickLanguage();
-			OPT_SET("App/Language")->SetString(STD_STR(lang));
+			OPT_SET("App/Language")->SetString(from_wx(lang));
 		}
 		locale.Init(lang);
 
@@ -246,7 +246,7 @@ bool AegisubApp::OnInit() {
 
 		// Load Automation scripts
 		StartupLog("Load global Automation scripts");
-		global_scripts = new Automation4::AutoloadScriptManager(lagi_wxString(OPT_GET("Path/Automation/Autoload")->GetString()));
+		global_scripts = new Automation4::AutoloadScriptManager(to_wx(OPT_GET("Path/Automation/Autoload")->GetString()));
 
 		// Load export filters
 		StartupLog("Register export filters");
@@ -282,7 +282,7 @@ bool AegisubApp::OnInit() {
 #endif
 
 	StartupLog("Clean old autosave files");
-	wxString autosave_path = StandardPaths::DecodePath(lagi_wxString(OPT_GET("Path/Auto/Save")->GetString()));
+	wxString autosave_path = StandardPaths::DecodePath(to_wx(OPT_GET("Path/Auto/Save")->GetString()));
 	CleanCache(autosave_path, "*.AUTOSAVE.ass", 100, 1000);
 
 	StartupLog("Initialization complete");
@@ -367,7 +367,7 @@ void AegisubApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEven
 		wxApp::HandleEvent(handler, func, event);
 	}
 	catch (const agi::Exception &e) {
-		SHOW_EXCEPTION(lagi_wxString(e.GetChainedMessage()));
+		SHOW_EXCEPTION(to_wx(e.GetChainedMessage()));
 	}
 	catch (const std::exception &e) {
 		SHOW_EXCEPTION(wxString(e.what(), wxConvUTF8));
@@ -462,7 +462,7 @@ int AegisubApp::OnRun() {
 	catch (const wxString &err) { error = err; }
 	catch (const char *err) { error = err; }
 	catch (const std::exception &e) { error = wxString("std::exception: ") + wxString(e.what(),wxConvUTF8); }
-	catch (const agi::Exception &e) { error = "agi::exception: " + lagi_wxString(e.GetChainedMessage()); }
+	catch (const agi::Exception &e) { error = "agi::exception: " + to_wx(e.GetChainedMessage()); }
 	catch (...) { error = "Program terminated in error."; }
 
 	// Report errors
@@ -492,7 +492,7 @@ void AegisubApp::MacOpenFile(const wxString &filename) {
 	if (frame != nullptr && !filename.empty()) {
 		frame->LoadSubtitles(filename);
 		wxFileName filepath(filename);
-		OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
+		OPT_SET("Path/Last/Subtitles")->SetString(from_wx(filepath.GetPath()));
 	}
 }
 #endif
diff --git a/aegisub/src/menu.cpp b/aegisub/src/menu.cpp
index ca944e7bede20f3f1bb8dcf8dc433177a2b61cd6..4c743dd96a59778a77ed60250770a2ba3f6f0d25 100644
--- a/aegisub/src/menu.cpp
+++ b/aegisub/src/menu.cpp
@@ -65,7 +65,7 @@ class MruMenu : public wxMenu {
 		for (size_t i = GetMenuItemCount(); i < new_size; ++i) {
 			if (i >= items.size()) {
 				items.push_back(new wxMenuItem(this, MENU_ID_BASE + cmds->size(), "_"));
-				cmds->push_back(STD_STR(wxString::Format("recent/%s/%d", lagi_wxString(type).Lower(), (int)i)));
+				cmds->push_back(from_wx(wxString::Format("recent/%s/%d", to_wx(type).Lower(), (int)i)));
 			}
 			Append(items[i]);
 		}
@@ -99,7 +99,7 @@ public:
 		for (auto it = mru->begin(); it != mru->end(); ++it, ++i) {
 			items[i]->SetItemLabel(wxString::Format("%s%d %s",
 				i <= 9 ? "&" : "", i + 1,
-				wxFileName(lagi_wxString(*it)).GetFullName()));
+				wxFileName(to_wx(*it)).GetFullName()));
 			items[i]->Enable(true);
 		}
 	}
@@ -182,7 +182,7 @@ public:
 			flags & cmd::COMMAND_TOGGLE ? wxITEM_CHECK :
 			wxITEM_NORMAL;
 
-		wxString menu_text = text.empty() ? co->StrMenu(context) : _(lagi_wxString(text));
+		wxString menu_text = text.empty() ? co->StrMenu(context) : _(to_wx(text));
 		menu_text += "\t" + hotkey::get_hotkey_str_first("Default", co->name());
 
 		wxMenuItem *item = new wxMenuItem(parent, MENU_ID_BASE + items.size(), menu_text, co->StrHelp(), kind);
@@ -332,7 +332,7 @@ void process_menu_item(wxMenu *parent, agi::Context *c, json::Object const& ele,
 	read_entry(ele, "special", &special);
 
 	if (read_entry(ele, "submenu", &submenu) && read_entry(ele, "text", &text)) {
-		wxString tl_text = _(lagi_wxString(text));
+		wxString tl_text = _(to_wx(text));
 		parent->AppendSubMenu(build_menu(submenu, c, cm), tl_text);
 #ifdef __WXMAC__
 		if (special == "help")
@@ -368,7 +368,7 @@ void process_menu_item(wxMenu *parent, agi::Context *c, json::Object const& ele,
 	}
 	catch (agi::Exception const& e) {
 #ifdef _DEBUG
-		parent->Append(-1, lagi_wxString(e.GetMessage()))->Enable(false);
+		parent->Append(-1, to_wx(e.GetMessage()))->Enable(false);
 #endif
 		LOG_W("menu/command/not_found") << "Skipping command " << command << ": " << e.GetMessage();
 	}
diff --git a/aegisub/src/mkv_wrap.cpp b/aegisub/src/mkv_wrap.cpp
index 715410c8bc4917bdcdf1fb638b3a066eb81ce6b1..978284d1291df1e738025254ddb8b41e56eb6b94 100644
--- a/aegisub/src/mkv_wrap.cpp
+++ b/aegisub/src/mkv_wrap.cpp
@@ -352,6 +352,6 @@ MkvStdIO::MkvStdIO(wxString filename)
 		setvbuf(fp, nullptr, _IOFBF, CACHESIZE);
 	}
 	else {
-		throw agi::FileNotFoundError(STD_STR(filename));
+		throw agi::FileNotFoundError(from_wx(filename));
 	}
 }
diff --git a/aegisub/src/preferences.cpp b/aegisub/src/preferences.cpp
index 3cf62ea99f5d3cd9db819259b63bafe7a2e7acd3..9fdb6b25c78a4ea1b78e6b14a0e6cdde700a761b 100644
--- a/aegisub/src/preferences.cpp
+++ b/aegisub/src/preferences.cpp
@@ -62,12 +62,6 @@
 #include <ffms.h>
 #endif
 
-static wxArrayString vec_to_arrstr(std::vector<std::string> const& vec) {
-	wxArrayString arrstr;
-	transform(vec.begin(), vec.end(), std::back_inserter(arrstr), &lagi_wxString);
-	return arrstr;
-}
-
 #define CLASS_PAGE(name)                             \
 class name: public OptionPage {                  \
 public:                                          \
@@ -242,7 +236,7 @@ Interface_Colours::Interface_Colours(wxTreebook *book, Preferences *parent): Opt
 	main_sizer->Add(sizer, wxEXPAND);
 
 	wxFlexGridSizer *color_schemes = PageSizer(_("Audio Color Schemes"));
-	wxArrayString schemes = vec_to_arrstr(OPT_GET("Audio/Colour Schemes")->GetListString());
+	wxArrayString schemes = to_wx(OPT_GET("Audio/Colour Schemes")->GetListString());
 	OptionChoice(color_schemes, _("Spectrum"), schemes, "Colour/Audio Display/Spectrum");
 	OptionChoice(color_schemes, _("Waveform"), schemes, "Colour/Audio Display/Waveform");
 
@@ -351,7 +345,7 @@ public:
 	}
 
 	void OnKeyDown(wxKeyEvent &evt) {
-		ctrl->ChangeValue(lagi_wxString(hotkey::keypress_to_str(evt.GetKeyCode(), evt.GetUnicodeKey(), evt.GetModifiers())));
+		ctrl->ChangeValue(to_wx(hotkey::keypress_to_str(evt.GetKeyCode(), evt.GetUnicodeKey(), evt.GetModifiers())));
 	}
 
 	bool SetValue(wxVariant const& var) {
@@ -501,10 +495,10 @@ Advanced::Advanced(wxTreebook *book, Preferences *parent): OptionPage(book, pare
 Advanced_Audio::Advanced_Audio(wxTreebook *book, Preferences *parent): OptionPage(book, parent, _("Audio"), PAGE_SUB) {
 	wxFlexGridSizer *expert = PageSizer(_("Expert"));
 
-	wxArrayString ap_choice = vec_to_arrstr(AudioProviderFactory::GetClasses());
+	wxArrayString ap_choice = to_wx(AudioProviderFactory::GetClasses());
 	OptionChoice(expert, _("Audio provider"), ap_choice, "Audio/Provider");
 
-	wxArrayString apl_choice = vec_to_arrstr(AudioPlayerFactory::GetClasses());
+	wxArrayString apl_choice = to_wx(AudioPlayerFactory::GetClasses());
 	OptionChoice(expert, _("Audio player"), apl_choice, "Audio/Player");
 
 	wxFlexGridSizer *cache = PageSizer(_("Cache"));
@@ -564,10 +558,10 @@ Advanced_Audio::Advanced_Audio(wxTreebook *book, Preferences *parent): OptionPag
 Advanced_Video::Advanced_Video(wxTreebook *book, Preferences *parent): OptionPage(book, parent, _("Video"), PAGE_SUB) {
 	wxFlexGridSizer *expert = PageSizer(_("Expert"));
 
-	wxArrayString vp_choice = vec_to_arrstr(VideoProviderFactory::GetClasses());
+	wxArrayString vp_choice = to_wx(VideoProviderFactory::GetClasses());
 	OptionChoice(expert, _("Video provider"), vp_choice, "Video/Provider");
 
-	wxArrayString sp_choice = vec_to_arrstr(SubtitlesProviderFactory::GetClasses());
+	wxArrayString sp_choice = to_wx(SubtitlesProviderFactory::GetClasses());
 	OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider");
 
 	CellSkip(expert);
diff --git a/aegisub/src/preferences_base.cpp b/aegisub/src/preferences_base.cpp
index c4bedb35647023da251a8755ecf389468395a911..d91414360088b4954b72dc9a40498739e58a911b 100644
--- a/aegisub/src/preferences_base.cpp
+++ b/aegisub/src/preferences_base.cpp
@@ -56,7 +56,7 @@
 		}                                                                   \
 	}
 
-OPTION_UPDATER(StringUpdater, wxCommandEvent, OptionValueString, STD_STR(evt.GetString()));
+OPTION_UPDATER(StringUpdater, wxCommandEvent, OptionValueString, from_wx(evt.GetString()));
 OPTION_UPDATER(IntUpdater, wxSpinEvent, OptionValueInt, evt.GetInt());
 OPTION_UPDATER(IntCBUpdater, wxCommandEvent, OptionValueInt, evt.GetInt());
 OPTION_UPDATER(DoubleUpdater, wxSpinEvent, OptionValueDouble, evt.GetInt());
@@ -154,7 +154,7 @@ wxControl *OptionPage::OptionAdd(wxFlexGridSizer *flex, const wxString &name, co
 		}
 
 		case agi::OptionValue::Type_String: {
-			wxTextCtrl *text = new wxTextCtrl(this, -1 , lagi_wxString(opt->GetString()));
+			wxTextCtrl *text = new wxTextCtrl(this, -1 , to_wx(opt->GetString()));
 			text->Bind(wxEVT_COMMAND_TEXT_UPDATED, StringUpdater(opt_name, parent));
 			Add(flex, name, text);
 			return text;
@@ -187,7 +187,7 @@ void OptionPage::OptionChoice(wxFlexGridSizer *flex, const wxString &name, const
 			break;
 		}
 		case agi::OptionValue::Type_String: {
-			wxString val(lagi_wxString(opt->GetString()));
+			wxString val(to_wx(opt->GetString()));
 			if (cb->FindString(val) != wxNOT_FOUND)
 				cb->SetStringSelection(val);
 			else if (!choices.empty())
diff --git a/aegisub/src/spellchecker_hunspell.cpp b/aegisub/src/spellchecker_hunspell.cpp
index b8331cd01d661b6e08337bd26cbaa42393354aa7..018c9c1b1552d139bcf9027d4ea7c4654bda522d 100644
--- a/aegisub/src/spellchecker_hunspell.cpp
+++ b/aegisub/src/spellchecker_hunspell.cpp
@@ -102,7 +102,7 @@ void HunspellSpellChecker::ReadUserDictionary() {
 	}
 	// Read the old contents of the user's dictionary
 	else {
-		agi::scoped_ptr<std::istream> stream(agi::io::Open(STD_STR(userDicPath)));
+		agi::scoped_ptr<std::istream> stream(agi::io::Open(from_wx(userDicPath)));
 		copy_if(
 			++agi::line_iterator<std::string>(*stream), agi::line_iterator<std::string>(),
 			inserter(customWords, customWords.end()),
@@ -113,7 +113,7 @@ void HunspellSpellChecker::ReadUserDictionary() {
 void HunspellSpellChecker::WriteUserDictionary() {
 	// Write the new dictionary
 	{
-		agi::io::Save writer(STD_STR(userDicPath));
+		agi::io::Save writer(from_wx(userDicPath));
 		writer.Get() << customWords.size() << "\n";
 		copy(customWords.begin(), customWords.end(), std::ostream_iterator<std::string>(writer.Get(), "\n"));
 	}
diff --git a/aegisub/src/subs_edit_ctrl.cpp b/aegisub/src/subs_edit_ctrl.cpp
index 4d612922d4be32f62938192aa0812be345164d7a..9ecf0e13e477648223bfe22353c5f357e5d00684 100644
--- a/aegisub/src/subs_edit_ctrl.cpp
+++ b/aegisub/src/subs_edit_ctrl.cpp
@@ -202,7 +202,7 @@ void SubsTextEditCtrl::SetSyntaxStyle(int id, wxFont &font, std::string const& n
 void SubsTextEditCtrl::SetStyles() {
 	wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
 	font.SetEncoding(wxFONTENCODING_DEFAULT); // this solves problems with some fonts not working properly
-	wxString fontname = lagi_wxString(OPT_GET("Subtitle/Edit Box/Font Face")->GetString());
+	wxString fontname = to_wx(OPT_GET("Subtitle/Edit Box/Font Face")->GetString());
 	if (!fontname.empty()) font.SetFaceName(fontname);
 	font.SetPointSize(OPT_GET("Subtitle/Edit Box/Font Size")->GetInt());
 
@@ -326,7 +326,7 @@ void SubsTextEditCtrl::OnContextMenu(wxContextMenuEvent &event) {
 	// Append language list
 	menu.Append(-1,_("Spell checker language"), GetLanguagesMenu(
 		EDIT_MENU_DIC_LANGS,
-		lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString()),
+		to_wx(OPT_GET("Tool/Spell Checker/Language")->GetString()),
 		to_wx(spellchecker->GetLanguageList())));
 	menu.AppendSeparator();
 
@@ -397,7 +397,7 @@ void SubsTextEditCtrl::AddThesaurusEntries(wxMenu &menu) {
 		for (auto const& result : results) {
 			// Single word, insert directly
 			if (result.second.size() == 1) {
-				thesMenu->Append(EDIT_MENU_THESAURUS_SUGS+curThesEntry, lagi_wxString(result.first));
+				thesMenu->Append(EDIT_MENU_THESAURUS_SUGS+curThesEntry, to_wx(result.first));
 				thesSugs.push_back(result.first);
 				++curThesEntry;
 			}
@@ -422,7 +422,7 @@ void SubsTextEditCtrl::AddThesaurusEntries(wxMenu &menu) {
 	// Append language list
 	menu.Append(-1,_("Thesaurus language"), GetLanguagesMenu(
 		EDIT_MENU_THES_LANGS,
-		lagi_wxString(OPT_GET("Tool/Thesaurus/Language")->GetString()),
+		to_wx(OPT_GET("Tool/Thesaurus/Language")->GetString()),
 		to_wx(thesaurus->GetLanguageList())));
 	menu.AppendSeparator();
 }
diff --git a/aegisub/src/subtitle_format_ass.cpp b/aegisub/src/subtitle_format_ass.cpp
index c913d69522f30a042a14109cf4736476e87f7a5e..1fc988eea6d74e84bcd90a181478307914254324 100644
--- a/aegisub/src/subtitle_format_ass.cpp
+++ b/aegisub/src/subtitle_format_ass.cpp
@@ -78,7 +78,7 @@ void AssSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
 		}
 		catch (const char *err) {
 			target->Clear();
-			throw AssParseError("Error processing line: " + STD_STR(line) + ": " + err, 0);
+			throw AssParseError("Error processing line: " + from_wx(line) + ": " + err, 0);
 		}
 	}
 }
diff --git a/aegisub/src/subtitle_format_ebu3264.cpp b/aegisub/src/subtitle_format_ebu3264.cpp
index 1904b884ec07050f7561d06e1ae663bf03406556..98655b5b9ef106e20ee320361cc8412ce3281a43 100644
--- a/aegisub/src/subtitle_format_ebu3264.cpp
+++ b/aegisub/src/subtitle_format_ebu3264.cpp
@@ -415,7 +415,7 @@ namespace
 			else if (!imline.CheckLineLengths(export_settings.max_line_length))
 			{
 				if (export_settings.line_wrapping_mode == EbuExportSettings::AbortOverLength)
-					throw Ebu3264SubtitleFormat::ConversionFailed(STD_STR(wxString::Format(_("Line over maximum length: %s"), line->Text.get())), 0);
+					throw Ebu3264SubtitleFormat::ConversionFailed(from_wx(wxString::Format(_("Line over maximum length: %s"), line->Text.get())), 0);
 				else // skip over-long lines
 					subs_list.pop_back();
 			}
@@ -675,7 +675,7 @@ void Ebu3264SubtitleFormat::WriteFile(const AssFile *src, wxString const& filena
 	snprintf(gsi.tns, 5, "%5u", (unsigned int)subs_list.size());
 
 	// write file
-	agi::io::Save f(STD_STR(filename), true);
+	agi::io::Save f(from_wx(filename), true);
 	f.Get().write((const char *)&gsi, sizeof(gsi));
 	for (auto const& block : tti)
 		f.Get().write((const char *)&block, sizeof(block));
diff --git a/aegisub/src/subtitle_format_srt.cpp b/aegisub/src/subtitle_format_srt.cpp
index 5f48f6e763fb5011935a9ecb23873785e71ade10..cb8e184ca81ebc47edf3b40937b20522cd7bb845 100644
--- a/aegisub/src/subtitle_format_srt.cpp
+++ b/aegisub/src/subtitle_format_srt.cpp
@@ -419,10 +419,10 @@ void SRTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
 				if (timestamp_regex.Matches(text_line))
 					goto found_timestamps;
 
-				throw SRTParseError(STD_STR(wxString::Format("Parsing SRT: Expected subtitle index at line %d", line_num)), 0);
+				throw SRTParseError(from_wx(wxString::Format("Parsing SRT: Expected subtitle index at line %d", line_num)), 0);
 			case STATE_TIMESTAMP:
 				if (!timestamp_regex.Matches(text_line))
-					throw SRTParseError(STD_STR(wxString::Format("Parsing SRT: Expected timestamp pair at line %d", line_num)), 0);
+					throw SRTParseError(from_wx(wxString::Format("Parsing SRT: Expected timestamp pair at line %d", line_num)), 0);
 found_timestamps:
 				if (line) {
 					// finalize active line
diff --git a/aegisub/src/subtitle_format_ttxt.cpp b/aegisub/src/subtitle_format_ttxt.cpp
index cb141a198822b7619526766967078315f2af2a9b..46492721771f589c4f72f8150f8fb6b0f1d129ae 100644
--- a/aegisub/src/subtitle_format_ttxt.cpp
+++ b/aegisub/src/subtitle_format_ttxt.cpp
@@ -82,7 +82,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxS
 	else if (verStr == "1.1")
 		version = 1;
 	else
-		throw TTXTParseError("Unknown TTXT version: " + STD_STR(verStr), 0);
+		throw TTXTParseError("Unknown TTXT version: " + from_wx(verStr), 0);
 
 	// Get children
 	AssDialogue *diag = 0;
diff --git a/aegisub/src/subtitle_format_txt.cpp b/aegisub/src/subtitle_format_txt.cpp
index f7bc41b9e2072b3b258910d7648fdb04b755a489..99449811b8c8f8ea8bf93cfc75148e3e99fa763f 100644
--- a/aegisub/src/subtitle_format_txt.cpp
+++ b/aegisub/src/subtitle_format_txt.cpp
@@ -77,8 +77,8 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
 	target->LoadDefault(false);
 
 	wxString actor;
-	wxString separator = lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString());
-	wxString comment = lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString());
+	wxString separator = to_wx(OPT_GET("Tool/Import/Text/Actor Separator")->GetString());
+	wxString comment = to_wx(OPT_GET("Tool/Import/Text/Comment Starter")->GetString());
 
 	// Parse file
 	while (file.HasMoreLines()) {
diff --git a/aegisub/src/text_file_reader.cpp b/aegisub/src/text_file_reader.cpp
index 39e4fb85fa95c3043d30f9db07111d096640112c..ad8ffccdbdc5a78bfa22708c73e002d88aed968e 100644
--- a/aegisub/src/text_file_reader.cpp
+++ b/aegisub/src/text_file_reader.cpp
@@ -39,8 +39,8 @@ TextFileReader::TextFileReader(wxString const& filename, wxString encoding, bool
 : trim(trim)
 {
 	if (encoding.empty()) encoding = CharSetDetect::GetEncoding(filename);
-	file.reset(agi::io::Open(STD_STR(filename), true));
-	iter = agi::line_iterator<wxString>(*file, STD_STR(encoding));
+	file.reset(agi::io::Open(from_wx(filename), true));
+	iter = agi::line_iterator<wxString>(*file, from_wx(encoding));
 }
 
 TextFileReader::~TextFileReader() {
diff --git a/aegisub/src/text_file_writer.cpp b/aegisub/src/text_file_writer.cpp
index 7a9d4d28833fcb5eb5cd8cc4860a1bbac7b7de54..815c52fde630e04c1d62a781600f2279ef7f8ae4 100644
--- a/aegisub/src/text_file_writer.cpp
+++ b/aegisub/src/text_file_writer.cpp
@@ -44,10 +44,10 @@
 #include "text_file_writer.h"
 
 TextFileWriter::TextFileWriter(wxString const& filename, wxString encoding)
-: file(new agi::io::Save(STD_STR(filename), true))
+: file(new agi::io::Save(from_wx(filename), true))
 , conv()
 {
-	if (encoding.empty()) encoding = lagi_wxString(OPT_GET("App/Save Charset")->GetString());
+	if (encoding.empty()) encoding = to_wx(OPT_GET("App/Save Charset")->GetString());
 	if (encoding.Lower() != wxSTRING_ENCODING)
 		conv.reset(new agi::charset::IconvWrapper(wxSTRING_ENCODING, encoding.utf8_str(), true));
 
diff --git a/aegisub/src/thesaurus.cpp b/aegisub/src/thesaurus.cpp
index 2fd95c29f090cb66c2ce9eb26c1484b469a54903..53708b160f11ff697dd2f3389239c2d52da27c2b 100644
--- a/aegisub/src/thesaurus.cpp
+++ b/aegisub/src/thesaurus.cpp
@@ -62,7 +62,7 @@ std::vector<std::string> Thesaurus::GetLanguageList() const {
 		wxDir::GetAllFiles(path, &idx, "th_*.idx", wxDIR_FILES);
 		wxDir::GetAllFiles(path, &dat, "th_*.dat", wxDIR_FILES);
 	}
-	path = StandardPaths::DecodePath(lagi_wxString(OPT_GET("Path/Dictionary")->GetString()) + "/");
+	path = StandardPaths::DecodePath(to_wx(OPT_GET("Path/Dictionary")->GetString()) + "/");
 	if (wxFileName::DirExists(path)) {
 		wxDir::GetAllFiles(path, &idx, "th_*.idx", wxDIR_FILES);
 		wxDir::GetAllFiles(path, &dat, "th_*.dat", wxDIR_FILES);
@@ -100,7 +100,7 @@ void Thesaurus::OnLanguageChanged() {
 	std::string language = OPT_GET("Tool/Thesaurus/Language")->GetString();
 	if (language.empty()) return;
 
-	wxString path = StandardPaths::DecodePath(lagi_wxString(OPT_GET("Path/Dictionary")->GetString()) + "/");
+	wxString path = StandardPaths::DecodePath(to_wx(OPT_GET("Path/Dictionary")->GetString()) + "/");
 
 	// Get index and data paths
 	wxString idxpath = wxString::Format("%s/th_%s.idx", path, language);
@@ -117,7 +117,7 @@ void Thesaurus::OnLanguageChanged() {
 
 	LOG_I("thesaurus/file") << "Using thesaurus: " << datpath.c_str();
 
-	impl.reset(new agi::Thesaurus(STD_STR(datpath), STD_STR(idxpath)));
+	impl.reset(new agi::Thesaurus(from_wx(datpath), from_wx(idxpath)));
 }
 
 void Thesaurus::OnPathChanged() {
diff --git a/aegisub/src/threaded_frame_source.cpp b/aegisub/src/threaded_frame_source.cpp
index a362098c1b3ec273535556d5ce080c3e1fefeb36..b53b68a9dcaf69de4ccb3789872ed60a4971c96d 100644
--- a/aegisub/src/threaded_frame_source.cpp
+++ b/aegisub/src/threaded_frame_source.cpp
@@ -255,7 +255,7 @@ VideoProviderErrorEvent::VideoProviderErrorEvent(VideoProviderError const& err)
 	SetEventType(EVT_VIDEO_ERROR);
 }
 SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(wxString err)
-: agi::Exception(STD_STR(err), nullptr)
+: agi::Exception(from_wx(err), nullptr)
 {
 	SetEventType(EVT_SUBTITLES_ERROR);
 }
diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp
index 5cd185cc90b8178528e7a5f174d422db62462d54..f8351f1972389e8b2524a91b885551dfc1c174db 100644
--- a/aegisub/src/utils.cpp
+++ b/aegisub/src/utils.cpp
@@ -216,7 +216,7 @@ void RestartAegisub() {
 	std::string helper_path = agi::util::OSX_GetBundleAuxillaryExecutablePath("restart-helper");
 	if (bundle_path.empty() || helper_path.empty()) return;
 
-	wxString exec = wxString::Format("\"%s\" /usr/bin/open -n \"%s\"'", lagi_wxString(helper_path), lagi_wxString(bundle_path));
+	wxString exec = wxString::Format("\"%s\" /usr/bin/open -n \"%s\"'", to_wx(helper_path), to_wx(bundle_path));
 	LOG_I("util/restart/exec") << exec;
 	wxExecute(exec);
 #else
@@ -291,7 +291,7 @@ class cache_cleaner : public wxThread {
 
 		wxDir cachedir;
 		if (!cachedir.Open(directory)) {
-			LOG_D("utils/clean_cache") << "couldn't open cache directory " << STD_STR(directory);
+			LOG_D("utils/clean_cache") << "couldn't open cache directory " << from_wx(directory);
 			return (wxThread::ExitCode)1;
 		}
 
@@ -346,7 +346,7 @@ class cache_cleaner : public wxThread {
 			int res = unlink(i.second.GetFullPath().fn_str());
 #endif
 			if (res) {
-				LOG_D("utils/clean_cache") << "failed to remove file " << STD_STR(i.second.GetFullPath());
+				LOG_D("utils/clean_cache") << "failed to remove file " << from_wx(i.second.GetFullPath());
 				continue;
 			}
 
diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp
index 325ee4bc5f18d722ff04774f79e5f9fed27b2e84..f60c50cbe74a9e4bd168765708957776464d9a06 100644
--- a/aegisub/src/video_context.cpp
+++ b/aegisub/src/video_context.cpp
@@ -193,7 +193,7 @@ void VideoContext::SetVideo(const wxString &filename) {
 			SetAspectRatio(4, dar);
 
 		// Set filename
-		config::mru->Add("Video", STD_STR(filename));
+		config::mru->Add("Video", from_wx(filename));
 		StandardPaths::SetPathValue("?video", wxFileName(filename).GetPath());
 
 		// Show warning
@@ -212,11 +212,11 @@ void VideoContext::SetVideo(const wxString &filename) {
 	}
 	catch (agi::UserCancelException const&) { }
 	catch (agi::FileNotAccessibleError const& err) {
-		config::mru->Remove("Video", STD_STR(filename));
-		wxMessageBox(lagi_wxString(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER);
+		config::mru->Remove("Video", from_wx(filename));
+		wxMessageBox(to_wx(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER);
 	}
 	catch (VideoProviderError const& err) {
-		wxMessageBox(lagi_wxString(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER);
+		wxMessageBox(to_wx(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER);
 	}
 
 	if (commit_subs)
@@ -414,24 +414,24 @@ void VideoContext::SetAspectRatio(int type, double value) {
 void VideoContext::LoadKeyframes(wxString filename) {
 	if (filename == keyFramesFilename || filename.empty()) return;
 	try {
-		keyFrames = agi::keyframe::Load(STD_STR(filename));
+		keyFrames = agi::keyframe::Load(from_wx(filename));
 		keyFramesFilename = filename;
 		KeyframesOpen(keyFrames);
-		config::mru->Add("Keyframes", STD_STR(filename));
+		config::mru->Add("Keyframes", from_wx(filename));
 	}
 	catch (agi::keyframe::Error const& err) {
 		wxMessageBox(err.GetMessage(), "Error opening keyframes file", wxOK | wxICON_ERROR | wxCENTER, context->parent);
-		config::mru->Remove("Keyframes", STD_STR(filename));
+		config::mru->Remove("Keyframes", from_wx(filename));
 	}
 	catch (agi::FileSystemError const&) {
 		wxLogError("Could not open file " + filename);
-		config::mru->Remove("Keyframes", STD_STR(filename));
+		config::mru->Remove("Keyframes", from_wx(filename));
 	}
 }
 
 void VideoContext::SaveKeyframes(wxString filename) {
-	agi::keyframe::Save(STD_STR(filename), GetKeyFrames());
-	config::mru->Add("Keyframes", STD_STR(filename));
+	agi::keyframe::Save(from_wx(filename), GetKeyFrames());
+	config::mru->Add("Keyframes", from_wx(filename));
 }
 
 void VideoContext::CloseKeyframes() {
@@ -446,15 +446,15 @@ void VideoContext::CloseKeyframes() {
 void VideoContext::LoadTimecodes(wxString filename) {
 	if (filename == ovrTimecodeFile || filename.empty()) return;
 	try {
-		ovrFPS = agi::vfr::Framerate(STD_STR(filename));
+		ovrFPS = agi::vfr::Framerate(from_wx(filename));
 		ovrTimecodeFile = filename;
-		config::mru->Add("Timecodes", STD_STR(filename));
+		config::mru->Add("Timecodes", from_wx(filename));
 		OnSubtitlesCommit(0, std::set<const AssEntry*>());
 		TimecodesOpen(ovrFPS);
 	}
 	catch (const agi::FileSystemError&) {
 		wxLogError("Could not open file " + filename);
-		config::mru->Remove("Timecodes", STD_STR(filename));
+		config::mru->Remove("Timecodes", from_wx(filename));
 	}
 	catch (const agi::vfr::Error& e) {
 		wxLogError("Timecode file parse error: %s", e.GetMessage());
@@ -462,8 +462,8 @@ void VideoContext::LoadTimecodes(wxString filename) {
 }
 void VideoContext::SaveTimecodes(wxString filename) {
 	try {
-		FPS().Save(STD_STR(filename), IsLoaded() ? GetLength() : -1);
-		config::mru->Add("Timecodes", STD_STR(filename));
+		FPS().Save(from_wx(filename), IsLoaded() ? GetLength() : -1);
+		config::mru->Add("Timecodes", from_wx(filename));
 	}
 	catch(const agi::FileSystemError&) {
 		wxLogError("Could not write to " + filename);
@@ -493,12 +493,12 @@ void VideoContext::OnVideoError(VideoProviderErrorEvent const& err) {
 	wxLogError(
 		"Failed seeking video. The video file may be corrupt or incomplete.\n"
 		"Error message reported: %s",
-		lagi_wxString(err.GetMessage()));
+		to_wx(err.GetMessage()));
 }
 void VideoContext::OnSubtitlesError(SubtitlesProviderErrorEvent const& err) {
 	wxLogError(
 		"Failed rendering subtitles. Error message reported: %s",
-		lagi_wxString(err.GetMessage()));
+		to_wx(err.GetMessage()));
 }
 
 void VideoContext::OnExit() {
diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp
index 98291524340ca1799206e0075c885671597dfeee..6f937b3ea45c320b21624fed72c705fbc778e752 100644
--- a/aegisub/src/video_display.cpp
+++ b/aegisub/src/video_display.cpp
@@ -75,7 +75,7 @@ int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 }
 class OpenGlException : public agi::Exception {
 public:
 	OpenGlException(const char *func, int err)
-		: agi::Exception(STD_STR(wxString::Format("%s failed with error code %d", func, err)))
+		: agi::Exception(from_wx(wxString::Format("%s failed with error code %d", func, err)))
 	{ }
 	const char * GetName() const { return "video/opengl"; }
 	Exception * Copy() const { return new OpenGlException(*this); }
diff --git a/aegisub/src/video_out_gl.h b/aegisub/src/video_out_gl.h
index 35ca3a2515dc0967a0e4502dafd69d898338ac16..222c85ffd4b3ff693fe4398705aa4c37d581b6e6 100644
--- a/aegisub/src/video_out_gl.h
+++ b/aegisub/src/video_out_gl.h
@@ -108,7 +108,7 @@ DEFINE_BASE_EXCEPTION_NOINNER(VideoOutException, agi::Exception)
 class VideoOutRenderException : public VideoOutException {
 public:
 	VideoOutRenderException(const char *func, int err)
-		: VideoOutException(STD_STR(wxString::Format("%s failed with error code %d", func, err)))
+		: VideoOutException(from_wx(wxString::Format("%s failed with error code %d", func, err)))
 	{ }
 	const char * GetName() const { return "videoout/opengl/render"; }
 	Exception * Copy() const { return new VideoOutRenderException(*this); }
@@ -119,7 +119,7 @@ public:
 class VideoOutInitException : public VideoOutException {
 public:
 	VideoOutInitException(const char *func, int err)
-		: VideoOutException(STD_STR(wxString::Format("%s failed with error code %d", func, err)))
+		: VideoOutException(from_wx(wxString::Format("%s failed with error code %d", func, err)))
 	{ }
 	VideoOutInitException(const char *err) : VideoOutException(err) { }
 	const char * GetName() const { return "videoout/opengl/init"; }
diff --git a/aegisub/src/video_provider_avs.cpp b/aegisub/src/video_provider_avs.cpp
index 379264fa82e8827533d3c17d9b088f0eaa524e9d..670d8b238bef80d077aaf6063b4943c70785c5f3 100644
--- a/aegisub/src/video_provider_avs.cpp
+++ b/aegisub/src/video_provider_avs.cpp
@@ -62,7 +62,7 @@ AvisynthVideoProvider::AvisynthVideoProvider(wxString filename)
 
 	wxFileName fname(filename);
 	if (!fname.FileExists())
-		throw agi::FileNotFoundError(STD_STR(filename));
+		throw agi::FileNotFoundError(from_wx(filename));
 
 	wxString extension = filename.Right(4).Lower();
 
diff --git a/aegisub/src/video_provider_ffmpegsource.cpp b/aegisub/src/video_provider_ffmpegsource.cpp
index fea795c95efcd05dd235032d1d0e084c50ed3c6a..3d2cb94186453f35aab74161af0f007388fe80bf 100644
--- a/aegisub/src/video_provider_ffmpegsource.cpp
+++ b/aegisub/src/video_provider_ffmpegsource.cpp
@@ -73,7 +73,7 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) try
 	LoadVideo(filename);
 }
 catch (wxString const& err) {
-	throw VideoOpenError(STD_STR(err));
+	throw VideoOpenError(from_wx(err));
 }
 catch (const char * err) {
 	throw VideoOpenError(err);
@@ -239,7 +239,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
 	for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
 		CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
 		if (CurFrameData == nullptr) {
-			throw VideoOpenError(STD_STR(wxString::Format("Couldn't get info about frame %d", CurFrameNum)));
+			throw VideoOpenError(from_wx(wxString::Format("Couldn't get info about frame %d", CurFrameNum)));
 		}
 
 		// keyframe?
diff --git a/aegisub/src/video_provider_manager.cpp b/aegisub/src/video_provider_manager.cpp
index 94531ff0fec3c2978653cfeb87ce5b20274bdbd9..070c7c3401c85c433448263aacc1adee79041629 100644
--- a/aegisub/src/video_provider_manager.cpp
+++ b/aegisub/src/video_provider_manager.cpp
@@ -68,7 +68,7 @@ VideoProvider *VideoProviderFactory::GetProvider(wxString video) {
 		std::string err;
 		try {
 			VideoProvider *provider = Create(factory, video);
-			LOG_I("manager/video/provider") << factory << ": opened " << STD_STR(video);
+			LOG_I("manager/video/provider") << factory << ": opened " << from_wx(video);
 			if (provider->WantsCaching()) {
 				return new VideoProviderCache(provider);
 			}
@@ -97,10 +97,10 @@ VideoProvider *VideoProviderFactory::GetProvider(wxString video) {
 	}
 
 	// No provider could open the file
-	LOG_E("manager/video/provider") << "Could not open " << STD_STR(video);
-	std::string msg = "Could not open " + STD_STR(video) + ":\n" + errors;
+	LOG_E("manager/video/provider") << "Could not open " << from_wx(video);
+	std::string msg = "Could not open " + from_wx(video) + ":\n" + errors;
 
-	if (!fileFound) throw agi::FileNotFoundError(STD_STR(video));
+	if (!fileFound) throw agi::FileNotFoundError(from_wx(video));
 	if (!fileSupported) throw VideoNotSupported(msg);
 	throw VideoOpenError(msg);
 }
diff --git a/aegisub/src/video_provider_yuv4mpeg.cpp b/aegisub/src/video_provider_yuv4mpeg.cpp
index de3d7dcc55c7f24949e8dbe66323100a136b3cd0..00afd65b59ac888728a7a16530f5e07b28820be3 100644
--- a/aegisub/src/video_provider_yuv4mpeg.cpp
+++ b/aegisub/src/video_provider_yuv4mpeg.cpp
@@ -75,7 +75,7 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString fname)
 		sf = fopen(filename.utf8_str(), "rb");
 #endif
 
-		if (sf == nullptr) throw agi::FileNotFoundError(STD_STR(fname));
+		if (sf == nullptr) throw agi::FileNotFoundError(from_wx(fname));
 
 		CheckFileFormat();
 
@@ -150,7 +150,7 @@ std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos) {
 	int buf;
 
 	if (fseeko(sf, startpos, SEEK_SET))
-		throw VideoOpenError(STD_STR(wxString::Format("YUV4MPEG video provider: ReadHeader: failed seeking to position %d", startpos)));
+		throw VideoOpenError(from_wx(wxString::Format("YUV4MPEG video provider: ReadHeader: failed seeking to position %d", startpos)));
 
 	// read header until terminating newline (0x0A) is found
 	while ((buf = fgetc(sf)) != 0x0A) {
@@ -247,7 +247,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
 				throw VideoOpenError("ParseFileHeader: invalid or unknown interlacing mode");
 		}
 		else
-			LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << STD_STR(tags[i]);
+			LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << from_wx(tags[i]);
 	}
 
 	// The point of all this is to allow multiple YUV4MPEG2 headers in a single file
@@ -328,7 +328,7 @@ int YUV4MPEGVideoProvider::IndexFile() {
 			seek_table.push_back(curpos);
 			// seek to next frame header start position
 			if (fseeko(sf, frame_sz, SEEK_CUR))
-				throw VideoOpenError(STD_STR(wxString::Format("IndexFile: failed seeking to position %d", curpos + frame_sz)));
+				throw VideoOpenError(from_wx(wxString::Format("IndexFile: failed seeking to position %d", curpos + frame_sz)));
 		}
 		else {
 			/// @todo implement rff flags etc