xref: /MusicPlayer2/scintilla/src/Decoration.cxx (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
1*8af74909SZhong Yang /** @file Decoration.cxx
2*8af74909SZhong Yang  ** Visual elements added over text.
3*8af74909SZhong Yang  **/
4*8af74909SZhong Yang // Copyright 1998-2007 by Neil Hodgson <[email protected]>
5*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
6*8af74909SZhong Yang 
7*8af74909SZhong Yang #include <cstddef>
8*8af74909SZhong Yang #include <cstdlib>
9*8af74909SZhong Yang #include <cstring>
10*8af74909SZhong Yang #include <cstdio>
11*8af74909SZhong Yang #include <cstdarg>
12*8af74909SZhong Yang 
13*8af74909SZhong Yang #include <stdexcept>
14*8af74909SZhong Yang #include <string_view>
15*8af74909SZhong Yang #include <vector>
16*8af74909SZhong Yang #include <algorithm>
17*8af74909SZhong Yang #include <memory>
18*8af74909SZhong Yang 
19*8af74909SZhong Yang #include "Platform.h"
20*8af74909SZhong Yang 
21*8af74909SZhong Yang #include "Scintilla.h"
22*8af74909SZhong Yang #include "Position.h"
23*8af74909SZhong Yang #include "SplitVector.h"
24*8af74909SZhong Yang #include "Partitioning.h"
25*8af74909SZhong Yang #include "RunStyles.h"
26*8af74909SZhong Yang #include "Decoration.h"
27*8af74909SZhong Yang 
28*8af74909SZhong Yang using namespace Scintilla;
29*8af74909SZhong Yang 
30*8af74909SZhong Yang namespace {
31*8af74909SZhong Yang 
32*8af74909SZhong Yang template <typename POS>
33*8af74909SZhong Yang class Decoration : public IDecoration {
34*8af74909SZhong Yang 	int indicator;
35*8af74909SZhong Yang public:
36*8af74909SZhong Yang 	RunStyles<POS, int> rs;
37*8af74909SZhong Yang 
Decoration(int indicator_)38*8af74909SZhong Yang 	explicit Decoration(int indicator_) : indicator(indicator_) {
39*8af74909SZhong Yang 	}
~Decoration()40*8af74909SZhong Yang 	~Decoration() override {
41*8af74909SZhong Yang 	}
42*8af74909SZhong Yang 
Empty() const43*8af74909SZhong Yang 	bool Empty() const noexcept override {
44*8af74909SZhong Yang 		return (rs.Runs() == 1) && (rs.AllSameAs(0));
45*8af74909SZhong Yang 	}
Indicator() const46*8af74909SZhong Yang 	int Indicator() const noexcept override {
47*8af74909SZhong Yang 		return indicator;
48*8af74909SZhong Yang 	}
Length() const49*8af74909SZhong Yang 	Sci::Position Length() const noexcept override {
50*8af74909SZhong Yang 		return rs.Length();
51*8af74909SZhong Yang 	}
ValueAt(Sci::Position position) const52*8af74909SZhong Yang 	int ValueAt(Sci::Position position) const noexcept override {
53*8af74909SZhong Yang 		return rs.ValueAt(static_cast<POS>(position));
54*8af74909SZhong Yang 	}
StartRun(Sci::Position position) const55*8af74909SZhong Yang 	Sci::Position StartRun(Sci::Position position) const noexcept override {
56*8af74909SZhong Yang 		return rs.StartRun(static_cast<POS>(position));
57*8af74909SZhong Yang 	}
EndRun(Sci::Position position) const58*8af74909SZhong Yang 	Sci::Position EndRun(Sci::Position position) const noexcept override {
59*8af74909SZhong Yang 		return rs.EndRun(static_cast<POS>(position));
60*8af74909SZhong Yang 	}
SetValueAt(Sci::Position position,int value)61*8af74909SZhong Yang 	void SetValueAt(Sci::Position position, int value) override {
62*8af74909SZhong Yang 		rs.SetValueAt(static_cast<POS>(position), value);
63*8af74909SZhong Yang 	}
InsertSpace(Sci::Position position,Sci::Position insertLength)64*8af74909SZhong Yang 	void InsertSpace(Sci::Position position, Sci::Position insertLength) override {
65*8af74909SZhong Yang 		rs.InsertSpace(static_cast<POS>(position), static_cast<POS>(insertLength));
66*8af74909SZhong Yang 	}
Runs() const67*8af74909SZhong Yang 	Sci::Position Runs() const noexcept override {
68*8af74909SZhong Yang 		return rs.Runs();
69*8af74909SZhong Yang 	}
70*8af74909SZhong Yang };
71*8af74909SZhong Yang 
72*8af74909SZhong Yang template <typename POS>
73*8af74909SZhong Yang class DecorationList : public IDecorationList {
74*8af74909SZhong Yang 	int currentIndicator;
75*8af74909SZhong Yang 	int currentValue;
76*8af74909SZhong Yang 	Decoration<POS> *current;	// Cached so FillRange doesn't have to search for each call.
77*8af74909SZhong Yang 	Sci::Position lengthDocument;
78*8af74909SZhong Yang 	// Ordered by indicator
79*8af74909SZhong Yang 	std::vector<std::unique_ptr<Decoration<POS>>> decorationList;
80*8af74909SZhong Yang 	std::vector<const IDecoration*> decorationView;	// Read-only view of decorationList
81*8af74909SZhong Yang 	bool clickNotified;
82*8af74909SZhong Yang 
83*8af74909SZhong Yang 	Decoration<POS> *DecorationFromIndicator(int indicator) noexcept;
84*8af74909SZhong Yang 	Decoration<POS> *Create(int indicator, Sci::Position length);
85*8af74909SZhong Yang 	void Delete(int indicator);
86*8af74909SZhong Yang 	void DeleteAnyEmpty();
87*8af74909SZhong Yang 	void SetView();
88*8af74909SZhong Yang public:
89*8af74909SZhong Yang 
90*8af74909SZhong Yang 	DecorationList();
91*8af74909SZhong Yang 	~DecorationList() override;
92*8af74909SZhong Yang 
View() const93*8af74909SZhong Yang 	const std::vector<const IDecoration*> &View() const noexcept override {
94*8af74909SZhong Yang 		return decorationView;
95*8af74909SZhong Yang 	}
96*8af74909SZhong Yang 
97*8af74909SZhong Yang 	void SetCurrentIndicator(int indicator) override;
GetCurrentIndicator() const98*8af74909SZhong Yang 	int GetCurrentIndicator() const noexcept override { return currentIndicator; }
99*8af74909SZhong Yang 
100*8af74909SZhong Yang 	void SetCurrentValue(int value) override;
GetCurrentValue() const101*8af74909SZhong Yang 	int GetCurrentValue() const noexcept override { return currentValue; }
102*8af74909SZhong Yang 
103*8af74909SZhong Yang 	// Returns changed=true if some values may have changed
104*8af74909SZhong Yang 	FillResult<Sci::Position> FillRange(Sci::Position position, int value, Sci::Position fillLength) override;
105*8af74909SZhong Yang 
106*8af74909SZhong Yang 	void InsertSpace(Sci::Position position, Sci::Position insertLength) override;
107*8af74909SZhong Yang 	void DeleteRange(Sci::Position position, Sci::Position deleteLength) override;
108*8af74909SZhong Yang 
109*8af74909SZhong Yang 	void DeleteLexerDecorations() override;
110*8af74909SZhong Yang 
111*8af74909SZhong Yang 	int AllOnFor(Sci::Position position) const noexcept override;
112*8af74909SZhong Yang 	int ValueAt(int indicator, Sci::Position position) noexcept override;
113*8af74909SZhong Yang 	Sci::Position Start(int indicator, Sci::Position position) noexcept override;
114*8af74909SZhong Yang 	Sci::Position End(int indicator, Sci::Position position) noexcept override;
115*8af74909SZhong Yang 
ClickNotified() const116*8af74909SZhong Yang 	bool ClickNotified() const noexcept override {
117*8af74909SZhong Yang 		return clickNotified;
118*8af74909SZhong Yang 	}
SetClickNotified(bool notified)119*8af74909SZhong Yang 	void SetClickNotified(bool notified) noexcept override {
120*8af74909SZhong Yang 		clickNotified = notified;
121*8af74909SZhong Yang 	}
122*8af74909SZhong Yang };
123*8af74909SZhong Yang 
124*8af74909SZhong Yang template <typename POS>
DecorationList()125*8af74909SZhong Yang DecorationList<POS>::DecorationList() : currentIndicator(0), currentValue(1), current(nullptr),
126*8af74909SZhong Yang 	lengthDocument(0), clickNotified(false) {
127*8af74909SZhong Yang }
128*8af74909SZhong Yang 
129*8af74909SZhong Yang template <typename POS>
~DecorationList()130*8af74909SZhong Yang DecorationList<POS>::~DecorationList() {
131*8af74909SZhong Yang 	current = nullptr;
132*8af74909SZhong Yang }
133*8af74909SZhong Yang 
134*8af74909SZhong Yang template <typename POS>
DecorationFromIndicator(int indicator)135*8af74909SZhong Yang Decoration<POS> *DecorationList<POS>::DecorationFromIndicator(int indicator) noexcept {
136*8af74909SZhong Yang 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
137*8af74909SZhong Yang 		if (deco->Indicator() == indicator) {
138*8af74909SZhong Yang 			return deco.get();
139*8af74909SZhong Yang 		}
140*8af74909SZhong Yang 	}
141*8af74909SZhong Yang 	return nullptr;
142*8af74909SZhong Yang }
143*8af74909SZhong Yang 
144*8af74909SZhong Yang template <typename POS>
Create(int indicator,Sci::Position length)145*8af74909SZhong Yang Decoration<POS> *DecorationList<POS>::Create(int indicator, Sci::Position length) {
146*8af74909SZhong Yang 	currentIndicator = indicator;
147*8af74909SZhong Yang 	std::unique_ptr<Decoration<POS>> decoNew = std::make_unique<Decoration<POS>>(indicator);
148*8af74909SZhong Yang 	decoNew->rs.InsertSpace(0, static_cast<POS>(length));
149*8af74909SZhong Yang 
150*8af74909SZhong Yang 	typename std::vector<std::unique_ptr<Decoration<POS>>>::iterator it = std::lower_bound(
151*8af74909SZhong Yang 		decorationList.begin(), decorationList.end(), decoNew,
152*8af74909SZhong Yang 		[](const std::unique_ptr<Decoration<POS>> &a, const std::unique_ptr<Decoration<POS>> &b) noexcept {
153*8af74909SZhong Yang 		return a->Indicator() < b->Indicator();
154*8af74909SZhong Yang 	});
155*8af74909SZhong Yang 	typename std::vector<std::unique_ptr<Decoration<POS>>>::iterator itAdded =
156*8af74909SZhong Yang 		decorationList.insert(it, std::move(decoNew));
157*8af74909SZhong Yang 
158*8af74909SZhong Yang 	SetView();
159*8af74909SZhong Yang 
160*8af74909SZhong Yang 	return itAdded->get();
161*8af74909SZhong Yang }
162*8af74909SZhong Yang 
163*8af74909SZhong Yang template <typename POS>
Delete(int indicator)164*8af74909SZhong Yang void DecorationList<POS>::Delete(int indicator) {
165*8af74909SZhong Yang 	decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
166*8af74909SZhong Yang 		[indicator](const std::unique_ptr<Decoration<POS>> &deco) noexcept {
167*8af74909SZhong Yang 		return deco->Indicator() == indicator;
168*8af74909SZhong Yang 	}), decorationList.end());
169*8af74909SZhong Yang 	current = nullptr;
170*8af74909SZhong Yang 	SetView();
171*8af74909SZhong Yang }
172*8af74909SZhong Yang 
173*8af74909SZhong Yang template <typename POS>
SetCurrentIndicator(int indicator)174*8af74909SZhong Yang void DecorationList<POS>::SetCurrentIndicator(int indicator) {
175*8af74909SZhong Yang 	currentIndicator = indicator;
176*8af74909SZhong Yang 	current = DecorationFromIndicator(indicator);
177*8af74909SZhong Yang 	currentValue = 1;
178*8af74909SZhong Yang }
179*8af74909SZhong Yang 
180*8af74909SZhong Yang template <typename POS>
SetCurrentValue(int value)181*8af74909SZhong Yang void DecorationList<POS>::SetCurrentValue(int value) {
182*8af74909SZhong Yang 	currentValue = value ? value : 1;
183*8af74909SZhong Yang }
184*8af74909SZhong Yang 
185*8af74909SZhong Yang template <typename POS>
FillRange(Sci::Position position,int value,Sci::Position fillLength)186*8af74909SZhong Yang FillResult<Sci::Position> DecorationList<POS>::FillRange(Sci::Position position, int value, Sci::Position fillLength) {
187*8af74909SZhong Yang 	if (!current) {
188*8af74909SZhong Yang 		current = DecorationFromIndicator(currentIndicator);
189*8af74909SZhong Yang 		if (!current) {
190*8af74909SZhong Yang 			current = Create(currentIndicator, lengthDocument);
191*8af74909SZhong Yang 		}
192*8af74909SZhong Yang 	}
193*8af74909SZhong Yang 	// Converting result from POS to Sci::Position as callers not polymorphic.
194*8af74909SZhong Yang 	const FillResult<POS> frInPOS = current->rs.FillRange(static_cast<POS>(position), value, static_cast<POS>(fillLength));
195*8af74909SZhong Yang 	const FillResult<Sci::Position> fr { frInPOS.changed, frInPOS.position, frInPOS.fillLength };
196*8af74909SZhong Yang 		if (current->Empty()) {
197*8af74909SZhong Yang 		Delete(currentIndicator);
198*8af74909SZhong Yang 	}
199*8af74909SZhong Yang 	return fr;
200*8af74909SZhong Yang }
201*8af74909SZhong Yang 
202*8af74909SZhong Yang template <typename POS>
InsertSpace(Sci::Position position,Sci::Position insertLength)203*8af74909SZhong Yang void DecorationList<POS>::InsertSpace(Sci::Position position, Sci::Position insertLength) {
204*8af74909SZhong Yang 	const bool atEnd = position == lengthDocument;
205*8af74909SZhong Yang 	lengthDocument += insertLength;
206*8af74909SZhong Yang 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
207*8af74909SZhong Yang 		deco->rs.InsertSpace(static_cast<POS>(position), static_cast<POS>(insertLength));
208*8af74909SZhong Yang 		if (atEnd) {
209*8af74909SZhong Yang 			deco->rs.FillRange(static_cast<POS>(position), 0, static_cast<POS>(insertLength));
210*8af74909SZhong Yang 		}
211*8af74909SZhong Yang 	}
212*8af74909SZhong Yang }
213*8af74909SZhong Yang 
214*8af74909SZhong Yang template <typename POS>
DeleteRange(Sci::Position position,Sci::Position deleteLength)215*8af74909SZhong Yang void DecorationList<POS>::DeleteRange(Sci::Position position, Sci::Position deleteLength) {
216*8af74909SZhong Yang 	lengthDocument -= deleteLength;
217*8af74909SZhong Yang 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
218*8af74909SZhong Yang 		deco->rs.DeleteRange(static_cast<POS>(position), static_cast<POS>(deleteLength));
219*8af74909SZhong Yang 	}
220*8af74909SZhong Yang 	DeleteAnyEmpty();
221*8af74909SZhong Yang 	if (decorationList.size() != decorationView.size()) {
222*8af74909SZhong Yang 		// One or more empty decorations deleted so update view.
223*8af74909SZhong Yang 		current = nullptr;
224*8af74909SZhong Yang 		SetView();
225*8af74909SZhong Yang 	}
226*8af74909SZhong Yang }
227*8af74909SZhong Yang 
228*8af74909SZhong Yang template <typename POS>
DeleteLexerDecorations()229*8af74909SZhong Yang void DecorationList<POS>::DeleteLexerDecorations() {
230*8af74909SZhong Yang 	decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
231*8af74909SZhong Yang 		[](const std::unique_ptr<Decoration<POS>> &deco) noexcept {
232*8af74909SZhong Yang 		return deco->Indicator() < INDICATOR_CONTAINER ;
233*8af74909SZhong Yang 	}), decorationList.end());
234*8af74909SZhong Yang 	current = nullptr;
235*8af74909SZhong Yang 	SetView();
236*8af74909SZhong Yang }
237*8af74909SZhong Yang 
238*8af74909SZhong Yang template <typename POS>
DeleteAnyEmpty()239*8af74909SZhong Yang void DecorationList<POS>::DeleteAnyEmpty() {
240*8af74909SZhong Yang 	if (lengthDocument == 0) {
241*8af74909SZhong Yang 		decorationList.clear();
242*8af74909SZhong Yang 	} else {
243*8af74909SZhong Yang 		decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
244*8af74909SZhong Yang 			[](const std::unique_ptr<Decoration<POS>> &deco) noexcept {
245*8af74909SZhong Yang 			return deco->Empty();
246*8af74909SZhong Yang 		}), decorationList.end());
247*8af74909SZhong Yang 	}
248*8af74909SZhong Yang }
249*8af74909SZhong Yang 
250*8af74909SZhong Yang template <typename POS>
SetView()251*8af74909SZhong Yang void DecorationList<POS>::SetView() {
252*8af74909SZhong Yang 	decorationView.clear();
253*8af74909SZhong Yang 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
254*8af74909SZhong Yang 		decorationView.push_back(deco.get());
255*8af74909SZhong Yang 	}
256*8af74909SZhong Yang }
257*8af74909SZhong Yang 
258*8af74909SZhong Yang template <typename POS>
AllOnFor(Sci::Position position) const259*8af74909SZhong Yang int DecorationList<POS>::AllOnFor(Sci::Position position) const noexcept {
260*8af74909SZhong Yang 	int mask = 0;
261*8af74909SZhong Yang 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
262*8af74909SZhong Yang 		if (deco->rs.ValueAt(static_cast<POS>(position))) {
263*8af74909SZhong Yang 			if (deco->Indicator() < INDICATOR_IME) {
264*8af74909SZhong Yang 				mask |= 1 << deco->Indicator();
265*8af74909SZhong Yang 			}
266*8af74909SZhong Yang 		}
267*8af74909SZhong Yang 	}
268*8af74909SZhong Yang 	return mask;
269*8af74909SZhong Yang }
270*8af74909SZhong Yang 
271*8af74909SZhong Yang template <typename POS>
ValueAt(int indicator,Sci::Position position)272*8af74909SZhong Yang int DecorationList<POS>::ValueAt(int indicator, Sci::Position position) noexcept {
273*8af74909SZhong Yang 	const Decoration<POS> *deco = DecorationFromIndicator(indicator);
274*8af74909SZhong Yang 	if (deco) {
275*8af74909SZhong Yang 		return deco->rs.ValueAt(static_cast<POS>(position));
276*8af74909SZhong Yang 	}
277*8af74909SZhong Yang 	return 0;
278*8af74909SZhong Yang }
279*8af74909SZhong Yang 
280*8af74909SZhong Yang template <typename POS>
Start(int indicator,Sci::Position position)281*8af74909SZhong Yang Sci::Position DecorationList<POS>::Start(int indicator, Sci::Position position) noexcept {
282*8af74909SZhong Yang 	const Decoration<POS> *deco = DecorationFromIndicator(indicator);
283*8af74909SZhong Yang 	if (deco) {
284*8af74909SZhong Yang 		return deco->rs.StartRun(static_cast<POS>(position));
285*8af74909SZhong Yang 	}
286*8af74909SZhong Yang 	return 0;
287*8af74909SZhong Yang }
288*8af74909SZhong Yang 
289*8af74909SZhong Yang template <typename POS>
End(int indicator,Sci::Position position)290*8af74909SZhong Yang Sci::Position DecorationList<POS>::End(int indicator, Sci::Position position) noexcept {
291*8af74909SZhong Yang 	const Decoration<POS> *deco = DecorationFromIndicator(indicator);
292*8af74909SZhong Yang 	if (deco) {
293*8af74909SZhong Yang 		return deco->rs.EndRun(static_cast<POS>(position));
294*8af74909SZhong Yang 	}
295*8af74909SZhong Yang 	return 0;
296*8af74909SZhong Yang }
297*8af74909SZhong Yang 
298*8af74909SZhong Yang }
299*8af74909SZhong Yang 
300*8af74909SZhong Yang namespace Scintilla {
301*8af74909SZhong Yang 
DecorationCreate(bool largeDocument,int indicator)302*8af74909SZhong Yang std::unique_ptr<IDecoration> DecorationCreate(bool largeDocument, int indicator) {
303*8af74909SZhong Yang 	if (largeDocument)
304*8af74909SZhong Yang 		return std::make_unique<Decoration<Sci::Position>>(indicator);
305*8af74909SZhong Yang 	else
306*8af74909SZhong Yang 		return std::make_unique<Decoration<int>>(indicator);
307*8af74909SZhong Yang }
308*8af74909SZhong Yang 
DecorationListCreate(bool largeDocument)309*8af74909SZhong Yang std::unique_ptr<IDecorationList> DecorationListCreate(bool largeDocument) {
310*8af74909SZhong Yang 	if (largeDocument)
311*8af74909SZhong Yang 		return std::make_unique<DecorationList<Sci::Position>>();
312*8af74909SZhong Yang 	else
313*8af74909SZhong Yang 		return std::make_unique<DecorationList<int>>();
314*8af74909SZhong Yang }
315*8af74909SZhong Yang 
316*8af74909SZhong Yang }
317*8af74909SZhong Yang 
318