diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 67d19512..7feb90fe 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -1408,8 +1408,12 @@ bool Notepad_plus::fileRename(BufferID id) // We are just going to rename the tab nothing else // So just rename the tab and rename the backup file too if applicable + // https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file + // Reserved characters: < > : " / \ | ? * + std::wstring reservedChars = TEXT("<>:\"/\\|\?*"); + StringDlg strDlg; - strDlg.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), TEXT("Rename Current Tab"), TEXT("New Name : "), buf->getFileName(), 0, true); + strDlg.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), TEXT("Rename Current Tab"), TEXT("New Name : "), buf->getFileName(), 0, reservedChars.c_str(), true); TCHAR *tabNewName = reinterpret_cast(strDlg.doDialog()); if (tabNewName) diff --git a/PowerEditor/src/ScitillaComponent/UserDefineDialog.cpp b/PowerEditor/src/ScitillaComponent/UserDefineDialog.cpp index 2a6e2ddf..d5a9b1c3 100644 --- a/PowerEditor/src/ScitillaComponent/UserDefineDialog.cpp +++ b/PowerEditor/src/ScitillaComponent/UserDefineDialog.cpp @@ -1443,6 +1443,13 @@ INT_PTR CALLBACK StringDlg::run_dlgProc(UINT Message, WPARAM wParam, LPARAM) { case WM_INITDIALOG : { + // Re-route to Subclassed the edit control's proc if needed + if (_restrictedChars.length()) + { + ::SetWindowLongPtr(GetDlgItem(_hSelf, IDC_STRING_EDIT), GWLP_USERDATA, reinterpret_cast(this)); + _oldEditProc = reinterpret_cast(SetWindowLongPtr(GetDlgItem(_hSelf, IDC_STRING_EDIT), GWLP_WNDPROC, reinterpret_cast(customEditProc))); + } + ::SetWindowText(_hSelf, _title.c_str()); ::SetDlgItemText(_hSelf, IDC_STRING_STATIC, _static.c_str()); ::SetDlgItemText(_hSelf, IDC_STRING_EDIT, _textValue.c_str()); @@ -1482,6 +1489,80 @@ INT_PTR CALLBACK StringDlg::run_dlgProc(UINT Message, WPARAM wParam, LPARAM) } } +LRESULT StringDlg::customEditProc(HWND hEdit, UINT msg, WPARAM wParam, LPARAM lParam) +{ + StringDlg *pSelf = reinterpret_cast(::GetWindowLongPtr(hEdit, GWLP_USERDATA)); + if (!pSelf) + { + return 0; + } + + switch (msg) + { + case WM_CHAR: + if (0x80 & GetKeyState(VK_CONTROL)) + { + switch (wParam) + { + case 0x16: // ctrl - V + pSelf->HandlePaste(hEdit); + return 0; + + case 0x03: // ctrl - C + case 0x18: // ctrl - X + default: + // Let them go to default + break; + } + } + else + { + // If Key pressed not permitted, then return 0 + if (!pSelf->isAllowed(reinterpret_cast(&wParam))) + return 0; + } + break; + + case WM_DESTROY: + // Reset the message handler to the original one + SetWindowLongPtr(hEdit, GWLP_WNDPROC, reinterpret_cast(pSelf->_oldEditProc)); + return 0; + } + + // Process the message using the default handler + return CallWindowProc(pSelf->_oldEditProc, hEdit, msg, wParam, lParam); +} + +bool StringDlg::isAllowed(const generic_string & txt) +{ + for (auto ch : txt) + { + if (std::find(_restrictedChars.cbegin(), _restrictedChars.cend(), ch) != _restrictedChars.cend()) + return false; + } + return true; +} + +void StringDlg::HandlePaste(HWND hEdit) +{ + if (OpenClipboard(hEdit)) + { + HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT); + if (NULL != hClipboardData) + { + LPTSTR pszText = reinterpret_cast(GlobalLock(hClipboardData)); + if (NULL != pszText && isAllowed(pszText)) + { + SendMessage(hEdit, EM_REPLACESEL, TRUE, reinterpret_cast(pszText)); + } + + GlobalUnlock(hClipboardData); + } + + CloseClipboard(); + } +} + INT_PTR CALLBACK StylerDlg::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { StylerDlg * dlg = (StylerDlg *)::GetProp(hwnd, TEXT("Styler dialog prop")); diff --git a/PowerEditor/src/ScitillaComponent/UserDefineDialog.h b/PowerEditor/src/ScitillaComponent/UserDefineDialog.h index 4b61aaae..226e5d07 100644 --- a/PowerEditor/src/ScitillaComponent/UserDefineDialog.h +++ b/PowerEditor/src/ScitillaComponent/UserDefineDialog.h @@ -399,13 +399,17 @@ class StringDlg : public StaticDialog { public : StringDlg() : StaticDialog() {}; - void init(HINSTANCE hInst, HWND parent, const TCHAR *title, const TCHAR *staticName, const TCHAR *text2Set, int txtLen = 0, bool bGotoCenter = false) { + void init(HINSTANCE hInst, HWND parent, const TCHAR *title, const TCHAR *staticName, const TCHAR *text2Set, int txtLen = 0, const TCHAR* restrictedChars = nullptr, bool bGotoCenter = false) { Window::init(hInst, parent); _title = title; _static = staticName; _textValue = text2Set; _txtLen = txtLen; _shouldGotoCenter = bGotoCenter; + if (restrictedChars && _tcslen(restrictedChars)) + { + _restrictedChars = restrictedChars; + } }; INT_PTR doDialog() { @@ -417,12 +421,20 @@ public : protected : INT_PTR CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM); + // Custom proc to subclass edit control + LRESULT static CALLBACK customEditProc(HWND hEdit, UINT msg, WPARAM wParam, LPARAM lParam); + + bool isAllowed(const generic_string& txt); + void HandlePaste(HWND hEdit); + private : generic_string _title; generic_string _textValue; generic_string _static; + generic_string _restrictedChars; int _txtLen = 0; bool _shouldGotoCenter = false; + WNDPROC _oldEditProc = nullptr; }; class StylerDlg