Don't allow restricted characters for tab file rename

Extend class StringDlg, so that characters which are not allowed in a file name such as |, :, >, < etc. will be restricted for tab's new name so that there will be no problem while saving backup file.

Close #5324
This commit is contained in:
Rajendra Singh 2019-02-17 23:28:33 +05:30 committed by Don HO
parent c4f493a7c8
commit ae980ce4d4
3 changed files with 99 additions and 2 deletions

View File

@ -1408,8 +1408,12 @@ bool Notepad_plus::fileRename(BufferID id)
// We are just going to rename the tab nothing else // We are just going to rename the tab nothing else
// So just rename the tab and rename the backup file too if applicable // 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; 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<TCHAR *>(strDlg.doDialog()); TCHAR *tabNewName = reinterpret_cast<TCHAR *>(strDlg.doDialog());
if (tabNewName) if (tabNewName)

View File

@ -1443,6 +1443,13 @@ INT_PTR CALLBACK StringDlg::run_dlgProc(UINT Message, WPARAM wParam, LPARAM)
{ {
case WM_INITDIALOG : 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<LONG_PTR>(this));
_oldEditProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(GetDlgItem(_hSelf, IDC_STRING_EDIT), GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(customEditProc)));
}
::SetWindowText(_hSelf, _title.c_str()); ::SetWindowText(_hSelf, _title.c_str());
::SetDlgItemText(_hSelf, IDC_STRING_STATIC, _static.c_str()); ::SetDlgItemText(_hSelf, IDC_STRING_STATIC, _static.c_str());
::SetDlgItemText(_hSelf, IDC_STRING_EDIT, _textValue.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<StringDlg *>(::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<TCHAR*>(&wParam)))
return 0;
}
break;
case WM_DESTROY:
// Reset the message handler to the original one
SetWindowLongPtr(hEdit, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(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<LPTSTR>(GlobalLock(hClipboardData));
if (NULL != pszText && isAllowed(pszText))
{
SendMessage(hEdit, EM_REPLACESEL, TRUE, reinterpret_cast<LPARAM>(pszText));
}
GlobalUnlock(hClipboardData);
}
CloseClipboard();
}
}
INT_PTR CALLBACK StylerDlg::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) INT_PTR CALLBACK StylerDlg::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
StylerDlg * dlg = (StylerDlg *)::GetProp(hwnd, TEXT("Styler dialog prop")); StylerDlg * dlg = (StylerDlg *)::GetProp(hwnd, TEXT("Styler dialog prop"));

View File

@ -399,13 +399,17 @@ class StringDlg : public StaticDialog
{ {
public : public :
StringDlg() : StaticDialog() {}; 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); Window::init(hInst, parent);
_title = title; _title = title;
_static = staticName; _static = staticName;
_textValue = text2Set; _textValue = text2Set;
_txtLen = txtLen; _txtLen = txtLen;
_shouldGotoCenter = bGotoCenter; _shouldGotoCenter = bGotoCenter;
if (restrictedChars && _tcslen(restrictedChars))
{
_restrictedChars = restrictedChars;
}
}; };
INT_PTR doDialog() { INT_PTR doDialog() {
@ -417,12 +421,20 @@ public :
protected : protected :
INT_PTR CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM); 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 : private :
generic_string _title; generic_string _title;
generic_string _textValue; generic_string _textValue;
generic_string _static; generic_string _static;
generic_string _restrictedChars;
int _txtLen = 0; int _txtLen = 0;
bool _shouldGotoCenter = false; bool _shouldGotoCenter = false;
WNDPROC _oldEditProc = nullptr;
}; };
class StylerDlg class StylerDlg