diff options
| author | nyamatongwe <unknown> | 2013-06-18 14:55:30 +1000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2013-06-18 14:55:30 +1000 | 
| commit | 99cf2f1c4d3479f94b61b0879b922effe766d393 (patch) | |
| tree | 7bd07a3fa77e0069005cb7acc14087289cfdc7e9 /src/Editor.cxx | |
| parent | 71851f214226abf8bd20a5236bf6760dee4e5c11 (diff) | |
| download | scintilla-mirror-99cf2f1c4d3479f94b61b0879b922effe766d393.tar.gz | |
Simplify line wrapping code, minimize lines wrapped and avoid rewrapping lines.
Diffstat (limited to 'src/Editor.cxx')
| -rw-r--r-- | src/Editor.cxx | 186 | 
1 files changed, 77 insertions, 109 deletions
| diff --git a/src/Editor.cxx b/src/Editor.cxx index f2e4c81b7..30f8120c0 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -212,8 +212,6 @@ Editor::Editor() {  	wrapState = eWrapNone;  	wrapWidth = LineLayout::wrapWidthInfinite; -	wrapStart = wrapLineLarge; -	wrapEnd = wrapLineLarge;  	wrapVisualFlags = 0;  	wrapVisualFlagsLocation = 0;  	wrapVisualStartIndent = 0; @@ -961,8 +959,8 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b  	int currentLine = pdoc->LineFromPosition(newPos.Position());  	if (ensureVisible) {  		// In case in need of wrapping to ensure DisplayFromDoc works. -		if (currentLine >= wrapStart) -			WrapLines(true, -1); +		if (currentLine >= wrapPending.start) +			WrapLines(wsAll);  		XYScrollPosition newXY = XYScrollToMakeVisible(  			SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);  		if (simpleCaret && (newXY.xOffset == xOffset)) { @@ -1541,17 +1539,12 @@ void Editor::UpdateSystemCaret() {  }  void Editor::NeedWrapping(int docLineStart, int docLineEnd) { -	docLineStart = Platform::Clamp(docLineStart, 0, pdoc->LinesTotal()); -	if (wrapStart > docLineStart) { -		wrapStart = docLineStart; +//Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd); +	if (wrapPending.AddRange(docLineStart, docLineEnd)) {  		llc.Invalidate(LineLayout::llPositions);  	} -	if (wrapEnd < docLineEnd) { -		wrapEnd = docLineEnd; -	} -	wrapEnd = Platform::Clamp(wrapEnd, 0, pdoc->LinesTotal());  	// Wrap lines during idle. -	if ((wrapState != eWrapNone) && (wrapEnd != wrapStart)) { +	if ((wrapState != eWrapNone) && wrapPending.NeedsWrap()) {  		SetIdle(true);  	}  } @@ -1567,60 +1560,64 @@ bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {  		(vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));  } -// Check if wrapping needed and perform any needed wrapping. -// fullwrap: if true, all lines which need wrapping will be done, -//           in this single call. -// priorityWrapLineStart: If greater than or equal to zero, all lines starting from -//           here to 1 page + 100 lines past will be wrapped (even if there are -//           more lines under wrapping process in idle). -// If it is neither fullwrap, nor priorityWrap, then 1 page + 100 lines will be -// wrapped, if there are any wrapping going on in idle. (Generally this -// condition is called only from idler). +// Perform  wrapping for a subset of the lines needing wrapping. +// wsAll: wrap all lines which need wrapping in this single call +// wsVisible: wrap currently visible lines +// wsIdle: wrap one page + 100 lines  // Return true if wrapping occurred. -bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { -	// If there are any pending wraps, do them during idle if possible. -	int linesInOneCall = LinesOnScreen() + 100; -	if (priorityWrapLineStart >= 0) { -		// Using DocFromDisplay() here may result in chicken and egg problem in certain corner cases, -		// which will hopefully be handled by added 100 lines. If some lines are still missed, idle wrapping will catch on. -		int docLinesInOneCall = cs.DocFromDisplay(topLine + LinesOnScreen() + 100) - cs.DocFromDisplay(topLine); -		linesInOneCall = Platform::Maximum(linesInOneCall, docLinesInOneCall); -	} -	if (wrapState != eWrapNone) { -		if (wrapStart < wrapEnd) { -			if (!SetIdle(true)) { -				// Idle processing not supported so full wrap required. -				fullWrap = true; -			} -		} -		if (!fullWrap && priorityWrapLineStart >= 0 && -		        // .. and if the paint window is outside pending wraps -		        (((priorityWrapLineStart + linesInOneCall) < wrapStart) || -		         (priorityWrapLineStart > wrapEnd))) { -			// No priority wrap pending -			return false; -		} -	} +bool Editor::WrapLines(enum wrapScope ws) {  	int goodTopLine = topLine;  	bool wrapOccurred = false; -	if (wrapStart <= pdoc->LinesTotal()) { -		if (wrapState == eWrapNone) { -			if (wrapWidth != LineLayout::wrapWidthInfinite) { -				wrapWidth = LineLayout::wrapWidthInfinite; -				for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) { -					cs.SetHeight(lineDoc, 1 + -						(vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0)); -				} -				wrapOccurred = true; +	if (wrapState == eWrapNone) { +		if (wrapWidth != LineLayout::wrapWidthInfinite) { +			wrapWidth = LineLayout::wrapWidthInfinite; +			for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) { +				cs.SetHeight(lineDoc, 1 + +					(vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0)); +			} +			wrapOccurred = true; +		} +		wrapPending.Reset(); + +	} else if (wrapPending.NeedsWrap()) { +		wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal()); +		if (!SetIdle(true)) { +			// Idle processing not supported so full wrap required. +			ws = wsAll; +		} +		// Decide where to start wrapping +		int lineToWrap = wrapPending.start; +		int lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal()); +		const int lineDocTop = cs.DocFromDisplay(topLine); +		const int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop); +		if (ws == wsVisible) { +			lineToWrap = Platform::Clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal()); +			// Priority wrap to just after visible area. +			// Since wrapping could reduce display lines, treat each +			// as taking only one display line. +			lineToWrapEnd = lineDocTop; +			int lines = LinesOnScreen() + 1; +			while ((lineToWrapEnd < cs.LinesInDoc()) && (lines>0)) { +				if (cs.GetVisible(lineToWrapEnd)) +					lines--; +				lineToWrapEnd++; +			} +			// .. and if the paint window is outside pending wraps +			if ((lineToWrap > wrapPending.end) || (lineToWrapEnd < wrapPending.start)) { +				// Currently visible text does not need wrapping +				return false;  			} -			wrapStart = wrapLineLarge; -			wrapEnd = wrapLineLarge; -		} else { -			if (wrapEnd >= pdoc->LinesTotal()) -				wrapEnd = pdoc->LinesTotal(); -			//ElapsedTime et; -			int lineDocTop = cs.DocFromDisplay(topLine); -			int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop); +		} else if (ws == wsIdle) { +			lineToWrapEnd = lineToWrap + LinesOnScreen() + 100; +		} +		const int lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal()); +		lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap); + +		// Ensure all lines being wrapped are styled. +		pdoc->EnsureStyledTo(pdoc->LineStart(lineToWrapEnd)); + +		if (lineToWrap < lineToWrapEnd) { +  			PRectangle rcTextArea = GetClientRectangle();  			rcTextArea.left = vs.textStart;  			rcTextArea.right -= vs.rightMarginWidth; @@ -1628,56 +1625,32 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {  			RefreshStyleData();  			AutoSurface surface(this);  			if (surface) { -				bool priorityWrap = false; -				int lastLineToWrap = wrapEnd; -				int lineToWrap = wrapStart; -				if (!fullWrap) { -					if (priorityWrapLineStart >= 0) { -						// This is a priority wrap. -						lineToWrap = priorityWrapLineStart; -						lastLineToWrap = priorityWrapLineStart + linesInOneCall; -						priorityWrap = true; -					} else { -						// This is idle wrap. -						lastLineToWrap = wrapStart + linesInOneCall; -					} -					if (lastLineToWrap >= wrapEnd) -						lastLineToWrap = wrapEnd; -				} // else do a fullWrap. - -				// Ensure all lines being wrapped are styled. -				pdoc->EnsureStyledTo(pdoc->LineEnd(lastLineToWrap)); +//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd); -				// Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap); -				// Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd); -				while (lineToWrap < lastLineToWrap) { +				while (lineToWrap < lineToWrapEnd) {  					if (WrapOneLine(surface, lineToWrap)) {  						wrapOccurred = true;  					} +					wrapPending.Wrapped(lineToWrap);  					lineToWrap++;  				} -				if (!priorityWrap) -					wrapStart = lineToWrap; -				// If wrapping is done, bring it to resting position -				if (wrapStart >= wrapEnd) { -					wrapStart = wrapLineLarge; -					wrapEnd = wrapLineLarge; -				} + +				goodTopLine = cs.DisplayFromDoc(lineDocTop) + std::min(subLineTop, cs.GetHeight(lineDocTop)-1);  			} -			goodTopLine = cs.DisplayFromDoc(lineDocTop); -			if (subLineTop < cs.GetHeight(lineDocTop)) -				goodTopLine += subLineTop; -			else -				goodTopLine += cs.GetHeight(lineDocTop); -			//double durWrap = et.Duration(true); -			//Platform::DebugPrintf("Wrap:%9.6g \n", durWrap); +		} + +		// If wrapping is done, bring it to resting position +		if (wrapPending.start >= lineEndNeedWrap) { +			wrapPending.Reset();  		}  	} +  	if (wrapOccurred) {  		SetScrollBars();  		SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos()));  		SetVerticalScrollPos();  	} +  	return wrapOccurred;  } @@ -3565,13 +3538,8 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {  		RefreshPixMaps(surfaceWindow);  	} -	// Call priority lines wrap on a window of lines which are likely -	// to rendered with the following paint (that is wrap the visible -	// 	lines first). -	int startLineToWrap = cs.DocFromDisplay(topLine) - 5; -	if (startLineToWrap < 0) -		startLineToWrap = 0; -	if (WrapLines(false, startLineToWrap)) { +	// Wrap the visible lines if needed. +	if (WrapLines(wsVisible)) {  		// The wrapping process has changed the height of some lines so  		// abandon this paint for a complete repaint.  		if (AbandonPaint()) { @@ -6750,9 +6718,9 @@ bool Editor::Idle() {  	if (!wrappingDone) {  		// Wrap lines during idle. -		WrapLines(false, -1); +		WrapLines(wsIdle);  		// No more wrapping -		if (wrapStart == wrapEnd) +		if (!wrapPending.NeedsWrap())  			wrappingDone = true;  	} @@ -7056,8 +7024,8 @@ int Editor::ContractedFoldNext(int lineStart) const {  void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {  	// In case in need of wrapping to ensure DisplayFromDoc works. -	if (lineDoc >= wrapStart) -		WrapLines(true, -1); +	if (lineDoc >= wrapPending.start) +		WrapLines(wsAll);  	if (!cs.GetVisible(lineDoc)) {  		// Back up to find a non-blank line | 
