From 12760a8a9c676dee69a59310977cb9a76da9868e Mon Sep 17 00:00:00 2001 From: CFrank Date: Tue, 31 Jul 2018 22:06:06 +0200 Subject: [PATCH 01/12] store/read user scripts relative to plugins config directory Fixes #15 --- PythonScript/src/ConfigFile.cpp | 65 ++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/PythonScript/src/ConfigFile.cpp b/PythonScript/src/ConfigFile.cpp index 053a7360..a600a382 100644 --- a/PythonScript/src/ConfigFile.cpp +++ b/PythonScript/src/ConfigFile.cpp @@ -62,24 +62,42 @@ void ConfigFile::readConfig() while (startupFile.good()) { + tstring scriptFullPath = _T(""); startupFile.getline(buffer, 500); char *context; char *element = strtok_s(buffer, "/", &context); if (element) { - // Menu item if (0 == strcmp(element, "ITEM")) { element = strtok_s(NULL, "/", &context); - m_menuItems.push_back(tstring(WcharMbcsConverter::char2tchar(element).get())); - m_menuScripts.push_back(tstring(WcharMbcsConverter::char2tchar(element).get())); + if ((element[1] == ':') || (element[1] == '\\')) + { + scriptFullPath = WcharMbcsConverter::char2tchar(element).get(); + } + else + { + scriptFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(element).get())); + } + m_menuItems.push_back(scriptFullPath); + m_menuScripts.push_back(scriptFullPath); } // Toolbar item else if (0 == strcmp(element, "TOOLBAR")) { + tstring iconFullPath = _T(""); element = strtok_s(NULL, "/", &context); + if ((element[1] == ':') || (element[1] == '\\')) + { + scriptFullPath = WcharMbcsConverter::char2tchar(element).get(); + } + else + { + scriptFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(element).get())); + } + char *iconPath = strtok_s(NULL, "/", &context); if (!iconPath || !(*iconPath)) { @@ -88,11 +106,17 @@ void ConfigFile::readConfig() } else { - hIcon = static_cast(LoadImage(NULL, WcharMbcsConverter::char2tchar(iconPath).get(), IMAGE_BITMAP, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADFROMFILE)); + if ((iconPath[1] == ':') || (iconPath[1] == '\\')) + { + iconFullPath = WcharMbcsConverter::char2tchar(iconPath).get(); + } + else + { + iconFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(iconPath).get())); + } + hIcon = static_cast(LoadImage(NULL, iconFullPath.c_str(), IMAGE_BITMAP, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADFROMFILE)); } - - - m_toolbarItems.push_back(std::pair >(tstring(WcharMbcsConverter::char2tchar(element).get()), std::pair(hIcon, iconPath ? tstring(WcharMbcsConverter::char2tchar(iconPath).get()) : tstring()))); + m_toolbarItems.push_back(std::pair >(scriptFullPath, std::pair(hIcon, iconPath ? iconFullPath : tstring()))); } else if (0 == strcmp(element, "SETTING")) { @@ -117,15 +141,38 @@ void ConfigFile::save() { //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::string userScriptsDir(WcharMbcsConverter::tchar2char((m_userScriptsDir).c_str()).get()); + 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/" << WcharMbcsConverter::tchar2char((*it).c_str()).get() << "\n"; + std::string scriptFullPath = WcharMbcsConverter::tchar2char((*it).c_str()).get(); + if (scriptFullPath.find(userScriptsDir, 0) == 0) + { + startupFile << "ITEM/" << scriptFullPath.replace(0, userScriptsDir.length(), "") << "\n"; + } + else + { + startupFile << "ITEM/" << scriptFullPath << "\n"; + } + } for(ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) { - startupFile << "TOOLBAR/" << WcharMbcsConverter::tchar2char((it->first).c_str()).get() << "/" << WcharMbcsConverter::tchar2char((it->second.second).c_str()).get() << "\n"; + std::string scriptFullPath = WcharMbcsConverter::tchar2char((it->first).c_str()).get(); + if (scriptFullPath.find(userScriptsDir,0) == 0) + { + scriptFullPath = scriptFullPath.replace(0, userScriptsDir.length(), ""); + } + + std::string iconFullPath = WcharMbcsConverter::tchar2char((it->second.second).c_str()).get(); + if (iconFullPath.find(userScriptsDir, 0) == 0) + { + iconFullPath = iconFullPath.replace(0, userScriptsDir.length(), ""); + } + + startupFile << "TOOLBAR/" << scriptFullPath << "/" << iconFullPath << "\n"; } for(SettingsTD::iterator it = m_settings.begin(); it != m_settings.end(); ++it) From 9a5c34b07d9de7ec2453d8d67a24098d14f41fc4 Mon Sep 17 00:00:00 2001 From: CFrank Date: Thu, 2 Aug 2018 19:34:11 +0200 Subject: [PATCH 02/12] introducing shortenPathIfPossible and expandPathIfNeeded functions adding NULL checks --- PythonScript/src/ConfigFile.cpp | 84 ++++++++++++++------------------- PythonScript/src/ConfigFile.h | 2 + 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/PythonScript/src/ConfigFile.cpp b/PythonScript/src/ConfigFile.cpp index a600a382..3a43611b 100644 --- a/PythonScript/src/ConfigFile.cpp +++ b/PythonScript/src/ConfigFile.cpp @@ -72,16 +72,12 @@ void ConfigFile::readConfig() if (0 == strcmp(element, "ITEM")) { element = strtok_s(NULL, "/", &context); - if ((element[1] == ':') || (element[1] == '\\')) + scriptFullPath = expandPathIfNeeded(element); + if (scriptFullPath != L"") { - scriptFullPath = WcharMbcsConverter::char2tchar(element).get(); + m_menuItems.push_back(scriptFullPath); + m_menuScripts.push_back(scriptFullPath); } - else - { - scriptFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(element).get())); - } - m_menuItems.push_back(scriptFullPath); - m_menuScripts.push_back(scriptFullPath); } // Toolbar item @@ -89,14 +85,7 @@ void ConfigFile::readConfig() { tstring iconFullPath = _T(""); element = strtok_s(NULL, "/", &context); - if ((element[1] == ':') || (element[1] == '\\')) - { - scriptFullPath = WcharMbcsConverter::char2tchar(element).get(); - } - else - { - scriptFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(element).get())); - } + scriptFullPath = expandPathIfNeeded(element); char *iconPath = strtok_s(NULL, "/", &context); if (!iconPath || !(*iconPath)) @@ -106,17 +95,13 @@ void ConfigFile::readConfig() } else { - if ((iconPath[1] == ':') || (iconPath[1] == '\\')) - { - iconFullPath = WcharMbcsConverter::char2tchar(iconPath).get(); - } - else - { - iconFullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(iconPath).get())); - } + iconFullPath = expandPathIfNeeded(iconPath); hIcon = static_cast(LoadImage(NULL, iconFullPath.c_str(), IMAGE_BITMAP, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADFROMFILE)); } - m_toolbarItems.push_back(std::pair >(scriptFullPath, std::pair(hIcon, iconPath ? iconFullPath : tstring()))); + if (scriptFullPath != L"") + { + m_toolbarItems.push_back(std::pair >(scriptFullPath, std::pair(hIcon, iconPath ? iconFullPath : tstring()))); + } } else if (0 == strcmp(element, "SETTING")) { @@ -137,6 +122,30 @@ void ConfigFile::clearItems() m_toolbarItems.erase(m_toolbarItems.begin(), m_toolbarItems.end()); } +tstring ConfigFile::expandPathIfNeeded(char *userPath) +{ + tstring fullPath = L""; + if (userPath) + { + if ((userPath[1] == ':') || (userPath[1] == '\\')) + { + fullPath = WcharMbcsConverter::char2tchar(userPath).get(); + } + else + { + fullPath.append(m_userScriptsDir).append(tstring(WcharMbcsConverter::char2tchar(userPath).get())); + } + } + return fullPath; +} + +std::string ConfigFile::shortenPathIfPossible(tstring userPath) +{ + std::string userScriptsDir(WcharMbcsConverter::tchar2char((m_userScriptsDir).c_str()).get()); + std::string fullPath = WcharMbcsConverter::tchar2char((userPath).c_str()).get(); + return (fullPath.find(userScriptsDir, 0) == 0) ? fullPath.replace(0, userScriptsDir.length(), "") : fullPath; +} + void ConfigFile::save() { //just char(UTF8) as TCHAR is not working as expected, because stream is converted to char implicitly @@ -146,33 +155,12 @@ void ConfigFile::save() 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) { - std::string scriptFullPath = WcharMbcsConverter::tchar2char((*it).c_str()).get(); - if (scriptFullPath.find(userScriptsDir, 0) == 0) - { - startupFile << "ITEM/" << scriptFullPath.replace(0, userScriptsDir.length(), "") << "\n"; - } - else - { - startupFile << "ITEM/" << scriptFullPath << "\n"; - } - + startupFile << "ITEM/" << shortenPathIfPossible(*it) << "\n"; } for(ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) { - std::string scriptFullPath = WcharMbcsConverter::tchar2char((it->first).c_str()).get(); - if (scriptFullPath.find(userScriptsDir,0) == 0) - { - scriptFullPath = scriptFullPath.replace(0, userScriptsDir.length(), ""); - } - - std::string iconFullPath = WcharMbcsConverter::tchar2char((it->second.second).c_str()).get(); - if (iconFullPath.find(userScriptsDir, 0) == 0) - { - iconFullPath = iconFullPath.replace(0, userScriptsDir.length(), ""); - } - - startupFile << "TOOLBAR/" << scriptFullPath << "/" << iconFullPath << "\n"; + startupFile << "TOOLBAR/" << shortenPathIfPossible(it->first) << "/" << shortenPathIfPossible(it->second.second) << "\n"; } for(SettingsTD::iterator it = m_settings.begin(); it != m_settings.end(); ++it) diff --git a/PythonScript/src/ConfigFile.h b/PythonScript/src/ConfigFile.h index 2ce691fd..8a90c00b 100644 --- a/PythonScript/src/ConfigFile.h +++ b/PythonScript/src/ConfigFile.h @@ -31,6 +31,8 @@ class ConfigFile void refresh() { clearItems(); readConfig(); }; + std::string shortenPathIfPossible(tstring userPath); + tstring expandPathIfNeeded(char *userPath); const tstring& getMachineScriptsDir() { return m_machineScriptsDir; }; const tstring& getUserScriptsDir() { return m_userScriptsDir; }; From 5046293b746b0f8af89340d5fdadf27fdbc8c9f4 Mon Sep 17 00:00:00 2001 From: CFrank Date: Fri, 3 Aug 2018 00:19:37 +0200 Subject: [PATCH 03/12] First step to replace chm with html help files (see #96) removed unnecessary declaration from ConfigFile --- PythonScript/src/ConfigFile.cpp | 1 - PythonScript/src/HelpController.cpp | 51 +++++++++++++++-------------- PythonScript/src/HelpController.h | 4 +-- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/PythonScript/src/ConfigFile.cpp b/PythonScript/src/ConfigFile.cpp index 3a43611b..ff4bc689 100644 --- a/PythonScript/src/ConfigFile.cpp +++ b/PythonScript/src/ConfigFile.cpp @@ -150,7 +150,6 @@ void ConfigFile::save() { //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::string userScriptsDir(WcharMbcsConverter::tchar2char((m_userScriptsDir).c_str()).get()); 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) diff --git a/PythonScript/src/HelpController.cpp b/PythonScript/src/HelpController.cpp index 08599772..bfe272dc 100644 --- a/PythonScript/src/HelpController.cpp +++ b/PythonScript/src/HelpController.cpp @@ -14,46 +14,49 @@ HelpController::HelpController(HWND hNotepad, HWND hScintilla) void HelpController::callHelp() { - //::HtmlHelp(m_hNotepad, getFilename(), HH_DISPLAY_TOPIC, getTopicUrl().c_str()); - std::string helpFile = getFilename(); - bool useWeb = false; + std::wstring helpFile = getFilename(); if (helpFile.empty()) { - helpFile = "http://npppythonscript.sourceforge.net/docs/"; - helpFile.append(PYSCR_VERSION_STRING); - helpFile.append("/"); - useWeb = true; - } - - if (useWeb) - { - helpFile.append(getTopicUrl()); - ::ShellExecuteA(m_hNotepad, "open", helpFile.c_str(), NULL, NULL, SW_SHOWDEFAULT); + helpFile = L"http://npppythonscript.sourceforge.net/docs/"; + helpFile.append(WcharMbcsConverter::char2tchar(PYSCR_VERSION_STRING).get()); + ::ShellExecute(m_hNotepad, L"open", helpFile.c_str(), NULL, NULL, SW_SHOWNORMAL); } else { - ::HtmlHelpA(m_hNotepad, helpFile.c_str(), HH_DISPLAY_TOPIC, reinterpret_cast(getTopicUrl().c_str())); + TCHAR *pszOut = NULL; + DWORD cchOUT = 0; + HRESULT res = ::AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, L".html", NULL, pszOut, &cchOUT); + if (res = S_FALSE) + pszOut = new TCHAR[cchOUT]; + ::AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, L".html", NULL, pszOut, &cchOUT); + + helpFile.insert(0, L"\"file://"); + helpFile.append(L"\\"); + std::wstring topicUrl = getTopicUrl(); + helpFile.append((topicUrl==L"") ? L"index.html" : topicUrl); + helpFile.append(L"\""); + ::ShellExecute(m_hNotepad, L"open", pszOut, helpFile.c_str(), NULL, SW_SHOWNORMAL); + delete pszOut; } - } -std::string HelpController::getFilename() +std::wstring HelpController::getFilename() { TCHAR helpPath[MAX_PATH]; ::SendMessage(m_hNotepad, NPPM_GETNPPDIRECTORY, MAX_PATH, reinterpret_cast(helpPath)); - _tcscat_s(helpPath, MAX_PATH, _T("\\plugins\\doc\\PythonScript\\PythonScript.chm")); + _tcscat_s(helpPath, MAX_PATH, _T("\\plugins\\doc\\PythonScript")); if (::PathFileExists(helpPath)) { - return std::string(WcharMbcsConverter::tchar2char(helpPath).get()); + return std::wstring(helpPath); } else { - return std::string(); + return std::wstring(); } } -std::string HelpController::getTopicUrl() +std::wstring HelpController::getTopicUrl() { size_t length = (size_t)SendMessage(m_hScintilla, SCI_GETCURLINE, 0, 0); char *buffer = new char[length + 1]; @@ -115,7 +118,7 @@ std::string HelpController::getTopicUrl() { if (dotPosition - startPosition == 7 && 0 == _strnicmp((buffer + startPosition), "notepad", dotPosition - startPosition)) { - url = "notepad.html#Notepad."; + url = "notepad.html#notepad."; url.append(buffer + dotPosition + 1); } @@ -123,16 +126,16 @@ std::string HelpController::getTopicUrl() || (dotPosition - startPosition == 7 && 0 == _strnicmp((buffer + startPosition), "editor1", dotPosition - startPosition)) || (dotPosition - startPosition == 7 && 0 == _strnicmp((buffer + startPosition), "editor2", dotPosition - startPosition))) { - url = "scintilla.html#Editor."; + url = "scintilla.html#editor."; url.append(buffer + dotPosition + 1); } if (dotPosition - startPosition == 7 && 0 == _strnicmp((buffer + startPosition), "console", dotPosition - startPosition)) { - url = "console.html#Console."; + url = "console.html#console."; url.append(buffer + dotPosition + 1); } } - return url; + return WcharMbcsConverter::char2tchar(url.c_str()).get(); } diff --git a/PythonScript/src/HelpController.h b/PythonScript/src/HelpController.h index e3b74213..330f7a9a 100644 --- a/PythonScript/src/HelpController.h +++ b/PythonScript/src/HelpController.h @@ -14,9 +14,9 @@ class HelpController HWND m_hScintilla; - std::string getFilename(); + std::wstring getFilename(); - std::string getTopicUrl(); + std::wstring getTopicUrl(); }; #endif From 847715f5e3d9840b2e20e418511244695854c272 Mon Sep 17 00:00:00 2001 From: CFrank Date: Fri, 3 Aug 2018 16:21:09 +0200 Subject: [PATCH 04/12] prevent memory leaks by correctly deleting newly created array change getFiles which fixes #98 --- PythonScript/src/HelpController.cpp | 3 ++- PythonScript/src/NotepadPlusWrapper.cpp | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/PythonScript/src/HelpController.cpp b/PythonScript/src/HelpController.cpp index bfe272dc..841f6308 100644 --- a/PythonScript/src/HelpController.cpp +++ b/PythonScript/src/HelpController.cpp @@ -36,7 +36,8 @@ void HelpController::callHelp() helpFile.append((topicUrl==L"") ? L"index.html" : topicUrl); helpFile.append(L"\""); ::ShellExecute(m_hNotepad, L"open", pszOut, helpFile.c_str(), NULL, SW_SHOWNORMAL); - delete pszOut; + + delete [] pszOut; } } diff --git a/PythonScript/src/NotepadPlusWrapper.cpp b/PythonScript/src/NotepadPlusWrapper.cpp index 0fedbd54..164f48e3 100644 --- a/PythonScript/src/NotepadPlusWrapper.cpp +++ b/PythonScript/src/NotepadPlusWrapper.cpp @@ -282,7 +282,12 @@ boost::python::list NotepadPlusWrapper::getFiles() boost::python::list files; - for(int view = 0; view <= 1; view++) + int view = 0; + bool onlyOneView = isSingleView(); + if (onlyOneView) { view = getCurrentView(); } + int view_end = onlyOneView ? view : 1; + + for(view; view <= view_end; view++) { count = (idx_t)callNotepad(NPPM_GETNBOPENFILES, 0, view ? SECOND_VIEW : PRIMARY_VIEW); @@ -300,12 +305,12 @@ boost::python::list NotepadPlusWrapper::getFiles() bufferID = callNotepad(NPPM_GETBUFFERIDFROMPOS, pos, view); if (bufferID) { -#ifdef UNICODE +//#ifdef UNICODE std::shared_ptr mbFilename = WcharMbcsConverter::tchar2char(fileNames[pos]); files.append(boost::python::make_tuple(const_cast(mbFilename.get()), bufferID, pos, view)); -#else - files.append(boost::python::make_tuple(const_cast(fileNames[pos]), bufferID, pos, view)); -#endif +//#else +// files.append(boost::python::make_tuple(const_cast(fileNames[pos]), bufferID, pos, view)); +//#endif } } } From 540c9c48e54179b540b0315f4a16ac4204b96447 Mon Sep 17 00:00:00 2001 From: CFrank Date: Fri, 3 Aug 2018 23:14:42 +0200 Subject: [PATCH 05/12] revert UNICODE/ANSI block changes --- PythonScript/src/NotepadPlusWrapper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PythonScript/src/NotepadPlusWrapper.cpp b/PythonScript/src/NotepadPlusWrapper.cpp index 164f48e3..b6cdc113 100644 --- a/PythonScript/src/NotepadPlusWrapper.cpp +++ b/PythonScript/src/NotepadPlusWrapper.cpp @@ -305,12 +305,12 @@ boost::python::list NotepadPlusWrapper::getFiles() bufferID = callNotepad(NPPM_GETBUFFERIDFROMPOS, pos, view); if (bufferID) { -//#ifdef UNICODE +#ifdef UNICODE std::shared_ptr mbFilename = WcharMbcsConverter::tchar2char(fileNames[pos]); files.append(boost::python::make_tuple(const_cast(mbFilename.get()), bufferID, pos, view)); -//#else -// files.append(boost::python::make_tuple(const_cast(fileNames[pos]), bufferID, pos, view)); -//#endif +#else + files.append(boost::python::make_tuple(const_cast(fileNames[pos]), bufferID, pos, view)); +#endif } } } From 38d7c74365b26e4bf9c10f6297cbf5441e10cb16 Mon Sep 17 00:00:00 2001 From: CFrank Date: Mon, 6 Aug 2018 16:12:05 +0200 Subject: [PATCH 06/12] missing curly braces added Run edit control converted to combobox - fixes issue #69 --- PythonScript/src/ConsoleDialog.cpp | 277 ++++++++-------------------- PythonScript/src/ConsoleDialog.h | 22 +-- PythonScript/src/HelpController.cpp | 4 +- 3 files changed, 92 insertions(+), 211 deletions(-) diff --git a/PythonScript/src/ConsoleDialog.cpp b/PythonScript/src/ConsoleDialog.cpp index d8c3a4c2..8cc2d741 100644 --- a/PythonScript/src/ConsoleDialog.cpp +++ b/PythonScript/src/ConsoleDialog.cpp @@ -21,21 +21,19 @@ ConsoleDialog::ConsoleDialog() : m_data(new tTbData), m_scintilla(NULL), m_hInput(NULL), + m_hCombo(NULL), m_console(NULL), m_currentPrompt(">>> "), m_standardPrompt(">>> "), m_continuePrompt("... "), m_originalInputWndProc(NULL), m_hTabIcon(NULL), - m_currentHistory(0), m_runButtonIsRun(true), m_hContext(NULL), m_nppData{0,0,0}, m_colorOutput(false), m_user_color(-1) -{ - m_historyIter = m_history.end(); -} +{} ConsoleDialog::~ConsoleDialog() @@ -66,6 +64,7 @@ ConsoleDialog::~ConsoleDialog() // To please Lint, let's NULL these handles and pointers m_hInput = NULL; + m_hCombo = NULL; m_console = NULL; } @@ -76,7 +75,7 @@ WNDPROC ConsoleDialog::s_originalScintillaWndProc; void ConsoleDialog::initDialog(HINSTANCE hInst, NppData& nppData, ConsoleInterface* console) { DockingDlgInterface::init(hInst, nppData._nppHandle); - + try { m_user_color = stoi(ConfigFile::getInstance()->getSetting(_T("COLORIZEOUTPUT"))); @@ -90,8 +89,8 @@ void ConsoleDialog::initDialog(HINSTANCE hInst, NppData& nppData, ConsoleInterfa m_currentPrompt = m_standardPrompt; //Window::init(hInst, nppData._nppHandle); createOutputWindow(nppData._nppHandle); - - + + m_console = console; m_hContext = CreatePopupMenu(); MENUITEMINFO mi; @@ -99,7 +98,7 @@ void ConsoleDialog::initDialog(HINSTANCE hInst, NppData& nppData, ConsoleInterfa mi.fMask = MIIM_ID | MIIM_STRING; mi.fType = MFT_STRING; mi.fState = MFS_ENABLED; - + mi.wID = 1; mi.dwTypeData = _T("Select all"); InsertMenuItem(m_hContext, 0, TRUE, &mi); @@ -123,17 +122,18 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM { SetParent(m_scintilla, _hSelf); ShowWindow(m_scintilla, SW_SHOW); - m_hInput = ::GetDlgItem(_hSelf, IDC_INPUT); + m_hCombo = ::GetDlgItem(_hSelf, IDC_COMBO1); + m_hInput = FindWindowEx(m_hCombo, NULL, L"Edit", NULL); HFONT hCourier = CreateFont(14,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, FIXED_PITCH, _T("Courier New")); if (hCourier != NULL) { - SendMessage(m_hInput, WM_SETFONT, reinterpret_cast(hCourier), TRUE); - SendMessage(::GetDlgItem(_hSelf, IDC_PROMPT), WM_SETFONT, reinterpret_cast(hCourier), TRUE); + SendMessage(m_hInput, WM_SETFONT, reinterpret_cast(hCourier), TRUE); + SendMessage(::GetDlgItem(_hSelf, IDC_PROMPT), WM_SETFONT, reinterpret_cast(hCourier), TRUE); } - // Subclass the Input box - ::SetWindowLongPtr(::GetDlgItem(_hSelf, IDC_INPUT), GWLP_USERDATA, reinterpret_cast(this)); - m_originalInputWndProc = reinterpret_cast(::SetWindowLongPtr(::GetDlgItem(_hSelf, IDC_INPUT), GWLP_WNDPROC, reinterpret_cast(ConsoleDialog::inputWndProc))); + // Subclass the Input box from the combobox + ::SetWindowLongPtr(m_hInput, GWLP_USERDATA, reinterpret_cast(this)); + m_originalInputWndProc = reinterpret_cast(::SetWindowLongPtr(m_hInput, GWLP_WNDPROC, reinterpret_cast(ConsoleDialog::inputWndProc))); // Subclass Scintilla s_originalScintillaWndProc = reinterpret_cast(SetWindowLongPtr(m_scintilla, GWLP_WNDPROC, reinterpret_cast(&ConsoleDialog::scintillaWndProc))); ::SetFocus(m_hInput); @@ -142,8 +142,8 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM case WM_SIZE: MoveWindow(m_scintilla, 0, 0, LOWORD(lParam), HIWORD(lParam)-30, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-25, 30, 25, TRUE); - MoveWindow(m_hInput, 30, HIWORD(lParam)-30, LOWORD(lParam) - 85, 25, TRUE); - MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam) - 50, HIWORD(lParam) - 30, 50, 25, TRUE); + MoveWindow(m_hCombo, 30, HIWORD(lParam)-25, LOWORD(lParam)-85, 25, TRUE); + MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-25, 50, 25, TRUE); // ::SendMessage(m_scintilla, WM_SIZE, 0, MAKEWORD(LOWORD(lParam) - 10, HIWORD(lParam) - 30)); return FALSE; @@ -160,14 +160,14 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM { mi.fState = MFS_ENABLED; } - + SetMenuItemInfo(m_hContext, 2, FALSE, &mi); // Thanks MS for corrupting the value of BOOL. :-/ // From the documentation (http://msdn.microsoft.com/en-us/library/ms648002.aspx): // - // If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item - // identifier of the item that the user selected. If the user cancels the menu without making + // If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item + // identifier of the item that the user selected. If the user cancels the menu without making // a selection, or if an error occurs, then the return value is zero. INT cmdID = (INT)TrackPopupMenu(m_hContext, TPM_RETURNCMD, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, _hSelf, NULL); @@ -242,7 +242,7 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM case SCN_HOTSPOTCLICK: onHotspotClick(reinterpret_cast(lParam)); return FALSE; - + default: break; } @@ -261,117 +261,19 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM return DockingDlgInterface::run_dlgProc(message, wParam, lParam); } - -void ConsoleDialog::historyPrevious() -{ - if (m_currentHistory > 0) - { - size_t length = GetWindowTextLength(m_hInput); - TCHAR *buffer = new TCHAR[length + 1]; - GetWindowText(m_hInput, buffer, (int)length + 1); - - // Not an empty string and different from orig - if (buffer[0] && (m_historyIter == m_history.end() || *m_historyIter != buffer)) - { - if (m_changes.find(m_currentHistory) == m_changes.end()) - { - m_changes.insert(std::pair(m_currentHistory, tstring(buffer))); - } - else - { - m_changes[m_currentHistory] = tstring(buffer); - } - } - delete [] buffer; - - --m_currentHistory; - --m_historyIter; - - // If there's no changes to the line, just copy the original - if (m_changes.find(m_currentHistory) == m_changes.end()) - { - ::SetWindowText(m_hInput, m_historyIter->c_str()); - ::SendMessage(m_hInput, EM_SETSEL, m_historyIter->size(), (LPARAM)m_historyIter->size()); - } - else - { - // Set it as the changed string - ::SetWindowText(m_hInput, m_changes[m_currentHistory].c_str()); - ::SendMessage(m_hInput, EM_SETSEL, m_changes[m_currentHistory].size(), (LPARAM)m_changes[m_currentHistory].size()); - } - - } -} - -void ConsoleDialog::historyNext() -{ - if (static_cast(m_currentHistory) < m_history.size()) - { - int length = GetWindowTextLength(m_hInput); - TCHAR *buffer = new TCHAR[length + 1]; - GetWindowText(m_hInput, buffer, length + 1); - - - // Not an empty string and different from orig - if (buffer[0] && *m_historyIter != buffer) - { - if (m_changes.find(m_currentHistory) == m_changes.end()) - { - m_changes.insert(std::pair(m_currentHistory, tstring(buffer))); - } - else - { - m_changes[m_currentHistory] = tstring(buffer); - } - } - delete [] buffer; - - ++m_currentHistory; - ++m_historyIter; - - // If there's no changes to the line, just copy the original - if (m_changes.find(m_currentHistory) == m_changes.end()) - { - if (m_historyIter != m_history.end()) - { - ::SetWindowText(m_hInput, m_historyIter->c_str()); - ::SendMessage(m_hInput, EM_SETSEL, m_historyIter->size(), (LPARAM)m_historyIter->size()); - } - else - { - ::SetWindowTextA(m_hInput, ""); - } - } - else - { - // Set it as the changed string - ::SetWindowText(m_hInput, m_changes[m_currentHistory].c_str()); - ::SendMessage(m_hInput, EM_SETSEL, m_changes[m_currentHistory].size(), (LPARAM)m_changes[m_currentHistory].size()); - } - } -} - - void ConsoleDialog::historyAdd(const TCHAR *line) { if (line && line[0]) { - m_history.push_back(tstring(line)); - m_currentHistory = m_history.size(); - } - - m_historyIter = m_history.end(); - m_changes.clear(); -} - -void ConsoleDialog::historyEnd() -{ - m_currentHistory = m_history.size(); - m_historyIter = m_history.end(); - ::SetWindowText(m_hInput, _T("")); + auto i = ::SendMessage(m_hCombo, CB_FINDSTRINGEXACT, static_cast(-1), reinterpret_cast(line)); + if (i != CB_ERR) // found + { + ::SendMessage(m_hCombo, CB_DELETESTRING, i, 0); + } + i = ::SendMessage(m_hCombo, CB_INSERTSTRING, 0, reinterpret_cast(line)); + } } - LRESULT ConsoleDialog::inputWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ConsoleDialog *dlg = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); @@ -380,24 +282,8 @@ LRESULT ConsoleDialog::inputWndProc(HWND hWnd, UINT message, WPARAM wParam, LPAR LRESULT ConsoleDialog::run_inputWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch(message) { - case WM_KEYDOWN: - switch(wParam) - { - case VK_UP: - historyPrevious(); - return FALSE; - - case VK_DOWN: - historyNext(); - return FALSE; - - default: - return CallWindowProc(m_originalInputWndProc, hWnd, message, wParam, lParam); - } - case WM_KEYUP: switch(wParam) { @@ -405,17 +291,13 @@ LRESULT ConsoleDialog::run_inputWndProc(HWND hWnd, UINT message, WPARAM wParam, runStatement(); return FALSE; - case VK_ESCAPE: - historyEnd(); - return FALSE; - default: return CallWindowProc(m_originalInputWndProc, hWnd, message, wParam, lParam); } - + case WM_SETFOCUS: OutputDebugString(_T("Input SetFocus\r\n")); - + default: return CallWindowProc(m_originalInputWndProc, hWnd, message, wParam, lParam); } @@ -426,19 +308,18 @@ void ConsoleDialog::runStatement() assert(m_console != NULL); if (m_console) { - - HWND hText = ::GetDlgItem(_hSelf, IDC_INPUT); - size_t length = GetWindowTextLength(hText); + size_t length = GetWindowTextLength(m_hInput); TCHAR *buffer = new TCHAR[length + 1]; - GetWindowText(hText, buffer, (int)length + 1); + GetWindowText(m_hInput, buffer, (int)length + 1); historyAdd(buffer); + std::shared_ptr charBuffer = WcharMbcsConverter::tchar2char(buffer); delete [] buffer; writeCmdText(m_currentPrompt.size(), m_currentPrompt.c_str()); writeCmdText(strlen(charBuffer.get()), charBuffer.get()); writeCmdText(1, "\n"); - SetWindowText(hText, _T("")); + SetWindowText(m_hInput, _T("")); m_console->runStatement(charBuffer.get()); } } @@ -468,7 +349,7 @@ std::string ConsoleDialog::getContinuePrompt(){ return m_continuePrompt;} void ConsoleDialog::createOutputWindow(HWND hParentWindow) { m_scintilla = (HWND)::SendMessage(_hParent, NPPM_CREATESCINTILLAHANDLE, 0, reinterpret_cast(hParentWindow)); - + LONG_PTR currentStyle = GetWindowLongPtr(m_scintilla, GWL_STYLE); SetWindowLongPtr(m_scintilla, GWL_STYLE, currentStyle | WS_TABSTOP); @@ -482,7 +363,7 @@ void ConsoleDialog::createOutputWindow(HWND hParentWindow) /* Style bits * LSB 0 - stderr = 1 - * 1 - hotspot + * 1 - hotspot * 2 - warning * ... to be continued */ @@ -491,48 +372,48 @@ void ConsoleDialog::createOutputWindow(HWND hParentWindow) callScintilla(SCI_SETCODEPAGE, 65001); // 0 is stdout, black text - callScintilla(SCI_STYLESETSIZE, 0 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 0 /* = style number */, 8 /* = size in points */); // 1 is stderr, red text - callScintilla(SCI_STYLESETSIZE, 1 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 1 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 1, RGB(250, 0, 0)); // 2 is stdout, black text, underline hotspot - callScintilla(SCI_STYLESETSIZE, 2 /* = style number */, 8 /* = size in points */); - callScintilla(SCI_STYLESETUNDERLINE, 2 /* = style number */, 1 /* = underline */); + callScintilla(SCI_STYLESETSIZE, 2 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETUNDERLINE, 2 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 2, 1); // 3 is stderr, red text, underline hotspot - callScintilla(SCI_STYLESETSIZE, 3 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 3 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 3, RGB(250, 0, 0)); - callScintilla(SCI_STYLESETUNDERLINE, 3 /* = style number */, 1 /* = underline */); + callScintilla(SCI_STYLESETUNDERLINE, 3 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 3, 1); - + // 4 stdout warning without hotspot - callScintilla(SCI_STYLESETSIZE, 4 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 4 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 4, RGB(199, 175, 7)); // mucky yellow - + // 5 stderr warning without hotspot - callScintilla(SCI_STYLESETSIZE, 5 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 5 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 5, RGB(255, 128, 64)); // orange - + // 6 is hotspot, stdout, warning - callScintilla(SCI_STYLESETSIZE, 6 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 6 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 6, RGB(199, 175, 7)); // mucky yellow - callScintilla(SCI_STYLESETUNDERLINE, 6 /* = style number */, 1 /* = underline */); + callScintilla(SCI_STYLESETUNDERLINE, 6 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 6, 1); // 7 is hotspot, stderr, warning - callScintilla(SCI_STYLESETSIZE, 7 /* = style number */, 8 /* = size in points */); + callScintilla(SCI_STYLESETSIZE, 7 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 7, RGB(255, 128, 64)); // orange - callScintilla(SCI_STYLESETUNDERLINE, 7 /* = style number */, 1 /* = underline */); + callScintilla(SCI_STYLESETUNDERLINE, 7 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 7, 1); - + // 8 is colored stdout inidcator intptr_t defaultColor = callScintilla(SCI_STYLEGETFORE, 0, 0); callScintilla(SCI_INDICSETSTYLE, 8 /* = indicator number */, INDIC_TEXTFORE); callScintilla(SCI_INDICSETFORE, 8, m_colorOutput ? m_user_color : defaultColor); // green - + callScintilla(SCI_USEPOPUP, 0); callScintilla(SCI_SETLEXER, SCLEX_CONTAINER); } @@ -547,7 +428,7 @@ LRESULT ConsoleDialog::scintillaWndProc(HWND hWnd, UINT message, WPARAM wParam, case WM_SETFOCUS: OutputDebugString(_T("Scintilla SetFocus\r\n")); break; - + default: break; } @@ -593,16 +474,16 @@ void ConsoleDialog::writeText(size_t length, const char *text) i = 0; } } - + if (length > 0) { ::SendMessage(m_scintilla, SCI_APPENDTEXT, length, reinterpret_cast(text)); } ::SendMessage(m_scintilla, SCI_SETREADONLY, 1, 0); - + ::SendMessage(m_scintilla, SCI_GOTOPOS, ::SendMessage(m_scintilla, SCI_GETLENGTH, 0, 0), 0); - + } void ConsoleDialog::writeColoredText(size_t length, const char *text) @@ -641,7 +522,7 @@ void ConsoleDialog::writeError(size_t length, const char *text) i = 0; } } - + if (length > 0) { callScintilla(SCI_APPENDTEXT, length, reinterpret_cast(text)); @@ -651,7 +532,7 @@ void ConsoleDialog::writeError(size_t length, const char *text) callScintilla(SCI_STARTSTYLING, docLength, 0x01); callScintilla(SCI_SETSTYLING, realLength, 1); - + callScintilla(SCI_COLOURISE, docLength, -1); callScintilla(SCI_GOTOPOS, docLength + realLength); } @@ -669,7 +550,7 @@ void ConsoleDialog::doDialog() // define the default docking behaviour m_data->uMask = DWS_DF_CONT_BOTTOM | DWS_ICONTAB; m_data->pszName = _T("Python"); - + RECT rc; rc.bottom = 0; rc.top = 0; @@ -703,7 +584,7 @@ void ConsoleDialog::hide() intptr_t currentView = MAIN_VIEW; ::SendMessage(m_nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)¤tView); HWND sci = (currentView == MAIN_VIEW) ? m_nppData._scintillaMainHandle : m_nppData._scintillaSecondHandle; - + DWORD currentThreadId = GetCurrentThreadId(); DWORD otherThreadId = GetWindowThreadProcessId(sci, NULL); @@ -754,8 +635,8 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification) callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast(lineDetails.line)); lineDetails.line[lineDetails.lineLength] = '\0'; lineDetails.errorLevel = EL_UNSET; - - + + if (parseLine(&lineDetails)) { startPos = (idx_t)callScintilla(SCI_POSITIONFROMLINE, lineNumber); @@ -793,7 +674,7 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification) callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameStart, mask | 0x02); callScintilla(SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart, style | 0x02); - + if (lineDetails.lineLength > lineDetails.filenameEnd) { callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameEnd, mask); @@ -805,7 +686,7 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification) } delete[] lineDetails.line; - + } } @@ -823,8 +704,8 @@ bool ConsoleDialog::parseLine(LineDetails *lineDetails) { return true; } - - // Eg. + + // Eg. // e:\work\pythonscript\pythonscript\src\consoledialog.cpp(523): error C2065: 'ee' : undeclared identifier // Potentially with spaces in front if MSBUILD used // Line number can contain "," for column (523,5) @@ -893,7 +774,7 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails) ++pos; } - + if (lineDetails->line[pos] == '(') // Found the opening bracket for line no { ++pos; @@ -915,7 +796,7 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails) } endLineNoPos = pos; - if (pos < (lineDetails->lineLength + 1) + if (pos < (lineDetails->lineLength + 1) && lineDetails->line[pos] == ',') { ++pos; @@ -924,10 +805,10 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails) ++pos; } } - - if (pos < (lineDetails->lineLength + 1) - && lineDetails->line[pos] == ')' + + if (pos < (lineDetails->lineLength + 1) + && lineDetails->line[pos] == ')' && lineDetails->line[pos+1] == ':') { // If no line number, jump out @@ -1020,15 +901,15 @@ bool ConsoleDialog::parseGCCErrorLine(LineDetails *lineDetails) if (isEscaped) isEscaped = false; - + if (lineDetails->line[pos] == '\\') isEscaped = true; - + ++pos; - + } - + if (lineDetails->line[pos] == ':') // Found the colon for line no { ++pos; @@ -1048,12 +929,12 @@ bool ConsoleDialog::parseGCCErrorLine(LineDetails *lineDetails) { ++pos; } - if (pos < (lineDetails->lineLength + 1) + if (pos < (lineDetails->lineLength + 1) && lineDetails->line[pos] == ':') { lineDetails->errorLineNo = strtoul(lineDetails->line + startLineNoPos, NULL, 0) - 1; - // If the line number came out as 0, ie. there wasn't any, + // If the line number came out as 0, ie. there wasn't any, // then the line is not a gcc error if (lineDetails->errorLineNo == IDX_MAX) { @@ -1137,14 +1018,14 @@ bool ConsoleDialog::parsePythonErrorLine(LineDetails *lineDetails) { ++pos; } - + if (pos >= lineDetails->lineLength) // Not found, so revert to default style { styleState = SS_EXIT; } else { - lineDetails->filenameEnd = pos; + lineDetails->filenameEnd = pos; retVal = true; styleState = SS_EXPECTLINE; } diff --git a/PythonScript/src/ConsoleDialog.h b/PythonScript/src/ConsoleDialog.h index bc526a3c..7dba1784 100644 --- a/PythonScript/src/ConsoleDialog.h +++ b/PythonScript/src/ConsoleDialog.h @@ -21,7 +21,7 @@ class ConsoleDialog : public DockingDlgInterface ConsoleDialog(const ConsoleDialog& other) = delete; ~ConsoleDialog(); - + void initDialog(HINSTANCE hInst, NppData& nppData, ConsoleInterface *console); void doDialog(); @@ -36,32 +36,33 @@ class ConsoleDialog : public DockingDlgInterface std::string getStandardPrompt(); std::string getContinuePrompt(); HWND getScintillaHwnd() { return m_scintilla; } - + void giveInputFocus() { SetFocus(m_hInput); } void runEnabled(bool enabled); NppData m_nppData; - + protected: virtual INT_PTR CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam); - + private: ConsoleDialog& operator = (const ConsoleDialog&); // assignment operator disabled void createOutputWindow(HWND hParentWindow); void runStatement(); void stopStatement(); - + LRESULT run_inputWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); static LRESULT inputWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); static LRESULT scintillaWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - + void historyNext(); void historyPrevious(); void historyAdd(const TCHAR *line); void historyEnd(); + void selectComboboxItem(); LRESULT callScintilla(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return ::SendMessage(m_scintilla, message, wParam, lParam); } @@ -82,7 +83,8 @@ class ConsoleDialog : public DockingDlgInterface tTbData* m_data; HWND m_scintilla; static WNDPROC s_originalScintillaWndProc; - HWND m_hInput; // Input TextBox + HWND m_hCombo; // ComboBox + HWND m_hInput; // Input ComboBox ConsoleInterface *m_console; std::string m_standardPrompt; std::string m_continuePrompt; @@ -90,16 +92,12 @@ class ConsoleDialog : public DockingDlgInterface WNDPROC m_originalInputWndProc; HICON m_hTabIcon; - std::list m_history; - std::list::iterator m_historyIter; - std::map m_changes; - idx_t m_currentHistory; bool m_runButtonIsRun; HMENU m_hContext; bool m_colorOutput; int m_user_color; - + }; enum ErrorLevel diff --git a/PythonScript/src/HelpController.cpp b/PythonScript/src/HelpController.cpp index 841f6308..b8b0f6ae 100644 --- a/PythonScript/src/HelpController.cpp +++ b/PythonScript/src/HelpController.cpp @@ -27,17 +27,19 @@ void HelpController::callHelp() DWORD cchOUT = 0; HRESULT res = ::AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, L".html", NULL, pszOut, &cchOUT); if (res = S_FALSE) + { pszOut = new TCHAR[cchOUT]; ::AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, L".html", NULL, pszOut, &cchOUT); helpFile.insert(0, L"\"file://"); helpFile.append(L"\\"); std::wstring topicUrl = getTopicUrl(); - helpFile.append((topicUrl==L"") ? L"index.html" : topicUrl); + helpFile.append((topicUrl == L"") ? L"index.html" : topicUrl); helpFile.append(L"\""); ::ShellExecute(m_hNotepad, L"open", pszOut, helpFile.c_str(), NULL, SW_SHOWNORMAL); delete [] pszOut; + } } } From f559c0f8866f71846dd62e687fd66064e4c471df Mon Sep 17 00:00:00 2001 From: CFrank Date: Mon, 6 Aug 2018 18:37:37 +0200 Subject: [PATCH 07/12] add missing identifier IDC_COMBO1 --- PythonScript/res/PythonScript.rc | 27 ++++++++++++++++----------- PythonScript/res/resource.h | 7 ++++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/PythonScript/res/PythonScript.rc b/PythonScript/res/PythonScript.rc index e2167672..c0cd1453 100644 --- a/PythonScript/res/PythonScript.rc +++ b/PythonScript/res/PythonScript.rc @@ -57,7 +57,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,143,168,50,14 LTEXT "Python Script",IDC_STATIC,146,7,49,8 - LTEXT "(C) 2010, 2011, 2014, 2018 Dave Brotherstone",IDC_STATIC,92,30,154,8 + LTEXT "(C) 2010, 2011, 2014, 2018 Dave Brotherstone",IDC_STATIC,105,30,133,8 CONTROL IDB_PYTHONPOWERED,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,118,42,93,34 EDITTEXT IDC_COPYRIGHT,7,84,324,74,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL CTEXT "1.0",IDC_VERSION,156,19,26,8 @@ -68,9 +68,9 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM CAPTION "Python Script" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - EDITTEXT IDC_INPUT,28,156,121,14,ES_AUTOHSCROLL | ES_WANTRETURN - PUSHBUTTON "Run",IDC_RUN,152,156,40,14 - LTEXT ">>>",IDC_PROMPT,7,161,17,8 + PUSHBUTTON "Run",IDC_RUN,152,155,40,15 + LTEXT ">>>",IDC_PROMPT,7,158,17,11 + COMBOBOX IDC_COMBO1,25,156,125,25,CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP END IDD_SCRIPTCONFIG DIALOGEX 0, 0, 377, 404 @@ -86,13 +86,13 @@ BEGIN CONTROL "User Scripts",IDC_RADUSER,"Button",BS_AUTORADIOBUTTON,94,18,54,10 PUSHBUTTON "Add",IDC_MENUADD,21,146,50,14 PUSHBUTTON "Remove",IDC_MENUREMOVE,89,146,50,14 - PUSHBUTTON "Add",IDC_TOOLBARADD,187,146,50,14 + PUSHBUTTON "Add",IDC_TOOLBARADD,187,145,50,14 PUSHBUTTON "Remove",IDC_TOOLBARREMOVE,245,146,50,14 - LTEXT "Menu items",IDC_STATIC,10,161,37,8 + LTEXT "Menu items",IDC_STATIC,10,162,37,8 LTEXT "Toolbar icons",IDC_STATIC,186,161,43,8 CONTROL "",IDC_TOOLBARITEMLIST2,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,186,172,184,104 PUSHBUTTON "Set Icon...",IDC_TOOLBARSETICON,304,146,50,14 - CONTROL "",IDC_MENUITEMLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,172,173,104 + CONTROL "",IDC_MENUITEMLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,171,173,106 COMBOBOX IDC_COMBOINITIALISATION,55,285,69,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Initialisation:",IDC_STATIC,9,287,44,12 LTEXT "Lazy initialisation initialises Python when it is first used. Use ATSTARTUP if you want your startup.py scripts to run as soon as Notepad++ starts.",IDC_STATIC,131,282,232,21 @@ -100,12 +100,12 @@ BEGIN "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,303,352,19 LTEXT "This has the effect that the directories under Notepad++ that contain Python libraries are searched AFTER the standard Python directories. If in doubt, leave unchecked.",IDC_STATIC,22,321,348,19 CONTROL "Add an additional end of line character for run statements and error messages to the console",IDC_CHECKADDEXTRALINETOOUTPUT, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,356,314,10 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,357,329,10 CONTROL "Automatically open console on error (no restart required)",IDC_CHECKOPENCONSOLEONERROR, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,342,197,10 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,343,197,10 CONTROL "Color output from run statements differently",IDC_CHECKCOLORIZEOUTPUT, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,11,370,157,10 - PUSHBUTTON "Choose a color...",IDC_COLORCHOOSER,169,367,65,14 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,11,371,157,10 + PUSHBUTTON "Chose a color...",IDC_COLORCHOOSER,169,368,62,14 END IDD_PROMPTDIALOG DIALOGEX 0, 0, 313, 105 @@ -204,6 +204,11 @@ BEGIN 0 END +IDD_CONSOLE AFX_DIALOG_LAYOUT +BEGIN + 0 +END + #endif // English (United Kingdom) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/PythonScript/res/resource.h b/PythonScript/res/resource.h index edb266c5..cb3f7857 100644 --- a/PythonScript/res/resource.h +++ b/PythonScript/res/resource.h @@ -16,7 +16,7 @@ #define IDI_ICON1 114 #define IDD_PROMPTDIALOG 116 #define IDB_PYTHONPOWERED 118 -#define IDC_INPUT 1001 +#define IDC_COMBO1 1001 #define IDC_RUN 1002 #define IDC_PROMPT 1003 #define IDC_FILETREE 1004 @@ -43,13 +43,14 @@ #define IDC_CHECKCOLORIZEOUTPUT 1023 #define IDC_COLORCHOOSER 1024 + // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 121 +#define _APS_NEXT_RESOURCE_VALUE 122 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1025 +#define _APS_NEXT_CONTROL_VALUE 1028 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif From 0958c9de13ddb443599af6b6f7db2c7c9e006e1c Mon Sep 17 00:00:00 2001 From: CFrank Date: Mon, 6 Aug 2018 19:58:10 +0200 Subject: [PATCH 08/12] Set stdout to console as default, fixes #78 --- scripts/startup.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/startup.py b/scripts/startup.py index 7756a5a1..47f23355 100644 --- a/scripts/startup.py +++ b/scripts/startup.py @@ -12,18 +12,19 @@ class ConsoleError: def __init__(self): global console self._console = console; - + def write(self, text): self._console.writeError(text); - + # Set the stderr to write errors in red sys.stderr = ConsoleError() # This imports the "normal" functions, including "help" import site -# This sets the stdout to be the currently active document, so print "hello world", -# will insert "hello world" at the current cursor position of the current document -sys.stdout = editor +sys.stdout = console +# In order to set the stdout to the current active document, uncomment the following line +# sys.stdout = editor +# So print "hello world", will insert "hello world" at the current cursor position From 383fe820129bc24d85561d5fa42705eacbad4c4a Mon Sep 17 00:00:00 2001 From: CFrank Date: Tue, 7 Aug 2018 01:58:36 +0200 Subject: [PATCH 09/12] recommit rc changes make last command stay in editbox --- PythonScript/res/PythonScript.rc | 28 ++++++++++++++-------------- PythonScript/src/ConsoleDialog.cpp | 3 +-- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/PythonScript/res/PythonScript.rc b/PythonScript/res/PythonScript.rc index c0cd1453..3856f38c 100644 --- a/PythonScript/res/PythonScript.rc +++ b/PythonScript/res/PythonScript.rc @@ -25,18 +25,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" @@ -57,7 +57,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,143,168,50,14 LTEXT "Python Script",IDC_STATIC,146,7,49,8 - LTEXT "(C) 2010, 2011, 2014, 2018 Dave Brotherstone",IDC_STATIC,105,30,133,8 + LTEXT "(C) 2010, 2011, 2014, 2018 Dave Brotherstone",IDC_STATIC,92,30,154,8 CONTROL IDB_PYTHONPOWERED,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,118,42,93,34 EDITTEXT IDC_COPYRIGHT,7,84,324,74,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL CTEXT "1.0",IDC_VERSION,156,19,26,8 @@ -68,9 +68,9 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM CAPTION "Python Script" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - PUSHBUTTON "Run",IDC_RUN,152,155,40,15 - LTEXT ">>>",IDC_PROMPT,7,158,17,11 - COMBOBOX IDC_COMBO1,25,156,125,25,CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Run",IDC_RUN,152,156,40,13 + LTEXT ">>>",IDC_PROMPT,7,160,17,11 + COMBOBOX IDC_COMBO1,25,156,125,50,CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP END IDD_SCRIPTCONFIG DIALOGEX 0, 0, 377, 404 @@ -86,13 +86,13 @@ BEGIN CONTROL "User Scripts",IDC_RADUSER,"Button",BS_AUTORADIOBUTTON,94,18,54,10 PUSHBUTTON "Add",IDC_MENUADD,21,146,50,14 PUSHBUTTON "Remove",IDC_MENUREMOVE,89,146,50,14 - PUSHBUTTON "Add",IDC_TOOLBARADD,187,145,50,14 + PUSHBUTTON "Add",IDC_TOOLBARADD,187,146,50,14 PUSHBUTTON "Remove",IDC_TOOLBARREMOVE,245,146,50,14 - LTEXT "Menu items",IDC_STATIC,10,162,37,8 + LTEXT "Menu items",IDC_STATIC,10,161,37,8 LTEXT "Toolbar icons",IDC_STATIC,186,161,43,8 CONTROL "",IDC_TOOLBARITEMLIST2,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,186,172,184,104 PUSHBUTTON "Set Icon...",IDC_TOOLBARSETICON,304,146,50,14 - CONTROL "",IDC_MENUITEMLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,171,173,106 + CONTROL "",IDC_MENUITEMLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,172,173,104 COMBOBOX IDC_COMBOINITIALISATION,55,285,69,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Initialisation:",IDC_STATIC,9,287,44,12 LTEXT "Lazy initialisation initialises Python when it is first used. Use ATSTARTUP if you want your startup.py scripts to run as soon as Notepad++ starts.",IDC_STATIC,131,282,232,21 @@ -100,12 +100,12 @@ BEGIN "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,303,352,19 LTEXT "This has the effect that the directories under Notepad++ that contain Python libraries are searched AFTER the standard Python directories. If in doubt, leave unchecked.",IDC_STATIC,22,321,348,19 CONTROL "Add an additional end of line character for run statements and error messages to the console",IDC_CHECKADDEXTRALINETOOUTPUT, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,357,329,10 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,356,314,10 CONTROL "Automatically open console on error (no restart required)",IDC_CHECKOPENCONSOLEONERROR, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,343,197,10 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,11,342,197,10 CONTROL "Color output from run statements differently",IDC_CHECKCOLORIZEOUTPUT, - "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,11,371,157,10 - PUSHBUTTON "Chose a color...",IDC_COLORCHOOSER,169,368,62,14 + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP,11,370,157,10 + PUSHBUTTON "Choose a color...",IDC_COLORCHOOSER,169,367,65,14 END IDD_PROMPTDIALOG DIALOGEX 0, 0, 313, 105 diff --git a/PythonScript/src/ConsoleDialog.cpp b/PythonScript/src/ConsoleDialog.cpp index 8cc2d741..fdaf7bcf 100644 --- a/PythonScript/src/ConsoleDialog.cpp +++ b/PythonScript/src/ConsoleDialog.cpp @@ -141,7 +141,7 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM } case WM_SIZE: MoveWindow(m_scintilla, 0, 0, LOWORD(lParam), HIWORD(lParam)-30, TRUE); - MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-25, 30, 25, TRUE); + MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-22, 30, 25, TRUE); MoveWindow(m_hCombo, 30, HIWORD(lParam)-25, LOWORD(lParam)-85, 25, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-25, 50, 25, TRUE); // ::SendMessage(m_scintilla, WM_SIZE, 0, MAKEWORD(LOWORD(lParam) - 10, HIWORD(lParam) - 30)); @@ -319,7 +319,6 @@ void ConsoleDialog::runStatement() writeCmdText(m_currentPrompt.size(), m_currentPrompt.c_str()); writeCmdText(strlen(charBuffer.get()), charBuffer.get()); writeCmdText(1, "\n"); - SetWindowText(m_hInput, _T("")); m_console->runStatement(charBuffer.get()); } } From dd3aaddcc92c9f59086b82e13ad2e4250436a3cf Mon Sep 17 00:00:00 2001 From: CFrank Date: Tue, 7 Aug 2018 09:51:38 +0200 Subject: [PATCH 10/12] slight position adjustment to RUN button --- PythonScript/src/ConsoleDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PythonScript/src/ConsoleDialog.cpp b/PythonScript/src/ConsoleDialog.cpp index fdaf7bcf..c230cbf2 100644 --- a/PythonScript/src/ConsoleDialog.cpp +++ b/PythonScript/src/ConsoleDialog.cpp @@ -143,7 +143,7 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM MoveWindow(m_scintilla, 0, 0, LOWORD(lParam), HIWORD(lParam)-30, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-22, 30, 25, TRUE); MoveWindow(m_hCombo, 30, HIWORD(lParam)-25, LOWORD(lParam)-85, 25, TRUE); - MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-25, 50, 25, TRUE); + MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-26, 50, 25, TRUE); // ::SendMessage(m_scintilla, WM_SIZE, 0, MAKEWORD(LOWORD(lParam) - 10, HIWORD(lParam) - 30)); return FALSE; From cd857f51256a5c0fcc29de10f901789c0fe7b187 Mon Sep 17 00:00:00 2001 From: CFrank Date: Thu, 9 Aug 2018 02:47:44 +0200 Subject: [PATCH 11/12] make selected combobox item stay make edit control in combobox scrolling --- PythonScript/res/PythonScript.rc | 4 ++-- PythonScript/src/ConsoleDialog.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PythonScript/res/PythonScript.rc b/PythonScript/res/PythonScript.rc index 3856f38c..cf52dfb8 100644 --- a/PythonScript/res/PythonScript.rc +++ b/PythonScript/res/PythonScript.rc @@ -69,8 +69,8 @@ CAPTION "Python Script" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Run",IDC_RUN,152,156,40,13 - LTEXT ">>>",IDC_PROMPT,7,160,17,11 - COMBOBOX IDC_COMBO1,25,156,125,50,CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP + LTEXT ">>>",IDC_PROMPT,7,158,17,11 + COMBOBOX IDC_COMBO1,25,156,125,50,CBS_DROPDOWN | CBS_HASSTRINGS | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP END IDD_SCRIPTCONFIG DIALOGEX 0, 0, 377, 404 diff --git a/PythonScript/src/ConsoleDialog.cpp b/PythonScript/src/ConsoleDialog.cpp index c230cbf2..7f331d7a 100644 --- a/PythonScript/src/ConsoleDialog.cpp +++ b/PythonScript/src/ConsoleDialog.cpp @@ -271,6 +271,7 @@ void ConsoleDialog::historyAdd(const TCHAR *line) ::SendMessage(m_hCombo, CB_DELETESTRING, i, 0); } i = ::SendMessage(m_hCombo, CB_INSERTSTRING, 0, reinterpret_cast(line)); + ::SendMessage(m_hCombo, CB_SETCURSEL, i, 0); } } From 0512efe7beedeabfce4b85332ec6f207ea002d5b Mon Sep 17 00:00:00 2001 From: CFrank Date: Fri, 10 Aug 2018 13:24:31 +0200 Subject: [PATCH 12/12] changing console combobox and run button position and dimensions --- PythonScript/src/ConsoleDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PythonScript/src/ConsoleDialog.cpp b/PythonScript/src/ConsoleDialog.cpp index 7f331d7a..5e715611 100644 --- a/PythonScript/src/ConsoleDialog.cpp +++ b/PythonScript/src/ConsoleDialog.cpp @@ -142,8 +142,8 @@ INT_PTR CALLBACK ConsoleDialog::run_dlgProc(UINT message, WPARAM wParam, LPARAM case WM_SIZE: MoveWindow(m_scintilla, 0, 0, LOWORD(lParam), HIWORD(lParam)-30, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-22, 30, 25, TRUE); - MoveWindow(m_hCombo, 30, HIWORD(lParam)-25, LOWORD(lParam)-85, 25, TRUE); - MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-26, 50, 25, TRUE); + MoveWindow(m_hCombo, 30, HIWORD(lParam)-25, LOWORD(lParam)-85, 50, TRUE); + MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam)-50, HIWORD(lParam)-25, 50, 21, TRUE); // ::SendMessage(m_scintilla, WM_SIZE, 0, MAKEWORD(LOWORD(lParam) - 10, HIWORD(lParam) - 30)); return FALSE;