diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Document.cxx | 164 | ||||
| -rw-r--r-- | src/Document.h | 47 | ||||
| -rw-r--r-- | src/Editor.cxx | 375 | ||||
| -rw-r--r-- | src/Editor.h | 5 | ||||
| -rw-r--r-- | src/PerLine.cxx | 464 | ||||
| -rw-r--r-- | src/PerLine.h | 104 | ||||
| -rw-r--r-- | src/ViewStyle.cxx | 11 | ||||
| -rw-r--r-- | src/ViewStyle.h | 4 | 
8 files changed, 1156 insertions, 18 deletions
| diff --git a/src/Document.cxx b/src/Document.cxx index e5913ad98..2c9ac34a9 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -17,6 +17,7 @@  #include "Partitioning.h"  #include "RunStyles.h"  #include "CellBuffer.h" +#include "PerLine.h"  #include "CharClassify.h"  #include "Decoration.h"  #include "Document.h" @@ -74,6 +75,14 @@ Document::Document() {  	matchesValid = false;  	regex = 0; + +	perLineData[ldMarkers] = new LineMarkers(); +	perLineData[ldLevels] = new LineLevels(); +	perLineData[ldState] = new LineState(); +	perLineData[ldMargin] = new LineAnnotation(); +	perLineData[ldAnnotation] = new LineAnnotation(); + +	cb.SetPerLine(this);  }  Document::~Document() { @@ -81,12 +90,30 @@ Document::~Document() {  		watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);  	}  	delete []watchers; +	for (int j=0; j<ldSize; j++) { +		delete perLineData[j]; +		perLineData[j] = 0; +	}  	watchers = 0;  	lenWatchers = 0;  	delete regex;  	regex = 0;  } +void Document::InsertLine(int line) { +	for (int j=0; j<ldSize; j++) { +		if (perLineData[j]) +			perLineData[j]->InsertLine(line); +	} +} + +void Document::RemoveLine(int line) { +	for (int j=0; j<ldSize; j++) { +		if (perLineData[j]) +			perLineData[j]->RemoveLine(line); +	} +} +  // Increase reference count and return its previous value.  int Document::AddRef() {  	return refCount++; @@ -106,8 +133,13 @@ void Document::SetSavePoint() {  	NotifySavePoint(true);  } +int Document::GetMark(int line) {  +	return static_cast<LineMarkers*>(perLineData[ldMarkers])->MarkValue(line);  +} +  int Document::AddMark(int line, int markerNum) { -	int prev = cb.AddMark(line, markerNum); +	int prev = static_cast<LineMarkers*>(perLineData[ldMarkers])-> +		AddMark(line, markerNum, LinesTotal());  	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);  	NotifyModified(mh);  	return prev; @@ -117,31 +149,38 @@ void Document::AddMarkSet(int line, int valueSet) {  	unsigned int m = valueSet;  	for (int i = 0; m; i++, m >>= 1)  		if (m & 1) -			cb.AddMark(line, i); +			static_cast<LineMarkers*>(perLineData[ldMarkers])-> +				AddMark(line, i, LinesTotal());  	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);  	NotifyModified(mh);  }  void Document::DeleteMark(int line, int markerNum) { -	cb.DeleteMark(line, markerNum); +	static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false);  	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);  	NotifyModified(mh);  }  void Document::DeleteMarkFromHandle(int markerHandle) { -	cb.DeleteMarkFromHandle(markerHandle); +	static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle);  	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);  	mh.line = -1;  	NotifyModified(mh);  }  void Document::DeleteAllMarks(int markerNum) { -	cb.DeleteAllMarks(markerNum); +	for (int line = 0; line < LinesTotal(); line++) { +		static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true); +	}  	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);  	mh.line = -1;  	NotifyModified(mh);  } +int Document::LineFromHandle(int markerHandle) {  +	return static_cast<LineMarkers*>(perLineData[ldMarkers])->LineFromHandle(markerHandle);  +} +  int Document::LineStart(int line) const {  	return cb.LineStart(line);  } @@ -181,7 +220,7 @@ int Document::VCHomePosition(int position) {  }  int Document::SetLevel(int line, int level) { -	int prev = cb.SetLevel(line, level); +	int prev = static_cast<LineLevels*>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());  	if (prev != level) {  		DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,  		                   LineStart(line), 0, 0, 0, line); @@ -192,6 +231,14 @@ int Document::SetLevel(int line, int level) {  	return prev;  } +int Document::GetLevel(int line) {  +	return static_cast<LineLevels*>(perLineData[ldLevels])->GetLevel(line);  +} + +void Document::ClearLevels() {  +	static_cast<LineLevels*>(perLineData[ldLevels])->ClearLevels();  +} +  static bool IsSubordinate(int levelStart, int levelTry) {  	if (levelTry & SC_FOLDLEVELWHITEFLAG)  		return true; @@ -1206,7 +1253,7 @@ void Document::EnsureStyledTo(int pos) {  }  int Document::SetLineState(int line, int state) { -	int statePrevious = cb.SetLineState(line, state); +	int statePrevious = static_cast<LineState*>(perLineData[ldState])->SetLineState(line, state);  	if (state != statePrevious) {  		DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);  		NotifyModified(mh); @@ -1214,6 +1261,109 @@ int Document::SetLineState(int line, int state) {  	return statePrevious;  } +int Document::GetLineState(int line) {  +	return static_cast<LineState*>(perLineData[ldState])->GetLineState(line);  +} + +int Document::GetMaxLineState() {  +	return static_cast<LineState*>(perLineData[ldState])->GetMaxLineState();  +} + +bool Document::MarginMultipleStyles(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldMargin])->MultipleStyles(line);  +} + +const char *Document::MarginText(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldMargin])->Text(line);  +} + +int Document::MarginStyle(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldMargin])->Style(line);  +} + +const char *Document::MarginStyles(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldMargin])->Styles(line);  +} + +void Document::MarginSetText(int line, const char *text) { +	static_cast<LineAnnotation*>(perLineData[ldMargin])->SetText(line, text);  +	DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line); +	NotifyModified(mh); +} + +void Document::MarginSetStyle(int line, int style) { +	static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyle(line, style);  +} + +void Document::MarginSetStyles(int line, const char *styles) { +	static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyles(line, styles);  +} + +int Document::MarginLength(int line) const { +	return static_cast<LineAnnotation*>(perLineData[ldMargin])->Length(line); +} + +void Document::MarginClearAll() { +	int maxEditorLine = LinesTotal(); +	for (int l=0;l<maxEditorLine;l++) +		MarginSetText(l, 0); +	// Free remaining data +	static_cast<LineAnnotation*>(perLineData[ldMargin])->ClearAll(); +} + +bool Document::AnnotationAny() const { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->AnySet();  +} + +bool Document::AnnotationMultipleStyles(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->MultipleStyles(line);  +} + +const char *Document::AnnotationText(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Text(line);  +} + +int Document::AnnotationStyle(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Style(line);  +} + +const char *Document::AnnotationStyles(int line) { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Styles(line);  +} + +void Document::AnnotationSetText(int line, const char *text) { +	const int linesBefore = AnnotationLines(line); +	static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetText(line, text);  +	const int linesAfter = AnnotationLines(line); +	DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); +	mh.annotationLinesAdded = linesAfter - linesBefore; +	NotifyModified(mh); +} + +void Document::AnnotationSetStyle(int line, int style) { +	static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyle(line, style);  +} + +void Document::AnnotationSetStyles(int line, const char *styles) { +	static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyles(line, styles);  +} + +int Document::AnnotationLength(int line) const { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Length(line); +} + +int Document::AnnotationLines(int line) const { +	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Lines(line); +} + +void Document::AnnotationClearAll() { +	int maxEditorLine = LinesTotal(); +	for (int l=0;l<maxEditorLine;l++) +		AnnotationSetText(l, 0); +	// Free remaining data +	static_cast<LineAnnotation*>(perLineData[ldAnnotation])->ClearAll(); +} +  void Document::IncrementStyleClock() {  	styleClock = (styleClock + 1) % 0x100000;  } diff --git a/src/Document.h b/src/Document.h index 2e8c43eeb..6c0d9d51c 100644 --- a/src/Document.h +++ b/src/Document.h @@ -95,7 +95,7 @@ extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable);  /**   */ -class Document { +class Document : PerLine {  public:  	/** Used to pair watcher pointer with user data. */ @@ -110,7 +110,6 @@ public:  	};  	enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation }; -  private:  	int refCount;  	CellBuffer cb; @@ -125,6 +124,10 @@ private:  	WatcherWithUserData *watchers;  	int lenWatchers; +	// ldSize is not real data - it is for dimensions and loops +	enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };	 +	PerLine *perLineData[ldSize]; +  	bool matchesValid;  	RegexSearchBase* regex; @@ -150,6 +153,9 @@ public:  	int AddRef();  	int Release(); +	virtual void InsertLine(int line); +	virtual void RemoveLine(int line); +  	int LineFromPosition(int pos);  	int ClampPositionIntoDocument(int pos);  	bool IsCrLf(int pos); @@ -200,21 +206,21 @@ public:  		cb.GetCharRange(buffer, position, lengthRetrieve);  	}  	char StyleAt(int position) { return cb.StyleAt(position); } -	int GetMark(int line) { return cb.GetMark(line); } +	int GetMark(int line);  	int AddMark(int line, int markerNum);  	void AddMarkSet(int line, int valueSet);  	void DeleteMark(int line, int markerNum);  	void DeleteMarkFromHandle(int markerHandle);  	void DeleteAllMarks(int markerNum); -	int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); } +	int LineFromHandle(int markerHandle);  	int LineStart(int line) const;  	int LineEnd(int line) const;  	int LineEndPosition(int position);  	int VCHomePosition(int position);  	int SetLevel(int line, int level); -	int GetLevel(int line) { return cb.GetLevel(line); } -	void ClearLevels() { cb.ClearLevels(); } +	int GetLevel(int line); +	void ClearLevels();  	int GetLastChild(int lineParent, int level=-1);  	int GetFoldParent(int line); @@ -245,8 +251,30 @@ public:  	void DecorationFillRange(int position, int value, int fillLength);  	int SetLineState(int line, int state); -	int GetLineState(int line) { return cb.GetLineState(line); } -	int GetMaxLineState() { return cb.GetMaxLineState(); } +	int GetLineState(int line); +	int GetMaxLineState(); + +	bool MarginMultipleStyles(int line); +	const char *MarginText(int line); +	int MarginStyle(int line); +	const char *MarginStyles(int line); +	void MarginSetStyle(int line, int style); +	void MarginSetStyles(int line, const char *styles); +	void MarginSetText(int line, const char *text); +	int MarginLength(int line) const; +	void MarginClearAll(); + +	bool AnnotationAny() const; +	bool AnnotationMultipleStyles(int line); +	const char *AnnotationText(int line); +	const char *AnnotationStyles(int line); +	int AnnotationStyle(int line); +	void AnnotationSetText(int line, const char *text); +	void AnnotationSetStyle(int line, int style); +	void AnnotationSetStyles(int line, const char *styles); +	int AnnotationLength(int line) const; +	int AnnotationLines(int line) const; +	void AnnotationClearAll();  	bool AddWatcher(DocWatcher *watcher, void *userData);  	bool RemoveWatcher(DocWatcher *watcher, void *userData); @@ -289,6 +317,7 @@ public:   	int line;  	int foldLevelNow;  	int foldLevelPrev; +	int annotationLinesAdded;  	int token;  	DocModification(int modificationType_, int position_=0, int length_=0, @@ -301,6 +330,7 @@ public:  		line(line_),  		foldLevelNow(0),  		foldLevelPrev(0), +		annotationLinesAdded(0),  		token(0) {}  	DocModification(int modificationType_, const Action &act, int linesAdded_=0) : @@ -312,6 +342,7 @@ public:  		line(0),  		foldLevelNow(0),  		foldLevelPrev(0), +		annotationLinesAdded(0),  		token(0) {}  }; diff --git a/src/Editor.cxx b/src/Editor.cxx index 5d709fe06..77fbb4cec 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1277,7 +1277,8 @@ bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {  		LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);  		linesWrapped = ll->lines;  	} -	return cs.SetHeight(lineToWrap, linesWrapped); +	return cs.SetHeight(lineToWrap, linesWrapped +  +		(vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));  }  // Check if wrapping needed and perform any needed wrapping. @@ -1315,7 +1316,8 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {  			if (wrapWidth != LineLayout::wrapWidthInfinite) {  				wrapWidth = LineLayout::wrapWidthInfinite;  				for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) { -					cs.SetHeight(lineDoc, 1); +					cs.SetHeight(lineDoc, 1 +  +						(vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));  				}  				wrapOccurred = true;  			} @@ -1457,6 +1459,30 @@ static int istrlen(const char *s) {  	return static_cast<int>(strlen(s));  } +void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,  +	const char *text, const char *styles, int length) { + +	int x = rcText.left; +	int i = 0; +	while (i < length) { +		int end = i; +		int style = styles[i]; +		while (end < length-1 && styles[end+1] == style) +			end++; +		style += styleOffset; +		int width = surface->WidthText(vs.styles[style].font, text + i, end - i + 1); +		PRectangle rcSegment = rcText; +		rcSegment.left = x; +		rcSegment.right = x + width + 1; +		surface->DrawTextNoClip(rcSegment, vs.styles[style].font, +				ascent, text + i, end - i + 1, +				vs.styles[style].fore.allocated, +				vs.styles[style].back.allocated); +		x += width; +		i = end + 1; +	} +} +  void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {  	if (vs.fixedColumnWidth == 0)  		return; @@ -1638,6 +1664,38 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {  					        rcNumber.top + vs.maxAscent, number, istrlen(number),  					        vs.styles[STYLE_LINENUMBER].fore.allocated,  					        vs.styles[STYLE_LINENUMBER].back.allocated); +				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { +					if (firstSubLine) { +						const char *marginText = pdoc->MarginText(lineDoc); +						int lengthMargin = pdoc->MarginLength(lineDoc); +						if (marginText) { +							if (pdoc->MarginMultipleStyles(lineDoc)) { +								const char *marginStyles = pdoc->MarginStyles(lineDoc); +								for (size_t iStyle=0;iStyle<static_cast<size_t>(lengthMargin); iStyle++) { +									if (!vs.ValidStyle(static_cast<size_t>( +										vs.marginStyleOffset + marginStyles[iStyle]))) +										return; +								} +								surface->FillRectangle(rcMarker,  +									vs.styles[marginStyles[0]+vs.marginStyleOffset].back.allocated); +								DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,  +									marginText, marginStyles, lengthMargin); +							} else { +								int style = pdoc->MarginStyle(lineDoc) + vs.marginStyleOffset; +								if (!vs.ValidStyle(static_cast<size_t>(style))) +									return; +								surface->FillRectangle(rcMarker, vs.styles[style].back.allocated); +								if (vs.ms[margin].style == SC_MARGIN_RTEXT) { +									int width = surface->WidthText(vs.styles[style].font, marginText, istrlen(marginText)); +									rcMarker.left = rcMarker.right - width - 3; +								} +								surface->DrawTextNoClip(rcMarker, vs.styles[style].font, +										rcMarker.top + vs.maxAscent, marginText, lengthMargin, +										vs.styles[style].fore.allocated, +										vs.styles[style].back.allocated); +							} +						} +					}  				}  				if (marks) { @@ -2221,6 +2279,161 @@ void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,  	        textBack, textFore);  } +struct LineSegment { +	const char *s; +	int len; +}; + +class LineEnumerator { +public: +	const char *s; +	int len; +	LineEnumerator(const char *s_, size_t len_) : s(s_), len(len_) { +	} +	LineSegment Next() { +		LineSegment ret; +		ret.s = s; +		int cur = 0; +		while ((cur < len) && (s[cur] != '\n')) +			cur++; +		ret.len = cur; +		s += cur + 1; +		len -= cur + 1; +		return ret; +	} +	bool Finished() const { +		return len <= 0; +	} +}; + +static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset, +	const char *text, const char *styles, size_t len) { +	int width = 0; +	size_t start = 0; +	while (start < len) { +		int style = styles[start]; +		size_t endSegment = start; +		while ((endSegment < len-1) && (styles[endSegment+1] == style)) +			endSegment++; +		width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, endSegment - start + 1); +		start = endSegment + 1; +	} +	return width; +} + +static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, +	const char *text, const char *styles, size_t len) { +	LineEnumerator le(text, len); +	int widthComment = 0; +	while (!le.Finished()) { +		LineSegment ls = le.Next(); +		int widthSubLine = WidthStyledText(surface, vs, styleOffset, ls.s, styles, ls.len); +		if (widthSubLine > widthComment) +			widthComment = widthSubLine; +		styles += ls.len; +	} +	return widthComment; +} + +static int WidestLineWidth(Surface *surface, const char *text, size_t len, Font &font) { +	LineEnumerator le(text, len); +	int widthComment = 0; +	while (!le.Finished()) { +		LineSegment ls = le.Next(); +		int widthSubLine = surface->WidthText(font, ls.s, ls.len); +		if (widthSubLine > widthComment) +			widthComment = widthSubLine; +	} +	return widthComment; +} + +void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, +    PRectangle rcLine, LineLayout *ll, int subLine) { +	int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth; +	PRectangle rcSegment = rcLine; +	int annotationLine = subLine - ll->lines; +	int annotationStyle = pdoc->AnnotationStyle(line) + vsDraw.annotationStyleOffset; +	const char *annotationText = pdoc->AnnotationText(line); +	const char *annotationStyles = pdoc->AnnotationStyles(line); +	int lengthAnnotation = pdoc->AnnotationLength(line); +	const bool multipleStyles = pdoc->AnnotationMultipleStyles(line); +	if (multipleStyles) { +		for (size_t iStyle=0;iStyle<static_cast<size_t>(lengthAnnotation); iStyle++) { +			if (!vsDraw.ValidStyle(static_cast<size_t>( +				vsDraw.annotationStyleOffset + annotationStyles[iStyle]))) +				return; +		} +	} else { +		if (!vsDraw.ValidStyle(static_cast<size_t>(annotationStyle))) +			return; +	} +	if (annotationText) { +		surface->FillRectangle(rcSegment, vsDraw.styles[0].back.allocated); + +		if (vs.annotationVisible == ANNOTATION_BOXED) { +			// Only care about calculating width if need to draw box +			int widthAnnotation; +			if (multipleStyles) { +				widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, +					annotationText, annotationStyles, lengthAnnotation); +			} else { +				widthAnnotation = WidestLineWidth(surface, annotationText, lengthAnnotation, vsDraw.styles[annotationStyle].font); +			} +			widthAnnotation += 16; // Margin +			rcSegment.left = xStart + indent; +			rcSegment.right = rcSegment.left + widthAnnotation; +			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated); +		} else { +			rcSegment.left = xStart; +		} +		const int annotationLines = pdoc->AnnotationLines(line); +		LineEnumerator le(annotationText, lengthAnnotation); +		LineSegment ls = le.Next(); +		annotationText = ls.s; +		lengthAnnotation = ls.len; +		int lineInAnnotation = 0; +		while ((lineInAnnotation < annotationLine) && !le.Finished()) { +			annotationStyles += ls.len; +			ls = le.Next(); +			annotationText = ls.s; +			lengthAnnotation = ls.len; +			lineInAnnotation++; +		} +		PRectangle rcText = rcSegment; +		if (vs.annotationVisible == ANNOTATION_BOXED) { +			if (multipleStyles) { +				surface->FillRectangle(rcText, vsDraw.styles[annotationStyles[0] + vsDraw.annotationStyleOffset].back.allocated); +			} else { +				surface->FillRectangle(rcText, vsDraw.styles[annotationStyle].back.allocated); +			} +			rcText.left += 8; +		} +		if (multipleStyles) { +			DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,  +				annotationText, annotationStyles, lengthAnnotation); +		} else { +			surface->DrawTextNoClip(rcText, vsDraw.styles[annotationStyle].font, +					rcLine.top + vsDraw.maxAscent, annotationText, lengthAnnotation, +					vsDraw.styles[annotationStyle].fore.allocated, +					vsDraw.styles[annotationStyle].back.allocated); +		} +		if (vs.annotationVisible == ANNOTATION_BOXED) { +			surface->MoveTo(rcSegment.left, rcSegment.top); +			surface->LineTo(rcSegment.left, rcSegment.bottom); +			surface->MoveTo(rcSegment.right, rcSegment.top); +			surface->LineTo(rcSegment.right, rcSegment.bottom); +			if (subLine == ll->lines){ +				surface->MoveTo(rcSegment.left, rcSegment.top); +				surface->LineTo(rcSegment.right, rcSegment.top); +			}  +			if (subLine == ll->lines+annotationLines-1) { +				surface->MoveTo(rcSegment.left, rcSegment.bottom - 1); +				surface->LineTo(rcSegment.right, rcSegment.bottom - 1); +			} +		} +	} +} +  void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,          PRectangle rcLine, LineLayout *ll, int subLine) { @@ -2280,6 +2493,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  	int startseg = ll->LineStart(subLine);  	int subLineStart = ll->positions[startseg]; +	if (subLine >= ll->lines) { +		DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine); +		return; // No further drawing +	}  	int lineStart = 0;  	int lineEnd = 0;  	if (subLine < ll->lines) { @@ -3810,6 +4027,10 @@ void Editor::CheckModificationForWrap(DocModification mh) {  			int lines = Platform::Maximum(0, mh.linesAdded);  			NeedWrapping(lineDoc, lineDoc + lines + 1);  		} +		// Fix up annotation heights +		int lineDoc = pdoc->LineFromPosition(mh.position); +		int lines = Platform::Maximum(0, mh.linesAdded); +		SetAnnotationHeights(lineDoc, lineDoc + lines + 2);  	}  } @@ -3897,6 +4118,12 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {  				cs.DeleteLines(lineOfPos, -mh.linesAdded);  			}  		} +		if (mh.modificationType & SC_MOD_CHANGEANNOTATION) { +			int lineDoc = pdoc->LineFromPosition(mh.position); +			if (vs.annotationVisible) { +				cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded); +			} +		}  		CheckModificationForWrap(mh);  		if (mh.linesAdded != 0) {  			// Avoid scrolling of display if change before current display @@ -3927,7 +4154,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {  		SetScrollBars();  	} -	if (mh.modificationType & SC_MOD_CHANGEMARKER) { +	if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {  		if ((paintState == notPainting) || !PaintContainsMargin()) {  			if (mh.modificationType & SC_MOD_CHANGEFOLD) {  				// Fold changes can affect the drawing of following lines so redraw whole margin @@ -3962,6 +4189,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {  		scn.foldLevelNow = mh.foldLevelNow;  		scn.foldLevelPrev = mh.foldLevelPrev;  		scn.token = mh.token; +		scn.annotationLinesAdded = mh.annotationLinesAdded;  		NotifyParent(scn);  	}  } @@ -4231,8 +4459,16 @@ void Editor::NewLine() {  void Editor::CursorUpOrDown(int direction, selTypes sel) {  	Point pt = LocationFromPosition(currentPos); +	int lineDoc = pdoc->LineFromPosition(currentPos); +	Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); +	int subLine = (pt.y - ptStartLine.y) / vs.lineHeight; +	int commentLines = vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0;  	int posNew = PositionFromLocation(  	            Point(lastXChosen, pt.y + direction * vs.lineHeight)); +	if ((direction > 0) && (subLine >= (cs.GetHeight(lineDoc) - 1 - commentLines))) { +		posNew = PositionFromLocation( +	            Point(lastXChosen, pt.y + (commentLines + 1) * vs.lineHeight)); +	}  	if (direction < 0) {  		// Line wrapping may lead to a location on the same line, so  		// seek back if that is the case. @@ -5668,6 +5904,14 @@ void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {  	}  } +void Editor::SetAnnotationHeights(int start, int end) { +	if (vs.annotationVisible) { +		for (int line=start; line<end; line++) { +			cs.SetHeight(line, pdoc->AnnotationLines(line) + 1); +		} +	} +} +  void Editor::SetDocPointer(Document *document) {  	//Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);  	pdoc->RemoveWatcher(this, 0); @@ -5692,6 +5936,7 @@ void Editor::SetDocPointer(Document *document) {  	// Reset the contraction state to fully shown.  	cs.Clear();  	cs.InsertLines(0, pdoc->LinesTotal() - 1); +	SetAnnotationHeights(0, pdoc->LinesTotal());  	llc.Deallocate();  	NeedWrapping(); @@ -5700,6 +5945,22 @@ void Editor::SetDocPointer(Document *document) {  	Redraw();  } +void Editor::SetAnnotationVisible(int visible) { +	if (vs.annotationVisible != visible) { +		bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0)); +		vs.annotationVisible = visible; +		if (changedFromOrToHidden) { +			int dir = vs.annotationVisible ? 1 : -1; +			for (int line=0; line<pdoc->LinesTotal(); line++) { +				int annotationLines = pdoc->AnnotationLines(line); +				if (annotationLines > 0) { +					cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir); +				} +			} +		} +	} +} +  /**   * Recursively expand a fold, making lines visible except where they have an unexpanded parent.   */ @@ -7636,6 +7897,114 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_GETEXTRADESCENT:  		return vs.extraDescent; +	case SCI_MARGINSETSTYLEOFFSET: +		vs.marginStyleOffset = wParam; +		InvalidateStyleRedraw(); +		break; + +	case SCI_MARGINGETSTYLEOFFSET: +		return vs.marginStyleOffset; + +	case SCI_MARGINSETTEXT: +		pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam)); +		break; + +	case SCI_MARGINGETTEXT: { +			const char *text = pdoc->MarginText(wParam); +			if (lParam) { +				if (text) +					memcpy(CharPtrFromSPtr(lParam), text, pdoc->MarginLength(wParam)); +				else +					strcpy(CharPtrFromSPtr(lParam), ""); +			} +			return text ? pdoc->MarginLength(wParam) : 0; +		} + +	case SCI_MARGINSETSTYLE: +		pdoc->MarginSetStyle(wParam, lParam); +		break; + +	case SCI_MARGINGETSTYLE: +		return pdoc->MarginStyle(wParam); + +	case SCI_MARGINSETSTYLES: +		pdoc->MarginSetStyles(wParam, CharPtrFromSPtr(lParam)); +		break; + +	case SCI_MARGINGETSTYLES: { +			const char *styles = pdoc->MarginStyles(wParam); +			if (lParam) { +				if (styles) +					memcpy(CharPtrFromSPtr(lParam), styles, pdoc->MarginLength(wParam)); +				else +					strcpy(CharPtrFromSPtr(lParam), ""); +			} +			return styles ? pdoc->MarginLength(wParam) : 0; +		} + +	case SCI_MARGINTEXTCLEARALL: +		pdoc->MarginClearAll(); +		break; + +	case SCI_ANNOTATIONSETTEXT: +		pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam)); +		break; + +	case SCI_ANNOTATIONGETTEXT: { +			const char *text = pdoc->AnnotationText(wParam); +			if (lParam) { +				if (text) +					memcpy(CharPtrFromSPtr(lParam), text, pdoc->AnnotationLength(wParam)); +				else +					strcpy(CharPtrFromSPtr(lParam), ""); +			} +			return text ? pdoc->AnnotationLength(wParam) : 0; +		} + +	case SCI_ANNOTATIONGETSTYLE: +		return pdoc->AnnotationStyle(wParam); + +	case SCI_ANNOTATIONSETSTYLE: +		pdoc->AnnotationSetStyle(wParam, lParam); +		break; + +	case SCI_ANNOTATIONSETSTYLES: +		pdoc->AnnotationSetStyles(wParam, CharPtrFromSPtr(lParam)); +		break; + +	case SCI_ANNOTATIONGETSTYLES: { +			const char *styles = pdoc->AnnotationStyles(wParam); +			if (lParam) { +				if (styles) +					memcpy(CharPtrFromSPtr(lParam), styles, pdoc->AnnotationLength(wParam)); +				else +					strcpy(CharPtrFromSPtr(lParam), ""); +			} +			return styles ? pdoc->AnnotationLength(wParam) : 0; +		} + +	case SCI_ANNOTATIONGETLINES: +		return pdoc->AnnotationLines(wParam); + +	case SCI_ANNOTATIONCLEARALL: +		pdoc->AnnotationClearAll(); +		break; + +	case SCI_ANNOTATIONSETVISIBLE: +		SetAnnotationVisible(wParam); +		break; + +	case SCI_ANNOTATIONGETVISIBLE: +		return vs.annotationVisible; + +	case SCI_ANNOTATIONSETSTYLEOFFSET: +		vs.annotationStyleOffset = wParam; +		InvalidateStyleRedraw(); +		break; + +	case SCI_ANNOTATIONGETSTYLEOFFSET: +		return vs.annotationStyleOffset; +  	case SCI_ADDUNDOACTION:  		pdoc->AddUndoAction(wParam);  		break; diff --git a/src/Editor.h b/src/Editor.h index 0d0b8ac9c..35564ca8c 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -322,6 +322,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  		bool drawWrapMark, ColourAllocated wrapColour);  	void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,  		PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); +	void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, +        PRectangle rcLine, LineLayout *ll, int subLine);  	void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,  		PRectangle rcLine, LineLayout *ll, int subLine=0);  	void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret); @@ -443,7 +445,10 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	void CheckForChangeOutsidePaint(Range r);  	void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); +	void SetAnnotationHeights(int start, int end);  	void SetDocPointer(Document *document); +	 +	void SetAnnotationVisible(int visible);  	void Expand(int &line, bool doExpand);  	void ToggleContraction(int line); diff --git a/src/PerLine.cxx b/src/PerLine.cxx new file mode 100644 index 000000000..b90416abb --- /dev/null +++ b/src/PerLine.cxx @@ -0,0 +1,464 @@ +// Scintilla source code edit control +/** @file PerLine.cxx + ** Manages data associated with each line of the document + **/ +// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <string.h> + +#include "Platform.h" + +#include "Scintilla.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "CellBuffer.h" +#include "PerLine.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +MarkerHandleSet::MarkerHandleSet() { +	root = 0; +} + +MarkerHandleSet::~MarkerHandleSet() { +	MarkerHandleNumber *mhn = root; +	while (mhn) { +		MarkerHandleNumber *mhnToFree = mhn; +		mhn = mhn->next; +		delete mhnToFree; +	} +	root = 0; +} + +int MarkerHandleSet::Length() const { +	int c = 0; +	MarkerHandleNumber *mhn = root; +	while (mhn) { +		c++; +		mhn = mhn->next; +	} +	return c; +} + +int MarkerHandleSet::NumberFromHandle(int handle) const { +	MarkerHandleNumber *mhn = root; +	while (mhn) { +		if (mhn->handle == handle) { +			return mhn->number; +		} +		mhn = mhn->next; +	} +	return - 1; +} + +int MarkerHandleSet::MarkValue() const { +	unsigned int m = 0; +	MarkerHandleNumber *mhn = root; +	while (mhn) { +		m |= (1 << mhn->number); +		mhn = mhn->next; +	} +	return m; +} + +bool MarkerHandleSet::Contains(int handle) const { +	MarkerHandleNumber *mhn = root; +	while (mhn) { +		if (mhn->handle == handle) { +			return true; +		} +		mhn = mhn->next; +	} +	return false; +} + +bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { +	MarkerHandleNumber *mhn = new MarkerHandleNumber; +	if (!mhn) +		return false; +	mhn->handle = handle; +	mhn->number = markerNum; +	mhn->next = root; +	root = mhn; +	return true; +} + +void MarkerHandleSet::RemoveHandle(int handle) { +	MarkerHandleNumber **pmhn = &root; +	while (*pmhn) { +		MarkerHandleNumber *mhn = *pmhn; +		if (mhn->handle == handle) { +			*pmhn = mhn->next; +			delete mhn; +			return; +		} +		pmhn = &((*pmhn)->next); +	} +} + +bool MarkerHandleSet::RemoveNumber(int markerNum) { +	bool performedDeletion = false; +	MarkerHandleNumber **pmhn = &root; +	while (*pmhn) { +		MarkerHandleNumber *mhn = *pmhn; +		if (mhn->number == markerNum) { +			*pmhn = mhn->next; +			delete mhn; +			performedDeletion = true; +		} else { +			pmhn = &((*pmhn)->next); +		} +	} +	return performedDeletion; +} + +void MarkerHandleSet::CombineWith(MarkerHandleSet *other) { +	MarkerHandleNumber **pmhn = &root; +	while (*pmhn) { +		pmhn = &((*pmhn)->next); +	} +	*pmhn = other->root; +	other->root = 0; +} + +LineMarkers::~LineMarkers() { +	for (int line = 0; line < markers.Length(); line++) { +		delete markers[line]; +		markers[line] = 0; +	} +	markers.DeleteAll(); +} + +void LineMarkers::InsertLine(int line) { +	if (markers.Length()) { +		markers.Insert(line, 0); +	} +} + +void LineMarkers::RemoveLine(int line) { +	// Retain the markers from the deleted line by oring them into the previous line +	if (markers.Length()) { +		if (line > 0) { +			MergeMarkers(line - 1); +		} +		markers.Delete(line); +	} +} + +int LineMarkers::LineFromHandle(int markerHandle) { +	if (markers.Length()) { +		for (int line = 0; line < markers.Length(); line++) { +			if (markers[line]) { +				if (markers[line]->Contains(markerHandle)) { +					return line; +				} +			} +		} +	} +	return -1; +} + +void LineMarkers::MergeMarkers(int pos) { +	if (markers[pos + 1] != NULL) { +		if (markers[pos] == NULL) +			markers[pos] = new MarkerHandleSet; +		markers[pos]->CombineWith(markers[pos + 1]); +		delete markers[pos + 1]; +		markers[pos + 1] = NULL; +	} +} + +int LineMarkers::MarkValue(int line) { +	if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) +		return markers[line]->MarkValue(); +	else +		return 0; +} + +int LineMarkers::AddMark(int line, int markerNum, int lines) { +	handleCurrent++; +	if (!markers.Length()) { +		// No existing markers so allocate one element per line +		markers.InsertValue(0, lines, 0); +	} +	if (!markers[line]) { +		// Need new structure to hold marker handle +		markers[line] = new MarkerHandleSet(); +		if (!markers[line]) +			return - 1; +	} +	markers[line]->InsertHandle(handleCurrent, markerNum); + +	return handleCurrent; +} + +void LineMarkers::DeleteMark(int line, int markerNum, bool all) { +	if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) { +		if (markerNum == -1) { +			delete markers[line]; +			markers[line] = NULL; +		} else { +			bool performedDeletion = markers[line]->RemoveNumber(markerNum); +			while (all && performedDeletion) { +				performedDeletion = markers[line]->RemoveNumber(markerNum); +			} +			if (markers[line]->Length() == 0) { +				delete markers[line]; +				markers[line] = NULL; +			} +		} +	} +} + +void LineMarkers::DeleteMarkFromHandle(int markerHandle) { +	int line = LineFromHandle(markerHandle); +	if (line >= 0) { +		markers[line]->RemoveHandle(markerHandle); +		if (markers[line]->Length() == 0) { +			delete markers[line]; +			markers[line] = NULL; +		} +	} +} + +LineLevels::~LineLevels() { +} + +void LineLevels::InsertLine(int line) { +	if (levels.Length()) { +		int level = SC_FOLDLEVELBASE; +		if ((line > 0) && (line < levels.Length())) {	 +			level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG; +		} +		levels.InsertValue(line, 1, level); +	} +} + +void LineLevels::RemoveLine(int line) { +	if (levels.Length()) { +		// Move up following lines but merge header flag from this line +		// to line before to avoid a temporary disappearence causing expansion. +		int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG; +		levels.Delete(line); +		if (line > 0) +			levels[line-1] |= firstHeader; +	} +} + +void LineLevels::ExpandLevels(int sizeNew) { +	levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE); +} + +void LineLevels::ClearLevels() { +	levels.DeleteAll(); +} + +int LineLevels::SetLevel(int line, int level, int lines) { +	int prev = 0; +	if ((line >= 0) && (line < lines)) { +		if (!levels.Length()) { +			ExpandLevels(lines + 1); +		} +		prev = levels[line]; +		if (prev != level) { +			levels[line] = level; +		} +	} +	return prev; +} + +int LineLevels::GetLevel(int line) { +	if (levels.Length() && (line >= 0) && (line < levels.Length())) { +		return levels[line]; +	} else { +		return SC_FOLDLEVELBASE; +	} +} + +LineState::~LineState() { +} + +void LineState::InsertLine(int line) { +	if (lineStates.Length()) { +		lineStates.EnsureLength(line); +		lineStates.Insert(line, 0); +	} +} + +void LineState::RemoveLine(int line) { +	if (lineStates.Length() > line) { +		lineStates.Delete(line); +	} +} + +int LineState::SetLineState(int line, int state) { +	lineStates.EnsureLength(line + 1); +	int stateOld = lineStates[line]; +	lineStates[line] = state; +	return stateOld; +} + +int LineState::GetLineState(int line) { +	lineStates.EnsureLength(line + 1); +	return lineStates[line]; +} + +int LineState::GetMaxLineState() { +	return lineStates.Length(); +} + +static int NumberLines(const char *text) { +	if (text) { +		int newLines = 0; +		while (*text) { +			if (*text == '\n') +				newLines++; +			text++; +		} +		return newLines+1; +	} else { +		return 0; +	} +} + +// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader +// and then has text and optional styles. + +static const int IndividualStyles = 0x100; + +struct AnnotationHeader { +	short style;	// Style IndividualStyles implies array of styles +	short lines; +	int length; +}; + +LineAnnotation::~LineAnnotation() { +	ClearAll(); +} + +void LineAnnotation::InsertLine(int line) { +	if (annotations.Length()) { +		annotations.Insert(line, 0); +	} +} + +void LineAnnotation::RemoveLine(int line) { +	if (annotations.Length() && (line < annotations.Length())) { +		delete []annotations[line]; +		annotations.Delete(line); +	} +} + +bool LineAnnotation::AnySet() const { +	return annotations.Length() > 0; +} + +bool LineAnnotation::MultipleStyles(int line) const { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line]) +		return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles; +	else +		return 0; +} + +int LineAnnotation::Style(int line) { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line]) +		return reinterpret_cast<AnnotationHeader *>(annotations[line])->style; +	else +		return 0; +} + +const char *LineAnnotation::Text(int line) const { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line]) +		return annotations[line]+sizeof(AnnotationHeader); +	else +		return 0; +} + +const char *LineAnnotation::Styles(int line) const { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line)) +		return annotations[line] + sizeof(AnnotationHeader) + Length(line); +	else +		return 0; +} + +static char *AllocateAnnotation(int length, int style) { +	size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0); +	char *ret = new char[len]; +	memset(ret, 0, len); +	return ret; +} + +void LineAnnotation::SetText(int line, const char *text) { +	if (text) { +		annotations.EnsureLength(line+1); +		int style = Style(line); +		if (annotations[line]) { +			delete []annotations[line]; +		} +		annotations[line] = AllocateAnnotation(strlen(text), style); +		AnnotationHeader *pah = reinterpret_cast<AnnotationHeader*>(annotations[line]); +		pah->style = static_cast<short>(style); +		pah->length = strlen(text); +		pah->lines = static_cast<short>(NumberLines(text)); +		memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length); +	} else { +		if (annotations.Length() && (line < annotations.Length()) && annotations[line]) { +			delete []annotations[line]; +			annotations[line] = 0; +		} +	} +} + +void LineAnnotation::ClearAll() { +	for (int line = 0; line < annotations.Length(); line++) { +		delete []annotations[line]; +		annotations[line] = 0; +	} +	annotations.DeleteAll(); +} + +void LineAnnotation::SetStyle(int line, int style) { +	annotations.EnsureLength(line+1); +	if (!annotations[line]) { +		annotations[line] = AllocateAnnotation(0, style); +	} +	reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style); +} + +void LineAnnotation::SetStyles(int line, const char *styles) { +	annotations.EnsureLength(line+1); +	if (!annotations[line]) { +		annotations[line] = AllocateAnnotation(0, IndividualStyles); +	} else { +		AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]); +		if (pahSource->style != IndividualStyles) { +			char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles); +			AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation); +			pahAlloc->length = pahSource->length; +			pahAlloc->lines = pahSource->lines; +			memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length); +			delete []annotations[line]; +			annotations[line] = allocation; +		} +	} +	AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]); +	pah->style = IndividualStyles; +	memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length); +} + +int LineAnnotation::Length(int line) const { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line]) +		return reinterpret_cast<AnnotationHeader *>(annotations[line])->length; +	else +		return 0; +} + +int LineAnnotation::Lines(int line) const { +	if (annotations.Length() && (line < annotations.Length()) && annotations[line]) +		return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines; +	else +		return 0; +} diff --git a/src/PerLine.h b/src/PerLine.h new file mode 100644 index 000000000..471219131 --- /dev/null +++ b/src/PerLine.h @@ -0,0 +1,104 @@ +// Scintilla source code edit control +/** @file PerLine.h + ** Manages data associated with each line of the document + **/ +// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +/** + * This holds the marker identifier and the marker type to display. + * MarkerHandleNumbers are members of lists. + */ +struct MarkerHandleNumber { +	int handle; +	int number; +	MarkerHandleNumber *next; +}; + +/** + * A marker handle set contains any number of MarkerHandleNumbers. + */ +class MarkerHandleSet { +	MarkerHandleNumber *root; + +public: +	MarkerHandleSet(); +	~MarkerHandleSet(); +	int Length() const; +	int NumberFromHandle(int handle) const; +	int MarkValue() const;	///< Bit set of marker numbers. +	bool Contains(int handle) const; +	bool InsertHandle(int handle, int markerNum); +	void RemoveHandle(int handle); +	bool RemoveNumber(int markerNum); +	void CombineWith(MarkerHandleSet *other); +}; + +class LineMarkers : public PerLine { +	SplitVector<MarkerHandleSet *> markers; +	/// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big. +	int handleCurrent; +public: +	LineMarkers() : handleCurrent(0) { +	} +	virtual ~LineMarkers(); +	virtual void InsertLine(int line); +	virtual void RemoveLine(int line); + +	int MarkValue(int line); +	int AddMark(int line, int marker, int lines); +	void MergeMarkers(int pos); +	void DeleteMark(int line, int markerNum, bool all); +	void DeleteMarkFromHandle(int markerHandle); +	int LineFromHandle(int markerHandle); +}; + +class LineLevels : public PerLine { +	SplitVector<int> levels; +public: +	virtual ~LineLevels(); +	virtual void InsertLine(int line); +	virtual void RemoveLine(int line); + +	void ExpandLevels(int sizeNew=-1); +	void ClearLevels(); +	int SetLevel(int line, int level, int lines); +	int GetLevel(int line); +}; + +class LineState : public PerLine { +	SplitVector<int> lineStates; +public: +	LineState() { +	} +	virtual ~LineState(); +	virtual void InsertLine(int line); +	virtual void RemoveLine(int line); + +	int SetLineState(int line, int state); +	int GetLineState(int line); +	int GetMaxLineState(); +}; + +class LineAnnotation : public PerLine { +	SplitVector<char *> annotations; +public: +	LineAnnotation() { +	} +	virtual ~LineAnnotation(); +	virtual void InsertLine(int line); +	virtual void RemoveLine(int line); + +	bool AnySet() const; +	bool MultipleStyles(int line) const; +	int Style(int line); +	const char *Text(int line) const; +	const char *Styles(int line) const; +	void SetText(int line, const char *text); +	void ClearAll(); +	void SetStyle(int line, int style); +	void SetStyles(int line, const char *styles); +	int Length(int line) const; +	int Lines(int line) const; +}; + diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 686862a2d..0955928b0 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -141,6 +141,9 @@ ViewStyle::ViewStyle(const ViewStyle &source) {  	extraFontFlag = source.extraFontFlag;  	extraAscent = source.extraAscent;  	extraDescent = source.extraDescent; +	marginStyleOffset = source.marginStyleOffset; +	annotationVisible = source.annotationVisible; +	annotationStyleOffset = source.annotationStyleOffset;  }  ViewStyle::~ViewStyle() { @@ -237,6 +240,9 @@ void ViewStyle::Init(size_t stylesSize_) {  	extraFontFlag = false;  	extraAscent = 0;  	extraDescent = 0; +	marginStyleOffset = 0; +	annotationVisible = ANNOTATION_HIDDEN; +	annotationStyleOffset = 0;  }  void ViewStyle::RefreshColourPalette(Palette &pal, bool want) { @@ -363,3 +369,8 @@ void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {  bool ViewStyle::ProtectionActive() const {  	return someStylesProtected;  } + +bool ViewStyle::ValidStyle(size_t styleIndex) const { +	return styleIndex < stylesSize; +} + diff --git a/src/ViewStyle.h b/src/ViewStyle.h index 3f8b856b9..5390848e5 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -104,6 +104,9 @@ public:  	bool extraFontFlag;  	int extraAscent;  	int extraDescent; +	int marginStyleOffset; +	int annotationVisible; +	int annotationStyleOffset;  	ViewStyle();  	ViewStyle(const ViewStyle &source); @@ -117,6 +120,7 @@ public:  	void ClearStyles();  	void SetStyleFontName(int styleIndex, const char *name);  	bool ProtectionActive() const; +	bool ValidStyle(size_t styleIndex) const;  };  #ifdef SCI_NAMESPACE | 
