diff --git a/App/NatronApp_main.cpp b/App/NatronApp_main.cpp index 6af0a5d11a..db3131c01f 100644 --- a/App/NatronApp_main.cpp +++ b/App/NatronApp_main.cpp @@ -47,6 +47,8 @@ NATRON_NAMESPACE_USING #ifdef Q_OS_WIN // g++ knows nothing about wmain // https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/ +// If it fails to compile it means either UNICODE or _UNICODE is not defined (it should be in global.pri) and +// the project is not linking against -municode extern "C" { int wmain(int argc, wchar_t** argv) #else @@ -94,7 +96,11 @@ int main(int argc, char *argv[]) AppManager manager; // coverity[tainted_data] +#ifdef Q_OS_WIN + if ( !manager.loadW(argc, argv, args) ) { +#else if ( !manager.load(argc, argv, args) ) { +#endif return 1; } else { return 0; @@ -103,8 +109,11 @@ int main(int argc, char *argv[]) GuiApplicationManager manager; // coverity[tainted_data] +#ifdef Q_OS_WIN + return manager.loadW(argc, argv, args); +#else return manager.load(argc, argv, args); - +#endif //exec() is called within the GuiApplicationManager } } // main diff --git a/Engine/AppManager.cpp b/Engine/AppManager.cpp index 0843a1dd0a..939c49501f 100644 --- a/Engine/AppManager.cpp +++ b/Engine/AppManager.cpp @@ -75,6 +75,7 @@ #include "Global/ProcInfo.h" #include "Global/GLIncludes.h" +#include "Global/StrUtils.h" #include "Engine/AppInstance.h" #include "Engine/Backdrop.h" @@ -454,7 +455,7 @@ AppManager::load(int argc, } bool -AppManager::load(int argc, +AppManager::loadW(int argc, wchar_t **argv, const CLArgs& cl) { @@ -2913,11 +2914,11 @@ AppManager::initPython() #ifndef IS_PYTHON_2 #ifdef __NATRON_WIN32__ - static const std::wstring pythonHome( Global::utf8_to_utf16(".") ); + static const std::wstring pythonHome( StrUtils::utf8_to_utf16(".") ); #elif defined(__NATRON_LINUX__) - static const std::wstring pythonHome( Global::utf8_to_utf16("../lib") ); + static const std::wstring pythonHome( StrUtils::utf8_to_utf16("../lib") ); #elif defined(__NATRON_OSX__) - static const std::wstring pythonHome( Global::utf8_to_utf16("../Frameworks/Python.framework/Versions/" NATRON_PY_VERSION_STRING "/lib") ); + static const std::wstring pythonHome( StrUtils::utf8_to_utf16("../Frameworks/Python.framework/Versions/" NATRON_PY_VERSION_STRING "/lib") ); #endif Py_SetPythonHome( const_cast( pythonHome.c_str() ) ); PySys_SetArgv( argc, &_imp->args.front() ); /// relative module import diff --git a/Engine/AppManager.h b/Engine/AppManager.h index a2d0907a43..f0c17d1361 100644 --- a/Engine/AppManager.h +++ b/Engine/AppManager.h @@ -125,7 +125,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON * main process. **/ bool load( int argc, char **argv, const CLArgs& cl); - bool load( int argc, wchar_t **argv, const CLArgs& cl); + bool loadW( int argc, wchar_t **argv, const CLArgs& cl); private: diff --git a/Engine/AppManagerPrivate.cpp b/Engine/AppManagerPrivate.cpp index e85d0f4ec2..c2990ed380 100644 --- a/Engine/AppManagerPrivate.cpp +++ b/Engine/AppManagerPrivate.cpp @@ -54,6 +54,7 @@ GCC_DIAG_ON(unused-parameter) #include "Global/GlobalDefines.h" #include "Global/GLIncludes.h" #include "Global/ProcInfo.h" +#include "Global/StrUtils.h" #include "Engine/FStreamsSupport.h" #include "Engine/CacheSerialization.h" @@ -903,7 +904,7 @@ AppManagerPrivate::handleCommandLineArgsW(int argc, wchar_t** argv) if (argv) { for (int i = 0; i < argc; ++i) { std::wstring ws(argv[i]); - utf8Args.push_back(Global::utf16_to_utf8(ws)); + utf8Args.push_back(StrUtils::utf16_to_utf8(ws)); } } else { // If the user didn't specify launch arguments (e.g unit testing), diff --git a/Engine/CLArgs.cpp b/Engine/CLArgs.cpp index 16bc03e8ba..e2071ce311 100644 --- a/Engine/CLArgs.cpp +++ b/Engine/CLArgs.cpp @@ -37,6 +37,8 @@ #include "Global/GlobalDefines.h" #include "Global/GitVersion.h" #include "Global/QtCompat.h" +#include "Global/StrUtils.h" + #include "Engine/AppManager.h" NATRON_NAMESPACE_ENTER; @@ -1152,7 +1154,7 @@ CLArgs::ensureCommandLineArgsUtf8(int argc, char **argv, std::vectorpush_back(Global::utf16_to_utf8(wide)); + utf8Args->push_back(StrUtils::utf16_to_utf8(wide)); if (argv) { std::cout << "Non UTF-8 arg: " << argv[i] << std::endl; } diff --git a/Engine/Cache.h b/Engine/Cache.h index 9fb1c2c019..0f043ce801 100644 --- a/Engine/Cache.h +++ b/Engine/Cache.h @@ -39,6 +39,7 @@ #include "Global/GlobalDefines.h" #include "Global/MemoryInfo.h" +#include "Global/StrUtils.h" GCC_DIAG_OFF(deprecated) #include @@ -1397,7 +1398,7 @@ class Cache QString getCachePath() const OVERRIDE FINAL WARN_UNUSED_RETURN { QString cacheFolderName( appPTR->getDiskCacheLocation() ); - Global::ensureLastPathSeparator(cacheFolderName); + StrUtils::ensureLastPathSeparator(cacheFolderName); cacheFolderName.append( QString::fromUtf8( cacheName().c_str() ) ); @@ -1407,7 +1408,7 @@ class Cache std::string getRestoreFilePath() const { QString newCachePath( getCachePath() ); - Global::ensureLastPathSeparator(newCachePath); + StrUtils::ensureLastPathSeparator(newCachePath); newCachePath.append( QString::fromUtf8("restoreFile." NATRON_CACHE_FILE_EXT) ); diff --git a/Engine/CacheEntry.h b/Engine/CacheEntry.h index 55b8ef9e6f..d8638687af 100644 --- a/Engine/CacheEntry.h +++ b/Engine/CacheEntry.h @@ -57,6 +57,7 @@ #include // for removePath #include "Engine/EngineFwd.h" #include "Global/GlobalDefines.h" +#include "Global/StrUtils.h" NATRON_NAMESPACE_ENTER; @@ -282,7 +283,7 @@ class CacheAPI { #ifdef _WIN32 WIN32_FIND_DATAW FindFileData; - std::wstring wpath = Global::utf8_to_utf16 (filename); + std::wstring wpath = StrUtils::utf8_to_utf16 (filename); HANDLE handle = FindFirstFileW(wpath.c_str(), &FindFileData); if (handle != INVALID_HANDLE_VALUE) { FindClose(handle); diff --git a/Engine/Engine.pro b/Engine/Engine.pro index 6c2f296fa2..a67b043b7d 100644 --- a/Engine/Engine.pro +++ b/Engine/Engine.pro @@ -200,6 +200,7 @@ SOURCES += \ WriteNode.cpp \ ../Global/glad_source.c \ ../Global/ProcInfo.cpp \ + ../Global/StrUtils.cpp \ ../libs/SequenceParsing/SequenceParsing.cpp \ NatronEngine/natronengine_module_wrapper.cpp \ NatronEngine/natron_namespace_wrapper.cpp \ @@ -443,6 +444,7 @@ HEADERS += \ ../Global/MemoryInfo.h \ ../Global/ProcInfo.h \ ../Global/QtCompat.h \ + ../Global/StrUtils.h \ ../libs/SequenceParsing/SequenceParsing.h \ ../libs/OpenFX/include/ofxCore.h \ ../libs/OpenFX/include/ofxDialog.h \ diff --git a/Engine/FStreamsSupport.cpp b/Engine/FStreamsSupport.cpp index 47a1110b08..282b62a1c2 100644 --- a/Engine/FStreamsSupport.cpp +++ b/Engine/FStreamsSupport.cpp @@ -23,7 +23,7 @@ // ***** END PYTHON BLOCK **** #include "FStreamsSupport.h" - +#include "Global/StrUtils.h" NATRON_NAMESPACE_ENTER; @@ -36,7 +36,7 @@ FStreamsSupport::open (FStreamsSupport::ifstream *stream, #ifdef __NATRON_WIN32__ // Windows std::ifstream accepts non-standard wchar_t* // On MingW, we use our own FStreamsSupport::ifstream - std::wstring wpath = Global::utf8_to_utf16(path); + std::wstring wpath = StrUtils::utf8_to_utf16(path); stream->open (wpath.c_str(), mode); stream->seekg (0, std::ios_base::beg); // force seek, otherwise broken #else @@ -52,7 +52,7 @@ FStreamsSupport::open (FStreamsSupport::ofstream *stream, #ifdef __NATRON_WIN32__ // Windows std::ofstream accepts non-standard wchar_t* // On MingW, we use our own FStreamsSupport::ofstream - std::wstring wpath = Global::utf8_to_utf16(path); + std::wstring wpath = StrUtils::utf8_to_utf16(path); stream->open (wpath.c_str(), mode); #else stream->open (path.c_str(), mode); diff --git a/Engine/LibraryBinary.cpp b/Engine/LibraryBinary.cpp index 13c10e0a54..07e27ef409 100644 --- a/Engine/LibraryBinary.cpp +++ b/Engine/LibraryBinary.cpp @@ -29,6 +29,8 @@ #include #include "Global/GlobalDefines.h" +#include "Global/StrUtils.h" + #ifdef __NATRON_UNIX__ #include #endif @@ -90,7 +92,7 @@ LibraryBinary::loadBinary(const std::string & binaryPath) _binaryPath = binaryPath; #ifdef __NATRON_WIN32__ - std::wstring ws = Global::utf8_to_utf16(binaryPath); + std::wstring ws = StrUtils::utf8_to_utf16(binaryPath); _library = LoadLibraryW( ws.c_str() ); #elif defined(__NATRON_UNIX__) diff --git a/Engine/MemoryFile.cpp b/Engine/MemoryFile.cpp index 5ee878ffbb..cef1dfbe73 100644 --- a/Engine/MemoryFile.cpp +++ b/Engine/MemoryFile.cpp @@ -43,6 +43,7 @@ #include #include "Global/GlobalDefines.h" +#include "Global/StrUtils.h" #define MIN_FILE_SIZE 4096 @@ -230,13 +231,13 @@ MemoryFilePrivate::openInternal(MemoryFile::FileOpenModeEnum open_mode) - R/W ******************************************************** *********************************************************/ - std::wstring wpath = Global::utf8_to_utf16(path); + std::wstring wpath = StrUtils::utf8_to_utf16(path); file_handle = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, windows_open_mode, FILE_ATTRIBUTE_NORMAL, 0); if (file_handle == INVALID_HANDLE_VALUE) { - std::string winError = Global::GetLastErrorAsString(); + std::string winError = StrUtils::GetLastErrorAsString(); std::string str("MemoryFile EXC : Failed to open file "); str.append(path); str.append(winError); diff --git a/Engine/Project.cpp b/Engine/Project.cpp index 9abdac618d..e835019a61 100644 --- a/Engine/Project.cpp +++ b/Engine/Project.cpp @@ -64,6 +64,8 @@ GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON #endif #include // OFX::XML::escape +#include "Global/StrUtils.h" + #include "Engine/AppInstance.h" #include "Engine/AppManager.h" #include "Engine/CreateNodeArgs.h" @@ -191,7 +193,7 @@ Project::loadProject(const QString & path, try { QString realPath = path; - Global::ensureLastPathSeparator(realPath); + StrUtils::ensureLastPathSeparator(realPath); QString realName = name; bool isAutoSave = isUntitledAutosave; if (!getApp()->isBackground() && !isUntitledAutosave) { @@ -518,7 +520,7 @@ Project::saveProjectInternal(const QString & path, ///Use a temporary file to save, so if Natron crashes it doesn't corrupt the user save. QString tmpFilename = StandardPaths::writableLocation(StandardPaths::eStandardLocationTemp); - Global::ensureLastPathSeparator(tmpFilename); + StrUtils::ensureLastPathSeparator(tmpFilename); tmpFilename.append( QString::number( time.toMSecsSinceEpoch() ) ); { @@ -1667,7 +1669,7 @@ Project::getLockFileInfos(const QString& projectPath, qint64* appPID) const { QString realPath = projectPath; - Global::ensureLastPathSeparator(realPath); + StrUtils::ensureLastPathSeparator(realPath); QString lockFilePath = realPath + projectName + QString::fromUtf8(".lock"); QFile f(lockFilePath); @@ -1719,7 +1721,7 @@ Project::removeLastAutosave() */ QString projectPath = QString::fromUtf8( _imp->getProjectPath().c_str() ); QString projectFilename = QString::fromUtf8( _imp->getProjectFilename().c_str() ); - Global::ensureLastPathSeparator(projectPath); + StrUtils::ensureLastPathSeparator(projectPath); QString autoSaveFilePath = projectPath + projectFilename + QString::fromUtf8(".autosave"); if ( QFile::exists(autoSaveFilePath) ) { QFile::remove(autoSaveFilePath); @@ -1759,7 +1761,7 @@ QString Project::autoSavesDir() { QString str = StandardPaths::writableLocation(StandardPaths::eStandardLocationData); - Global::ensureLastPathSeparator(str); + StrUtils::ensureLastPathSeparator(str); str += QString::fromUtf8("Autosaves"); diff --git a/Engine/Settings.cpp b/Engine/Settings.cpp index dba780e997..d088c8a671 100644 --- a/Engine/Settings.cpp +++ b/Engine/Settings.cpp @@ -40,6 +40,7 @@ #endif #include "Global/MemoryInfo.h" +#include "Global/StrUtils.h" #include "Engine/AppManager.h" #include "Engine/AppInstance.h" @@ -89,7 +90,7 @@ static QStringList getDefaultOcioConfigPaths() { QString binaryPath = appPTR->getApplicationBinaryPath(); - Global::ensureLastPathSeparator(binaryPath); + StrUtils::ensureLastPathSeparator(binaryPath); #ifdef __NATRON_LINUX__ QStringList ret; diff --git a/Global/GlobalDefines.h b/Global/GlobalDefines.h index 8f3e2eb34e..99ef6b85be 100644 --- a/Global/GlobalDefines.h +++ b/Global/GlobalDefines.h @@ -158,108 +158,6 @@ typedef OfxRangeD RangeD; #define NATRON_PY_VERSION_STRING PY_VERSION_STRINGIZE(PY_MAJOR_VERSION, PY_MINOR_VERSION) - -namespace Global { -/*Converts a std::string to wide string*/ -inline std::wstring -utf8_to_utf16(const std::string & s) -{ -#ifdef __NATRON_WIN32__ - std::wstring native; - - - native.resize(MultiByteToWideChar (CP_UTF8, 0, s.c_str(), -1, NULL, 0) - 1); - MultiByteToWideChar ( CP_UTF8, 0, s.c_str(), s.size(), &native[0], (int)native.size() ); - - return native; - -#else - std::wstring dest; - size_t max = s.size() * 4; - mbtowc (NULL, NULL, max); /* reset mbtowc */ - - const char* cstr = s.c_str(); - - while (max > 0) { - wchar_t w; - size_t length = mbtowc(&w, cstr, max); - if (length < 1) { - break; - } - dest.push_back(w); - cstr += length; - max -= length; - } - - return dest; -#endif -} // utf8_to_utf16 - -inline std::string -utf16_to_utf8 (const std::wstring& str) -{ -#ifdef __NATRON_WIN32__ - std::string utf8; - - utf8.resize(WideCharToMultiByte (CP_UTF8, 0, str.data(), str.length(), NULL, 0, NULL, NULL)); - WideCharToMultiByte (CP_UTF8, 0, str.data(), str.length(), &utf8[0], (int)utf8.size(), NULL, NULL); - - return utf8; -#else - std::string utf8; - for (std::size_t i = 0; i < str.size(); ++i) { - char c[MB_LEN_MAX]; - int nbBytes = wctomb(c, str[i]); - if (nbBytes > 0) { - for (int j = 0; j < nbBytes; ++j) { - utf8.push_back(c[j]); - } - } else { - break; - } - } - return utf8; -#endif -} // utf16_to_utf8 - -#ifdef __NATRON_WIN32__ - - -//Returns the last Win32 error, in string format. Returns an empty string if there is no error. -inline -std::string -GetLastErrorAsString() -{ - //Get the error message, if any. - DWORD errorMessageID = ::GetLastError(); - - if (errorMessageID == 0) { - return std::string(); //No error message has been recorded - } - LPSTR messageBuffer = 0; - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); - std::string message(messageBuffer, size); - - //Free the buffer. - LocalFree(messageBuffer); - - return message; -} // GetLastErrorAsString - -#endif // __NATRON_WIN32__ - -inline void -ensureLastPathSeparator(QString& path) -{ - static const QChar separator( QLatin1Char('/') ); - - if ( !path.endsWith(separator) ) { - path += separator; - } -} -} // namespace Global - NATRON_NAMESPACE_EXIT; Q_DECLARE_METATYPE(NATRON_NAMESPACE::SequenceTime) diff --git a/Gui/Gui.cpp b/Gui/Gui.cpp index fb3e5ecabd..f4415d59de 100644 --- a/Gui/Gui.cpp +++ b/Gui/Gui.cpp @@ -42,6 +42,8 @@ GCC_DIAG_UNUSED_PRIVATE_FIELD_ON #include "Engine/ViewerInstance.h" #include "Engine/Settings.h" +#include "Global/StrUtils.h" + #include "Gui/ActionShortcuts.h" #include "Gui/CurveEditor.h" #include "Gui/DopeSheetEditor.h" @@ -174,7 +176,7 @@ Gui::reloadProject() } QString filename = proj->getProjectFilename(); QString projectPath = proj->getProjectPath(); - Global::ensureLastPathSeparator(projectPath); + StrUtils::ensureLastPathSeparator(projectPath); projectPath.append(filename); diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp index f61cad3eee..f53b0d2931 100644 --- a/Gui/GuiAppInstance.cpp +++ b/Gui/GuiAppInstance.cpp @@ -49,6 +49,7 @@ #include "Engine/ViewerInstance.h" #include "Global/QtCompat.h" +#include "Global/StrUtils.h" #include "Gui/GuiApplicationManager.h" #include "Gui/Gui.h" @@ -377,7 +378,7 @@ GuiAppInstance::loadInternal(const CLArgs& cl, ///Otherwise just load the project specified. QString name = info.fileName(); QString path = info.path(); - Global::ensureLastPathSeparator(path); + StrUtils::ensureLastPathSeparator(path); appPTR->setLoadingStatus(tr("Loading project: ") + path + name); getProject()->loadProject(path, name); ///remove any file open event that might have occured diff --git a/Gui/SequenceFileDialog.cpp b/Gui/SequenceFileDialog.cpp index b27cbf014c..5683c22950 100644 --- a/Gui/SequenceFileDialog.cpp +++ b/Gui/SequenceFileDialog.cpp @@ -84,6 +84,8 @@ CLANG_DIAG_ON(uninitialized) #include "Global/QtCompat.h" #include "Global/MemoryInfo.h" +#include "Global/StrUtils.h" + #include "Gui/GuiDefines.h" #include "Engine/CreateNodeArgs.h" @@ -1416,7 +1418,7 @@ SequenceFileDialog::createDir() if ( !newFolderString.isEmpty() ) { QString folderName = newFolderString; QString prefix = currentDirectory().absolutePath(); - Global::ensureLastPathSeparator(prefix); + StrUtils::ensureLastPathSeparator(prefix); if ( QFile::exists(prefix + folderName) ) { qlonglong suffix = 2; while ( QFile::exists(prefix + folderName) ) { diff --git a/Renderer/NatronRenderer_main.cpp b/Renderer/NatronRenderer_main.cpp index e2baab5511..9a6fe00d24 100644 --- a/Renderer/NatronRenderer_main.cpp +++ b/Renderer/NatronRenderer_main.cpp @@ -90,7 +90,11 @@ extern "C" { AppManager manager; // coverity[tainted_data] - if ( !manager.load(argc, argv, args) ) { +#ifdef Q_OS_WIN + if ( !manager.loadW(argc, argv, args) ) { +#else + if ( !manager.load(argc, argv, args) ) { +#endif return 1; } else { return 0; diff --git a/Tests/Tests.pro b/Tests/Tests.pro index 2d897a5754..d113ca37e9 100644 --- a/Tests/Tests.pro +++ b/Tests/Tests.pro @@ -49,7 +49,8 @@ SOURCES += \ Lut_Test.cpp \ KnobFile_Test.cpp \ Curve_Test.cpp \ - Tracker_Test.cpp + Tracker_Test.cpp \ + wmain.cpp HEADERS += \ BaseTest.h