diff options
| -rw-r--r-- | cocoa/ScintillaCocoa.h | 3 | ||||
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 3 | ||||
| -rw-r--r-- | gtk/makefile | 3 | ||||
| -rw-r--r-- | qt/ScintillaEdit/ScintillaEdit.pro | 3 | ||||
| -rw-r--r-- | qt/ScintillaEditBase/ScintillaEditBase.pro | 3 | ||||
| -rw-r--r-- | qt/ScintillaEditBase/ScintillaQt.h | 3 | ||||
| -rw-r--r-- | scripts/HeaderOrder.txt | 3 | ||||
| -rw-r--r-- | src/EditModel.cxx | 74 | ||||
| -rw-r--r-- | src/EditModel.h | 67 | ||||
| -rw-r--r-- | src/EditView.cxx | 1815 | ||||
| -rw-r--r-- | src/EditView.h | 113 | ||||
| -rw-r--r-- | src/Editor.cxx | 2298 | ||||
| -rw-r--r-- | src/Editor.h | 141 | ||||
| -rw-r--r-- | src/MarginView.cxx | 532 | ||||
| -rw-r--r-- | src/MarginView.h | 47 | ||||
| -rw-r--r-- | src/ScintillaBase.cxx | 3 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 3 | ||||
| -rw-r--r-- | win32/deps.mak | 141 | ||||
| -rw-r--r-- | win32/makefile | 9 | ||||
| -rw-r--r-- | win32/scintilla.mak | 684 | 
20 files changed, 3316 insertions, 2632 deletions
| diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h index ec253b161..61d78c449 100644 --- a/cocoa/ScintillaCocoa.h +++ b/cocoa/ScintillaCocoa.h @@ -48,6 +48,9 @@  #include "CaseConvert.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "AutoComplete.h" diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index fe3547fe2..3285967da 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -57,6 +57,9 @@  #include "UniConversion.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "AutoComplete.h"  #include "ScintillaBase.h" diff --git a/gtk/makefile b/gtk/makefile index 10528fac1..c4c5822e8 100644 --- a/gtk/makefile +++ b/gtk/makefile @@ -90,7 +90,8 @@ deps:  $(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \  	CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o CaseConvert.o CaseFolder.o \ -	ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \ +	ScintillaBase.o ContractionState.o EditModel.o Editor.o EditView.o ExternalLexer.o MarginView.o \ +	PropSetSimple.o PlatGTK.o \  	KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o CharacterCategory.o ViewStyle.o \  	RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \  	$(MARSHALLER) $(LEXOBJS) diff --git a/qt/ScintillaEdit/ScintillaEdit.pro b/qt/ScintillaEdit/ScintillaEdit.pro index eb0250e4e..2ee0ef1d8 100644 --- a/qt/ScintillaEdit/ScintillaEdit.pro +++ b/qt/ScintillaEdit/ScintillaEdit.pro @@ -29,11 +29,14 @@ SOURCES += \      ../../src/RESearch.cxx \      ../../src/PositionCache.cxx \      ../../src/PerLine.cxx \ +    ../../src/MarginView.cxx \      ../../src/LineMarker.cxx \      ../../src/KeyMap.cxx \      ../../src/Indicator.cxx \      ../../src/ExternalLexer.cxx \ +    ../../src/EditView.cxx \      ../../src/Editor.cxx \ +    ../../src/EditModel.cxx \      ../../src/Document.cxx \      ../../src/Decoration.cxx \      ../../src/ContractionState.cxx \ diff --git a/qt/ScintillaEditBase/ScintillaEditBase.pro b/qt/ScintillaEditBase/ScintillaEditBase.pro index 6baf52193..4cdd0f257 100644 --- a/qt/ScintillaEditBase/ScintillaEditBase.pro +++ b/qt/ScintillaEditBase/ScintillaEditBase.pro @@ -27,11 +27,14 @@ SOURCES += \      ../../src/RESearch.cxx \      ../../src/PositionCache.cxx \      ../../src/PerLine.cxx \ +    ../../src/MarginView.cxx \      ../../src/LineMarker.cxx \      ../../src/KeyMap.cxx \      ../../src/Indicator.cxx \      ../../src/ExternalLexer.cxx \ +    ../../src/EditView.cxx \      ../../src/Editor.cxx \ +    ../../src/EditModel.cxx \      ../../src/Document.cxx \      ../../src/Decoration.cxx \      ../../src/ContractionState.cxx \ diff --git a/qt/ScintillaEditBase/ScintillaQt.h b/qt/ScintillaEditBase/ScintillaQt.h index 7defd7c05..ff4d65992 100644 --- a/qt/ScintillaEditBase/ScintillaQt.h +++ b/qt/ScintillaEditBase/ScintillaQt.h @@ -43,6 +43,9 @@  #include "Document.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "ScintillaBase.h"  #include "CaseConvert.h" diff --git a/scripts/HeaderOrder.txt b/scripts/HeaderOrder.txt index 96af584d3..d2a397bd9 100644 --- a/scripts/HeaderOrder.txt +++ b/scripts/HeaderOrder.txt @@ -106,6 +106,9 @@  #include "Selection.h"  #include "PositionCache.h"  #include "FontQuality.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "AutoComplete.h" diff --git a/src/EditModel.cxx b/src/EditModel.cxx new file mode 100644 index 000000000..815d22781 --- /dev/null +++ b/src/EditModel.cxx @@ -0,0 +1,74 @@ +// Scintilla source code edit control +/** @file EditModel.cxx + ** Defines the editor state that must be visible to EditorView. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <vector> +#include <map> +#include <algorithm> +#include <memory> + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +Caret::Caret() : +	active(false), on(false), period(500) {} + +EditModel::EditModel() { +	inOverstrike = false; +	xOffset = 0; +	trackLineWidth = false; +	posDrag = SelectionPosition(invalidPosition); +	braces[0] = invalidPosition; +	braces[1] = invalidPosition; +	bracesMatchStyle = STYLE_BRACEBAD; +	highlightGuideColumn = 0; +	primarySelection = true; +	foldFlags = 0; +	hotspot = Range(invalidPosition); +	wrapWidth = LineLayout::wrapWidthInfinite; +	pdoc = new Document(); +	pdoc->AddRef(); +} + +EditModel::~EditModel() { +	pdoc->Release(); +	pdoc = 0; +} diff --git a/src/EditModel.h b/src/EditModel.h new file mode 100644 index 000000000..86d2cd40e --- /dev/null +++ b/src/EditModel.h @@ -0,0 +1,67 @@ +// Scintilla source code edit control +/** @file EditModel.h + ** Defines the editor state that must be visible to EditorView. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef EDITMODEL_H +#define EDITMODEL_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +/** +*/ +class Caret { +public: +	bool active; +	bool on; +	int period; + +	Caret(); +}; + +class EditModel { +	// Private so EditModel objects can not be copied +	EditModel(const EditModel &); +	EditModel &operator=(const EditModel &); + +public: +	bool inOverstrike; +	int xOffset;		///< Horizontal scrolled amount in pixels +	bool trackLineWidth; + +	SpecialRepresentations reprs; +	Caret caret; +	SelectionPosition posDrag; +	Position braces[2]; +	int bracesMatchStyle; +	int highlightGuideColumn; +	Selection sel; +	bool primarySelection; + +	int foldFlags; +	ContractionState cs; +	// Hotspot support +	Range hotspot; + +	// Wrapping support +	int wrapWidth; + +	Document *pdoc; + +	EditModel(); +	~EditModel(); +	virtual int TopLineOfMain() const = 0; +	virtual Point GetVisibleOriginInMain() const = 0; +	virtual int LinesOnScreen() const = 0; +	virtual Range GetHotSpotRange() const = 0; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/EditView.cxx b/src/EditView.cxx new file mode 100644 index 000000000..26ede6cd9 --- /dev/null +++ b/src/EditView.cxx @@ -0,0 +1,1815 @@ +// Scintilla source code edit control +/** @file Editor.cxx + ** Defines the appearance of the main text area of the editor window. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <vector> +#include <map> +#include <algorithm> +#include <memory> + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsControlCharacter(int ch) { +	// iscntrl returns true for lots of chars > 127 which are displayable +	return ch >= 0 && ch < ' '; +} + +PrintParameters::PrintParameters() { +	magnification = 0; +	colourMode = SC_PRINT_NORMAL; +	wrapState = eWrapWord; +} + +const XYPOSITION epsilon = 0.0001f;	// A small nudge to avoid floating point precision issues + +EditView::EditView() { +	hideSelection = false; +	drawOverstrikeCaret = true; +	bufferedDraw = true; +	twoPhaseDraw = true; +	lineWidthMaxSeen = 0; +	additionalCaretsBlink = true; +	additionalCaretsVisible = true; +	pixmapLine = 0; +	pixmapIndentGuide = 0; +	pixmapIndentGuideHighlight = 0; +	llc.SetLevel(LineLayoutCache::llcCaret); +	posCache.SetSize(0x400); +} + +void EditView::DropGraphics(bool freeObjects) { +	if (freeObjects) { +		delete pixmapLine; +		pixmapLine = 0; +		delete pixmapIndentGuide; +		pixmapIndentGuide = 0; +		delete pixmapIndentGuideHighlight; +		pixmapIndentGuideHighlight = 0; +	} else { +		if (pixmapLine) +			pixmapLine->Release(); +		if (pixmapIndentGuide) +			pixmapIndentGuide->Release(); +		if (pixmapIndentGuideHighlight) +			pixmapIndentGuideHighlight->Release(); +	} +} + +void EditView::AllocateGraphics(const ViewStyle &vsDraw) { +	if (!pixmapLine) +		pixmapLine = Surface::Allocate(vsDraw.technology); +	if (!pixmapIndentGuide) +		pixmapIndentGuide = Surface::Allocate(vsDraw.technology); +	if (!pixmapIndentGuideHighlight) +		pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology); +} + +const char *ControlCharacterString(unsigned char ch) { +	const char *reps[] = { +		"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", +		"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", +		"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", +		"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" +	}; +	if (ch < ELEMENTS(reps)) { +		return reps[ch]; +	} else { +		return "BAD"; +	} +} + +void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { +	int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2; +	int xhead = static_cast<int>(rcTab.right) - 1 - ydiff; +	if (xhead <= rcTab.left) { +		ydiff -= static_cast<int>(rcTab.left) - xhead - 1; +		xhead = static_cast<int>(rcTab.left) - 1; +	} +	if ((rcTab.left + 2) < (rcTab.right - 1)) +		surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid); +	else +		surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid); +	surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid); +	surface->LineTo(xhead, ymid - ydiff); +	surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid); +	surface->LineTo(xhead, ymid + ydiff); +} + +void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { +	if (!pixmapIndentGuide->Initialised()) { +		// 1 extra pixel in height so can handle odd/even positions and so produce a continuous line +		pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); +		pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); +		PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight); +		pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back); +		pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore); +		pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back); +		pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore); +		for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) { +			PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1); +			pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore); +			pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore); +		} +	} +} + +LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) { +	int posLineStart = model.pdoc->LineStart(lineNumber); +	int posLineEnd = model.pdoc->LineStart(lineNumber + 1); +	PLATFORM_ASSERT(posLineEnd >= posLineStart); +	int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret()); +	return llc.Retrieve(lineNumber, lineCaret, +		posLineEnd - posLineStart, model.pdoc->GetStyleClock(), +		model.LinesOnScreen() + 1, model.pdoc->LinesTotal()); +} + +/** +* Fill in the LineLayout data for the given line. +* Copy the given @a line and its styles from the document into local arrays. +* Also determine the x position at which each character starts. +*/ +void EditView::LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, const EditModel &model, int width) { +	if (!ll) +		return; + +	PLATFORM_ASSERT(line < model.pdoc->LinesTotal()); +	PLATFORM_ASSERT(ll->chars != NULL); +	int posLineStart = model.pdoc->LineStart(line); +	int posLineEnd = model.pdoc->LineStart(line + 1); +	// If the line is very long, limit the treatment to a length that should fit in the viewport +	if (posLineEnd >(posLineStart + ll->maxLineLength)) { +		posLineEnd = posLineStart + ll->maxLineLength; +	} +	if (ll->validity == LineLayout::llCheckTextAndStyle) { +		int lineLength = posLineEnd - posLineStart; +		if (!vstyle.viewEOL) { +			lineLength = model.pdoc->LineEnd(line) - posLineStart; +		} +		if (lineLength == ll->numCharsInLine) { +			// See if chars, styles, indicators, are all the same +			bool allSame = true; +			// Check base line layout +			char styleByte = 0; +			int numCharsInLine = 0; +			while (numCharsInLine < lineLength) { +				int charInDoc = numCharsInLine + posLineStart; +				char chDoc = model.pdoc->CharAt(charInDoc); +				styleByte = model.pdoc->StyleAt(charInDoc); +				allSame = allSame && +					(ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte)); +				if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) +					allSame = allSame && +					(ll->chars[numCharsInLine] == chDoc); +				else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) +					allSame = allSame && +					(ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc))); +				else	// Style::caseUpper +					allSame = allSame && +					(ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc))); +				numCharsInLine++; +			} +			allSame = allSame && (ll->styles[numCharsInLine] == styleByte);	// For eolFilled +			if (allSame) { +				ll->validity = LineLayout::llPositions; +			} else { +				ll->validity = LineLayout::llInvalid; +			} +		} else { +			ll->validity = LineLayout::llInvalid; +		} +	} +	if (ll->validity == LineLayout::llInvalid) { +		ll->widthLine = LineLayout::wrapWidthInfinite; +		ll->lines = 1; +		if (vstyle.edgeState == EDGE_BACKGROUND) { +			ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge); +			if (ll->edgeColumn >= posLineStart) { +				ll->edgeColumn -= posLineStart; +			} +		} else { +			ll->edgeColumn = -1; +		} + +		// Fill base line layout +		const int lineLength = posLineEnd - posLineStart; +		model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength); +		model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); +		int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart; +		const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; +		for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { +			const unsigned char styleByte = ll->styles[styleInLine]; +			ll->styles[styleInLine] = styleByte; +		} +		const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0; +		if (vstyle.someStylesForceCase) { +			for (int charInLine = 0; charInLine<lineLength; charInLine++) { +				char chDoc = ll->chars[charInLine]; +				if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) +					ll->chars[charInLine] = static_cast<char>(toupper(chDoc)); +				else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) +					ll->chars[charInLine] = static_cast<char>(tolower(chDoc)); +			} +		} +		ll->xHighlightGuide = 0; +		// Extra element at the end of the line to hold end x position and act as +		ll->chars[numCharsInLine] = 0;   // Also triggers processing in the loops as this is a control character +		ll->styles[numCharsInLine] = styleByteLast;	// For eolFilled + +		// Layout the line, determining the position of each character, +		// with an extra element at the end for the end of the line. +		ll->positions[0] = 0; +		bool lastSegItalics = false; + +		BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs); +		while (bfLayout.More()) { + +			const TextSegment ts = bfLayout.Next(); + +			std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f); +			if (vstyle.styles[ll->styles[ts.start]].visible) { +				if (ts.representation) { +					XYPOSITION representationWidth = vstyle.controlCharWidth; +					if (ll->chars[ts.start] == '\t') { +						// Tab is a special case of representation, taking a variable amount of space +						representationWidth = +							((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start]; +					} else { +						if (representationWidth <= 0.0) { +							XYPOSITION positionsRepr[256];	// Should expand when needed +							posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(), +								static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, model.pdoc); +							representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding; +						} +					} +					for (int ii = 0; ii < ts.length; ii++) +						ll->positions[ts.start + 1 + ii] = representationWidth; +				} else { +					if ((ts.length == 1) && (' ' == ll->chars[ts.start])) { +						// Over half the segments are single characters and of these about half are space characters. +						ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth; +					} else { +						posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start, +							ts.length, ll->positions + ts.start + 1, model.pdoc); +					} +				} +				lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic); +			} + +			for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) { +				ll->positions[posToIncrease] += ll->positions[ts.start]; +			} +		} + +		// Small hack to make lines that end with italics not cut off the edge of the last character +		if (lastSegItalics) { +			ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset; +		} +		ll->numCharsInLine = numCharsInLine; +		ll->numCharsBeforeEOL = numCharsBeforeEOL; +		ll->validity = LineLayout::llPositions; +	} +	// Hard to cope when too narrow, so just assume there is space +	if (width < 20) { +		width = 20; +	} +	if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { +		ll->widthLine = width; +		if (width == LineLayout::wrapWidthInfinite) { +			ll->lines = 1; +		} else if (width > ll->positions[ll->numCharsInLine]) { +			// Simple common case where line does not need wrapping. +			ll->lines = 1; +		} else { +			if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { +				width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark +			} +			XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line +			if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) { +				wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth; +			} else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) { +				wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth; +			} +			ll->wrapIndent = wrapAddIndent; +			if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED) +			for (int i = 0; i < ll->numCharsInLine; i++) { +				if (!IsSpaceOrTab(ll->chars[i])) { +					ll->wrapIndent += ll->positions[i]; // Add line indent +					break; +				} +			} +			// Check for text width minimum +			if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15) +				ll->wrapIndent = wrapAddIndent; +			// Check for wrapIndent minimum +			if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) +				ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual +			ll->lines = 0; +			// Calculate line start positions based upon width. +			int lastGoodBreak = 0; +			int lastLineStart = 0; +			XYACCUMULATOR startOffset = 0; +			int p = 0; +			while (p < ll->numCharsInLine) { +				if ((ll->positions[p + 1] - startOffset) >= width) { +					if (lastGoodBreak == lastLineStart) { +						// Try moving to start of last character +						if (p > 0) { +							lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) +								- posLineStart; +						} +						if (lastGoodBreak == lastLineStart) { +							// Ensure at least one character on line. +							lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) +								- posLineStart; +						} +					} +					lastLineStart = lastGoodBreak; +					ll->lines++; +					ll->SetLineStart(ll->lines, lastGoodBreak); +					startOffset = ll->positions[lastGoodBreak]; +					// take into account the space for start wrap mark and indent +					startOffset -= ll->wrapIndent; +					p = lastGoodBreak + 1; +					continue; +				} +				if (p > 0) { +					if (vstyle.wrapState == eWrapChar) { +						lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) +							- posLineStart; +						p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart; +						continue; +					} else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) { +						lastGoodBreak = p; +					} else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) { +						lastGoodBreak = p; +					} +				} +				p++; +			} +			ll->lines++; +		} +		ll->validity = LineLayout::llLines; +	} +} + +Point EditView::LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs) { +	Point pt; +	if (pos.Position() == INVALID_POSITION) +		return pt; +	const int line = model.pdoc->LineFromPosition(pos.Position()); +	const int lineVisible = model.cs.DisplayFromDoc(line); +	//Platform::DebugPrintf("line=%d\n", line); +	AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); +	if (surface && ll) { +		const int posLineStart = model.pdoc->LineStart(line); +		LayoutLine(line, surface, vs, ll, model, model.wrapWidth); +		const int posInLine = pos.Position() - posLineStart; +		pt = ll->PointFromPosition(posInLine, vs.lineHeight); +		pt.y += (lineVisible - topLine) * vs.lineHeight; +		pt.x += vs.textStart - model.xOffset; +	} +	pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; +	return pt; +} + +SelectionPosition EditView::SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const EditModel &model, const ViewStyle &vs) { +	pt.x = pt.x - vs.textStart; +	int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight)); +	if (!canReturnInvalid && (visibleLine < 0)) +		visibleLine = 0; +	const int lineDoc = model.cs.DocFromDisplay(visibleLine); +	if (canReturnInvalid && (lineDoc < 0)) +		return SelectionPosition(INVALID_POSITION); +	if (lineDoc >= model.pdoc->LinesTotal()) +		return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length()); +	const int posLineStart = model.pdoc->LineStart(lineDoc); +	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); +	if (surface && ll) { +		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); +		const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); +		const int subLine = visibleLine - lineStartSet; +		if (subLine < ll->lines) { +			const Range rangeSubLine = ll->SubLineRange(subLine); +			const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; +			if (subLine > 0)	// Wrapped +				pt.x -= ll->wrapIndent; +			const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); +			if (positionInLine < rangeSubLine.end) { +				return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); +			} +			if (virtualSpace) { +				const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; +				const int spaceOffset = static_cast<int>( +					(pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); +				return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); +			} else if (canReturnInvalid) { +				if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { +					return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); +				} +			} else { +				return SelectionPosition(rangeSubLine.end + posLineStart); +			} +		} +		if (!canReturnInvalid) +			return SelectionPosition(ll->numCharsInLine + posLineStart); +	} +	return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); +} + +/** +* Find the document position corresponding to an x coordinate on a particular document line. +* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. +* This method is used for rectangular selections and does not work on wrapped lines. +*/ +SelectionPosition EditView::SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs) { +	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); +	if (surface && ll) { +		const int posLineStart = model.pdoc->LineStart(lineDoc); +		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); +		const Range rangeSubLine = ll->SubLineRange(0); +		const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; +		const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); +		if (positionInLine < rangeSubLine.end) { +			return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); +		} +		const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; +		const int spaceOffset = static_cast<int>( +			(x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); +		return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); +	} +	return SelectionPosition(0); +} + +int EditView::DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs) { +	int lineDoc = model.pdoc->LineFromPosition(pos); +	int lineDisplay = model.cs.DisplayFromDoc(lineDoc); +	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); +	if (surface && ll) { +		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); +		unsigned int posLineStart = model.pdoc->LineStart(lineDoc); +		int posInLine = pos - posLineStart; +		lineDisplay--; // To make up for first increment ahead. +		for (int subLine = 0; subLine < ll->lines; subLine++) { +			if (posInLine >= ll->LineStart(subLine)) { +				lineDisplay++; +			} +		} +	} +	return lineDisplay; +} + +int EditView::StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs) { +	int line = model.pdoc->LineFromPosition(pos); +	AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); +	int posRet = INVALID_POSITION; +	if (surface && ll) { +		unsigned int posLineStart = model.pdoc->LineStart(line); +		LayoutLine(line, surface, vs, ll, model, model.wrapWidth); +		int posInLine = pos - posLineStart; +		if (posInLine <= ll->maxLineLength) { +			for (int subLine = 0; subLine < ll->lines; subLine++) { +				if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { +					if (start) { +						posRet = ll->LineStart(subLine) + posLineStart; +					} else { +						if (subLine == ll->lines - 1) +							posRet = ll->LineStart(subLine + 1) + posLineStart; +						else +							posRet = ll->LineStart(subLine + 1) + posLineStart - 1; +					} +				} +			} +		} +	} +	return posRet; +} + +static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) { +	return main ? +		(primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) : +		vsDraw.selAdditionalBackground; +} + +static ColourDesired TextBackground(const ViewStyle &vsDraw, +	ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i, +	LineLayout *ll, const EditModel &model) { +	if (inSelection == 1) { +		if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { +			return SelectionBackground(vsDraw, true, model.primarySelection); +		} +	} else if (inSelection == 2) { +		if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) { +			return SelectionBackground(vsDraw, false, model.primarySelection); +		} +	} else { +		if ((vsDraw.edgeState == EDGE_BACKGROUND) && +			(i >= ll->edgeColumn) && +			(i < ll->numCharsBeforeEOL)) +			return vsDraw.edgecolour; +		if (inHotspot && vsDraw.hotspotColours.back.isSet) +			return vsDraw.hotspotColours.back; +	} +	if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { +		return background; +	} else { +		return vsDraw.styles[styleMain].back; +	} +} + +void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { +	Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); +	PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast<int>(rcSegment.top), start + 2, static_cast<int>(rcSegment.bottom)); +	surface->Copy(rcCopyArea, from, +		highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); +} + +static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { +	if (alpha != SC_ALPHA_NOALPHA) { +		surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); +	} +} + +void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, +	const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) { +	if (!twoPhaseDraw) { +		surface->FillRectangle(rcSegment, textBack); +	} +	FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; +	int normalCharHeight = static_cast<int>(surface->Ascent(ctrlCharsFont) - +		surface->InternalLeading(ctrlCharsFont)); +	PRectangle rcCChar = rcSegment; +	rcCChar.left = rcCChar.left + 1; +	rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight; +	rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1; +	PRectangle rcCentral = rcCChar; +	rcCentral.top++; +	rcCentral.bottom--; +	surface->FillRectangle(rcCentral, textFore); +	PRectangle rcChar = rcCChar; +	rcChar.left++; +	rcChar.right--; +	surface->DrawTextClipped(rcChar, ctrlCharsFont, +		rcSegment.top + vsDraw.maxAscent, s, static_cast<int>(s ? strlen(s) : 0), +		textBack, textFore); +} + +void EditView::DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, +	int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, +	ColourOptional background, const EditModel &model) { + +	const int posLineStart = model.pdoc->LineStart(line); +	PRectangle rcSegment = rcLine; + +	const bool lastSubLine = subLine == (ll->lines - 1); +	XYPOSITION virtualSpace = 0; +	if (lastSubLine) { +		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; +		virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth; +	} +	XYPOSITION xEol = static_cast<XYPOSITION>(ll->positions[lineEnd] - subLineStart); + +	// Fill the virtual space and show selections within it +	if (virtualSpace) { +		rcSegment.left = xEol + xStart; +		rcSegment.right = xEol + xStart + virtualSpace; +		surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back); +		if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { +			SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)))); +			for (size_t r = 0; r<model.sel.Count(); r++) { +				int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; +				if (alpha == SC_ALPHA_NOALPHA) { +					SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); +					if (!portion.Empty()) { +						const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; +						rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - +							static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth; +						rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - +							static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth; +						rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; +						rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; +						surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection)); +					} +				} +			} +		} +	} + +	int eolInSelection = 0; +	int alpha = SC_ALPHA_NOALPHA; +	if (!hideSelection) { +		int posAfterLineEnd = model.pdoc->LineStart(line + 1); +		eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; +		alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; +	} + +	// Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on +	XYPOSITION blobsWidth = 0; +	if (lastSubLine) { +		for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) { +			rcSegment.left = xStart + ll->positions[eolPos] - static_cast<XYPOSITION>(subLineStart)+virtualSpace; +			rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast<XYPOSITION>(subLineStart)+virtualSpace; +			blobsWidth += rcSegment.Width(); +			char hexits[4]; +			const char *ctrlChar; +			unsigned char chEOL = ll->chars[eolPos]; +			int styleMain = ll->styles[eolPos]; +			ColourDesired textBack = TextBackground(vsDraw, background, eolInSelection, false, styleMain, eolPos, ll, model); +			if (UTF8IsAscii(chEOL)) { +				ctrlChar = ControlCharacterString(chEOL); +			} else { +				const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos); +				if (repr) { +					ctrlChar = repr->stringRep.c_str(); +					eolPos = ll->numCharsInLine; +				} else { +					sprintf(hexits, "x%2X", chEOL); +					ctrlChar = hexits; +				} +			} +			ColourDesired textFore = vsDraw.styles[styleMain].fore; +			if (eolInSelection && vsDraw.selColours.fore.isSet) { +				textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; +			} +			if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) { +				if (alpha == SC_ALPHA_NOALPHA) { +					surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); +				} else { +					surface->FillRectangle(rcSegment, textBack); +				} +			} else { +				surface->FillRectangle(rcSegment, textBack); +			} +			DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw); +			if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { +				SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); +			} +		} +	} + +	// Draw the eol-is-selected rectangle +	rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; +	rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; + +	if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { +		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); +	} else { +		if (background.isSet) { +			surface->FillRectangle(rcSegment, background); +		} else if (line < model.pdoc->LinesTotal() - 1) { +			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); +		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { +			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); +		} else { +			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); +		} +		if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { +			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); +		} +	} + +	// Fill the remainder of the line +	rcSegment.left = rcSegment.right; +	if (rcSegment.left < rcLine.left) +		rcSegment.left = rcLine.left; +	rcSegment.right = rcLine.right; + +	if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { +		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); +	} else { +		if (background.isSet) { +			surface->FillRectangle(rcSegment, background); +		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { +			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); +		} else { +			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); +		} +		if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { +			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); +		} +	} + +	bool drawWrapMarkEnd = false; + +	if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { +		if (subLine + 1 < ll->lines) { +			drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; +		} +	} + +	if (drawWrapMarkEnd) { +		PRectangle rcPlace = rcSegment; + +		if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { +			rcPlace.left = xEol + xStart + virtualSpace; +			rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; +		} else { +			// rcLine is clipped to text area +			rcPlace.right = rcLine.right; +			rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; +		} +		DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); +	} +} + +static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw, +	int xStart, PRectangle rcLine, LineLayout *ll, int subLine) { +	const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; +	PRectangle rcIndic( +		ll->positions[startPos] + xStart - subLineStart, +		rcLine.top + vsDraw.maxAscent, +		ll->positions[endPos] + xStart - subLineStart, +		rcLine.top + vsDraw.maxAscent + 3); +	vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine); +} + +static void DrawIndicators(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, +	PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under, const EditModel &model) { +	// Draw decorators +	const int posLineStart = model.pdoc->LineStart(line); +	const int lineStart = ll->LineStart(subLine); +	const int posLineEnd = posLineStart + lineEnd; + +	for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { +		if (under == vsDraw.indicators[deco->indicator].under) { +			int startPos = posLineStart + lineStart; +			if (!deco->rs.ValueAt(startPos)) { +				startPos = deco->rs.EndRun(startPos); +			} +			while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) { +				int endPos = deco->rs.EndRun(startPos); +				if (endPos > posLineEnd) +					endPos = posLineEnd; +				DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, +					surface, vsDraw, xStart, rcLine, ll, subLine); +				startPos = endPos; +				if (!deco->rs.ValueAt(startPos)) { +					startPos = deco->rs.EndRun(startPos); +				} +			} +		} +	} + +	// Use indicators to highlight matching braces +	if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || +		(vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { +		int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator; +		if (under == vsDraw.indicators[braceIndicator].under) { +			Range rangeLine(posLineStart + lineStart, posLineEnd); +			if (rangeLine.ContainsCharacter(model.braces[0])) { +				int braceOffset = model.braces[0] - posLineStart; +				if (braceOffset < ll->numCharsInLine) { +					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); +				} +			} +			if (rangeLine.ContainsCharacter(model.braces[1])) { +				int braceOffset = model.braces[1] - posLineStart; +				if (braceOffset < ll->numCharsInLine) { +					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); +				} +			} +		} +	} +} + +void EditView::DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, +	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) { +	int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth); +	PRectangle rcSegment = rcLine; +	int annotationLine = subLine - ll->lines; +	const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line); +	if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { +		surface->FillRectangle(rcSegment, vsDraw.styles[0].back); +		rcSegment.left = static_cast<XYPOSITION>(xStart); +		if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) { +			// Only care about calculating width if tracking or need to draw box +			int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); +			if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +				widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins +			} +			if (widthAnnotation > lineWidthMaxSeen) +				lineWidthMaxSeen = widthAnnotation; +			if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +				rcSegment.left = static_cast<XYPOSITION>(xStart + indent); +				rcSegment.right = rcSegment.left + widthAnnotation; +			} +		} +		const int annotationLines = model.pdoc->AnnotationLines(line); +		size_t start = 0; +		size_t lengthAnnotation = stAnnotation.LineLength(start); +		int lineInAnnotation = 0; +		while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { +			start += lengthAnnotation + 1; +			lengthAnnotation = stAnnotation.LineLength(start); +			lineInAnnotation++; +		} +		PRectangle rcText = rcSegment; +		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +			surface->FillRectangle(rcText, +				vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); +			rcText.left += vsDraw.spaceWidth; +		} +		DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, +			stAnnotation, start, lengthAnnotation); +		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); +			surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top)); +			surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom)); +			surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top)); +			surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom)); +			if (subLine == ll->lines) { +				surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top)); +				surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top)); +			} +			if (subLine == ll->lines + annotationLines - 1) { +				surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1)); +				surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1)); +			} +		} +	} +} + +static void DrawBlockCaret(Surface *surface, const ViewStyle &vsDraw, LineLayout *ll, int subLine, +	int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour, const EditModel &model) { + +	int lineStart = ll->LineStart(subLine); +	int posBefore = posCaret; +	int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1); +	int numCharsToDraw = posAfter - posCaret; + +	// Work out where the starting and ending offsets are. We need to +	// see if the previous character shares horizontal space, such as a +	// glyph / combining character. If so we'll need to draw that too. +	int offsetFirstChar = offset; +	int offsetLastChar = offset + (posAfter - posCaret); +	while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { +		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { +			// The char does not share horizontal space +			break; +		} +		// Char shares horizontal space, update the numChars to draw +		// Update posBefore to point to the prev char +		posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1); +		numCharsToDraw = posAfter - posBefore; +		offsetFirstChar = offset - (posCaret - posBefore); +	} + +	// See if the next character shares horizontal space, if so we'll +	// need to draw that too. +	if (offsetFirstChar < 0) +		offsetFirstChar = 0; +	numCharsToDraw = offsetLastChar - offsetFirstChar; +	while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { +		// Update posAfter to point to the 2nd next char, this is where +		// the next character ends, and 2nd next begins. We'll need +		// to compare these two +		posBefore = posAfter; +		posAfter = model.pdoc->MovePositionOutsideChar(posAfter + 1, 1); +		offsetLastChar = offset + (posAfter - posCaret); +		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { +			// The char does not share horizontal space +			break; +		} +		// Char shares horizontal space, update the numChars to draw +		numCharsToDraw = offsetLastChar - offsetFirstChar; +	} + +	// We now know what to draw, update the caret drawing rectangle +	rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; +	rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart; + +	// Adjust caret position to take into account any word wrapping symbols. +	if ((ll->wrapIndent != 0) && (lineStart != 0)) { +		XYPOSITION wordWrapCharWidth = ll->wrapIndent; +		rcCaret.left += wordWrapCharWidth; +		rcCaret.right += wordWrapCharWidth; +	} + +	// This character is where the caret block is, we override the colours +	// (inversed) for drawing the caret here. +	int styleMain = ll->styles[offsetFirstChar]; +	FontAlias fontText = vsDraw.styles[styleMain].font; +	surface->DrawTextClipped(rcCaret, fontText, +		rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, +		numCharsToDraw, vsDraw.styles[styleMain].back, +		caretColour); +} + +void EditView::DrawCarets(Surface *surface, const ViewStyle &vsDraw, int lineDoc, int xStart, +	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const { +	// When drag is active it is the only caret drawn +	bool drawDrag = model.posDrag.IsValid(); +	if (hideSelection && !drawDrag) +		return; +	const int posLineStart = model.pdoc->LineStart(lineDoc); +	// For each selection draw +	for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) { +		const bool mainCaret = r == model.sel.Main(); +		const SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret); +		const int offset = posCaret.Position() - posLineStart; +		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; +		const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; +		if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { +			XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; +			if (ll->wrapIndent != 0) { +				int lineStart = ll->LineStart(subLine); +				if (lineStart != 0)	// Wrapped +					xposCaret += ll->wrapIndent; +			} +			bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret); +			bool caretVisibleState = additionalCaretsVisible || mainCaret; +			if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) && +				((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) { +				bool caretAtEOF = false; +				bool caretAtEOL = false; +				bool drawBlockCaret = false; +				XYPOSITION widthOverstrikeCaret; +				XYPOSITION caretWidthOffset = 0; +				PRectangle rcCaret = rcLine; + +				if (posCaret.Position() == model.pdoc->Length()) {   // At end of document +					caretAtEOF = true; +					widthOverstrikeCaret = vsDraw.aveCharWidth; +				} else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) {	// At end of line +					caretAtEOL = true; +					widthOverstrikeCaret = vsDraw.aveCharWidth; +				} else { +					widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; +				} +				if (widthOverstrikeCaret < 3)	// Make sure its visible +					widthOverstrikeCaret = 3; + +				if (xposCaret > 0) +					caretWidthOffset = 0.51f;	// Move back so overlaps both character cells. +				xposCaret += xStart; +				if (model.posDrag.IsValid()) { +					/* Dragging text, use a line caret */ +					rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset)); +					rcCaret.right = rcCaret.left + vsDraw.caretWidth; +				} else if (model.inOverstrike && drawOverstrikeCaret) { +					/* Overstrike (insert mode), use a modified bar caret */ +					rcCaret.top = rcCaret.bottom - 2; +					rcCaret.left = xposCaret + 1; +					rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; +				} else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) { +					/* Block caret */ +					rcCaret.left = xposCaret; +					if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { +						drawBlockCaret = true; +						rcCaret.right = xposCaret + widthOverstrikeCaret; +					} else { +						rcCaret.right = xposCaret + vsDraw.aveCharWidth; +					} +				} else { +					/* Line caret */ +					rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset)); +					rcCaret.right = rcCaret.left + vsDraw.caretWidth; +				} +				ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; +				if (drawBlockCaret) { +					DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour, model); +				} else { +					surface->FillRectangle(rcCaret, caretColour); +				} +			} +		} +		if (drawDrag) +			break; +	} +} + +void EditView::DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart, +	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) { + +	if (subLine >= ll->lines) { +		DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine, model); +		return; // No further drawing +	} + +	// Using one font for all control characters so it can be controlled independently to ensure +	// the box goes around the characters tightly. Seems to be no way to work out what height +	// is taken by an individual character - internal leading gives varying results. +	FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + +	// See if something overrides the line background color. +	const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); + +	const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) && +		(!background.isSet) && (vsDraw.whitespaceColours.back.isSet); + +	const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth; + +	const int posLineStart = model.pdoc->LineStart(line); + +	const Range lineRange = ll->SubLineRange(subLine); +	const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; + +	if ((ll->wrapIndent != 0) && (subLine > 0) && (subLine < ll->lines)) { +		// default bgnd here.. +		surface->FillRectangle(rcLine, background.isSet ? background : +			vsDraw.styles[STYLE_DEFAULT].back); + +		if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) { + +			// draw continuation rect +			PRectangle rcPlace = rcLine; + +			rcPlace.left = static_cast<XYPOSITION>(xStart); +			rcPlace.right = rcPlace.left + ll->wrapIndent; + +			if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) +				rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; +			else +				rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; + +			DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); +		} + +		xStart += static_cast<int>(ll->wrapIndent); +	} + +	const bool selBackDrawn = vsDraw.selColours.back.isSet && +		((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)); + +	// Does not take margin into account but not significant +	const int xStartVisible = static_cast<int>(subLineStart)-xStart; + +	if (twoPhaseDraw) { +		bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline. +		BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs); + +		// Background drawing loop +		while (bfBack.More()) { + +			const TextSegment ts = bfBack.Next(); +			const int i = ts.end() - 1; +			const int iDoc = i + posLineStart; + +			PRectangle rcSegment = rcLine; +			rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart); +			rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart); +			// Only try to draw if really visible - enhances performance by not calling environment to +			// draw strings that are completely past the right side of the window. +			if (rcSegment.Intersects(rcLine)) { +				// Clip to line rectangle, since may have a huge position which will not work with some platforms +				if (rcSegment.left < rcLine.left) +					rcSegment.left = rcLine.left; +				if (rcSegment.right > rcLine.right) +					rcSegment.right = rcLine.right; + +				const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); +				const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); +				ColourDesired textBack = TextBackground(vsDraw, background, inSelection, +					inHotspot, ll->styles[i], i, ll, model); +				if (ts.representation) { +					if (ll->chars[i] == '\t') { +						// Tab display +						if (drawWhitespaceBackground && +							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) +							textBack = vsDraw.whitespaceColours.back; +					} else { +						// Blob display +						inIndentation = false; +					} +					surface->FillRectangle(rcSegment, textBack); +				} else { +					// Normal text display +					surface->FillRectangle(rcSegment, textBack); +					if (vsDraw.viewWhitespace != wsInvisible || +						(inIndentation && vsDraw.viewIndentationGuides == ivReal)) { +						for (int cpos = 0; cpos <= i - ts.start; cpos++) { +							if (ll->chars[cpos + ts.start] == ' ') { +								if (drawWhitespaceBackground && +									(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { +									PRectangle rcSpace( +										ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart), +										rcSegment.top, +										ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart), +										rcSegment.bottom); +									surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back); +								} +							} else { +								inIndentation = false; +							} +						} +					} +				} +			} else if (rcSegment.left > rcLine.right) { +				break; +			} +		} + +		DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end, +			xStart, subLine, subLineStart, background, model); +	} + +	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, true, model); + +	if (vsDraw.edgeState == EDGE_LINE) { +		PRectangle rcSegment = rcLine; +		int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth); +		rcSegment.left = static_cast<XYPOSITION>(edgeX + xStart); +		if ((ll->wrapIndent != 0) && (lineRange.start != 0)) +			rcSegment.left -= ll->wrapIndent; +		rcSegment.right = rcSegment.left + 1; +		surface->FillRectangle(rcSegment, vsDraw.edgecolour); +	} + +	// Draw underline mark as part of background if not transparent +	int marks = model.pdoc->GetMark(line); +	int markBit; +	for (markBit = 0; (markBit < 32) && marks; markBit++) { +		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) && +			(vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { +			PRectangle rcUnderline = rcLine; +			rcUnderline.top = rcUnderline.bottom - 2; +			surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); +		} +		marks >>= 1; +	} + +	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline. +	// Foreground drawing loop +	BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, +		((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs); + +	while (bfFore.More()) { + +		const TextSegment ts = bfFore.Next(); +		const int i = ts.end() - 1; +		const int iDoc = i + posLineStart; + +		PRectangle rcSegment = rcLine; +		rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart); +		rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart); +		// Only try to draw if really visible - enhances performance by not calling environment to +		// draw strings that are completely past the right side of the window. +		if (rcSegment.Intersects(rcLine)) { +			int styleMain = ll->styles[i]; +			ColourDesired textFore = vsDraw.styles[styleMain].fore; +			FontAlias textFont = vsDraw.styles[styleMain].font; +			//hotspot foreground +			const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); +			if (inHotspot) { +				if (vsDraw.hotspotColours.fore.isSet) +					textFore = vsDraw.hotspotColours.fore; +			} +			const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); +			if (inSelection && (vsDraw.selColours.fore.isSet)) { +				textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; +			} +			ColourDesired textBack = TextBackground(vsDraw, background, inSelection, inHotspot, styleMain, i, ll, model); +			if (ts.representation) { +				if (ll->chars[i] == '\t') { +					// Tab display +					if (!twoPhaseDraw) { +						if (drawWhitespaceBackground && +							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) +							textBack = vsDraw.whitespaceColours.back; +						surface->FillRectangle(rcSegment, textBack); +					} +					if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { +						for (int indentCount = static_cast<int>((ll->positions[i] + epsilon) / indentWidth); +							indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; +							indentCount++) { +							if (indentCount > 0) { +								int xIndent = static_cast<int>(indentCount * indentWidth); +								DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, +									(ll->xHighlightGuide == xIndent)); +							} +						} +					} +					if (vsDraw.viewWhitespace != wsInvisible) { +						if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { +							if (vsDraw.whitespaceColours.fore.isSet) +								textFore = vsDraw.whitespaceColours.fore; +							surface->PenColour(textFore); +							PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, +								rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); +							DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2)); +						} +					} +				} else { +					inIndentation = false; +					if (vsDraw.controlCharSymbol >= 32) { +						char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' }; +						surface->DrawTextNoClip(rcSegment, ctrlCharsFont, +							rcSegment.top + vsDraw.maxAscent, +							cc, 1, textBack, textFore); +					} else { +						DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw); +					} +				} +			} else { +				// Normal text display +				if (vsDraw.styles[styleMain].visible) { +					if (twoPhaseDraw) { +						surface->DrawTextTransparent(rcSegment, textFont, +							rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, +							i - ts.start + 1, textFore); +					} else { +						surface->DrawTextNoClip(rcSegment, textFont, +							rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, +							i - ts.start + 1, textFore, textBack); +					} +				} +				if (vsDraw.viewWhitespace != wsInvisible || +					(inIndentation && vsDraw.viewIndentationGuides != ivNone)) { +					for (int cpos = 0; cpos <= i - ts.start; cpos++) { +						if (ll->chars[cpos + ts.start] == ' ') { +							if (vsDraw.viewWhitespace != wsInvisible) { +								if (vsDraw.whitespaceColours.fore.isSet) +									textFore = vsDraw.whitespaceColours.fore; +								if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { +									XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; +									if (!twoPhaseDraw && drawWhitespaceBackground && +										(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { +										textBack = vsDraw.whitespaceColours.back; +										PRectangle rcSpace( +											ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart), +											rcSegment.top, +											ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart), +											rcSegment.bottom); +										surface->FillRectangle(rcSpace, textBack); +									} +									PRectangle rcDot(xmid + xStart - static_cast<XYPOSITION>(subLineStart), +										rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f); +									rcDot.right = rcDot.left + vsDraw.whitespaceSize; +									rcDot.bottom = rcDot.top + vsDraw.whitespaceSize; +									surface->FillRectangle(rcDot, textFore); +								} +							} +							if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { +								for (int indentCount = static_cast<int>((ll->positions[cpos + ts.start] + epsilon) / indentWidth); +									indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth; +									indentCount++) { +									if (indentCount > 0) { +										int xIndent = static_cast<int>(indentCount * indentWidth); +										DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, +											(ll->xHighlightGuide == xIndent)); +									} +								} +							} +						} else { +							inIndentation = false; +						} +					} +				} +			} +			if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) { +				PRectangle rcUL = rcSegment; +				rcUL.top = rcUL.top + vsDraw.maxAscent + 1; +				rcUL.bottom = rcUL.top + 1; +				if (vsDraw.hotspotColours.fore.isSet) +					surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore); +				else +					surface->FillRectangle(rcUL, textFore); +			} else if (vsDraw.styles[styleMain].underline) { +				PRectangle rcUL = rcSegment; +				rcUL.top = rcUL.top + vsDraw.maxAscent + 1; +				rcUL.bottom = rcUL.top + 1; +				surface->FillRectangle(rcUL, textFore); +			} +		} else if (rcSegment.left > rcLine.right) { +			break; +		} +	} +	if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth) +		&& (subLine == 0)) { +		int indentSpace = model.pdoc->GetLineIndentation(line); +		int xStartText = static_cast<int>(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]); + +		// Find the most recent line with some text + +		int lineLastWithText = line; +		while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) { +			lineLastWithText--; +		} +		if (lineLastWithText < line) { +			xStartText = 100000;	// Don't limit to visible indentation on empty line +			// This line is empty, so use indentation of last line with text +			int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText); +			int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG; +			if (isFoldHeader) { +				// Level is one more level than parent +				indentLastWithText += model.pdoc->IndentSize(); +			} +			if (vsDraw.viewIndentationGuides == ivLookForward) { +				// In viLookForward mode, previous line only used if it is a fold header +				if (isFoldHeader) { +					indentSpace = Platform::Maximum(indentSpace, indentLastWithText); +				} +			} else {	// viLookBoth +				indentSpace = Platform::Maximum(indentSpace, indentLastWithText); +			} +		} + +		int lineNextWithText = line; +		while (lineNextWithText < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) { +			lineNextWithText++; +		} +		if (lineNextWithText > line) { +			xStartText = 100000;	// Don't limit to visible indentation on empty line +			// This line is empty, so use indentation of first next line with text +			indentSpace = Platform::Maximum(indentSpace, +				model.pdoc->GetLineIndentation(lineNextWithText)); +		} + +		for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) { +			int xIndent = static_cast<int>(indentPos * vsDraw.spaceWidth); +			if (xIndent < xStartText) { +				DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine, +					(ll->xHighlightGuide == xIndent)); +			} +		} +	} + +	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, false, model); + +	// End of the drawing of the current line +	if (!twoPhaseDraw) { +		DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end, +			xStart, subLine, subLineStart, background, model); +	} +	if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) { +		// For each selection draw +		int virtualSpaces = 0; +		if (subLine == (ll->lines - 1)) { +			virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)); +		} +		SelectionPosition posStart(posLineStart + lineRange.start); +		SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces); +		SelectionSegment virtualSpaceRange(posStart, posEnd); +		for (size_t r = 0; r<model.sel.Count(); r++) { +			int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; +			if (alpha != SC_ALPHA_NOALPHA) { +				SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); +				if (!portion.Empty()) { +					const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; +					PRectangle rcSegment = rcLine; +					rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - +						static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth; +					rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - +						static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth; +					if ((ll->wrapIndent != 0) && (lineRange.start != 0)) { +						if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) +							rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here +					} +					rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; +					rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; +					if (rcSegment.right > rcLine.left) +						SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha); +				} +			} +		} +	} + +	// Draw any translucent whole line states +	if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) { +		SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); +	} +	marks = model.pdoc->GetMark(line); +	for (markBit = 0; (markBit < 32) && marks; markBit++) { +		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { +			SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); +		} else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { +			PRectangle rcUnderline = rcLine; +			rcUnderline.top = rcUnderline.bottom - 2; +			SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); +		} +		marks >>= 1; +	} +	if (vsDraw.maskInLine) { +		int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine; +		if (marksMasked) { +			for (markBit = 0; (markBit < 32) && marksMasked; markBit++) { +				if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { +					SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); +				} +				marksMasked >>= 1; +			} +		} +	} +} + +void EditView::PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient, +	const EditModel &model, const ViewStyle &vsDraw) { +	// Allow text at start of line to overlap 1 pixel into the margin as this displays +	// serifs and italic stems for aliased text. +	const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0; + +	// Do the painting +	if (rcArea.right > vsDraw.textStart - leftTextOverlap) { + +		Surface *surface = surfaceWindow; +		if (bufferedDraw) { +			surface = pixmapLine; +			PLATFORM_ASSERT(pixmapLine->Initialised()); +		} +		surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage); +		surface->SetDBCSMode(model.pdoc->dbcsCodePage); + +		Point ptOrigin = model.GetVisibleOriginInMain(); + +		int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight; +		int ypos = 0; +		if (!bufferedDraw) +			ypos += screenLinePaintFirst * vsDraw.lineHeight; +		int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x); + +		int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; +		int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; + +		SelectionPosition posCaret = model.sel.RangeMain().caret; +		if (model.posDrag.IsValid()) +			posCaret = model.posDrag; +		int lineCaret = model.pdoc->LineFromPosition(posCaret.Position()); + +		PRectangle rcTextArea = rcClient; +		if (vsDraw.marginInside) { +			rcTextArea.left += vsDraw.textStart; +			rcTextArea.right -= vsDraw.rightMarginWidth; +		} else { +			rcTextArea = rcArea; +		} + +		// Remove selection margin from drawing area so text will not be drawn +		// on it in unbuffered mode. +		if (!bufferedDraw && vsDraw.marginInside) { +			PRectangle rcClipText = rcTextArea; +			rcClipText.left -= leftTextOverlap; +			surfaceWindow->SetClip(rcClipText); +		} + +		// Loop on visible lines +		//double durLayout = 0.0; +		//double durPaint = 0.0; +		//double durCopy = 0.0; +		//ElapsedTime etWhole; +		int lineDocPrevious = -1;	// Used to avoid laying out one document line multiple times +		AutoLineLayout ll(llc, 0); +		while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { + +			int lineDoc = model.cs.DocFromDisplay(visibleLine); +			// Only visible lines should be handled by the code within the loop +			PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); +			int lineStartSet = model.cs.DisplayFromDoc(lineDoc); +			int subLine = visibleLine - lineStartSet; + +			// Copy this line and its styles from the document into local arrays +			// and determine the x position at which each character starts. +			//ElapsedTime et; +			if (lineDoc != lineDocPrevious) { +				ll.Set(0); +				ll.Set(RetrieveLineLayout(lineDoc, model)); +				LayoutLine(lineDoc, surface, vsDraw, ll, model, model.wrapWidth); +				lineDocPrevious = lineDoc; +			} +			//durLayout += et.Duration(true); + +			if (ll) { +				ll->containsCaret = lineDoc == lineCaret; +				if (hideSelection) { +					ll->containsCaret = false; +				} + +				ll->hotspot = model.GetHotSpotRange(); + +				PRectangle rcLine = rcTextArea; +				rcLine.top = static_cast<XYPOSITION>(ypos); +				rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight); + +				bool bracesIgnoreStyle = false; +				if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || +					(vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { +					bracesIgnoreStyle = true; +				} +				Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); +				// Highlight the current braces if any +				ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle), +					static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); + +				if (leftTextOverlap && bufferedDraw) { +					PRectangle rcSpacer = rcLine; +					rcSpacer.right = rcSpacer.left; +					rcSpacer.left -= 1; +					surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); +				} + +				// Draw the line +				DrawLine(surface, vsDraw, lineDoc, visibleLine, xStart, rcLine, ll, subLine, model); +				//durPaint += et.Duration(true); + +				// Restore the previous styles for the brace highlights in case layout is in cache. +				ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); + +				bool expanded = model.cs.GetExpanded(lineDoc); +				const int level = model.pdoc->GetLevel(lineDoc); +				const int levelNext = model.pdoc->GetLevel(lineDoc + 1); +				if ((level & SC_FOLDLEVELHEADERFLAG) && +					((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { +					// Paint the line above the fold +					if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) +						|| +						(!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { +						PRectangle rcFoldLine = rcLine; +						rcFoldLine.bottom = rcFoldLine.top + 1; +						surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); +					} +					// Paint the line below the fold +					if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) +						|| +						(!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { +						PRectangle rcFoldLine = rcLine; +						rcFoldLine.top = rcFoldLine.bottom - 1; +						surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); +					} +				} + +				DrawCarets(surface, vsDraw, lineDoc, xStart, rcLine, ll, subLine, model); + +				if (bufferedDraw) { +					Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); +					PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, +						static_cast<int>(rcClient.right - vsDraw.rightMarginWidth), +						yposScreen + vsDraw.lineHeight); +					surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); +				} + +				lineWidthMaxSeen = Platform::Maximum( +					lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine])); +				//durCopy += et.Duration(true); +			} + +			if (!bufferedDraw) { +				ypos += vsDraw.lineHeight; +			} + +			yposScreen += vsDraw.lineHeight; +			visibleLine++; + +			//gdk_flush(); +		} +		ll.Set(0); +		//if (durPaint < 0.00000001) +		//	durPaint = 0.00000001; + +		// Right column limit indicator +		PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea; +		rcBeyondEOF.left = static_cast<XYPOSITION>(vsDraw.textStart); +		rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0); +		rcBeyondEOF.top = static_cast<XYPOSITION>((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight); +		if (rcBeyondEOF.top < rcBeyondEOF.bottom) { +			surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back); +			if (vsDraw.edgeState == EDGE_LINE) { +				int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth); +				rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart); +				rcBeyondEOF.right = rcBeyondEOF.left + 1; +				surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour); +			} +		} +		//Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); + +		//Platform::DebugPrintf( +		//"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n", +		//durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); +	} +} + +// Space (3 space characters) between line numbers and text when printing. +#define lineNumberPrintSpace "   " + +ColourDesired InvertedLight(ColourDesired orig) { +	unsigned int r = orig.GetRed(); +	unsigned int g = orig.GetGreen(); +	unsigned int b = orig.GetBlue(); +	unsigned int l = (r + g + b) / 3; 	// There is a better calculation for this that matches human eye +	unsigned int il = 0xff - l; +	if (l == 0) +		return ColourDesired(0xff, 0xff, 0xff); +	r = r * il / l; +	g = g * il / l; +	b = b * il / l; +	return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); +} + +long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, +	const EditModel &model, const ViewStyle &vs) { +	// Can't use measurements cached for screen +	posCache.Clear(); + +	ViewStyle vsPrint(vs); +	vsPrint.technology = SC_TECHNOLOGY_DEFAULT; + +	// Modify the view style for printing as do not normally want any of the transient features to be printed +	// Printing supports only the line number margin. +	int lineNumberIndex = -1; +	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { +		if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) { +			lineNumberIndex = margin; +		} else { +			vsPrint.ms[margin].width = 0; +		} +	} +	vsPrint.fixedColumnWidth = 0; +	vsPrint.zoomLevel = printParameters.magnification; +	// Don't show indentation guides +	// If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT +	vsPrint.viewIndentationGuides = ivNone; +	// Don't show the selection when printing +	vsPrint.selColours.back.isSet = false; +	vsPrint.selColours.fore.isSet = false; +	vsPrint.selAlpha = SC_ALPHA_NOALPHA; +	vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA; +	vsPrint.whitespaceColours.back.isSet = false; +	vsPrint.whitespaceColours.fore.isSet = false; +	vsPrint.showCaretLineBackground = false; +	vsPrint.alwaysShowCaretLineBackground = false; +	// Don't highlight matching braces using indicators +	vsPrint.braceHighlightIndicatorSet = false; +	vsPrint.braceBadLightIndicatorSet = false; + +	// Set colours for printing according to users settings +	for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) { +		if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) { +			vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); +			vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); +		} else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) { +			vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); +			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); +		} else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) { +			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); +		} else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { +			if (sty <= STYLE_DEFAULT) { +				vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); +			} +		} +	} +	// White background for the line numbers +	vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); + +	// Printing uses different margins, so reset screen margins +	vsPrint.leftMarginWidth = 0; +	vsPrint.rightMarginWidth = 0; + +	vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); +	// Determining width must happen after fonts have been realised in Refresh +	int lineNumberWidth = 0; +	if (lineNumberIndex >= 0) { +		lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, +			"99999" lineNumberPrintSpace, 5 + static_cast<int>(strlen(lineNumberPrintSpace)))); +		vsPrint.ms[lineNumberIndex].width = lineNumberWidth; +		vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars);	// Recalculate fixedColumnWidth +	} + +	int linePrintStart = model.pdoc->LineFromPosition(pfr->chrg.cpMin); +	int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; +	if (linePrintLast < linePrintStart) +		linePrintLast = linePrintStart; +	int linePrintMax = model.pdoc->LineFromPosition(pfr->chrg.cpMax); +	if (linePrintLast > linePrintMax) +		linePrintLast = linePrintMax; +	//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", +	//      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, +	//      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); +	int endPosPrint = model.pdoc->Length(); +	if (linePrintLast < model.pdoc->LinesTotal()) +		endPosPrint = model.pdoc->LineStart(linePrintLast + 1); + +	// Ensure we are styled to where we are formatting. +	model.pdoc->EnsureStyledTo(endPosPrint); + +	int xStart = vsPrint.fixedColumnWidth + pfr->rc.left; +	int ypos = pfr->rc.top; + +	int lineDoc = linePrintStart; + +	int nPrintPos = pfr->chrg.cpMin; +	int visibleLine = 0; +	int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; +	if (printParameters.wrapState == eWrapNone) +		widthPrint = LineLayout::wrapWidthInfinite; + +	while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) { + +		// When printing, the hdc and hdcTarget may be the same, so +		// changing the state of surfaceMeasure may change the underlying +		// state of surface. Therefore, any cached state is discarded before +		// using each surface. +		surfaceMeasure->FlushCachedState(); + +		// Copy this line and its styles from the document into local arrays +		// and determine the x position at which each character starts. +		LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1); +		LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, model, widthPrint); + +		ll.containsCaret = false; + +		PRectangle rcLine = PRectangle::FromInts( +			pfr->rc.left, +			ypos, +			pfr->rc.right - 1, +			ypos + vsPrint.lineHeight); + +		// When document line is wrapped over multiple display lines, find where +		// to start printing from to ensure a particular position is on the first +		// line of the page. +		if (visibleLine == 0) { +			int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc); +			for (int iwl = 0; iwl < ll.lines - 1; iwl++) { +				if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { +					visibleLine = -iwl; +				} +			} + +			if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { +				visibleLine = -(ll.lines - 1); +			} +		} + +		if (draw && lineNumberWidth && +			(ypos + vsPrint.lineHeight <= pfr->rc.bottom) && +			(visibleLine >= 0)) { +			char number[100]; +			sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1); +			PRectangle rcNumber = rcLine; +			rcNumber.right = rcNumber.left + lineNumberWidth; +			// Right justify +			rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( +				vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast<int>(strlen(number))); +			surface->FlushCachedState(); +			surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, +				static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number, static_cast<int>(strlen(number)), +				vsPrint.styles[STYLE_LINENUMBER].fore, +				vsPrint.styles[STYLE_LINENUMBER].back); +		} + +		// Draw the line +		surface->FlushCachedState(); + +		for (int iwl = 0; iwl < ll.lines; iwl++) { +			if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) { +				if (visibleLine >= 0) { +					if (draw) { +						rcLine.top = static_cast<XYPOSITION>(ypos); +						rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight); +						DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl, model); +					} +					ypos += vsPrint.lineHeight; +				} +				visibleLine++; +				if (iwl == ll.lines - 1) +					nPrintPos = model.pdoc->LineStart(lineDoc + 1); +				else +					nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl); +			} +		} + +		++lineDoc; +	} + +	// Clear cache so measurements are not used for screen +	posCache.Clear(); + +	return nPrintPos; +} diff --git a/src/EditView.h b/src/EditView.h new file mode 100644 index 000000000..f55a6f331 --- /dev/null +++ b/src/EditView.h @@ -0,0 +1,113 @@ +// Scintilla source code edit control +/** @file EditView.h + ** Defines the appearance of the main text area of the editor window. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef EDITVIEW_H +#define EDITVIEW_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +struct PrintParameters { +	int magnification; +	int colourMode; +	WrapMode wrapState; +	PrintParameters(); +}; + +/** +* EditView draws the main text area. +*/ +class EditView { +public: +	PrintParameters printParameters; + +	bool hideSelection; +	bool drawOverstrikeCaret; + +	/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to +	* the screen. This avoids flashing but is about 30% slower. */ +	bool bufferedDraw; +	/** In twoPhaseDraw mode, drawing is performed in two phases, first the background +	* and then the foreground. This avoids chopping off characters that overlap the next run. */ +	bool twoPhaseDraw; + +	int lineWidthMaxSeen; + +	bool additionalCaretsBlink; +	bool additionalCaretsVisible; + +	Surface *pixmapLine; +	Surface *pixmapIndentGuide; +	Surface *pixmapIndentGuideHighlight; + +	LineLayoutCache llc; +	PositionCache posCache; + +	EditView(); + +	void DropGraphics(bool freeObjects); +	void AllocateGraphics(const ViewStyle &vsDraw); +	void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); + +	LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model); +	void LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, +		const EditModel &model, int width = LineLayout::wrapWidthInfinite); + +	Point LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs); +	SelectionPosition SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, +		const EditModel &model, const ViewStyle &vs); +	SelectionPosition SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs); +	int DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs); +	int StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs); + +	void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); +	void DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, +		int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, +		ColourOptional background, const EditModel &model); +	void DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, +		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model); +	void DrawCarets(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, +		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const; +	void DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart, +		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model); +	void PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient, +		const EditModel &model, const ViewStyle &vsDraw); +	long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, +		const EditModel &model, const ViewStyle &vs); +}; + +/** +* Convenience class to ensure LineLayout objects are always disposed. +*/ +class AutoLineLayout { +	LineLayoutCache &llc; +	LineLayout *ll; +	AutoLineLayout &operator=(const AutoLineLayout &); +public: +	AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {} +	~AutoLineLayout() { +		llc.Dispose(ll); +		ll = 0; +	} +	LineLayout *operator->() const { +		return ll; +	} +	operator LineLayout *() const { +		return ll; +	} +	void Set(LineLayout *ll_) { +		llc.Dispose(ll); +		ll = ll_; +	} +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/Editor.cxx b/src/Editor.cxx index 360540a83..a23683698 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -42,6 +42,9 @@  #include "UniConversion.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #ifdef SCI_NAMESPACE @@ -79,20 +82,12 @@ static bool IsLastStep(const DocModification &mh) {  	    && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;  } -Caret::Caret() : -		active(false), on(false), period(500) {} -  Timer::Timer() :  		ticking(false), ticksToWait(0), tickerID(0) {}  Idler::Idler() :  		state(false), idlerID(0) {} -static inline bool IsControlCharacter(int ch) { -	// iscntrl returns true for lots of chars > 127 which are displayable -	return ch >= 0 && ch < ' '; -} -  static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {  	for (unsigned int i = 0; i < len; i++) {  		// This is safe because IsSpaceOrTab() will return false for null terminators @@ -102,2293 +97,6 @@ static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {  	return true;  } -EditModel::EditModel() { -	inOverstrike = false; -	xOffset = 0; -	trackLineWidth = false; -	posDrag = SelectionPosition(invalidPosition); -	braces[0] = invalidPosition; -	braces[1] = invalidPosition; -	bracesMatchStyle = STYLE_BRACEBAD; -	highlightGuideColumn = 0; -	primarySelection = true; -	foldFlags = 0; -	hotspot = Range(invalidPosition); -	wrapWidth = LineLayout::wrapWidthInfinite; -	pdoc = new Document(); -	pdoc->AddRef(); -} - -EditModel::~EditModel() { -	pdoc->Release(); -	pdoc = 0; -} - -bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { -	if (st.multipleStyles) { -		for (size_t iStyle = 0; iStyle<st.length; iStyle++) { -			if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) -				return false; -		} -	} else { -		if (!vs.ValidStyle(styleOffset + st.style)) -			return false; -	} -	return true; -} - -static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, -	const char *text, const unsigned char *styles, size_t len) { -	int width = 0; -	size_t start = 0; -	while (start < len) { -		size_t style = styles[start]; -		size_t endSegment = start; -		while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style)) -			endSegment++; -		FontAlias fontText = vs.styles[style + styleOffset].font; -		width += static_cast<int>(surface->WidthText(fontText, text + start, -			static_cast<int>(endSegment - start + 1))); -		start = endSegment + 1; -	} -	return width; -} - -static int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { -	int widthMax = 0; -	size_t start = 0; -	while (start < st.length) { -		size_t lenLine = st.LineLength(start); -		int widthSubLine; -		if (st.multipleStyles) { -			widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); -		} else { -			FontAlias fontText = vs.styles[styleOffset + st.style].font; -			widthSubLine = static_cast<int>(surface->WidthText(fontText, -				st.text + start, static_cast<int>(lenLine))); -		} -		if (widthSubLine > widthMax) -			widthMax = widthSubLine; -		start += lenLine + 1; -	} -	return widthMax; -} - -static void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) { -	FontAlias fontText = style.font; -	surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length), -		style.fore, style.back); -} - -static void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, -	const StyledText &st, size_t start, size_t length) { - -	if (st.multipleStyles) { -		int x = static_cast<int>(rcText.left); -		size_t i = 0; -		while (i < length) { -			size_t end = i; -			size_t style = st.styles[i + start]; -			while (end < length - 1 && st.styles[start + end + 1] == style) -				end++; -			style += styleOffset; -			FontAlias fontText = vs.styles[style].font; -			const int width = static_cast<int>(surface->WidthText(fontText, -				st.text + start + i, static_cast<int>(end - i + 1))); -			PRectangle rcSegment = rcText; -			rcSegment.left = static_cast<XYPOSITION>(x); -			rcSegment.right = static_cast<XYPOSITION>(x + width + 1); -			DrawTextInStyle(surface, rcSegment, vs.styles[style], rcText.top + vs.maxAscent, -				st.text + start + i, end - i + 1); -			x += width; -			i = end + 1; -		} -	} else { -		const size_t style = st.style + styleOffset; -		DrawTextInStyle(surface, rcText, vs.styles[style], rcText.top + vs.maxAscent, -			st.text + start, length); -	} -} - -static void DrawWrapMarker(Surface *surface, PRectangle rcPlace, -	bool isEndMarker, ColourDesired wrapColour) { -	surface->PenColour(wrapColour); - -	enum { xa = 1 }; // gap before start -	int w = static_cast<int>(rcPlace.right - rcPlace.left) - xa - 1; - -	bool xStraight = isEndMarker;  // x-mirrored symbol for start marker - -	int x0 = static_cast<int>(xStraight ? rcPlace.left : rcPlace.right - 1); -	int y0 = static_cast<int>(rcPlace.top); - -	int dy = static_cast<int>(rcPlace.bottom - rcPlace.top) / 5; -	int y = static_cast<int>(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, 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); -} - -MarginView::MarginView() { -	pixmapSelMargin = 0; -	pixmapSelPattern = 0; -	pixmapSelPatternOffset1 = 0; -} - -void MarginView::DropGraphics(bool freeObjects) { -	if (freeObjects) { -		delete pixmapSelMargin; -		pixmapSelMargin = 0; -		delete pixmapSelPattern; -		pixmapSelPattern = 0; -		delete pixmapSelPatternOffset1; -		pixmapSelPatternOffset1 = 0; -	} else { -		if (pixmapSelMargin) -			pixmapSelMargin->Release(); -		if (pixmapSelPattern) -			pixmapSelPattern->Release(); -		if (pixmapSelPatternOffset1) -			pixmapSelPatternOffset1->Release(); -	} -} - -void MarginView::AllocateGraphics(const ViewStyle &vsDraw) { -	if (!pixmapSelMargin) -		pixmapSelMargin = Surface::Allocate(vsDraw.technology); -	if (!pixmapSelPattern) -		pixmapSelPattern = Surface::Allocate(vsDraw.technology); -	if (!pixmapSelPatternOffset1) -		pixmapSelPatternOffset1 = Surface::Allocate(vsDraw.technology); -} - -void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { -	if (!pixmapSelPattern->Initialised()) { -		const int patternSize = 8; -		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid); -		pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid); -		// This complex procedure is to reproduce the checkerboard dithered pattern used by windows -		// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half -		// way between the chrome colour and the chrome highlight colour making a nice transition -		// between the window chrome and the content area. And it works in low colour depths. -		PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize); - -		// Initialize default colours based on the chrome colour scheme.  Typically the highlight is white. -		ColourDesired colourFMFill = vsDraw.selbar; -		ColourDesired colourFMStripes = vsDraw.selbarlight; - -		if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) { -			// User has chosen an unusual chrome colour scheme so just use the highlight edge colour. -			// (Typically, the highlight colour is white.) -			colourFMFill = vsDraw.selbarlight; -		} - -		if (vsDraw.foldmarginColour.isSet) { -			// override default fold margin colour -			colourFMFill = vsDraw.foldmarginColour; -		} -		if (vsDraw.foldmarginHighlightColour.isSet) { -			// override default fold margin highlight colour -			colourFMStripes = vsDraw.foldmarginHighlightColour; -		} - -		pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); -		pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes); -		for (int y = 0; y < patternSize; y++) { -			for (int x = y % 2; x < patternSize; x += 2) { -				PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1); -				pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes); -				pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill); -			} -		} -	} -} - -static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) { -	if (vs.markers[markerCheck].markType == SC_MARK_EMPTY) -		return markerDefault; -	return markerCheck; -} - -void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, -	const EditModel &model, const ViewStyle &vs) { - -	PRectangle rcSelMargin = rcMargin; -	rcSelMargin.right = rcMargin.left; -	if (rcSelMargin.bottom < rc.bottom) -		rcSelMargin.bottom = rc.bottom; - -	Point ptOrigin = model.GetVisibleOriginInMain(); -	FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font; -	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { -		if (vs.ms[margin].width > 0) { - -			rcSelMargin.left = rcSelMargin.right; -			rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; - -			if (vs.ms[margin].style != SC_MARGIN_NUMBER) { -				if (vs.ms[margin].mask & SC_MASK_FOLDERS) { -					// Required because of special way brush is created for selection margin -					// Ensure patterns line up when scrolling with separate margin view -					// by choosing correctly aligned variant. -					bool invertPhase = static_cast<int>(ptOrigin.y) & 1; -					surface->FillRectangle(rcSelMargin, -						invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1); -				} else { -					ColourDesired colour; -					switch (vs.ms[margin].style) { -					case SC_MARGIN_BACK: -						colour = vs.styles[STYLE_DEFAULT].back; -						break; -					case SC_MARGIN_FORE: -						colour = vs.styles[STYLE_DEFAULT].fore; -						break; -					default: -						colour = vs.styles[STYLE_LINENUMBER].back; -						break; -					} -					surface->FillRectangle(rcSelMargin, colour); -				} -			} else { -				surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back); -			} - -			const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight; -			int visibleLine = model.TopLineOfMain() + lineStartPaint; -			int yposScreen = lineStartPaint * vs.lineHeight - static_cast<int>(ptOrigin.y); -			// Work out whether the top line is whitespace located after a -			// lessening of fold level which implies a 'fold tail' but which should not -			// be displayed until the last of a sequence of whitespace. -			bool needWhiteClosure = false; -			if (vs.ms[margin].mask & SC_MASK_FOLDERS) { -				int level = model.pdoc->GetLevel(model.cs.DocFromDisplay(visibleLine)); -				if (level & SC_FOLDLEVELWHITEFLAG) { -					int lineBack = model.cs.DocFromDisplay(visibleLine); -					int levelPrev = level; -					while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { -						lineBack--; -						levelPrev = model.pdoc->GetLevel(lineBack); -					} -					if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { -						if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) -							needWhiteClosure = true; -					} -				} -				if (highlightDelimiter.isEnabled) { -					int lastLine = model.cs.DocFromDisplay(topLine + model.LinesOnScreen()) + 1; -					model.pdoc->GetHighlightDelimiters(highlightDelimiter, model.pdoc->LineFromPosition(model.sel.MainCaret()), lastLine); -				} -			} - -			// Old code does not know about new markers needed to distinguish all cases -			const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, -				SC_MARKNUM_FOLDEROPEN, vs); -			const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, -				SC_MARKNUM_FOLDER, vs); - -			while ((visibleLine < model.cs.LinesDisplayed()) && yposScreen < rc.bottom) { - -				PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed()); -				const int lineDoc = model.cs.DocFromDisplay(visibleLine); -				PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); -				const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc); -				const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc); - -				int marks = model.pdoc->GetMark(lineDoc); -				if (!firstSubLine) -					marks = 0; - -				bool headWithTail = false; - -				if (vs.ms[margin].mask & SC_MASK_FOLDERS) { -					// Decide which fold indicator should be displayed -					const int level = model.pdoc->GetLevel(lineDoc); -					const int levelNext = model.pdoc->GetLevel(lineDoc + 1); -					const int levelNum = level & SC_FOLDLEVELNUMBERMASK; -					const int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; -					if (level & SC_FOLDLEVELHEADERFLAG) { -						if (firstSubLine) { -							if (levelNum < levelNextNum) { -								if (model.cs.GetExpanded(lineDoc)) { -									if (levelNum == SC_FOLDLEVELBASE) -										marks |= 1 << SC_MARKNUM_FOLDEROPEN; -									else -										marks |= 1 << folderOpenMid; -								} else { -									if (levelNum == SC_FOLDLEVELBASE) -										marks |= 1 << SC_MARKNUM_FOLDER; -									else -										marks |= 1 << folderEnd; -								} -							} else if (levelNum > SC_FOLDLEVELBASE) { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -							} -						} else { -							if (levelNum < levelNextNum) { -								if (model.cs.GetExpanded(lineDoc)) { -									marks |= 1 << SC_MARKNUM_FOLDERSUB; -								} else if (levelNum > SC_FOLDLEVELBASE) { -									marks |= 1 << SC_MARKNUM_FOLDERSUB; -								} -							} else if (levelNum > SC_FOLDLEVELBASE) { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -							} -						} -						needWhiteClosure = false; -						const int firstFollowupLine = model.cs.DocFromDisplay(model.cs.DisplayFromDoc(lineDoc + 1)); -						const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine); -						const int secondFollowupLineLevelNum = model.pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; -						if (!model.cs.GetExpanded(lineDoc)) { -							if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && -								(levelNum > secondFollowupLineLevelNum)) -								needWhiteClosure = true; - -							if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) -								headWithTail = true; -						} -					} else if (level & SC_FOLDLEVELWHITEFLAG) { -						if (needWhiteClosure) { -							if (levelNext & SC_FOLDLEVELWHITEFLAG) { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -							} else if (levelNextNum > SC_FOLDLEVELBASE) { -								marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; -								needWhiteClosure = false; -							} else { -								marks |= 1 << SC_MARKNUM_FOLDERTAIL; -								needWhiteClosure = false; -							} -						} else if (levelNum > SC_FOLDLEVELBASE) { -							if (levelNextNum < levelNum) { -								if (levelNextNum > SC_FOLDLEVELBASE) { -									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; -								} else { -									marks |= 1 << SC_MARKNUM_FOLDERTAIL; -								} -							} else { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -							} -						} -					} else if (levelNum > SC_FOLDLEVELBASE) { -						if (levelNextNum < levelNum) { -							needWhiteClosure = false; -							if (levelNext & SC_FOLDLEVELWHITEFLAG) { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -								needWhiteClosure = true; -							} else if (lastSubLine) { -								if (levelNextNum > SC_FOLDLEVELBASE) { -									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; -								} else { -									marks |= 1 << SC_MARKNUM_FOLDERTAIL; -								} -							} else { -								marks |= 1 << SC_MARKNUM_FOLDERSUB; -							} -						} else { -							marks |= 1 << SC_MARKNUM_FOLDERSUB; -						} -					} -				} - -				marks &= vs.ms[margin].mask; - -				PRectangle rcMarker = rcSelMargin; -				rcMarker.top = static_cast<XYPOSITION>(yposScreen); -				rcMarker.bottom = static_cast<XYPOSITION>(yposScreen + vs.lineHeight); -				if (vs.ms[margin].style == SC_MARGIN_NUMBER) { -					if (firstSubLine) { -						char number[100] = ""; -						if (lineDoc >= 0) -							sprintf(number, "%d", lineDoc + 1); -						if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) { -							if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { -								int lev = model.pdoc->GetLevel(lineDoc); -								sprintf(number, "%c%c %03X %03X", -									(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', -									(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', -									lev & SC_FOLDLEVELNUMBERMASK, -									lev >> 16 -									); -							} else { -								int state = model.pdoc->GetLineState(lineDoc); -								sprintf(number, "%0X", state); -							} -						} -						PRectangle rcNumber = rcMarker; -						// Right justify -						XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast<int>(strlen(number))); -						XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding; -						rcNumber.left = xpos; -						DrawTextInStyle(surface, rcNumber, vs.styles[STYLE_LINENUMBER], -							rcNumber.top + vs.maxAscent, number, strlen(number)); -					} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { -						PRectangle rcWrapMarker = rcMarker; -						rcWrapMarker.right -= 3; -						rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; -						DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); -					} -				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { -					if (firstSubLine) { -						const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc); -						if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { -							surface->FillRectangle(rcMarker, -								vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); -							if (vs.ms[margin].style == SC_MARGIN_RTEXT) { -								int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); -								rcMarker.left = rcMarker.right - width - 3; -							} -							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, -								stMargin, 0, stMargin.length); -						} -					} -				} - -				if (marks) { -					for (int markBit = 0; (markBit < 32) && marks; markBit++) { -						if (marks & 1) { -							LineMarker::typeOfFold tFold = LineMarker::undefined; -							if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { -								if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { -									tFold = LineMarker::body; -								} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { -									if (firstSubLine) { -										tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; -									} else { -										if (model.cs.GetExpanded(lineDoc) || headWithTail) { -											tFold = LineMarker::body; -										} else { -											tFold = LineMarker::undefined; -										} -									} -								} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { -									tFold = LineMarker::tail; -								} -							} -							vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style); -						} -						marks >>= 1; -					} -				} - -				visibleLine++; -				yposScreen += vs.lineHeight; -			} -		} -	} - -	PRectangle rcBlankMargin = rcMargin; -	rcBlankMargin.left = rcSelMargin.right; -	surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back); -} - -/** -* Convenience class to ensure LineLayout objects are always disposed. -*/ -class AutoLineLayout { -	LineLayoutCache &llc; -	LineLayout *ll; -	AutoLineLayout &operator=(const AutoLineLayout &); -public: -	AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {} -	~AutoLineLayout() { -		llc.Dispose(ll); -		ll = 0; -	} -	LineLayout *operator->() const { -		return ll; -	} -	operator LineLayout *() const { -		return ll; -	} -	void Set(LineLayout *ll_) { -		llc.Dispose(ll); -		ll = ll_; -	} -}; - -PrintParameters::PrintParameters() { -	magnification = 0; -	colourMode = SC_PRINT_NORMAL; -	wrapState = eWrapWord; -} - -const XYPOSITION epsilon = 0.0001f;	// A small nudge to avoid floating point precision issues - -EditView::EditView() { -	hideSelection = false; -	drawOverstrikeCaret = true; -	bufferedDraw = true; -	twoPhaseDraw = true; -	lineWidthMaxSeen = 0; -	additionalCaretsBlink = true; -	additionalCaretsVisible = true; -	pixmapLine = 0; -	pixmapIndentGuide = 0; -	pixmapIndentGuideHighlight = 0; -	llc.SetLevel(LineLayoutCache::llcCaret); -	posCache.SetSize(0x400); -} - -void EditView::DropGraphics(bool freeObjects) { -	if (freeObjects) { -		delete pixmapLine; -		pixmapLine = 0; -		delete pixmapIndentGuide; -		pixmapIndentGuide = 0; -		delete pixmapIndentGuideHighlight; -		pixmapIndentGuideHighlight = 0; -	} else { -		if (pixmapLine) -			pixmapLine->Release(); -		if (pixmapIndentGuide) -			pixmapIndentGuide->Release(); -		if (pixmapIndentGuideHighlight) -			pixmapIndentGuideHighlight->Release(); -	} -} - -void EditView::AllocateGraphics(const ViewStyle &vsDraw) { -	if (!pixmapLine) -		pixmapLine = Surface::Allocate(vsDraw.technology); -	if (!pixmapIndentGuide) -		pixmapIndentGuide = Surface::Allocate(vsDraw.technology); -	if (!pixmapIndentGuideHighlight) -		pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology); -} - -const char *ControlCharacterString(unsigned char ch) { -	const char *reps[] = { -		"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", -		"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", -		"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", -		"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" -	}; -	if (ch < ELEMENTS(reps)) { -		return reps[ch]; -	} else { -		return "BAD"; -	} -} - -void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { -	int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2; -	int xhead = static_cast<int>(rcTab.right) - 1 - ydiff; -	if (xhead <= rcTab.left) { -		ydiff -= static_cast<int>(rcTab.left) - xhead - 1; -		xhead = static_cast<int>(rcTab.left) - 1; -	} -	if ((rcTab.left + 2) < (rcTab.right - 1)) -		surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid); -	else -		surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid); -	surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid); -	surface->LineTo(xhead, ymid - ydiff); -	surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid); -	surface->LineTo(xhead, ymid + ydiff); -} - -void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { -	if (!pixmapIndentGuide->Initialised()) { -		// 1 extra pixel in height so can handle odd/even positions and so produce a continuous line -		pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); -		pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); -		PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight); -		pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back); -		pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore); -		pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back); -		pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore); -		for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) { -			PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1); -			pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore); -			pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore); -		} -	} -} - -LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) { -	int posLineStart = model.pdoc->LineStart(lineNumber); -	int posLineEnd = model.pdoc->LineStart(lineNumber + 1); -	PLATFORM_ASSERT(posLineEnd >= posLineStart); -	int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret()); -	return llc.Retrieve(lineNumber, lineCaret, -		posLineEnd - posLineStart, model.pdoc->GetStyleClock(), -		model.LinesOnScreen() + 1, model.pdoc->LinesTotal()); -} - -/** -* Fill in the LineLayout data for the given line. -* Copy the given @a line and its styles from the document into local arrays. -* Also determine the x position at which each character starts. -*/ -void EditView::LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, const EditModel &model, int width) { -	if (!ll) -		return; - -	PLATFORM_ASSERT(line < model.pdoc->LinesTotal()); -	PLATFORM_ASSERT(ll->chars != NULL); -	int posLineStart = model.pdoc->LineStart(line); -	int posLineEnd = model.pdoc->LineStart(line + 1); -	// If the line is very long, limit the treatment to a length that should fit in the viewport -	if (posLineEnd >(posLineStart + ll->maxLineLength)) { -		posLineEnd = posLineStart + ll->maxLineLength; -	} -	if (ll->validity == LineLayout::llCheckTextAndStyle) { -		int lineLength = posLineEnd - posLineStart; -		if (!vstyle.viewEOL) { -			lineLength = model.pdoc->LineEnd(line) - posLineStart; -		} -		if (lineLength == ll->numCharsInLine) { -			// See if chars, styles, indicators, are all the same -			bool allSame = true; -			// Check base line layout -			char styleByte = 0; -			int numCharsInLine = 0; -			while (numCharsInLine < lineLength) { -				int charInDoc = numCharsInLine + posLineStart; -				char chDoc = model.pdoc->CharAt(charInDoc); -				styleByte = model.pdoc->StyleAt(charInDoc); -				allSame = allSame && -					(ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte)); -				if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) -					allSame = allSame && -					(ll->chars[numCharsInLine] == chDoc); -				else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) -					allSame = allSame && -					(ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc))); -				else	// Style::caseUpper -					allSame = allSame && -					(ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc))); -				numCharsInLine++; -			} -			allSame = allSame && (ll->styles[numCharsInLine] == styleByte);	// For eolFilled -			if (allSame) { -				ll->validity = LineLayout::llPositions; -			} else { -				ll->validity = LineLayout::llInvalid; -			} -		} else { -			ll->validity = LineLayout::llInvalid; -		} -	} -	if (ll->validity == LineLayout::llInvalid) { -		ll->widthLine = LineLayout::wrapWidthInfinite; -		ll->lines = 1; -		if (vstyle.edgeState == EDGE_BACKGROUND) { -			ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge); -			if (ll->edgeColumn >= posLineStart) { -				ll->edgeColumn -= posLineStart; -			} -		} else { -			ll->edgeColumn = -1; -		} - -		// Fill base line layout -		const int lineLength = posLineEnd - posLineStart; -		model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength); -		model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); -		int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart; -		const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; -		for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { -			const unsigned char styleByte = ll->styles[styleInLine]; -			ll->styles[styleInLine] = styleByte; -		} -		const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0; -		if (vstyle.someStylesForceCase) { -			for (int charInLine = 0; charInLine<lineLength; charInLine++) { -				char chDoc = ll->chars[charInLine]; -				if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) -					ll->chars[charInLine] = static_cast<char>(toupper(chDoc)); -				else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) -					ll->chars[charInLine] = static_cast<char>(tolower(chDoc)); -			} -		} -		ll->xHighlightGuide = 0; -		// Extra element at the end of the line to hold end x position and act as -		ll->chars[numCharsInLine] = 0;   // Also triggers processing in the loops as this is a control character -		ll->styles[numCharsInLine] = styleByteLast;	// For eolFilled - -		// Layout the line, determining the position of each character, -		// with an extra element at the end for the end of the line. -		ll->positions[0] = 0; -		bool lastSegItalics = false; - -		BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs); -		while (bfLayout.More()) { - -			const TextSegment ts = bfLayout.Next(); - -			std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f); -			if (vstyle.styles[ll->styles[ts.start]].visible) { -				if (ts.representation) { -					XYPOSITION representationWidth = vstyle.controlCharWidth; -					if (ll->chars[ts.start] == '\t') { -						// Tab is a special case of representation, taking a variable amount of space -						representationWidth = -							((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start]; -					} else { -						if (representationWidth <= 0.0) { -							XYPOSITION positionsRepr[256];	// Should expand when needed -							posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(), -								static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, model.pdoc); -							representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding; -						} -					} -					for (int ii = 0; ii < ts.length; ii++) -						ll->positions[ts.start + 1 + ii] = representationWidth; -				} else { -					if ((ts.length == 1) && (' ' == ll->chars[ts.start])) { -						// Over half the segments are single characters and of these about half are space characters. -						ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth; -					} else { -						posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start, -							ts.length, ll->positions + ts.start + 1, model.pdoc); -					} -				} -				lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic); -			} - -			for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) { -				ll->positions[posToIncrease] += ll->positions[ts.start]; -			} -		} - -		// Small hack to make lines that end with italics not cut off the edge of the last character -		if (lastSegItalics) { -			ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset; -		} -		ll->numCharsInLine = numCharsInLine; -		ll->numCharsBeforeEOL = numCharsBeforeEOL; -		ll->validity = LineLayout::llPositions; -	} -	// Hard to cope when too narrow, so just assume there is space -	if (width < 20) { -		width = 20; -	} -	if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { -		ll->widthLine = width; -		if (width == LineLayout::wrapWidthInfinite) { -			ll->lines = 1; -		} else if (width > ll->positions[ll->numCharsInLine]) { -			// Simple common case where line does not need wrapping. -			ll->lines = 1; -		} else { -			if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { -				width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark -			} -			XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line -			if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) { -				wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth; -			} else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) { -				wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth; -			} -			ll->wrapIndent = wrapAddIndent; -			if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED) -			for (int i = 0; i < ll->numCharsInLine; i++) { -				if (!IsSpaceOrTab(ll->chars[i])) { -					ll->wrapIndent += ll->positions[i]; // Add line indent -					break; -				} -			} -			// Check for text width minimum -			if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15) -				ll->wrapIndent = wrapAddIndent; -			// Check for wrapIndent minimum -			if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) -				ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual -			ll->lines = 0; -			// Calculate line start positions based upon width. -			int lastGoodBreak = 0; -			int lastLineStart = 0; -			XYACCUMULATOR startOffset = 0; -			int p = 0; -			while (p < ll->numCharsInLine) { -				if ((ll->positions[p + 1] - startOffset) >= width) { -					if (lastGoodBreak == lastLineStart) { -						// Try moving to start of last character -						if (p > 0) { -							lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) -								- posLineStart; -						} -						if (lastGoodBreak == lastLineStart) { -							// Ensure at least one character on line. -							lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) -								- posLineStart; -						} -					} -					lastLineStart = lastGoodBreak; -					ll->lines++; -					ll->SetLineStart(ll->lines, lastGoodBreak); -					startOffset = ll->positions[lastGoodBreak]; -					// take into account the space for start wrap mark and indent -					startOffset -= ll->wrapIndent; -					p = lastGoodBreak + 1; -					continue; -				} -				if (p > 0) { -					if (vstyle.wrapState == eWrapChar) { -						lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) -							- posLineStart; -						p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart; -						continue; -					} else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) { -						lastGoodBreak = p; -					} else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) { -						lastGoodBreak = p; -					} -				} -				p++; -			} -			ll->lines++; -		} -		ll->validity = LineLayout::llLines; -	} -} - -Point EditView::LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs) { -	Point pt; -	if (pos.Position() == INVALID_POSITION) -		return pt; -	const int line = model.pdoc->LineFromPosition(pos.Position()); -	const int lineVisible = model.cs.DisplayFromDoc(line); -	//Platform::DebugPrintf("line=%d\n", line); -	AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); -	if (surface && ll) { -		const int posLineStart = model.pdoc->LineStart(line); -		LayoutLine(line, surface, vs, ll, model, model.wrapWidth); -		const int posInLine = pos.Position() - posLineStart; -		pt = ll->PointFromPosition(posInLine, vs.lineHeight); -		pt.y += (lineVisible - topLine) * vs.lineHeight; -		pt.x += vs.textStart - model.xOffset; -	} -	pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; -	return pt; -} - -SelectionPosition EditView::SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const EditModel &model, const ViewStyle &vs) { -	pt.x = pt.x - vs.textStart; -	int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight)); -	if (!canReturnInvalid && (visibleLine < 0)) -		visibleLine = 0; -	const int lineDoc = model.cs.DocFromDisplay(visibleLine); -	if (canReturnInvalid && (lineDoc < 0)) -		return SelectionPosition(INVALID_POSITION); -	if (lineDoc >= model.pdoc->LinesTotal()) -		return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length()); -	const int posLineStart = model.pdoc->LineStart(lineDoc); -	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); -	if (surface && ll) { -		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); -		const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); -		const int subLine = visibleLine - lineStartSet; -		if (subLine < ll->lines) { -			const Range rangeSubLine = ll->SubLineRange(subLine); -			const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; -			if (subLine > 0)	// Wrapped -				pt.x -= ll->wrapIndent; -			const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); -			if (positionInLine < rangeSubLine.end) { -				return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); -			} -			if (virtualSpace) { -				const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; -				const int spaceOffset = static_cast<int>( -					(pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); -				return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); -			} else if (canReturnInvalid) { -				if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { -					return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); -				} -			} else { -				return SelectionPosition(rangeSubLine.end + posLineStart); -			} -		} -		if (!canReturnInvalid) -			return SelectionPosition(ll->numCharsInLine + posLineStart); -	} -	return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); -} - -/** -* Find the document position corresponding to an x coordinate on a particular document line. -* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. -* This method is used for rectangular selections and does not work on wrapped lines. -*/ -SelectionPosition EditView::SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs) { -	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); -	if (surface && ll) { -		const int posLineStart = model.pdoc->LineStart(lineDoc); -		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); -		const Range rangeSubLine = ll->SubLineRange(0); -		const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; -		const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); -		if (positionInLine < rangeSubLine.end) { -			return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); -		} -		const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; -		const int spaceOffset = static_cast<int>( -			(x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); -		return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); -	} -	return SelectionPosition(0); -} - -int EditView::DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs) { -	int lineDoc = model.pdoc->LineFromPosition(pos); -	int lineDisplay = model.cs.DisplayFromDoc(lineDoc); -	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); -	if (surface && ll) { -		LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth); -		unsigned int posLineStart = model.pdoc->LineStart(lineDoc); -		int posInLine = pos - posLineStart; -		lineDisplay--; // To make up for first increment ahead. -		for (int subLine = 0; subLine < ll->lines; subLine++) { -			if (posInLine >= ll->LineStart(subLine)) { -				lineDisplay++; -			} -		} -	} -	return lineDisplay; -} - -int EditView::StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs) { -	int line = model.pdoc->LineFromPosition(pos); -	AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); -	int posRet = INVALID_POSITION; -	if (surface && ll) { -		unsigned int posLineStart = model.pdoc->LineStart(line); -		LayoutLine(line, surface, vs, ll, model, model.wrapWidth); -		int posInLine = pos - posLineStart; -		if (posInLine <= ll->maxLineLength) { -			for (int subLine = 0; subLine < ll->lines; subLine++) { -				if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { -					if (start) { -						posRet = ll->LineStart(subLine) + posLineStart; -					} else { -						if (subLine == ll->lines - 1) -							posRet = ll->LineStart(subLine + 1) + posLineStart; -						else -							posRet = ll->LineStart(subLine + 1) + posLineStart - 1; -					} -				} -			} -		} -	} -	return posRet; -} - -static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) { -	return main ? -		(primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) : -		vsDraw.selAdditionalBackground; -} - -static ColourDesired TextBackground(const ViewStyle &vsDraw, -	ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i, -	LineLayout *ll, const EditModel &model) { -	if (inSelection == 1) { -		if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { -			return SelectionBackground(vsDraw, true, model.primarySelection); -		} -	} else if (inSelection == 2) { -		if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) { -			return SelectionBackground(vsDraw, false, model.primarySelection); -		} -	} else { -		if ((vsDraw.edgeState == EDGE_BACKGROUND) && -			(i >= ll->edgeColumn) && -			(i < ll->numCharsBeforeEOL)) -			return vsDraw.edgecolour; -		if (inHotspot && vsDraw.hotspotColours.back.isSet) -			return vsDraw.hotspotColours.back; -	} -	if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { -		return background; -	} else { -		return vsDraw.styles[styleMain].back; -	} -} - -void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { -	Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); -	PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast<int>(rcSegment.top), start + 2, static_cast<int>(rcSegment.bottom)); -	surface->Copy(rcCopyArea, from, -		highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); -} - -static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { -	if (alpha != SC_ALPHA_NOALPHA) { -		surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); -	} -} - -void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, -	const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) { -	if (!twoPhaseDraw) { -		surface->FillRectangle(rcSegment, textBack); -	} -	FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; -	int normalCharHeight = static_cast<int>(surface->Ascent(ctrlCharsFont) - -		surface->InternalLeading(ctrlCharsFont)); -	PRectangle rcCChar = rcSegment; -	rcCChar.left = rcCChar.left + 1; -	rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight; -	rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1; -	PRectangle rcCentral = rcCChar; -	rcCentral.top++; -	rcCentral.bottom--; -	surface->FillRectangle(rcCentral, textFore); -	PRectangle rcChar = rcCChar; -	rcChar.left++; -	rcChar.right--; -	surface->DrawTextClipped(rcChar, ctrlCharsFont, -		rcSegment.top + vsDraw.maxAscent, s, static_cast<int>(s ? strlen(s) : 0), -		textBack, textFore); -} - -void EditView::DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, -	int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, -	ColourOptional background, const EditModel &model) { - -	const int posLineStart = model.pdoc->LineStart(line); -	PRectangle rcSegment = rcLine; - -	const bool lastSubLine = subLine == (ll->lines - 1); -	XYPOSITION virtualSpace = 0; -	if (lastSubLine) { -		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; -		virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth; -	} -	XYPOSITION xEol = static_cast<XYPOSITION>(ll->positions[lineEnd] - subLineStart); - -	// Fill the virtual space and show selections within it -	if (virtualSpace) { -		rcSegment.left = xEol + xStart; -		rcSegment.right = xEol + xStart + virtualSpace; -		surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back); -		if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { -			SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)))); -			for (size_t r = 0; r<model.sel.Count(); r++) { -				int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; -				if (alpha == SC_ALPHA_NOALPHA) { -					SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); -					if (!portion.Empty()) { -						const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; -						rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - -							static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth; -						rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - -							static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth; -						rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; -						rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; -						surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection)); -					} -				} -			} -		} -	} - -	int eolInSelection = 0; -	int alpha = SC_ALPHA_NOALPHA; -	if (!hideSelection) { -		int posAfterLineEnd = model.pdoc->LineStart(line + 1); -		eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; -		alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; -	} - -	// Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on -	XYPOSITION blobsWidth = 0; -	if (lastSubLine) { -		for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) { -			rcSegment.left = xStart + ll->positions[eolPos] - static_cast<XYPOSITION>(subLineStart)+virtualSpace; -			rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast<XYPOSITION>(subLineStart)+virtualSpace; -			blobsWidth += rcSegment.Width(); -			char hexits[4]; -			const char *ctrlChar; -			unsigned char chEOL = ll->chars[eolPos]; -			int styleMain = ll->styles[eolPos]; -			ColourDesired textBack = TextBackground(vsDraw, background, eolInSelection, false, styleMain, eolPos, ll, model); -			if (UTF8IsAscii(chEOL)) { -				ctrlChar = ControlCharacterString(chEOL); -			} else { -				const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos); -				if (repr) { -					ctrlChar = repr->stringRep.c_str(); -					eolPos = ll->numCharsInLine; -				} else { -					sprintf(hexits, "x%2X", chEOL); -					ctrlChar = hexits; -				} -			} -			ColourDesired textFore = vsDraw.styles[styleMain].fore; -			if (eolInSelection && vsDraw.selColours.fore.isSet) { -				textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; -			} -			if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) { -				if (alpha == SC_ALPHA_NOALPHA) { -					surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); -				} else { -					surface->FillRectangle(rcSegment, textBack); -				} -			} else { -				surface->FillRectangle(rcSegment, textBack); -			} -			DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw); -			if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { -				SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); -			} -		} -	} - -	// Draw the eol-is-selected rectangle -	rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; -	rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; - -	if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { -		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); -	} else { -		if (background.isSet) { -			surface->FillRectangle(rcSegment, background); -		} else if (line < model.pdoc->LinesTotal() - 1) { -			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); -		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { -			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); -		} else { -			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); -		} -		if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { -			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); -		} -	} - -	// Fill the remainder of the line -	rcSegment.left = rcSegment.right; -	if (rcSegment.left < rcLine.left) -		rcSegment.left = rcLine.left; -	rcSegment.right = rcLine.right; - -	if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { -		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); -	} else { -		if (background.isSet) { -			surface->FillRectangle(rcSegment, background); -		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { -			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); -		} else { -			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); -		} -		if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { -			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); -		} -	} - -	bool drawWrapMarkEnd = false; - -	if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { -		if (subLine + 1 < ll->lines) { -			drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; -		} -	} - -	if (drawWrapMarkEnd) { -		PRectangle rcPlace = rcSegment; - -		if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { -			rcPlace.left = xEol + xStart + virtualSpace; -			rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; -		} else { -			// rcLine is clipped to text area -			rcPlace.right = rcLine.right; -			rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; -		} -		DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); -	} -} - -static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw, -	int xStart, PRectangle rcLine, LineLayout *ll, int subLine) { -	const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; -	PRectangle rcIndic( -		ll->positions[startPos] + xStart - subLineStart, -		rcLine.top + vsDraw.maxAscent, -		ll->positions[endPos] + xStart - subLineStart, -		rcLine.top + vsDraw.maxAscent + 3); -	vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine); -} - -static void DrawIndicators(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, -	PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under, const EditModel &model) { -	// Draw decorators -	const int posLineStart = model.pdoc->LineStart(line); -	const int lineStart = ll->LineStart(subLine); -	const int posLineEnd = posLineStart + lineEnd; - -	for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { -		if (under == vsDraw.indicators[deco->indicator].under) { -			int startPos = posLineStart + lineStart; -			if (!deco->rs.ValueAt(startPos)) { -				startPos = deco->rs.EndRun(startPos); -			} -			while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) { -				int endPos = deco->rs.EndRun(startPos); -				if (endPos > posLineEnd) -					endPos = posLineEnd; -				DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, -					surface, vsDraw, xStart, rcLine, ll, subLine); -				startPos = endPos; -				if (!deco->rs.ValueAt(startPos)) { -					startPos = deco->rs.EndRun(startPos); -				} -			} -		} -	} - -	// Use indicators to highlight matching braces -	if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || -		(vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { -		int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator; -		if (under == vsDraw.indicators[braceIndicator].under) { -			Range rangeLine(posLineStart + lineStart, posLineEnd); -			if (rangeLine.ContainsCharacter(model.braces[0])) { -				int braceOffset = model.braces[0] - posLineStart; -				if (braceOffset < ll->numCharsInLine) { -					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); -				} -			} -			if (rangeLine.ContainsCharacter(model.braces[1])) { -				int braceOffset = model.braces[1] - posLineStart; -				if (braceOffset < ll->numCharsInLine) { -					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); -				} -			} -		} -	} -} - -void EditView::DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, -	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) { -	int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth); -	PRectangle rcSegment = rcLine; -	int annotationLine = subLine - ll->lines; -	const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line); -	if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { -		surface->FillRectangle(rcSegment, vsDraw.styles[0].back); -		rcSegment.left = static_cast<XYPOSITION>(xStart); -		if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) { -			// Only care about calculating width if tracking or need to draw box -			int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); -			if (vsDraw.annotationVisible == ANNOTATION_BOXED) { -				widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins -			} -			if (widthAnnotation > lineWidthMaxSeen) -				lineWidthMaxSeen = widthAnnotation; -			if (vsDraw.annotationVisible == ANNOTATION_BOXED) { -				rcSegment.left = static_cast<XYPOSITION>(xStart + indent); -				rcSegment.right = rcSegment.left + widthAnnotation; -			} -		} -		const int annotationLines = model.pdoc->AnnotationLines(line); -		size_t start = 0; -		size_t lengthAnnotation = stAnnotation.LineLength(start); -		int lineInAnnotation = 0; -		while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { -			start += lengthAnnotation + 1; -			lengthAnnotation = stAnnotation.LineLength(start); -			lineInAnnotation++; -		} -		PRectangle rcText = rcSegment; -		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { -			surface->FillRectangle(rcText, -				vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); -			rcText.left += vsDraw.spaceWidth; -		} -		DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, -			stAnnotation, start, lengthAnnotation); -		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { -			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); -			surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top)); -			surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom)); -			surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top)); -			surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom)); -			if (subLine == ll->lines) { -				surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top)); -				surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top)); -			} -			if (subLine == ll->lines + annotationLines - 1) { -				surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1)); -				surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1)); -			} -		} -	} -} - -static void DrawBlockCaret(Surface *surface, const ViewStyle &vsDraw, LineLayout *ll, int subLine, -	int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour, const EditModel &model) { - -	int lineStart = ll->LineStart(subLine); -	int posBefore = posCaret; -	int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1); -	int numCharsToDraw = posAfter - posCaret; - -	// Work out where the starting and ending offsets are. We need to -	// see if the previous character shares horizontal space, such as a -	// glyph / combining character. If so we'll need to draw that too. -	int offsetFirstChar = offset; -	int offsetLastChar = offset + (posAfter - posCaret); -	while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { -		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { -			// The char does not share horizontal space -			break; -		} -		// Char shares horizontal space, update the numChars to draw -		// Update posBefore to point to the prev char -		posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1); -		numCharsToDraw = posAfter - posBefore; -		offsetFirstChar = offset - (posCaret - posBefore); -	} - -	// See if the next character shares horizontal space, if so we'll -	// need to draw that too. -	if (offsetFirstChar < 0) -		offsetFirstChar = 0; -	numCharsToDraw = offsetLastChar - offsetFirstChar; -	while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { -		// Update posAfter to point to the 2nd next char, this is where -		// the next character ends, and 2nd next begins. We'll need -		// to compare these two -		posBefore = posAfter; -		posAfter = model.pdoc->MovePositionOutsideChar(posAfter + 1, 1); -		offsetLastChar = offset + (posAfter - posCaret); -		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { -			// The char does not share horizontal space -			break; -		} -		// Char shares horizontal space, update the numChars to draw -		numCharsToDraw = offsetLastChar - offsetFirstChar; -	} - -	// We now know what to draw, update the caret drawing rectangle -	rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; -	rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart; - -	// Adjust caret position to take into account any word wrapping symbols. -	if ((ll->wrapIndent != 0) && (lineStart != 0)) { -		XYPOSITION wordWrapCharWidth = ll->wrapIndent; -		rcCaret.left += wordWrapCharWidth; -		rcCaret.right += wordWrapCharWidth; -	} - -	// This character is where the caret block is, we override the colours -	// (inversed) for drawing the caret here. -	int styleMain = ll->styles[offsetFirstChar]; -	FontAlias fontText = vsDraw.styles[styleMain].font; -	surface->DrawTextClipped(rcCaret, fontText, -		rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, -		numCharsToDraw, vsDraw.styles[styleMain].back, -		caretColour); -} - -void EditView::DrawCarets(Surface *surface, const ViewStyle &vsDraw, int lineDoc, int xStart, -	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const { -	// When drag is active it is the only caret drawn -	bool drawDrag = model.posDrag.IsValid(); -	if (hideSelection && !drawDrag) -		return; -	const int posLineStart = model.pdoc->LineStart(lineDoc); -	// For each selection draw -	for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) { -		const bool mainCaret = r == model.sel.Main(); -		const SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret); -		const int offset = posCaret.Position() - posLineStart; -		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; -		const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; -		if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { -			XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; -			if (ll->wrapIndent != 0) { -				int lineStart = ll->LineStart(subLine); -				if (lineStart != 0)	// Wrapped -					xposCaret += ll->wrapIndent; -			} -			bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret); -			bool caretVisibleState = additionalCaretsVisible || mainCaret; -			if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) && -				((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) { -				bool caretAtEOF = false; -				bool caretAtEOL = false; -				bool drawBlockCaret = false; -				XYPOSITION widthOverstrikeCaret; -				XYPOSITION caretWidthOffset = 0; -				PRectangle rcCaret = rcLine; - -				if (posCaret.Position() == model.pdoc->Length()) {   // At end of document -					caretAtEOF = true; -					widthOverstrikeCaret = vsDraw.aveCharWidth; -				} else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) {	// At end of line -					caretAtEOL = true; -					widthOverstrikeCaret = vsDraw.aveCharWidth; -				} else { -					widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; -				} -				if (widthOverstrikeCaret < 3)	// Make sure its visible -					widthOverstrikeCaret = 3; - -				if (xposCaret > 0) -					caretWidthOffset = 0.51f;	// Move back so overlaps both character cells. -				xposCaret += xStart; -				if (model.posDrag.IsValid()) { -					/* Dragging text, use a line caret */ -					rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset)); -					rcCaret.right = rcCaret.left + vsDraw.caretWidth; -				} else if (model.inOverstrike && drawOverstrikeCaret) { -					/* Overstrike (insert mode), use a modified bar caret */ -					rcCaret.top = rcCaret.bottom - 2; -					rcCaret.left = xposCaret + 1; -					rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; -				} else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) { -					/* Block caret */ -					rcCaret.left = xposCaret; -					if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { -						drawBlockCaret = true; -						rcCaret.right = xposCaret + widthOverstrikeCaret; -					} else { -						rcCaret.right = xposCaret + vsDraw.aveCharWidth; -					} -				} else { -					/* Line caret */ -					rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset)); -					rcCaret.right = rcCaret.left + vsDraw.caretWidth; -				} -				ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; -				if (drawBlockCaret) { -					DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour, model); -				} else { -					surface->FillRectangle(rcCaret, caretColour); -				} -			} -		} -		if (drawDrag) -			break; -	} -} - -void EditView::DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart, -	PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) { - -	if (subLine >= ll->lines) { -		DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine, model); -		return; // No further drawing -	} - -	// Using one font for all control characters so it can be controlled independently to ensure -	// the box goes around the characters tightly. Seems to be no way to work out what height -	// is taken by an individual character - internal leading gives varying results. -	FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; - -	// See if something overrides the line background color. -	const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); - -	const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) && -		(!background.isSet) && (vsDraw.whitespaceColours.back.isSet); - -	const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth; - -	const int posLineStart = model.pdoc->LineStart(line); - -	const Range lineRange = ll->SubLineRange(subLine); -	const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; - -	if ((ll->wrapIndent != 0) && (subLine > 0) && (subLine < ll->lines)) { -		// default bgnd here.. -		surface->FillRectangle(rcLine, background.isSet ? background : -			vsDraw.styles[STYLE_DEFAULT].back); - -		if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) { - -			// draw continuation rect -			PRectangle rcPlace = rcLine; - -			rcPlace.left = static_cast<XYPOSITION>(xStart); -			rcPlace.right = rcPlace.left + ll->wrapIndent; - -			if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) -				rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; -			else -				rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; - -			DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); -		} - -		xStart += static_cast<int>(ll->wrapIndent); -	} - -	const bool selBackDrawn = vsDraw.selColours.back.isSet && -		((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)); - -	// Does not take margin into account but not significant -	const int xStartVisible = static_cast<int>(subLineStart)-xStart; - -	if (twoPhaseDraw) { -		bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline. -		BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs); - -		// Background drawing loop -		while (bfBack.More()) { - -			const TextSegment ts = bfBack.Next(); -			const int i = ts.end() - 1; -			const int iDoc = i + posLineStart; - -			PRectangle rcSegment = rcLine; -			rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart); -			rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart); -			// Only try to draw if really visible - enhances performance by not calling environment to -			// draw strings that are completely past the right side of the window. -			if (rcSegment.Intersects(rcLine)) { -				// Clip to line rectangle, since may have a huge position which will not work with some platforms -				if (rcSegment.left < rcLine.left) -					rcSegment.left = rcLine.left; -				if (rcSegment.right > rcLine.right) -					rcSegment.right = rcLine.right; - -				const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); -				const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); -				ColourDesired textBack = TextBackground(vsDraw, background, inSelection, -					inHotspot, ll->styles[i], i, ll, model); -				if (ts.representation) { -					if (ll->chars[i] == '\t') { -						// Tab display -						if (drawWhitespaceBackground && -							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) -							textBack = vsDraw.whitespaceColours.back; -					} else { -						// Blob display -						inIndentation = false; -					} -					surface->FillRectangle(rcSegment, textBack); -				} else { -					// Normal text display -					surface->FillRectangle(rcSegment, textBack); -					if (vsDraw.viewWhitespace != wsInvisible || -						(inIndentation && vsDraw.viewIndentationGuides == ivReal)) { -						for (int cpos = 0; cpos <= i - ts.start; cpos++) { -							if (ll->chars[cpos + ts.start] == ' ') { -								if (drawWhitespaceBackground && -									(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { -									PRectangle rcSpace( -										ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart), -										rcSegment.top, -										ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart), -										rcSegment.bottom); -									surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back); -								} -							} else { -								inIndentation = false; -							} -						} -					} -				} -			} else if (rcSegment.left > rcLine.right) { -				break; -			} -		} - -		DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end, -			xStart, subLine, subLineStart, background, model); -	} - -	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, true, model); - -	if (vsDraw.edgeState == EDGE_LINE) { -		PRectangle rcSegment = rcLine; -		int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth); -		rcSegment.left = static_cast<XYPOSITION>(edgeX + xStart); -		if ((ll->wrapIndent != 0) && (lineRange.start != 0)) -			rcSegment.left -= ll->wrapIndent; -		rcSegment.right = rcSegment.left + 1; -		surface->FillRectangle(rcSegment, vsDraw.edgecolour); -	} - -	// Draw underline mark as part of background if not transparent -	int marks = model.pdoc->GetMark(line); -	int markBit; -	for (markBit = 0; (markBit < 32) && marks; markBit++) { -		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) && -			(vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { -			PRectangle rcUnderline = rcLine; -			rcUnderline.top = rcUnderline.bottom - 2; -			surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); -		} -		marks >>= 1; -	} - -	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline. -	// Foreground drawing loop -	BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, -		((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs); - -	while (bfFore.More()) { - -		const TextSegment ts = bfFore.Next(); -		const int i = ts.end() - 1; -		const int iDoc = i + posLineStart; - -		PRectangle rcSegment = rcLine; -		rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart); -		rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart); -		// Only try to draw if really visible - enhances performance by not calling environment to -		// draw strings that are completely past the right side of the window. -		if (rcSegment.Intersects(rcLine)) { -			int styleMain = ll->styles[i]; -			ColourDesired textFore = vsDraw.styles[styleMain].fore; -			FontAlias textFont = vsDraw.styles[styleMain].font; -			//hotspot foreground -			const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); -			if (inHotspot) { -				if (vsDraw.hotspotColours.fore.isSet) -					textFore = vsDraw.hotspotColours.fore; -			} -			const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); -			if (inSelection && (vsDraw.selColours.fore.isSet)) { -				textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; -			} -			ColourDesired textBack = TextBackground(vsDraw, background, inSelection, inHotspot, styleMain, i, ll, model); -			if (ts.representation) { -				if (ll->chars[i] == '\t') { -					// Tab display -					if (!twoPhaseDraw) { -						if (drawWhitespaceBackground && -							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) -							textBack = vsDraw.whitespaceColours.back; -						surface->FillRectangle(rcSegment, textBack); -					} -					if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { -						for (int indentCount = static_cast<int>((ll->positions[i] + epsilon) / indentWidth); -							indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; -							indentCount++) { -							if (indentCount > 0) { -								int xIndent = static_cast<int>(indentCount * indentWidth); -								DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, -									(ll->xHighlightGuide == xIndent)); -							} -						} -					} -					if (vsDraw.viewWhitespace != wsInvisible) { -						if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { -							if (vsDraw.whitespaceColours.fore.isSet) -								textFore = vsDraw.whitespaceColours.fore; -							surface->PenColour(textFore); -							PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, -								rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); -							DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2)); -						} -					} -				} else { -					inIndentation = false; -					if (vsDraw.controlCharSymbol >= 32) { -						char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' }; -						surface->DrawTextNoClip(rcSegment, ctrlCharsFont, -							rcSegment.top + vsDraw.maxAscent, -							cc, 1, textBack, textFore); -					} else { -						DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw); -					} -				} -			} else { -				// Normal text display -				if (vsDraw.styles[styleMain].visible) { -					if (twoPhaseDraw) { -						surface->DrawTextTransparent(rcSegment, textFont, -							rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, -							i - ts.start + 1, textFore); -					} else { -						surface->DrawTextNoClip(rcSegment, textFont, -							rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, -							i - ts.start + 1, textFore, textBack); -					} -				} -				if (vsDraw.viewWhitespace != wsInvisible || -					(inIndentation && vsDraw.viewIndentationGuides != ivNone)) { -					for (int cpos = 0; cpos <= i - ts.start; cpos++) { -						if (ll->chars[cpos + ts.start] == ' ') { -							if (vsDraw.viewWhitespace != wsInvisible) { -								if (vsDraw.whitespaceColours.fore.isSet) -									textFore = vsDraw.whitespaceColours.fore; -								if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { -									XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; -									if (!twoPhaseDraw && drawWhitespaceBackground && -										(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { -										textBack = vsDraw.whitespaceColours.back; -										PRectangle rcSpace( -											ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart), -											rcSegment.top, -											ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart), -											rcSegment.bottom); -										surface->FillRectangle(rcSpace, textBack); -									} -									PRectangle rcDot(xmid + xStart - static_cast<XYPOSITION>(subLineStart), -										rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f); -									rcDot.right = rcDot.left + vsDraw.whitespaceSize; -									rcDot.bottom = rcDot.top + vsDraw.whitespaceSize; -									surface->FillRectangle(rcDot, textFore); -								} -							} -							if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { -								for (int indentCount = static_cast<int>((ll->positions[cpos + ts.start] + epsilon) / indentWidth); -									indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth; -									indentCount++) { -									if (indentCount > 0) { -										int xIndent = static_cast<int>(indentCount * indentWidth); -										DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, -											(ll->xHighlightGuide == xIndent)); -									} -								} -							} -						} else { -							inIndentation = false; -						} -					} -				} -			} -			if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) { -				PRectangle rcUL = rcSegment; -				rcUL.top = rcUL.top + vsDraw.maxAscent + 1; -				rcUL.bottom = rcUL.top + 1; -				if (vsDraw.hotspotColours.fore.isSet) -					surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore); -				else -					surface->FillRectangle(rcUL, textFore); -			} else if (vsDraw.styles[styleMain].underline) { -				PRectangle rcUL = rcSegment; -				rcUL.top = rcUL.top + vsDraw.maxAscent + 1; -				rcUL.bottom = rcUL.top + 1; -				surface->FillRectangle(rcUL, textFore); -			} -		} else if (rcSegment.left > rcLine.right) { -			break; -		} -	} -	if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth) -		&& (subLine == 0)) { -		int indentSpace = model.pdoc->GetLineIndentation(line); -		int xStartText = static_cast<int>(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]); - -		// Find the most recent line with some text - -		int lineLastWithText = line; -		while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) { -			lineLastWithText--; -		} -		if (lineLastWithText < line) { -			xStartText = 100000;	// Don't limit to visible indentation on empty line -			// This line is empty, so use indentation of last line with text -			int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText); -			int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG; -			if (isFoldHeader) { -				// Level is one more level than parent -				indentLastWithText += model.pdoc->IndentSize(); -			} -			if (vsDraw.viewIndentationGuides == ivLookForward) { -				// In viLookForward mode, previous line only used if it is a fold header -				if (isFoldHeader) { -					indentSpace = Platform::Maximum(indentSpace, indentLastWithText); -				} -			} else {	// viLookBoth -				indentSpace = Platform::Maximum(indentSpace, indentLastWithText); -			} -		} - -		int lineNextWithText = line; -		while (lineNextWithText < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) { -			lineNextWithText++; -		} -		if (lineNextWithText > line) { -			xStartText = 100000;	// Don't limit to visible indentation on empty line -			// This line is empty, so use indentation of first next line with text -			indentSpace = Platform::Maximum(indentSpace, -				model.pdoc->GetLineIndentation(lineNextWithText)); -		} - -		for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) { -			int xIndent = static_cast<int>(indentPos * vsDraw.spaceWidth); -			if (xIndent < xStartText) { -				DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine, -					(ll->xHighlightGuide == xIndent)); -			} -		} -	} - -	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, false, model); - -	// End of the drawing of the current line -	if (!twoPhaseDraw) { -		DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end, -			xStart, subLine, subLineStart, background, model); -	} -	if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) { -		// For each selection draw -		int virtualSpaces = 0; -		if (subLine == (ll->lines - 1)) { -			virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)); -		} -		SelectionPosition posStart(posLineStart + lineRange.start); -		SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces); -		SelectionSegment virtualSpaceRange(posStart, posEnd); -		for (size_t r = 0; r<model.sel.Count(); r++) { -			int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; -			if (alpha != SC_ALPHA_NOALPHA) { -				SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); -				if (!portion.Empty()) { -					const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; -					PRectangle rcSegment = rcLine; -					rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - -						static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth; -					rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - -						static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth; -					if ((ll->wrapIndent != 0) && (lineRange.start != 0)) { -						if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) -							rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here -					} -					rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; -					rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; -					if (rcSegment.right > rcLine.left) -						SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha); -				} -			} -		} -	} - -	// Draw any translucent whole line states -	if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) { -		SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); -	} -	marks = model.pdoc->GetMark(line); -	for (markBit = 0; (markBit < 32) && marks; markBit++) { -		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { -			SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); -		} else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { -			PRectangle rcUnderline = rcLine; -			rcUnderline.top = rcUnderline.bottom - 2; -			SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); -		} -		marks >>= 1; -	} -	if (vsDraw.maskInLine) { -		int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine; -		if (marksMasked) { -			for (markBit = 0; (markBit < 32) && marksMasked; markBit++) { -				if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { -					SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); -				} -				marksMasked >>= 1; -			} -		} -	} -} - -void EditView::PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient, -	const EditModel &model, const ViewStyle &vsDraw) { -	// Allow text at start of line to overlap 1 pixel into the margin as this displays -	// serifs and italic stems for aliased text. -	const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0; - -	// Do the painting -	if (rcArea.right > vsDraw.textStart - leftTextOverlap) { - -		Surface *surface = surfaceWindow; -		if (bufferedDraw) { -			surface = pixmapLine; -			PLATFORM_ASSERT(pixmapLine->Initialised()); -		} -		surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage); -		surface->SetDBCSMode(model.pdoc->dbcsCodePage); - -		Point ptOrigin = model.GetVisibleOriginInMain(); - -		int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight; -		int ypos = 0; -		if (!bufferedDraw) -			ypos += screenLinePaintFirst * vsDraw.lineHeight; -		int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x); - -		int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; -		int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; - -		SelectionPosition posCaret = model.sel.RangeMain().caret; -		if (model.posDrag.IsValid()) -			posCaret = model.posDrag; -		int lineCaret = model.pdoc->LineFromPosition(posCaret.Position()); - -		PRectangle rcTextArea = rcClient; -		if (vsDraw.marginInside) { -			rcTextArea.left += vsDraw.textStart; -			rcTextArea.right -= vsDraw.rightMarginWidth; -		} else { -			rcTextArea = rcArea; -		} - -		// Remove selection margin from drawing area so text will not be drawn -		// on it in unbuffered mode. -		if (!bufferedDraw && vsDraw.marginInside) { -			PRectangle rcClipText = rcTextArea; -			rcClipText.left -= leftTextOverlap; -			surfaceWindow->SetClip(rcClipText); -		} - -		// Loop on visible lines -		//double durLayout = 0.0; -		//double durPaint = 0.0; -		//double durCopy = 0.0; -		//ElapsedTime etWhole; -		int lineDocPrevious = -1;	// Used to avoid laying out one document line multiple times -		AutoLineLayout ll(llc, 0); -		while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { - -			int lineDoc = model.cs.DocFromDisplay(visibleLine); -			// Only visible lines should be handled by the code within the loop -			PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); -			int lineStartSet = model.cs.DisplayFromDoc(lineDoc); -			int subLine = visibleLine - lineStartSet; - -			// Copy this line and its styles from the document into local arrays -			// and determine the x position at which each character starts. -			//ElapsedTime et; -			if (lineDoc != lineDocPrevious) { -				ll.Set(0); -				ll.Set(RetrieveLineLayout(lineDoc, model)); -				LayoutLine(lineDoc, surface, vsDraw, ll, model, model.wrapWidth); -				lineDocPrevious = lineDoc; -			} -			//durLayout += et.Duration(true); - -			if (ll) { -				ll->containsCaret = lineDoc == lineCaret; -				if (hideSelection) { -					ll->containsCaret = false; -				} - -				ll->hotspot = model.GetHotSpotRange(); - -				PRectangle rcLine = rcTextArea; -				rcLine.top = static_cast<XYPOSITION>(ypos); -				rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight); - -				bool bracesIgnoreStyle = false; -				if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || -					(vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { -					bracesIgnoreStyle = true; -				} -				Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); -				// Highlight the current braces if any -				ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle), -					static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); - -				if (leftTextOverlap && bufferedDraw) { -					PRectangle rcSpacer = rcLine; -					rcSpacer.right = rcSpacer.left; -					rcSpacer.left -= 1; -					surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); -				} - -				// Draw the line -				DrawLine(surface, vsDraw, lineDoc, visibleLine, xStart, rcLine, ll, subLine, model); -				//durPaint += et.Duration(true); - -				// Restore the previous styles for the brace highlights in case layout is in cache. -				ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); - -				bool expanded = model.cs.GetExpanded(lineDoc); -				const int level = model.pdoc->GetLevel(lineDoc); -				const int levelNext = model.pdoc->GetLevel(lineDoc + 1); -				if ((level & SC_FOLDLEVELHEADERFLAG) && -					((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { -					// Paint the line above the fold -					if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) -						|| -						(!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { -						PRectangle rcFoldLine = rcLine; -						rcFoldLine.bottom = rcFoldLine.top + 1; -						surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); -					} -					// Paint the line below the fold -					if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) -						|| -						(!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { -						PRectangle rcFoldLine = rcLine; -						rcFoldLine.top = rcFoldLine.bottom - 1; -						surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); -					} -				} - -				DrawCarets(surface, vsDraw, lineDoc, xStart, rcLine, ll, subLine, model); - -				if (bufferedDraw) { -					Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); -					PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, -						static_cast<int>(rcClient.right - vsDraw.rightMarginWidth), -						yposScreen + vsDraw.lineHeight); -					surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); -				} - -				lineWidthMaxSeen = Platform::Maximum( -					lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine])); -				//durCopy += et.Duration(true); -			} - -			if (!bufferedDraw) { -				ypos += vsDraw.lineHeight; -			} - -			yposScreen += vsDraw.lineHeight; -			visibleLine++; - -			//gdk_flush(); -		} -		ll.Set(0); -		//if (durPaint < 0.00000001) -		//	durPaint = 0.00000001; - -		// Right column limit indicator -		PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea; -		rcBeyondEOF.left = static_cast<XYPOSITION>(vsDraw.textStart); -		rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0); -		rcBeyondEOF.top = static_cast<XYPOSITION>((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight); -		if (rcBeyondEOF.top < rcBeyondEOF.bottom) { -			surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back); -			if (vsDraw.edgeState == EDGE_LINE) { -				int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth); -				rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart); -				rcBeyondEOF.right = rcBeyondEOF.left + 1; -				surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour); -			} -		} -		//Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); - -		//Platform::DebugPrintf( -		//"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n", -		//durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); -	} -} - -// Space (3 space characters) between line numbers and text when printing. -#define lineNumberPrintSpace "   " - -ColourDesired InvertedLight(ColourDesired orig) { -	unsigned int r = orig.GetRed(); -	unsigned int g = orig.GetGreen(); -	unsigned int b = orig.GetBlue(); -	unsigned int l = (r + g + b) / 3; 	// There is a better calculation for this that matches human eye -	unsigned int il = 0xff - l; -	if (l == 0) -		return ColourDesired(0xff, 0xff, 0xff); -	r = r * il / l; -	g = g * il / l; -	b = b * il / l; -	return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); -} - -long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, -	const EditModel &model, const ViewStyle &vs) { -	// Can't use measurements cached for screen -	posCache.Clear(); - -	ViewStyle vsPrint(vs); -	vsPrint.technology = SC_TECHNOLOGY_DEFAULT; - -	// Modify the view style for printing as do not normally want any of the transient features to be printed -	// Printing supports only the line number margin. -	int lineNumberIndex = -1; -	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { -		if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) { -			lineNumberIndex = margin; -		} else { -			vsPrint.ms[margin].width = 0; -		} -	} -	vsPrint.fixedColumnWidth = 0; -	vsPrint.zoomLevel = printParameters.magnification; -	// Don't show indentation guides -	// If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT -	vsPrint.viewIndentationGuides = ivNone; -	// Don't show the selection when printing -	vsPrint.selColours.back.isSet = false; -	vsPrint.selColours.fore.isSet = false; -	vsPrint.selAlpha = SC_ALPHA_NOALPHA; -	vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA; -	vsPrint.whitespaceColours.back.isSet = false; -	vsPrint.whitespaceColours.fore.isSet = false; -	vsPrint.showCaretLineBackground = false; -	vsPrint.alwaysShowCaretLineBackground = false; -	// Don't highlight matching braces using indicators -	vsPrint.braceHighlightIndicatorSet = false; -	vsPrint.braceBadLightIndicatorSet = false; - -	// Set colours for printing according to users settings -	for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) { -		if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) { -			vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); -			vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); -		} else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) { -			vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); -			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); -		} else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) { -			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); -		} else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { -			if (sty <= STYLE_DEFAULT) { -				vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); -			} -		} -	} -	// White background for the line numbers -	vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); - -	// Printing uses different margins, so reset screen margins -	vsPrint.leftMarginWidth = 0; -	vsPrint.rightMarginWidth = 0; - -	vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); -	// Determining width must happen after fonts have been realised in Refresh -	int lineNumberWidth = 0; -	if (lineNumberIndex >= 0) { -		lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, -			"99999" lineNumberPrintSpace, 5 + static_cast<int>(strlen(lineNumberPrintSpace)))); -		vsPrint.ms[lineNumberIndex].width = lineNumberWidth; -		vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars);	// Recalculate fixedColumnWidth -	} - -	int linePrintStart = model.pdoc->LineFromPosition(pfr->chrg.cpMin); -	int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; -	if (linePrintLast < linePrintStart) -		linePrintLast = linePrintStart; -	int linePrintMax = model.pdoc->LineFromPosition(pfr->chrg.cpMax); -	if (linePrintLast > linePrintMax) -		linePrintLast = linePrintMax; -	//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", -	//      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, -	//      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); -	int endPosPrint = model.pdoc->Length(); -	if (linePrintLast < model.pdoc->LinesTotal()) -		endPosPrint = model.pdoc->LineStart(linePrintLast + 1); - -	// Ensure we are styled to where we are formatting. -	model.pdoc->EnsureStyledTo(endPosPrint); - -	int xStart = vsPrint.fixedColumnWidth + pfr->rc.left; -	int ypos = pfr->rc.top; - -	int lineDoc = linePrintStart; - -	int nPrintPos = pfr->chrg.cpMin; -	int visibleLine = 0; -	int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; -	if (printParameters.wrapState == eWrapNone) -		widthPrint = LineLayout::wrapWidthInfinite; - -	while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) { - -		// When printing, the hdc and hdcTarget may be the same, so -		// changing the state of surfaceMeasure may change the underlying -		// state of surface. Therefore, any cached state is discarded before -		// using each surface. -		surfaceMeasure->FlushCachedState(); - -		// Copy this line and its styles from the document into local arrays -		// and determine the x position at which each character starts. -		LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1); -		LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, model, widthPrint); - -		ll.containsCaret = false; - -		PRectangle rcLine = PRectangle::FromInts( -			pfr->rc.left, -			ypos, -			pfr->rc.right - 1, -			ypos + vsPrint.lineHeight); - -		// When document line is wrapped over multiple display lines, find where -		// to start printing from to ensure a particular position is on the first -		// line of the page. -		if (visibleLine == 0) { -			int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc); -			for (int iwl = 0; iwl < ll.lines - 1; iwl++) { -				if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { -					visibleLine = -iwl; -				} -			} - -			if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { -				visibleLine = -(ll.lines - 1); -			} -		} - -		if (draw && lineNumberWidth && -			(ypos + vsPrint.lineHeight <= pfr->rc.bottom) && -			(visibleLine >= 0)) { -			char number[100]; -			sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1); -			PRectangle rcNumber = rcLine; -			rcNumber.right = rcNumber.left + lineNumberWidth; -			// Right justify -			rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( -				vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast<int>(strlen(number))); -			surface->FlushCachedState(); -			surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, -				static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number, static_cast<int>(strlen(number)), -				vsPrint.styles[STYLE_LINENUMBER].fore, -				vsPrint.styles[STYLE_LINENUMBER].back); -		} - -		// Draw the line -		surface->FlushCachedState(); - -		for (int iwl = 0; iwl < ll.lines; iwl++) { -			if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) { -				if (visibleLine >= 0) { -					if (draw) { -						rcLine.top = static_cast<XYPOSITION>(ypos); -						rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight); -						DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl, model); -					} -					ypos += vsPrint.lineHeight; -				} -				visibleLine++; -				if (iwl == ll.lines - 1) -					nPrintPos = model.pdoc->LineStart(lineDoc + 1); -				else -					nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl); -			} -		} - -		++lineDoc; -	} - -	// Clear cache so measurements are not used for screen -	posCache.Clear(); - -	return nPrintPos; -} -  Editor::Editor() {  	ctrlID = 0; diff --git a/src/Editor.h b/src/Editor.h index fd368df39..53da90906 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -14,17 +14,6 @@ namespace Scintilla {  /**   */ -class Caret { -public: -	bool active; -	bool on; -	int period; - -	Caret(); -}; - -/** - */  class Timer {  public:  	bool ticking; @@ -160,136 +149,6 @@ struct WrapPending {  	}  }; -struct PrintParameters { -	int magnification; -	int colourMode; -	WrapMode wrapState; -	PrintParameters(); -}; - -/** -* EditModel holds the state that needs to be seen by EditView. -*/ -class EditModel { -	// Private so EditModel objects can not be copied -	EditModel(const EditModel &); -	EditModel &operator=(const EditModel &); - -public: -	bool inOverstrike; -	int xOffset;		///< Horizontal scrolled amount in pixels -	bool trackLineWidth; - -	SpecialRepresentations reprs; -	Caret caret; -	SelectionPosition posDrag; -	Position braces[2]; -	int bracesMatchStyle; -	int highlightGuideColumn; -	Selection sel; -	bool primarySelection; - -	int foldFlags; -	ContractionState cs; - -	// Hotspot support -	Range hotspot; - -	// Wrapping support -	int wrapWidth; - -	Document *pdoc; - -	EditModel(); -	~EditModel(); - -	virtual int TopLineOfMain() const = 0; -	virtual Point GetVisibleOriginInMain() const = 0; -	virtual int LinesOnScreen() const = 0; -	virtual Range GetHotSpotRange() const = 0; -}; - -/** -* MarginView draws the margins. -*/ -class MarginView { -public: -	// Highlight current folding block -	HighlightDelimiter highlightDelimiter; -	Surface *pixmapSelMargin; -	Surface *pixmapSelPattern; -	Surface *pixmapSelPatternOffset1; - -	MarginView(); - -	void DropGraphics(bool freeObjects); -	void AllocateGraphics(const ViewStyle &vsDraw); -	void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); -	void PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, -		const EditModel &model, const ViewStyle &vs); -}; - -/** -* EditView draws the main text area. -*/ -class EditView { -public: -	PrintParameters printParameters; - -	bool hideSelection; -	bool drawOverstrikeCaret; - -	/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to -	* the screen. This avoids flashing but is about 30% slower. */ -	bool bufferedDraw; -	/** In twoPhaseDraw mode, drawing is performed in two phases, first the background -	* and then the foreground. This avoids chopping off characters that overlap the next run. */ -	bool twoPhaseDraw; - -	int lineWidthMaxSeen; -	bool additionalCaretsBlink; -	bool additionalCaretsVisible; - -	Surface *pixmapLine; -	Surface *pixmapIndentGuide; -	Surface *pixmapIndentGuideHighlight; - -	LineLayoutCache llc; -	PositionCache posCache; - -	EditView(); - -	void DropGraphics(bool freeObjects); -	void AllocateGraphics(const ViewStyle &vsDraw); -	void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); - -	LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model); -	void LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, -		const EditModel &model, int width = LineLayout::wrapWidthInfinite); - -	Point LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs); -	SelectionPosition SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, -		const EditModel &model, const ViewStyle &vs); -	SelectionPosition SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs); -	int DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs); -	int StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs); - -	void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); -	void DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, -		int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, -		ColourOptional background, const EditModel &model); -	void DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, -		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model); -	void DrawCarets(Surface *surface, const ViewStyle &vsDraw, int line, int xStart, -		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const; -	void DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart, -		PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model); -	void PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient, -		const EditModel &model, const ViewStyle &vsDraw); -	long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, -		const EditModel &model, const ViewStyle &vs); -}; -  /**   */  class Editor : public EditModel, public DocWatcher { diff --git a/src/MarginView.cxx b/src/MarginView.cxx new file mode 100644 index 000000000..efe84ecb5 --- /dev/null +++ b/src/MarginView.cxx @@ -0,0 +1,532 @@ +// Scintilla source code edit control +/** @file MarginView.cxx + ** Defines the appearance of the editor margin. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <vector> +#include <map> +#include <algorithm> +#include <memory> + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { +	if (st.multipleStyles) { +		for (size_t iStyle = 0; iStyle<st.length; iStyle++) { +			if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) +				return false; +		} +	} else { +		if (!vs.ValidStyle(styleOffset + st.style)) +			return false; +	} +	return true; +} + +static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, +	const char *text, const unsigned char *styles, size_t len) { +	int width = 0; +	size_t start = 0; +	while (start < len) { +		size_t style = styles[start]; +		size_t endSegment = start; +		while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style)) +			endSegment++; +		FontAlias fontText = vs.styles[style + styleOffset].font; +		width += static_cast<int>(surface->WidthText(fontText, text + start, +			static_cast<int>(endSegment - start + 1))); +		start = endSegment + 1; +	} +	return width; +} + +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { +	int widthMax = 0; +	size_t start = 0; +	while (start < st.length) { +		size_t lenLine = st.LineLength(start); +		int widthSubLine; +		if (st.multipleStyles) { +			widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); +		} else { +			FontAlias fontText = vs.styles[styleOffset + st.style].font; +			widthSubLine = static_cast<int>(surface->WidthText(fontText, +				st.text + start, static_cast<int>(lenLine))); +		} +		if (widthSubLine > widthMax) +			widthMax = widthSubLine; +		start += lenLine + 1; +	} +	return widthMax; +} + +static void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) { +	FontAlias fontText = style.font; +	surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length), +		style.fore, style.back); +} + +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, +	const StyledText &st, size_t start, size_t length) { + +	if (st.multipleStyles) { +		int x = static_cast<int>(rcText.left); +		size_t i = 0; +		while (i < length) { +			size_t end = i; +			size_t style = st.styles[i + start]; +			while (end < length - 1 && st.styles[start + end + 1] == style) +				end++; +			style += styleOffset; +			FontAlias fontText = vs.styles[style].font; +			const int width = static_cast<int>(surface->WidthText(fontText, +				st.text + start + i, static_cast<int>(end - i + 1))); +			PRectangle rcSegment = rcText; +			rcSegment.left = static_cast<XYPOSITION>(x); +			rcSegment.right = static_cast<XYPOSITION>(x + width + 1); +			DrawTextInStyle(surface, rcSegment, vs.styles[style], rcText.top + vs.maxAscent, +				st.text + start + i, end - i + 1); +			x += width; +			i = end + 1; +		} +	} else { +		const size_t style = st.style + styleOffset; +		DrawTextInStyle(surface, rcText, vs.styles[style], rcText.top + vs.maxAscent, +			st.text + start, length); +	} +} + +void DrawWrapMarker(Surface *surface, PRectangle rcPlace, +	bool isEndMarker, ColourDesired wrapColour) { +	surface->PenColour(wrapColour); + +	enum { xa = 1 }; // gap before start +	int w = static_cast<int>(rcPlace.right - rcPlace.left) - xa - 1; + +	bool xStraight = isEndMarker;  // x-mirrored symbol for start marker + +	int x0 = static_cast<int>(xStraight ? rcPlace.left : rcPlace.right - 1); +	int y0 = static_cast<int>(rcPlace.top); + +	int dy = static_cast<int>(rcPlace.bottom - rcPlace.top) / 5; +	int y = static_cast<int>(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, 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); +} + +MarginView::MarginView() { +	pixmapSelMargin = 0; +	pixmapSelPattern = 0; +	pixmapSelPatternOffset1 = 0; +} + +void MarginView::DropGraphics(bool freeObjects) { +	if (freeObjects) { +		delete pixmapSelMargin; +		pixmapSelMargin = 0; +		delete pixmapSelPattern; +		pixmapSelPattern = 0; +		delete pixmapSelPatternOffset1; +		pixmapSelPatternOffset1 = 0; +	} else { +		if (pixmapSelMargin) +			pixmapSelMargin->Release(); +		if (pixmapSelPattern) +			pixmapSelPattern->Release(); +		if (pixmapSelPatternOffset1) +			pixmapSelPatternOffset1->Release(); +	} +} + +void MarginView::AllocateGraphics(const ViewStyle &vsDraw) { +	if (!pixmapSelMargin) +		pixmapSelMargin = Surface::Allocate(vsDraw.technology); +	if (!pixmapSelPattern) +		pixmapSelPattern = Surface::Allocate(vsDraw.technology); +	if (!pixmapSelPatternOffset1) +		pixmapSelPatternOffset1 = Surface::Allocate(vsDraw.technology); +} + +void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { +	if (!pixmapSelPattern->Initialised()) { +		const int patternSize = 8; +		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid); +		pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid); +		// This complex procedure is to reproduce the checkerboard dithered pattern used by windows +		// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half +		// way between the chrome colour and the chrome highlight colour making a nice transition +		// between the window chrome and the content area. And it works in low colour depths. +		PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize); + +		// Initialize default colours based on the chrome colour scheme.  Typically the highlight is white. +		ColourDesired colourFMFill = vsDraw.selbar; +		ColourDesired colourFMStripes = vsDraw.selbarlight; + +		if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) { +			// User has chosen an unusual chrome colour scheme so just use the highlight edge colour. +			// (Typically, the highlight colour is white.) +			colourFMFill = vsDraw.selbarlight; +		} + +		if (vsDraw.foldmarginColour.isSet) { +			// override default fold margin colour +			colourFMFill = vsDraw.foldmarginColour; +		} +		if (vsDraw.foldmarginHighlightColour.isSet) { +			// override default fold margin highlight colour +			colourFMStripes = vsDraw.foldmarginHighlightColour; +		} + +		pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); +		pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes); +		for (int y = 0; y < patternSize; y++) { +			for (int x = y % 2; x < patternSize; x += 2) { +				PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1); +				pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes); +				pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill); +			} +		} +	} +} + +static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) { +	if (vs.markers[markerCheck].markType == SC_MARK_EMPTY) +		return markerDefault; +	return markerCheck; +} + +void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, +	const EditModel &model, const ViewStyle &vs) { + +	PRectangle rcSelMargin = rcMargin; +	rcSelMargin.right = rcMargin.left; +	if (rcSelMargin.bottom < rc.bottom) +		rcSelMargin.bottom = rc.bottom; + +	Point ptOrigin = model.GetVisibleOriginInMain(); +	FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font; +	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { +		if (vs.ms[margin].width > 0) { + +			rcSelMargin.left = rcSelMargin.right; +			rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; + +			if (vs.ms[margin].style != SC_MARGIN_NUMBER) { +				if (vs.ms[margin].mask & SC_MASK_FOLDERS) { +					// Required because of special way brush is created for selection margin +					// Ensure patterns line up when scrolling with separate margin view +					// by choosing correctly aligned variant. +					bool invertPhase = static_cast<int>(ptOrigin.y) & 1; +					surface->FillRectangle(rcSelMargin, +						invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1); +				} else { +					ColourDesired colour; +					switch (vs.ms[margin].style) { +					case SC_MARGIN_BACK: +						colour = vs.styles[STYLE_DEFAULT].back; +						break; +					case SC_MARGIN_FORE: +						colour = vs.styles[STYLE_DEFAULT].fore; +						break; +					default: +						colour = vs.styles[STYLE_LINENUMBER].back; +						break; +					} +					surface->FillRectangle(rcSelMargin, colour); +				} +			} else { +				surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back); +			} + +			const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight; +			int visibleLine = model.TopLineOfMain() + lineStartPaint; +			int yposScreen = lineStartPaint * vs.lineHeight - static_cast<int>(ptOrigin.y); +			// Work out whether the top line is whitespace located after a +			// lessening of fold level which implies a 'fold tail' but which should not +			// be displayed until the last of a sequence of whitespace. +			bool needWhiteClosure = false; +			if (vs.ms[margin].mask & SC_MASK_FOLDERS) { +				int level = model.pdoc->GetLevel(model.cs.DocFromDisplay(visibleLine)); +				if (level & SC_FOLDLEVELWHITEFLAG) { +					int lineBack = model.cs.DocFromDisplay(visibleLine); +					int levelPrev = level; +					while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { +						lineBack--; +						levelPrev = model.pdoc->GetLevel(lineBack); +					} +					if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { +						if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) +							needWhiteClosure = true; +					} +				} +				if (highlightDelimiter.isEnabled) { +					int lastLine = model.cs.DocFromDisplay(topLine + model.LinesOnScreen()) + 1; +					model.pdoc->GetHighlightDelimiters(highlightDelimiter, model.pdoc->LineFromPosition(model.sel.MainCaret()), lastLine); +				} +			} + +			// Old code does not know about new markers needed to distinguish all cases +			const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, +				SC_MARKNUM_FOLDEROPEN, vs); +			const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, +				SC_MARKNUM_FOLDER, vs); + +			while ((visibleLine < model.cs.LinesDisplayed()) && yposScreen < rc.bottom) { + +				PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed()); +				const int lineDoc = model.cs.DocFromDisplay(visibleLine); +				PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); +				const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc); +				const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc); + +				int marks = model.pdoc->GetMark(lineDoc); +				if (!firstSubLine) +					marks = 0; + +				bool headWithTail = false; + +				if (vs.ms[margin].mask & SC_MASK_FOLDERS) { +					// Decide which fold indicator should be displayed +					const int level = model.pdoc->GetLevel(lineDoc); +					const int levelNext = model.pdoc->GetLevel(lineDoc + 1); +					const int levelNum = level & SC_FOLDLEVELNUMBERMASK; +					const int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; +					if (level & SC_FOLDLEVELHEADERFLAG) { +						if (firstSubLine) { +							if (levelNum < levelNextNum) { +								if (model.cs.GetExpanded(lineDoc)) { +									if (levelNum == SC_FOLDLEVELBASE) +										marks |= 1 << SC_MARKNUM_FOLDEROPEN; +									else +										marks |= 1 << folderOpenMid; +								} else { +									if (levelNum == SC_FOLDLEVELBASE) +										marks |= 1 << SC_MARKNUM_FOLDER; +									else +										marks |= 1 << folderEnd; +								} +							} else if (levelNum > SC_FOLDLEVELBASE) { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +							} +						} else { +							if (levelNum < levelNextNum) { +								if (model.cs.GetExpanded(lineDoc)) { +									marks |= 1 << SC_MARKNUM_FOLDERSUB; +								} else if (levelNum > SC_FOLDLEVELBASE) { +									marks |= 1 << SC_MARKNUM_FOLDERSUB; +								} +							} else if (levelNum > SC_FOLDLEVELBASE) { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +							} +						} +						needWhiteClosure = false; +						const int firstFollowupLine = model.cs.DocFromDisplay(model.cs.DisplayFromDoc(lineDoc + 1)); +						const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine); +						const int secondFollowupLineLevelNum = model.pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; +						if (!model.cs.GetExpanded(lineDoc)) { +							if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && +								(levelNum > secondFollowupLineLevelNum)) +								needWhiteClosure = true; + +							if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) +								headWithTail = true; +						} +					} else if (level & SC_FOLDLEVELWHITEFLAG) { +						if (needWhiteClosure) { +							if (levelNext & SC_FOLDLEVELWHITEFLAG) { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +							} else if (levelNextNum > SC_FOLDLEVELBASE) { +								marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; +								needWhiteClosure = false; +							} else { +								marks |= 1 << SC_MARKNUM_FOLDERTAIL; +								needWhiteClosure = false; +							} +						} else if (levelNum > SC_FOLDLEVELBASE) { +							if (levelNextNum < levelNum) { +								if (levelNextNum > SC_FOLDLEVELBASE) { +									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; +								} else { +									marks |= 1 << SC_MARKNUM_FOLDERTAIL; +								} +							} else { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +							} +						} +					} else if (levelNum > SC_FOLDLEVELBASE) { +						if (levelNextNum < levelNum) { +							needWhiteClosure = false; +							if (levelNext & SC_FOLDLEVELWHITEFLAG) { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +								needWhiteClosure = true; +							} else if (lastSubLine) { +								if (levelNextNum > SC_FOLDLEVELBASE) { +									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; +								} else { +									marks |= 1 << SC_MARKNUM_FOLDERTAIL; +								} +							} else { +								marks |= 1 << SC_MARKNUM_FOLDERSUB; +							} +						} else { +							marks |= 1 << SC_MARKNUM_FOLDERSUB; +						} +					} +				} + +				marks &= vs.ms[margin].mask; + +				PRectangle rcMarker = rcSelMargin; +				rcMarker.top = static_cast<XYPOSITION>(yposScreen); +				rcMarker.bottom = static_cast<XYPOSITION>(yposScreen + vs.lineHeight); +				if (vs.ms[margin].style == SC_MARGIN_NUMBER) { +					if (firstSubLine) { +						char number[100] = ""; +						if (lineDoc >= 0) +							sprintf(number, "%d", lineDoc + 1); +						if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) { +							if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { +								int lev = model.pdoc->GetLevel(lineDoc); +								sprintf(number, "%c%c %03X %03X", +									(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', +									(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', +									lev & SC_FOLDLEVELNUMBERMASK, +									lev >> 16 +									); +							} else { +								int state = model.pdoc->GetLineState(lineDoc); +								sprintf(number, "%0X", state); +							} +						} +						PRectangle rcNumber = rcMarker; +						// Right justify +						XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast<int>(strlen(number))); +						XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding; +						rcNumber.left = xpos; +						DrawTextInStyle(surface, rcNumber, vs.styles[STYLE_LINENUMBER], +							rcNumber.top + vs.maxAscent, number, strlen(number)); +					} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { +						PRectangle rcWrapMarker = rcMarker; +						rcWrapMarker.right -= 3; +						rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; +						DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); +					} +				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { +					if (firstSubLine) { +						const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc); +						if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { +							surface->FillRectangle(rcMarker, +								vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); +							if (vs.ms[margin].style == SC_MARGIN_RTEXT) { +								int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); +								rcMarker.left = rcMarker.right - width - 3; +							} +							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, +								stMargin, 0, stMargin.length); +						} +					} +				} + +				if (marks) { +					for (int markBit = 0; (markBit < 32) && marks; markBit++) { +						if (marks & 1) { +							LineMarker::typeOfFold tFold = LineMarker::undefined; +							if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { +								if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { +									tFold = LineMarker::body; +								} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { +									if (firstSubLine) { +										tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; +									} else { +										if (model.cs.GetExpanded(lineDoc) || headWithTail) { +											tFold = LineMarker::body; +										} else { +											tFold = LineMarker::undefined; +										} +									} +								} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { +									tFold = LineMarker::tail; +								} +							} +							vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style); +						} +						marks >>= 1; +					} +				} + +				visibleLine++; +				yposScreen += vs.lineHeight; +			} +		} +	} + +	PRectangle rcBlankMargin = rcMargin; +	rcBlankMargin.left = rcSelMargin.right; +	surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back); +} diff --git a/src/MarginView.h b/src/MarginView.h new file mode 100644 index 000000000..8c401ae4a --- /dev/null +++ b/src/MarginView.h @@ -0,0 +1,47 @@ +// Scintilla source code edit control +/** @file MarginView.h + ** Defines the appearance of the editor margin. + **/ +// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef MARGINVIEW_H +#define MARGINVIEW_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st); + +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, +	const StyledText &st, size_t start, size_t length); +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st); + +void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); + +/** +* MarginView draws the margins. +*/ +class MarginView { +public: +	Surface *pixmapSelMargin; +	Surface *pixmapSelPattern; +	Surface *pixmapSelPatternOffset1; +	// Highlight current folding block +	HighlightDelimiter highlightDelimiter; + +	MarginView(); + +	void DropGraphics(bool freeObjects); +	void AllocateGraphics(const ViewStyle &vsDraw); +	void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); +	void PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, +		const EditModel &model, const ViewStyle &vs); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index d42dfc7ff..48ec46808 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -50,6 +50,9 @@  #include "Document.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "AutoComplete.h"  #include "ScintillaBase.h" diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 2635b84e4..38e85a7a8 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -70,6 +70,9 @@  #include "UniConversion.h"  #include "Selection.h"  #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h"  #include "Editor.h"  #include "AutoComplete.h" diff --git a/win32/deps.mak b/win32/deps.mak index 8580b27c0..b92e30545 100644 --- a/win32/deps.mak +++ b/win32/deps.mak @@ -1,23 +1,25 @@  CheckD2D.o: CheckD2D.cxx -PlatWin.o: PlatWin.cxx ../include/Platform.h ../src/UniConversion.h \ - ../src/XPM.h ../src/FontQuality.h +PlatWin.o: PlatWin.cxx ../include/Platform.h ../lexlib/StringCopy.h \ + ../src/XPM.h ../src/UniConversion.h ../src/FontQuality.h  ScintillaWin.o: ScintillaWin.cxx ../include/Platform.h \ - ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \ - ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ - ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ - ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ - ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ - ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \ - ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \ - ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h + ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \ + ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ + ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \ + ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ + ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ + ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \ + ../src/CaseConvert.h ../src/UniConversion.h ../src/Selection.h \ + ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \ + ../src/EditView.h ../src/Editor.h ../src/AutoComplete.h \ + ../src/ScintillaBase.h PlatWin.h  AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \ - ../lexlib/CharacterSet.h ../src/AutoComplete.h ../include/Scintilla.h + ../include/Scintilla.h ../lexlib/CharacterSet.h ../src/AutoComplete.h  CallTip.o: ../src/CallTip.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/CallTip.h -CaseConvert.o: ../src/CaseConvert.cxx ../src/CaseConvert.h \ - ../src/UniConversion.h ../src/UnicodeFromUTF8.h -CaseFolder.o: ../src/CaseFolder.cxx ../src/CaseConvert.h \ - ../src/UniConversion.h ../src/CaseFolder.h + ../include/Scintilla.h ../lexlib/StringCopy.h ../src/CallTip.h +CaseConvert.o: ../src/CaseConvert.cxx ../lexlib/StringCopy.h \ + ../src/CaseConvert.h ../src/UniConversion.h ../src/UnicodeFromUTF8.h +CaseFolder.o: ../src/CaseFolder.cxx ../src/CaseFolder.h \ + ../src/CaseConvert.h ../src/UniConversion.h  Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \   ../src/Catalogue.h @@ -32,37 +34,65 @@ Decoration.o: ../src/Decoration.cxx ../include/Platform.h \   ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \   ../src/RunStyles.h ../src/Decoration.h  Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \ - ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \ + ../include/Scintilla.h ../lexlib/CharacterSet.h ../src/SplitVector.h \ + ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \ + ../src/PerLine.h ../src/CharClassify.h ../src/Decoration.h \   ../src/CaseFolder.h ../src/Document.h ../src/RESearch.h \   ../src/UniConversion.h +EditModel.o: ../src/EditModel.cxx ../include/Platform.h \ + ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \ + ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ + ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \ + ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \ + ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ + ../src/CaseFolder.h ../src/Document.h ../src/UniConversion.h \ + ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h  Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ - ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ - ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \ - ../src/UniConversion.h ../src/Selection.h ../src/PositionCache.h \ - ../src/Editor.h + ../include/Scintilla.h ../lexlib/StringCopy.h ../src/SplitVector.h \ + ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ + ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \ + ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \ + ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \ + ../src/Document.h ../src/UniConversion.h ../src/Selection.h \ + ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \ + ../src/EditView.h ../src/Editor.h +EditView.o: ../src/EditView.cxx ../include/Platform.h ../include/ILexer.h \ + ../include/Scintilla.h ../lexlib/StringCopy.h ../src/SplitVector.h \ + ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ + ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \ + ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \ + ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \ + ../src/Document.h ../src/UniConversion.h ../src/Selection.h \ + ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \ + ../src/EditView.h  ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \   ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \   ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h  Indicator.o: ../src/Indicator.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/XPM.h ../src/Indicator.h + ../include/Scintilla.h ../src/Indicator.h ../src/XPM.h  KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \   ../src/KeyMap.h  LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h + ../include/Scintilla.h ../lexlib/StringCopy.h ../src/XPM.h \ + ../src/LineMarker.h +MarginView.o: ../src/MarginView.cxx ../include/Platform.h \ + ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \ + ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ + ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \ + ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \ + ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ + ../src/CaseFolder.h ../src/Document.h ../src/UniConversion.h \ + ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h \ + ../src/MarginView.h ../src/EditView.h  PerLine.o: ../src/PerLine.cxx ../include/Platform.h \   ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \   ../src/CellBuffer.h ../src/PerLine.h  PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ - ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ - ../src/Decoration.h ../include/ILexer.h ../src/CaseFolder.h \ + ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \ + ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ + ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \ + ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \ + ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \   ../src/Document.h ../src/UniConversion.h ../src/Selection.h \   ../src/PositionCache.h  RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h @@ -74,10 +104,11 @@ ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \   ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \   ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \   ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \ - ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \ - ../src/Document.h ../src/Selection.h ../src/PositionCache.h \ - ../src/Editor.h ../src/ScintillaBase.h + ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ + ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \ + ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h \ + ../src/MarginView.h ../src/EditView.h ../src/Editor.h \ + ../src/AutoComplete.h ../src/ScintillaBase.h  Selection.o: ../src/Selection.cxx ../include/Platform.h \   ../include/Scintilla.h ../src/Selection.h  Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \ @@ -92,7 +123,7 @@ Accessor.o: ../lexlib/Accessor.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \   ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h  CharacterCategory.o: ../lexlib/CharacterCategory.cxx \ - ../lexlib/CharacterCategory.h + ../lexlib/StringCopy.h ../lexlib/CharacterCategory.h  CharacterSet.o: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h  LexerBase.o: ../lexlib/LexerBase.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ @@ -114,7 +145,8 @@ LexerSimple.o: ../lexlib/LexerSimple.cxx ../include/ILexer.h \  PropSetSimple.o: ../lexlib/PropSetSimple.cxx ../lexlib/PropSetSimple.h  StyleContext.o: ../lexlib/StyleContext.cxx ../include/ILexer.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h -WordList.o: ../lexlib/WordList.cxx ../lexlib/WordList.h +WordList.o: ../lexlib/WordList.cxx ../lexlib/StringCopy.h \ + ../lexlib/WordList.h  LexA68k.o: ../lexers/LexA68k.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ @@ -218,6 +250,14 @@ LexD.o: ../lexers/LexD.cxx ../include/ILexer.h ../include/Scintilla.h \   ../include/SciLexer.h ../lexlib/WordList.h ../lexlib/LexAccessor.h \   ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \   ../lexlib/LexerModule.h ../lexlib/OptionSet.h +LexDMAP.o: ../lexers/LexDMAP.cxx ../include/ILexer.h \ + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \ + ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ + ../lexlib/CharacterSet.h ../lexlib/LexerModule.h +LexDMIS.o: ../lexers/LexDMIS.cxx ../include/ILexer.h \ + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \ + ../lexlib/LexAccessor.h ../lexlib/StyleContext.h \ + ../lexlib/CharacterSet.h ../lexlib/LexerModule.h  LexECL.o: ../lexers/LexECL.cxx ../include/ILexer.h ../include/Scintilla.h \   ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ @@ -258,12 +298,13 @@ LexHaskell.o: ../lexers/LexHaskell.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \   ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \   ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \ - ../lexlib/LexerModule.h ../lexlib/OptionSet.h \ - ../lexlib/CharacterCategory.h + ../lexlib/CharacterCategory.h ../lexlib/LexerModule.h \ + ../lexlib/OptionSet.h  LexHTML.o: ../lexers/LexHTML.cxx ../include/ILexer.h \ - ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \ - ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ - ../lexlib/CharacterSet.h ../lexlib/LexerModule.h + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/StringCopy.h \ + ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ + ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \ + ../lexlib/LexerModule.h  LexInno.o: ../lexers/LexInno.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ @@ -272,6 +313,10 @@ LexKix.o: ../lexers/LexKix.cxx ../include/ILexer.h ../include/Scintilla.h \   ../include/SciLexer.h ../lexlib/WordList.h ../lexlib/LexAccessor.h \   ../lexlib/Accessor.h ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \   ../lexlib/LexerModule.h +LexKVIrc.o: ../lexers/LexKVIrc.cxx ../include/ILexer.h \ + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \ + ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ + ../lexlib/CharacterSet.h ../lexlib/LexerModule.h  LexLaTeX.o: ../lexers/LexLaTeX.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \   ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ @@ -402,6 +447,11 @@ LexRuby.o: ../lexers/LexRuby.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \   ../lexlib/CharacterSet.h ../lexlib/LexerModule.h +LexRust.o: ../lexers/LexRust.cxx ../include/ILexer.h \ + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ + ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ + ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \ + ../lexlib/LexerModule.h ../lexlib/OptionSet.h  LexScriptol.o: ../lexers/LexScriptol.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ @@ -477,7 +527,8 @@ LexVHDL.o: ../lexers/LexVHDL.cxx ../include/ILexer.h \  LexVisualProlog.o: ../lexers/LexVisualProlog.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ - ../lexlib/CharacterSet.h ../lexlib/LexerModule.h ../lexlib/OptionSet.h + ../lexlib/CharacterSet.h ../lexlib/CharacterCategory.h \ + ../lexlib/LexerModule.h ../lexlib/OptionSet.h  LexYAML.o: ../lexers/LexYAML.cxx ../include/ILexer.h \   ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \   ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ diff --git a/win32/makefile b/win32/makefile index d4a39d278..299c3c32c 100644 --- a/win32/makefile +++ b/win32/makefile @@ -63,10 +63,13 @@ BASEOBJS = \  	ContractionState.o \  	Decoration.o \  	Document.o \ +	EditModel.o \  	Editor.o \ +	EditView.o \  	KeyMap.o \  	Indicator.o \  	LineMarker.o \ +	MarginView.o \  	PerLine.o \  	PlatWin.o \  	PositionCache.o \ @@ -117,7 +120,7 @@ ScintillaBaseL.o: ScintillaBase.cxx Platform.h \   KeyMap.h Indicator.h XPM.h LineMarker.h \   Style.h ViewStyle.h AutoComplete.h \   CharClassify.h Decoration.h Document.h \ - Selection.h PositionCache.h Editor.h \ + Selection.h PositionCache.h EditModel.h Editor.h EditView.h \   ScintillaBase.h LexAccessor.h Accessor.h \   LexerModule.h Catalogue.h CaseFolder.h @@ -128,7 +131,7 @@ ScintillaWinL.o: ScintillaWin.cxx Platform.h \   XPM.h LineMarker.h Style.h AutoComplete.h \   ViewStyle.h CharClassify.h Decoration.h \   Document.h Selection.h PositionCache.h \ - Editor.h ScintillaBase.h UniConversion.h \ + EditModel.h Editor.h EditView.h ScintillaBase.h UniConversion.h \   LexAccessor.h Accessor.h \   LexerModule.h Catalogue.h CaseConvert.h \   CaseFolder.h @@ -140,7 +143,7 @@ ScintillaWinS.o: ScintillaWin.cxx Platform.h \   XPM.h LineMarker.h Style.h AutoComplete.h \   ViewStyle.h CharClassify.h Decoration.h \   Document.h Selection.h PositionCache.h \ - Editor.h ScintillaBase.h UniConversion.h \ + EditModel.h Editor.h EditView.h ScintillaBase.h UniConversion.h \   CaseConvert.h CaseFolder.h  ScintillaBaseL.o: diff --git a/win32/scintilla.mak b/win32/scintilla.mak index eaa407d3b..2febf86f3 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -67,10 +67,13 @@ SHAREDOBJS=\  	$(DIR_O)\ContractionState.obj \  	$(DIR_O)\Decoration.obj \  	$(DIR_O)\Document.obj \ +	$(DIR_O)\EditModel.obj \  	$(DIR_O)\Editor.obj \ +	$(DIR_O)\EditView.obj \  	$(DIR_O)\Indicator.obj \  	$(DIR_O)\KeyMap.obj \  	$(DIR_O)\LineMarker.obj \ +	$(DIR_O)\MarginView.obj \  	$(DIR_O)\PerLine.obj \  	$(DIR_O)\PlatWin.obj \  	$(DIR_O)\PositionCache.obj \ @@ -238,58 +241,209 @@ $(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx  # Dependencies  # All lexers depend on this set of headers -LEX_HEADERS= ..\include\ILexer.h ..\include\Scintilla.h ..\include\SciLexer.h \ - ..\lexlib\Accessor.h ..\lexlib\CharacterSet.h ..\lexlib\LexAccessor.h \ - ..\lexlib\LexerModule.h ..\lexlib\StyleContext.h - -$(DIR_O)\Accessor.obj: ../lexlib/Accessor.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ -  ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h -$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \ -  ../lexlib/CharacterSet.h ../src/AutoComplete.h ../include/Scintilla.h -$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/CallTip.h -$(DIR_O)\CaseConvert.obj: ../src/CaseConvert.cxx ../src/CaseConvert.h \ -  ../src/UniConversion.h ../src/UnicodeFromUTF8.h -$(DIR_O)\CaseFolder.obj: ../src/CaseFolder.cxx ../src/CaseConvert.h \ -  ../src/UniConversion.h ../src/CaseFolder.h -$(DIR_O)\Catalogue.obj: ../src/Catalogue.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \ -  ../src/Catalogue.h -$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/CellBuffer.h ../src/UniConversion.h -$(DIR_O)\CharacterCategory.obj: ../lexlib/CharacterCategory.cxx \ -  ../lexlib/CharacterCategory.h -$(DIR_O)\CharacterSet.obj: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h -$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h -$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \ -  ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ -  ../src/ContractionState.h -$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h ../src/Decoration.h -$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \ -  ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \ -  ../src/CaseFolder.h ../src/Document.h ../src/RESearch.h \ -  ../src/UniConversion.h -$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ -  ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ -  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ -  ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \ -  ../src/UniConversion.h ../src/Selection.h ../src/PositionCache.h \ -  ../src/Editor.h -$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \ -  ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h -$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/XPM.h ../src/Indicator.h -$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \ -  ../src/KeyMap.h +LEX_HEADERS= \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/StyleContext.h \ +	../lexlib/CharacterSet.h \ +	../lexlib/LexerModule.h \ +	../lexlib/OptionSet.h \ +	../lexlib/SparseState.h \ +	../lexlib/SubStyles.h + +$(DIR_O)\Accessor.obj: \ +	../lexlib/Accessor.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/PropSetSimple.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h +$(DIR_O)\AutoComplete.obj: \ +	../src/AutoComplete.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../lexlib/CharacterSet.h \ +	../src/AutoComplete.h +$(DIR_O)\CallTip.obj: \ +	../src/CallTip.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/CallTip.h +$(DIR_O)\CaseConvert.obj: \ +	../src/CaseConvert.cxx \ +	../lexlib/StringCopy.h \ +	../src/CaseConvert.h \ +	../src/UniConversion.h \ +	../src/UnicodeFromUTF8.h +$(DIR_O)\CaseFolder.obj: \ +	../src/CaseFolder.cxx \ +	../src/CaseFolder.h \ +	../src/CaseConvert.h \ +	../src/UniConversion.h +$(DIR_O)\Catalogue.obj: \ +	../src/Catalogue.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/LexerModule.h \ +	../src/Catalogue.h +$(DIR_O)\CellBuffer.obj: \ +	../src/CellBuffer.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/CellBuffer.h \ +	../src/UniConversion.h +$(DIR_O)\CharacterCategory.obj: \ +	../lexlib/CharacterCategory.cxx \ +	../lexlib/StringCopy.h \ +	../lexlib/CharacterCategory.h +$(DIR_O)\CharacterSet.obj: \ +	../lexlib/CharacterSet.cxx \ +	../lexlib/CharacterSet.h +$(DIR_O)\CharClassify.obj: \ +	../src/CharClassify.cxx \ +	../src/CharClassify.h +$(DIR_O)\ContractionState.obj: \ +	../src/ContractionState.cxx \ +	../include/Platform.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h +$(DIR_O)\Decoration.obj: \ +	../src/Decoration.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/Decoration.h +$(DIR_O)\Document.obj: \ +	../src/Document.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/CharacterSet.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/CellBuffer.h \ +	../src/PerLine.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/RESearch.h \ +	../src/UniConversion.h +$(DIR_O)\EditModel.obj: \ +	../src/EditModel.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h +$(DIR_O)\Editor.obj: \ +	../src/Editor.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h +$(DIR_O)\EditView.obj: \ +	../src/EditView.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h +$(DIR_O)\ExternalLexer.obj: \ +	../src/ExternalLexer.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/LexerModule.h \ +	../src/Catalogue.h \ +	../src/ExternalLexer.h +$(DIR_O)\Indicator.obj: \ +	../src/Indicator.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/Indicator.h \ +	../src/XPM.h +$(DIR_O)\KeyMap.obj: \ +	../src/KeyMap.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/KeyMap.h  #++Autogenerated -- run scripts/LexGen.py to regenerate  #**\n\($(DIR_O)\\\*.obj: ..\\lexers\\\*.cxx $(LEX_HEADERS)\n\n\) @@ -485,98 +639,334 @@ $(DIR_O)\LexYAML.obj: ..\lexers\LexYAML.cxx $(LEX_HEADERS)  #--Autogenerated -- end of automatically generated section -$(DIR_O)\LexerBase.obj: ../lexlib/LexerBase.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ -  ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ -  ../lexlib/LexerModule.h ../lexlib/LexerBase.h -$(DIR_O)\LexerModule.obj: ../lexlib/LexerModule.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ -  ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ -  ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h -$(DIR_O)\LexerNoExceptions.obj: ../lexlib/LexerNoExceptions.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ -  ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ -  ../lexlib/LexerModule.h ../lexlib/LexerBase.h \ -  ../lexlib/LexerNoExceptions.h -$(DIR_O)\LexerSimple.obj: ../lexlib/LexerSimple.cxx ../include/ILexer.h \ -  ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \ -  ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \ -  ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h -$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h -$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/CellBuffer.h ../src/PerLine.h -$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h ../src/UniConversion.h \ -  ../src/XPM.h ../src/FontQuality.h -$(DIR_O)\PositionCache.obj: ../src/PositionCache.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ -  ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ -  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ -  ../src/Decoration.h ../include/ILexer.h ../src/CaseFolder.h \ -  ../src/Document.h ../src/UniConversion.h ../src/Selection.h \ -  ../src/PositionCache.h -$(DIR_O)\PropSetSimple.obj: ../lexlib/PropSetSimple.cxx ../lexlib/PropSetSimple.h -$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h -$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h -$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \ -  ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ -  ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \ -  ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ -  ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \ -  ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \ -  ../src/Document.h ../src/Selection.h ../src/PositionCache.h \ -  ../src/Editor.h ../src/ScintillaBase.h -$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \ -  ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ -  ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \ -  ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ -  ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \ -  ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \ -  ../src/Document.h ../src/Selection.h ../src/PositionCache.h \ -  ../src/Editor.h ../src/ScintillaBase.h -$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \ -  ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ -  ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ -  ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ -  ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ -  ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \ -  ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \ -  ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h -$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \ -  ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ -  ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ -  ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ -  ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ -  ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \ -  ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \ -  ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h -$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \ -  ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \ -  ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ -  ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ -  ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ -  ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \ -  ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \ -  ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \ -  ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h -$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/Selection.h -$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \ -  ../src/Style.h -$(DIR_O)\StyleContext.obj: ../lexlib/StyleContext.cxx ../include/ILexer.h \ -  ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h -$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h -$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \ -  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ -  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ -  ../src/Style.h ../src/ViewStyle.h -$(DIR_O)\WordList.obj: ../lexlib/WordList.cxx ../lexlib/WordList.h -$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h +$(DIR_O)\LexerBase.obj: \ +	../lexlib/LexerBase.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/PropSetSimple.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/LexerModule.h \ +	../lexlib/LexerBase.h +$(DIR_O)\LexerModule.obj: \ +	../lexlib/LexerModule.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/PropSetSimple.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/LexerModule.h \ +	../lexlib/LexerBase.h \ +	../lexlib/LexerSimple.h +$(DIR_O)\LexerNoExceptions.obj: \ +	../lexlib/LexerNoExceptions.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/PropSetSimple.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/LexerModule.h \ +	../lexlib/LexerBase.h \ +	../lexlib/LexerNoExceptions.h +$(DIR_O)\LexerSimple.obj: \ +	../lexlib/LexerSimple.cxx \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../include/SciLexer.h \ +	../lexlib/PropSetSimple.h \ +	../lexlib/WordList.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/LexerModule.h \ +	../lexlib/LexerBase.h \ +	../lexlib/LexerSimple.h +$(DIR_O)\LineMarker.obj: \ +	../src/LineMarker.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/XPM.h \ +	../src/LineMarker.h +$(DIR_O)\MarginView.obj: \ +	../src/MarginView.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h +$(DIR_O)\PerLine.obj: \ +	../src/PerLine.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/CellBuffer.h \ +	../src/PerLine.h +$(DIR_O)\PlatWin.obj: \ +	PlatWin.cxx \ +	../include/Platform.h \ +	../lexlib/StringCopy.h \ +	../src/XPM.h \ +	../src/UniConversion.h \ +	../src/FontQuality.h +$(DIR_O)\PositionCache.obj: \ +	../src/PositionCache.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h +$(DIR_O)\PropSetSimple.obj: \ +	../lexlib/PropSetSimple.cxx \ +	../lexlib/PropSetSimple.h +$(DIR_O)\RESearch.obj: \ +	../src/RESearch.cxx \ +	../src/CharClassify.h \ +	../src/RESearch.h +$(DIR_O)\RunStyles.obj: \ +	../src/RunStyles.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h +$(DIR_O)\ScintillaBase.obj: \ +	../src/ScintillaBase.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/PropSetSimple.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/CallTip.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h \ +	../src/AutoComplete.h \ +	../src/ScintillaBase.h +$(DIR_O)\ScintillaBaseL.obj: \ +	../src/ScintillaBase.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/PropSetSimple.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/CallTip.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h \ +	../src/AutoComplete.h \ +	../src/ScintillaBase.h +$(DIR_O)\ScintillaWin.obj: \ +	ScintillaWin.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/CallTip.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/CaseConvert.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h \ +	../src/AutoComplete.h \ +	../src/ScintillaBase.h \ +	PlatWin.h +$(DIR_O)\ScintillaWinL.obj: \ +	ScintillaWin.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/CallTip.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/CaseConvert.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h \ +	../src/AutoComplete.h \ +	../src/ScintillaBase.h \ +	PlatWin.h +$(DIR_O)\ScintillaWinS.obj: \ +	ScintillaWin.cxx \ +	../include/Platform.h \ +	../include/ILexer.h \ +	../include/Scintilla.h \ +	../lexlib/StringCopy.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/ContractionState.h \ +	../src/CellBuffer.h \ +	../src/CallTip.h \ +	../src/KeyMap.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h \ +	../src/CharClassify.h \ +	../src/Decoration.h \ +	../src/CaseFolder.h \ +	../src/Document.h \ +	../src/CaseConvert.h \ +	../src/UniConversion.h \ +	../src/Selection.h \ +	../src/PositionCache.h \ +	../src/EditModel.h \ +	../src/MarginView.h \ +	../src/EditView.h \ +	../src/Editor.h \ +	../src/AutoComplete.h \ +	../src/ScintillaBase.h \ +	PlatWin.h +$(DIR_O)\Selection.obj: \ +	../src/Selection.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/Selection.h +$(DIR_O)\Style.obj: \ +	../src/Style.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/Style.h +$(DIR_O)\StyleContext.obj: \ +	../lexlib/StyleContext.cxx \ +	../include/ILexer.h \ +	../lexlib/LexAccessor.h \ +	../lexlib/Accessor.h \ +	../lexlib/StyleContext.h +$(DIR_O)\UniConversion.obj: \ +	../src/UniConversion.cxx \ +	../src/UniConversion.h +$(DIR_O)\ViewStyle.obj: \ +	../src/ViewStyle.cxx \ +	../include/Platform.h \ +	../include/Scintilla.h \ +	../src/SplitVector.h \ +	../src/Partitioning.h \ +	../src/RunStyles.h \ +	../src/Indicator.h \ +	../src/XPM.h \ +	../src/LineMarker.h \ +	../src/Style.h \ +	../src/ViewStyle.h +$(DIR_O)\WordList.obj: \ +	../lexlib/WordList.cxx \ +	../lexlib/StringCopy.h \ +	../lexlib/WordList.h +$(DIR_O)\XPM.obj: \ +	../src/XPM.cxx \ +	../include/Platform.h \ +	../src/XPM.h | 
