1 // SciTE - Scintilla based Text Editor
2 /** @file StyleWriter.cxx
3  ** Simple buffered interface to the text and styles of a document held by Scintilla.
4  **/
5 // Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7 
8 #include <cstdint>
9 
10 #include <string>
11 #include <string_view>
12 #include <chrono>
13 
14 #include "ScintillaTypes.h"
15 #include "ScintillaCall.h"
16 
17 #include "GUI.h"
18 #include "StyleWriter.h"
19 
20 namespace SA = Scintilla::API;
21 
TextReader(SA::ScintillaCall & sc_)22 TextReader::TextReader(SA::ScintillaCall &sc_) noexcept :
23 	startPos(extremePosition),
24 	endPos(0),
25 	codePage(0),
26 	sc(sc_),
27 	lenDoc(-1) {
28 	buf[0] = 0;
29 }
30 
InternalIsLeadByte(char ch) const31 bool TextReader::InternalIsLeadByte(char ch) const {
32 	return GUI::IsDBCSLeadByte(codePage, ch);
33 }
34 
Fill(SA::Position position)35 void TextReader::Fill(SA::Position position) {
36 	if (lenDoc == -1)
37 		lenDoc = sc.Length();
38 	startPos = position - slopSize;
39 	if (startPos + bufferSize > lenDoc)
40 		startPos = lenDoc - bufferSize;
41 	if (startPos < 0)
42 		startPos = 0;
43 	endPos = startPos + bufferSize;
44 	if (endPos > lenDoc)
45 		endPos = lenDoc;
46 	sc.SetTarget(SA::Range(startPos, endPos));
47 	sc.TargetText(buf);
48 }
49 
Match(SA::Position pos,const char * s)50 bool TextReader::Match(SA::Position pos, const char *s) {
51 	for (int i=0; *s; i++) {
52 		if (*s != SafeGetCharAt(pos+i))
53 			return false;
54 		s++;
55 	}
56 	return true;
57 }
58 
StyleAt(SA::Position position)59 int TextReader::StyleAt(SA::Position position) {
60 	return sc.UnsignedStyleAt(position);
61 }
62 
GetLine(SA::Position position)63 SA::Line TextReader::GetLine(SA::Position position) {
64 	return sc.LineFromPosition(position);
65 }
66 
LineStart(SA::Line line)67 SA::Position TextReader::LineStart(SA::Line line) {
68 	return sc.LineStart(line);
69 }
70 
LevelAt(SA::Line line)71 SA::FoldLevel TextReader::LevelAt(SA::Line line) {
72 	return sc.FoldLevel(line);
73 }
74 
Length()75 SA::Position TextReader::Length() {
76 	if (lenDoc == -1)
77 		lenDoc = sc.Length();
78 	return lenDoc;
79 }
80 
GetLineState(SA::Line line)81 int TextReader::GetLineState(SA::Line line) {
82 	return sc.LineState(line);
83 }
84 
StyleWriter(SA::ScintillaCall & sc_)85 StyleWriter::StyleWriter(SA::ScintillaCall &sc_) noexcept :
86 	TextReader(sc_),
87 	validLen(0),
88 	startSeg(0) {
89 	styleBuf[0] = 0;
90 }
91 
SetLineState(SA::Line line,int state)92 void StyleWriter::SetLineState(SA::Line line, int state) {
93 	sc.SetLineState(line, state);
94 }
95 
StartAt(SA::Position start,char chMask)96 void StyleWriter::StartAt(SA::Position start, char chMask) {
97 	sc.StartStyling(start, chMask);
98 }
99 
StartSegment(SA::Position pos)100 void StyleWriter::StartSegment(SA::Position pos) noexcept {
101 	startSeg = pos;
102 }
103 
ColourTo(SA::Position pos,int chAttr)104 void StyleWriter::ColourTo(SA::Position pos, int chAttr) {
105 	// Only perform styling if non empty range
106 	if (pos != startSeg - 1) {
107 		if (validLen + (pos - startSeg + 1) >= bufferSize)
108 			Flush();
109 		if (validLen + (pos - startSeg + 1) >= bufferSize) {
110 			// Too big for buffer so send directly
111 			sc.SetStyling(pos - startSeg + 1, chAttr);
112 		} else {
113 			for (SA::Position i = startSeg; i <= pos; i++) {
114 				styleBuf[validLen++] = static_cast<char>(chAttr);
115 			}
116 		}
117 	}
118 	startSeg = pos+1;
119 }
120 
SetLevel(SA::Line line,SA::FoldLevel level)121 void StyleWriter::SetLevel(SA::Line line, SA::FoldLevel level) {
122 	sc.SetFoldLevel(line, level);
123 }
124 
Flush()125 void StyleWriter::Flush() {
126 	startPos = extremePosition;
127 	lenDoc = -1;
128 	if (validLen > 0) {
129 		sc.SetStylingEx(validLen, styleBuf);
130 		validLen = 0;
131 	}
132 }
133