From 3ebe29dbf2ac516dc32523580f2adcd75972719d Mon Sep 17 00:00:00 2001 From: Microeinstein Date: Sat, 2 Feb 2019 09:44:41 -0500 Subject: [PATCH] Add support for any keyboard layout. Closes #1, Closes #2, Closes #3, Closes #5 --- README.md | 6 ++-- src/Main.cpp | 88 +++++++++++++++++++++++++++------------------------ src/Version.h | 8 ++--- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 15e5d19..e9de454 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,17 @@ Notepad++ plugin to automatically surround the selection in quotes/brackets/parenthesis/etc. This can also be used on multiple or rectangular selections. -**Note:** This is still in early development. It has not been fully tested with non-US keyboard layouts. - ![Demo](/img/Demo.gif) ## Usage Select some text and type one of the following characters: - `'` - `"` +- `` ` `` - `(` or `)` -- `{` or `}` - `[` or `]` +- `{` or `}` +- `<` or `>` ## Installation Install the plugin by downloading it from the [Release](https://github.com/dail8859/SurroundSelection/releases) page and copy `SurroundSelection.dll` to your `plugins` folder. diff --git a/src/Main.cpp b/src/Main.cpp index 00824c7..22e0148 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -24,11 +24,16 @@ #include #include +#define buffChars 1 + static HANDLE _hModule; static NppData nppData; static HHOOK hook = NULL; +static HKL keyboardLayout = NULL; static bool hasFocus = true; static ScintillaGateway editor; +static LPWORD kbBuff = (LPWORD)new byte[buffChars]; +static PBYTE kbState = new byte[256]; static void enableSurroundSelection(); static void showAbout(); @@ -52,6 +57,10 @@ const wchar_t *GetIniFilePath() { return iniPath; } +static void updateKL() { + keyboardLayout = GetKeyboardLayout(0); +} + static void enableSurroundSelection() { if (hook) { UnhookWindowsHookEx(hook); @@ -117,49 +126,41 @@ static void SurroundSelectionsWith(char ch1, char ch2) { } LRESULT CALLBACK KeyboardProc(int ncode, WPARAM wparam, LPARAM lparam) { - if (ncode == HC_ACTION) { - if ((HIWORD(lparam) & KF_UP) == 0) { - if (hasFocus && !(GetKeyState(VK_CONTROL) & KF_UP) && !(GetKeyState(VK_MENU) & KF_UP)) { - char ch1 = 0, ch2 = 0; - - if (wparam == VK_OEM_7) { - if (GetKeyState(VK_SHIFT) & KF_UP) { - ch1 = ch2 = '"'; - } - else { - ch1 = ch2 = '\''; - } - } - else if (wparam == VK_OEM_4 || wparam == VK_OEM_6) { - if (GetKeyState(VK_SHIFT) & KF_UP) { - ch1 = '{'; - ch2 = '}'; - } - else { - ch1 = '['; - ch2 = ']'; - } - } - else if (wparam == 0x39 || wparam == 0x30) { - if (GetKeyState(VK_SHIFT) & KF_UP) { - ch1 = '('; - ch2 = ')'; - } - } - //else if (wparam == VK_OEM_COMMA) { - // if (GetKeyState(VK_SHIFT) & KF_UP) { - // ch1 = '<'; - // ch2 = '>'; - // } - //} - - if (ch1 != 0 && editor.GetSelectionEmpty() == 0) { - SurroundSelectionsWith(ch1, ch2); - return TRUE; // This key has been "handled" and won't propogate - } - } - } + if (ncode != HC_ACTION) + goto proceed; + if ((HIWORD(lparam) & KF_UP) != 0 || !hasFocus) + goto proceed; + + char ch1 = 0, ch2 = 0; + UINT scanCode = (lparam >> 16) & 0xFF; + //Get full keyboard state + if (!GetKeyboardState(kbState)) + goto proceed; + //Translate state, pressed key and keyboard layout in the respective characters + int amount = ToAsciiEx((UINT)wparam, scanCode, kbState, kbBuff, 0, keyboardLayout); + if (amount < 1) + goto proceed; + + //Get first translated character + char ch = (char)kbBuff[0]; + if (ch == '"' || ch == '\'' || ch == '`') { + ch1 = ch2 = (char)ch; + } else if (ch == '(' || ch == ')') { + ch1 = '('; ch2 = ')'; + } else if (ch == '[' || ch == ']') { + ch1 = '['; ch2 = ']'; + } else if (ch == '{' || ch == '}') { + ch1 = '{'; ch2 = '}'; + } else if (ch == '<' || ch == '>') { + ch1 = '<'; ch2 = '>'; + } + + if (ch1 != 0 && editor.GetSelectionEmpty() == 0) { + SurroundSelectionsWith(ch1, ch2); + return TRUE; // This key has been "handled" and won't propogate } + + proceed: return CallNextHookEx(hook, ncode, wparam, lparam); //pass control to next hook in the hook chain. } @@ -168,6 +169,7 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD reasonForCall, LPVOID lpReserved) { switch (reasonForCall) { case DLL_PROCESS_ATTACH: _hModule = hModule; + updateKL(); break; case DLL_PROCESS_DETACH: break; @@ -224,6 +226,8 @@ extern "C" __declspec(dllexport) void beNotified(SCNotification *notifyCode) { } extern "C" __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam) { + if (Message == WM_INPUTLANGCHANGE) + updateKL(); return TRUE; } diff --git a/src/Version.h b/src/Version.h index 725592a..b81fa27 100644 --- a/src/Version.h +++ b/src/Version.h @@ -16,8 +16,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -#define VERSION_NUM 1,1,0,0 -#define VERSION_LINEAR 1100 -#define VERSION_LINEAR_TEXT TEXT("1100") -#define VERSION_TEXT TEXT("1.1") // This must match the tag pushed on the server minus the "v" +#define VERSION_NUM 1,2,0,0 +#define VERSION_LINEAR 1200 +#define VERSION_LINEAR_TEXT TEXT("1200") +#define VERSION_TEXT TEXT("1.2") // This must match the tag pushed on the server minus the "v" #define VERSION_STAGE TEXT("") // "alpha", "beta", ""