diff options
-rw-r--r-- | win32/ScintillaWin.cxx | 932 |
1 files changed, 521 insertions, 411 deletions
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 4ed03c787..f95b89ab7 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -421,6 +421,16 @@ class ScintillaWin : void ChangeScrollPos(int barType, Sci::Position pos); sptr_t GetTextLength(); sptr_t GetText(uptr_t wParam, sptr_t lParam); + Window::Cursor ContextCursor(); + sptr_t ShowContextMenu(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + void SizeWindow(); + sptr_t MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t KeyMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t FocusMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t IMEMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t EditMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t IdleMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + sptr_t SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); public: ~ScintillaWin() override; @@ -1315,6 +1325,492 @@ sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) { } } +Window::Cursor ScintillaWin::ContextCursor() { + if (inDragDrop == ddDragging) { + return Window::cursorUp; + } else { + // Display regular (drag) cursor over selection + POINT pt; + if (0 != ::GetCursorPos(&pt)) { + ::ScreenToClient(MainHWND(), &pt); + if (PointInSelMargin(PointFromPOINT(pt))) { + return GetMarginCursor(PointFromPOINT(pt)); + } else if (PointInSelection(PointFromPOINT(pt)) && !SelectionEmpty()) { + return Window::cursorArrow; + } else if (PointIsHotspot(PointFromPOINT(pt))) { + return Window::cursorHand; + } + } + } + return Window::cursorText; +} + +sptr_t ScintillaWin::ShowContextMenu(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + Point pt = PointFromLParam(lParam); + POINT rpt = { static_cast<int>(pt.x), static_cast<int>(pt.y) }; + ::ScreenToClient(MainHWND(), &rpt); + const Point ptClient = PointFromPOINT(rpt); + if (ShouldDisplayPopup(ptClient)) { + if ((pt.x == -1) && (pt.y == -1)) { + // Caused by keyboard so display menu near caret + pt = PointMainCaret(); + POINT spt = POINTFromPoint(pt); + ::ClientToScreen(MainHWND(), &spt); + pt = PointFromPOINT(spt); + } + ContextMenu(pt); + return 0; + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); +} + +void ScintillaWin::SizeWindow() { +#if defined(USE_D2D) + if (paintState == notPainting) { + DropRenderTarget(); + } else { + renderTargetValid = false; + } +#endif + //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam)); + ChangeSize(); +} + +sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + case WM_LBUTTONDOWN: { + // For IME, set the composition string as the result string. + IMContext imc(MainHWND()); + if (imc.hIMC) { + ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); + } + // + //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam, + // KeyboardIsKeyDown(VK_SHIFT), + // KeyboardIsKeyDown(VK_CONTROL), + // KeyboardIsKeyDown(VK_MENU)); + ::SetFocus(MainHWND()); + ButtonDownWithModifiers(PointFromLParam(lParam), ::GetMessageTime(), + MouseModifiers(wParam)); + } + break; + + case WM_LBUTTONUP: + ButtonUpWithModifiers(PointFromLParam(lParam), + ::GetMessageTime(), MouseModifiers(wParam)); + break; + + case WM_RBUTTONDOWN: { + ::SetFocus(MainHWND()); + const Point pt = PointFromLParam(lParam); + if (!PointInSelection(pt)) { + CancelModes(); + SetEmptySelection(PositionFromLocation(PointFromLParam(lParam))); + } + + RightButtonDownWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam)); + } + break; + + case WM_MOUSEMOVE: { + const Point pt = PointFromLParam(lParam); + + // Windows might send WM_MOUSEMOVE even though the mouse has not been moved: + // http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx + if (ptMouseLast != pt) { + SetTrackMouseLeaveEvent(true); + ButtonMoveWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam)); + } + } + break; + + case WM_MOUSELEAVE: + SetTrackMouseLeaveEvent(false); + MouseLeave(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_MOUSEWHEEL: + if (!mouseWheelCaptures) { + // if the mouse wheel is not captured, test if the mouse + // pointer is over the editor window and if not, don't + // handle the message but pass it on. + RECT rc; + GetWindowRect(MainHWND(), &rc); + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + if (!PtInRect(&rc, pt)) + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + // if autocomplete list active then send mousewheel message to it + if (ac.Active()) { + HWND hWnd = static_cast<HWND>(ac.lb->GetID()); + ::SendMessage(hWnd, iMessage, wParam, lParam); + break; + } + + // Don't handle datazoom. + // (A good idea for datazoom would be to "fold" or "unfold" details. + // i.e. if datazoomed out only class structures are visible, when datazooming in the control + // structures appear, then eventually the individual statements...) + if (wParam & MK_SHIFT) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + // Either SCROLL or ZOOM. We handle the wheel steppings calculation + wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam); + if (std::abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) { + Sci::Line linesToScroll = linesPerScroll; + if (linesPerScroll == WHEEL_PAGESCROLL) + linesToScroll = LinesOnScreen() - 1; + if (linesToScroll == 0) { + linesToScroll = 1; + } + linesToScroll *= (wheelDelta / WHEEL_DELTA); + if (wheelDelta >= 0) + wheelDelta = wheelDelta % WHEEL_DELTA; + else + wheelDelta = -(-wheelDelta % WHEEL_DELTA); + + if (wParam & MK_CONTROL) { + // Zoom! We play with the font sizes in the styles. + // Number of steps/line is ignored, we just care if sizing up or down + if (linesToScroll < 0) { + KeyCommand(SCI_ZOOMIN); + } else { + KeyCommand(SCI_ZOOMOUT); + } + } else { + // Scroll + ScrollTo(topLine + linesToScroll); + } + } + return 0; + } + return 0; +} + +sptr_t ScintillaWin::KeyMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + // Platform::DebugPrintf("Keydown %c %c%c%c%c %x %x\n", + // iMessage == WM_KEYDOWN ? 'K' : 'S', + // (lParam & (1 << 24)) ? 'E' : '-', + // KeyboardIsKeyDown(VK_SHIFT) ? 'S' : '-', + // KeyboardIsKeyDown(VK_CONTROL) ? 'C' : '-', + // KeyboardIsKeyDown(VK_MENU) ? 'A' : '-', + // wParam, lParam); + lastKeyDownConsumed = false; + const bool altDown = KeyboardIsKeyDown(VK_MENU); + if (altDown && KeyboardIsNumericKeypadFunction(wParam, lParam)) { + // Don't interpret these as they may be characters entered by number. + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + const int ret = KeyDownWithModifiers(KeyTranslate(static_cast<int>(wParam)), + ModifierFlags(KeyboardIsKeyDown(VK_SHIFT), + KeyboardIsKeyDown(VK_CONTROL), + altDown), + &lastKeyDownConsumed); + if (!ret && !lastKeyDownConsumed) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + break; + } + + case WM_KEYUP: + //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_CHAR: + if (((wParam >= 128) || !iscntrl(static_cast<int>(wParam))) || !lastKeyDownConsumed) { + wchar_t wcs[3] = { static_cast<wchar_t>(wParam), 0 }; + unsigned int wclen = 1; + if (IS_HIGH_SURROGATE(wcs[0])) { + // If this is a high surrogate character, we need a second one + lastHighSurrogateChar = wcs[0]; + return 0; + } else if (IS_LOW_SURROGATE(wcs[0])) { + wcs[1] = wcs[0]; + wcs[0] = lastHighSurrogateChar; + lastHighSurrogateChar = 0; + wclen = 2; + } + AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput); + } + return 0; + + case WM_UNICHAR: + if (wParam == UNICODE_NOCHAR) { + return TRUE; + } else if (lastKeyDownConsumed) { + return 1; + } else { + wchar_t wcs[3] = { 0 }; + const unsigned int wclen = UTF16FromUTF32Character(static_cast<unsigned int>(wParam), wcs); + AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput); + return FALSE; + } + } + + return 0; +} + +sptr_t ScintillaWin::FocusMessage(unsigned int iMessage, uptr_t wParam, sptr_t) { + switch (iMessage) { + case WM_KILLFOCUS: { + HWND wOther = reinterpret_cast<HWND>(wParam); + HWND wThis = MainHWND(); + const HWND wCT = static_cast<HWND>(ct.wCallTip.GetID()); + if (!wParam || + !(::IsChild(wThis, wOther) || (wOther == wCT))) { + SetFocusState(false); + DestroySystemCaret(); + } + // Explicitly complete any IME composition + IMContext imc(MainHWND()); + if (imc.hIMC) { + ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); + } + break; + } + + case WM_SETFOCUS: + SetFocusState(true); + DestroySystemCaret(); + CreateSystemCaret(); + break; + } + return 0; +} + +sptr_t ScintillaWin::IMEMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + + case WM_IME_KEYDOWN: { + if (wParam == VK_HANJA) { + ToggleHanja(); + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_IME_REQUEST: { + if (wParam == IMR_RECONVERTSTRING) { + return ImeOnReconvert(lParam); + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_IME_STARTCOMPOSITION: // dbcs + if (KoreanIME() || imeInteraction == imeInline) { + return 0; + } else { + ImeStartComposition(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_IME_ENDCOMPOSITION: // dbcs + ImeEndComposition(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_IME_COMPOSITION: + if (KoreanIME() || imeInteraction == imeInline) { + return HandleCompositionInline(wParam, lParam); + } else { + return HandleCompositionWindowed(wParam, lParam); + } + + case WM_IME_SETCONTEXT: + if (KoreanIME() || imeInteraction == imeInline) { + if (wParam) { + LPARAM NoImeWin = lParam; + NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW); + return ::DefWindowProc(MainHWND(), iMessage, wParam, NoImeWin); + } + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_IME_NOTIFY: + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + } + return 0; +} + +sptr_t ScintillaWin::EditMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + + case EM_LINEFROMCHAR: + if (static_cast<int>(wParam) < 0) { + wParam = SelectionStart().Position(); + } + return pdoc->LineFromPosition(static_cast<int>(wParam)); + + case EM_EXLINEFROMCHAR: + return pdoc->LineFromPosition(static_cast<int>(lParam)); + + case EM_GETSEL: + if (wParam) { + *reinterpret_cast<int *>(wParam) = static_cast<int>(SelectionStart().Position()); + } + if (lParam) { + *reinterpret_cast<int *>(lParam) = static_cast<int>(SelectionEnd().Position()); + } + return MAKELRESULT(SelectionStart().Position(), SelectionEnd().Position()); + + case EM_EXGETSEL: { + if (lParam == 0) { + return 0; + } + Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam); + pCR->cpMin = static_cast<Sci_PositionCR>(SelectionStart().Position()); + pCR->cpMax = static_cast<Sci_PositionCR>(SelectionEnd().Position()); + } + break; + + case EM_SETSEL: { + Sci::Position nStart = static_cast<Sci::Position>(wParam); + Sci::Position nEnd = lParam; + if (nStart == 0 && nEnd == -1) { + nEnd = pdoc->Length(); + } + if (nStart == -1) { + nStart = nEnd; // Remove selection + } + SetSelection(nEnd, nStart); + EnsureCaretVisible(); + } + break; + + case EM_EXSETSEL: { + if (lParam == 0) { + return 0; + } + const Sci_CharacterRange *pCR = reinterpret_cast<const Sci_CharacterRange *>(lParam); + sel.selType = Selection::selStream; + if (pCR->cpMin == 0 && pCR->cpMax == -1) { + SetSelection(pCR->cpMin, pdoc->Length()); + } else { + SetSelection(pCR->cpMin, pCR->cpMax); + } + EnsureCaretVisible(); + return pdoc->LineFromPosition(SelectionStart().Position()); + } + } + return 0; +} + +sptr_t ScintillaWin::IdleMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + case SC_WIN_IDLE: + // wParam=dwTickCountInitial, or 0 to initialize. lParam=bSkipUserInputTest + if (idler.state) { + if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, nullptr, 0, 0, QS_INPUT | QS_HOTKEY))) { + if (Idle()) { + // User input was given priority above, but all events do get a turn. Other + // messages, notifications, etc. will get interleaved with the idle messages. + + // However, some things like WM_PAINT are a lower priority, and will not fire + // when there's a message posted. So, several times a second, we stop and let + // the low priority events have a turn (after which the timer will fire again). + + // Suppress a warning from Code Analysis that the GetTickCount function + // wraps after 49 days. The WM_TIMER will kick off another SC_WIN_IDLE + // after the wrap. +#ifdef _MSC_VER +#pragma warning(suppress: 28159) +#endif + const DWORD dwCurrent = GetTickCount(); + const DWORD dwStart = wParam ? static_cast<DWORD>(wParam) : dwCurrent; + const DWORD maxWorkTime = 50; + + if (dwCurrent >= dwStart && dwCurrent > maxWorkTime &&dwCurrent - maxWorkTime < dwStart) + PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0); + } else { + SetIdle(false); + } + } + } + break; + + case SC_WORK_IDLE: + IdleWork(); + break; + } + return 0; +} + +sptr_t ScintillaWin::SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + switch (iMessage) { + case SCI_GETDIRECTFUNCTION: + return reinterpret_cast<sptr_t>(DirectFunction); + + case SCI_GETDIRECTPOINTER: + return reinterpret_cast<sptr_t>(this); + + case SCI_GRABFOCUS: + ::SetFocus(MainHWND()); + break; + +#ifdef INCLUDE_DEPRECATED_FEATURES + case SCI_SETKEYSUNICODE: + break; + + case SCI_GETKEYSUNICODE: + return true; +#endif + + case SCI_SETTECHNOLOGY: + if ((wParam == SC_TECHNOLOGY_DEFAULT) || + (wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) || + (wParam == SC_TECHNOLOGY_DIRECTWRITEDC) || + (wParam == SC_TECHNOLOGY_DIRECTWRITE)) { + const int technologyNew = static_cast<int>(wParam); + if (technology != technologyNew) { + if (technologyNew > SC_TECHNOLOGY_DEFAULT) { +#if defined(USE_D2D) + if (!LoadD2D()) + // Failed to load Direct2D or DirectWrite so no effect + return 0; +#else + return 0; +#endif + } else { + bidirectional = EditModel::Bidirectional::bidiDisabled; + } +#if defined(USE_D2D) + DropRenderTarget(); +#endif + technology = technologyNew; + // Invalidate all cached information including layout. + DropGraphics(true); + InvalidateStyleRedraw(); + } + } + break; + + case SCI_SETBIDIRECTIONAL: + if (technology == SC_TECHNOLOGY_DEFAULT) { + bidirectional = EditModel::Bidirectional::bidiDisabled; + } else if (wParam <= SC_BIDIRECTIONAL_R2L) { + bidirectional = static_cast<EditModel::Bidirectional>(wParam); + } + // Invalidate all cached information including layout. + DropGraphics(true); + InvalidateStyleRedraw(); + break; + + case SCI_TARGETASUTF8: + return TargetAsUTF8(CharPtrFromSPtr(lParam)); + + case SCI_ENCODEDFROMUTF8: + return EncodedFromUTF8(ConstCharPtrFromUPtr(wParam), + CharPtrFromSPtr(lParam)); + + } + return 0; +} + sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { try { //Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam); @@ -1327,9 +1823,11 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam GetIntelliMouseParameters(); ::RegisterDragDrop(MainHWND(), reinterpret_cast<IDropTarget *>(&dt)); break; + case WM_COMMAND: Command(LOWORD(wParam)); break; + case WM_PAINT: return WndPaint(); @@ -1350,76 +1848,10 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam HorizontalScrollMessage(wParam); break; - case WM_SIZE: { -#if defined(USE_D2D) - if (paintState == notPainting) { - DropRenderTarget(); - } else { - renderTargetValid = false; - } -#endif - //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam)); - ChangeSize(); - } + case WM_SIZE: + SizeWindow(); break; - case WM_MOUSEWHEEL: - if (!mouseWheelCaptures) { - // if the mouse wheel is not captured, test if the mouse - // pointer is over the editor window and if not, don't - // handle the message but pass it on. - RECT rc; - GetWindowRect(MainHWND(), &rc); - POINT pt; - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - if (!PtInRect(&rc, pt)) - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - // if autocomplete list active then send mousewheel message to it - if (ac.Active()) { - HWND hWnd = static_cast<HWND>(ac.lb->GetID()); - ::SendMessage(hWnd, iMessage, wParam, lParam); - break; - } - - // Don't handle datazoom. - // (A good idea for datazoom would be to "fold" or "unfold" details. - // i.e. if datazoomed out only class structures are visible, when datazooming in the control - // structures appear, then eventually the individual statements...) - if (wParam & MK_SHIFT) { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - // Either SCROLL or ZOOM. We handle the wheel steppings calculation - wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam); - if (std::abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) { - Sci::Line linesToScroll = linesPerScroll; - if (linesPerScroll == WHEEL_PAGESCROLL) - linesToScroll = LinesOnScreen() - 1; - if (linesToScroll == 0) { - linesToScroll = 1; - } - linesToScroll *= (wheelDelta / WHEEL_DELTA); - if (wheelDelta >= 0) - wheelDelta = wheelDelta % WHEEL_DELTA; - else - wheelDelta = - (-wheelDelta % WHEEL_DELTA); - - if (wParam & MK_CONTROL) { - // Zoom! We play with the font sizes in the styles. - // Number of steps/line is ignored, we just care if sizing up or down - if (linesToScroll < 0) { - KeyCommand(SCI_ZOOMIN); - } else { - KeyCommand(SCI_ZOOMOUT); - } - } else { - // Scroll - ScrollTo(topLine + linesToScroll); - } - } - return 0; - case WM_TIMER: if (wParam == idleTimerID && idler.state) { SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1); @@ -1429,191 +1861,34 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam break; case SC_WIN_IDLE: - // wParam=dwTickCountInitial, or 0 to initialize. lParam=bSkipUserInputTest - if (idler.state) { - if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, nullptr, 0, 0, QS_INPUT|QS_HOTKEY))) { - if (Idle()) { - // User input was given priority above, but all events do get a turn. Other - // messages, notifications, etc. will get interleaved with the idle messages. - - // However, some things like WM_PAINT are a lower priority, and will not fire - // when there's a message posted. So, several times a second, we stop and let - // the low priority events have a turn (after which the timer will fire again). - - // Suppress a warning from Code Analysis that the GetTickCount function - // wraps after 49 days. The WM_TIMER will kick off another SC_WIN_IDLE - // after the wrap. -#ifdef _MSC_VER -#pragma warning(suppress: 28159) -#endif - const DWORD dwCurrent = GetTickCount(); - const DWORD dwStart = wParam ? static_cast<DWORD>(wParam) : dwCurrent; - const DWORD maxWorkTime = 50; - - if (dwCurrent >= dwStart && dwCurrent > maxWorkTime && dwCurrent - maxWorkTime < dwStart) - PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0); - } else { - SetIdle(false); - } - } - } - break; - case SC_WORK_IDLE: - IdleWork(); - break; + return IdleMessage(iMessage, wParam, lParam); case WM_GETMINMAXINFO: return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - case WM_LBUTTONDOWN: { - // For IME, set the composition string as the result string. - IMContext imc(MainHWND()); - if (imc.hIMC) { - ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); - } - // - //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam, - // KeyboardIsKeyDown(VK_SHIFT), - // KeyboardIsKeyDown(VK_CONTROL), - // KeyboardIsKeyDown(VK_MENU)); - ::SetFocus(MainHWND()); - ButtonDownWithModifiers(PointFromLParam(lParam), ::GetMessageTime(), - MouseModifiers(wParam)); - } - break; - - case WM_MOUSEMOVE: { - const Point pt = PointFromLParam(lParam); - - // Windows might send WM_MOUSEMOVE even though the mouse has not been moved: - // http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx - if (ptMouseLast != pt) { - SetTrackMouseLeaveEvent(true); - ButtonMoveWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam)); - } - } - break; - - case WM_MOUSELEAVE: - SetTrackMouseLeaveEvent(false); - MouseLeave(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - + case WM_LBUTTONDOWN: case WM_LBUTTONUP: - ButtonUpWithModifiers(PointFromLParam(lParam), - ::GetMessageTime(), MouseModifiers(wParam)); - break; - - case WM_RBUTTONDOWN: { - ::SetFocus(MainHWND()); - const Point pt = PointFromLParam(lParam); - if (!PointInSelection(pt)) { - CancelModes(); - SetEmptySelection(PositionFromLocation(PointFromLParam(lParam))); - } + case WM_RBUTTONDOWN: + case WM_MOUSEMOVE: + case WM_MOUSELEAVE: + case WM_MOUSEWHEEL: + return MouseMessage(iMessage, wParam, lParam); - RightButtonDownWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam)); - } - break; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { - if (inDragDrop == ddDragging) { - DisplayCursor(Window::cursorUp); - } else { - // Display regular (drag) cursor over selection - POINT pt; - if (0 != ::GetCursorPos(&pt)) { - ::ScreenToClient(MainHWND(), &pt); - if (PointInSelMargin(PointFromPOINT(pt))) { - DisplayCursor(GetMarginCursor(PointFromPOINT(pt))); - } else if (PointInSelection(PointFromPOINT(pt)) && !SelectionEmpty()) { - DisplayCursor(Window::cursorArrow); - } else if (PointIsHotspot(PointFromPOINT(pt))) { - DisplayCursor(Window::cursorHand); - } else { - DisplayCursor(Window::cursorText); - } - } - } + DisplayCursor(ContextCursor()); return TRUE; } else { return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); } - case WM_CHAR: - if (((wParam >= 128) || !iscntrl(static_cast<int>(wParam))) || !lastKeyDownConsumed) { - wchar_t wcs[3] = {static_cast<wchar_t>(wParam), 0}; - unsigned int wclen = 1; - if (IS_HIGH_SURROGATE(wcs[0])) { - // If this is a high surrogate character, we need a second one - lastHighSurrogateChar = wcs[0]; - return 0; - } else if (IS_LOW_SURROGATE(wcs[0])) { - wcs[1] = wcs[0]; - wcs[0] = lastHighSurrogateChar; - lastHighSurrogateChar = 0; - wclen = 2; - } - AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput); - } - return 0; - - case WM_UNICHAR: - if (wParam == UNICODE_NOCHAR) { - return TRUE; - } else if (lastKeyDownConsumed) { - return 1; - } else { - wchar_t wcs[3] = {0}; - const unsigned int wclen = UTF16FromUTF32Character(static_cast<unsigned int>(wParam), wcs); - AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput); - return FALSE; - } - case WM_SYSKEYDOWN: - case WM_KEYDOWN: { - // Platform::DebugPrintf("Keydown %c %c%c%c%c %x %x\n", - // iMessage == WM_KEYDOWN ? 'K' : 'S', - // (lParam & (1 << 24)) ? 'E' : '-', - // KeyboardIsKeyDown(VK_SHIFT) ? 'S' : '-', - // KeyboardIsKeyDown(VK_CONTROL) ? 'C' : '-', - // KeyboardIsKeyDown(VK_MENU) ? 'A' : '-', - // wParam, lParam); - lastKeyDownConsumed = false; - const bool altDown = KeyboardIsKeyDown(VK_MENU); - if (altDown && KeyboardIsNumericKeypadFunction(wParam, lParam)) { - // Don't interpret these as they may be characters entered by number. - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - const int ret = KeyDownWithModifiers(KeyTranslate(static_cast<int>(wParam)), - ModifierFlags(KeyboardIsKeyDown(VK_SHIFT), - KeyboardIsKeyDown(VK_CONTROL), - altDown), - &lastKeyDownConsumed); - if (!ret && !lastKeyDownConsumed) { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - break; - } - - case WM_IME_KEYDOWN: { - if (wParam == VK_HANJA) { - ToggleHanja(); - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_IME_REQUEST: { - if (wParam == IMR_RECONVERTSTRING) { - return ImeOnReconvert(lParam); - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - + case WM_KEYDOWN: case WM_KEYUP: - //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + case WM_CHAR: + case WM_UNICHAR: + return KeyMessage(iMessage, wParam, lParam); case WM_SETTINGCHANGE: //Platform::DebugPrintf("Setting Changed\n"); @@ -1625,71 +1900,18 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case WM_GETDLGCODE: return DLGC_HASSETSEL | DLGC_WANTALLKEYS; - case WM_KILLFOCUS: { - HWND wOther = reinterpret_cast<HWND>(wParam); - HWND wThis = MainHWND(); - const HWND wCT = static_cast<HWND>(ct.wCallTip.GetID()); - if (!wParam || - !(::IsChild(wThis, wOther) || (wOther == wCT))) { - SetFocusState(false); - DestroySystemCaret(); - } - // Explicitly complete any IME composition - IMContext imc(MainHWND()); - if (imc.hIMC) { - ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); - } - } - break; - + case WM_KILLFOCUS: case WM_SETFOCUS: - SetFocusState(true); - DestroySystemCaret(); - CreateSystemCaret(); - break; + return FocusMessage(iMessage, wParam, lParam); case WM_SYSCOLORCHANGE: //Platform::DebugPrintf("Setting Changed\n"); InvalidateStyleData(); break; - case WM_IME_STARTCOMPOSITION: // dbcs - if (KoreanIME() || imeInteraction == imeInline) { - return 0; - } else { - ImeStartComposition(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_IME_ENDCOMPOSITION: // dbcs - ImeEndComposition(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + case WM_CONTEXTMENU: + return ShowContextMenu(iMessage, wParam, lParam); - case WM_IME_COMPOSITION: - if (KoreanIME() || imeInteraction == imeInline) { - return HandleCompositionInline(wParam, lParam); - } else { - return HandleCompositionWindowed(wParam, lParam); - } - - case WM_CONTEXTMENU: { - Point pt = PointFromLParam(lParam); - POINT rpt = {static_cast<int>(pt.x), static_cast<int>(pt.y)}; - ::ScreenToClient(MainHWND(), &rpt); - const Point ptClient = PointFromPOINT(rpt); - if (ShouldDisplayPopup(ptClient)) { - if ((pt.x == -1) && (pt.y == -1)) { - // Caused by keyboard so display menu near caret - pt = PointMainCaret(); - POINT spt = POINTFromPoint(pt); - ::ClientToScreen(MainHWND(), &spt); - pt = PointFromPOINT(spt); - } - ContextMenu(pt); - return 0; - } - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); case WM_INPUTLANGCHANGE: return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); case WM_INPUTLANGCHANGEREQUEST: @@ -1702,16 +1924,6 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam capturedMouse = false; return 0; - case WM_IME_SETCONTEXT: - if (KoreanIME() || imeInteraction == imeInline) { - if (wParam) { - LPARAM NoImeWin = lParam; - NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW); - return ::DefWindowProc(MainHWND(), iMessage, wParam, NoImeWin); - } - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - // These are not handled in Scintilla and its faster to dispatch them here. // Also moves time out to here so profile doesn't count lots of empty message calls. @@ -1722,7 +1934,6 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case WM_NCPAINT: case WM_NCMOUSEMOVE: case WM_NCLBUTTONDOWN: - case WM_IME_NOTIFY: case WM_SYSCOMMAND: case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: @@ -1735,126 +1946,25 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam return GetText(wParam, lParam); case EM_LINEFROMCHAR: - if (static_cast<int>(wParam) < 0) { - wParam = SelectionStart().Position(); - } - return pdoc->LineFromPosition(static_cast<int>(wParam)); - case EM_EXLINEFROMCHAR: - return pdoc->LineFromPosition(static_cast<int>(lParam)); - case EM_GETSEL: - if (wParam) { - *reinterpret_cast<int *>(wParam) = static_cast<int>(SelectionStart().Position()); - } - if (lParam) { - *reinterpret_cast<int *>(lParam) = static_cast<int>(SelectionEnd().Position()); - } - return MAKELRESULT(SelectionStart().Position(), SelectionEnd().Position()); - - case EM_EXGETSEL: { - if (lParam == 0) { - return 0; - } - Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam); - pCR->cpMin = static_cast<Sci_PositionCR>(SelectionStart().Position()); - pCR->cpMax = static_cast<Sci_PositionCR>(SelectionEnd().Position()); - } - break; - - case EM_SETSEL: { - Sci::Position nStart = static_cast<Sci::Position>(wParam); - Sci::Position nEnd = lParam; - if (nStart == 0 && nEnd == -1) { - nEnd = pdoc->Length(); - } - if (nStart == -1) { - nStart = nEnd; // Remove selection - } - SetSelection(nEnd, nStart); - EnsureCaretVisible(); - } - break; - - case EM_EXSETSEL: { - if (lParam == 0) { - return 0; - } - const Sci_CharacterRange *pCR = reinterpret_cast<const Sci_CharacterRange *>(lParam); - sel.selType = Selection::selStream; - if (pCR->cpMin == 0 && pCR->cpMax == -1) { - SetSelection(pCR->cpMin, pdoc->Length()); - } else { - SetSelection(pCR->cpMin, pCR->cpMax); - } - EnsureCaretVisible(); - return pdoc->LineFromPosition(SelectionStart().Position()); - } + case EM_EXGETSEL: + case EM_SETSEL: + case EM_EXSETSEL: + return EditMessage(iMessage, wParam, lParam); case SCI_GETDIRECTFUNCTION: - return reinterpret_cast<sptr_t>(DirectFunction); - case SCI_GETDIRECTPOINTER: - return reinterpret_cast<sptr_t>(this); - case SCI_GRABFOCUS: - ::SetFocus(MainHWND()); - break; - #ifdef INCLUDE_DEPRECATED_FEATURES case SCI_SETKEYSUNICODE: - break; - case SCI_GETKEYSUNICODE: - return true; #endif - case SCI_SETTECHNOLOGY: - if ((wParam == SC_TECHNOLOGY_DEFAULT) || - (wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) || - (wParam == SC_TECHNOLOGY_DIRECTWRITEDC) || - (wParam == SC_TECHNOLOGY_DIRECTWRITE)) { - const int technologyNew = static_cast<int>(wParam); - if (technology != technologyNew) { - if (technologyNew > SC_TECHNOLOGY_DEFAULT) { -#if defined(USE_D2D) - if (!LoadD2D()) - // Failed to load Direct2D or DirectWrite so no effect - return 0; -#else - return 0; -#endif - } else { - bidirectional = EditModel::Bidirectional::bidiDisabled; - } -#if defined(USE_D2D) - DropRenderTarget(); -#endif - technology = technologyNew; - // Invalidate all cached information including layout. - DropGraphics(true); - InvalidateStyleRedraw(); - } - } - break; - case SCI_SETBIDIRECTIONAL: - if (technology == SC_TECHNOLOGY_DEFAULT) { - bidirectional = EditModel::Bidirectional::bidiDisabled; - } else if (wParam <= SC_BIDIRECTIONAL_R2L) { - bidirectional = static_cast<EditModel::Bidirectional>(wParam); - } - // Invalidate all cached information including layout. - DropGraphics(true); - InvalidateStyleRedraw(); - break; - case SCI_TARGETASUTF8: - return TargetAsUTF8(CharPtrFromSPtr(lParam)); - case SCI_ENCODEDFROMUTF8: - return EncodedFromUTF8(ConstCharPtrFromUPtr(wParam), - CharPtrFromSPtr(lParam)); + return SciMessage(iMessage, wParam, lParam); default: return ScintillaBase::WndProc(iMessage, wParam, lParam); |