aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2020-01-28 11:18:36 +1100
committerNeil <nyamatongwe@gmail.com>2020-01-28 11:18:36 +1100
commitbd97651f7bb7e7c1b6df6e57c2a2d6ab93da1d46 (patch)
tree2e0b7de0675f36e761520d2efecaaa6e3636feb4
parent2494d4ec4b7af0c7916d5b777bdd9f71eef2906b (diff)
downloadscintilla-mirror-bd97651f7bb7e7c1b6df6e57c2a2d6ab93da1d46.tar.gz
Break WndProc up into shorter, more focussed methods.
-rw-r--r--win32/ScintillaWin.cxx932
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);