diff --git a/common/include/Utilities/StringHelpers.h b/common/include/Utilities/StringHelpers.h index ec64f0098a..4e8b674b6d 100644 --- a/common/include/Utilities/StringHelpers.h +++ b/common/include/Utilities/StringHelpers.h @@ -20,6 +20,47 @@ #include #include // for wxPoint/wxRect stuff + +// -------------------------------------------------------------------------------------- +// pxToUTF8 +// -------------------------------------------------------------------------------------- +// Converts a string to UTF8 and provides an interface for getting its length. +class pxToUTF8 +{ + DeclareNoncopyableObject( pxToUTF8 ); + +protected: + wxCharBuffer m_result; + int m_length; + +public: + explicit pxToUTF8(const wxString& src) + : m_result( src.ToUTF8() ) + { + m_length = -1; + } + + size_t Length() + { + if( -1 == m_length ) + m_length = strlen( m_result ); + return m_length; + } + + void Convert( const wxString& src ) + { + m_result = src.ToUTF8(); + m_length = -1; + } + + const char* data() const { return m_result; } + + operator const char*() const + { + return m_result.data(); + } +}; + extern void px_fputs( FILE* fp, const char* src ); extern wxString fromUTF8( const char* src ); diff --git a/common/src/Utilities/pxTextStream.cpp b/common/src/Utilities/pxTextStream.cpp index 0d1f0d834a..a380e06155 100644 --- a/common/src/Utilities/pxTextStream.cpp +++ b/common/src/Utilities/pxTextStream.cpp @@ -82,7 +82,10 @@ void pxWriteLine( wxOutputStream& output ) void pxWriteLine( wxOutputStream& output, const wxString& text ) { if( !text.IsEmpty() ) - output.Write(text.ToUTF8(), text.Length()); + { + pxToUTF8 utf8(text); + output.Write(utf8, utf8.Length()); + } pxWriteLine( output ); } @@ -92,7 +95,8 @@ void pxWriteMultiline( wxOutputStream& output, const wxString& src ) wxString result( src ); result.Replace( L"\r\n", L"\n" ); - result.Replace( L"\r", wxEmptyString ); + result.Replace( L"\r", L"\n" ); - output.Write(result.ToUTF8(), result.Length()); + pxToUTF8 utf8(result); + output.Write(utf8, utf8.Length()); } diff --git a/pcsx2/DataBase_Loader.cpp b/pcsx2/DataBase_Loader.cpp index 560aaecadf..c8302f616f 100644 --- a/pcsx2/DataBase_Loader.cpp +++ b/pcsx2/DataBase_Loader.cpp @@ -19,37 +19,40 @@ void DataBase_Loader::doError(const wxString& line, key_pair& keyPair, bool doMs // [/section] // // ... where the =value part is OPTIONAL. -void DataBase_Loader::extractMultiLine(key_pair& keyPair, wxInputStream& ffile) { +bool DataBase_Loader::extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& ffile) { - if (!keyPair.key.EndsWith(L"]")) { - doError(keyPair.key, keyPair, true); - return; + if (line[0] != L'[') return false; // All multiline sections begin with a '['! + + if (!line.EndsWith(L"]")) { + doError(line, keyPair, true); + return false; } - // Use Mid() to strip off the left and right side brackets. - ParsedAssignmentString set( keyPair.key.Mid(1, keyPair.key.Length()-2) ); - - wxString endString; - endString.Printf( L"[/%s]", set.lvalue.c_str() ); + keyPair.key = line; - for(;;) { + // Use Mid() to strip off the left and right side brackets. + wxString midLine(line.Mid(1, line.Length()-2)); + wxString lvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false)); + //wxString rvalue(midLine.AfterFirst(L'=').Trim(true).Trim(false)); + + wxString endString; + endString.Printf( L"[/%s]", lvalue.c_str() ); + + while(!ffile.Eof()) { pxReadLine( ffile, m_dest, m_intermediate ); if (m_dest == endString) break; keyPair.value += m_dest + L"\n"; } + return true; } void DataBase_Loader::extract(const wxString& line, key_pair& keyPair, wxInputStream& reader) { - keyPair.key = line; + keyPair.key.clear(); keyPair.value.clear(); if( line.IsEmpty() ) return; - if (keyPair.key[0] == L'[') { - extractMultiLine(keyPair, reader); - return; - } - + if( extractMultiLine(line, keyPair, reader) ) return; if( !pxParseAssignmentString( line, keyPair.key, keyPair.value ) ) return; if( keyPair.value.IsEmpty() ) doError(line, keyPair, true); diff --git a/pcsx2/DataBase_Loader.h b/pcsx2/DataBase_Loader.h index ff47acb064..737702d23a 100644 --- a/pcsx2/DataBase_Loader.h +++ b/pcsx2/DataBase_Loader.h @@ -31,8 +31,15 @@ struct key_pair { wxString toString() const { if (key[0] == '[') { pxAssumeDev( key.EndsWith(L"]"), "Malformed multiline key detected: missing end bracket!" ); - return wxsFormat( L"%s\n%s\n[/%s\n", - key.c_str(), value.c_str(), key.Mid(1, key.length()-1).c_str() + + // Terminating tag must be written without the "rvalue" -- in the form of: + // [/patches] + // Use Mid() to strip off the left and right side brackets. + wxString midLine(key.Mid(1, key.Length()-2)); + wxString keyLvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false)); + + return wxsFormat( L"%s\n%s[/%s]\n", + key.c_str(), value.c_str(), keyLvalue.c_str() ); } else { @@ -70,7 +77,7 @@ class DataBase_Loader { protected: bool isComment(const wxString& s); void doError(const wxString& line, key_pair& keyPair, bool doMsg = false); - void extractMultiLine(key_pair& keyPair, wxInputStream& reader); + bool extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& reader); void extract(const wxString& line, key_pair& keyPair, wxInputStream& reader); const wxString m_emptyString; // empty string for returning stuff .. never modify! diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 649a06004b..257574f496 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -1385,7 +1385,7 @@ void PluginManager::SendSettingsFolder() ScopedLock lock( m_mtx_PluginStatus ); if( m_SettingsFolder.IsEmpty() ) return; - wxCharBuffer utf8buffer( m_SettingsFolder.ToUTF8() ); + pxToUTF8 utf8buffer( m_SettingsFolder ); const PluginInfo* pi = tbl_PluginInfo; do { if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetSettingsDir( utf8buffer ); @@ -1412,7 +1412,7 @@ void PluginManager::SendLogFolder() ScopedLock lock( m_mtx_PluginStatus ); if( m_LogFolder.IsEmpty() ) return; - wxCharBuffer utf8buffer( m_LogFolder.ToUTF8() ); + pxToUTF8 utf8buffer( m_LogFolder ); const PluginInfo* pi = tbl_PluginInfo; do { if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogFolder( utf8buffer ); diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index d53048a2ff..2a8d2a4fa5 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -111,8 +111,9 @@ void SaveStateBase::FreezeBios() memzero( descin ); memzero( desccmp ); - memcpy_fast( descin, descout.ToUTF8().data(), descout.Length() ); - memcpy_fast( desccmp, descout.ToUTF8().data(), descout.Length() ); + pxToUTF8 utf8(descout); + memcpy_fast( descin, utf8, utf8.Length() ); + memcpy_fast( desccmp, utf8, utf8.Length() ); // ... and only freeze bios info once per state, since the user msg could // become really annoying on a corrupted state or something. (have to always @@ -130,7 +131,7 @@ void SaveStateBase::FreezeBios() Console.Indent(2).Error( "Current Version: %s\n" "Savestate Version: %s\n", - descout.ToUTF8().data(), descin + utf8.data(), descin ); } } diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index 06164606ee..9c04d42b42 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -359,14 +359,17 @@ namespace Panels wxTextCtrl* commentBox; wxTextCtrl* patchesBox; pxCheckBox* gameFixes[NUM_OF_GAME_FIXES]; + public: GameDatabasePanel( wxWindow* parent ); virtual ~GameDatabasePanel() throw() { } - void PopulateFields(); - void WriteFieldsToDB(); - void Search_Click( wxCommandEvent& evt ); void Apply(); void AppStatusEvent_OnSettingsApplied(); + + protected: + void PopulateFields(); + bool WriteFieldsToDB(); + void Search_Click( wxCommandEvent& evt ); }; class SettingsDirPickerPanel : public DirPickerPanel diff --git a/pcsx2/gui/Panels/GameDatabasePanel.cpp b/pcsx2/gui/Panels/GameDatabasePanel.cpp index 29c40317c5..301d7038e9 100644 --- a/pcsx2/gui/Panels/GameDatabasePanel.cpp +++ b/pcsx2/gui/Panels/GameDatabasePanel.cpp @@ -141,11 +141,12 @@ void Panels::GameDatabasePanel::PopulateFields() { else GameDB->writeBool(wxT(_key), _value); \ } -void Panels::GameDatabasePanel::WriteFieldsToDB() { +// returns True if the database is modified, or FALSE if no changes to save. +bool Panels::GameDatabasePanel::WriteFieldsToDB() { wxString wxStr( serialBox->GetValue() ); - if (wxStr.IsEmpty()) return; - if (wxStr == GameDB->getString("Serial")) { + if (wxStr.IsEmpty()) return false; + if (wxStr != GameDB->getString("Serial")) { GameDB->addGame(wxStr); } @@ -163,6 +164,7 @@ void Panels::GameDatabasePanel::WriteFieldsToDB() { writeGameFixToDB("IPUWaitHack", gameFixes[6]->GetValue()); writeGameFixToDB("EETimingHack", gameFixes[7]->GetValue()); writeGameFixToDB("SkipMPEGHack", gameFixes[8]->GetValue()); + return true; } void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) { @@ -178,9 +180,11 @@ void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) { } void Panels::GameDatabasePanel::Apply() { - Console.WriteLn("Saving changes to Game Database..."); - WriteFieldsToDB(); - GameDB->saveToFile(); + if( WriteFieldsToDB() ) + { + Console.WriteLn("Saving changes to Game Database..."); + GameDB->saveToFile(); + } } void Panels::GameDatabasePanel::AppStatusEvent_OnSettingsApplied()