diff options
| -rw-r--r-- | include/WindowAccessor.h | 69 | ||||
| -rw-r--r-- | src/DocumentAccessor.cxx | 166 | ||||
| -rw-r--r-- | src/DocumentAccessor.h | 71 | ||||
| -rw-r--r-- | src/WindowAccessor.cxx | 165 | 
4 files changed, 471 insertions, 0 deletions
| diff --git a/include/WindowAccessor.h b/include/WindowAccessor.h new file mode 100644 index 000000000..a24ef9fa3 --- /dev/null +++ b/include/WindowAccessor.h @@ -0,0 +1,69 @@ +// WindowAccessor.h - implementation of BufferAccess and StylingAccess on a Scintilla rapid easy access to contents of a Scintilla +// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +class WindowAccessor : public Accessor { +protected: +	// bufferSize is a trade off between time taken to copy the characters and SendMessage overhead +	// slopSize positions the buffer before the desired position in case there is some backtracking +	enum {bufferSize=4000, slopSize=bufferSize/8}; +	char buf[bufferSize+1]; +	WindowID id; +	PropSet &props; +	int startPos; +	int endPos; +	int lenDoc; +	int codePage;	 + +	char styleBuf[bufferSize]; +	int validLen; +	char chFlags; +	char chWhile; +	unsigned int startSeg; + +	bool InternalIsLeadByte(char ch); +	void Fill(int position); +public: +	WindowAccessor(WindowID id_, PropSet &props_) :  +			id(id_), props(props_), startPos(0x7FFFFFFF), endPos(0),  +			lenDoc(-1), codePage(0), validLen(0), chFlags(0) { +	} +	void SetCodePage(int codePage_) { codePage = codePage_; } +	char operator[](int position) { +		if (position < startPos || position >= endPos) { +			Fill(position); +		} +		return buf[position - startPos]; +	} +	char SafeGetCharAt(int position, char chDefault=' ') { +		// Safe version of operator[], returning a defined value for invalid position  +		if (position < startPos || position >= endPos) { +			Fill(position); +			if (position < startPos || position >= endPos) { +				// Position is outside range of document  +				return chDefault; +			} +		} +		return buf[position - startPos]; +	} +	bool IsLeadByte(char ch) { +		return codePage && InternalIsLeadByte(ch); +	} +	char StyleAt(int position); +	int GetLine(int position); +	int LineStart(int line); +	int LevelAt(int line); +	int Length(); +	void Flush(); +	int GetLineState(int line); +	int SetLineState(int line, int state); +	PropSet &GetPropSet() { return props; } + +	void StartAt(unsigned int start, char chMask=31); +	void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }; +	unsigned int GetStartSegment() { return startSeg; } +	void StartSegment(unsigned int pos); +	void ColourTo(unsigned int pos, int chAttr); +	void SetLevel(int line, int level); +	int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0); +}; diff --git a/src/DocumentAccessor.cxx b/src/DocumentAccessor.cxx new file mode 100644 index 000000000..a69f4a445 --- /dev/null +++ b/src/DocumentAccessor.cxx @@ -0,0 +1,166 @@ +// SciTE - Scintilla based Text Editor +// Accessor.cxx - rapid easy access to contents of a Scintilla +// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <ctype.h>  +#include <stdio.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "SVector.h" +#include "Accessor.h" +#include "DocumentAccessor.h" +#include "CellBuffer.h" +#include "Scintilla.h" +#include "Document.h" + +bool DocumentAccessor::InternalIsLeadByte(char ch) { +#if PLAT_GTK +	// TODO: support DBCS under GTK+ +	return false; +#elif PLAT_WIN  +	return IsDBCSLeadByteEx(codePage, ch); +#elif PLAT_WX  +	return false; +#endif  +} + +void DocumentAccessor::Fill(int position) { +	if (lenDoc == -1) +		lenDoc = pdoc->Length(); +	startPos = position - slopSize; +	if (startPos + bufferSize > lenDoc) +		startPos = lenDoc - bufferSize; +	if (startPos < 0) +		startPos = 0; +	endPos = startPos + bufferSize; +	if (endPos > lenDoc) +		endPos = lenDoc; + +	pdoc->GetCharRange(buf, startPos, endPos-startPos); +	buf[endPos-startPos] = '\0'; +} + +char DocumentAccessor::StyleAt(int position) { +	return pdoc->StyleAt(position); +} + +int DocumentAccessor::GetLine(int position) { +	return pdoc->LineFromPosition(position); +} + +int DocumentAccessor::LineStart(int line) { +	return pdoc->LineStart(line); +} + +int DocumentAccessor::LevelAt(int line) { +	return pdoc->GetLevel(line); +} + +int DocumentAccessor::Length() {  +	if (lenDoc == -1)  +		lenDoc = pdoc->Length(); +	return lenDoc;  +} + +int DocumentAccessor::GetLineState(int line) { +	return pdoc->GetLineState(line); +} + +int DocumentAccessor::SetLineState(int line, int state) { +	return pdoc->SetLineState(line, state); +} + +void DocumentAccessor::StartAt(unsigned int start, char chMask) { +	pdoc->StartStyling(start, chMask); +} + +void DocumentAccessor::StartSegment(unsigned int pos) { +	startSeg = pos; +} + +void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) { +	// Only perform styling if non empty range +	if (pos != startSeg - 1) { +		if (pos < startSeg) { +			Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos); +		} + +		if (validLen + (pos - startSeg + 1) >= bufferSize) +			Flush(); +		if (validLen + (pos - startSeg + 1) >= bufferSize) { +			// Too big for buffer so send directly +			pdoc->SetStyleFor(pos - startSeg + 1, chAttr); +		} else { +			if (chAttr != chWhile) +				chFlags = 0; +			chAttr |= chFlags; +			for (unsigned int i = startSeg; i <= pos; i++) { +				styleBuf[validLen++] = static_cast<char>(chAttr); +			} +		} +	} +	startSeg = pos+1; +} + +void DocumentAccessor::SetLevel(int line, int level) { +	pdoc->SetLevel(line, level); +} + +void DocumentAccessor::Flush() { +	startPos = 0x7FFFFFFF; +	lenDoc = -1; +	if (validLen > 0) { +		pdoc->SetStyles(validLen, styleBuf); +		validLen = 0; +	} +} + +int DocumentAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { +	int end = Length(); +	int spaceFlags = 0; +	 +	// Determines the indentation level of the current line and also checks for consistent  +	// indentation compared to the previous line. +	// Indentation is judged consistent when the indentation whitespace of each line lines  +	// the same or the indentation of one line is a prefix of the other. +	 +	int pos = LineStart(line); +	char ch = (*this)[pos]; +	int indent = 0; +	bool inPrevPrefix = line > 0; +	int posPrev = inPrevPrefix ? LineStart(line-1) : 0; +	while ((ch == ' ' || ch == '\t') && (pos < end)) { +		if (inPrevPrefix) { +			char chPrev = (*this)[posPrev++]; +			if (chPrev == ' ' || chPrev == '\t') { +				if (chPrev != ch) +					spaceFlags |= wsInconsistent; +			} else { +				inPrevPrefix = false; +			} +		} +		if (ch == ' ') { +			spaceFlags |= wsSpace; +			indent++; +		} else {	// Tab +			spaceFlags |= wsTab; +			if (spaceFlags & wsSpace) +				spaceFlags |= wsSpaceTab; +			indent = (indent / 8 + 1) * 8; +		} +		ch = (*this)[++pos]; +	} +	 +	*flags = spaceFlags; +	indent += SC_FOLDLEVELBASE; +	// if completely empty line or the start of a comment... +	if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) ) +		return indent | SC_FOLDLEVELWHITEFLAG; +	else +		return indent; +} + diff --git a/src/DocumentAccessor.h b/src/DocumentAccessor.h new file mode 100644 index 000000000..f0577b355 --- /dev/null +++ b/src/DocumentAccessor.h @@ -0,0 +1,71 @@ +// DocumentAccessor.h - implementation of BufferAccess and StylingAccess on a Scintilla rapid easy access to contents of a Scintilla +// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +class Document; + +class DocumentAccessor : public Accessor { +protected: +	// bufferSize is a trade off between time taken to copy the characters and SendMessage overhead +	// slopSize positions the buffer before the desired position in case there is some backtracking +	enum {bufferSize=4000, slopSize=bufferSize/8}; +	char buf[bufferSize+1]; +	Document *pdoc; +	PropSet &props; +	int startPos; +	int endPos; +	int lenDoc; +	int codePage;	 + +	char styleBuf[bufferSize]; +	int validLen; +	char chFlags; +	char chWhile; +	unsigned int startSeg; + +	bool InternalIsLeadByte(char ch); +	void Fill(int position); +public: +	DocumentAccessor(Document *pdoc_, PropSet &props_) :  +			pdoc(pdoc_), props(props_), startPos(0x7FFFFFFF), endPos(0),  +			lenDoc(-1), codePage(0), validLen(0), chFlags(0) { +	} +	void SetCodePage(int codePage_) { codePage = codePage_; } +	char operator[](int position) { +		if (position < startPos || position >= endPos) { +			Fill(position); +		} +		return buf[position - startPos]; +	} +	char SafeGetCharAt(int position, char chDefault=' ') { +		// Safe version of operator[], returning a defined value for invalid position  +		if (position < startPos || position >= endPos) { +			Fill(position); +			if (position < startPos || position >= endPos) { +				// Position is outside range of document  +				return chDefault; +			} +		} +		return buf[position - startPos]; +	} +	bool IsLeadByte(char ch) { +		return codePage && InternalIsLeadByte(ch); +	} +	char StyleAt(int position); +	int GetLine(int position); +	int LineStart(int line); +	int LevelAt(int line); +	int Length(); +	void Flush(); +	int GetLineState(int line); +	int SetLineState(int line, int state); +	PropSet &GetPropSet() { return props; } + +	void StartAt(unsigned int start, char chMask=31); +	void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }; +	unsigned int GetStartSegment() { return startSeg; } +	void StartSegment(unsigned int pos); +	void ColourTo(unsigned int pos, int chAttr); +	void SetLevel(int line, int level); +	int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0); +}; diff --git a/src/WindowAccessor.cxx b/src/WindowAccessor.cxx new file mode 100644 index 000000000..0c33acd88 --- /dev/null +++ b/src/WindowAccessor.cxx @@ -0,0 +1,165 @@ +// SciTE - Scintilla based Text Editor +// Accessor.cxx - rapid easy access to contents of a Scintilla +// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <ctype.h>  +#include <stdio.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "WindowAccessor.h" +#include "Scintilla.h" + +bool WindowAccessor::InternalIsLeadByte(char ch) { +#if PLAT_GTK +	// TODO: support DBCS under GTK+ +	return false; +#elif PLAT_WIN  +	return IsDBCSLeadByteEx(codePage, ch); +#elif PLAT_WX  +	return false; +#endif  +} + +void WindowAccessor::Fill(int position) { +	if (lenDoc == -1) +		lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0); +	startPos = position - slopSize; +	if (startPos + bufferSize > lenDoc) +		startPos = lenDoc - bufferSize; +	if (startPos < 0) +		startPos = 0; +	endPos = startPos + bufferSize; +	if (endPos > lenDoc) +		endPos = lenDoc; + +	TEXTRANGE tr = {{startPos, endPos}, buf}; +	Platform::SendScintilla(id, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr)); +} + +char WindowAccessor::StyleAt(int position) { +	return static_cast<char>(Platform::SendScintilla( +		id, SCI_GETSTYLEAT, position, 0)); +} + +int WindowAccessor::GetLine(int position) { +	return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0); +} + +int WindowAccessor::LineStart(int line) { +	return Platform::SendScintilla(id, EM_LINEINDEX, line, 0); +} + +int WindowAccessor::LevelAt(int line) { +	return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0); +} + +int WindowAccessor::Length() {  +	if (lenDoc == -1)  +		lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0); +	return lenDoc;  +} + +int WindowAccessor::GetLineState(int line) { +	return Platform::SendScintilla(id, SCI_GETLINESTATE, line); +} + +int WindowAccessor::SetLineState(int line, int state) { +	return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state); +} + +void WindowAccessor::StartAt(unsigned int start, char chMask) { +	Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask); +} + +void WindowAccessor::StartSegment(unsigned int pos) { +	startSeg = pos; +} + +void WindowAccessor::ColourTo(unsigned int pos, int chAttr) { +	// Only perform styling if non empty range +	if (pos != startSeg - 1) { +		if (pos < startSeg) { +			Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos); +		} + +		if (validLen + (pos - startSeg + 1) >= bufferSize) +			Flush(); +		if (validLen + (pos - startSeg + 1) >= bufferSize) { +			// Too big for buffer so send directly +			Platform::SendScintilla(id, SCI_SETSTYLING, pos - startSeg + 1, chAttr); +		} else { +			if (chAttr != chWhile) +				chFlags = 0; +			chAttr |= chFlags; +			for (unsigned int i = startSeg; i <= pos; i++) { +				styleBuf[validLen++] = chAttr; +			} +		} +	} +	startSeg = pos+1; +} + +void WindowAccessor::SetLevel(int line, int level) { +	Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level); +} + +void WindowAccessor::Flush() { +	startPos = 0x7FFFFFFF; +	lenDoc = -1; +	if (validLen > 0) { +		Platform::SendScintilla(id, SCI_SETSTYLINGEX, validLen,  +			reinterpret_cast<LPARAM>(styleBuf)); +		validLen = 0; +	} +} + +int WindowAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { +	int end = Length(); +	int spaceFlags = 0; +	 +	// Determines the indentation level of the current line and also checks for consistent  +	// indentation compared to the previous line. +	// Indentation is judged consistent when the indentation whitespace of each line lines  +	// the same or the indentation of one line is a prefix of the other. +	 +	int pos = LineStart(line); +	char ch = (*this)[pos]; +	int indent = 0; +	bool inPrevPrefix = line > 0; +	int posPrev = inPrevPrefix ? LineStart(line-1) : 0; +	while ((ch == ' ' || ch == '\t') && (pos < end)) { +		if (inPrevPrefix) { +			char chPrev = (*this)[posPrev++]; +			if (chPrev == ' ' || chPrev == '\t') { +				if (chPrev != ch) +					spaceFlags |= wsInconsistent; +			} else { +				inPrevPrefix = false; +			} +		} +		if (ch == ' ') { +			spaceFlags |= wsSpace; +			indent++; +		} else {	// Tab +			spaceFlags |= wsTab; +			if (spaceFlags & wsSpace) +				spaceFlags |= wsSpaceTab; +			indent = (indent / 8 + 1) * 8; +		} +		ch = (*this)[++pos]; +	} +	 +	*flags = spaceFlags; +	indent += SC_FOLDLEVELBASE; +	// if completely empty line or the start of a comment... +	if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) ) +		return indent | SC_FOLDLEVELWHITEFLAG; +	else +		return indent; +} + | 
