From 9ea03f3f6596c9b80e786122e1a3e72ef026aaa1 Mon Sep 17 00:00:00 2001 From: Christian Grasser Date: Tue, 15 May 2018 17:04:33 +0200 Subject: [PATCH] - started to adapt for unicode filenames to be displayed in menu list - removed trailing whitespaces - added workaround to load unicode scripts via the short name - used char(UTF8) to store config file on disk, due to issue with TCHAR, see https://www.codeproject.com/Articles/38242/Reading-UTF-with-C-streams --- PythonScript/src/ConfigFile.cpp | 74 ++++--- PythonScript/src/ConfigFile.h | 20 +- PythonScript/src/MenuManager.cpp | 272 ++++++++++++------------ PythonScript/src/MenuManager.h | 34 +-- PythonScript/src/PythonHandler.cpp | 110 ++++++---- PythonScript/src/PythonHandler.h | 22 +- PythonScript/src/PythonScript.cpp | 143 +++++++------ PythonScript/src/ScintillaWrapper.h | 38 ++-- PythonScript/src/ShortcutDlg.cpp | 98 ++++----- PythonScript/src/WcharMbcsConverter.cpp | 14 +- PythonScript/src/WcharMbcsConverter.h | 3 +- 11 files changed, 430 insertions(+), 398 deletions(-) diff --git a/PythonScript/src/ConfigFile.cpp b/PythonScript/src/ConfigFile.cpp index d42f42de..14266693 100644 --- a/PythonScript/src/ConfigFile.cpp +++ b/PythonScript/src/ConfigFile.cpp @@ -22,7 +22,7 @@ ConfigFile::ConfigFile(const TCHAR *configDir, const TCHAR *pluginDir, HINSTANCE m_configDir(configDir) { m_configFilename.append(_T("\\PythonScriptStartup.cnf")); - + m_machineScriptsDir.append(_T("\\PythonScript\\scripts")); m_userScriptsDir.append(_T("\\PythonScript\\scripts")); @@ -33,61 +33,63 @@ ConfigFile::ConfigFile(const TCHAR *configDir, const TCHAR *pluginDir, HINSTANCE ConfigFile::~ConfigFile() { m_hInst = NULL; - // TODO: Clean up + // TODO: Clean up // DeleteImage - // - + // + } void ConfigFile::readConfig() { - std::basic_ifstream startupFile(m_configFilename.c_str()); - - TCHAR buffer[500]; - - + //just char(UTF8) as TCHAR is not working as expected, because stream is converted to char implicitly + //see also https://www.codeproject.com/Articles/38242/Reading-UTF-with-C-streams + std::ifstream startupFile(m_configFilename.c_str()); + + char buffer[500]; + + HBITMAP hIcon; while (startupFile.good()) { startupFile.getline(buffer, 500); - TCHAR *context; - TCHAR *element = _tcstok_s(buffer, _T("/"), &context); + char *context; + char *element = strtok_s(buffer, "/", &context); if (element) { // Menu item - if (0 == _tcscmp(element, _T("ITEM"))) + if (0 == strcmp(element, "ITEM")) { - element = _tcstok_s(NULL, _T("/"), &context); - m_menuItems.push_back(tstring(element)); - m_menuScripts.push_back(std::string(WcharMbcsConverter::tchar2char(element).get())); + element = strtok_s(NULL, "/", &context); + m_menuItems.push_back(tstring(WcharMbcsConverter::char2tchar(element).get())); + m_menuScripts.push_back(tstring(WcharMbcsConverter::char2tchar(element).get())); } - + // Toolbar item - else if (0 == _tcscmp(element, _T("TOOLBAR"))) + else if (0 == strcmp(element, "TOOLBAR")) { - element = _tcstok_s(NULL, _T("/"), &context); - TCHAR *iconPath = _tcstok_s(NULL, _T("/"), &context); + element = strtok_s(NULL, "/", &context); + char *iconPath = strtok_s(NULL, "/", &context); if (!iconPath || !(*iconPath)) { hIcon = static_cast(LoadImage(m_hInst, MAKEINTRESOURCE(IDB_PYTHON), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE)); iconPath = NULL; } - else + else { - hIcon = static_cast(LoadImage(NULL, iconPath, IMAGE_BITMAP, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADFROMFILE)); + hIcon = static_cast(LoadImage(NULL, WcharMbcsConverter::char2tchar(iconPath).get(), IMAGE_BITMAP, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADFROMFILE)); } - - m_toolbarItems.push_back(std::pair >(tstring(element), std::pair(hIcon, iconPath ? tstring(iconPath) : tstring()))); + + m_toolbarItems.push_back(std::pair >(tstring(WcharMbcsConverter::char2tchar(element).get()), std::pair(hIcon, iconPath ? tstring(WcharMbcsConverter::char2tchar(iconPath).get()) : tstring()))); } - else if (0 == _tcscmp(element, _T("SETTING"))) + else if (0 == strcmp(element, "SETTING")) { - element = _tcstok_s(NULL, _T("/"), &context); - TCHAR *settingValue = _tcstok_s(NULL, _T("/"), &context); - m_settings.insert(std::pair(tstring(element), tstring(settingValue))); + element = strtok_s(NULL, "/", &context); + char *settingValue = strtok_s(NULL, "/", &context); + m_settings.insert(std::pair(tstring(WcharMbcsConverter::char2tchar(element).get()), tstring(WcharMbcsConverter::char2tchar(settingValue).get()))); } } @@ -104,20 +106,22 @@ void ConfigFile::clearItems() void ConfigFile::save() { - std::basic_ofstream startupFile(m_configFilename.c_str(), std::ios_base::out | std::ios_base::trunc); + //just char(UTF8) as TCHAR is not working as expected, because stream is converted to char implicitly + //see also https://www.codeproject.com/Articles/38242/Reading-UTF-with-C-streams + std::ofstream startupFile(m_configFilename.c_str(), std::ios_base::out | std::ios_base::trunc); for(MenuItemsTD::iterator it = m_menuItems.begin(); it != m_menuItems.end(); ++it) { - startupFile << "ITEM/" << (*it) << "\n"; + startupFile << "ITEM/" << WcharMbcsConverter::tchar2char((*it).c_str()).get() << "\n"; } for(ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) { - startupFile << _T("TOOLBAR/") << it->first << _T("/") << it->second.second << _T("\n"); + startupFile << "TOOLBAR/" << WcharMbcsConverter::tchar2char((it->first).c_str()).get() << "/" << WcharMbcsConverter::tchar2char((it->second.second).c_str()).get() << "\n"; } for(SettingsTD::iterator it = m_settings.begin(); it != m_settings.end(); ++it) { - startupFile << _T("SETTING/") << it->first << _T("/") << it->second << _T("\n"); + startupFile << "SETTING/" << WcharMbcsConverter::tchar2char((it->first).c_str()).get() << "/" << WcharMbcsConverter::tchar2char((it->second).c_str()).get() << "\n"; } startupFile.close(); @@ -128,7 +132,7 @@ void ConfigFile::save() void ConfigFile::addMenuItem(const tstring scriptPath) { m_menuItems.push_back(scriptPath); - m_menuScripts.push_back(std::string(WcharMbcsConverter::tchar2char(scriptPath.c_str()).get())); + m_menuScripts.push_back(scriptPath); } void ConfigFile::addToolbarItem(const tstring scriptPath, const tstring iconPath) @@ -147,11 +151,11 @@ const tstring& ConfigFile::getSetting(const TCHAR *settingName) return m_settings[tstring(settingName)]; } -const std::string& ConfigFile::getMenuScript(idx_t index) const -{ +const tstring& ConfigFile::getMenuScript(idx_t index) const +{ if (m_menuScripts.size() > index) { - return m_menuScripts[index]; + return m_menuScripts[index]; } else { diff --git a/PythonScript/src/ConfigFile.h b/PythonScript/src/ConfigFile.h index 729386dc..b453b766 100644 --- a/PythonScript/src/ConfigFile.h +++ b/PythonScript/src/ConfigFile.h @@ -1,4 +1,4 @@ -#ifndef _CONFIGFILE_H +#ifndef _CONFIGFILE_H #define _CONFIGFILE_H class ConfigFile @@ -14,13 +14,13 @@ class ConfigFile static ConfigFile* create(const TCHAR *configDir, const TCHAR *pluginDir, HINSTANCE hInst); static ConfigFile* getInstance() { return s_instance; }; - + // TODO: Need to make these pointers MenuItemsTD getMenuItems() { return m_menuItems; }; ToolbarItemsTD getToolbarItems() { return m_toolbarItems; }; - const std::string& getMenuScript(idx_t index) const; - + const tstring& getMenuScript(idx_t index) const; + void addMenuItem(const tstring scriptPath); void addToolbarItem(const tstring scriptPath, const tstring iconPath); void setSetting(const tstring& settingName, const tstring settingValue); @@ -30,7 +30,7 @@ class ConfigFile void save(); void refresh() { clearItems(); readConfig(); }; - + const tstring& getMachineScriptsDir() { return m_machineScriptsDir; }; const tstring& getUserScriptsDir() { return m_userScriptsDir; }; @@ -53,13 +53,13 @@ class ConfigFile tstring m_configDir; MenuItemsTD m_menuItems; - std::vector< std::string > m_menuScripts; - + std::vector< tstring > m_menuScripts; + // Used in case an invalid script number is requested // so we can return a reference to this puppy instead. - std::string m_emptyString; - - + tstring m_emptyString; + + ToolbarItemsTD m_toolbarItems; std::map< tstring, HICON > m_icons; SettingsTD m_settings; diff --git a/PythonScript/src/MenuManager.cpp b/PythonScript/src/MenuManager.cpp index ae275df3..b04e0e39 100644 --- a/PythonScript/src/MenuManager.cpp +++ b/PythonScript/src/MenuManager.cpp @@ -35,7 +35,7 @@ MenuManager::~MenuManager() try { // Free the Scripts menu HMENUs - for(std::map::iterator iter = m_submenus.begin(); iter != m_submenus.end(); ++iter) + for(std::map::iterator iter = m_submenus.begin(); iter != m_submenus.end(); ++iter) { DestroyMenu((*iter).second); } @@ -89,8 +89,8 @@ MenuManager* MenuManager::getInstance() } MenuManager::MenuManager(HWND hNotepad, HINSTANCE hInst, runScriptFunc runScript) : - m_runScript (runScript), - m_hNotepad (hNotepad), + m_runScript (runScript), + m_hNotepad (hNotepad), m_hInst (hInst), m_dynamicStartIndex(IDX_MAX), m_dynamicCount(0), @@ -160,7 +160,7 @@ MenuManager::MenuManager(HWND hNotepad, HINSTANCE hInst, runScriptFunc runScript m_runScriptFuncs[47] = runScript47; m_runScriptFuncs[48] = runScript48; m_runScriptFuncs[49] = runScript49; - + @@ -296,7 +296,7 @@ void MenuManager::stopScriptEnabled(bool enabled) HMENU pythonPluginMenu = getOurMenu(); if (pythonPluginMenu) { - ::EnableMenuItem(pythonPluginMenu, m_stopScriptIndex, MF_BYPOSITION | (enabled ? MF_ENABLED : MF_GRAYED)); + ::EnableMenuItem(pythonPluginMenu, static_cast(m_stopScriptIndex), MF_BYPOSITION | (enabled ? MF_ENABLED : MF_GRAYED)); } } @@ -310,24 +310,24 @@ bool MenuManager::populateScriptsMenu() } else { - + m_hScriptsMenu = CreateMenu(); - - InsertMenu(m_pythonPluginMenu, m_scriptsMenuIndex, MF_BYPOSITION | MF_POPUP, reinterpret_cast(m_hScriptsMenu), _T("Scripts")); - m_submenus.insert(std::pair("\\", m_hScriptsMenu)); - + + InsertMenu(m_pythonPluginMenu, static_cast(m_scriptsMenuIndex), MF_BYPOSITION | MF_POPUP, reinterpret_cast(m_hScriptsMenu), _T("Scripts")); + m_submenus.insert(std::pair(_T("\\"), m_hScriptsMenu)); + TCHAR pluginDir[MAX_PATH]; TCHAR configDir[MAX_PATH]; ::SendMessage(m_hNotepad, NPPM_GETNPPDIRECTORY, MAX_PATH, reinterpret_cast(pluginDir)); ::SendMessage(m_hNotepad, NPPM_GETPLUGINSCONFIGDIR, MAX_PATH, reinterpret_cast(configDir)); - std::shared_ptr path = WcharMbcsConverter::tchar2char(pluginDir); + std::shared_ptr path = WcharMbcsConverter::tchar2tchar(pluginDir); m_machineScriptsPath = path.get(); - m_machineScriptsPath.append("\\plugins\\PythonScript\\scripts"); - - path = WcharMbcsConverter::tchar2char(configDir); + m_machineScriptsPath.append(_T("\\plugins\\PythonScript\\scripts")); + + path = WcharMbcsConverter::tchar2tchar(configDir); m_userScriptsPath = path.get(); - m_userScriptsPath.append("\\PythonScript\\scripts"); + m_userScriptsPath.append(_T("\\PythonScript\\scripts")); // Fill the actual menu refreshScriptsMenu(); @@ -335,7 +335,7 @@ bool MenuManager::populateScriptsMenu() // Dynamic scripts will start at one lower index now we've inserted the Scripts submenu ++m_dynamicStartIndex; - + } return true; @@ -344,7 +344,7 @@ bool MenuManager::populateScriptsMenu() // Fills the Scripts menu void MenuManager::refreshScriptsMenu() { - + // Remove all the menu items (or submenus) from the scripts menu // Remove, not destroy, as we need to destroy all the sub-submenus too int menuCount = GetMenuItemCount(m_hScriptsMenu); @@ -357,21 +357,21 @@ void MenuManager::refreshScriptsMenu() m_scriptCommands.erase(m_scriptCommands.begin(), m_scriptCommands.end()); m_machineScriptNames.erase(m_machineScriptNames.begin(), m_machineScriptNames.end()); - - + + // Destroy all the menus we've created for(SubmenusTD::iterator it = m_submenus.begin(); it != m_submenus.end(); ++it) { - if (it->first != "\\") + if (it->first != _T("\\")) { // Destroy the menu DestroyMenu(it->second); } } - + m_submenus.erase(m_submenus.begin(), m_submenus.end()); - + assert(m_scriptsMenuManager != NULL); if (m_scriptsMenuManager) { @@ -382,7 +382,7 @@ void MenuManager::refreshScriptsMenu() findScripts(m_hScriptsMenu, m_userScriptsPath.size(), m_userScriptsPath); - + DrawMenuBar(m_hNotepad); } @@ -395,11 +395,11 @@ idx_t MenuManager::getOriginalCommandID(idx_t scriptNumber) { retVal = (idx_t)m_funcItems[m_dynamicStartIndex + scriptNumber - 1]._cmdID; } - + return retVal; } -bool MenuManager::findScripts(HMENU hBaseMenu, size_t basePathLength, std::string& path) +bool MenuManager::findScripts(HMENU hBaseMenu, size_t basePathLength, tstring& path) { assert(m_scriptsMenuManager != NULL); if (!m_scriptsMenuManager) @@ -407,29 +407,29 @@ bool MenuManager::findScripts(HMENU hBaseMenu, size_t basePathLength, std::strin return false; } - WIN32_FIND_DATAA findData; - std::string indexPath; - std::string searchPath(path); - searchPath.append("\\*"); - HANDLE hFound = FindFirstFileA(searchPath.c_str(), &findData); + WIN32_FIND_DATA findData; + tstring indexPath; + tstring searchPath(path); + searchPath.append(_T("\\*")); + HANDLE hFound = FindFirstFile(searchPath.c_str(), &findData); BOOL found = (hFound != INVALID_HANDLE_VALUE) ? TRUE : FALSE; idx_t position = 0; while (found) { if (FILE_ATTRIBUTE_DIRECTORY == (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - && strcmp(findData.cFileName, ".") - && strcmp(findData.cFileName, "..")) + && _tcscmp(findData.cFileName, _T(".")) + && _tcscmp(findData.cFileName, _T(".."))) { searchPath = path; - searchPath.append("\\"); + searchPath.append(_T("\\")); searchPath.append(findData.cFileName); HMENU hSubmenu = CreateMenu(); // Add the submenu handle and path to the map indexPath.assign(searchPath.substr(basePathLength)); - - std::pair< std::map::iterator, bool> result = m_submenus.insert(std::pair(indexPath, hSubmenu)); - + + std::pair< std::map::iterator, bool> result = m_submenus.insert(std::pair(indexPath, hSubmenu)); + // If the path has already been added, use the original HMENU if (!result.second) { @@ -444,9 +444,9 @@ bool MenuManager::findScripts(HMENU hBaseMenu, size_t basePathLength, std::strin // Insert the submenu if it's new if (result.second) { - InsertMenuA(hBaseMenu, position, MF_BYCOMMAND | MF_POPUP, reinterpret_cast(hSubmenu), findData.cFileName); + InsertMenu(hBaseMenu, static_cast(position), MF_BYCOMMAND | MF_POPUP, reinterpret_cast(hSubmenu), findData.cFileName); } - + } else { @@ -455,54 +455,54 @@ bool MenuManager::findScripts(HMENU hBaseMenu, size_t basePathLength, std::strin ++position; } - found = FindNextFileA(hFound, &findData); + found = FindNextFile(hFound, &findData); } FindClose(hFound); searchPath = path; - searchPath.append("\\*.py"); - hFound = FindFirstFileA(searchPath.c_str(), &findData); + searchPath.append(_T("\\*.py")); + hFound = FindFirstFile(searchPath.c_str(), &findData); found = (hFound != INVALID_HANDLE_VALUE) ? TRUE : FALSE; - + bool scriptsFound = (TRUE == found); while(found) { - std::string fullFilename(path); - fullFilename.append("\\"); + tstring fullFilename(path); + fullFilename.append(_T("\\")); fullFilename.append(findData.cFileName); - m_scriptCommands.insert(std::pair(m_scriptsMenuManager->currentID(), fullFilename)); - - - std::string indexedName = fullFilename.substr(basePathLength); - - std::pair::iterator, bool> indexResult = m_machineScriptNames.insert(indexedName); - - char displayName[MAX_PATH]; - strcpy_s(displayName, MAX_PATH, indexedName.c_str()); - char *filename = PathFindFileNameA(displayName); - PathRemoveExtensionA(filename); - + m_scriptCommands.insert(std::pair(m_scriptsMenuManager->currentID(), fullFilename)); + + + tstring indexedName = fullFilename.substr(basePathLength); + + std::pair::iterator, bool> indexResult = m_machineScriptNames.insert(indexedName); + + TCHAR displayName[MAX_PATH]; + _tcscpy_s(displayName, MAX_PATH, indexedName.c_str()); + TCHAR *filename = PathFindFileName(displayName); + PathRemoveExtension(filename); + // If script name is already in the index // then the script name is already shown, so append " (User)" to the display name // as the first one must be a machine script if (!indexResult.second) { - std::string sFilename(filename); - sFilename.append(" (User)"); - InsertMenuA(hBaseMenu, position, MF_BYCOMMAND | MF_STRING | MF_UNCHECKED, m_scriptsMenuManager->currentID(), sFilename.c_str()); + tstring sFilename(filename); + sFilename.append(_T(" (User)")); + InsertMenu(hBaseMenu, static_cast(position), MF_BYCOMMAND | MF_STRING | MF_UNCHECKED, m_scriptsMenuManager->currentID(), sFilename.c_str()); } else { - InsertMenuA(hBaseMenu, position, MF_BYCOMMAND | MF_STRING | MF_UNCHECKED, m_scriptsMenuManager->currentID(), filename); + InsertMenu(hBaseMenu, static_cast(position), MF_BYCOMMAND | MF_STRING | MF_UNCHECKED, m_scriptsMenuManager->currentID(), filename); } - + ++position; ++(*m_scriptsMenuManager); - found = FindNextFileA(hFound, &findData); + found = FindNextFile(hFound, &findData); } FindClose(hFound); @@ -547,9 +547,9 @@ static LRESULT CALLBACK notepadWndProc(HWND hWnd, UINT message, WPARAM wParam, L } } - + return CallWindowProc(MenuManager::s_origWndProc, hWnd, message, wParam, lParam); - + } BOOL MenuManager::processWmCommand(WPARAM wParam, LPARAM /* lParam */) @@ -583,22 +583,22 @@ void MenuManager::subclassNotepadPlusPlus() -FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, runScriptIDFunc runScript, idx_t dynamicStartIndex, idx_t scriptsMenuIndex, idx_t stopScriptIndex, idx_t runPreviousIndex) +FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, runScriptIDFunc runScript, idx_t dynamicStartIndex, idx_t scriptsMenuIndex, idx_t stopScriptIndex, idx_t runPreviousIndex) { s_runScript = runScript; - - + + ConfigFile* configFile = ConfigFile::getInstance(); - + ConfigFile::MenuItemsTD menuItems = configFile->getMenuItems(); - - + + // Remove one from the count of menu items if the list is empty // as we'll only have one separator *nbF = (int)(menuItems.size() + items.size() + (menuItems.empty() ? 0 : 1)); - + m_funcItemCount = (size_t)*nbF; // WARNING: If getFuncItemArray is called twice, we'll leak memory! @@ -606,12 +606,12 @@ FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, runScriptI // Add all the static items passed in idx_t position = 0; - + for(ItemVectorTD::iterator it = items.begin(); it != items.end(); ++it) { if (position == dynamicStartIndex) { - + for (ConfigFile::MenuItemsTD::iterator iter = menuItems.begin(); iter != menuItems.end(); ++iter) { TCHAR filenameCopy[MAX_PATH]; @@ -633,7 +633,7 @@ FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, runScriptI m_funcItems[position]._pFunc = NULL; ++position; } - + } _tcscpy_s(m_funcItems[position]._itemName, 64, it->first.c_str()); @@ -641,14 +641,14 @@ FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, runScriptI m_funcItems[position]._pShKey = NULL; m_funcItems[position]._pFunc = it->second; ++position; - - - + + + } - - + + m_dynamicStartIndex = dynamicStartIndex; m_dynamicCount = menuItems.size(); @@ -685,42 +685,42 @@ void MenuManager::reconfigure() ConfigFile *configFile = ConfigFile::getInstance(); ConfigFile::MenuItemsTD menuItems = configFile->getMenuItems(); - + TCHAR buffer[MAX_PATH]; TCHAR *filename; - + // Remove the current list of script commands m_menuCommands.clear(); HMENU hPluginMenu = getOurMenu(); - + // Ensure we have enough "extra" dynamic IDs m_dynamicMenuManager->reserve(menuItems.size()); - + m_dynamicMenuManager->begin(); // Remove the current "extra" entries - ie. entries after the original list in funcItems for(idx_t menuPosition = m_originalDynamicCount; menuPosition < m_dynamicCount; ++menuPosition) { - ::DeleteMenu(hPluginMenu, m_dynamicStartIndex + m_originalDynamicCount, MF_BYPOSITION); + ::DeleteMenu(hPluginMenu, static_cast(m_dynamicStartIndex + m_originalDynamicCount), MF_BYPOSITION); } - + idx_t position = 0; for(ConfigFile::MenuItemsTD::iterator it = menuItems.begin(); it != menuItems.end(); ++it) { _tcscpy_s(buffer, (*it).c_str()); - + filename = PathFindFileName(buffer); PathRemoveExtension(filename); - // If it's less than the original funcItem count given + // If it's less than the original funcItem count given // back from getFuncItems if (position < m_originalDynamicCount) { ShortcutKey sk; BOOL hasKey = ::SendMessage(m_hNotepad, NPPM_GETSHORTCUTBYCMDID, static_cast(m_funcItems[m_dynamicStartIndex + position - 1]._cmdID), reinterpret_cast(&sk)); - + tstring menuTitle(filename); if (hasKey) @@ -729,46 +729,46 @@ void MenuManager::reconfigure() menuTitle.append(getKeyName(sk)); } - + if (position >= m_dynamicCount) { - // Using m_dynamicMenuManager->currentID() will either give us the next valid + // Using m_dynamicMenuManager->currentID() will either give us the next valid // ID that N++ originally assigned, or one that we've allocated after we ran out. - // That means that shortcuts can be assigned for all scripts in the menu, + // That means that shortcuts can be assigned for all scripts in the menu, // up to the number of menu-scripts that were there when n++ originally started up. - ::InsertMenu(hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION, m_dynamicMenuManager->currentID(), menuTitle.c_str()); + ::InsertMenu(hPluginMenu, static_cast(position + m_dynamicStartIndex), MF_BYPOSITION, m_dynamicMenuManager->currentID(), menuTitle.c_str()); } else { // Update the existing menu - // scripts sub menu didn't exist when dynamicStartIndex was set, hence the -1 - - ::ModifyMenu(hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION, m_dynamicMenuManager->currentID(), menuTitle.c_str()); + // scripts sub menu didn't exist when dynamicStartIndex was set, hence the -1 + + ::ModifyMenu(hPluginMenu, static_cast(position + m_dynamicStartIndex), MF_BYPOSITION, m_dynamicMenuManager->currentID(), menuTitle.c_str()); } - m_menuCommands.insert(std::pair(m_dynamicMenuManager->currentID(), std::string(WcharMbcsConverter::tchar2char(it->c_str()).get()))); + m_menuCommands.insert(std::pair(m_dynamicMenuManager->currentID(), tstring(WcharMbcsConverter::tchar2tchar(it->c_str()).get()))); } else // position >= m_funcItemCount, so just add a new one { - ::InsertMenu(hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION, m_dynamicMenuManager->currentID(), filename); - m_menuCommands.insert(std::pair(m_dynamicMenuManager->currentID(), std::string(WcharMbcsConverter::tchar2char(it->c_str()).get()))); - + ::InsertMenu(hPluginMenu, static_cast(position + m_dynamicStartIndex), MF_BYPOSITION, m_dynamicMenuManager->currentID(), filename); + m_menuCommands.insert(std::pair(m_dynamicMenuManager->currentID(), tstring(WcharMbcsConverter::tchar2tchar(it->c_str()).get()))); + } - + ++(*m_dynamicMenuManager); ++position; } - // Delete any extra menus where we now have less menus than - // a) we had last time, and + // Delete any extra menus where we now have less menus than + // a) we had last time, and // b) we had originally if (menuItems.size() < static_cast(m_dynamicCount) && menuItems.size() < static_cast(m_originalDynamicCount)) { for(idx_t currentIdx = position; currentIdx < m_dynamicCount && currentIdx < m_originalDynamicCount; ++currentIdx) { - ::DeleteMenu(hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION); + ::DeleteMenu(hPluginMenu, static_cast(position + m_dynamicStartIndex), MF_BYPOSITION); } } @@ -791,12 +791,12 @@ void MenuManager::configureToolbarIcons() m_toolbarMenuManager->reserve(toolbarItems.size()); m_toolbarMenuManager->begin(); toolbarIcons icons; - + for(ConfigFile::ToolbarItemsTD::iterator it = toolbarItems.begin(); it != toolbarItems.end(); ++it) { icons.hToolbarBmp = it->second.first; icons.hToolbarIcon = NULL; - m_toolbarCommands.insert(std::pair(m_toolbarMenuManager->currentID(), WcharMbcsConverter::tchar2char(it->first.c_str()).get())); + m_toolbarCommands.insert(std::pair(m_toolbarMenuManager->currentID(), WcharMbcsConverter::tchar2tchar(it->first.c_str()).get())); ::SendMessage(m_hNotepad, NPPM_ADDTOOLBARICON, m_toolbarMenuManager->currentID(), reinterpret_cast(&icons)); ++(*m_toolbarMenuManager); } @@ -831,7 +831,7 @@ idx_t MenuManager::findPluginCommand(const TCHAR *pluginName, const TCHAR *menuO if (0 == retVal) { HMENU hPluginMenu = (HMENU)::SendMessage(m_hNotepad, NPPM_GETMENUHANDLE, 0, 0); - + size_t iMenuItems = (size_t)GetMenuItemCount(hPluginMenu); TCHAR strBuffer[500]; for ( idx_t i = 0; i < iMenuItems; ++i ) @@ -842,14 +842,14 @@ idx_t MenuManager::findPluginCommand(const TCHAR *pluginName, const TCHAR *menuO mii.cch = 500; mii.dwTypeData = strBuffer; - ::GetMenuItemInfo(hPluginMenu, i, TRUE, &mii); + ::GetMenuItemInfo(hPluginMenu, static_cast(i), TRUE, &mii); tstring thisMenuName = formatMenuName(strBuffer); if (NULL != mii.hSubMenu && 0 == _tcsicmp(pluginName, thisMenuName.c_str())) { retVal = findMenuCommand(mii.hSubMenu, pluginName, NULL, menuOption); break; } - + } } @@ -862,10 +862,10 @@ idx_t MenuManager::findPluginCommand(const TCHAR *pluginName, const TCHAR *menuO /* int iMenuItems = GetMenuItemCount(hPluginMenu); TCHAR strBuffer[500]; - + for ( int i = 0; i < iMenuItems; ++i ) { - + ::GetMenuString(hPluginMenu, i, strBuffer, 500, MF_BYPOSITION); if (0 == _tcsicmp(pluginName, strBuffer)) { @@ -874,7 +874,7 @@ idx_t MenuManager::findPluginCommand(const TCHAR *pluginName, const TCHAR *menuO int subMenuItems = ::GetMenuItemCount(hSubMenu); for (int subMenuPos = 0; subMenuPos < subMenuItems; ++subMenuPos) { - + TCHAR *context = NULL;; ::GetMenuString(hSubMenu, subMenuPos, strBuffer, 500, MF_BYPOSITION); TCHAR *name = _tcstok_s(strBuffer, _T("\t"), &context); @@ -889,7 +889,7 @@ idx_t MenuManager::findPluginCommand(const TCHAR *pluginName, const TCHAR *menuO } } - + return 0; */ } @@ -906,10 +906,10 @@ idx_t MenuManager::findMenuCommand(const TCHAR *menuName, const TCHAR *menuOptio return it->second; } } - + HMENU hMenuBar = ::GetMenu(m_hNotepad); idx_t retVal = findMenuCommand(hMenuBar, _T(""), menuName, menuOption); - + if (retVal != 0) { m_menuCommandCache[std::pair(tstring(menuName), tstring(menuOption))] = retVal; @@ -935,7 +935,7 @@ idx_t MenuManager::findMenuCommand(HMENU hParentMenu, const TCHAR *parentMenuNam idx_t retVal = 0; TCHAR strBuffer[500]; - + for ( idx_t i = 0; i < iMenuItems; ++i ) { MENUITEMINFO mii; @@ -944,8 +944,8 @@ idx_t MenuManager::findMenuCommand(HMENU hParentMenu, const TCHAR *parentMenuNam mii.cch = 500; mii.dwTypeData = strBuffer; - ::GetMenuItemInfo(hParentMenu, i, TRUE, &mii); - + ::GetMenuItemInfo(hParentMenu, static_cast(i), TRUE, &mii); + if (NULL != mii.hSubMenu) { tstring thisMenuName = formatMenuName(strBuffer); @@ -953,14 +953,14 @@ idx_t MenuManager::findMenuCommand(HMENU hParentMenu, const TCHAR *parentMenuNam { size_t subMenuItems = (size_t)GetMenuItemCount(mii.hSubMenu); for (idx_t subMenuPos = 0; subMenuPos < subMenuItems; ++subMenuPos) - { + { TCHAR *context = NULL; - ::GetMenuString(mii.hSubMenu, subMenuPos, strBuffer, 500, MF_BYPOSITION); + ::GetMenuString(mii.hSubMenu, static_cast(subMenuPos), strBuffer, 500, MF_BYPOSITION); TCHAR *name = _tcstok_s(strBuffer, _T("\t"), &context); if (name) { tstring nameStr = formatMenuName(name); - + if (0 == _tcsicmp(menuOption, nameStr.c_str())) { return ::GetMenuItemID(mii.hSubMenu, (int)subMenuPos); @@ -976,14 +976,14 @@ idx_t MenuManager::findMenuCommand(HMENU hParentMenu, const TCHAR *parentMenuNam if (name) { tstring nameStr = formatMenuName(name); - + if (0 == _tcsicmp(menuOption, nameStr.c_str())) { return mii.wID; } } } - + if (NULL != mii.hSubMenu) { retVal = findMenuCommand(mii.hSubMenu, strBuffer, menuName, menuOption); @@ -1009,8 +1009,8 @@ void MenuManager::initPreviousScript() { m_runLastScriptShortcut = getKeyName(key); } - - ::EnableMenuItem(getOurMenu(), m_runPreviousIndex, MF_GRAYED | MF_BYPOSITION); + + ::EnableMenuItem(getOurMenu(), static_cast(m_runPreviousIndex), MF_GRAYED | MF_BYPOSITION); } @@ -1032,16 +1032,16 @@ void MenuManager::updateShortcut(UINT cmdID, ShortcutKey* key) } } -void MenuManager::updatePreviousScript(const char *filename) +void MenuManager::updatePreviousScript(const TCHAR *filename) { - char displayName[MAX_PATH]; - strcpy_s(displayName, MAX_PATH, PathFindFileNameA(filename)); - PathRemoveExtensionA(displayName); + TCHAR displayName[MAX_PATH]; + _tcscpy_s(displayName, MAX_PATH, PathFindFileName(filename)); + PathRemoveExtension(displayName); m_previousRunFilename = filename; - + tstring tdisplayName(_T("Run Previous Script (")); - tdisplayName.append(WcharMbcsConverter::char2tchar(displayName).get()); + tdisplayName.append(WcharMbcsConverter::tchar2tchar(displayName).get()); tdisplayName.append(_T(")")); if (!m_runLastScriptShortcut.empty()) @@ -1050,18 +1050,18 @@ void MenuManager::updatePreviousScript(const char *filename) tdisplayName.append(m_runLastScriptShortcut); } - + MENUITEMINFO mi; mi.cbSize = sizeof(MENUITEMINFO); mi.fMask = MIIM_STATE | MIIM_STRING; mi.fState = MFS_ENABLED; - + // string is not altered in SetMenuItemInfo() call, so we're safe to cast this mi.dwTypeData = const_cast(tdisplayName.c_str()); - SetMenuItemInfo(getOurMenu(), m_runPreviousIndex, TRUE, &mi); + SetMenuItemInfo(getOurMenu(), static_cast(m_runPreviousIndex), TRUE, &mi); DrawMenuBar(m_hNotepad); - + } @@ -1085,7 +1085,7 @@ void MenuManager::idsInitialised() } assert(m_dynamicStartIndex != IDX_MAX); - + m_dynamicMenuManager = new DynamicIDManager(m_idAllocator); m_originalDynamicMenuManager = new DynamicIDManager(m_idAllocator); @@ -1105,7 +1105,7 @@ void MenuManager::idsInitialised() } lastID = (idx_t)m_funcItems[i]._cmdID; } - + if (startBlock != (idx_t)m_funcItems[(m_dynamicStartIndex + m_originalDynamicCount) - 1]._cmdID) { m_originalDynamicMenuManager->addBlock(startBlock, (lastID - startBlock) + 1); diff --git a/PythonScript/src/MenuManager.h b/PythonScript/src/MenuManager.h index ad599ae6..e97aa6f9 100644 --- a/PythonScript/src/MenuManager.h +++ b/PythonScript/src/MenuManager.h @@ -26,10 +26,10 @@ class MenuManager typedef std::vector > ItemVectorTD; typedef void (*runScriptIDFunc)(idx_t); - typedef void(*runScriptFunc)(const char *, bool, HANDLE, bool); + typedef void(*runScriptFunc)(const TCHAR *, bool, HANDLE, bool); static MenuManager* create(HWND hNotepad, HINSTANCE hInst, runScriptFunc runScript); - + /** Destroys the static instance. Must be recreated with create() after usage. * Designed for use in the tests */ @@ -64,7 +64,7 @@ class MenuManager idx_t findMenuCommand(HMENU parentMenu, const TCHAR *parentMenuName, const TCHAR *menuName, const TCHAR *menuOption); - void updatePreviousScript(const char *filename); + void updatePreviousScript(const TCHAR *filename); void updateShortcut(UINT cmdID, ShortcutKey* key); void initPreviousScript(); @@ -73,15 +73,15 @@ class MenuManager bool inDynamicRange(idx_t commandID); bool inToolbarRange(idx_t commandID); bool inFixedRange(idx_t commandID); - + BOOL processWmCommand(WPARAM wParam, LPARAM lParam); idx_t getOriginalCommandID(idx_t scriptNumber); static bool s_menuItemClicked; static WNDPROC s_origWndProc; - - + + private: MenuManager(); // default constructor disabled @@ -89,19 +89,19 @@ class MenuManager MenuManager(HWND hNotepad, HINSTANCE hInst, runScriptFunc runScript); HMENU getOurMenu(); - bool findScripts(HMENU hBaseMenu, size_t basePathLength, std::string& path); + bool findScripts(HMENU hBaseMenu, size_t basePathLength, tstring& path); void subclassNotepadPlusPlus(); - + tstring formatMenuName(const TCHAR *name); - + runScriptFunc m_runScript; - typedef std::set MachineScriptNamesTD; - typedef std::map ScriptCommandsTD; - typedef std::map SubmenusTD; + typedef std::set MachineScriptNamesTD; + typedef std::map ScriptCommandsTD; + typedef std::map SubmenusTD; typedef std::map, idx_t> MenuCommandCacheTD; MenuCommandCacheTD m_menuCommandCache; MenuCommandCacheTD m_pluginCommandCache; @@ -130,12 +130,12 @@ class MenuManager idx_t m_originalLastCmdIndex; HMENU m_pythonPluginMenu; HMENU m_hScriptsMenu; - FuncItem* m_funcItems; + FuncItem* m_funcItems; size_t m_funcItemCount; - std::string m_machineScriptsPath; - std::string m_userScriptsPath; + tstring m_machineScriptsPath; + tstring m_userScriptsPath; tstring m_runLastScriptShortcut; - std::string m_previousRunFilename; + tstring m_previousRunFilename; IDAllocator* m_idAllocator; DynamicIDManager* m_dynamicMenuManager; @@ -200,7 +200,7 @@ class MenuManager void (*m_runScriptFuncs[MAX_MENU_SCRIPTS])(void); - + }; #endif // _MENUMANAGER_H diff --git a/PythonScript/src/PythonHandler.cpp b/PythonScript/src/PythonHandler.cpp index 1b20949d..1aa29cb9 100644 --- a/PythonScript/src/PythonHandler.cpp +++ b/PythonScript/src/PythonHandler.cpp @@ -30,7 +30,7 @@ PythonHandler::PythonHandler(TCHAR *pluginsDir, TCHAR *configDir, HINSTANCE hIns { m_machineBaseDir.append(_T("\\PythonScript\\")); m_userBaseDir.append(_T("\\PythonScript\\")); - + mp_notepad = createNotepadPlusWrapper(); mp_scintilla = createScintillaWrapper(); mp_scintilla1.reset(new ScintillaWrapper(scintilla1Handle, m_nppHandle)); @@ -45,11 +45,11 @@ PythonHandler::~PythonHandler(void) { if (consumerBusy()) { - stopScript(); + stopScript(); } // We need to swap back to the main thread - GILLock lock; // It's actually pointless, as we don't need it anymore, + GILLock lock; // It's actually pointless, as we don't need it anymore, // but we'll grab it anyway, just in case we need to wait for something to finish // Can't call finalize with boost::python. @@ -86,11 +86,11 @@ void PythonHandler::initPython() if (Py_IsInitialized()) return; - + preinitScintillaModule(); // Don't import site - if Python 2.7 doesn't find it as part of Py_Initialize, - // it does an exit(1) - AGH! + // it does an exit(1) - AGH! Py_NoSiteFlag = 1; Py_Initialize(); @@ -100,16 +100,16 @@ void PythonHandler::initPython() std::shared_ptr machineBaseDir = WcharMbcsConverter::tchar2char(m_machineBaseDir.c_str()); std::shared_ptr configDir = WcharMbcsConverter::tchar2char(m_userBaseDir.c_str()); - + bool machineIsUnicode = containsExtendedChars(machineBaseDir.get()); bool userIsUnicode = containsExtendedChars(configDir.get()); - - + + std::string smachineDir(machineBaseDir.get()); std::string suserDir(configDir.get()); - - // Init paths + + // Init paths char initBuffer[1024]; char pathCommands[500]; @@ -132,34 +132,34 @@ void PythonHandler::initPython() ); } - _snprintf_s(initBuffer, 1024, 1024, - pathCommands, - smachineDir.c_str(), + _snprintf_s(initBuffer, 1024, 1024, + pathCommands, + smachineDir.c_str(), machineIsUnicode ? ".decode('utf8')" : "", - + suserDir.c_str(), userIsUnicode ? ".decode('utf8')" : "", - - smachineDir.c_str(), + + smachineDir.c_str(), machineIsUnicode ? ".decode('utf8')" : "", - + suserDir.c_str(), userIsUnicode ? ".decode('utf8')" : "", - - smachineDir.c_str(), + + smachineDir.c_str(), machineIsUnicode ? ".decode('utf8')" : "" ); PyRun_SimpleString(initBuffer); - + initSysArgv(); - + // Init Notepad++/Scintilla modules initModules(); mp_mainThreadState = PyEval_SaveThread(); - + } void PythonHandler::initSysArgv() @@ -181,7 +181,7 @@ void PythonHandler::initSysArgv() boost::python::object sysModule(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("sys")))); sysModule.attr("argv") = argvList; - + } void PythonHandler::initModules() @@ -208,28 +208,28 @@ bool PythonHandler::containsExtendedChars(char *s) void PythonHandler::runStartupScripts() { - + // Machine scripts (N++\Plugins\PythonScript\scripts dir) - std::string startupPath(WcharMbcsConverter::tchar2char(m_machineBaseDir.c_str()).get()); - startupPath.append("scripts\\startup.py"); - if (::PathFileExistsA(startupPath.c_str())) + tstring startupPath(m_machineBaseDir); + startupPath.append(_T("scripts\\startup.py")); + if (::PathFileExists(startupPath.c_str())) { - + runScript(startupPath, true); } // User scripts ($CONFIGDIR$\PythonScript\scripts dir) - startupPath = WcharMbcsConverter::tchar2char(m_userBaseDir.c_str()).get(); - startupPath.append("scripts\\startup.py"); - if (::PathFileExistsA(startupPath.c_str())) + startupPath = m_userBaseDir; + startupPath.append(_T("scripts\\startup.py")); + if (::PathFileExists(startupPath.c_str())) { runScript(startupPath, true); } } -bool PythonHandler::runScript(const std::string& scriptFile, - bool synchronous /* = false */, +bool PythonHandler::runScript(const tstring& scriptFile, + bool synchronous /* = false */, bool allowQueuing /* = false */, HANDLE completedEvent /* = NULL */, bool isStatement /* = false */) @@ -237,8 +237,8 @@ bool PythonHandler::runScript(const std::string& scriptFile, return runScript(scriptFile.c_str(), synchronous, allowQueuing, completedEvent, isStatement); } -bool PythonHandler::runScript(const char *filename, - bool synchronous /* = false */, +bool PythonHandler::runScript(const TCHAR *filename, + bool synchronous /* = false */, bool allowQueuing /* = false */, HANDLE completedEvent /* = NULL */, bool isStatement /* = false */) @@ -285,27 +285,49 @@ void PythonHandler::runScriptWorker(const std::shared_ptr& args) { GILLock gilLock; - + if (args->m_isStatement) { - PyRun_SimpleString(args->m_filename.c_str()); + PyRun_SimpleString(WcharMbcsConverter::tchar2char(args->m_filename.c_str()).get()); } else { + std::shared_ptr filenameUFT8 = WcharMbcsConverter::tchar2char(args->m_filename.c_str()); + + if (containsExtendedChars(filenameUFT8.get())) + { + // First obtain the size needed by passing NULL and 0. + const long initLength = GetShortPathName(args->m_filename.c_str(), NULL, 0); + if (initLength > 0) + { + // Dynamically allocate the correct size + // (terminating null char was included in length) + tstring buffer(initLength, 0); + + // Now simply call again using same long path. + + long length = GetShortPathName(args->m_filename.c_str(), const_cast(buffer.c_str()), initLength); + if (length > 0) + { + filenameUFT8 = WcharMbcsConverter::tchar2char(buffer.c_str()); + } + } + } + // We assume PyFile_FromString won't modify the file name passed in param // (that would be quite troubling) and that the missing 'const' is simply an oversight - // from the Python API developers. + // from the Python API developers. // We also assume the second parameter, "r" won't be modified by the function call. //lint -e{1776} Converting a string literal to char * is not const safe (arg. no. 2) - PyObject* pyFile = PyFile_FromString(const_cast(args->m_filename.c_str()), "r"); + PyObject* pyFile = PyFile_FromString(filenameUFT8.get(), "r"); if (pyFile) { - PyRun_SimpleFile(PyFile_AsFile(pyFile), args->m_filename.c_str()); - Py_DECREF(pyFile); + PyRun_SimpleFile(PyFile_AsFile(pyFile), filenameUFT8.get()); + Py_DECREF(pyFile); } } - + if (NULL != args->m_completedEvent) { SetEvent(args->m_completedEvent); @@ -351,9 +373,9 @@ void PythonHandler::stopScript() void PythonHandler::stopScriptWorker(PythonHandler *handler) { GILLock gilLock; - + PyThreadState_SetAsyncExc((long)handler->getExecutingThreadID(), PyExc_KeyboardInterrupt); - + } diff --git a/PythonScript/src/PythonHandler.h b/PythonScript/src/PythonHandler.h index 3b303bc6..91bc31ce 100644 --- a/PythonScript/src/PythonHandler.h +++ b/PythonScript/src/PythonHandler.h @@ -20,13 +20,13 @@ struct RunScriptArgs { public: RunScriptArgs( - const char* filename, + const TCHAR* filename, PyThreadState *threadState, bool synchronous, HANDLE completedEvent, bool isStatement ): - m_filename(filename?filename:""), + m_filename(filename?filename:_T("")), m_threadState(threadState), m_synchronous(synchronous), m_completedEvent(completedEvent), @@ -35,7 +35,7 @@ struct RunScriptArgs } - std::string m_filename; + tstring m_filename; PyThreadState *m_threadState; bool m_synchronous; HANDLE m_completedEvent; @@ -52,9 +52,9 @@ class PythonHandler : public PyProducerConsumer PythonHandler::PythonHandler(TCHAR *pluginsDir, TCHAR *configDir, HINSTANCE hInst, HWND nppHandle, HWND scintilla1Handle, HWND scintilla2Handle, boost::shared_ptr pythonConsole); ~PythonHandler(); - bool runScript(const char *filename, bool synchronous = false, bool allowQueuing = false, HANDLE completedEvent = NULL, bool isStatement = false); - bool runScript(const std::string& filename, bool synchronous = false, bool allowQueuing = false, HANDLE completedEvent = NULL, bool isStatement = false); - + bool runScript(const TCHAR *filename, bool synchronous = false, bool allowQueuing = false, HANDLE completedEvent = NULL, bool isStatement = false); + bool runScript(const tstring& filename, bool synchronous = false, bool allowQueuing = false, HANDLE completedEvent = NULL, bool isStatement = false); + void runScriptWorker(const std::shared_ptr& args); void notify(SCNotification *notifyCode); @@ -66,7 +66,7 @@ class PythonHandler : public PyProducerConsumer PyThreadState* getMainThreadState() { return mp_mainThreadState; }; DWORD getExecutingThreadID() { return getConsumerThreadID(); }; - + protected: void consume(std::shared_ptr args); @@ -79,13 +79,13 @@ class PythonHandler : public PyProducerConsumer HWND m_nppHandle; HWND m_scintilla1Handle; HWND m_scintilla2Handle; - + private: - PythonHandler(); // default constructor disabled - PythonHandler(const PythonHandler&); // copy constructor disabled - PythonHandler& operator = (const PythonHandler&); // Disable assignment operator disabled + PythonHandler() = delete; // default constructor disabled + PythonHandler(const PythonHandler&) = delete; // copy constructor disabled + PythonHandler& operator = (const PythonHandler&) = delete; // Disable assignment operator disabled // Private methods void initModules(); diff --git a/PythonScript/src/PythonScript.cpp b/PythonScript/src/PythonScript.cpp index e2e6025c..bee64062 100644 --- a/PythonScript/src/PythonScript.cpp +++ b/PythonScript/src/PythonScript.cpp @@ -42,7 +42,7 @@ static char g_pluginDir[MAX_PATH]; static char g_configDir[MAX_PATH]; static TCHAR g_tPluginDir[MAX_PATH]; static TCHAR g_tConfigDir[MAX_PATH]; -static std::string g_previousScript; +static tstring g_previousScript; static bool g_infoSet = false; static bool g_initialised = false; @@ -62,8 +62,8 @@ static void showConsole(); static void showShortcutDlg(); static void stopScript(); static void runScript(idx_t number); -static void runScript(const char *script, bool synchronous, HANDLE completedEvent = NULL, bool allowQueuing = false); -static void runStatement(const char *statement, bool synchronous, HANDLE completedEvent = NULL, bool allowQueuing = false); +static void runScript(const TCHAR *script, bool synchronous, HANDLE completedEvent = NULL, bool allowQueuing = false); +static void runStatement(const TCHAR *statement, bool synchronous, HANDLE completedEvent = NULL, bool allowQueuing = false); static void shutdown(void *); static void doHelp(); static void previousScript(); @@ -122,7 +122,7 @@ extern "C" __declspec(dllexport) void setInfo(NppData notepadPlusData) ::SendMessage(nppData._nppHandle, NPPM_GETNPPDIRECTORY, MAX_PATH, reinterpret_cast(g_tPluginDir)); _tcscat_s(g_tPluginDir, MAX_PATH, _T("\\plugins")); strcpy_s(g_pluginDir, MAX_PATH, WcharMbcsConverter::tchar2char(g_tPluginDir).get()); - + ConfigFile::create(g_tConfigDir, g_tPluginDir, reinterpret_cast(g_hModule)); MenuManager::create(nppData._nppHandle, reinterpret_cast(g_hModule), runScript); @@ -160,9 +160,9 @@ extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int *nbF) static FuncItem* getGeneratedFuncItemArray(int *nbF) { - + MenuManager* menuManager = MenuManager::getInstance(); - + MenuManager::ItemVectorTD items; items.reserve(8); idx_t stopScriptIndex; @@ -172,16 +172,16 @@ static FuncItem* getGeneratedFuncItemArray(int *nbF) items.push_back(std::pair(_T("New Script"), newScript)); items.push_back(std::pair(_T("Show Console"), showConsole)); - + items.push_back(std::pair(_T("--"), reinterpret_cast(NULL))); - + items.push_back(std::pair(_T("Stop Script"), stopScript)); stopScriptIndex = items.size() - 1; items.push_back(std::pair(_T("--"), reinterpret_cast(NULL))); - - + + items.push_back(std::pair(_T("Run Previous Script"), previousScript)); runPreviousIndex = items.size() - 1; @@ -198,16 +198,16 @@ static FuncItem* getGeneratedFuncItemArray(int *nbF) items.push_back(std::pair(_T("--"), reinterpret_cast(NULL))); items.push_back(std::pair(_T("Context-Help"), doHelp)); items.push_back(std::pair(_T("About"), doAbout)); - + FuncItem* funcItems = menuManager->getFuncItemArray(nbF, items, runScript, dynamicStartIndex, scriptsMenuIndex, stopScriptIndex, runPreviousIndex); - + return funcItems; } - + static void initialise() { @@ -215,58 +215,58 @@ static void initialise() g_console.reset(new NppPythonScript::PythonConsole(nppData._nppHandle)); pythonHandler = new NppPythonScript::PythonHandler(g_tPluginDir, g_tConfigDir, (HINSTANCE)g_hModule, nppData._nppHandle, nppData._scintillaMainHandle, nppData._scintillaSecondHandle, g_console); - + aboutDlg.initDialog((HINSTANCE)g_hModule, nppData); - + g_shortcutDlg = new ShortcutDlg((HINSTANCE)g_hModule, nppData, _T("\\PythonScript\\scripts")); g_console->init((HINSTANCE)g_hModule, nppData); - - + + MenuManager* menuManager = MenuManager::getInstance(); //menuManager->idsInitialised(); menuManager->populateScriptsMenu(); menuManager->stopScriptEnabled(false); menuManager->initPreviousScript(); - - + + } static void initialisePython() { g_initialised = true; DWORD startTicks = GetTickCount(); - + DEBUG_TRACE_S(("starting python at %ld", startTicks)); - + pythonHandler->initPython(); - + g_console->initPython(pythonHandler); - + pythonHandler->runStartupScripts(); - + DWORD endTicks = GetTickCount(); g_console->message("Python "); g_console->message(Py_GetVersion()); - + char result[200]; - + sprintf_s(result, 200, "\nInitialisation took %ldms\nReady.\n", endTicks-startTicks); g_console->message(result); - + } static void registerToolbarIcons() { #ifdef DEBUG_STARTUP - MessageBox(NULL, _T("Register toolbar icons"), _T("Python Script"), 0); + MessageBox(NULL, _T("Register toolbar icons"), _T("Python Script"), 0); #endif MenuManager* menuManager = MenuManager::getInstance(); - menuManager->idsInitialised(); + menuManager->idsInitialised(); menuManager->configureToolbarIcons(); } @@ -276,9 +276,9 @@ extern "C" __declspec(dllexport) void beNotified(SCNotification *notifyCode) * 1. Notifications that must be run BEFORE any registered Python callbacks, and * 2. Notifications that must be run AFTER any registered Python callbacks */ - - // Note: The callback isn't actually complete until after this method returns, and - // scintilla has finished through it's iterator of watchers. However, under "normal" circumstances, this stops a synchronous + + // Note: The callback isn't actually complete until after this method returns, and + // scintilla has finished through it's iterator of watchers. However, under "normal" circumstances, this stops a synchronous // callback from calling a function that changes the watchers on the internal Scintilla document. // Async callbacks aren't an issue, as they may call into scintilla whilst a callback is ongoing, but as scintilla is running // on a single thread, it waits until the callback code is complete for continuing (ie. processing the next message in the message loop). @@ -288,7 +288,7 @@ extern "C" __declspec(dllexport) void beNotified(SCNotification *notifyCode) { callbackCount = NppPythonScript::ScintillaCallbackCounter::inCallback(); } - + switch(notifyCode->nmhdr.code) { @@ -338,7 +338,7 @@ extern "C" __declspec(dllexport) void beNotified(SCNotification *notifyCode) break; } - + // Notify the scripts if (pythonHandler) pythonHandler->notify(notifyCode); @@ -351,12 +351,12 @@ extern "C" __declspec(dllexport) void beNotified(SCNotification *notifyCode) DWORD shutdownThreadID; CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)shutdown, NULL, NULL, &shutdownThreadID); } - break; + break; default: // Ignore all other messages break; } - + } @@ -381,7 +381,7 @@ extern "C" __declspec(dllexport) LRESULT messageProc(UINT message, WPARAM wParam return TRUE; } - std::shared_ptr script = WcharMbcsConverter::tchar2char(pse->script); + std::shared_ptr script = WcharMbcsConverter::tchar2tchar(pse->script); bool synchronous = (pse->flags & PYSCRF_SYNC) == PYSCRF_SYNC; @@ -426,7 +426,7 @@ extern "C" __declspec(dllexport) LRESULT messageProc(UINT message, WPARAM wParam default: // Other messages can just be ignored break; - + } return TRUE; } @@ -480,8 +480,8 @@ static void runScript(idx_t number) /* If the shortcut for the given script number does not have a control in it, * (or no shortcut key is assigned), then we can pretend the user clicked the menu option. * runScript() will then check if Ctrl is held down, if it is, it will edit the script. - * Obviously if this menu item's key DOES have Ctrl in it, (and we're on N++ 5.8 or upwards) - * then we can't tell the difference (as we haven't subclassed N++). + * Obviously if this menu item's key DOES have Ctrl in it, (and we're on N++ 5.8 or upwards) + * then we can't tell the difference (as we haven't subclassed N++). * If that's the case, then ctrl-click won't work. That's just tough, I think. */ if (!shortcutKeyHasCtrl(number)) @@ -495,7 +495,7 @@ static void runScript(idx_t number) -static void runStatement(const char *statement, bool synchronous, HANDLE completedEvent /* = NULL */, bool allowQueuing /* = false */) +static void runStatement(const TCHAR *statement, bool synchronous, HANDLE completedEvent /* = NULL */, bool allowQueuing /* = false */) { CHECK_INITIALISED(); MenuManager::getInstance()->stopScriptEnabled(true); @@ -506,7 +506,7 @@ static void runStatement(const char *statement, bool synchronous, HANDLE complet } -static void updatePreviousScript(const char *filename) +static void updatePreviousScript(const TCHAR *filename) { if (g_previousScript == filename) return; @@ -517,13 +517,13 @@ static void updatePreviousScript(const char *filename) menuManager->updatePreviousScript(filename); } -static void runScript(const char *filename, bool synchronous, HANDLE completedEvent /* = NULL */, bool allowQueuing /* = false */) +static void runScript(const TCHAR *filename, bool synchronous, HANDLE completedEvent /* = NULL */, bool allowQueuing /* = false */) { - + BYTE keyState[256]; - + // If the filename is empty, then just ignore it - if (!filename || (*filename) == '\0') + if (!filename || (*filename) == _T('\0')) { // Reset the menuItemClicked, just in case (highly unlikely, but still) MenuManager::s_menuItemClicked = false; @@ -531,24 +531,24 @@ static void runScript(const char *filename, bool synchronous, HANDLE completedEv } ::GetKeyboardState(keyState); - + // If a menu item was clicked (or assumed to be, see runScript(int)) // and either control held down, and shift + alt are not, then edit the file - if (MenuManager::s_menuItemClicked + if (MenuManager::s_menuItemClicked && (keyState[VK_CONTROL] & 0x80) && ((keyState[VK_SHIFT] & 0x80) == 0) && ((keyState[VK_MENU] & 0x80) == 0)) { - if (!SendMessage(nppData._nppHandle, NPPM_SWITCHTOFILE, 0, reinterpret_cast(WcharMbcsConverter::char2tchar(filename).get()))) + if (!SendMessage(nppData._nppHandle, NPPM_SWITCHTOFILE, 0, reinterpret_cast(WcharMbcsConverter::tchar2tchar(filename).get()))) { - SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, reinterpret_cast(WcharMbcsConverter::char2tchar(filename).get())); + SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, reinterpret_cast(WcharMbcsConverter::tchar2tchar(filename).get())); } } else { CHECK_INITIALISED(); MenuManager::getInstance()->stopScriptEnabled(true); - + // TODO: Really need to not change this if it's a MSGTOPLUGIN run updatePreviousScript(filename); @@ -602,9 +602,9 @@ static void ensurePathExists(const tstring& path) created = TRUE; } - } while (createPath.find(_T('\\')) != tstring::npos + } while (createPath.find(_T('\\')) != tstring::npos && !created); - + if (created) { for(std::list::reverse_iterator iter = pathsToCreate.rbegin(); iter != pathsToCreate.rend(); iter++) @@ -621,39 +621,38 @@ static void ensurePathExists(const tstring& path) static void newScript() { - - OPENFILENAMEA ofn; - memset(&ofn, 0, sizeof(OPENFILENAMEA)); - ofn.lStructSize = sizeof(OPENFILENAMEA); + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(OPENFILENAME)); + + ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nppData._nppHandle; ensurePathExists(ConfigFile::getInstance()->getUserScriptsDir()); - std::shared_ptr userScriptsDir = WcharMbcsConverter::tchar2char(ConfigFile::getInstance()->getUserScriptsDir().c_str()); - ofn.lpstrInitialDir = userScriptsDir.get(); + ofn.lpstrInitialDir = ConfigFile::getInstance()->getUserScriptsDir().c_str(); //ofn.lpstrFileTitle = "Choose filename for new script"; - ofn.lpstrFile = new char[MAX_PATH]; - ofn.lpstrFile[0] = '\0'; + ofn.lpstrFile = new TCHAR[MAX_PATH]; + ofn.lpstrFile[0] = _T('\0'); ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "py"; + ofn.lpstrDefExt = _T("py"); //lint -e840 Use of nul character in a string literal // This is how it's meant to be used. - ofn.lpstrFilter = "Python Source Files (*.py)\0*.py\0All Files (*.*)\0*.*\0"; + ofn.lpstrFilter = _T("Python Source Files (*.py)\0*.py\0All Files (*.*)\0*.*\0"); //lint +e840 ofn.nFilterIndex = 1; ofn.Flags = OFN_OVERWRITEPROMPT; - - if (GetSaveFileNameA(&ofn)) + + if (GetSaveFileName(&ofn)) { - - HANDLE hFile = CreateFileA(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + + HANDLE hFile = CreateFile(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); CloseHandle(hFile); - SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, reinterpret_cast(WcharMbcsConverter::char2tchar(ofn.lpstrFile).get())); + SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, reinterpret_cast(ofn.lpstrFile)); intptr_t bufferID = SendMessage(nppData._nppHandle, NPPM_GETCURRENTBUFFERID, 0, 0); SendMessage(nppData._nppHandle, NPPM_SETBUFFERLANGTYPE, L_PYTHON, bufferID); } - + delete [] ofn.lpstrFile; @@ -693,16 +692,16 @@ static void shutdown(void* /* dummy */) } MenuManager::deleteInstance(); - + } static void doHelp() { int which; - + SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, reinterpret_cast(&which)); - + HelpController help(nppData._nppHandle, which ? nppData._scintillaSecondHandle : nppData._scintillaMainHandle); help.callHelp(); } diff --git a/PythonScript/src/ScintillaWrapper.h b/PythonScript/src/ScintillaWrapper.h index 325133bf..d37293ed 100644 --- a/PythonScript/src/ScintillaWrapper.h +++ b/PythonScript/src/ScintillaWrapper.h @@ -68,7 +68,7 @@ class ScintillaWrapper : public PyProducerConsumer void clearCallbackEvents(boost::python::list events); void clearCallback(PyObject* callback, boost::python::list events); - /* Helper functions + /* Helper functions * These functions are designed to make life easier for scripting, * but don't perform any "magic" */ @@ -79,8 +79,8 @@ class ScintillaWrapper : public PyProducerConsumer boost::python::tuple getUserLineSelection(); boost::python::tuple getUserCharSelection(); void setTarget(int start, int end); - - /** Returns the flag to be combined with the re flag constants, in order to set the + + /** Returns the flag to be combined with the re flag constants, in order to set the * re anchors to treat the document as a whole, a not per line. ie. ^ matches the start of the document, * and $ matches the end. Default is ^ matches start of line, $ the end. */ @@ -98,7 +98,7 @@ class ScintillaWrapper : public PyProducerConsumer void replaceRegexFlagsStartEndMaxCount(boost::python::object searchStr, boost::python::object replaceStr, int flags, int start, int end, int maxCount); void replaceImpl(boost::python::object searchStr, boost::python::object replaceStr, int count, python_re_flags flags, int startPosition, int endPosition); - + void searchPlain(boost::python::object searchStr, boost::python::object matchFunction); void searchPlainFlags(boost::python::object searchStr, boost::python::object matchFunction, int flags); void searchPlainFlagsStart(boost::python::object searchStr, boost::python::object matchFunction, int flags, int startPosition); @@ -127,7 +127,7 @@ class ScintillaWrapper : public PyProducerConsumer void pyreplaceNoEnd(boost::python::object searchExp, boost::python::object replaceStr, boost::python::object count, boost::python::object flags, boost::python::object startLine) { pyreplace(searchExp, replaceStr, count, flags, startLine, boost::python::object()); }; - + void pymlreplace(boost::python::object searchExp, boost::python::object replaceStr, boost::python::object count, boost::python::object flags, boost::python::object startPosition, boost::python::object endPosition); void pymlreplaceNoFlagsNoCount(boost::python::object searchExp, boost::python::object replaceStr) { pymlreplace(searchExp, replaceStr, boost::python::object(0), boost::python::object(0), boost::python::object(), boost::python::object()); }; @@ -160,20 +160,20 @@ class ScintillaWrapper : public PyProducerConsumer { return getWord(position, boost::python::object(true)); }; boost::python::str getCurrentWord() { return getWord(boost::python::object(), boost::python::object(true)); }; - + // This "normal" Scintilla function has been implemented manually, as it returns a pointer, which we can convert to a string boost::python::str GetCharacterPointer(); // This "normal" Scintilla function has been implemented manually, as it returns a pointer, which we can convert to a string boost::python::str GetRangePointer(int position, int length); - /** This helper function gets a std::string from the given object. + /** This helper function gets a std::string from the given object. * If the object is a unicode string, it converts the string to UTF-8. * If it's an object, it calls the __str__ method to convert the object to a string */ std::string getStringFromObject(boost::python::object o); - /** Flash the editor by reversing foreground and background colours + /** Flash the editor by reversing foreground and background colours */ void flash() { flashMilliseconds(50); } void flashMilliseconds(int milliseconds); @@ -3023,28 +3023,28 @@ class ScintillaWrapper : public PyProducerConsumer GILRelease release; return SendMessage(m_handle, message, wParam, lParam); } - - + + protected: void consume(std::shared_ptr args); - + private: - ScintillaWrapper(); // default constructor disabled - ScintillaWrapper(const ScintillaWrapper& copy); // copy constructor disabled - ScintillaWrapper& operator = (const ScintillaWrapper& rhs); // assignment operator disabled + ScintillaWrapper() = delete; // default constructor disabled + ScintillaWrapper(const ScintillaWrapper& copy) = delete; // copy constructor disabled + ScintillaWrapper& operator = (const ScintillaWrapper& rhs) = delete; // assignment operator disabled // Active Scintilla handle HWND m_handle; // Notepad++ handle (used for replace) HWND m_hNotepad; - + // Callbacks HANDLE m_callbackMutex; callbackT m_callbacks; - + bool m_notificationsEnabled; - + static void runCallbacks(CallbackExecArgs *args); void runCallbacks(std::shared_ptr args); @@ -3055,8 +3055,8 @@ class ScintillaWrapper : public PyProducerConsumer boost::python::object m_pythonMatchHandler; const char *getCurrentAnsiCodePageName(); - - // If the current thread is the main UI thread and a callback is currently in progress, + + // If the current thread is the main UI thread and a callback is currently in progress, // then this call throws an exception void notAllowedInCallback(const char *message); diff --git a/PythonScript/src/ShortcutDlg.cpp b/PythonScript/src/ShortcutDlg.cpp index 6f48fdb6..0784feb1 100644 --- a/PythonScript/src/ShortcutDlg.cpp +++ b/PythonScript/src/ShortcutDlg.cpp @@ -27,12 +27,12 @@ ShortcutDlg::ShortcutDlg(HINSTANCE hInst, NppData& nppData, const TCHAR *scriptD Window::init(hInst, nppData._nppHandle); TCHAR temp[MAX_PATH]; ::SendMessage(nppData._nppHandle, NPPM_GETPLUGINSCONFIGDIR, MAX_PATH, reinterpret_cast(temp)); - + m_userScriptDir = temp; m_userScriptDir.append(scriptDirAppend); ::SendMessage(nppData._nppHandle, NPPM_GETNPPDIRECTORY, MAX_PATH, reinterpret_cast(temp)); - + m_machineScriptDir = temp; m_machineScriptDir.append(_T("\\plugins")); m_machineScriptDir.append(scriptDirAppend); @@ -141,7 +141,7 @@ INT_PTR CALLBACK ShortcutDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP // a non-NULL lParam means it's a python file (with a full path) if (lptvdi->item.lParam) imageIndex = m_iconPython; - else + else imageIndex = m_iconFolderClosed; } @@ -181,12 +181,12 @@ INT_PTR CALLBACK ShortcutDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP } // end switch (hdr->code) } // end case IDC_FILETREE - break; + break; default: // Other windows we can ignore break; - } // end switch hdr->idFrom + } // end switch hdr->idFrom } // end case WM_NOTIFY break; @@ -209,34 +209,34 @@ void ShortcutDlg::onInitDialog() m_hListToolbarItems = ::GetDlgItem(_hSelf, IDC_TOOLBARITEMLIST2); m_hComboInitialisation = ::GetDlgItem(_hSelf, IDC_COMBOINITIALISATION); InitCommonControls(); - HICON hIcon; // handle to icon - - // Create a masked image list large enough to hold the icons. - m_hIcons = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 3, 0); - - // Load the icon resources, and add the icons to the image list. - hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDERCLOSED)); - m_iconFolderClosed = ImageList_AddIcon(m_hIcons, hIcon); - - hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDEROPEN)); - m_iconFolderOpen = ImageList_AddIcon(m_hIcons, hIcon); - - hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_PYTHON)); - m_iconPython = ImageList_AddIcon(m_hIcons, hIcon); + HICON hIcon; // handle to icon + + // Create a masked image list large enough to hold the icons. + m_hIcons = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 3, 0); + + // Load the icon resources, and add the icons to the image list. + hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDERCLOSED)); + m_iconFolderClosed = ImageList_AddIcon(m_hIcons, hIcon); + + hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDEROPEN)); + m_iconFolderOpen = ImageList_AddIcon(m_hIcons, hIcon); + + hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_PYTHON)); + m_iconPython = ImageList_AddIcon(m_hIcons, hIcon); ::SendMessage(m_hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, reinterpret_cast(m_hIcons)); ::SendMessage(m_hTree, TVM_SETIMAGELIST, TVSIL_STATE, reinterpret_cast(m_hIcons)); m_hImageList = ImageList_Create(16, 16, ILC_MASK |ILC_COLOR32, 5, 1); HBITMAP hPython = static_cast(LoadImage(_hInst, MAKEINTRESOURCE(IDB_PYTHON), IMAGE_BITMAP, 0, 0, LR_COLOR | LR_LOADMAP3DCOLORS | LR_DEFAULTSIZE)); m_hDefaultImageIndex = ImageList_Add(m_hImageList, hPython, NULL); - ListView_SetImageList(m_hListToolbarItems, m_hImageList, LVSIL_SMALL); + ListView_SetImageList(m_hListToolbarItems, m_hImageList, LVSIL_SMALL); LVCOLUMN lvCol; lvCol.cchTextMax = 10; lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; lvCol.iSubItem = 0; lvCol.pszText = _T("Script"); lvCol.fmt = LVCFMT_LEFT; - + RECT rect; ::GetClientRect(m_hListToolbarItems, &rect); m_toolbarColumnWidth = (size_t)((rect.right - rect.left) - 18); @@ -289,19 +289,19 @@ void ShortcutDlg::populateScripts(tstring dir, HTREEITEM parent /* = TVI_ROOT */ while (found) { if (FILE_ATTRIBUTE_DIRECTORY == (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - && _tcscmp(findData.cFileName, _T(".")) + && _tcscmp(findData.cFileName, _T(".")) && _tcscmp(findData.cFileName, _T(".."))) { searchPath = dir; searchPath.append(_T("\\")); searchPath.append(findData.cFileName); - - + + lastItem = addTreeItem(parent, lastItem, NULL, findData.cFileName, true); - - + + populateScripts(searchPath, lastItem); - + } found = FindNextFile(hFound, &findData); @@ -314,29 +314,29 @@ void ShortcutDlg::populateScripts(tstring dir, HTREEITEM parent /* = TVI_ROOT */ searchPath.append(_T("\\*.py")); hFound = FindFirstFile(searchPath.c_str(), &findData); found = (hFound != INVALID_HANDLE_VALUE) ? TRUE : FALSE; - - + + while(found) { tstring fullFilename(dir); fullFilename.append(_T("\\")); fullFilename.append(findData.cFileName); - + size_t length = fullFilename.size() + 1; std::shared_ptr item(new TCHAR[length]); - + _tcscpy_s(item.get(), length, fullFilename.c_str()); m_itemList.push_back(item); lastItem = addTreeItem(parent, lastItem, item.get(), findData.cFileName, false); - - + + found = FindNextFile(hFound, &findData); } FindClose(hFound); - + } @@ -346,7 +346,7 @@ void ShortcutDlg::populateScripts(tstring dir, HTREEITEM parent /* = TVI_ROOT */ HTREEITEM ShortcutDlg::addTreeItem(HTREEITEM parent, HTREEITEM /* lastItem */, TCHAR *fullPath, TCHAR *text, bool isDirectory) { TV_INSERTSTRUCT tvInsert; - tvInsert.hParent = parent; + tvInsert.hParent = parent; tvInsert.hInsertAfter = TVI_SORT; tvInsert.item.mask = TVIF_TEXT | TVIF_PARAM |TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvInsert.item.lParam = reinterpret_cast(fullPath); @@ -387,10 +387,10 @@ void ShortcutDlg::addMenuItem(const TCHAR *item) lvItem.iSubItem = 0; lvItem.state = 0; lvItem.stateMask = 0; - + TCHAR path[MAX_PATH]; _tcscpy_s(path, MAX_PATH, item); - ::PathCompactPath(NULL, path, m_menuItemColumnWidth); + ::PathCompactPath(NULL, path, static_cast(m_menuItemColumnWidth)); lvItem.pszText = path; lvItem.cchTextMax = (int)_tcslen(path); @@ -400,7 +400,7 @@ void ShortcutDlg::addMenuItem(const TCHAR *item) void ShortcutDlg::removeMenuItem() { int index = ListView_GetNextItem(m_hListMenuItems, -1, LVIS_SELECTED); - + if (index != -1) { ListView_DeleteItem(m_hListMenuItems, index); @@ -437,10 +437,10 @@ void ShortcutDlg::addToolbarItem(const TCHAR *item, HBITMAP hBitmap) lvItem.state = 0; lvItem.stateMask = 0; lvItem.iImage = imageIndex; - + TCHAR path[MAX_PATH]; _tcscpy_s(path, MAX_PATH, item); - ::PathCompactPath(NULL, path, m_toolbarColumnWidth); + ::PathCompactPath(NULL, path, static_cast(m_toolbarColumnWidth)); lvItem.pszText = path; lvItem.cchTextMax = (int)_tcslen(path); @@ -458,9 +458,9 @@ void ShortcutDlg::addToolbarItem(const TCHAR *item, HBITMAP hBitmap) void ShortcutDlg::removeToolbarItem() { - + int index = ListView_GetNextItem(m_hListToolbarItems, -1, LVIS_SELECTED); - + if (index != -1) { ListView_DeleteItem(m_hListToolbarItems, index); @@ -515,21 +515,21 @@ void ShortcutDlg::saveConfig() configFile->clearItems(); for (ConfigFile::MenuItemsTD::iterator it = m_menuItems.begin(); it != m_menuItems.end(); ++it) - { + { configFile->addMenuItem(*it); } - + for (ConfigFile::ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) - { + { configFile->addToolbarItem(it->first, it->second.second); } TCHAR startupBuffer[50]; ComboBox_GetText(m_hComboInitialisation, startupBuffer, 50); configFile->setSetting(_T("STARTUP"), startupBuffer); - + if (BST_CHECKED == IsDlgButtonChecked(_hSelf, IDC_CHECKPREFERINSTALLEDPYTHON)) { configFile->setSetting(_T("PREFERINSTALLEDPYTHON"), _T("1")); } else { @@ -543,7 +543,7 @@ void ShortcutDlg::saveConfig() void ShortcutDlg::toolbarSetIcon() { int index = ListView_GetNextItem(m_hListToolbarItems, -1, LVIS_SELECTED); - + if (index != -1) { OPENFILENAME ofn; @@ -551,7 +551,7 @@ void ShortcutDlg::toolbarSetIcon() ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = _hSelf; - + tstring configDir(ConfigFile::getInstance()->getConfigDir()); configDir.append(_T("\\PythonScript\\icons")); ofn.lpstrInitialDir = configDir.c_str(); @@ -566,7 +566,7 @@ void ShortcutDlg::toolbarSetIcon() ofn.nFilterIndex = 1; ofn.Flags = OFN_FILEMUSTEXIST; - + if (GetOpenFileName(&ofn)) { diff --git a/PythonScript/src/WcharMbcsConverter.cpp b/PythonScript/src/WcharMbcsConverter.cpp index 7adc5c12..58a0b3b4 100644 --- a/PythonScript/src/WcharMbcsConverter.cpp +++ b/PythonScript/src/WcharMbcsConverter.cpp @@ -24,12 +24,12 @@ Modified for inclusion in VS2010 project "Python Script" std::shared_ptr WcharMbcsConverter::char2wchar(const char* mbStr) { - + std::shared_ptr wideCharStr; size_t len = (size_t)MultiByteToWideChar(CP_UTF8, 0, mbStr, -1, NULL, 0); - - + + if (len > 0) { wideCharStr.reset(new wchar_t[len]); @@ -92,4 +92,10 @@ std::shared_ptr WcharMbcsConverter::tchar2char(const TCHAR* tStr) #endif } - +std::shared_ptr WcharMbcsConverter::tchar2tchar(const TCHAR* tStr) +{ + size_t len = _tcslen(tStr) + 1; + std::shared_ptr result(new TCHAR[len]); + _tcscpy_s(result.get(), len, tStr); + return result; +} diff --git a/PythonScript/src/WcharMbcsConverter.h b/PythonScript/src/WcharMbcsConverter.h index 401f7f8f..74d572b6 100644 --- a/PythonScript/src/WcharMbcsConverter.h +++ b/PythonScript/src/WcharMbcsConverter.h @@ -24,13 +24,14 @@ Modified for inclusion in VS2010 project "Python Script" class WcharMbcsConverter { public: - + static std::shared_ptr char2wchar(const char* mbStr); static std::shared_ptr wchar2char(const wchar_t* wcStr); static std::shared_ptr char2tchar(const char* mbStr); static std::shared_ptr tchar2char(const TCHAR* tStr); + static std::shared_ptr tchar2tchar(const TCHAR * tStr); };