diff options
| author | Prakash Sahni <unknown> | 2020-06-12 09:34:59 +1000 | 
|---|---|---|
| committer | Prakash Sahni <unknown> | 2020-06-12 09:34:59 +1000 | 
| commit | ee0f914744608d9a859aa7212fe839e5e638776e (patch) | |
| tree | 3c2546438e5a28d792d8f896e6df84f940e64b04 /src | |
| parent | 7bdbad1346fa2d34ab37d7fd7d1574b78f879b6f (diff) | |
| download | scintilla-mirror-ee0f914744608d9a859aa7212fe839e5e638776e.tar.gz | |
Backport: Bug [#2141]. Implement end of line annotations.
Backport of changeset 8306:1b383adfdf71.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Document.cxx | 35 | ||||
| -rw-r--r-- | src/Document.h | 8 | ||||
| -rw-r--r-- | src/EditView.cxx | 92 | ||||
| -rw-r--r-- | src/EditView.h | 2 | ||||
| -rw-r--r-- | src/Editor.cxx | 50 | ||||
| -rw-r--r-- | src/Editor.h | 1 | ||||
| -rw-r--r-- | src/ViewStyle.cxx | 4 | ||||
| -rw-r--r-- | src/ViewStyle.h | 2 | 
8 files changed, 192 insertions, 2 deletions
| diff --git a/src/Document.cxx b/src/Document.cxx index b3ff671da..be3c01fa3 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -140,6 +140,7 @@ Document::Document(int options) :  	perLineData[ldState] = Sci::make_unique<LineState>();  	perLineData[ldMargin] = Sci::make_unique<LineAnnotation>();  	perLineData[ldAnnotation] = Sci::make_unique<LineAnnotation>(); +	perLineData[ldEOLAnnotation] = Sci::make_unique<LineAnnotation>();  	decorations = DecorationListCreate(IsLarge()); @@ -215,6 +216,10 @@ LineAnnotation *Document::Annotations() const noexcept {  	return dynamic_cast<LineAnnotation *>(perLineData[ldAnnotation].get());  } +LineAnnotation *Document::EOLAnnotations() const noexcept { +	return dynamic_cast<LineAnnotation *>(perLineData[ldEOLAnnotation].get()); +} +  int Document::LineEndTypesSupported() const {  	if ((SC_CP_UTF8 == dbcsCodePage) && pli)  		return pli->LineEndTypesSupported(); @@ -2388,6 +2393,36 @@ void Document::AnnotationClearAll() {  	Annotations()->ClearAll();  } +StyledText Document::EOLAnnotationStyledText(Sci::Line line) const noexcept { +	const LineAnnotation *pla = EOLAnnotations(); +	return StyledText(pla->Length(line), pla->Text(line), +		pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); +} + +void Document::EOLAnnotationSetText(Sci::Line line, const char *text) { +	if (line >= 0 && line < LinesTotal()) { +		EOLAnnotations()->SetText(line, text); +		DocModification mh(SC_MOD_CHANGEEOLANNOTATION, LineStart(line), +			0, 0, 0, line); +		NotifyModified(mh); +	} +} + +void Document::EOLAnnotationSetStyle(Sci::Line line, int style) { +	EOLAnnotations()->SetStyle(line, style); +	const DocModification mh(SC_MOD_CHANGEEOLANNOTATION, LineStart(line), +		0, 0, 0, line); +	NotifyModified(mh); +} + +void Document::EOLAnnotationClearAll() { +	const Sci::Line maxEditorLine = LinesTotal(); +	for (Sci::Line l=0; l<maxEditorLine; l++) +		EOLAnnotationSetText(l, nullptr); +	// Free remaining data +	EOLAnnotations()->ClearAll(); +} +  void Document::IncrementStyleClock() noexcept {  	styleClock = (styleClock + 1) % 0x100000;  } diff --git a/src/Document.h b/src/Document.h index f56bf01eb..a9c591cb1 100644 --- a/src/Document.h +++ b/src/Document.h @@ -244,13 +244,14 @@ private:  	std::vector<WatcherWithUserData> watchers;  	// ldSize is not real data - it is for dimensions and loops -	enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; +	enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldEOLAnnotation, ldSize };  	std::unique_ptr<PerLine> perLineData[ldSize];  	LineMarkers *Markers() const noexcept;  	LineLevels *Levels() const noexcept;  	LineState *States() const noexcept;  	LineAnnotation *Margins() const noexcept;  	LineAnnotation *Annotations() const noexcept; +	LineAnnotation *EOLAnnotations() const noexcept;  	bool matchesValid;  	std::unique_ptr<RegexSearchBase> regex; @@ -483,6 +484,11 @@ public:  	int AnnotationLines(Sci::Line line) const noexcept;  	void AnnotationClearAll(); +	StyledText EOLAnnotationStyledText(Sci::Line line) const noexcept; +	void EOLAnnotationSetStyle(Sci::Line line, int style); +	void EOLAnnotationSetText(Sci::Line line, const char *text); +	void EOLAnnotationClearAll(); +  	bool AddWatcher(DocWatcher *watcher, void *userData);  	bool RemoveWatcher(DocWatcher *watcher, void *userData); diff --git a/src/EditView.cxx b/src/EditView.cxx index b3c577177..35fee11f5 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -986,7 +986,8 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle  		rcSegment.left = rcLine.left;  	rcSegment.right = rcLine.right; -	const bool fillRemainder = !lastSubLine || !model.GetFoldDisplayText(line); +	bool drawEOLAnnotationStyledText = (vsDraw.eolAnnotationVisible != EOLANNOTATION_HIDDEN) && model.pdoc->EOLAnnotationStyledText(line).text; +	const bool fillRemainder = (!lastSubLine || (!model.GetFoldDisplayText(line) && !drawEOLAnnotationStyledText));  	if (fillRemainder) {  		// Fill the remainder of the line  		FillLineRemainder(surface, model, vsDraw, ll, line, rcSegment, subLine); @@ -1194,6 +1195,93 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con  	}  } +void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line line, int xStart, PRectangle rcLine, int subLine, XYACCUMULATOR subLineStart, DrawPhase phase) { + +	const bool lastSubLine = subLine == (ll->lines - 1); +	if (!lastSubLine) +		return; + +	if (vsDraw.eolAnnotationVisible == EOLANNOTATION_HIDDEN) { +		return; +	} +	const StyledText stEOLAnnotation = model.pdoc->EOLAnnotationStyledText(line); +	if (!stEOLAnnotation.text || !ValidStyledText(vsDraw, vsDraw.eolAnnotationStyleOffset, stEOLAnnotation)) { +		return; +	} +	const size_t style = stEOLAnnotation.style + vsDraw.eolAnnotationStyleOffset; + +	PRectangle rcSegment = rcLine; +	FontAlias fontText = vsDraw.styles[style].font; +	const int widthEOLAnnotationText = static_cast<int>(surface->WidthText(fontText, stEOLAnnotation.text, stEOLAnnotation.length)); + +	const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; +	const XYPOSITION virtualSpace = model.sel.VirtualSpaceFor( +		model.pdoc->LineEnd(line)) * spaceWidth; +	rcSegment.left = xStart + +		static_cast<XYPOSITION>(ll->positions[ll->numCharsInLine] - subLineStart) +		+ virtualSpace + vsDraw.aveCharWidth; + +	const char *textFoldDisplay = model.GetFoldDisplayText(line); +	if (textFoldDisplay) { +		rcSegment.left += (static_cast<int>(surface->WidthText(fontText, textFoldDisplay, static_cast<int>(strlen(textFoldDisplay)))) + vsDraw.aveCharWidth); +	} +	rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthEOLAnnotationText); + +	const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); +	ColourDesired textFore = vsDraw.styles[style].fore; +	const ColourDesired textBack = TextBackground(model, vsDraw, ll, background, false, +											false, static_cast<int>(style), -1); + +	if (model.trackLineWidth) { +		if (rcSegment.right + 1> lineWidthMaxSeen) { +			// EOL Annotation text border drawn on rcSegment.right with width 1 is the last visible object of the line +			lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1); +		} +	} + +	if (phase & drawBack) { +		surface->FillRectangle(rcSegment, textBack); + +		// Fill Remainder of the line +		PRectangle rcRemainder = rcSegment; +		rcRemainder.left = rcRemainder.right; +		if (rcRemainder.left < rcLine.left) +			rcRemainder.left = rcLine.left; +		rcRemainder.right = rcLine.right; +		FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine); +	} + +	if (phase & drawText) { +		if (phasesDraw != phasesOne) { +			surface->DrawTextTransparent(rcSegment, fontText, +			rcSegment.top + vsDraw.maxAscent, stEOLAnnotation.text, stEOLAnnotation.length, +			textFore); +		} else { +			surface->DrawTextNoClip(rcSegment, fontText, +			rcSegment.top + vsDraw.maxAscent, stEOLAnnotation.text, stEOLAnnotation.length, +			textFore, textBack); +		} +	} + +	if (phase & drawIndicatorsFore) { +		if (vsDraw.eolAnnotationVisible == EOLANNOTATION_BOXED ) { +			surface->PenColour(textFore); +			PRectangle rcBox = rcSegment; +			rcBox.left = Sci::round(rcSegment.left); +			rcBox.right = Sci::round(rcSegment.right); +			const IntegerRectangle ircBox(rcBox); +			surface->MoveTo(ircBox.left, ircBox.top); +			surface->LineTo(ircBox.left, ircBox.bottom); +			surface->MoveTo(ircBox.right, ircBox.top); +			surface->LineTo(ircBox.right, ircBox.bottom); +			surface->MoveTo(ircBox.left, ircBox.top); +			surface->LineTo(ircBox.right, ircBox.top); +			surface->MoveTo(ircBox.left, ircBox.bottom - 1); +			surface->LineTo(ircBox.right, ircBox.bottom - 1); +		} +	} +} +  static constexpr bool AnnotationBoxedOrIndented(int annotationVisible) noexcept {  	return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED;  } @@ -1910,6 +1998,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl  			DrawBackground(surface, model, vsDraw, ll, rcLine, lineRange, posLineStart, xStart,  				subLine, background);  			DrawFoldDisplayText(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, subLineStart, drawBack); +			DrawEOLAnnotationText(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, subLineStart, drawBack);  			phase = static_cast<DrawPhase>(phase & ~drawBack);	// Remove drawBack to not draw again in DrawFoldDisplayText  			DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end,  				xStart, subLine, subLineStart, background); @@ -1938,6 +2027,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl  	}  	DrawFoldDisplayText(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, subLineStart, phase); +	DrawEOLAnnotationText(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, subLineStart, phase);  	if (phasesDraw == phasesOne) {  		DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end, diff --git a/src/EditView.h b/src/EditView.h index 5f2950dc5..0ff5ef834 100644 --- a/src/EditView.h +++ b/src/EditView.h @@ -131,6 +131,8 @@ public:  		ColourOptional background);  	void DrawFoldDisplayText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,  		Sci::Line line, int xStart, PRectangle rcLine, int subLine, XYACCUMULATOR subLineStart, DrawPhase phase); +	void DrawEOLAnnotationText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, +		Sci::Line line, int xStart, PRectangle rcLine, int subLine, XYACCUMULATOR subLineStart, DrawPhase phase);  	void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,  		Sci::Line line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);  	void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line lineDoc, diff --git a/src/Editor.cxx b/src/Editor.cxx index e655b7e82..195be8a01 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2122,6 +2122,7 @@ void Editor::ClearAll() {  		if (!pdoc->IsReadOnly()) {  			pcs->Clear();  			pdoc->AnnotationClearAll(); +			pdoc->EOLAnnotationClearAll();  			pdoc->MarginClearAll();  		}  	} @@ -2657,6 +2658,11 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {  				Redraw();  			}  		} +		if (mh.modificationType & SC_MOD_CHANGEEOLANNOTATION) { +			if (vs.eolAnnotationVisible) { +				Redraw(); +			} +		}  		CheckModificationForWrap(mh);  		if (mh.linesAdded != 0) {  			// Avoid scrolling of display if change before current display @@ -5298,6 +5304,13 @@ void Editor::SetAnnotationVisible(int visible) {  	}  } +void Editor::SetEOLAnnotationVisible(int visible) { +	if (vs.eolAnnotationVisible != visible) { +		vs.eolAnnotationVisible = visible; +		Redraw(); +	} +} +  /**   * Recursively expand a fold, making lines visible except where they have an unexpanded parent.   */ @@ -8055,6 +8068,43 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_ANNOTATIONGETSTYLEOFFSET:  		return vs.annotationStyleOffset; +	case SCI_EOLANNOTATIONSETTEXT: +		pdoc->EOLAnnotationSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam)); +		break; + +	case SCI_EOLANNOTATIONGETTEXT: { +			const StyledText st = pdoc->EOLAnnotationStyledText(static_cast<Sci::Line>(wParam)); +			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length); +		} + +	case SCI_EOLANNOTATIONGETSTYLE: { +			const StyledText st = pdoc->EOLAnnotationStyledText(static_cast<Sci::Line>(wParam)); +			return st.style; +		} + +	case SCI_EOLANNOTATIONSETSTYLE: +		pdoc->EOLAnnotationSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam)); +		break; + +	case SCI_EOLANNOTATIONCLEARALL: +		pdoc->EOLAnnotationClearAll(); +		break; + +	case SCI_EOLANNOTATIONSETVISIBLE: +		SetEOLAnnotationVisible(static_cast<int>(wParam)); +		break; + +	case SCI_EOLANNOTATIONGETVISIBLE: +		return vs.eolAnnotationVisible; + +	case SCI_EOLANNOTATIONSETSTYLEOFFSET: +		vs.eolAnnotationStyleOffset = static_cast<int>(wParam); +		InvalidateStyleRedraw(); +		break; + +	case SCI_EOLANNOTATIONGETSTYLEOFFSET: +		return vs.eolAnnotationStyleOffset; +  	case SCI_RELEASEALLEXTENDEDSTYLES:  		vs.ReleaseAllExtendedStyles();  		break; diff --git a/src/Editor.h b/src/Editor.h index 626b67325..4f629bad4 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -546,6 +546,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	virtual void SetDocPointer(Document *document);  	void SetAnnotationVisible(int visible); +	void SetEOLAnnotationVisible(int visible);  	Sci::Line ExpandLine(Sci::Line line);  	void SetFoldExpanded(Sci::Line lineDoc, bool expanded); diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 5b8a226f3..e2dc4b70e 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -128,6 +128,8 @@ ViewStyle::ViewStyle(const ViewStyle &source) : markers(MARKER_MAX + 1), indicat  	marginStyleOffset = source.marginStyleOffset;  	annotationVisible = source.annotationVisible;  	annotationStyleOffset = source.annotationStyleOffset; +	eolAnnotationVisible = source.eolAnnotationVisible; +	eolAnnotationStyleOffset = source.eolAnnotationStyleOffset;  	braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;  	braceHighlightIndicator = source.braceHighlightIndicator;  	braceBadLightIndicatorSet = source.braceBadLightIndicatorSet; @@ -261,6 +263,8 @@ void ViewStyle::Init(size_t stylesSize_) {  	marginStyleOffset = 0;  	annotationVisible = ANNOTATION_HIDDEN;  	annotationStyleOffset = 0; +	eolAnnotationVisible = EOLANNOTATION_HIDDEN; +	eolAnnotationStyleOffset = 0;  	braceHighlightIndicatorSet = false;  	braceHighlightIndicator = 0;  	braceBadLightIndicatorSet = false; diff --git a/src/ViewStyle.h b/src/ViewStyle.h index 33ea1d6c2..e5bf375f4 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -145,6 +145,8 @@ public:  	int marginStyleOffset;  	int annotationVisible;  	int annotationStyleOffset; +	int eolAnnotationVisible; +	int eolAnnotationStyleOffset;  	bool braceHighlightIndicatorSet;  	int braceHighlightIndicator;  	bool braceBadLightIndicatorSet; | 
