diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Document.cxx | 1 | ||||
| -rw-r--r-- | src/Document.h | 4 | ||||
| -rw-r--r-- | src/Editor.cxx | 211 | ||||
| -rw-r--r-- | src/Editor.h | 8 | 
4 files changed, 208 insertions, 16 deletions
| diff --git a/src/Document.cxx b/src/Document.cxx index 25cb0de9f..046a72683 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -57,6 +57,7 @@ Document::Document() {  	enteredReadOnlyCount = 0;  	tabInChars = 8;  	indentInChars = 0; +	actualIndentInChars = 8;  	useTabs = true;  	tabIndents = true;  	backspaceUnindents = false; diff --git a/src/Document.h b/src/Document.h index 18b47eaf5..e31f8e324 100644 --- a/src/Document.h +++ b/src/Document.h @@ -116,6 +116,7 @@ public:  	int dbcsCodePage;  	int tabInChars;  	int indentInChars; +	int actualIndentInChars;  	bool useTabs;  	bool tabIndents;  	bool backspaceUnindents; @@ -228,6 +229,7 @@ public:  	int ExtendStyleRange(int pos, int delta, bool singleLine = false);  	int ParaUp(int pos);  	int ParaDown(int pos); +	int IndentSize() { return actualIndentInChars; }  private:  	charClassification WordCharClass(unsigned char ch); @@ -239,8 +241,6 @@ private:  	void NotifyModifyAttempt();  	void NotifySavePoint(bool atSavePoint);  	void NotifyModified(DocModification mh); - -	int IndentSize() { return indentInChars ? indentInChars : tabInChars; }  };  /** diff --git a/src/Editor.cxx b/src/Editor.cxx index af5caf46d..63a015ce6 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -385,6 +385,10 @@ Editor::Editor() {  	docLineLastWrapped = -1;  	docLastLineToWrap = -1;  	backgroundWrapEnabled = true; +	wrapVisualFlags = 0; +	wrapVisualFlagsLocation = 0; +	wrapVisualStartIndent = 0; +	actualWrapVisualStartIndent = 0;  	hsStart = -1;  	hsEnd = -1; @@ -636,9 +640,16 @@ Point Editor::LocationFromPosition(int pos) {  		if (posInLine > ll->maxLineLength) {  			pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];  		} +  		for (int subLine = 0; subLine < ll->lines; subLine++) {  			if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {  				pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)]; +				if (actualWrapVisualStartIndent != 0) { +					int lineStart = ll->LineStart(subLine); +					bool continuedWrapLine = lineStart != 0; +					if (continuedWrapLine) +						pt.x += actualWrapVisualStartIndent * vs.aveCharWidth; +				}  			}  			if (posInLine >= ll->LineStart(subLine)) {  				pt.y += vs.lineHeight; @@ -691,6 +702,12 @@ int Editor::PositionFromLocation(Point pt) {  			int lineStart = ll->LineStart(subLine);  			int lineEnd = ll->LineStart(subLine + 1);  			int subLineStart = ll->positions[lineStart]; + +			if (actualWrapVisualStartIndent != 0) { +				bool continuedWrapLine = lineStart != 0; +				if (continuedWrapLine) +					pt.x -= actualWrapVisualStartIndent * vs.aveCharWidth; +			}  			for (int i = lineStart; i < lineEnd; i++) {  				if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) ||  				        IsEOLChar(ll->chars[i])) { @@ -735,6 +752,12 @@ int Editor::PositionFromLocationClose(Point pt) {  			int lineStart = ll->LineStart(subLine);  			int lineEnd = ll->LineStart(subLine + 1);  			int subLineStart = ll->positions[lineStart]; + +			if (actualWrapVisualStartIndent != 0) { +				bool continuedWrapLine = lineStart != 0; +				if (continuedWrapLine) +					pt.x -= actualWrapVisualStartIndent * vs.aveCharWidth; +			}  			for (int i = lineStart; i < lineEnd; i++) {  				if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) ||  				        IsEOLChar(ll->chars[i])) { @@ -767,6 +790,12 @@ int Editor::PositionFromLineX(int lineDoc, int x) {  		int lineStart = ll->LineStart(subLine);  		int lineEnd = ll->LineStart(subLine + 1);  		int subLineStart = ll->positions[lineStart]; + +		if (actualWrapVisualStartIndent != 0) { +			bool continuedWrapLine = lineStart != 0; +			if (continuedWrapLine) +				x -= actualWrapVisualStartIndent * vs.aveCharWidth; +		}  		for (int i = lineStart; i < lineEnd; i++) {  			if (x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) ||  			        IsEOLChar(ll->chars[i])) { @@ -1992,6 +2021,9 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou  			// Simple common case where line does not need wrapping.  			ll->lines = 1;  		} else { +			if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) { +				width -= vstyle.aveCharWidth; // take into account the space for end wrap mark +			}  			ll->lines = 0;  			// Calculate line start positions based upon width.  			// For now this is simplistic - wraps on byte rather than character and @@ -2018,6 +2050,8 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou  					ll->lines++;  					ll->SetLineStart(ll->lines, lastGoodBreak);  					startOffset = ll->positions[lastGoodBreak]; +					// take into account the space for start wrap mark and indent +					startOffset -= actualWrapVisualStartIndent * vstyle.aveCharWidth;  					p = lastGoodBreak + 1;  					continue;  				} @@ -2065,9 +2099,56 @@ void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight,  	              highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);  } +void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace, +                            bool isEndMarker, ColourAllocated wrapColour) { +	surface->PenColour(wrapColour); + +	enum { xa = 1 }; // gap before start +	int w = rcPlace.right - rcPlace.left - xa - 1; + +	bool xStraight = isEndMarker;  // x-mirrored symbol for start marker +	bool yStraight = true; +	//bool yStraight= isEndMarker; // comment in for start marker y-mirrowed + +	int x0 = xStraight ? rcPlace.left : rcPlace.right - 1; +	int y0 = yStraight ? rcPlace.top : rcPlace.bottom - 1; + +	int dy = (rcPlace.bottom - rcPlace.top) / 5; +	int y = (rcPlace.bottom - rcPlace.top) / 2 + dy; + +	struct Relative { +		Surface *surface; +		int xBase; +		int xDir; +		int yBase; +		int yDir; +		void MoveTo(int xRelative, int yRelative) { +		    surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative); +		} +		void LineTo(int xRelative, int yRelative) { +		    surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative); +		} +	}; +	Relative rel = {surface, x0, xStraight?1:-1, y0, yStraight?1:-1}; + +	// arrow head +	rel.MoveTo(xa, y); +	rel.LineTo(xa + 2*w / 3, y - dy); +	rel.MoveTo(xa, y); +	rel.LineTo(xa + 2*w / 3, y + dy); + +	// arrow body +	rel.MoveTo(xa, y); +	rel.LineTo(xa + w, y); +	rel.LineTo(xa + w, y - 2 * dy); +	rel.LineTo(xa - 1,   // on windows lineto is exclusive endpoint, perhaps GTK not... +	                y - 2 * dy); +} +  void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,                       int line, int lineEnd, int xStart, int subLine, int subLineStart, -                     bool overrideBackground, ColourAllocated background) { +                     bool overrideBackground, ColourAllocated background, +                     bool drawWrapMarkEnd, ColourAllocated wrapColour) {  	int styleMask = pdoc->stylingBitsMask;  	PRectangle rcSegment = rcLine; @@ -2079,6 +2160,7 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin  	int posLineEnd = pdoc->LineStart(line + 1);  	bool eolInSelection = (subLine == (ll->lines - 1)) &&  	                      (posLineEnd > ll->selStart) && (posLineEnd <= ll->selEnd) && (ll->selStart != ll->selEnd); +  	if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) {  		if (primarySelection)  			surface->FillRectangle(rcSegment, vsDraw.selbackground.allocated); @@ -2099,6 +2181,20 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin  	} else {  		surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);  	} + +	if (drawWrapMarkEnd) { +		PRectangle rcPlace = rcSegment; + +		if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { +			rcPlace.left = xEol + xStart; +			rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; +		} else { +			// draw left of the right text margin, to avoid clipping by the current clip rect +			rcPlace.right = rcLine.right - vs.rightMarginWidth; +			rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; +		} +		DrawWrapMarker(surface, rcPlace, true, wrapColour); +	}  }  void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, @@ -2151,9 +2247,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  	                                (!overrideBackground) && (vsDraw.whitespaceBackgroundSet);  	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline. -	int indentWidth = pdoc->indentInChars * vsDraw.spaceWidth; -	if (indentWidth == 0) -		indentWidth = pdoc->tabInChars * vsDraw.spaceWidth; +	int indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;  	int posLineStart = pdoc->LineStart(line); @@ -2165,6 +2259,51 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  		lineStart = ll->LineStart(subLine);  		lineEnd = ll->LineStart(subLine + 1);  	} + +	bool drawWrapMarkEnd = false; + +	if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) { +		if (subLine + 1 < ll->lines) { +			drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; +		} +	} + +	if (actualWrapVisualStartIndent != 0) { + +		bool continuedWrapLine = false; +		if (subLine < ll->lines) { +			continuedWrapLine = ll->LineStart(subLine) != 0; +		} + +		if (continuedWrapLine) { +			// draw continuation rect +			PRectangle rcPlace = rcSegment; + +			rcPlace.left = ll->positions[startseg] + xStart - subLineStart; +			rcPlace.right = rcPlace.left + actualWrapVisualStartIndent * vsDraw.aveCharWidth; + +			// default bgnd here.. +			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated); + +			// main line style would be below but this would be inconsistent with end markers +			// also would possibly not be the style at wrap point +			//int styleMain = ll->styles[lineStart]; +			//surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back.allocated); + +			if (wrapVisualFlags & SC_WRAPVISUALFLAG_START) { + +				if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) +					rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; +				else +					rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; + +				DrawWrapMarker(surface, rcPlace, false, vsDraw.whitespaceForeground.allocated); +			} + +			xStart += actualWrapVisualStartIndent * vsDraw.aveCharWidth; +		} +	} +  	int i;  	// Background drawing loop @@ -2222,7 +2361,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  	if (twoPhaseDraw) {  		DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd, -		        xStart, subLine, subLineStart, overrideBackground, background); +		        xStart, subLine, subLineStart, overrideBackground, background, +		        drawWrapMarkEnd, vsDraw.whitespaceForeground.allocated);  	}  	inIndentation = subLine == 0;	// Do not handle indentation except on first subline. @@ -2412,10 +2552,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  		}  	}  	// End of the drawing of the current line -  	if (!twoPhaseDraw) {  		DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd, -		        xStart, subLine, subLineStart, overrideBackground, background); +		        xStart, subLine, subLineStart, overrideBackground, background, +		        drawWrapMarkEnd, vsDraw.whitespaceForeground.allocated);  	}  	if (vsDraw.edgeState == EDGE_LINE) { @@ -2681,7 +2821,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {  					int FoldLevelCurr = (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;  					int FoldLevelPrev = (pdoc->GetLevel(lineDoc - 1) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;  					int FoldLevelFlags = (pdoc->GetLevel(lineDoc) & ~SC_FOLDLEVELNUMBERMASK) & ~(0xFFF0000); -					int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); +					int indentationStep = pdoc->IndentSize();  					// Draw line above fold  					if ((FoldLevelPrev < FoldLevelCurr)  					        || @@ -2719,6 +2859,13 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {  					if ((offset >= ll->LineStart(subLine)) &&  					        ((offset < ll->LineStart(subLine + 1)) || offset == ll->numCharsInLine)) {  						int xposCaret = ll->positions[offset] - ll->positions[ll->LineStart(subLine)] + xStart; + +						if (actualWrapVisualStartIndent != 0) { +							int lineStart = ll->LineStart(subLine); +							bool continuedWrapLine = lineStart != 0; +							if (continuedWrapLine) +								xposCaret += actualWrapVisualStartIndent * vs.aveCharWidth; +						}  						int widthOverstrikeCaret;  						if (posCaret == pdoc->Length())	{   // At end of document  							widthOverstrikeCaret = vs.aveCharWidth; @@ -3249,7 +3396,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {  				        pdoc->GetColumn(currentPos) > 0 && pdoc->backspaceUnindents) {  					pdoc->BeginUndoAction();  					int indentation = pdoc->GetLineIndentation(lineCurrentPos); -					int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); +					int indentationStep = pdoc->IndentSize();  					if (indentation % indentationStep == 0) {  						pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);  					} else { @@ -4292,8 +4439,7 @@ void Editor::Indent(bool forwards) {  			if (pdoc->GetColumn(currentPos) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&  			        pdoc->tabIndents) {  				int indentation = pdoc->GetLineIndentation(lineCurrentPos); -				int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); -				//~ pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep); +				int indentationStep = pdoc->IndentSize();  				pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep);  				SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos));  			} else { @@ -4317,7 +4463,7 @@ void Editor::Indent(bool forwards) {  			        pdoc->tabIndents) {  				pdoc->BeginUndoAction();  				int indentation = pdoc->GetLineIndentation(lineCurrentPos); -				int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); +				int indentationStep = pdoc->IndentSize();  				pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);  				SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos));  				pdoc->EndUndoAction(); @@ -5996,8 +6142,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  		break;  	case SCI_SETTABWIDTH: -		if (wParam > 0) +		if (wParam > 0) {  			pdoc->tabInChars = wParam; +			if (pdoc->indentInChars == 0) +				pdoc->actualIndentInChars = pdoc->tabInChars; +		}  		InvalidateStyleRedraw();  		break; @@ -6006,6 +6155,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_SETINDENT:  		pdoc->indentInChars = wParam; +		if (pdoc->indentInChars != 0) +			pdoc->actualIndentInChars = pdoc->indentInChars; +		else +			pdoc->actualIndentInChars = pdoc->tabInChars;  		InvalidateStyleRedraw();  		break; @@ -6068,6 +6221,38 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_GETWRAPMODE:  		return wrapState; +	case SCI_SETWRAPVISUALFLAGS: +		wrapVisualFlags = wParam; +		actualWrapVisualStartIndent = wrapVisualStartIndent; +		if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (actualWrapVisualStartIndent == 0)) +			actualWrapVisualStartIndent = 1; // must indent to show start visual +		InvalidateStyleRedraw(); +		ReconfigureScrollBars(); +		break; + +	case SCI_GETWRAPVISUALFLAGS: +		return wrapVisualFlags; + +	case SCI_SETWRAPVISUALFLAGSLOCATION: +		wrapVisualFlagsLocation = wParam; +		InvalidateStyleRedraw(); +		break; + +	case SCI_GETWRAPVISUALFLAGSLOCATION: +		return wrapVisualFlagsLocation; + +	case SCI_SETWRAPSTARTINDENT: +		wrapVisualStartIndent = wParam; +		actualWrapVisualStartIndent = wrapVisualStartIndent; +		if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (actualWrapVisualStartIndent == 0)) +			actualWrapVisualStartIndent = 1; // must indent to show start visual +		InvalidateStyleRedraw(); +		ReconfigureScrollBars(); +		break; + +	case SCI_GETWRAPSTARTINDENT: +		return wrapVisualStartIndent; +  	case SCI_SETLAYOUTCACHE:  		llc.SetLevel(wParam);  		break; diff --git a/src/Editor.h b/src/Editor.h index c9c4c26e1..76635e658 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -296,6 +296,10 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	int wrapWidth;  	int docLineLastWrapped;  	int docLastLineToWrap; +	int wrapVisualFlags; +	int wrapVisualFlagsLocation; +	int wrapVisualStartIndent; +	int actualWrapVisualStartIndent;  	Document *pdoc; @@ -368,9 +372,11 @@ protected:	// ScintillaBase subclass needs access to much of Editor  		int width=LineLayout::wrapWidthInfinite);  	ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, bool inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll);  	void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); +	void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourAllocated wrapColour);  	void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,  		int line, int lineEnd, int xStart, int subLine, int subLineStart, -		bool overrideBackground, ColourAllocated background); +		bool overrideBackground, ColourAllocated background, +		bool drawWrapMark, ColourAllocated wrapColour);  	void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,  		PRectangle rcLine, LineLayout *ll, int subLine=0);  	void RefreshPixMaps(Surface *surfaceWindow); | 
