diff options
-rw-r--r-- | src/Editor.cxx | 30 | ||||
-rw-r--r-- | src/Editor.h | 1 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 37 |
3 files changed, 50 insertions, 18 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 422237f97..9cf3c31b3 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -380,6 +380,7 @@ Editor::Editor() { wrapWidth = LineLayout::wrapWidthInfinite; docLineLastWrapped = -1; docLastLineToWrap = -1; + backgroundWrapEnabled = true; hsStart = -1; hsEnd = -1; @@ -1426,11 +1427,12 @@ void Editor::NeedWrapping(int docLineStartWrapping, int docLineEndWrapping) { // condition is called only from idler). // Return true if wrapping occurred. bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { - // If there are any pending wraps do them during idle. + // If there are any pending wraps, do them during idle if possible. if (wrapState != eWrapNone) { if (docLineLastWrapped < docLastLineToWrap) { - if (!SetIdle(true)) { - // If platform does not have Idle events, perform full wrap + if (!(backgroundWrapEnabled && SetIdle(true))) { + // Background wrapping is disabled, or idle processing + // not supported. A full wrap is required. fullWrap = true; } } @@ -1441,9 +1443,6 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { // No priority wrap pending return false; } - } else { - // If there is no wrap, disable the idle call. - SetIdle(false); } int goodTopLine = topLine; bool wrapOccurred = false; @@ -5050,18 +5049,25 @@ void Editor::Tick() { bool Editor::Idle() { - bool idleDone = false; - // Wrap lines during idle. - WrapLines(false, -1); - // No more wrapping - if (docLineLastWrapped == docLastLineToWrap) - idleDone = true; + bool idleDone; + + bool wrappingDone = (wrapState == eWrapNone) || (!backgroundWrapEnabled); + + if (!wrappingDone) { + // Wrap lines during idle. + WrapLines(false, -1); + // No more wrapping + if (docLineLastWrapped == docLastLineToWrap) + wrappingDone = true; + } // Add more idle things to do here, but make sure idleDone is // set correctly before the function returns. returning // false will stop calling this idle funtion until SetIdle() is // called again. + idleDone = wrappingDone; // && thatDone && theOtherThingDone... + return !idleDone; } diff --git a/src/Editor.h b/src/Editor.h index b8c32ab64..6eccb50bd 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -287,6 +287,7 @@ protected: // ScintillaBase subclass needs access to much of Editor // Wrapping support enum { eWrapNone, eWrapWord } wrapState; + bool backgroundWrapEnabled; int wrapWidth; int docLineLastWrapped; int docLastLineToWrap; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 4c9f7341a..9c2d78e1c 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -171,10 +171,13 @@ class ScintillaWin : static sptr_t PASCAL CTWndProc( HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam); + enum { invalidTimerID, standardTimerID, idleTimerID }; + virtual void StartDrag(); sptr_t WndPaint(uptr_t wParam); sptr_t HandleComposition(uptr_t wParam, sptr_t lParam); virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + virtual bool SetIdle(bool on); virtual void SetTicking(bool on); virtual void SetMouseCapture(bool on); virtual bool HaveMouseCapture(); @@ -282,6 +285,7 @@ void ScintillaWin::Initialise() { void ScintillaWin::Finalise() { ScintillaBase::Finalise(); SetTicking(false); + SetIdle(false); ::RevokeDragDrop(MainHWND()); ::OleUninitialize(); } @@ -577,7 +581,14 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam return 0; case WM_TIMER: - Tick(); + if (wParam == standardTimerID && timer.ticking) { + Tick(); + } else if (wParam == idleTimerID && idler.state) { + if (!Idle()) + SetIdle(false); + } else { + return 1; + } break; case WM_GETMINMAXINFO: @@ -887,11 +898,8 @@ void ScintillaWin::SetTicking(bool on) { if (timer.ticking != on) { timer.ticking = on; if (timer.ticking) { - timer.tickerID = reinterpret_cast<TickerID>(1); - if (::SetTimer(MainHWND(), reinterpret_cast<uptr_t>(timer.tickerID), timer.tickSize, NULL) == 0) { - timer.ticking = false; - timer.tickerID = 0; - } + timer.tickerID = ::SetTimer(MainHWND(), standardTimerID, timer.tickSize, NULL) + ? reinterpret_cast<TickerID>(standardTimerID) : 0; } else { ::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(timer.tickerID)); timer.tickerID = 0; @@ -900,6 +908,23 @@ void ScintillaWin::SetTicking(bool on) { timer.ticksToWait = caret.period; } +bool ScintillaWin::SetIdle(bool on) { + // On Win32 the Idler is implemented as a Timer on the Scintilla window. This + // takes advantage of the fact that WM_TIMER messages are very low priority, + // and are only posted when the message queue is empty, i.e. during idle time. + if (idler.state != on) { + if (on) { + idler.idlerID = ::SetTimer(MainHWND(), idleTimerID, 20, NULL) + ? reinterpret_cast<IdlerID>(idleTimerID) : 0; + } else { + ::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(idler.idlerID)); + idler.idlerID = 0; + } + idler.state = idler.idlerID != 0; + } + return idler.state; +} + void ScintillaWin::SetMouseCapture(bool on) { if (mouseDownCaptures) { if (on) { |