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