diff options
-rw-r--r-- | gtk/ScintillaGTK.cxx | 32 | ||||
-rw-r--r-- | src/Editor.cxx | 63 | ||||
-rw-r--r-- | src/Editor.h | 2 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 37 |
4 files changed, 91 insertions, 43 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index b3c9b8bd4..c6b0fbf3e 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -129,6 +129,8 @@ class ScintillaGTK : public ScintillaBase { gint lastWheelMouseDirection; gint wheelMouseIntensity; + GdkRegion *rgnUpdate; + // Private so ScintillaGTK objects can not be copied ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {} ScintillaGTK &operator=(const ScintillaGTK &) { return * this; } @@ -153,6 +155,7 @@ private: virtual bool SetIdle(bool on); virtual void SetMouseCapture(bool on); virtual bool HaveMouseCapture(); + virtual bool PaintContains(PRectangle rc); void FullPaint(); virtual PRectangle GetClientRectangle(); void SyncPaint(PRectangle rc); @@ -317,7 +320,8 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : #endif #endif lastWheelMouseDirection(0), - wheelMouseIntensity(0) { + wheelMouseIntensity(0), + rgnUpdate(0) { sci = sci_; wMain = GTK_WIDGET(sci); @@ -947,6 +951,22 @@ bool ScintillaGTK::HaveMouseCapture() { return capturedMouse; } +bool ScintillaGTK::PaintContains(PRectangle rc) { + bool contains = true; + if (paintState == painting) { + if (!rcPaint.Contains(rc)) { + contains = false; + } else if (rgnUpdate) { + GdkRectangle grc = {rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top}; + if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) { + contains = false; + } + } + } + return contains; +} + // Redraw all of text area. This paint will not be abandoned. void ScintillaGTK::FullPaint() { #if GTK_MAJOR_VERSION < 2 @@ -2152,6 +2172,10 @@ gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) { rcPaint.right = ose->area.x + ose->area.width; rcPaint.bottom = ose->area.y + ose->area.height; + PLATFORM_ASSERT(rgnUpdate == NULL); +#if GTK_MAJOR_VERSION >= 2 + rgnUpdate = gdk_region_copy(ose->region); +#endif PRectangle rcClient = GetClientRectangle(); paintingAllText = rcPaint.Contains(rcClient); Surface *surfaceWindow = Surface::Allocate(); @@ -2166,6 +2190,12 @@ gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) { FullPaint(); } paintState = notPainting; + + if (rgnUpdate) { + g_free(rgnUpdate); + } + rgnUpdate = 0; + return FALSE; } diff --git a/src/Editor.cxx b/src/Editor.cxx index f4ef99b5a..93560abdf 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -3749,8 +3749,13 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { } if (mh.modificationType & SC_MOD_CHANGEMARKER) { - if (paintState == notPainting) { - RedrawSelMargin(mh.line); + if ((paintState == notPainting) || !PaintContainsMargin()) { + if (mh.modificationType & SC_MOD_CHANGEFOLD) { + // Fold changes can affect the drawing of following lines so redraw whole margin + RedrawSelMargin(); + } else { + RedrawSelMargin(mh.line); + } } } @@ -5372,16 +5377,14 @@ void Editor::SetFocusState(bool focusState) { } } -static bool IsIn(int a, int minimum, int maximum) { - return (a >= minimum) && (a <= maximum); +bool Editor::PaintContains(PRectangle rc) { + return rcPaint.Contains(rc); } -static bool IsOverlap(int mina, int maxa, int minb, int maxb) { - return - IsIn(mina, minb, maxb) || - IsIn(maxa, minb, maxb) || - IsIn(minb, mina, maxa) || - IsIn(maxb, mina, maxa); +bool Editor::PaintContainsMargin() { + PRectangle rcSelMargin = GetClientRectangle(); + rcSelMargin.right = vs.fixedColumnWidth; + return PaintContains(rcSelMargin); } void Editor::CheckForChangeOutsidePaint(Range r) { @@ -5390,41 +5393,17 @@ void Editor::CheckForChangeOutsidePaint(Range r) { if (!r.Valid()) return; + PRectangle rcRange = RectangleFromRange(r.start, r.end); PRectangle rcText = GetTextRectangle(); - // Determine number of lines displayed including a possible partially displayed last line - int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1; - int bottomLine = topLine + linesDisplayed - 1; - - int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start)); - int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end)); - if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) { - //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n", - // lineRangeStart, lineRangeEnd, topLine, bottomLine); - return; + if (rcRange.top < rcText.top) { + rcRange.top = rcText.top; } - - // Assert rcPaint contained within or equal to rcText - if (rcPaint.top > rcText.top) { - // does range intersect rcText.top .. rcPaint.top - int paintTopLine = ((rcPaint.top - rcText.top - 1) / vs.lineHeight) + topLine; - // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle - if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) { - //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", - // lineRangeStart, lineRangeEnd, topLine, paintTopLine); - AbandonPaint(); - return; - } + if (rcRange.bottom > rcText.bottom) { + rcRange.bottom = rcText.bottom; } - if (rcPaint.bottom < rcText.bottom) { - // does range intersect rcPaint.bottom .. rcText.bottom - int paintBottomLine = ((rcPaint.bottom - rcText.top - 1) / vs.lineHeight + 1) + topLine; - // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle - if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) { - //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", - // lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine); - AbandonPaint(); - return; - } + + if (!PaintContains(rcRange)) { + AbandonPaint(); } } } diff --git a/src/Editor.h b/src/Editor.h index 0ac6ec917..1207425dd 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -504,6 +504,8 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual bool HaveMouseCapture() = 0; void SetFocusState(bool focusState); + virtual bool PaintContains(PRectangle rc); + bool PaintContainsMargin(); void CheckForChangeOutsidePaint(Range r); int BraceMatch(int position, int maxReStyle); void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index a4c09a0fb..c7f569970 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -147,6 +147,8 @@ class ScintillaWin : unsigned int linesPerScroll; ///< Intellimouse support int wheelDelta; ///< Wheel delta from roll + HRGN hRgnUpdate; + bool hasOKText; CLIPFORMAT cfColumnSelect; @@ -183,6 +185,7 @@ class ScintillaWin : virtual void SetTicking(bool on); virtual void SetMouseCapture(bool on); virtual bool HaveMouseCapture(); + virtual bool PaintContains(PRectangle rc); virtual void ScrollText(int linesToMove); virtual void UpdateSystemCaret(); virtual void SetVerticalScrollPos(); @@ -277,6 +280,8 @@ ScintillaWin::ScintillaWin(HWND hwnd) { linesPerScroll = 0; wheelDelta = 0; // Wheel delta from roll + hRgnUpdate = 0; + hasOKText = false; // There does not seem to be a real standard for indicating that the clipboard @@ -409,9 +414,12 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { bool IsOcxCtrl = (wParam != 0); // if wParam != 0, it contains // a PAINSTRUCT* from the OCX + PLATFORM_ASSERT(hRgnUpdate == NULL); + hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0); if (IsOcxCtrl) { pps = reinterpret_cast<PAINTSTRUCT*>(wParam); } else { + ::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE); pps = &ps; ::BeginPaint(MainHWND(), pps); } @@ -428,6 +436,11 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { Paint(surfaceWindow, rcPaint); surfaceWindow->Release(); } + if (hRgnUpdate) { + ::DeleteRgn(hRgnUpdate); + hRgnUpdate = 0; + } + if(!IsOcxCtrl) ::EndPaint(MainHWND(), pps); if (paintState == paintAbandoned) { @@ -989,6 +1002,30 @@ bool ScintillaWin::HaveMouseCapture() { //return capturedMouse && (::GetCapture() == MainHWND()); } +bool ScintillaWin::PaintContains(PRectangle rc) { + bool contains = true; + if (paintState == painting) { + if (!rcPaint.Contains(rc)) { + contains = false; + } else { + // In bounding rectangle so check more accurately using region + HRGN hRgnRange = ::CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); + if (hRgnRange) { + HRGN hRgnDest = ::CreateRectRgn(0, 0, 0, 0); + if (hRgnDest) { + int combination = ::CombineRgn(hRgnDest, hRgnRange, hRgnUpdate, RGN_DIFF); + if (combination != NULLREGION) { + contains = false; + } + ::DeleteRgn(hRgnDest); + } + ::DeleteRgn(hRgnRange); + } + } + } + return contains; +} + void ScintillaWin::ScrollText(int linesToMove) { //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove); ::ScrollWindow(MainHWND(), 0, |