From 75ae73c17333e6a83ce84c11ef052b6e2e5693ca Mon Sep 17 00:00:00 2001 From: Don Ho Date: Sat, 13 Jan 2024 19:53:53 +0100 Subject: [PATCH] Fix Copy/Cut/Paste shortcut modification conflict problem The bug is introduced by: https://github.com/notepad-plus-plus/notepad-plus-plus/commit/f7c44b4413457e42e0ba56ae84f34ef0540029e8 Fix #14585, close #14586 --- PowerEditor/src/NppCommands.cpp | 2 +- PowerEditor/src/Parameters.cpp | 62 +++++++++++++++++-- PowerEditor/src/Parameters.h | 2 +- .../src/WinControls/shortcut/shortcut.cpp | 10 +++ .../src/WinControls/shortcut/shortcut.h | 11 +++- 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index d58b10a5f..41bda4bee 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -364,7 +364,7 @@ void Notepad_plus::command(int id) { _pEditView->execute(WM_CUT); } - else // Cul the entire line + else // Cut the entire line { _pEditView->execute(SCI_COPYALLOWLINE); _pEditView->execute(SCI_LINEDELETE); diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 63a4a7a24..420226f20 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -2082,11 +2082,13 @@ void NppParameters::initMenuKeys() { int nbCommands = sizeof(winKeyDefs)/sizeof(WinMenuKeyDefinition); WinMenuKeyDefinition wkd; + int previousFuncID = 0; for (int i = 0; i < nbCommands; ++i) { wkd = winKeyDefs[i]; Shortcut sc((wkd.specialName ? wstring2string(wkd.specialName, CP_UTF8).c_str() : ""), wkd.isCtrl, wkd.isAlt, wkd.isShift, static_cast(wkd.vKey)); - _shortcuts.push_back( CommandShortcut(sc, wkd.functionId) ); + _shortcuts.push_back( CommandShortcut(sc, wkd.functionId, previousFuncID == wkd.functionId) ); + previousFuncID = wkd.functionId; } } @@ -2839,12 +2841,15 @@ void NppParameters::feedShortcut(TiXmlNodeA *node) { //find the commandid that matches this Shortcut sc and alter it, push back its index in the modified list, if not present size_t len = _shortcuts.size(); - for (size_t i = 0; i < len; ++i) + bool isFound = false; + for (size_t i = 0; i < len, !isFound; ++i) { if (_shortcuts[i].getID() == (unsigned long)id) { //found our match - getShortcuts(childNode, _shortcuts[i]); - addUserModifiedIndex(i); + isFound = getInternalCommandShortcuts(childNode, _shortcuts[i]); + + if (isFound) + addUserModifiedIndex(i); } } } @@ -3031,6 +3036,52 @@ void NppParameters::feedScintKeys(TiXmlNodeA *node) } } +bool NppParameters::getInternalCommandShortcuts(TiXmlNodeA *node, CommandShortcut & cs, string* folderName) +{ + if (!node) return false; + + const char* name = (node->ToElement())->Attribute("name"); + if (!name) + name = ""; + + bool isCtrl = false; + const char* isCtrlStr = (node->ToElement())->Attribute("Ctrl"); + if (isCtrlStr) + isCtrl = (strcmp("yes", isCtrlStr) == 0); + + bool isAlt = false; + const char* isAltStr = (node->ToElement())->Attribute("Alt"); + if (isAltStr) + isAlt = (strcmp("yes", isAltStr) == 0); + + bool isShift = false; + const char* isShiftStr = (node->ToElement())->Attribute("Shift"); + if (isShiftStr) + isShift = (strcmp("yes", isShiftStr) == 0); + + int key; + const char* keyStr = (node->ToElement())->Attribute("Key", &key); + if (!keyStr) + return false; + + int nth = -1; // 0 based + const char* nthStr = (node->ToElement())->Attribute("nth", &nth); + if (nthStr && nth == 1) + { + if (cs.getNth() != nth) + return false; + } + + if (folderName) + { + const char* fn = (node->ToElement())->Attribute("FolderName"); + *folderName = fn ? fn : ""; + } + + cs = Shortcut(name, isCtrl, isAlt, isShift, static_cast(key)); + return true; +} + bool NppParameters::getShortcuts(TiXmlNodeA *node, Shortcut & sc, string* folderName) { if (!node) return false; @@ -3059,6 +3110,7 @@ bool NppParameters::getShortcuts(TiXmlNodeA *node, Shortcut & sc, string* folder if (!keyStr) return false; + if (folderName) { const char* fn = (node->ToElement())->Attribute("FolderName"); @@ -3458,6 +3510,8 @@ void NppParameters::insertCmd(TiXmlNodeA *shortcutsRoot, const CommandShortcut & sc->ToElement()->SetAttribute("Alt", key._isAlt?"yes":"no"); sc->ToElement()->SetAttribute("Shift", key._isShift?"yes":"no"); sc->ToElement()->SetAttribute("Key", key._key); + if (cmd.getNth() != 0) + sc->ToElement()->SetAttribute("nth", cmd.getNth()); } diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 4fce3886f..523a12c76 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -1603,7 +1603,6 @@ public: bool isRemappingShortcut() const {return _shortcuts.size() != 0;}; std::vector & getUserShortcuts() { return _shortcuts; }; - std::vector & getUserModifiedShortcuts() { return _customizedShortcuts; }; void addUserModifiedIndex(size_t index); std::vector & getMacroList() { return _macros; }; @@ -2017,6 +2016,7 @@ private: void getActions(TiXmlNodeA *node, Macro & macro); bool getShortcuts(TiXmlNodeA *node, Shortcut & sc, std::string* folderName = nullptr); + bool getInternalCommandShortcuts(TiXmlNodeA* node, CommandShortcut& cs, std::string* folderName = nullptr); void writeStyle2Element(const Style & style2Write, Style & style2Sync, TiXmlElement *element); void insertUserLang2Tree(TiXmlNode *node, UserLangContainer *userLang); diff --git a/PowerEditor/src/WinControls/shortcut/shortcut.cpp b/PowerEditor/src/WinControls/shortcut/shortcut.cpp index bd3ab2284..e5f95f2e2 100644 --- a/PowerEditor/src/WinControls/shortcut/shortcut.cpp +++ b/PowerEditor/src/WinControls/shortcut/shortcut.cpp @@ -1264,3 +1264,13 @@ void CommandShortcut::setCategoryFromMenu(HMENU hMenu) else pNativeSpeaker->getMainMenuEntryName(_category, hMenu, "run", L"Run"); } + +CommandShortcut& CommandShortcut::operator = (const Shortcut& sct) +{ + if (this != &sct) + { + strcpy(this->_name, sct.getName()); + this->_keyCombo = sct.getKeyCombo(); + } + return *this; +} diff --git a/PowerEditor/src/WinControls/shortcut/shortcut.h b/PowerEditor/src/WinControls/shortcut/shortcut.h index a7157e4e2..bd18d37e4 100644 --- a/PowerEditor/src/WinControls/shortcut/shortcut.h +++ b/PowerEditor/src/WinControls/shortcut/shortcut.h @@ -184,19 +184,26 @@ protected : class CommandShortcut : public Shortcut { public: - CommandShortcut(const Shortcut& sc, long id) : Shortcut(sc), _id(id){ + CommandShortcut(const Shortcut& sc, long id, bool isDuplicated = false) : Shortcut(sc), _id(id) { _shortcutName = string2wstring(getName(), CP_UTF8); + if (isDuplicated) _nth = 1; }; + + CommandShortcut& operator = (const Shortcut& sct); void setCategoryFromMenu(HMENU hMenu); unsigned long getID() const {return _id;}; void setID(unsigned long id) { _id = id;}; + int getNth() const { return _nth; }; const TCHAR * getCategory() const { return _category.c_str(); }; const TCHAR * getShortcutName() const { return _shortcutName.c_str(); }; private : - unsigned long _id; + unsigned long _id = 0; generic_string _category; generic_string _shortcutName; + int _nth = 0; // Allow several shortcuts for the same command (_id). + // If there is the 2nd identical command in winKeyDefs array, the value of _nth will be 1. + // This variable member allows the application to distinguish the different shortcuts assigned to the same command. };