aboutsummaryrefslogtreecommitdiff
path: root/Src/auth/Loginbox/editboxExtender.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/auth/Loginbox/editboxExtender.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/auth/Loginbox/editboxExtender.cpp')
-rw-r--r--Src/auth/Loginbox/editboxExtender.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/Src/auth/Loginbox/editboxExtender.cpp b/Src/auth/Loginbox/editboxExtender.cpp
new file mode 100644
index 00000000..0588c22a
--- /dev/null
+++ b/Src/auth/Loginbox/editboxExtender.cpp
@@ -0,0 +1,269 @@
+#include "./editboxExtender.h"
+#include "./common.h"
+
+#include <commctrl.h>
+
+#define NAEF_USERFLAGSMASK 0x00FFFFFF
+#define NAEF_UNICODE 0x01000000
+
+typedef struct __EDITBOXEXTENDER
+{
+ WNDPROC originalProc;
+ UINT flags;
+ DWORD dblclkTime;
+ LPWSTR rollbackText;
+} EDITBOXEXTENDER;
+
+#define EDITBOXEXTENDER_PROP L"NullsoftEditboxExtender"
+
+#define GetEditbox(__hwnd) ((EDITBOXEXTENDER*)GetProp((__hwnd), EDITBOXEXTENDER_PROP))
+
+static LRESULT CALLBACK EditboxExtender_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL EditboxExtender_AttachWindow(HWND hEditbox)
+{
+ if (!IsWindow(hEditbox))
+ return FALSE;
+
+ EDITBOXEXTENDER *editbox = (EDITBOXEXTENDER*)GetProp(hEditbox, EDITBOXEXTENDER_PROP);
+ if (NULL != editbox) return TRUE;
+
+ editbox = (EDITBOXEXTENDER*)calloc(1, sizeof(EDITBOXEXTENDER));
+ if (NULL == editbox) return FALSE;
+
+ if (IsWindowUnicode(hEditbox))
+ editbox->flags |= NAEF_UNICODE;
+
+ editbox->originalProc = (WNDPROC)(LONG_PTR)((0 != (NAEF_UNICODE & editbox->flags)) ?
+ SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditboxExtender_WindowProc) :
+ SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditboxExtender_WindowProc));
+
+ if (NULL == editbox->originalProc || !SetProp(hEditbox, EDITBOXEXTENDER_PROP, editbox))
+ {
+ if (NULL != editbox->originalProc)
+ {
+ if (0 != (NAEF_UNICODE & editbox->flags))
+ SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
+ else
+ SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
+ }
+
+ free(editbox);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+static void EditboxExtender_Detach(HWND hwnd)
+{
+ EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
+ RemoveProp(hwnd, EDITBOXEXTENDER_PROP);
+
+ if (NULL == editbox)
+ return;
+
+ if (NULL != editbox->originalProc)
+ {
+ if (0 != (NAEF_UNICODE & editbox->flags))
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
+ else
+ SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
+ }
+ free(editbox);
+}
+
+
+static LRESULT EditboxExtender_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
+
+ if (NULL == editbox || NULL == editbox->originalProc)
+ {
+ return (0 != (NAEF_UNICODE & editbox->flags)) ?
+ DefWindowProcW(hwnd, uMsg, wParam, lParam) :
+ DefWindowProcA(hwnd, uMsg, wParam, lParam);
+ }
+
+ return (0 != (NAEF_UNICODE & editbox->flags)) ?
+ CallWindowProcW(editbox->originalProc, hwnd, uMsg, wParam, lParam) :
+ CallWindowProcA(editbox->originalProc, hwnd, uMsg, wParam, lParam);
+}
+
+static void EditboxExtender_OnDestroy(HWND hwnd)
+{
+ EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
+
+ WNDPROC originalProc = editbox->originalProc;
+ BOOL fUnicode = (0 != (NAEF_UNICODE & editbox->flags));
+
+ EditboxExtender_Detach(hwnd);
+
+ if (NULL != originalProc)
+ {
+ if (FALSE != fUnicode)
+ CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
+ else
+ CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
+ }
+}
+
+static LRESULT EditboxExtender_OnGetDlgCode(HWND hwnd, INT vKey, MSG* pMsg)
+{
+ LRESULT result = EditboxExtender_CallOrigWindowProc(hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)pMsg);
+ return result;
+}
+
+static void EditboxExtender_OnLButtonDown(HWND hwnd, UINT vKey, POINTS pts)
+{
+ EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
+ if (NULL != editbox)
+ {
+ DWORD clickTime = GetTickCount();
+ if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + GetDoubleClickTime()))
+ {
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return;
+ }
+ }
+ EditboxExtender_CallOrigWindowProc(hwnd, WM_LBUTTONDOWN, (WPARAM)vKey, *((LPARAM*)&pts));
+}
+
+static void EditboxExtender_OnLButtonDblClk(HWND hwnd, UINT vKey, POINTS pts)
+{
+ EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
+ if (NULL == editbox) return;
+
+ DWORD clickTime = GetTickCount();
+ if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + 2*GetDoubleClickTime()))
+ {
+ INT r = (INT)SendMessage(hwnd, EM_CHARFROMPOS, 0, *(LPARAM*)&pts);
+ r = LOWORD(r);
+ SendMessage(hwnd, EM_SETSEL, (WPARAM)r, (LPARAM)r);
+ editbox->dblclkTime = 0;
+ }
+ else
+ {
+ editbox->dblclkTime = clickTime;
+ }
+
+ INT f, l;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
+ if (f != l) return;
+
+
+ EditboxExtender_CallOrigWindowProc(hwnd, WM_LBUTTONDBLCLK, (WPARAM)vKey, *((LPARAM*)&pts));
+
+}
+
+static void EditboxExtender_OnChar(HWND hwnd, UINT vKey, UINT state)
+{
+ if (0 == (0x8000 & GetAsyncKeyState(VK_CONTROL)) && 0 == (0x8000 & GetAsyncKeyState(VK_MENU)))
+ {
+ HWND hParent = GetAncestor(hwnd, GA_PARENT);
+ if (NULL != hParent)
+ {
+ NMCHAR nmh;
+ nmh.hdr.hwndFrom = hwnd;
+ nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
+ nmh.hdr.code = NM_CHAR;
+ nmh.ch = vKey;
+ nmh.dwItemNext = 0;
+ nmh.dwItemPrev = 0;
+ if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
+ return;
+ }
+ }
+ EditboxExtender_CallOrigWindowProc(hwnd, WM_CHAR, (WPARAM)vKey, (LPARAM)state);
+}
+
+static void EditboxExtender_OnKeyDown(HWND hwnd, UINT vKey, UINT state)
+{
+ HWND hParent = GetAncestor(hwnd, GA_PARENT);
+ if (NULL != hParent)
+ {
+ NMKEY nmh;
+ nmh.hdr.hwndFrom = hwnd;
+ nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
+ nmh.hdr.code = NM_KEYDOWN;
+ nmh.nVKey = vKey;
+ nmh.uFlags = HIWORD(state);
+ if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
+ return;
+ }
+
+ EditboxExtender_CallOrigWindowProc(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
+}
+
+static void EditboxExtender_PasteText(HWND hwnd, LPCWSTR pszClipboard)
+{
+ HWND hParent = GetAncestor(hwnd, GA_PARENT);
+ if (NULL != hParent)
+ {
+ EENMPASTE nmh;
+ nmh.hdr.hwndFrom = hwnd;
+ nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
+ nmh.hdr.code = EENM_PASTE;
+ nmh.text = pszClipboard;
+ if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
+ return;
+ }
+
+ SendMessage(hwnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)pszClipboard);
+}
+
+static void EditboxExtender_OnPaste(HWND hwnd)
+{
+ IDataObject *pObject;
+ HRESULT hr = OleGetClipboard(&pObject);
+ if (SUCCEEDED(hr))
+ {
+ FORMATETC fmt = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ STGMEDIUM stgm;
+ hr = pObject->GetData(&fmt, &stgm);
+ if(S_OK == hr)
+ {
+ LPCWSTR pClipboard = (LPCWSTR)GlobalLock(stgm.hGlobal);
+ EditboxExtender_PasteText(hwnd, pClipboard);
+
+ GlobalUnlock(stgm.hGlobal);
+ ReleaseStgMedium(&stgm);
+
+ }
+ else
+ {
+ fmt.cfFormat = CF_TEXT;
+ hr = pObject->GetData(&fmt, &stgm);
+ if(S_OK == hr)
+ {
+ LPCSTR pClipboardAnsi = (LPCSTR)GlobalLock(stgm.hGlobal);
+ LPWSTR pClipboard;
+ if (FAILED(LoginBox_MultiByteToWideChar(CP_ACP, 0, pClipboardAnsi, -1, &pClipboard)))
+ pClipboard = NULL;
+
+ EditboxExtender_PasteText(hwnd, pClipboard);
+
+ LoginBox_FreeString(pClipboard);
+ GlobalUnlock(stgm.hGlobal);
+ ReleaseStgMedium(&stgm);
+ }
+ }
+ pObject->Release();
+ }
+}
+
+static LRESULT CALLBACK EditboxExtender_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_DESTROY: EditboxExtender_OnDestroy(hwnd); return 0;
+ case WM_GETDLGCODE: return EditboxExtender_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam);
+ case WM_LBUTTONDOWN: EditboxExtender_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_LBUTTONDBLCLK: EditboxExtender_OnLButtonDblClk(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_CHAR: EditboxExtender_OnChar(hwnd, (UINT)wParam, (UINT)lParam); return 0;
+ case WM_KEYDOWN: EditboxExtender_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam); return 0;
+ case WM_PASTE: EditboxExtender_OnPaste(hwnd); return 1;
+ }
+
+ return EditboxExtender_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
+}