diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Document.cxx | 10 | ||||
| -rw-r--r-- | src/Document.h | 13 | ||||
| -rw-r--r-- | src/Editor.cxx | 277 | 
3 files changed, 154 insertions, 146 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 2c9ac34a9..b0070233f 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -1285,6 +1285,11 @@ const char *Document::MarginStyles(int line) {  	return static_cast<LineAnnotation*>(perLineData[ldMargin])->Styles(line);   } +StyledText Document::MarginStyledText(int line) { +	return StyledText(MarginLength(line), MarginText(line),  +		MarginMultipleStyles(line), MarginStyle(line), MarginStyles(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); @@ -1331,6 +1336,11 @@ const char *Document::AnnotationStyles(int line) {  	return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Styles(line);   } +StyledText Document::AnnotationStyledText(int line) { +	return StyledText(AnnotationLength(line), AnnotationText(line),  +		AnnotationMultipleStyles(line), AnnotationStyle(line), AnnotationStyles(line)); +} +  void Document::AnnotationSetText(int line, const char *text) {  	const int linesBefore = AnnotationLines(line);  	static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetText(line, text);  diff --git a/src/Document.h b/src/Document.h index c0d221d35..2804a9a4f 100644 --- a/src/Document.h +++ b/src/Document.h @@ -93,6 +93,17 @@ public:  /// Factory function for RegexSearchBase  extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable); +struct StyledText { +	size_t length; +	const char *text; +	bool multipleStyles; +	int style; +	const char *styles; +	StyledText(	size_t length_, const char *text_, bool multipleStyles_, int style_, const char *styles_) :  +		length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { +	} +}; +  /**   */  class Document : PerLine { @@ -258,6 +269,7 @@ public:  	const char *MarginText(int line);  	int MarginStyle(int line);  	const char *MarginStyles(int line); +	StyledText MarginStyledText(int line);  	void MarginSetStyle(int line, int style);  	void MarginSetStyles(int line, const char *styles);  	void MarginSetText(int line, const char *text); @@ -269,6 +281,7 @@ public:  	const char *AnnotationText(int line);  	const char *AnnotationStyles(int line);  	int AnnotationStyle(int line); +	StyledText AnnotationStyledText(int line);  	void AnnotationSetText(int line, const char *text);  	void AnnotationSetStyle(int line, int style);  	void AnnotationSetStyles(int line, const char *styles); diff --git a/src/Editor.cxx b/src/Editor.cxx index 0c15a8c98..580e2baa3 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1459,27 +1459,109 @@ static int istrlen(const char *s) {  	return static_cast<int>(strlen(s));  } +bool ValidStyledText(ViewStyle &vs, int styleOffset, const StyledText &st) { +	if (st.multipleStyles) { +		for (size_t iStyle=0;iStyle<st.length; iStyle++) { +			if (!vs.ValidStyle(static_cast<size_t>(styleOffset + st.styles[iStyle]))) +				return false; +		} +	} else { +		if (!vs.ValidStyle(static_cast<size_t>(styleOffset + st.style))) +			return false; +	} +	return true; +} + +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 StyledText &st) { +	const char *styles = st.styles; +	LineEnumerator le(st.text, st.length); +	int widthMax = 0; +	while (!le.Finished()) { +		LineSegment ls = le.Next(); +		int widthSubLine; +		if (st.multipleStyles) { +			widthSubLine = WidthStyledText(surface, vs, styleOffset, ls.s, styles, ls.len); +			styles += ls.len + 1; +		} else { +			widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, ls.s, ls.len); +		} +		if (widthSubLine > widthMax) +			widthMax = widthSubLine; +	} +	return widthMax; +} +  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, +	const StyledText &st, size_t start, size_t length) { + +	if (st.multipleStyles) { +		int x = rcText.left; +		size_t i = 0; +		while (i < length) { +			size_t end = i; +			int style = st.styles[i + start]; +			while (end < length-1 && st.styles[start+end+1] == style) +				end++; +			style += styleOffset; +			int width = surface->WidthText(vs.styles[style].font, st.text + start + i, end - i + 1); +			PRectangle rcSegment = rcText; +			rcSegment.left = x; +			rcSegment.right = x + width + 1; +			surface->DrawTextNoClip(rcSegment, vs.styles[style].font, +					ascent, st.text + start + i, end - i + 1, +					vs.styles[style].fore.allocated, +					vs.styles[style].back.allocated); +			x += width; +			i = end + 1; +		} +	} else { +		int style = st.style + styleOffset; +		surface->DrawTextNoClip(rcText, vs.styles[style].font, +				rcText.top + vs.maxAscent, st.text, st.length,  				vs.styles[style].fore.allocated,  				vs.styles[style].back.allocated); -		x += width; -		i = end + 1;  	}  } @@ -1666,34 +1748,20 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {  					        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; -								} +						StyledText marginStyledText  = pdoc->MarginStyledText(lineDoc); +						if (marginStyledText.text && ValidStyledText(vs, vs.marginStyleOffset, marginStyledText)) { +							if (marginStyledText.multipleStyles) {  								surface->FillRectangle(rcMarker,  -									vs.styles[marginStyles[0]+vs.marginStyleOffset].back.allocated); -								DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,  -									marginText, marginStyles, lengthMargin); +									vs.styles[marginStyledText.styles[0]+vs.marginStyleOffset].back.allocated);  							} 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); +								surface->FillRectangle(rcMarker, vs.styles[marginStyledText.style].back.allocated);  							} +							if (vs.ms[margin].style == SC_MARGIN_RTEXT) { +								int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, marginStyledText); +								rcMarker.left = rcMarker.right - width - 3; +							} +							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,  +								marginStyledText, 0, marginStyledText.length);  						}  					}  				} @@ -2279,107 +2347,30 @@ 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++) { +	StyledText annotationStyledText  = pdoc->AnnotationStyledText(line); +	int annotationStyle = annotationStyledText.style + vsDraw.annotationStyleOffset; +	if (annotationStyledText.multipleStyles) { +		for (size_t iStyle=0;iStyle<annotationStyledText.length; iStyle++) {  			if (!vsDraw.ValidStyle(static_cast<size_t>( -				vsDraw.annotationStyleOffset + annotationStyles[iStyle]))) +				vsDraw.annotationStyleOffset + annotationStyledText.styles[iStyle])))  				return;  		}  	} else {  		if (!vsDraw.ValidStyle(static_cast<size_t>(annotationStyle)))  			return;  	} -	if (annotationText) { +	if (annotationStyledText.text) {  		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 +			int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, annotationStyledText); +			widthAnnotation += vsDraw.spaceWidth * 2; // Margins  			rcSegment.left = xStart + indent;  			rcSegment.right = rcSegment.left + widthAnnotation;  			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated); @@ -2387,36 +2378,28 @@ void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int x  			rcSegment.left = xStart;  		}  		const int annotationLines = pdoc->AnnotationLines(line); -		LineEnumerator le(annotationText, lengthAnnotation); +		LineEnumerator le(annotationStyledText.text, annotationStyledText.length);  		LineSegment ls = le.Next(); -		annotationText = ls.s; -		lengthAnnotation = ls.len; +		size_t start = 0; +		size_t lengthAnnotation = ls.len;  		int lineInAnnotation = 0;  		while ((lineInAnnotation < annotationLine) && !le.Finished()) { -			annotationStyles += ls.len; +			start += ls.len + 1;  			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); +			if (annotationStyledText.multipleStyles) { +				surface->FillRectangle(rcText, vsDraw.styles[annotationStyledText.styles[start] + 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); +			rcText.left += vsDraw.spaceWidth;  		} +		DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,  +			annotationStyledText, start, lengthAnnotation);  		if (vs.annotationVisible == ANNOTATION_BOXED) {  			surface->MoveTo(rcSegment.left, rcSegment.top);  			surface->LineTo(rcSegment.left, rcSegment.bottom); @@ -3017,7 +3000,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {  	//Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);  	int endPosPaint = pdoc->Length();  	if (lineStyleLast < cs.LinesDisplayed()) -		endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast + 1)); +		endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast) + 1);  	int xStart = vs.fixedColumnWidth - xOffset;  	int ypos = 0; @@ -3707,6 +3690,8 @@ void Editor::ClearAll() {  	}  	if (!pdoc->IsReadOnly()) {  		cs.Clear(); +		pdoc->AnnotationClearAll(); +		pdoc->MarginClearAll();  	}  	pdoc->EndUndoAction();  	anchor = 0;  | 
