aboutsummaryrefslogtreecommitdiff
path: root/Src/omBrowser/toolbarEditbox.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/omBrowser/toolbarEditbox.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/omBrowser/toolbarEditbox.cpp')
-rw-r--r--Src/omBrowser/toolbarEditbox.cpp990
1 files changed, 990 insertions, 0 deletions
diff --git a/Src/omBrowser/toolbarEditbox.cpp b/Src/omBrowser/toolbarEditbox.cpp
new file mode 100644
index 00000000..e4940676
--- /dev/null
+++ b/Src/omBrowser/toolbarEditbox.cpp
@@ -0,0 +1,990 @@
+#define OEMRESOURCE
+
+#include "main.h"
+#include "./toolbarEditbox.h"
+#include "./menu.h"
+#include "./ifc_skinhelper.h"
+
+#include "../Plugins/General/gen_ml/ml_ipc_0313.h"
+
+#include <richedit.h>
+#include <strsafe.h>
+
+#define NTEF_USERFLAGSMASK 0x00FFFFFF
+#define NTEF_UNICODE 0x01000000
+#define NTEF_CLICKEDONCE 0x02000000
+#define NTEF_SHOWCURSOR 0x04000000
+#define NTEF_KEYDOWN 0x08000000
+#define NTEF_MENULOOP 0x10000000
+#define NTEF_SHOWCARET 0x20000000
+
+typedef struct __TOOLBAREDITBOX
+{
+ WNDPROC originalProc;
+ UINT flags;
+ ToolbarEditboxHost *host;
+ DWORD dblclkTime;
+} TOOLBAREDITBOX;
+
+static ATOM TOOLBAREDITBOX_PROP = 0;
+static HHOOK mouseHook = NULL;
+
+#define GetEditbox(__hwnd) ((TOOLBAREDITBOX*)GetProp((__hwnd), MAKEINTATOM(TOOLBAREDITBOX_PROP)))
+
+static LRESULT CALLBACK ToolbarEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static INT CALLBACK ToolbarEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
+static INT CALLBACK ToolbarEditbox_WordBreakProc2(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
+
+static void CALLBACK ToolbarEditbox_Uninitialize()
+{
+ if (0 != TOOLBAREDITBOX_PROP)
+ {
+ GlobalDeleteAtom(TOOLBAREDITBOX_PROP);
+ TOOLBAREDITBOX_PROP = 0;
+ }
+}
+
+
+BOOL ToolbarEditbox_AttachWindow(HWND hEditbox, ToolbarEditboxHost *host)
+{
+ if (!IsWindow(hEditbox))
+ return FALSE;
+
+ if (0 == TOOLBAREDITBOX_PROP)
+ {
+ TOOLBAREDITBOX_PROP = GlobalAddAtom(L"NullsoftToolbarEditBox");
+ if (0 == TOOLBAREDITBOX_PROP) return FALSE;
+ Plugin_RegisterUnloadCallback(ToolbarEditbox_Uninitialize);
+ }
+
+ TOOLBAREDITBOX *editbox = (TOOLBAREDITBOX*)GetProp(hEditbox, MAKEINTATOM(TOOLBAREDITBOX_PROP));
+ if (NULL != editbox) return TRUE;
+
+ editbox = (TOOLBAREDITBOX*)calloc(1, sizeof(TOOLBAREDITBOX));
+ if (NULL == editbox) return FALSE;
+
+
+ ifc_skinhelper *skinHelper = NULL;
+ if (SUCCEEDED(Plugin_GetSkinHelper(&skinHelper)))
+ {
+ // skinHelper->SkinControl(hEditbox, SKINNEDWND_TYPE_EDIT, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWES_BOTTOM);
+ skinHelper->Release();
+ }
+
+ ZeroMemory(editbox, sizeof(TOOLBAREDITBOX));
+
+ if (IsWindowUnicode(hEditbox))
+ editbox->flags |= NTEF_UNICODE;
+
+ editbox->host = host;
+
+ editbox->originalProc = (WNDPROC)(LONG_PTR)((0 != (NTEF_UNICODE & editbox->flags)) ?
+ SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ToolbarEditbox_WindowProc) :
+ SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ToolbarEditbox_WindowProc));
+
+ if (NULL == editbox->originalProc || !SetProp(hEditbox, MAKEINTATOM(TOOLBAREDITBOX_PROP), editbox))
+ {
+ if (NULL != editbox->originalProc)
+ {
+ if (0 != (NTEF_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;
+ }
+ SendMessage(hEditbox, EM_SETWORDBREAKPROC, 0, (LPARAM)ToolbarEditbox_WordBreakProc);
+ return TRUE;
+}
+
+static void ToolbarEditbox_PatchCursor()
+{
+ ShowCursor(FALSE);
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ ShowCursor(TRUE);
+
+ CURSORINFO cursorInfo;
+ cursorInfo.cbSize = sizeof(CURSORINFO);
+ if (GetCursorInfo(&cursorInfo) &&
+ 0 != (CURSOR_SHOWING & cursorInfo.flags))
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ HWND hTarget= WindowFromPoint(pt);
+ if (NULL != hTarget)
+ {
+ UINT hitTest = (UINT)SendMessage(hTarget, WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));
+ UINT uMsg = (HTCLIENT == hitTest) ? WM_MOUSEMOVE : WM_NCMOUSEMOVE;
+ SendMessage(hTarget, WM_SETCURSOR, (WPARAM)hTarget, MAKELPARAM(hitTest, uMsg));
+ }
+ }
+}
+
+
+static void ToolbarEditbox_Detach(HWND hwnd)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ RemoveProp(hwnd, MAKEINTATOM(TOOLBAREDITBOX_PROP));
+
+ ToolbarEditbox_PatchCursor();
+
+ if (NULL != editbox && 0 != (NTEF_SHOWCURSOR & editbox->flags))
+ {
+ ShowCursor(TRUE);
+ editbox->flags &= ~NTEF_SHOWCURSOR;
+ }
+
+ if (NULL != mouseHook)
+ {
+ UnhookWindowsHookEx(mouseHook);
+ mouseHook = NULL;
+ }
+
+ if (NULL == editbox)
+ return;
+
+ if (NULL != editbox->originalProc)
+ {
+ if (0 != (NTEF_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 ToolbarEditbox_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+
+ if (NULL == editbox || NULL == editbox->originalProc)
+ {
+ return (0 != (NTEF_UNICODE & editbox->flags)) ?
+ DefWindowProcW(hwnd, uMsg, wParam, lParam) :
+ DefWindowProcA(hwnd, uMsg, wParam, lParam);
+ }
+
+ return (0 != (NTEF_UNICODE & editbox->flags)) ?
+ CallWindowProcW(editbox->originalProc, hwnd, uMsg, wParam, lParam) :
+ CallWindowProcA(editbox->originalProc, hwnd, uMsg, wParam, lParam);
+}
+
+static void ToolbarEditbox_ResetText(HWND hwnd)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host)
+ editbox->host->EditboxResetText(hwnd);
+}
+
+static void ToolbarEditbox_NavigateNextCtrl(HWND hwnd, BOOL fForward)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host)
+ editbox->host->EditboxNavigateNextCtrl(hwnd, fForward);
+}
+
+static void ToolbarEditbox_AcceptText(HWND hwnd)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host)
+ editbox->host->EditboxAcceptText(hwnd);
+}
+
+static BOOL ToolbarEditbox_IsDelimiterChar(WCHAR testChar)
+{
+ WORD info;
+ if (FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &testChar, 1, &info))
+ return 0;
+
+ return (0 != ((C1_SPACE | C1_PUNCT | C1_CNTRL | C1_BLANK) & info));
+}
+
+static INT ToolbarEditbox_FindLeft(LPCWSTR pszText, INT iCurrent, INT cchLen)
+{
+ if (iCurrent <= 0)
+ return 0;
+
+ LPCWSTR pszCursor = &pszText[iCurrent];
+ BOOL charDelim = ToolbarEditbox_IsDelimiterChar(*pszCursor);
+
+ for(;;)
+ {
+ pszCursor = CharPrev(pszText, pszCursor);
+ if (charDelim != ToolbarEditbox_IsDelimiterChar(*pszCursor))
+ return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
+
+ if (pszCursor == pszText)
+ break;
+ }
+ return 0;
+}
+
+static INT ToolbarEditbox_FindRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
+{
+ if (iCurrent >= cchLen)
+ return cchLen;
+
+ LPCWSTR pszEnd = &pszText[cchLen];
+ LPCWSTR pszCursor = &pszText[iCurrent];
+
+ if (iCurrent > 0)
+ pszCursor = CharNext(pszCursor);
+
+ BOOL charDelim = ToolbarEditbox_IsDelimiterChar(*pszCursor);
+
+ for(;;)
+ {
+ pszCursor = CharNext(pszCursor);
+ if (pszCursor >= pszEnd)
+ break;
+
+ if (charDelim != ToolbarEditbox_IsDelimiterChar(*pszCursor))
+ return (INT)(INT_PTR)(pszCursor - pszText);
+ }
+ return cchLen;
+}
+
+static INT ToolbarEditbox_FindWordLeft(LPCWSTR pszText, INT iCurrent, INT cchLen, BOOL fRightCtrl)
+{
+ if (iCurrent < 2)
+ return 0;
+
+ LPCWSTR pszCursor = &pszText[iCurrent];
+
+ if (FALSE == fRightCtrl)
+ pszCursor = CharPrev(pszText, pszCursor);
+
+ BOOL prevCharDelim = ToolbarEditbox_IsDelimiterChar(*pszCursor);
+ for(;;)
+ {
+ pszCursor = CharPrev(pszText, pszCursor);
+ if (TRUE == ToolbarEditbox_IsDelimiterChar(*pszCursor))
+ {
+ if (FALSE == prevCharDelim)
+ return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
+
+ prevCharDelim = TRUE;
+ }
+ else
+ prevCharDelim = FALSE;
+
+ if (pszCursor == pszText)
+ break;
+ }
+ return 0;
+}
+
+static INT ToolbarEditbox_FindWordRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
+{
+ if ( iCurrent >= (cchLen - 1))
+ return cchLen;
+
+ LPCWSTR pszEnd = &pszText[cchLen];
+ LPCWSTR pszCursor = &pszText[iCurrent];
+
+ BOOL prevCharDelim = ToolbarEditbox_IsDelimiterChar(*pszCursor);
+
+ for(;;)
+ {
+ pszCursor = CharNext(pszCursor);
+ if (pszCursor >= pszEnd)
+ break;
+
+ if (prevCharDelim != ToolbarEditbox_IsDelimiterChar(*pszCursor))
+ {
+ prevCharDelim = TRUE;
+ return (INT)(INT_PTR)(pszCursor - pszText);
+ }
+ else
+ prevCharDelim = FALSE;
+
+ }
+ return cchLen;
+}
+
+static INT CALLBACK ToolbarEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
+{
+ switch(code)
+ {
+ case WB_ISDELIMITER: return (iCurrent < 0) ? 0 : ((iCurrent > cchLen) ? (cchLen + 1) : ToolbarEditbox_IsDelimiterChar(pszText[iCurrent]));
+ case WB_LEFT: return ToolbarEditbox_FindLeft(pszText, iCurrent, cchLen);
+ case WB_RIGHT: return ToolbarEditbox_FindRight(pszText, iCurrent, cchLen);
+ case WB_MOVEWORDLEFT: return ToolbarEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
+ case WB_MOVEWORDRIGHT: return ToolbarEditbox_FindWordRight(pszText, iCurrent, cchLen);
+ }
+ return 0;
+}
+
+static INT CALLBACK ToolbarEditbox_WordBreakProcOverrideLeft(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
+{
+ switch(code)
+ {
+ case WB_LEFT: return ToolbarEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
+ case WB_RIGHT: return ToolbarEditbox_FindWordRight(pszText, iCurrent, cchLen);
+ }
+ return ToolbarEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
+}
+
+static INT CALLBACK ToolbarEditbox_WordBreakProcOverrideRight(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
+{
+ switch(code)
+ {
+ case WB_LEFT: return ToolbarEditbox_FindWordLeft(pszText, iCurrent, cchLen, TRUE);
+ case WB_RIGHT: return ToolbarEditbox_FindWordRight(pszText, iCurrent, cchLen);
+ }
+ return ToolbarEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
+}
+
+
+static void ToolbarEditbox_OnDestroy(HWND hwnd)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host)
+ editbox->host->EditboxDestroyed(hwnd);
+
+ WNDPROC originalProc = (editbox ? editbox->originalProc : NULL);
+ BOOL fUnicode = (0 != (NTEF_UNICODE & editbox->flags));
+
+ ToolbarEditbox_Detach(hwnd);
+
+ if (NULL != originalProc)
+ {
+ if (FALSE != fUnicode)
+ CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
+ else
+ CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
+ }
+
+}
+
+static void ToolbarEditbox_OnSetFocus(HWND hwnd, HWND hFocus)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox)
+ {
+ editbox->flags &= ~NTEF_CLICKEDONCE;
+ }
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hFocus, 0L);
+}
+
+static void ToolbarEditbox_OnKillFocus(HWND hwnd, HWND hFocus)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host )
+ {
+ if (FALSE != editbox->host->EditboxKillFocus(hwnd, hFocus))
+ return;
+ }
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hFocus, 0L);
+}
+
+static LRESULT ToolbarEditbox_OnGetDlgCode(HWND hwnd, INT vKey, MSG* pMsg)
+{
+ LRESULT result = ToolbarEditbox_CallOrigWindowProc(hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)pMsg);
+ result |= DLGC_WANTALLKEYS;
+ result &= ~DLGC_HASSETSEL;
+ return result;
+}
+
+
+static LRESULT ToolbarEditbox_OnSetCursor(HWND hwnd, HWND hOwner, INT hitTest, INT messageId)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (HTCLIENT == hitTest &&
+ NULL != editbox && 0 == (NTEF_MENULOOP & editbox->flags))
+ {
+ HCURSOR hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(OCR_IBEAM), IMAGE_CURSOR,
+ 0, 0, LR_DEFAULTCOLOR | LR_SHARED | LR_DEFAULTSIZE);
+ if (NULL != hCursor)
+ {
+ SetCursor(hCursor);
+ return TRUE;
+ }
+ }
+
+ HWND hParent = GetParent(hwnd);
+ if (NULL != hParent &&
+ FALSE != (BOOL)SendMessage(hParent, WM_SETCURSOR, (WPARAM)hOwner, MAKELPARAM(hitTest, messageId)))
+ {
+ return TRUE;
+ }
+
+ return ToolbarEditbox_CallOrigWindowProc(hwnd, WM_SETCURSOR, (WPARAM)hOwner, MAKELPARAM(hitTest, messageId));
+}
+
+static void ToolbarEditbox_OnContextMenu(HWND hwnd, HWND hTarget, POINTS pts)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox) editbox->flags |= NTEF_MENULOOP;
+// SendMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE));
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_CONTEXTMENU, (WPARAM)hTarget, *((LPARAM*)&pts));
+ if (NULL != editbox) editbox->flags &= ~NTEF_MENULOOP;
+}
+
+static void ToolbarEditbox_OnLButtonDown(HWND hwnd, UINT vKey, POINTS pts)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox)
+ {
+ if (0 != (NTEF_SHOWCARET & editbox->flags))
+ {
+ editbox->flags &= ~NTEF_SHOWCARET;
+ ShowCaret(hwnd);
+ }
+
+
+ DWORD clickTime = GetTickCount();
+ if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + GetDoubleClickTime()))
+ {
+ SendMessage(hwnd, NTEBM_SELECTALL, 0, 0L);
+ return;
+ }
+
+ UINT start, end;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
+ if (start != end)
+ {
+ editbox->flags |= NTEF_CLICKEDONCE;
+ }
+ }
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDOWN, (WPARAM)vKey, *((LPARAM*)&pts));
+}
+
+static void ToolbarEditbox_OnLButtonUp(HWND hwnd, UINT vKey, POINTS pts)
+{
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONUP, (WPARAM)vKey, *((LPARAM*)&pts));
+
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && 0 == (NTEF_CLICKEDONCE & editbox->flags) && hwnd == GetFocus())
+ {
+ editbox->flags |= NTEF_CLICKEDONCE;
+ UINT start, end;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
+ if (start == end)
+ {
+ SendMessage(hwnd, NTEBM_SELECTALL, 0, 0L);
+ }
+ }
+}
+
+static void ToolbarEditbox_OnLButtonDblClk(HWND hwnd, UINT vKey, POINTS pts)
+{
+ TOOLBAREDITBOX *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;
+
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDBLCLK, (WPARAM)vKey, *((LPARAM*)&pts));
+
+}
+
+static void ToolbarEditbox_OnMouseMove(HWND hwnd, UINT vKey, POINTS pts)
+{
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_MOUSEMOVE, (WPARAM)vKey, *((LPARAM*)&pts));
+
+ if (0 != (MK_LBUTTON & vKey))
+ {
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && 0 == (NTEF_SHOWCARET & editbox->flags) &&
+ hwnd == GetFocus())
+ {
+ UINT start, end;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
+ if (start != end)
+ {
+ if (FALSE != HideCaret(hwnd))
+ editbox->flags |= NTEF_SHOWCARET;
+ }
+ }
+ }
+}
+
+static LRESULT CALLBACK ToolbarEditbox_MouseHook(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ ToolbarEditbox_PatchCursor();
+
+ TOOLBAREDITBOX *editbox = GetEditbox(GetFocus());
+ if (NULL != editbox && 0 != (NTEF_SHOWCURSOR & editbox->flags))
+ {
+ ShowCursor(TRUE);
+ editbox->flags &= ~NTEF_SHOWCURSOR;
+ }
+
+ LRESULT result = CallNextHookEx(mouseHook, nCode, wParam, lParam);
+ UnhookWindowsHookEx(mouseHook);
+ mouseHook = NULL;
+ return result;
+}
+
+static void ToolbarEditbox_DeleteWord(HWND hwnd, UINT vKey, UINT state)
+{
+ BOOL resetVisible = FALSE;
+ INT first, last;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&first, (LPARAM)&last);
+ if (first == last)
+ {
+ UINT windowStyle = GetWindowStyle(hwnd);
+ if (0 != (WS_VISIBLE & windowStyle))
+ {
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
+ resetVisible = TRUE;
+ }
+
+ SendMessage(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
+ INT newFirst, newLast;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&newFirst, (LPARAM)&newLast);
+ if (newFirst != first || newLast != last)
+ SendMessage(hwnd, EM_SETSEL, (WPARAM)first, (LPARAM)newLast);
+ }
+
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, NULL);
+ if (FALSE != resetVisible)
+ {
+ UINT windowStyle = GetWindowStyle(hwnd);
+ if (0 == (WS_VISIBLE & windowStyle))
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
+
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+
+}
+static void ToolbarEditbox_OnKeyDown(HWND hwnd, UINT vKey, UINT state)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox)
+ {
+ if (0 != (NTEF_SHOWCARET & editbox->flags))
+ {
+ editbox->flags &= ~NTEF_SHOWCARET;
+ ShowCaret(hwnd);
+ }
+
+ editbox->flags |= NTEF_KEYDOWN;
+
+ }
+
+
+ if (NULL == editbox || NULL == editbox->host ||
+ FALSE == editbox->host->EditboxKeyDown(hwnd, vKey, state))
+ {
+ EDITWORDBREAKPROC fnOrigBreak = NULL;
+ if(0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
+ {
+ switch(vKey)
+ {
+ case VK_LEFT:
+ case VK_RIGHT:
+ fnOrigBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
+ if (ToolbarEditbox_WordBreakProc == fnOrigBreak)
+ {
+ EDITWORDBREAKPROC fnOverride = (VK_LEFT == vKey) ?
+ ToolbarEditbox_WordBreakProcOverrideLeft : ToolbarEditbox_WordBreakProcOverrideRight;
+ SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOverride);
+ }
+ break;
+ case VK_DELETE:
+ ToolbarEditbox_DeleteWord(hwnd, VK_RIGHT, state);
+ return;
+ case VK_BACK:
+ ToolbarEditbox_DeleteWord(hwnd, VK_LEFT, state);
+ return;
+
+
+ }
+ }
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
+
+ if (NULL != fnOrigBreak)
+ SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOrigBreak);
+ }
+
+ if (('0' <= vKey && vKey <= '9') ||
+ ('A' <= vKey && vKey <= 'Z') ||
+ (VK_NUMPAD0 <= vKey && vKey <= VK_DIVIDE) ||
+ (VK_OEM_1 <= vKey && vKey <= VK_OEM_3) ||
+ (VK_OEM_4 <= vKey && vKey <= VK_OEM_8) ||
+ VK_OEM_NEC_EQUAL == vKey ||
+ VK_OEM_102 == vKey)
+ {
+ if (0 == (0x8000 & GetAsyncKeyState(VK_CONTROL)) &&
+ 0 == (0x8000 & GetAsyncKeyState(VK_MENU)))
+ {
+ PostMessage(hwnd, NTEBM_UPDATECURSOR, 0, 0L);
+ }
+ }
+
+}
+
+static void ToolbarEditbox_OnKeyUp(HWND hwnd, UINT vKey, UINT state)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL == editbox || NULL == editbox->host ||
+ FALSE == editbox->host->EditboxKeyUp(hwnd, vKey, state))
+ {
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_KEYUP, (WPARAM)vKey, (LPARAM)state);
+ }
+
+ if (NULL != editbox)
+ editbox->flags &= ~NTEF_KEYDOWN;
+
+ if (NULL == mouseHook)
+ {
+ mouseHook = SetWindowsHookEx(WH_MOUSE, ToolbarEditbox_MouseHook, NULL, GetCurrentThreadId());
+ }
+
+}
+
+static void ToolbarEditbox_OnChar(HWND hwnd, UINT vKey, UINT state)
+{
+ BOOL fControl = FALSE;
+ if (0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
+ {
+ fControl = TRUE;
+ UINT scanCode = (HIWORD(state) & 0x00FF);
+ vKey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
+ }
+
+ switch(vKey)
+ {
+ case VK_ESCAPE: ToolbarEditbox_ResetText(hwnd); return;
+ case VK_TAB: ToolbarEditbox_NavigateNextCtrl(hwnd, 0 == (0x8000 & GetAsyncKeyState(VK_SHIFT))); return;
+ case VK_RETURN: ToolbarEditbox_AcceptText(hwnd); return;
+ }
+
+ if (FALSE != fControl)
+ {
+ switch(vKey)
+ {
+ case 'A': SendMessage(hwnd, NTEBM_SELECTALL, 0, 0L); return;
+ case 'Z': SendMessage(hwnd, EM_UNDO, 0, 0L); return;
+ case 'X': SendMessage(hwnd, WM_CUT, 0, 0L); return;
+ case 'C': SendMessage(hwnd, WM_COPY, 0, 0L); return;
+ case 'V': SendMessage(hwnd, WM_PASTE, 0, 0L); return;
+ }
+ return;
+ }
+
+
+
+
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && NULL != editbox->host &&
+ FALSE != editbox->host->EditboxPreviewChar(hwnd, vKey, state))
+ {
+ return;
+ }
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_CHAR, (WPARAM)vKey, (LPARAM)state);
+}
+
+
+static void ToolbarEditbox_OnUpdateCursor(HWND hwnd)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox && 0 != (NTEF_KEYDOWN & editbox->flags))
+ {
+ if (NULL != mouseHook)
+ {
+ UnhookWindowsHookEx(mouseHook);
+ mouseHook = NULL;
+ }
+
+ if (0 == (NTEF_SHOWCURSOR & editbox->flags))
+ {
+ CURSORINFO cursorInfo;
+ cursorInfo.cbSize = sizeof(CURSORINFO);
+ if (GetCursorInfo(&cursorInfo) && 0 != (CURSOR_SHOWING & cursorInfo.flags))
+ {
+ ShowCursor(FALSE);
+ editbox->flags |= NTEF_SHOWCURSOR;
+ }
+ }
+ }
+}
+
+static void ToolbarEditbox_OnEnterMenuLoop(HWND hwnd, BOOL fContext)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox) editbox->flags |= NTEF_MENULOOP;
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_ENTERMENULOOP, (WPARAM)fContext, 0L);
+}
+
+static void ToolbarEditbox_OnExitMenuLoop(HWND hwnd, BOOL fContext)
+{
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox) editbox->flags &= ~NTEF_MENULOOP;
+
+ ToolbarEditbox_CallOrigWindowProc(hwnd, WM_EXITMENULOOP, (WPARAM)fContext, 0L);
+}
+
+static BOOL ToolbarEditbox_RemoveBadChars(LPCWSTR pszText, LPWSTR *bufferOut)
+{
+ LPWSTR buffer = NULL;
+ if (NULL == pszText) return FALSE;
+
+ const WCHAR szBadChars[] = { L'\r', L'\n', L'\t', L'\0'};
+ BOOL fDetected = FALSE;
+
+ for (LPCWSTR p = pszText; L'\0' != *p && FALSE == fDetected; p++)
+ {
+ for (LPCWSTR b = szBadChars; L'\0' != *b; b++)
+ {
+ if (*p == *b)
+ {
+ fDetected = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (FALSE == fDetected)
+ return FALSE;
+
+ if (NULL == bufferOut)
+ return TRUE;
+
+ INT cchText = lstrlen(pszText);
+ buffer = Plugin_MallocString(cchText + 1);
+ if (NULL == buffer) return FALSE;
+
+ LPCWSTR s = pszText;
+ LPWSTR d = buffer;
+ LPCWSTR b;
+ for(;;)
+ {
+ for (b = szBadChars; L'\0' != *b && *s != *b; b++);
+ if(L'\0' != *b)
+ {
+ if (L'\t' == *b)
+ {
+ *d = L' ';
+ d++;
+ }
+ }
+ else
+ {
+ *d = *s;
+ d++;
+ }
+
+ if (L'\0' == *s)
+ break;
+
+ s++;
+
+ }
+
+ *bufferOut = buffer;
+ return TRUE;
+}
+
+static LRESULT ToolbarEditbox_OnSetText(HWND hwnd, LPCWSTR pszText)
+{
+ LPWSTR buffer;
+ if (FALSE == ToolbarEditbox_RemoveBadChars(pszText, &buffer))
+ buffer = NULL;
+ else
+ pszText = buffer;
+
+ LRESULT result = ToolbarEditbox_CallOrigWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
+
+ if (NULL != buffer)
+ Plugin_FreeString(buffer);
+
+ return result;
+}
+
+static LRESULT ToolbarEditbox_OnReplaceSel(HWND hwnd, BOOL fUndo, LPCWSTR pszText)
+{
+ LPWSTR buffer;
+ if (FALSE == ToolbarEditbox_RemoveBadChars(pszText, &buffer))
+ buffer = NULL;
+ else
+ pszText = buffer;
+
+ LRESULT result = ToolbarEditbox_CallOrigWindowProc(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
+
+ if (NULL != buffer)
+ Plugin_FreeString(buffer);
+
+ return result;
+}
+
+static void ToolbarEditbox_ReplaceText(HWND hwnd, LPCWSTR pszText, BOOL fUndo, BOOL fScrollCaret)
+{
+ UINT windowStyle = GetWindowStyle(hwnd);
+ if (0 != (WS_VISIBLE & windowStyle))
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
+
+ SendMessage(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
+ if (FALSE != fScrollCaret)
+ {
+ INT f, l;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
+ SendMessage(hwnd, EM_SETSEL, (WPARAM)f, (LPARAM)l);
+ }
+
+ if (0 != (WS_VISIBLE & windowStyle))
+ {
+ windowStyle = GetWindowStyle(hwnd);
+ if (0 == (WS_VISIBLE & windowStyle))
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+}
+
+static void ToolbarEditbox_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);
+ ToolbarEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
+ 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 = Plugin_MultiByteToWideChar(CP_ACP, 0, pClipboardAnsi, -1);
+ ToolbarEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
+ Plugin_FreeString(pClipboard);
+ GlobalUnlock(stgm.hGlobal);
+ ReleaseStgMedium(&stgm);
+ }
+ }
+ pObject->Release();
+ }
+}
+
+
+static void ToolbarEditbox_OnSelectAll(HWND hwnd)
+{
+ UINT windowStyle = GetWindowStyle(hwnd);
+
+ INT f, l, tl;
+ tl = GetWindowTextLength(hwnd);
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
+ if (f == 0 && tl == l)
+ return;
+
+ if (0 != (WS_VISIBLE & windowStyle))
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
+
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+ SetWindowPos(hwnd, NULL, 0, 0, 0xFFFFF, rc.bottom - rc.top,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS);
+
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+
+ SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS);
+
+ if (0 != (WS_VISIBLE & windowStyle))
+ {
+ UINT windowStyle = GetWindowStyle(hwnd);
+ if (0 == (WS_VISIBLE & windowStyle))
+ {
+ SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+ }
+
+ TOOLBAREDITBOX *editbox = GetEditbox(hwnd);
+ if (NULL != editbox &&
+ 0 == (NTEF_SHOWCARET & editbox->flags) &&
+ FALSE != HideCaret(hwnd))
+ {
+ editbox->flags |= NTEF_SHOWCARET;
+ }
+}
+
+
+
+static LRESULT ToolbarEditbox_OnFindWordBreak(HWND hwnd, INT code, INT start)
+{
+ EDITWORDBREAKPROC fnBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
+ if (NULL == fnBreak) return 0;
+
+ UINT cchText = GetWindowTextLength(hwnd);
+ if (0 == cchText) return 0;
+
+ LPWSTR pszText = Plugin_MallocString(cchText + 1);
+ if (NULL == pszText) return 0;
+
+ LRESULT result = 0;
+ cchText = GetWindowText(hwnd, pszText, cchText + 1);
+ if (0 != cchText)
+ {
+ result = fnBreak(pszText, start, cchText, code);
+ }
+ Plugin_FreeString(pszText);
+ return result;
+}
+
+static LRESULT CALLBACK ToolbarEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_DESTROY: ToolbarEditbox_OnDestroy(hwnd); return 0;
+ case WM_SETFOCUS: ToolbarEditbox_OnSetFocus(hwnd, (HWND)wParam); return 0;
+ case WM_KILLFOCUS: ToolbarEditbox_OnKillFocus(hwnd, (HWND)wParam); return 0;
+ case WM_GETDLGCODE: return ToolbarEditbox_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam);
+ case WM_SETCURSOR: return ToolbarEditbox_OnSetCursor(hwnd, (HWND)wParam, (INT)LOWORD(lParam), (INT)HIWORD(lParam));
+ case WM_CONTEXTMENU: ToolbarEditbox_OnContextMenu(hwnd, (HWND)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_LBUTTONDOWN: ToolbarEditbox_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_LBUTTONUP: ToolbarEditbox_OnLButtonUp(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_LBUTTONDBLCLK: ToolbarEditbox_OnLButtonDblClk(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_MOUSEMOVE: ToolbarEditbox_OnMouseMove(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
+ case WM_KEYDOWN: ToolbarEditbox_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam); return 0;
+ case WM_KEYUP: ToolbarEditbox_OnKeyUp(hwnd, (UINT)wParam, (UINT)lParam); return 0;
+ case WM_CHAR: ToolbarEditbox_OnChar(hwnd, (UINT)wParam, (UINT)lParam); return 0;
+ case WM_ENTERMENULOOP: ToolbarEditbox_OnEnterMenuLoop(hwnd, (BOOL)wParam); return 0;
+ case WM_EXITMENULOOP: ToolbarEditbox_OnExitMenuLoop(hwnd, (BOOL)wParam); return 0;
+ case WM_SETTEXT: return ToolbarEditbox_OnSetText(hwnd, (LPCWSTR)lParam);
+ case WM_PASTE: ToolbarEditbox_OnPaste(hwnd); return 1;
+ case EM_REPLACESEL: ToolbarEditbox_OnReplaceSel(hwnd, (BOOL)wParam, (LPCWSTR)lParam); return 0;
+ case EM_FINDWORDBREAK: return ToolbarEditbox_OnFindWordBreak(hwnd, (INT)wParam, (INT)lParam);
+
+ case NTEBM_UPDATECURSOR: ToolbarEditbox_OnUpdateCursor(hwnd); return 0;
+ case NTEBM_SELECTALL: ToolbarEditbox_OnSelectAll(hwnd); return 0;
+ }
+
+ return ToolbarEditbox_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
+}