From 60b8093f5bbb93c829e96f9cf737cfffb858081e Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 18 May 2011 21:49:11 +0000 Subject: [PATCH] - attempt to get non ascii file paths working in megaglest (Japanese etc...) --- mk/windoze/glest_game.vcproj | 4 +- mk/windoze/shared_lib.vcproj | 6 +- source/g3d_viewer/main.cpp | 55 ++++++++------- source/glest_game/ai/ai_interface.cpp | 8 +++ source/glest_game/facilities/logger.cpp | 9 +++ source/glest_game/global/config.cpp | 9 ++- source/glest_game/graphics/renderer.cpp | 8 +++ source/glest_game/main/main.cpp | Bin 122047 -> 245292 bytes source/glest_game/menu/menu_state_about.cpp | 8 +++ .../menu/menu_state_connected_game.cpp | 4 ++ .../menu/menu_state_custom_game.cpp | 12 ++++ source/glest_game/menu/menu_state_mods.cpp | 7 +- source/glest_game/world/map.cpp | 4 ++ source/glest_game/world/world.cpp | 9 ++- .../shared_lib/include/graphics/FileReader.h | 64 ++++++++++++++++-- .../include/platform/win32/platform_util.h | 4 ++ .../sources/graphics/gl/font_gl.cpp | 2 + source/shared_lib/sources/graphics/model.cpp | 11 +++ source/shared_lib/sources/graphics/pixmap.cpp | 24 +++++++ source/shared_lib/sources/map/map_preview.cpp | 10 ++- .../platform/common/platform_common.cpp | 63 +++++++++++++---- .../sources/platform/posix/ircclient.cpp | 12 ++-- .../sources/platform/posix/miniftpclient.cpp | 9 +++ .../sources/platform/win32/gl_wrap_billy.cpp | 52 ++++++++++++-- .../platform/win32/{glob.c => glob.cpp} | 26 ++++--- .../sources/platform/win32/platform_util.cpp | 64 ++++++++++++++++-- .../sources/sound/sound_file_loader.cpp | 10 ++- source/shared_lib/sources/util/checksum.cpp | 6 ++ .../shared_lib/sources/util/leak_dumper.cpp | 4 ++ source/shared_lib/sources/util/profiler.cpp | 4 ++ source/shared_lib/sources/util/properties.cpp | 49 +++++++++++--- source/shared_lib/sources/util/util.cpp | 53 +++++++++------ source/tools/glexemel/g2xml.c | 11 ++- source/tools/glexemel/xml2g.c | 8 ++- 34 files changed, 519 insertions(+), 110 deletions(-) rename source/shared_lib/sources/platform/win32/{glob.c => glob.cpp} (93%) diff --git a/mk/windoze/glest_game.vcproj b/mk/windoze/glest_game.vcproj index b662a898a..9fc01be87 100644 --- a/mk/windoze/glest_game.vcproj +++ b/mk/windoze/glest_game.vcproj @@ -46,7 +46,7 @@ WholeProgramOptimization="false" AdditionalIncludeDirectories="../../source/shared_lib/include/graphics;../../source/shared_lib/include/graphics/gl;../../source/shared_lib/include/platform;../../source/shared_lib/include/platform/win32;../../source/shared_lib/include/sound;../../source/shared_lib/include/sound/ds8;../../source/shared_lib/include/util;../../source/shared_lib/include/lua;../../source/shared_lib/include/xml;../../source/shared_lib/include/tinyxml;../../source/glest_game/ai;../../source/glest_game/facilities;../../source/glest_game/game;../../source/glest_game/global;../../source/glest_game/graphics;../../source/glest_game/gui;../../source/glest_game/main;../../source/glest_game/menu;../../source/glest_game/network;../../source/glest_game/sound;../../source/glest_game/type_instances;../../source/glest_game/types;../../source/glest_game/world;../../source/win32_deps/include;"../../source/win32_deps/xerces-c-3.0.1/src";"../../source/win32_deps/SDL-1.2.x/include";../../source/shared_lib/include/platform/sdl;../../source/shared_lib/include/sound/openal;"../../source/win32_deps/openal-soft-1.12.854/include";../../source/shared_lib/include/platform/posix;../../source/shared_lib/include/streflop;../../source/shared_lib/include/platform/common;"../../source/win32_deps/curl-7.21.3/include";../../source/shared_lib/include/map;$(NOINHERIT);../../source/win32_deps/libircclient/include" AdditionalUsingDirectories="" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;XML_LIBRARY;USE_PCH=1;_CRT_SECURE_NO_WARNINGS;USE_STREFLOP;STREFLOP_SSE;LIBM_COMPILING_FLT32;CURL_STATICLIB" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;XML_LIBRARY;USE_PCH=1;_CRT_SECURE_NO_WARNINGS;USE_STREFLOP;STREFLOP_SSE;LIBM_COMPILING_FLT32;CURL_STATICLIB; UNICODE" StringPooling="true" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -139,7 +139,7 @@ WholeProgramOptimization="false" AdditionalIncludeDirectories="../../source/shared_lib/include/graphics;../../source/shared_lib/include/graphics/gl;../../source/shared_lib/include/platform;../../source/shared_lib/include/platform/win32;../../source/shared_lib/include/sound;../../source/shared_lib/include/sound/ds8;../../source/shared_lib/include/util;../../source/shared_lib/include/lua;../../source/shared_lib/include/xml;../../source/shared_lib/include/tinyxml;../../source/glest_game/ai;../../source/glest_game/facilities;../../source/glest_game/game;../../source/glest_game/global;../../source/glest_game/graphics;../../source/glest_game/gui;../../source/glest_game/main;../../source/glest_game/menu;../../source/glest_game/network;../../source/glest_game/sound;../../source/glest_game/type_instances;../../source/glest_game/types;../../source/glest_game/world;../../source/win32_deps/include;"../../source/win32_deps/xerces-c-3.0.1/src";"../../source/win32_deps/SDL-1.2.x/include";../../source/shared_lib/include/platform/sdl;../../source/shared_lib/include/sound/openal;"../../source/win32_deps/openal-soft-1.12.854/include";../../source/shared_lib/include/platform/posix;../../source/shared_lib/include/streflop;../../source/shared_lib/include/platform/common;"../../source/win32_deps/curl-7.21.3/include";../../source/shared_lib/include/map;$(NOINHERIT);../../source/win32_deps/libircclient/include" AdditionalUsingDirectories="" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;XML_LIBRARY;USE_PCH=1;_CRT_SECURE_NO_WARNINGS;USE_STREFLOP;STREFLOP_SSE;LIBM_COMPILING_FLT32;CURL_STATICLIB" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;XML_LIBRARY;USE_PCH=1;_CRT_SECURE_NO_WARNINGS;USE_STREFLOP;STREFLOP_SSE;LIBM_COMPILING_FLT32;CURL_STATICLIB;UNICODE" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" diff --git a/mk/windoze/shared_lib.vcproj b/mk/windoze/shared_lib.vcproj index 7d4a53283..ff9c7abd1 100644 --- a/mk/windoze/shared_lib.vcproj +++ b/mk/windoze/shared_lib.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../source/shared_lib/include;../../source/shared_lib/include/graphics;../../source/shared_lib/include/graphics/gl;../../source/shared_lib/include/platform;../../source/shared_lib/include/platform/win32;../../source/shared_lib/include/sound;../../source/shared_lib/include/sound/ds8;../../source/shared_lib/include/util;../../source/shared_lib/include/lua;../../source/shared_lib/include/xml;../../source/win32_deps/include;"../../source/win32_deps/xerces-c-3.0.1/src";"../../source/win32_deps/xerces-c-3.0.1/src/xercesc/xinclude";../../source/win32_deps/lpng141;"../../source/win32_deps/jpeg-8a";"../../source/win32_deps/SDL-1.2.x/include";../../source/shared_lib/include/platform/sdl;"../../source/win32_deps/openal-soft-1.12.854/include";../../source/shared_lib/include/sound/openal;../../source/shared_lib/include/platform/posix;../../source/shared_lib/include/streflop;../../source/shared_lib/include/streflop/libm_flt32_source;../../source/shared_lib/include/platform/common;"../../source/win32_deps/curl-7.21.3/include";../../source/shared_lib/include/map;../../source/shared_lib/include/platform/miniupnpc;../../source/shared_lib/include/libircclient/include;../../source/shared_lib/include/feathery_ftp" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_PCH=1;USE_STREFLOP;STREFLOP_SSE;STREFLOP_RANDOM_GEN_SIZE=32;LIBM_COMPILING_FLT32;CURL_STATICLIB" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_PCH=1;USE_STREFLOP;STREFLOP_SSE;STREFLOP_RANDOM_GEN_SIZE=32;LIBM_COMPILING_FLT32;CURL_STATICLIB;UNICODE" StringPooling="true" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -121,7 +121,7 @@ FavorSizeOrSpeed="1" WholeProgramOptimization="false" AdditionalIncludeDirectories="../../source/shared_lib/include;../../source/shared_lib/include/graphics;../../source/shared_lib/include/graphics/gl;../../source/shared_lib/include/platform;../../source/shared_lib/include/platform/win32;../../source/shared_lib/include/sound;../../source/shared_lib/include/sound/ds8;../../source/shared_lib/include/util;../../source/shared_lib/include/lua;../../source/shared_lib/include/xml;../../source/win32_deps/include;"../../source/win32_deps/xerces-c-3.0.1/src";"../../source/win32_deps/xerces-c-3.0.1/src/xercesc/xinclude";../../source/win32_deps/lpng141;"../../source/win32_deps/jpeg-8a";"../../source/win32_deps/SDL-1.2.x/include";../../source/shared_lib/include/platform/sdl;"../../source/win32_deps/openal-soft-1.12.854/include";../../source/shared_lib/include/sound/openal;../../source/shared_lib/include/platform/posix;../../source/shared_lib/include/streflop;../../source/shared_lib/include/streflop/libm_flt32_source;../../source/shared_lib/include/platform/common;"../../source/win32_deps/curl-7.21.3/include";../../source/shared_lib/include/map;../../source/shared_lib/include/platform/miniupnpc;../../source/shared_lib/include/libircclient/include;../../source/shared_lib/include/feathery_ftp;$(NOINHERIT)" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_PCH=1;USE_STREFLOP;STREFLOP_SSE;STREFLOP_RANDOM_GEN_SIZE=32;LIBM_COMPILING_FLT32;CURL_STATICLIB" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_PCH=1;USE_STREFLOP;STREFLOP_SSE;STREFLOP_RANDOM_GEN_SIZE=32;LIBM_COMPILING_FLT32;CURL_STATICLIB;UNICODE" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" @@ -687,7 +687,7 @@ > +#include //#include #ifndef WIN32 @@ -360,30 +361,30 @@ MainWindow::MainWindow( std::pair > unitToLoad, // For windows register g3d file extension to launch this app #if defined(WIN32) && !defined(__MINGW32__) // example from: http://stackoverflow.com/questions/1387769/create-registry-entry-to-associate-file-extension-with-application-in-c - //[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command] - //@="c:\path\to\app.exe \"%1\"" - //[HKEY_CURRENT_USER\Software\Classes\.blerg] + //[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command] + //@="c:\path\to\app.exe \"%1\"" + //[HKEY_CURRENT_USER\Software\Classes\.blerg] //@="blergcorp.blergapp.v1" //Open the registry key. - string subKey = "Software\\Classes\\megaglest.g3d\\shell\\open\\command"; + string subKey = "Software\\Classes\\megaglest.g3d\\shell\\open\\command"; HKEY keyHandle; - DWORD dwDisposition; - RegCreateKeyEx(HKEY_CURRENT_USER,subKey.c_str(),0, NULL, 0, KEY_ALL_ACCESS, NULL, &keyHandle, &dwDisposition); - //Set the value. - string launchApp = appPath + " \"%1\""; - DWORD len = launchApp.length() + 1; - RegSetValueEx(keyHandle, NULL, 0, REG_SZ, (PBYTE)launchApp.c_str(), len); - RegCloseKey(keyHandle); - - subKey = "Software\\Classes\\.g3d"; - RegCreateKeyEx(HKEY_CURRENT_USER,subKey.c_str(),0, NULL, 0, KEY_ALL_ACCESS, NULL, &keyHandle, &dwDisposition); - //Set the value. - launchApp = "megaglest.g3d"; - len = launchApp.length() + 1; - RegSetValueEx(keyHandle, NULL, 0, REG_SZ, (PBYTE)launchApp.c_str(), len); - RegCloseKey(keyHandle); - + DWORD dwDisposition; + RegCreateKeyEx(HKEY_CURRENT_USER,subKey.c_str(),0, NULL, 0, KEY_ALL_ACCESS, NULL, &keyHandle, &dwDisposition); + //Set the value. + string launchApp = appPath + " \"%1\""; + DWORD len = launchApp.length() + 1; + RegSetValueEx(keyHandle, NULL, 0, REG_SZ, (PBYTE)launchApp.c_str(), len); + RegCloseKey(keyHandle); + + subKey = "Software\\Classes\\.g3d"; + RegCreateKeyEx(HKEY_CURRENT_USER,subKey.c_str(),0, NULL, 0, KEY_ALL_ACCESS, NULL, &keyHandle, &dwDisposition); + //Set the value. + launchApp = "megaglest.g3d"; + len = launchApp.length() + 1; + RegSetValueEx(keyHandle, NULL, 0, REG_SZ, (PBYTE)launchApp.c_str(), len); + RegCloseKey(keyHandle); + #endif } @@ -799,7 +800,11 @@ void MainWindow::saveScreenshot() { if(autoSaveScreenshotIndex >= 0) { string saveAsFilename = autoScreenShotParams[autoSaveScreenshotIndex]; saveAsFilename.erase(0,7); +#ifdef WIN32 + FILE*f = _wfopen(utf8_decode(saveAsFilename).c_str(), L"rb"); +#else FILE *f= fopen(saveAsFilename.c_str(), "rb"); +#endif if(f == NULL) { renderer->saveScreen(saveAsFilename.c_str()); } @@ -829,7 +834,11 @@ void MainWindow::saveScreenshot() { for(int i=0; i < 5000; ++i) { path = screenShotsPath; path += string("screen") + intToStr(i) + string(".") + fileFormat; +#ifdef WIN32 + FILE*f= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else FILE *f= fopen(path.c_str(), "rb"); +#endif if(f == NULL) { renderer->saveScreen(path); break; @@ -2128,9 +2137,9 @@ bool App::OnInit() { //#endif // printf("appPath [%s]\n",argv[0]); - wxString exe_path = wxStandardPaths::Get().GetExecutablePath(); - //wxString path_separator = wxFileName::GetPathSeparator(); - //exe_path = exe_path.BeforeLast(path_separator[0]); + wxString exe_path = wxStandardPaths::Get().GetExecutablePath(); + //wxString path_separator = wxFileName::GetPathSeparator(); + //exe_path = exe_path.BeforeLast(path_separator[0]); //exe_path += path_separator; #if defined(__MINGW32__) diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index 8d4d5e4e9..bd04856fa 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -52,7 +52,11 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useSta //clear log file if(logLevel>0){ +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(getLogFilename()).c_str(), L"wt"); +#else FILE *f= fopen(getLogFilename().c_str(), "wt"); +#endif if(f==NULL){ throw runtime_error("Can't open file: "+getLogFilename()); } @@ -80,7 +84,11 @@ void AiInterface::printLog(int logLevel, const string &s){ string logString= "(" + intToStr(factionIndex) + ") " + s; //print log to file +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(getLogFilename()).c_str(), L"at"); +#else FILE *f= fopen(getLogFilename().c_str(), "at"); +#endif if(f==NULL){ throw runtime_error("Can't open file: "+getLogFilename()); } diff --git a/source/glest_game/facilities/logger.cpp b/source/glest_game/facilities/logger.cpp index 3cd50e4ad..98251b773 100644 --- a/source/glest_game/facilities/logger.cpp +++ b/source/glest_game/facilities/logger.cpp @@ -19,6 +19,7 @@ #include "graphics_interface.h" #include "game_constants.h" #include "game_util.h" +#include "platform_util.h" #include "leak_dumper.h" using namespace std; @@ -63,7 +64,11 @@ Logger & Logger::getInstance() { } void Logger::add(const string str, bool renderScreen, const string statusText) { +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(fileName).c_str(), L"at+"); +#else FILE *f = fopen(fileName.c_str(), "at+"); +#endif if(f != NULL){ fprintf(f, "%s\n", str.c_str()); fclose(f); @@ -79,7 +84,11 @@ void Logger::add(const string str, bool renderScreen, const string statusText) void Logger::clear() { string s = "Log file\n"; +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(fileName).c_str(), L"wt+"); +#else FILE *f= fopen(fileName.c_str(), "wt+"); +#endif if(f == NULL){ throw runtime_error("Error opening log file" + fileName); } diff --git a/source/glest_game/global/config.cpp b/source/glest_game/global/config.cpp index c8dc260cc..2fad23955 100644 --- a/source/glest_game/global/config.cpp +++ b/source/glest_game/global/config.cpp @@ -194,10 +194,17 @@ Config::Config(std::pair type, std::pair f if(fileName.second != "" && fileExists(fileName.second) == false) { if(SystemFlags::VERBOSE_MODE_ENABLED) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] attempting to auto-create cfgFile.second = [%s]\n",__FILE__,__FUNCTION__,__LINE__,fileName.second.c_str()); +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(fileName.second).c_str(), L"w"); + std::ofstream userFile(fp); +#else std::ofstream userFile; userFile.open(fileName.second.c_str(), ios_base::out | ios_base::trunc); +#endif userFile.close(); - +#ifdef WIN32 + fclose(fp); +#endif fileLoaded.second = true; properties.second.load(fileName.second); } diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 16bc97dfd..d91ee0702 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -2488,6 +2488,12 @@ void Renderer::renderWater() { SurfaceCell *tc0= map->getSurfaceCell(i, j); SurfaceCell *tc1= map->getSurfaceCell(i, j+1); + if(tc0 == NULL) { + throw runtime_error("tc0 == NULL"); + } + if(tc1 == NULL) { + throw runtime_error("tc1 == NULL"); + } int thisTeamIndex= world->getThisTeamIndex(); @@ -4458,6 +4464,8 @@ void Renderer::init2dList() { //this list sets the state for the 2d rendering list2d= glGenLists(1); + assertGl(); + glNewList(list2d, GL_COMPILE); //projection diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 718bb5fba17bd06e32eec176f2e4f476d728fce1..284ec5fd10826ac508d7cba98648d14f529a7697 100644 GIT binary patch literal 245292 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 != mapFiles.end()); + string mapNameToRender = keyMapButtons[i]->getText(); + bool alreadyHasMap = (std::find(mapFiles.begin(),mapFiles.end(),mapNameToRender) != mapFiles.end()); if(keyMapButtons[i]->getText() == selectedMapName) { bool lightedOverride = true; renderer.renderButton(keyMapButtons[i],&WHITE,&lightedOverride); diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index 3e9039b81..82881a463 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -202,7 +202,11 @@ Vec2i Map::getStartLocation(int locationIndex) const { Checksum Map::load(const string &path, TechTree *techTree, Tileset *tileset) { Checksum mapChecksum; try{ +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else FILE *f = fopen(path.c_str(), "rb"); +#endif if(f != NULL) { mapChecksum.addFile(path); checksumValue.addFile(path); diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 6d13e4a2a..e3a0f7ef1 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -1677,9 +1677,13 @@ std::string World::DumpWorldToLog(bool consoleBasicInfoOnly) const { } else { +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(debugWorldLogFile).c_str(), L"w"); + std::ofstream logFile(fp); +#else std::ofstream logFile; logFile.open(debugWorldLogFile.c_str(), ios_base::out | ios_base::trunc); - +#endif logFile << "World debug information:" << std::endl; logFile << "========================" << std::endl; @@ -1704,6 +1708,9 @@ std::string World::DumpWorldToLog(bool consoleBasicInfoOnly) const { } logFile.close(); +#ifdef WIN32 + fclose(fp); +#endif } return debugWorldLogFile; } diff --git a/source/shared_lib/include/graphics/FileReader.h b/source/shared_lib/include/graphics/FileReader.h index 12baf3871..13fe5957c 100644 --- a/source/shared_lib/include/graphics/FileReader.h +++ b/source/shared_lib/include/graphics/FileReader.h @@ -141,7 +141,12 @@ public: template static inline T* readFromFileReaders(vector const *>* readers, const string& filepath) { //try to assign file +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(filepath).c_str(), L"rb"); + ifstream file(fp); +#else ifstream file(filepath.c_str(), ios::in | ios::binary); +#endif if (!file.is_open()) { //An error occured; TODO: Which one - throw an exception, print error message? throw runtime_error("Could not open file " + filepath); } @@ -155,18 +160,39 @@ static inline T* readFromFileReaders(vector const *>* readers, con continue; } if (ret != NULL) { + file.close(); +#ifdef WIN32 + fclose(fp); +#endif return ret; } } + file.close(); +#ifdef WIN32 + fclose(fp); +#endif + return NULL; } template static inline T* readFromFileReaders(vector const *>* readers, const string& filepath, T* object) { //try to assign file - ifstream file(filepath.c_str(), ios::in | ios::binary); +#ifdef WIN32 + wstring wstr = utf8_decode(filepath); + FILE *fp = _wfopen(wstr.c_str(), L"rb"); + int fileErrno = errno; + ifstream file(fp); +#else + ifstream file(friendly_path.c_str(), ios::in | ios::binary); +#endif if (!file.is_open()) { //An error occured; TODO: Which one - throw an exception, print error message? - throw runtime_error("Could not open file [" + filepath + "]"); +#ifdef WIN32 + DWORD error = GetLastError(); + throw runtime_error("Could not open file, result: " + intToStr(error) + " - " + intToStr(fileErrno) + " [" + filepath + "]"); +#else + throw runtime_error("Could not open file [" + friendly_path + "]"); +#endif } for (typename vector const *>::const_iterator i = readers->begin(); i != readers->end(); ++i) { T* ret = NULL; @@ -178,9 +204,17 @@ static inline T* readFromFileReaders(vector const *>* readers, con continue; } if (ret != NULL) { + file.close(); +#ifdef WIN32 + fclose(fp); +#endif return ret; } } + file.close(); +#ifdef WIN32 + fclose(fp); +#endif return NULL; } @@ -292,11 +326,22 @@ bool FileReader::canRead(ifstream& file) const { */ template T* FileReader::read(const string& filepath) const { +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(filepath).c_str(), L"rb"); + ifstream file(fp); +#else ifstream file(filepath.c_str(), ios::in | ios::binary); +#endif if (!file.is_open()) { //An error occured; TODO: Which one - throw an exception, print error message? throw runtime_error("Could not open file " + filepath); } - return read(file,filepath); + T* ret = read(file,filepath); + file.close(); +#ifdef WIN32 + fclose(fp); +#endif + + return ret; } /**Reads a file @@ -306,11 +351,22 @@ T* FileReader::read(const string& filepath) const { */ template T* FileReader::read(const string& filepath, T* object) const { +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(filepath).c_str(), L"rb"); + ifstream file(fp); +#else ifstream file(filepath.c_str(), ios::in | ios::binary); +#endif if (!file.is_open()) { //An error occured; TODO: Which one - throw an exception, print error message? throw runtime_error("Could not open file " + filepath); } - return read(file,filepath,object); + T* ret = read(file,filepath,object); + file.close(); +#ifdef WIN32 + fclose(fp); +#endif + + return ret; } diff --git a/source/shared_lib/include/platform/win32/platform_util.h b/source/shared_lib/include/platform/win32/platform_util.h index 9c1b21673..4d420e93e 100644 --- a/source/shared_lib/include/platform/win32/platform_util.h +++ b/source/shared_lib/include/platform/win32/platform_util.h @@ -28,6 +28,10 @@ namespace Shared{ namespace Platform{ // class PlatformExceptionHandler // ===================================================== +LPWSTR Ansi2WideString(LPCSTR lpaszString); +std::string utf8_encode(const std::wstring &wstr); +std::wstring utf8_decode(const std::string &str); + LONG WINAPI UnhandledExceptionFilter2(struct _EXCEPTION_POINTERS *ExceptionInfo); class PlatformExceptionHandler{ diff --git a/source/shared_lib/sources/graphics/gl/font_gl.cpp b/source/shared_lib/sources/graphics/gl/font_gl.cpp index e54bc58e3..77cd08e1f 100644 --- a/source/shared_lib/sources/graphics/gl/font_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/font_gl.cpp @@ -30,6 +30,8 @@ void Font2DGl::init(){ if(!inited){ handle= glGenLists(charCount); + assertGl(); + createGlFontBitmaps(handle, type, size, width, charCount, metrics); inited= true; } diff --git a/source/shared_lib/sources/graphics/model.cpp b/source/shared_lib/sources/graphics/model.cpp index 4d58e74d6..efa462bb3 100644 --- a/source/shared_lib/sources/graphics/model.cpp +++ b/source/shared_lib/sources/graphics/model.cpp @@ -20,6 +20,7 @@ #include "util.h" #include "platform_common.h" #include "opengl.h" +#include "platform_util.h" #include "leak_dumper.h" using namespace Shared::Platform; @@ -27,6 +28,7 @@ using namespace Shared::PlatformCommon; using namespace Shared::Graphics::Gl; using namespace std; +using namespace Shared::Util; namespace Shared{ namespace Graphics{ @@ -801,7 +803,11 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad, string sourceLoader) { try{ +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else FILE *f=fopen(path.c_str(),"rb"); +#endif if (f == NULL) { printf("In [%s::%s] cannot load file = [%s]\n",__FILE__,__FUNCTION__,path.c_str()); throw runtime_error("Error opening g3d model file [" + path + "]"); @@ -887,7 +893,12 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad, void Model::saveG3d(const string &path, string convertTextureToFormat, bool keepsmallest) { string tempModelFilename = path + "cvt"; + +#ifdef WIN32 + FILE *f= _wfopen(utf8_decode(tempModelFilename).c_str(), L"wb"); +#else FILE *f= fopen(tempModelFilename.c_str(), "wb"); +#endif if(f == NULL) { throw runtime_error("Cant open file for writting: [" + tempModelFilename + "]"); } diff --git a/source/shared_lib/sources/graphics/pixmap.cpp b/source/shared_lib/sources/graphics/pixmap.cpp index 6b360ae75..033ec5db6 100644 --- a/source/shared_lib/sources/graphics/pixmap.cpp +++ b/source/shared_lib/sources/graphics/pixmap.cpp @@ -101,7 +101,11 @@ PixmapIoTga::~PixmapIoTga() { } void PixmapIoTga::openRead(const string &path) { +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else file= fopen(path.c_str(),"rb"); +#endif if (file == NULL) { throw runtime_error("Can't open TGA file: "+ path); } @@ -181,7 +185,11 @@ void PixmapIoTga::openWrite(const string &path, int w, int h, int components) { this->h= h; this->components= components; +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"wb"); +#else file= fopen(path.c_str(),"wb"); +#endif if (file == NULL) { throw runtime_error("Can't open TGA file: "+ path); } @@ -229,7 +237,11 @@ PixmapIoBmp::~PixmapIoBmp() { } void PixmapIoBmp::openRead(const string &path){ +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else file= fopen(path.c_str(),"rb"); +#endif if (file==NULL){ throw runtime_error("Can't open BMP file: "+ path); } @@ -288,7 +300,11 @@ void PixmapIoBmp::openWrite(const string &path, int w, int h, int components) { this->h= h; this->components= components; +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"wb"); +#else file= fopen(path.c_str(),"wb"); +#endif if (file == NULL) { throw runtime_error("Can't open BMP file for writing: "+ path); } @@ -413,7 +429,11 @@ void PixmapIoPng::openWrite(const string &path, int w, int h, int components) { this->h= h; this->components= components; +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"wb"); +#else file= fopen(path.c_str(),"wb"); +#endif if (file == NULL) { throw runtime_error("Can't open PNG file for writing: "+ path); } @@ -602,7 +622,11 @@ void PixmapIoJpg::openWrite(const string &path, int w, int h, int components) { this->h= h; this->components= components; +#ifdef WIN32 + file= _wfopen(utf8_decode(path).c_str(), L"wb"); +#else file= fopen(path.c_str(),"wb"); +#endif if (file == NULL) { throw runtime_error("Can't open JPG file for writing: "+ path); } diff --git a/source/shared_lib/sources/map/map_preview.cpp b/source/shared_lib/sources/map/map_preview.cpp index 68dbcc8b9..82c1d10c5 100644 --- a/source/shared_lib/sources/map/map_preview.cpp +++ b/source/shared_lib/sources/map/map_preview.cpp @@ -15,6 +15,7 @@ #include "math_wrapper.h" #include #include +#include "platform_util.h" using namespace Shared::Util; using namespace std; @@ -682,7 +683,11 @@ void MapPreview::switchSurfaces(MapSurfaceType surf1, MapSurfaceType surf2) { void MapPreview::loadFromFile(const string &path) { +#ifdef WIN32 + FILE* f1= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else FILE *f1 = fopen(path.c_str(), "rb"); +#endif if (f1 != NULL) { //read header @@ -751,8 +756,11 @@ void MapPreview::loadFromFile(const string &path) { void MapPreview::saveToFile(const string &path) { - +#ifdef WIN32 + FILE* f1= _wfopen(utf8_decode(path).c_str(), L"wb"); +#else FILE *f1 = fopen(path.c_str(), "wb"); +#endif if (f1 != NULL) { //write header diff --git a/source/shared_lib/sources/platform/common/platform_common.cpp b/source/shared_lib/sources/platform/common/platform_common.cpp index 08a338650..c4bcd65d1 100644 --- a/source/shared_lib/sources/platform/common/platform_common.cpp +++ b/source/shared_lib/sources/platform/common/platform_common.cpp @@ -56,6 +56,7 @@ #include #include "randomgen.h" #include +#include "platform_util.h" #include "leak_dumper.h" using namespace Shared::Platform; @@ -290,7 +291,7 @@ void findAll(const vector &paths, const string &fileFilter, vector 0) { for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) { - string ¤t_file = current_results[folder_index]; + string current_file = current_results[folder_index]; if(keepDuplicates == true || std::find(results.begin(),results.end(),current_file) == results.end()) { results.push_back(current_file); } @@ -319,16 +320,14 @@ void findAll(const string &path, vector &results, bool cutExtension, boo glob_t globbuf; int res = glob(mypath.c_str(), 0, 0, &globbuf); - if(res < 0 && errorOnNotFound == true) - { + if(res < 0 && errorOnNotFound == true) { if(errorOnNotFound) { std::stringstream msg; msg << "#1 Couldn't scan directory '" << mypath << "': " << strerror(errno); throw runtime_error(msg.str()); } } - else - { + else { for(int i = 0; i < globbuf.gl_pathc; ++i) { const char* p = globbuf.gl_pathv[i]; const char* begin = p; @@ -370,8 +369,13 @@ bool isdir(const char *path) } #endif +#ifdef WIN32 + struct _stat64i32 stats; + int result = _wstat(utf8_decode(friendly_path).c_str(), &stats); +#else struct stat stats; int result = stat(friendly_path.c_str(), &stats); +#endif bool ret = (result == 0); if(ret == true) { ret = S_ISDIR(stats.st_mode); // #define S_ISDIR(mode) ((mode) & _S_IFDIR) @@ -423,7 +427,8 @@ void removeFolder(const string path) { //printf("~~~~~ REMOVE FOLDER [%s] in [%s]\n",item.c_str(),path.c_str()); #ifdef WIN32 - int result = _rmdir(item.c_str()); + //int result = _rmdir(item.c_str()); + int result = _wrmdir(utf8_decode(item).c_str()); #else int result = rmdir(item.c_str()); #endif @@ -437,7 +442,8 @@ void removeFolder(const string path) { } #ifdef WIN32 - int result = _rmdir(path.c_str()); + //int result = _rmdir(path.c_str()); + int result = _wrmdir(utf8_decode(path).c_str()); #else int result = rmdir(path.c_str()); #endif @@ -555,7 +561,11 @@ pair hasCachedFileCRCValue(string crcCacheFile, int32 &value) { //bool result = false; pair result = make_pair(false,0); if(fileExists(crcCacheFile) == true) { +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"r"); +#else FILE *fp = fopen(crcCacheFile.c_str(),"r"); +#endif if(fp != NULL) { time_t refreshDate = 0; int32 crcValue = 0; @@ -589,7 +599,11 @@ pair hasCachedFileCRCValue(string crcCacheFile, int32 &value) { } void writeCachedFileCRCValue(string crcCacheFile, int32 &crcValue) { +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"w"); +#else FILE *fp = fopen(crcCacheFile.c_str(),"w"); +#endif if(fp != NULL) { //RandomGen random; //int offset = random.randRange(5, 15); @@ -1258,7 +1272,8 @@ void createDirectoryPaths(string Path) { if ('/' == *path) { if(isdir(DirName) == false) { #ifdef WIN32 - int result = _mkdir(DirName); + int result = _wmkdir(utf8_decode(DirName).c_str()); + //int result = _mkdir(DirName); #elif defined(__GNUC__) int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG); #else @@ -1271,12 +1286,14 @@ void createDirectoryPaths(string Path) { *dirName = '\0'; } #ifdef WIN32 - _mkdir(DirName); + //int result = _mkdir(DirName); + int result = _wmkdir(utf8_decode(DirName).c_str()); #elif defined(__GNUC__) - mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG); + int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG); #else #error "Your compiler needs to support mkdir!" #endif + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DirName [%s] result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,DirName,result,errno); } void getFullscreenVideoInfo(int &colorBits,int &screenWidth,int &screenHeight,bool isFullscreen) { @@ -1653,7 +1670,7 @@ bool executeShellCommand(string cmd, int expectedResult) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to run [%s]", cmd.c_str()); #ifdef WIN32 - FILE *file = _popen(cmd.c_str(),"r"); + FILE *file = _wpopen(utf8_decode(cmd).c_str(),L"r"); #else FILE *file = popen(cmd.c_str(),"r"); #endif @@ -1699,8 +1716,13 @@ bool renameFile(string oldFile, string newFile) { } off_t getFileSize(string filename) { +#ifdef WIN32 + struct _stat64i32 stbuf; + if(_wstat(utf8_decode(filename).c_str(), &stbuf) != -1) { +#else struct stat stbuf; if(stat(filename.c_str(), &stbuf) != -1) { +#endif return stbuf.st_size; } return 0; @@ -1710,7 +1732,7 @@ string executable_path(string exeName, bool includeExeNameInPath) { string value = ""; #ifdef _WIN32 char path[MAX_PATH]=""; - if( GetModuleFileName(NULL,path,MAX_PATH) == 0 ) { + if( GetModuleFileNameA(NULL,path,MAX_PATH) == 0 ) { if(includeExeNameInPath == true) { value = exeName; } @@ -1802,8 +1824,13 @@ bool searchAndReplaceTextInFile(string fileName, string findText, string replace size_t find_len = findText.length(); string tempfileName = fileName + "_tmp"; +#ifdef WIN32 + fp1 = _wfopen(utf8_decode(fileName).c_str(), L"r"); + fp2 = _wfopen(utf8_decode(tempfileName).c_str(), L"w"); +#else fp1 = fopen(fileName.c_str(),"r"); fp2 = fopen(tempfileName.c_str(),"w"); +#endif while(fgets(buffer,MAX_LEN_SINGLE_LINE + 2,fp1)) { buff_ptr = buffer; @@ -1839,8 +1866,15 @@ bool searchAndReplaceTextInFile(string fileName, string findText, string replace void copyFileTo(string fromFileName, string toFileName) { //Open an input and output stream in binary mode +#ifdef WIN32 + FILE *fp1 = _wfopen(utf8_decode(fromFileName).c_str(), L"rb"); + ifstream in(fp1); + FILE *fp2 = _wfopen(utf8_decode(toFileName).c_str(), L"wb"); + ofstream out(fp2); +#else ifstream in(fromFileName.c_str(),ios::binary); ofstream out(toFileName.c_str(),ios::binary); +#endif if(in.is_open() && out.is_open()) { while(in.eof() == false) { @@ -1851,6 +1885,11 @@ void copyFileTo(string fromFileName, string toFileName) { //Close both files in.close(); out.close(); + +#ifdef WIN32 + fclose(fp1); + fclose(fp2); +#endif } // ===================================== diff --git a/source/shared_lib/sources/platform/posix/ircclient.cpp b/source/shared_lib/sources/platform/posix/ircclient.cpp index 00beae37a..5ae898171 100644 --- a/source/shared_lib/sources/platform/posix/ircclient.cpp +++ b/source/shared_lib/sources/platform/posix/ircclient.cpp @@ -43,12 +43,12 @@ void addlog (const char * fmt, ...) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> IRC: %s\n", buf); - if(SystemFlags::VERBOSE_MODE_ENABLED == true) { - if ( (fp = fopen ("irctest.log", "ab")) != 0 ) { - fprintf (fp, "%s\n", buf); - fclose (fp); - } - } + //if(SystemFlags::VERBOSE_MODE_ENABLED == true) { + // if ( (fp = fopen ("irctest.log", "ab")) != 0 ) { + // fprintf (fp, "%s\n", buf); + // fclose (fp); + // } + //} } void dump_event (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) { diff --git a/source/shared_lib/sources/platform/posix/miniftpclient.cpp b/source/shared_lib/sources/platform/posix/miniftpclient.cpp index 711c0e4cc..d392ebab3 100644 --- a/source/shared_lib/sources/platform/posix/miniftpclient.cpp +++ b/source/shared_lib/sources/platform/posix/miniftpclient.cpp @@ -19,6 +19,7 @@ #include #include #include "conversion.h" +#include "platform_util.h" using namespace Shared::Util; using namespace Shared::PlatformCommon; @@ -85,7 +86,11 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread opening file for writing [%s]\n",fullFilePath.c_str()); /* open file for writing */ +#ifdef WIN32 + out->stream= _wfopen(utf8_decode(fullFilePath).c_str(), L"wb"); +#else out->stream = fopen(fullFilePath.c_str(), "wb"); +#endif if(out->stream == NULL) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str()); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str()); @@ -1164,7 +1169,11 @@ pair FTPClientThread::getFileFromServer(FTP_Clien ftpfile.stream = NULL; } +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(destFileSaveAs).c_str(), L"rt"); +#else FILE *fp = fopen(destFileSaveAs.c_str(), "rt"); +#endif if(fp != NULL) { char szBuf[4096]=""; while(feof(fp) == false) { diff --git a/source/shared_lib/sources/platform/win32/gl_wrap_billy.cpp b/source/shared_lib/sources/platform/win32/gl_wrap_billy.cpp index 9c4bdde42..1cc6b6f51 100644 --- a/source/shared_lib/sources/platform/win32/gl_wrap_billy.cpp +++ b/source/shared_lib/sources/platform/win32/gl_wrap_billy.cpp @@ -19,13 +19,14 @@ #include "window.h" #include //#include +#include "platform_util.h" #include "leak_dumper.h" using namespace Shared::Graphics::Gl; using namespace Shared::Util; namespace Shared{ namespace Platform{ - + // ====================================== @@ -43,11 +44,15 @@ namespace Shared{ namespace Platform{ void createGlFontBitmaps(uint32 &base, const string &type, int size, int width, int charCount, FontMetrics &metrics) { + //return; + // -adecw-screen-medium-r-normal--18-180-75-75-m-160-gb2312.1980-1 this is a Chinese font std::string useRealFontName = type; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] trying to load useRealFontName [%s], size = %d, width = %d\n",__FILE__,__FUNCTION__,__LINE__,useRealFontName.c_str(),size,width); + DWORD dwErrorGL = 0; + HDC hDC = 0; static std::vector systemFontList; if(systemFontList.size() == 0) { LOGFONT lf; @@ -56,7 +61,16 @@ namespace Shared{ namespace Platform{ lf.lfCharSet = (BYTE)charSet; lf.lfFaceName[0]='\0'; - HDC hDC = wglGetCurrentDC(); + //HGLRC hdRC =wglGetCurrentContext(); + //DWORD dwErrorGL = GetLastError(); + //assertGl(); + + hDC = wglGetCurrentDC(); + dwErrorGL = GetLastError(); + assertGl(); + //hDC = CreateCompatibleDC(0); + //dwErrorGL = GetLastError(); + ::EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC) EnumFontFamExProc, @@ -79,17 +93,39 @@ namespace Shared{ namespace Platform{ } } } - + + LPWSTR wstr = Ansi2WideString(useRealFontName.c_str()); HFONT font= CreateFont( size, 0, 0, 0, width, FALSE, FALSE, FALSE, charSet, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - DEFAULT_PITCH| (useRealFontName.c_str() ? FF_DONTCARE:FF_SWISS), useRealFontName.c_str()); - + DEFAULT_PITCH| (useRealFontName.c_str() ? FF_DONTCARE:FF_SWISS), wstr); + delete [] wstr; assert(font!=NULL); HDC dc= wglGetCurrentDC(); + dwErrorGL = GetLastError(); + assertGl(); + SelectObject(dc, font); - BOOL err= wglUseFontBitmaps(dc, 0, charCount, base); + dwErrorGL = GetLastError(); + assertGl(); + + BOOL err= 0; + err= wglUseFontBitmaps(dc, 0, charCount, base); + dwErrorGL = GetLastError(); + +/* + for(int glBugRetry = 0; glBugRetry <= 10; glBugRetry++) { + err= wglUseFontBitmaps(dc, 0, charCount, base); + dwErrorGL = GetLastError(); + //assertGl(); + GLenum error = glGetError(); + if(error == 0) { + break; + } + } +*/ + assertGl(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] wglUseFontBitmaps returned = %d, charCount = %d, base = %d\n",__FILE__,__FUNCTION__,__LINE__,err,charCount,base); @@ -131,6 +167,10 @@ namespace Shared{ namespace Platform{ DeleteObject(font); + //if(hDC != 0) { + // DeleteDC(hDC); + //} + assert(err); } diff --git a/source/shared_lib/sources/platform/win32/glob.c b/source/shared_lib/sources/platform/win32/glob.cpp similarity index 93% rename from source/shared_lib/sources/platform/win32/glob.c rename to source/shared_lib/sources/platform/win32/glob.cpp index 5e95d3a23..291baff1c 100644 --- a/source/shared_lib/sources/platform/win32/glob.c +++ b/source/shared_lib/sources/platform/win32/glob.cpp @@ -47,21 +47,23 @@ #include #define NOMINMAX #include +#include "platform_util.h" #define NUM_ELEMENTS(ar) (sizeof(ar) / sizeof(ar[0])) +using namespace Shared::Util; /* ///////////////////////////////////////////////////////////////////////// * Helper functions */ static char const *strrpbrk(char const *string, char const *strCharSet) { - char *part = NULL; + char const *part = NULL; char const *pch; for(pch = strCharSet; *pch; ++pch) { - char *p = strrchr(string, *pch); + const char *p = strrchr(string, *pch); if(NULL != p) { @@ -102,7 +104,7 @@ int glob( char const *pattern int result; char szRelative[1 + _MAX_PATH]; char const *file_part; - WIN32_FIND_DATAA find_data; + WIN32_FIND_DATAW find_data; HANDLE hFind; char *buffer; char szPattern2[1 + _MAX_PATH]; @@ -167,7 +169,8 @@ int glob( char const *pattern bMagic0 = (leafMost == strpbrk(leafMost, "?*")); - hFind = FindFirstFileA(effectivePattern, &find_data); + std::wstring wstr = utf8_decode(effectivePattern); + hFind = FindFirstFileW(wstr.c_str(), &find_data); buffer = NULL; pglob->gl_pathc = 0; @@ -234,8 +237,8 @@ int glob( char const *pattern GLOB_NODOTSDIRS == (flags & GLOB_NODOTSDIRS)) { /* Pattern must begin with '.' to match either dots directory */ - if( 0 == lstrcmpA(".", find_data.cFileName) || - 0 == lstrcmpA("..", find_data.cFileName)) + if( 0 == lstrcmpW(L".", find_data.cFileName) || + 0 == lstrcmpW(L"..", find_data.cFileName)) { continue; } @@ -246,7 +249,7 @@ int glob( char const *pattern #if 0 if(find_data.cFileName[0] >= 'A' && find_data.cFileName[0] <= 'M') #endif /* 0 */ - (void)lstrcatA(find_data.cFileName, "/"); + (void)lstrcatW(find_data.cFileName, L"/"); } } else @@ -261,7 +264,9 @@ int glob( char const *pattern } } - cch = lstrlenA(find_data.cFileName); + //cch = lstrlenW(find_data.cFileName); + string sFileName = utf8_encode(find_data.cFileName); + cch = sFileName.length(); if(NULL != file_part) { cch += (int)(file_part - effectivePattern); @@ -291,12 +296,13 @@ int glob( char const *pattern } (void)lstrcpynA(buffer + cbCurr, szRelative, 1 + (int)(file_part - effectivePattern)); - (void)lstrcatA(buffer + cbCurr, find_data.cFileName); + (void)lstrcatA(buffer + cbCurr, sFileName.c_str()); cbCurr += cch + 1; ++cMatches; } - while(FindNextFile(hFind, &find_data) && cMatches != maxMatches); + //while(FindNextFileA(hFind, &find_data) && cMatches != maxMatches); + while(FindNextFileW(hFind, &find_data) && cMatches != maxMatches); (void)FindClose(hFind); diff --git a/source/shared_lib/sources/platform/win32/platform_util.cpp b/source/shared_lib/sources/platform/win32/platform_util.cpp index db489670e..a4e4aadd0 100644 --- a/source/shared_lib/sources/platform/win32/platform_util.cpp +++ b/source/shared_lib/sources/platform/win32/platform_util.cpp @@ -33,18 +33,63 @@ namespace Shared { namespace Platform { PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL; +// Constructs object and convert lpaszString to Unicode +LPWSTR Ansi2WideString(LPCSTR lpaszString) { + LPWSTR lpwszString(NULL); + int nLen = ::lstrlenA(lpaszString) + 1; + lpwszString = new WCHAR[nLen]; + if (lpwszString == NULL) { + return lpwszString; + } + + memset(lpwszString, 0, nLen * sizeof(WCHAR)); + + if (::MultiByteToWideChar(CP_ACP, 0, lpaszString, nLen, lpwszString, nLen) == 0) { + // Conversation failed + return lpwszString; + } + + return lpwszString; +} + +// Convert a wide Unicode string to an UTF8 string +std::string utf8_encode(const std::wstring &wstr) { + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); + std::string strTo( size_needed, 0 ); + WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); + replaceAll(strTo, "/", "\\"); + replaceAll(strTo, "\\\\", "\\"); + updatePathClimbingParts(strTo); + return strTo; +} + +// Convert an UTF8 string to a wide Unicode String +std::wstring utf8_decode(const std::string &str) { + string friendly_path = str; + replaceAll(friendly_path, "/", "\\"); + replaceAll(friendly_path, "\\\\", "\\"); + updatePathClimbingParts(friendly_path); + int size_needed = MultiByteToWideChar(CP_UTF8, 0, &friendly_path[0], (int)friendly_path.size(), NULL, 0); + std::wstring wstrTo( size_needed, 0 ); + MultiByteToWideChar(CP_UTF8, 0, &friendly_path[0], (int)friendly_path.size(), &wstrTo[0], size_needed); + return wstrTo; +} + + LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){ //printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + LPWSTR wstr = Ansi2WideString(thisPointer->dumpFileName.c_str()); HANDLE hFile = CreateFile( - thisPointer->dumpFileName.c_str(), + wstr, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + delete [] wstr; //printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -158,11 +203,16 @@ void message(string message){ std::cerr << " " << message << "\n"; std::cerr << "******************************************************\n"; - MessageBox(NULL, message.c_str(), "Message", MB_OK); + LPWSTR wstr = Ansi2WideString(message.c_str()); + MessageBox(NULL, wstr, L"Message", MB_OK); + delete [] wstr; } bool ask(string message){ - return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES; + LPWSTR wstr = Ansi2WideString(message.c_str()); + bool result = MessageBox(NULL, wstr, L"Confirmation", MB_YESNO)==IDYES; + delete [] wstr; + return result; } void exceptionMessage(const exception &excp){ @@ -175,7 +225,11 @@ void exceptionMessage(const exception &excp){ title= "Error: Unhandled Exception"; printf("Error detected with text: %s\n",message.c_str()); - MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL); + LPWSTR wstr = Ansi2WideString(message.c_str()); + LPWSTR wstr1 = Ansi2WideString(title.c_str()); + MessageBox(NULL, wstr, wstr1, MB_ICONSTOP | MB_OK | MB_TASKMODAL); + delete [] wstr; + delete [] wstr1; } //int getScreenW(){ @@ -192,7 +246,7 @@ HICON icon; void init_win32() { HINSTANCE handle = ::GetModuleHandle(NULL); - icon = ::LoadIcon(handle, "IDI_ICON1"); + icon = ::LoadIcon(handle, L"IDI_ICON1"); SDL_SysWMinfo wminfo; SDL_VERSION(&wminfo.version) diff --git a/source/shared_lib/sources/sound/sound_file_loader.cpp b/source/shared_lib/sources/sound/sound_file_loader.cpp index 0ff6a56c1..6038ccb6e 100644 --- a/source/shared_lib/sources/sound/sound_file_loader.cpp +++ b/source/shared_lib/sources/sound/sound_file_loader.cpp @@ -16,6 +16,7 @@ #include "sound.h" #include "util.h" +#include "platform_util.h" #include "leak_dumper.h" using namespace Shared::Platform; @@ -144,7 +145,11 @@ void WavSoundFileLoader::restart(){ void OggSoundFileLoader::open(const string &path, SoundInfo *soundInfo){ fileName = path; +#ifdef WIN32 + f = _wfopen(utf8_decode(path).c_str(), L"rb"); +#else f= fopen(path.c_str(), "rb"); +#endif if(f==NULL){ throw runtime_error("Can't open ogg file: "+path); } @@ -189,12 +194,13 @@ uint32 OggSoundFileLoader::read(int8 *samples, uint32 size){ return totalBytesRead; } -void OggSoundFileLoader::close(){ - if(vf!=NULL){ +void OggSoundFileLoader::close() { + if(vf != NULL) { ov_clear(vf); delete vf; vf= 0; } + fclose(f); } void OggSoundFileLoader::restart(){ diff --git a/source/shared_lib/sources/util/checksum.cpp b/source/shared_lib/sources/util/checksum.cpp index ab8ba63d4..2345fbde6 100644 --- a/source/shared_lib/sources/util/checksum.cpp +++ b/source/shared_lib/sources/util/checksum.cpp @@ -24,10 +24,12 @@ #include "util.h" #include "platform_common.h" #include "conversion.h" +#include "platform_util.h" #include "leak_dumper.h" using namespace std; using namespace Shared::PlatformCommon; +using namespace Shared::Util; namespace Shared{ namespace Util{ @@ -131,7 +133,11 @@ bool Checksum::addFileToSum(const string &path) { */ bool fileExists = false; +#ifdef WIN32 + FILE* file= _wfopen(utf8_decode(path).c_str(), L"rb"); +#else FILE* file= fopen(path.c_str(), "rb"); +#endif if(file != NULL) { fileExists = true; addString(lastFile(path)); diff --git a/source/shared_lib/sources/util/leak_dumper.cpp b/source/shared_lib/sources/util/leak_dumper.cpp index a689eaa23..a7e552aaa 100644 --- a/source/shared_lib/sources/util/leak_dumper.cpp +++ b/source/shared_lib/sources/util/leak_dumper.cpp @@ -91,7 +91,11 @@ void AllocRegistry::reset(){ } void AllocRegistry::dump(const char *path){ +#ifdef WIN32 + FILE* f= = _wfopen(utf8_decode(path).c_str(), L"wt"); +#else FILE *f= fopen(path, "wt"); +#endif int leakCount=0; size_t leakBytes=0; diff --git a/source/shared_lib/sources/util/profiler.cpp b/source/shared_lib/sources/util/profiler.cpp index d1d526b82..4cced37b4 100644 --- a/source/shared_lib/sources/util/profiler.cpp +++ b/source/shared_lib/sources/util/profiler.cpp @@ -83,7 +83,11 @@ Profiler::~Profiler(){ } profileLog = userData + profileLog; } +#ifdef WIN32 + FILE* f= = _wfopen(utf8_decode(profileLog).c_str(), L"w"); +#else FILE *f= fopen(profileLog.c_str(), "w"); +#endif if(f==NULL) throw runtime_error("Can not open file: " + profileLog); diff --git a/source/shared_lib/sources/util/properties.cpp b/source/shared_lib/sources/util/properties.cpp index ecf531983..5ed1828b4 100644 --- a/source/shared_lib/sources/util/properties.cpp +++ b/source/shared_lib/sources/util/properties.cpp @@ -18,6 +18,7 @@ #include "conversion.h" #include "util.h" #include "platform_common.h" +#include "platform_util.h" #ifdef WIN32 #include @@ -28,6 +29,7 @@ using namespace std; using namespace Shared::PlatformCommon; +using namespace Shared::Platform; namespace Shared{ namespace Util{ @@ -39,14 +41,19 @@ string Properties::applicationPath = ""; void Properties::load(const string &path, bool clearCurrentProperties) { - ifstream fileStream; char lineBuffer[maxLine]=""; string line, key, value; size_t pos=0; - this->path= path; +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(path).c_str(), L"r"); + ifstream fileStream(fp); +#else + ifstream fileStream; fileStream.open(path.c_str(), ios_base::in); +#endif + if(fileStream.fail()){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path = [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str()); throw runtime_error("Can't open propertyMap file: " + path); @@ -102,6 +109,9 @@ void Properties::load(const string &path, bool clearCurrentProperties) { } fileStream.close(); +#ifdef WIN32 + fclose(fp); +#endif } std::map Properties::getTagReplacementValues(std::map *mapExtraTagReplacementValues) { @@ -127,11 +137,20 @@ std::map Properties::getTagReplacementValues(std::map *mapTag // For win32 we allow use of the appdata variable since that is the recommended // place for application data in windows platform #ifdef WIN32 - TCHAR szPath[MAX_PATH]=""; + TCHAR szPath[MAX_PATH]; // Get path for each computer, non-user specific and non-roaming data. if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, 0, szPath))) { - string appPath = szPath; + //const wchar_t *wBuf = &szPath[0]; + //size_t size = MAX_PATH + 1; + //char pMBBuffer[MAX_PATH + 1]=""; + //wcstombs_s(&size, &pMBBuffer[0], (size_t)size, wBuf, (size_t)size);// Convert to char* from TCHAR[] + //string appPath=""; + //appPath.assign(&pMBBuffer[0]); // Now assign the char* to the string, and there you have it!!! :) + std::string appPath = utf8_encode(szPath); + + //string appPath = szPath; replaceAll(value, "$APPDATA", appPath); replaceAll(value, "%%APPDATA%%", appPath); } @@ -241,10 +268,13 @@ bool Properties::applyTagsToValue(string &value, std::map *mapTag } void Properties::save(const string &path){ +#ifdef WIN32 + FILE *fp = _wfopen(utf8_decode(path).c_str(), L"w"); + ofstream fileStream(fp); +#else ofstream fileStream; - fileStream.open(path.c_str(), ios_base::out | ios_base::trunc); - +#endif fileStream << "; === propertyMap File === \n"; fileStream << '\n'; @@ -253,6 +283,9 @@ void Properties::save(const string &path){ } fileStream.close(); +#ifdef WIN32 + fclose(fp); +#endif } void Properties::clear(){ diff --git a/source/shared_lib/sources/util/util.cpp b/source/shared_lib/sources/util/util.cpp index a6865fe1b..9000dccb2 100644 --- a/source/shared_lib/sources/util/util.cpp +++ b/source/shared_lib/sources/util/util.cpp @@ -29,12 +29,13 @@ #include "platform_common.h" #include "conversion.h" #include "simple_threads.h" - +#include "platform_util.h" #include "leak_dumper.h" using namespace std; using namespace Shared::Platform; using namespace Shared::PlatformCommon; +using namespace Shared::Util; namespace Shared{ namespace Util{ @@ -508,8 +509,12 @@ void SystemFlags::logDebugEntry(DebugType type, string debugEntry, time_t debugT } if(currentDebugLog.fileStream == NULL) { +#ifdef WIN32 + currentDebugLog.fileStream = new std::ofstream(_wfopen(utf8_decode(debugLog).c_str(), L"w")); +#else currentDebugLog.fileStream = new std::ofstream(); currentDebugLog.fileStream->open(debugLog.c_str(), ios_base::out | ios_base::trunc); +#endif currentDebugLog.fileStreamOwner = true; currentDebugLog.mutex = new Mutex(); } @@ -583,8 +588,8 @@ string lastDir(const string &s) { pos= i 0 && @@ -610,43 +615,47 @@ string cutLastFile(const string &s){ size_t j= s.find_last_of('\\'); size_t pos; - if(i==string::npos){ + if(i == string::npos) { pos= j; } - else if(j==string::npos){ + else if(j == string::npos) { pos= i; } else{ - pos= i