diff options
Diffstat (limited to 'Src/omBrowser/toolbarEditbox.cpp')
-rw-r--r-- | Src/omBrowser/toolbarEditbox.cpp | 990 |
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); +} |