From 02b3defcd0e200ab29fd091032caf26ee3092b18 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Wed, 13 Sep 2017 05:32:44 -0700 Subject: [PATCH] restore wx 2.8 compat, improve string processing Fix building with wx 2.8 by rewriting some more string related code. Replace all calls to .c_str() with .mb_str(). Remove some of the .c_str()/.mb_str() calls where the target is already wxString. Move the split()/enum_idx() functions from opts.cpp into str_split()/vec_find() in strutils.h/strutils.cpp for use in other files. Replace the C-style string parsing code in a couple of places in wxvbam.cpp for processing possible command line options by splitting on '='. Also replace a couple of places that use pointer arithmetic in widgets/joyedit.cpp and widgets/keyedit.cpp with wxString methods. --- README.md | 2 +- src/wx/CMakeLists.txt | 1 + src/wx/cmdevents.cpp | 36 +++++++++---------- src/wx/guiinit.cpp | 20 +++++------ src/wx/opts.cpp | 74 +++++++++++++------------------------- src/wx/panel.cpp | 32 ++++++++--------- src/wx/strutils.cpp | 30 ++++++++++++++++ src/wx/strutils.h | 15 ++++++++ src/wx/sys.cpp | 24 ++++++------- src/wx/viewers.cpp | 2 +- src/wx/widgets/joyedit.cpp | 6 ++-- src/wx/widgets/keyedit.cpp | 6 ++-- src/wx/wxvbam.cpp | 55 +++++++++++++--------------- src/wx/wxvbam.h | 5 ++- 14 files changed, 163 insertions(+), 145 deletions(-) create mode 100644 src/wx/strutils.cpp create mode 100644 src/wx/strutils.h diff --git a/README.md b/README.md index be97cfad..1e148702 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ And the following development libraries: - [SDL](https://www.libsdl.org/)2 (required) - [SFML](https://www.sfml-dev.org/) (optional, for link) - OpenAL (optional, a sound interface) -- [wxWidgets](https://wxwidgets.org/) (required, 2.8 is still supported) +- [wxWidgets](https://wxwidgets.org/) (required, 2.8 is still supported, --enable-stl is supported) On Linux and similar, you also need the version of GTK your wxWidgets is linked to (usually 2 or 3). diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index 573d00b6..cfe6a3c1 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -422,6 +422,7 @@ SET( SRC_WX panel.cpp viewsupt.cpp wayland.cpp + strutils.cpp widgets/keyedit.cpp widgets/joyedit.cpp widgets/sdljoy.cpp diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 89907d64..919642f1 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -547,7 +547,7 @@ EVT_HANDLER_MASK(RomInformation, "ROM information...", CMDEN_GB | CMDEN_GBA) s.Printf(wxT("%02x"), gbRom[0x14b]); setlab("MakerCode"); - const rom_maker m = { s.c_str() }, *rm; + const rom_maker m = { s }, *rm; rm = std::lower_bound(&makers[0], &makers[num_makers], m, maker_lt); if (rm < &makers[num_makers] && !wxStrcmp(m.code, rm->code)) @@ -775,7 +775,7 @@ EVT_HANDLER_MASK(RomInformation, "ROM information...", CMDEN_GB | CMDEN_GBA) SetDialogLabel(dlg, wxT("CRC32"), rom_crc32, 8); setlabs("GameCode", rom[0xac], 4); setlabs("MakerCode", rom[0xb0], 2); - const rom_maker m = { s.c_str() }, *rm; + const rom_maker m = { s }, *rm; rm = std::lower_bound(&makers[0], &makers[num_makers], m, maker_lt); if (rm < &makers[num_makers] && !wxStrcmp(m.code, rm->code)) @@ -864,9 +864,9 @@ EVT_HANDLER_MASK(ImportBatteryFile, "Import battery file...", CMDEN_GB | CMDEN_G wxString msg; if (panel->emusys->emuReadBattery(fn.mb_fn_str())) - msg.Printf(_("Loaded battery %s"), fn.c_str()); + msg.Printf(_("Loaded battery %s"), fn.mb_str()); else - msg.Printf(_("Error loading battery %s"), fn.c_str()); + msg.Printf(_("Error loading battery %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -902,7 +902,7 @@ EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN wxFFile f(fn, wxT("rb")); if (!f.IsOpened()) { - wxLogError(_("Cannot open file %s"), fn.c_str()); + wxLogError(_("Cannot open file %s"), fn.mb_str()); return; } @@ -912,7 +912,7 @@ EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN char buf[14]; if (f.Read(&len, sizeof(len)) != sizeof(len) || wxUINT32_SWAP_ON_BE(len) != 14 || f.Read(buf, 14) != 14 || memcmp(buf, "SharkPortCODES", 14)) { - wxLogError(_("Unsupported code file %s"), fn.c_str()); + wxLogError(_("Unsupported code file %s"), fn.mb_str()); return; } @@ -982,9 +982,9 @@ EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN } if (res) - msg.Printf(_("Loaded code file %s"), fn.c_str()); + msg.Printf(_("Loaded code file %s"), fn.mb_str()); else - msg.Printf(_("Error loading code file %s"), fn.c_str()); + msg.Printf(_("Error loading code file %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -1030,9 +1030,9 @@ EVT_HANDLER_MASK(ImportGamesharkActionReplaySnapshot, } if (res) - msg.Printf(_("Loaded snapshot file %s"), fn.c_str()); + msg.Printf(_("Loaded snapshot file %s"), fn.mb_str()); else - msg.Printf(_("Error loading snapshot file %s"), fn.c_str()); + msg.Printf(_("Error loading snapshot file %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -1055,9 +1055,9 @@ EVT_HANDLER_MASK(ExportBatteryFile, "Export battery file...", CMDEN_GB | CMDEN_G wxString msg; if (panel->emusys->emuWriteBattery(fn.mb_fn_str())) - msg.Printf(_("Wrote battery %s"), fn.c_str()); + msg.Printf(_("Wrote battery %s"), fn.mb_str()); else - msg.Printf(_("Error writing battery %s"), fn.c_str()); + msg.Printf(_("Error writing battery %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -1096,11 +1096,11 @@ EVT_HANDLER_MASK(ExportGamesharkSnapshot, "Export GameShark snapshot...", CMDEN_ // FIXME: this will fail on big-endian machines if file format is // little-endian // fix in GBA.cpp - if (CPUWriteGSASnapshot(fn.mb_fn_str(), tit->GetValue().utf8_str(), - dsc->GetValue().utf8_str(), n->GetValue().utf8_str())) - msg.Printf(_("Saved snapshot file %s"), fn.c_str()); + if (CPUWriteGSASnapshot(fn.mb_str(), tit->GetValue().mb_str(), + dsc->GetValue().mb_str(), n->GetValue().mb_str())) + msg.Printf(_("Saved snapshot file %s"), fn.mb_str()); else - msg.Printf(_("Error saving snapshot file %s"), fn.c_str()); + msg.Printf(_("Error saving snapshot file %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -1140,7 +1140,7 @@ EVT_HANDLER_MASK(ScreenCapture, "Screen capture...", CMDEN_GB | CMDEN_GBA) panel->emusys->emuWriteBMP(fn.mb_fn_str()); wxString msg; - msg.Printf(_("Wrote snapshot %s"), fn.c_str()); + msg.Printf(_("Wrote snapshot %s"), fn.mb_str()); systemScreenMessage(msg); } @@ -1936,7 +1936,7 @@ void MainFrame::GDBBreak() if (!debugOpenPty()) return; - msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().c_str()); + msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().mb_str()); } else #endif { diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index 02cb97de..bc1a2f4a 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -110,10 +110,10 @@ public: char host[length]; GetLinkServerHost(host, length); title.Printf(_("Waiting for clients...")); - connmsg.Printf(_("Server IP address is: %s\n"), wxString(host, wxConvLibc).c_str()); + connmsg.Printf(_("Server IP address is: %s\n"), wxString(host, wxConvLibc).mb_str()); } else { title.Printf(_("Waiting for connection...")); - connmsg.Printf(_("Connecting to %s\n"), gopts.link_host.c_str()); + connmsg.Printf(_("Connecting to %s\n"), gopts.link_host.mb_str()); } // Init link @@ -1802,7 +1802,7 @@ public: // to put the plugins... it depends on where program was // installed, and of course OS wxString msg; - msg.Printf(_("No usable rpi plugins found in %s"), plpath.c_str()); + msg.Printf(_("No usable rpi plugins found in %s"), plpath.mb_str()); systemScreenMessage(msg); ch->Hide(); txt->Hide(); @@ -2298,7 +2298,7 @@ void CheckThrowXRCError(T pointer, const wxString& name) std::string errormessage = "Unable to load a \""; errormessage += typeid(pointer).name(); errormessage += "\" from the builtin xrc file: "; - errormessage += name.utf8_str(); + errormessage += name.mb_str(); throw std::runtime_error(errormessage); } } @@ -2661,9 +2661,9 @@ bool MainFrame::BindControls() if (a->GetFlags() == e->GetFlags() && a->GetKeyCode() == e->GetKeyCode()) { if (e->GetMenuItem()) { wxLogInfo(_("Duplicate menu accelerator: %s for %s and %s; keeping first"), - wxKeyTextCtrl::ToString(a->GetFlags(), a->GetKeyCode()).c_str(), - e->GetMenuItem()->GetItemLabelText().c_str(), - mi->GetItemLabelText().c_str()); + wxKeyTextCtrl::ToString(a->GetFlags(), a->GetKeyCode()).mb_str(), + e->GetMenuItem()->GetItemLabelText().mb_str(), + mi->GetItemLabelText().mb_str()); delete a; a = 0; } else { @@ -2675,8 +2675,8 @@ bool MainFrame::BindControls() break; wxLogInfo(_("Menu accelerator %s for %s overrides default for %s ; keeping menu"), - wxKeyTextCtrl::ToString(a->GetFlags(), a->GetKeyCode()).c_str(), - mi->GetItemLabelText().c_str(), + wxKeyTextCtrl::ToString(a->GetFlags(), a->GetKeyCode()).mb_str(), + mi->GetItemLabelText().mb_str(), cmdtab[cmd].cmd); } @@ -2781,7 +2781,7 @@ bool MainFrame::BindControls() for (int i = 0; i < checkable_mi.size(); i++) if (!checkable_mi[i].boolopt && !checkable_mi[i].intopt) { wxLogError(_("Invalid menu item %s; removing"), - checkable_mi[i].mi->GetItemLabelText().c_str()); + checkable_mi[i].mi->GetItemLabelText().mb_str()); checkable_mi[i].mi->GetMenu()->Remove(checkable_mi[i].mi); checkable_mi[i].mi = NULL; } diff --git a/src/wx/opts.cpp b/src/wx/opts.cpp index 358971ce..a3d0fbf7 100644 --- a/src/wx/opts.cpp +++ b/src/wx/opts.cpp @@ -1,9 +1,8 @@ #include "../common/ConfigManager.h" #include "wxvbam.h" #include -#include -#include #include +#include "strutils.h" /* disableSfx(F) -> cpuDisableSfx @@ -21,15 +20,15 @@ } #define INTOPT(c, n, d, v, min, max) \ { \ - wxT(c), (n), d, NULL, &v, "", min, max \ + wxT(c), (n), d, NULL, &v, wxT(""), min, max \ } #define DOUBLEOPT(c, n, d, v, min, max) \ { \ - wxT(c), (n), d, NULL, NULL, "", min, max, NULL, &v \ + wxT(c), (n), d, NULL, NULL, wxT(""), min, max, NULL, &v \ } #define BOOLOPT(c, n, d, v) \ { \ - wxT(c), (n), d, NULL, NULL, "", 0, 0, &v \ + wxT(c), (n), d, NULL, NULL, wxT(""), 0, 0, &v \ } #define ENUMOPT(c, n, d, v, e) \ { \ @@ -333,31 +332,6 @@ bool opt_lt(const opt_desc& opt1, const opt_desc& opt2) return wxStrcmp(opt1.opt, opt2.opt) < 0; } -// From: https://stackoverflow.com/a/7408245/262458 -static std::vector split(const wxString& text_, const wxString& sep_) { - std::vector tokens; - std::size_t start = 0, end = 0; - std::string text = text_.ToStdString(), sep = sep_.ToStdString(); - - while ((end = text.find(sep, start)) != std::string::npos) { - tokens.push_back(text.substr(start, end - start)); - start = end + 1; - } - - tokens.push_back(text.substr(start)); - - return tokens; -} - -static std::size_t enum_idx(std::vector& opts, const wxString& val) { - auto it = std::find(opts.begin(), opts.end(), val); - - if (it == opts.end()) - return wxNOT_FOUND; - - return std::distance(opts.begin(), it); -} - // FIXME: simulate MakeInstanceFilename(vbam.ini) using subkeys (Slave%d/*) void load_opts() @@ -389,7 +363,7 @@ void load_opts() for (cont = cfg->GetFirstEntry(s, grp_idx); cont; cont = cfg->GetNextEntry(s, grp_idx)) { - //wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option %s present; removing if possible"), s.mb_str()); item_del.push_back(s); } @@ -427,7 +401,7 @@ void load_opts() for (cont = cfg->GetFirstGroup(e, key_idx); cont; cont = cfg->GetNextGroup(e, key_idx)) { s.append(e); - //wxLogWarning(_("Invalid option group %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option group %s present; removing if possible"), s.mb_str()); grp_del.push_back(s); s.resize(poff2); } @@ -442,7 +416,7 @@ void load_opts() if (i == NUM_KEYS) { s.append(e); - //wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option %s present; removing if possible"), s.mb_str()); item_del.push_back(s); s.resize(poff2); } @@ -454,7 +428,7 @@ void load_opts() } else { s.append(wxT('/')); s.append(e); - //wxLogWarning(_("Invalid option group %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option group %s present; removing if possible"), s.mb_str()); grp_del.push_back(s); s.resize(poff); } @@ -464,23 +438,23 @@ void load_opts() cont = cfg->GetNextEntry(e, entry_idx)) { // kb options come from a different list if (s == wxT("Keyboard")) { - const cmditem dummy = { e.c_str() }; + const cmditem dummy = { e }; if (!std::binary_search(&cmdtab[0], &cmdtab[ncmds], dummy, cmditem_lt)) { s.append(wxT('/')); s.append(e); - //wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option %s present; removing if possible"), s.mb_str()); item_del.push_back(s); s.resize(poff); } } else { s.append(wxT('/')); s.append(e); - const opt_desc dummy = { s.c_str() }; + const opt_desc dummy = { s }; wxString opt_name(dummy.opt); if (!std::binary_search(&opts[0], &opts[num_opts], dummy, opt_lt) && opt_name != wxT("General/LastUpdated") && opt_name != wxT("General/LastUpdatedFileName")) { - //wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str()); + //wxLogWarning(_("Invalid option %s present; removing if possible"), s.mb_str()); item_del.push_back(s); } @@ -507,13 +481,13 @@ void load_opts() if (opt.stropt) { opt.curstr = *opt.stropt; } else if (!opt.enumvals.empty()) { - auto enum_opts = split(opt.enumvals.MakeLower(), wxT("|")); + auto enum_opts = str_split(opt.enumvals.MakeLower(), wxT("|")); opt.curint = *opt.intopt; bool gotit = cfg->Read(opt.opt, &s); s.MakeLower(); if (gotit && !s.empty()) { - const std::size_t found_pos = enum_idx(enum_opts, s); - const bool matched = found_pos != wxNOT_FOUND; + const auto found_pos = vec_find(enum_opts, s); + const bool matched = found_pos != wxNOT_FOUND; if (!matched) { opt.curint = 0; @@ -560,7 +534,7 @@ void load_opts() wxString optn; optn.Printf(wxT("GB/Palette%d"), i); wxString val; - const opt_desc dummy = { optn.c_str() }; + const opt_desc dummy = { optn }; opt_desc* opt = std::lower_bound(&opts[0], &opts[num_opts], dummy, opt_lt); wxString entry; @@ -605,7 +579,7 @@ void load_opts() gopts.joykey_bindings[i][j] = wxJoyKeyTextCtrl::FromString(s); if (s.size() && !gopts.joykey_bindings[i][j].size()) - wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), optname.c_str()); + wxLogWarning(_("Invalid key binding %s for %s"), s.mb_str(), optname.mb_str()); } else { s = wxJoyKeyTextCtrl::ToString(gopts.joykey_bindings[i][j]); cfg->Write(optname, s); @@ -626,7 +600,7 @@ void load_opts() wxAcceleratorEntry_v val = wxKeyTextCtrl::FromString(s); if (!val.size()) - wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), kbopt.c_str()); + wxLogWarning(_("Invalid key binding %s for %s"), s.mb_str(), kbopt.mb_str()); else { for (int j = 0; j < val.size(); j++) val[j].Set(val[j].GetFlags(), val[j].GetKeyCode(), @@ -662,7 +636,7 @@ void update_opts() } else if (!opt.enumvals.empty()) { if (*opt.intopt != opt.curint) { opt.curint = *opt.intopt; - auto enum_opts = split(opt.enumvals.MakeLower(), wxT("|")); + auto enum_opts = str_split(opt.enumvals.MakeLower(), wxT("|")); cfg->Write(opt.opt, enum_opts[opt.curint]); } @@ -683,7 +657,7 @@ void update_opts() for (int i = 0; i < 3; i++) { wxString optn; optn.Printf(wxT("GB/Palette%d"), i); - const opt_desc dummy = { optn.c_str() }; + const opt_desc dummy = { optn }; opt_desc* opt = std::lower_bound(&opts[0], &opts[num_opts], dummy, opt_lt); wxString val; wxString entry; @@ -727,7 +701,7 @@ void update_opts() for (bool cont = cfg->GetFirstEntry(s, entry_idx); cont; cont = cfg->GetNextEntry(s, entry_idx)) { - const cmditem dummy = { s.c_str() }; + const cmditem dummy = { s }; cmditem* cmd = std::lower_bound(&cmdtab[0], &cmdtab[ncmds], dummy, cmditem_lt); int i; @@ -793,9 +767,9 @@ bool opt_set(const wxString& name, const wxString& val) } else if (!opt->enumvals.empty()) { wxString s = val; s.MakeLower(); wxString ev = opt->enumvals; ev.MakeLower(); - auto enum_opts = split(ev, wxT("|")); + auto enum_opts = str_split(ev, wxT("|")); - const std::size_t found_pos = enum_idx(enum_opts, s); + const std::size_t found_pos = vec_find(enum_opts, s); const bool matched = found_pos != wxNOT_FOUND; if (!matched) { @@ -863,7 +837,7 @@ bool opt_set(const wxString& name, const wxString& val) if (name.Find(wxT('/')) == wxNOT_FOUND) return false; - auto parts = split(name, wxT("/")); + auto parts = str_split(name, wxT("/")); if (parts[0] != wxT("Keyboard")) { const cmditem parts_1 = { parts[1] }; diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 5823e90b..d6ae00b6 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -81,7 +81,7 @@ void GameArea::LoadGame(const wxString& name) if (t == IMAGE_UNKNOWN) { wxString s; - s.Printf(_("%s is not a valid ROM file"), name.c_str()); + s.Printf(_("%s is not a valid ROM file"), name.mb_str()); wxMessageDialog dlg(GetParent(), s, _("Problem loading file"), wxOK | wxICON_ERROR); dlg.ShowModal(); return; @@ -138,7 +138,7 @@ void GameArea::LoadGame(const wxString& name) if (t == IMAGE_GB) { if (!gbLoadRom(fn)) { wxString s; - s.Printf(_("Unable to load Game Boy ROM %s"), name.c_str()); + s.Printf(_("Unable to load Game Boy ROM %s"), name.mb_str()); wxMessageDialog dlg(GetParent(), s, _("Problem loading file"), wxOK | wxICON_ERROR); dlg.ShowModal(); return; @@ -188,7 +188,7 @@ void GameArea::LoadGame(const wxString& name) gbCPUInit(fn, use_bios); if (use_bios && !useBios) { - wxLogError(_("Could not load BIOS %s"), (gbCgbMode ? gopts.gbc_bios : gopts.gb_bios).c_str()); + wxLogError(_("Could not load BIOS %s"), (gbCgbMode ? gopts.gbc_bios : gopts.gb_bios).mb_str()); // could clear use flag & file name now, but better to force // user to do it } @@ -211,7 +211,7 @@ void GameArea::LoadGame(const wxString& name) { if (!(rom_size = CPULoadRom(fn))) { wxString s; - s.Printf(_("Unable to load Game Boy Advance ROM %s"), name.c_str()); + s.Printf(_("Unable to load Game Boy Advance ROM %s"), name.mb_str()); wxMessageDialog dlg(GetParent(), s, _("Problem loading file"), wxOK | wxICON_ERROR); dlg.ShowModal(); return; @@ -285,7 +285,7 @@ void GameArea::LoadGame(const wxString& name) CPUInit(gopts.gba_bios.mb_fn_str(), useBiosFileGBA); if (useBiosFileGBA && !useBios) { - wxLogError(_("Could not load BIOS %s"), gopts.gba_bios.c_str()); + wxLogError(_("Could not load BIOS %s"), gopts.gba_bios.mb_str()); // could clear use flag & file name now, but better to force // user to do it } @@ -354,7 +354,7 @@ void GameArea::LoadGame(const wxString& name) if (emusys->emuReadBattery(fnb.data())) { wxString msg; - msg.Printf(_("Loaded battery %s"), bat.GetFullPath().c_str()); + msg.Printf(_("Loaded battery %s"), bat.GetFullPath().mb_str()); systemScreenMessage(msg); if (cpuSaveType == 0 && ovSaveType == 0 && t == IMAGE_GBA) { @@ -570,7 +570,7 @@ bool GameArea::LoadState() bool GameArea::LoadState(int slot) { wxString fname; - fname.Printf(SAVESLOT_FMT, game_name().c_str(), slot); + fname.Printf(SAVESLOT_FMT, game_name().mb_str(), slot); return LoadState(wxFileName(statedir, fname)); } @@ -604,7 +604,7 @@ bool GameArea::LoadState(const wxFileName& fname) wxString msg; msg.Printf(ret ? _("Loaded state %s") : _("Error loading state %s"), - fname.GetFullPath().c_str()); + fname.GetFullPath().mb_str()); systemScreenMessage(msg); return ret; } @@ -617,7 +617,7 @@ bool GameArea::SaveState() bool GameArea::SaveState(int slot) { wxString fname; - fname.Printf(SAVESLOT_FMT, game_name().c_str(), slot); + fname.Printf(SAVESLOT_FMT, game_name().mb_str(), slot); return SaveState(wxFileName(statedir, fname)); } @@ -628,7 +628,7 @@ bool GameArea::SaveState(const wxFileName& fname) wxGetApp().frame->update_state_ts(true); wxString msg; msg.Printf(ret ? _("Saved state %s") : _("Error saving state %s"), - fname.GetFullPath().c_str()); + fname.GetFullPath().mb_str()); systemScreenMessage(msg); return ret; } @@ -659,9 +659,9 @@ void GameArea::SaveBattery(bool quiet) // of course some games just write battery way too often for such // a thing to be useful if (emusys->emuWriteBattery(fnb.data())) - msg.Printf(_("Wrote battery %s"), fn.c_str()); + msg.Printf(_("Wrote battery %s"), fn.mb_str()); else - msg.Printf(_("Error writing battery %s"), fn.c_str()); + msg.Printf(_("Error writing battery %s"), fn.mb_str()); systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; @@ -1782,7 +1782,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data) if (panel->osdstat.size()) drawText(todraw + outstride * (systemColorDepth != 24), outstride, - 10, 20, panel->osdstat.utf8_str(), showSpeedTransparent); + 10, 20, panel->osdstat.mb_str(), showSpeedTransparent); if (!disableStatusMessages && !panel->osdtext.empty()) { if (systemGetClock() - panel->osdtime < OSD_TIME) { @@ -1790,7 +1790,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data) int linelen = std::ceil(width * scale - 20) / 8; int nlines = (message.size() + linelen - 1) / linelen; int cury = height - 14 - nlines * 10; - const char* msg_data = message.utf8_str(); + const char* msg_data = message.mb_str(); char buf[message.size() + 1]; char* ptr = &buf[0]; std::strncpy(ptr, msg_data, message.size() + 1); @@ -2262,7 +2262,7 @@ void GameArea::StartVidRecording(const wxString& fname) if ((ret = vid_rec.Record(fnb.data(), basic_width, basic_height, systemColorDepth)) != MRET_OK) - wxLogError(_("Unable to begin recording to %s (%s)"), fname.c_str(), + wxLogError(_("Unable to begin recording to %s (%s)"), fname.mb_str(), media_err(ret)); else { MainFrame* mf = wxGetApp().frame; @@ -2293,7 +2293,7 @@ void GameArea::StartSoundRecording(const wxString& fname) MediaRet ret; if ((ret = snd_rec.Record(fnb.data())) != MRET_OK) - wxLogError(_("Unable to begin recording to %s (%s)"), fname.c_str(), + wxLogError(_("Unable to begin recording to %s (%s)"), fname.mb_str(), media_err(ret)); else { MainFrame* mf = wxGetApp().frame; diff --git a/src/wx/strutils.cpp b/src/wx/strutils.cpp new file mode 100644 index 00000000..d0f5fde6 --- /dev/null +++ b/src/wx/strutils.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "strutils.h" + +// From: https://stackoverflow.com/a/7408245/262458 +std::vector str_split(const wxString& text, const wxString& sep) { + std::vector tokens; + std::size_t start = 0, end = 0; + + while ((end = text.find(sep, start)) != std::string::npos) { + tokens.push_back(text.substr(start, end - start)); + start = end + 1; + } + + tokens.push_back(text.substr(start)); + + return tokens; +} + +// From: https://stackoverflow.com/a/15099743/262458 +std::size_t vec_find(std::vector& opts, const wxString& val) { + auto it = std::find(opts.begin(), opts.end(), val); + + if (it == opts.end()) + return wxNOT_FOUND; + + return std::distance(opts.begin(), it); +} diff --git a/src/wx/strutils.h b/src/wx/strutils.h new file mode 100644 index 00000000..5669154e --- /dev/null +++ b/src/wx/strutils.h @@ -0,0 +1,15 @@ +#ifndef STRUTILS_H +#define STRUTILS_H + +#include +#include +#include +#include + +// From: https://stackoverflow.com/a/7408245/262458 +std::vector str_split(const wxString& text, const wxString& sep); + +// From: https://stackoverflow.com/a/15099743/262458 +std::size_t vec_find(std::vector& opts, const wxString& val); + +#endif diff --git a/src/wx/sys.cpp b/src/wx/sys.cpp index 57199787..d777c750 100644 --- a/src/wx/sys.cpp +++ b/src/wx/sys.cpp @@ -44,7 +44,7 @@ void systemMessage(int id, const char* fmt, ...) va_list args; // auto-conversion of wxCharBuffer to const char * seems broken // so save underlying wxCharBuffer (or create one of none is used) - wxCharBuffer _fmt(wxString(wxGetTranslation(wxString(fmt, wxConvLibc))).utf8_str()); + wxCharBuffer _fmt(wxString(wxGetTranslation(wxString(fmt, wxConvLibc))).mb_str()); if (!buf) { buf = (char*)malloc(buflen); @@ -71,7 +71,7 @@ void systemMessage(int id, const char* fmt, ...) exit(1); } - wxLogError(wxT("%s"), wxString(buf, wxConvLibc).c_str()); + wxLogError(wxT("%s"), wxString(buf, wxConvLibc).mb_str()); } static int frames = 0; @@ -128,8 +128,8 @@ void systemStartGameRecording(const wxString& fname) uint32_t version = 1; - if (!game_file.Open(fn.c_str(), wxT("wb")) || game_file.Write(&version, sizeof(version)) != sizeof(version)) { - wxLogError(_("Cannot open output file %s"), fname.c_str()); + if (!game_file.Open(fn, wxT("wb")) || game_file.Write(&version, sizeof(version)) != sizeof(version)) { + wxLogError(_("Cannot open output file %s"), fname.mb_str()); return; } @@ -189,8 +189,8 @@ void systemStartGamePlayback(const wxString& fname) uint32_t version; - if (!game_file.Open(fn.c_str(), wxT("rb")) || game_file.Read(&version, sizeof(version)) != sizeof(version) || wxUINT32_SWAP_ON_BE(version) != 1) { - wxLogError(_("Cannot open recording file %s"), fname.c_str()); + if (!game_file.Open(fn, wxT("rb")) || game_file.Read(&version, sizeof(version)) != sizeof(version) || wxUINT32_SWAP_ON_BE(version) != 1) { + wxLogError(_("Cannot open recording file %s"), fname.mb_str()); return; } @@ -415,7 +415,7 @@ void systemScreenCapture(int num) do { wxString bfn; - bfn.Printf(wxT("%s%02d"), panel->game_name().c_str(), + bfn.Printf(wxT("%s%02d"), panel->game_name().mb_str(), num++); if (captureFormat == 0) @@ -434,7 +434,7 @@ void systemScreenCapture(int num) panel->emusys->emuWriteBMP(fn.GetFullPath().mb_fn_str()); wxString msg; - msg.Printf(_("Wrote snapshot %s"), fn.GetFullPath().c_str()); + msg.Printf(_("Wrote snapshot %s"), fn.GetFullPath().mb_str()); systemScreenMessage(msg); } @@ -805,7 +805,7 @@ void PrintDialog::DoSave(wxCommandEvent&) if (scimg.SaveFile(of)) { wxString msg; - msg.Printf(_("Wrote printer output to %s"), of.c_str()); + msg.Printf(_("Wrote printer output to %s"), of.mb_str()); systemScreenMessage(msg); wxButton* cb = wxStaticCast(dlg->FindWindow(wxID_CANCEL), wxButton); @@ -963,7 +963,7 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con do { wxString bfn; - bfn.Printf(wxT("%s-print%02d"), panel->game_name().c_str(), + bfn.Printf(wxT("%s-print%02d"), panel->game_name().mb_str(), num++); if (captureFormat == 0) @@ -986,7 +986,7 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con if (ret) { wxString msg; - msg.Printf(_("Wrote printer output to %s"), of.c_str()); + msg.Printf(_("Wrote printer output to %s"), of.mb_str()); systemScreenMessage(msg); } @@ -1170,7 +1170,7 @@ bool debugOpenPty() if ((pty_master = posix_openpt(O_RDWR | O_NOCTTY)) < 0 || grantpt(pty_master) < 0 || unlockpt(pty_master) < 0 || !(slave_name = ptsname(pty_master))) { wxLogError(_("Error opening pseudo tty: %s"), wxString(strerror(errno), wxConvLibc) - .c_str()); + .mb_str()); if (pty_master >= 0) { close(pty_master); diff --git a/src/wx/viewers.cpp b/src/wx/viewers.cpp index ebd2eb65..a47b8ed1 100644 --- a/src/wx/viewers.cpp +++ b/src/wx/viewers.cpp @@ -686,7 +686,7 @@ public: wxFileName fn(memsave_fn); if (!fn.IsFileReadable()) { - wxLogError(wxT("Can't open file %s"), memsave_fn.c_str()); + wxLogError(wxT("Can't open file %s"), memsave_fn.mb_str()); return; } diff --git a/src/wx/widgets/joyedit.cpp b/src/wx/widgets/joyedit.cpp index eb39631b..d5f9e695 100644 --- a/src/wx/widgets/joyedit.cpp +++ b/src/wx/widgets/joyedit.cpp @@ -261,7 +261,7 @@ bool wxJoyKeyTextCtrl::ParseString(const wxString& s, int len, int& mod, int& ke bool wxJoyKeyTextCtrl::FromString(const wxString& s, int& mod, int& key, int& joy) { - return ParseString(s.c_str(), s.size(), mod, key, joy); + return ParseString(s, s.size(), mod, key, joy); } wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString& s, wxChar sep) @@ -283,7 +283,7 @@ wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString& s, wxChar sep) continue; } - if (!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key, joy)) + if (!ParseString(s.Mid(lastkey + 1), len - lastkey - 1, mod, key, joy)) return empty; wxJoyKeyBinding jb = { key, mod, joy }; @@ -291,7 +291,7 @@ wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString& s, wxChar sep) len = lastkey; } - if (!ParseString(s.c_str(), len, mod, key, joy)) + if (!ParseString(s, len, mod, key, joy)) return empty; wxJoyKeyBinding jb = { key, mod, joy }; diff --git a/src/wx/widgets/keyedit.cpp b/src/wx/widgets/keyedit.cpp index a55967e6..2e5e94a0 100644 --- a/src/wx/widgets/keyedit.cpp +++ b/src/wx/widgets/keyedit.cpp @@ -245,7 +245,7 @@ bool wxKeyTextCtrl::ParseString(const wxString& s, int len, int& mod, int& key) bool wxKeyTextCtrl::FromString(const wxString& s, int& mod, int& key) { - return ParseString(s.c_str(), s.size(), mod, key); + return ParseString(s, s.size(), mod, key); } wxAcceleratorEntry_v wxKeyTextCtrl::FromString(const wxString& s, wxChar sep) @@ -264,14 +264,14 @@ wxAcceleratorEntry_v wxKeyTextCtrl::FromString(const wxString& s, wxChar sep) continue; } - if (!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key)) + if (!ParseString(s.Mid(lastkey + 1), len - lastkey - 1, mod, key)) return empty; ret.insert(ret.begin(), wxAcceleratorEntry(mod, key)); len = lastkey; } - if (!ParseString(s.c_str(), len, mod, key)) + if (!ParseString(s, len, mod, key)) return empty; ret.insert(ret.begin(), wxAcceleratorEntry(mod, key)); diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 37cd8fe9..b3df41df 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -19,8 +19,8 @@ #include #include #include - #include "wayland.h" +#include "strutils.h" // The built-in xrc file #include "builtin-xrc.h" @@ -58,13 +58,13 @@ static void get_config_path(wxPathList& path, bool exists = true) static bool debug_dumped = false; if (!debug_dumped) { - wxLogDebug(wxT("GetUserLocalDataDir(): %s"), stdp.GetUserLocalDataDir().c_str()); - wxLogDebug(wxT("GetUserDataDir(): %s"), stdp.GetUserDataDir().c_str()); - wxLogDebug(wxT("GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()): %s"), stdp.GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()).c_str()); - wxLogDebug(wxT("GetResourcesDir(): %s"), stdp.GetResourcesDir().c_str()); - wxLogDebug(wxT("GetDataDir(): %s"), stdp.GetDataDir().c_str()); - wxLogDebug(wxT("GetLocalDataDir(): %s"), stdp.GetLocalDataDir().c_str()); - wxLogDebug(wxT("GetPluginsDir(): %s"), stdp.GetPluginsDir().c_str()); + wxLogDebug(wxT("GetUserLocalDataDir(): %s"), stdp.GetUserLocalDataDir().mb_str()); + wxLogDebug(wxT("GetUserDataDir(): %s"), stdp.GetUserDataDir().mb_str()); + wxLogDebug(wxT("GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()): %s"), stdp.GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()).mb_str()); + wxLogDebug(wxT("GetResourcesDir(): %s"), stdp.GetResourcesDir().mb_str()); + wxLogDebug(wxT("GetDataDir(): %s"), stdp.GetDataDir().mb_str()); + wxLogDebug(wxT("GetLocalDataDir(): %s"), stdp.GetLocalDataDir().mb_str()); + wxLogDebug(wxT("GetPluginsDir(): %s"), stdp.GetPluginsDir().mb_str()); debug_dumped = true; } @@ -261,10 +261,8 @@ bool wxvbamApp::OnInit() // process command-line options for (int i = 0; i < pending_optset.size(); i++) { - wxString p = pending_optset[i]; - size_t eqat = p.find(wxT('=')); - p[eqat] = 0; - opt_set(p.c_str(), p.c_str() + eqat + 1); + auto parts = str_split(pending_optset[i], wxT('=')); + opt_set(parts[0], parts[1]); } pending_optset.clear(); @@ -458,7 +456,7 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) "To override, remove all but changed root node(s). " "First found root node of correct name in any .xrc or " ".xrs files in following search path overrides built-in:"), - s.c_str()); + s.mb_str()); tack_full_path(lm); wxLogMessage(lm); return false; @@ -483,7 +481,7 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) wxString lm; lm.Printf(_("Wrote built-in override file to %s\n" "To override, delete all but changed section. First found section is used from search path:"), - s.c_str()); + s.mb_str()); wxString oi = wxFileName::GetPathSeparator(); oi += wxT("vba-over.ini"); tack_full_path(lm, oi); @@ -537,44 +535,41 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) bool complained = false, gotfile = false; for (int i = 0; i < nparm; i++) { - wxString p = cl.GetParam(i); - size_t eqat = p.find(wxT('=')); + auto p = cl.GetParam(i); + auto parts = str_split(p, wxT('=')); - if (eqat != wxString::npos) { - p[eqat] = 0; - - if (!opt_set(p.c_str(), p.c_str() + eqat + 1)) { - p[eqat] = wxT('='); - eqat = wxString::npos; - } else - p[eqat] = wxT('='); + if (parts.size() > 1) { + opt_set(parts[0], parts[1]); pending_optset.push_back(p); } - - if (eqat == wxString::npos) { + else { if (!gotfile) { pending_load = p; gotfile = true; } else { if (!complained) { wxFprintf(stderr, _("Bad configuration option or multiple ROM files given:\n")); - wxFprintf(stderr, wxT("%s\n"), pending_load.c_str()); + wxFprintf(stderr, wxT("%s\n"), pending_load.mb_str()); complained = true; } - wxFprintf(stderr, wxT("%s\n"), p.c_str()); + wxFprintf(stderr, wxT("%s\n"), p); } } } - home = strdup(wxApp::argv[0].utf8_str()); + home = strdup(wxString(wxApp::argv[0]).char_str()); SetHome(home); LoadConfig(); // Parse command line arguments (overrides ini) ReadOpts(argc, (char**)argv); return true; } +wxvbamApp::~wxvbamApp() { + free(home); +} + MainFrame::MainFrame() : wxFrame() , focused(false) @@ -730,7 +725,7 @@ void MainFrame::update_state_ts(bool force) if (panel->game_type() != IMAGE_UNKNOWN) { wxString fn; - fn.Printf(SAVESLOT_FMT, panel->game_name().c_str(), i + 1); + fn.Printf(SAVESLOT_FMT, panel->game_name().mb_str(), i + 1); wxFileName fp(panel->state_dir(), fn); wxDateTime ts; // = wxInvalidDateTime diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 4db9b5ab..a33960ae 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -44,7 +44,7 @@ #undef wxLogDebug #define wxLogDebug(...) \ do { \ - fputs(wxString::Format(wxDateTime::UNow().Format(wxT("%X")) + wxT(": Debug: ") + __VA_ARGS__).utf8_str(), VBAM_DEBUG_STREAM); \ + fputs(wxString::Format(wxDateTime::UNow().Format(wxT("%X")) + wxT(": Debug: ") + __VA_ARGS__).mb_str(), VBAM_DEBUG_STREAM); \ fputc('\n', VBAM_DEBUG_STREAM); \ } while(0) #endif @@ -134,6 +134,9 @@ public: return false; } } + + virtual ~wxvbamApp(); + protected: bool using_wayland;