1 /** @file Decoration.cxx
2 ** Visual elements added over text.
4 // Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
5 // The License.txt file describes the conditions under which this software may be distributed.
20 #include "Scintilla.h"
22 #include "SplitVector.h"
23 #include "Partitioning.h"
24 #include "RunStyles.h"
25 #include "Decoration.h"
27 using namespace Scintilla
;
31 template <typename POS
>
32 class Decoration
: public IDecoration
{
35 RunStyles
<POS
, int> rs
;
37 explicit Decoration(int indicator_
) : indicator(indicator_
) {
39 ~Decoration() override
{
42 bool Empty() const override
{
43 return (rs
.Runs() == 1) && (rs
.AllSameAs(0));
45 int Indicator() const override
{
48 Sci::Position
Length() const override
{
51 int ValueAt(Sci::Position position
) const override
{
52 return rs
.ValueAt(static_cast<POS
>(position
));
54 Sci::Position
StartRun(Sci::Position position
) const override
{
55 return rs
.StartRun(static_cast<POS
>(position
));
57 Sci::Position
EndRun(Sci::Position position
) const override
{
58 return rs
.EndRun(static_cast<POS
>(position
));
60 void SetValueAt(Sci::Position position
, int value
) override
{
61 rs
.SetValueAt(static_cast<POS
>(position
), value
);
63 void InsertSpace(Sci::Position position
, Sci::Position insertLength
) override
{
64 rs
.InsertSpace(static_cast<POS
>(position
), static_cast<POS
>(insertLength
));
66 Sci::Position
Runs() const override
{
71 template <typename POS
>
72 class DecorationList
: public IDecorationList
{
75 Decoration
<POS
> *current
; // Cached so FillRange doesn't have to search for each call.
76 Sci::Position lengthDocument
;
77 // Ordered by indicator
78 std::vector
<std::unique_ptr
<Decoration
<POS
>>> decorationList
;
79 std::vector
<const IDecoration
*> decorationView
; // Read-only view of decorationList
82 Decoration
<POS
> *DecorationFromIndicator(int indicator
);
83 Decoration
<POS
> *Create(int indicator
, Sci::Position length
);
84 void Delete(int indicator
);
85 void DeleteAnyEmpty();
90 ~DecorationList() override
;
92 const std::vector
<const IDecoration
*> &View() const override
{
93 return decorationView
;
96 void SetCurrentIndicator(int indicator
) override
;
97 int GetCurrentIndicator() const override
{ return currentIndicator
; }
99 void SetCurrentValue(int value
) override
;
100 int GetCurrentValue() const override
{ return currentValue
; }
102 // Returns changed=true if some values may have changed
103 FillResult
<Sci::Position
> FillRange(Sci::Position position
, int value
, Sci::Position fillLength
) override
;
105 void InsertSpace(Sci::Position position
, Sci::Position insertLength
) override
;
106 void DeleteRange(Sci::Position position
, Sci::Position deleteLength
) override
;
108 void DeleteLexerDecorations() override
;
110 int AllOnFor(Sci::Position position
) const override
;
111 int ValueAt(int indicator
, Sci::Position position
) override
;
112 Sci::Position
Start(int indicator
, Sci::Position position
) override
;
113 Sci::Position
End(int indicator
, Sci::Position position
) override
;
115 bool ClickNotified() const override
{
116 return clickNotified
;
118 void SetClickNotified(bool notified
) override
{
119 clickNotified
= notified
;
123 template <typename POS
>
124 DecorationList
<POS
>::DecorationList() : currentIndicator(0), currentValue(1), current(nullptr),
125 lengthDocument(0), clickNotified(false) {
128 template <typename POS
>
129 DecorationList
<POS
>::~DecorationList() {
133 template <typename POS
>
134 Decoration
<POS
> *DecorationList
<POS
>::DecorationFromIndicator(int indicator
) {
135 for (const std::unique_ptr
<Decoration
<POS
>> &deco
: decorationList
) {
136 if (deco
->Indicator() == indicator
) {
143 template <typename POS
>
144 Decoration
<POS
> *DecorationList
<POS
>::Create(int indicator
, Sci::Position length
) {
145 currentIndicator
= indicator
;
146 std::unique_ptr
<Decoration
<POS
>> decoNew
= std::unique_ptr
<Decoration
<POS
>>(new Decoration
<POS
>(indicator
));
147 decoNew
->rs
.InsertSpace(0, static_cast<POS
>(length
));
149 typename
std::vector
<std::unique_ptr
<Decoration
<POS
>>>::iterator it
= std::lower_bound(
150 decorationList
.begin(), decorationList
.end(), decoNew
,
151 [](const std::unique_ptr
<Decoration
<POS
>> &a
, const std::unique_ptr
<Decoration
<POS
>> &b
) {
152 return a
->Indicator() < b
->Indicator();
154 typename
std::vector
<std::unique_ptr
<Decoration
<POS
>>>::iterator itAdded
=
155 decorationList
.insert(it
, std::move(decoNew
));
159 return itAdded
->get();
162 template <typename POS
>
163 void DecorationList
<POS
>::Delete(int indicator
) {
164 decorationList
.erase(std::remove_if(decorationList
.begin(), decorationList
.end(),
165 [indicator
](const std::unique_ptr
<Decoration
<POS
>> &deco
) {
166 return deco
->Indicator() == indicator
;
167 }), decorationList
.end());
172 template <typename POS
>
173 void DecorationList
<POS
>::SetCurrentIndicator(int indicator
) {
174 currentIndicator
= indicator
;
175 current
= DecorationFromIndicator(indicator
);
179 template <typename POS
>
180 void DecorationList
<POS
>::SetCurrentValue(int value
) {
181 currentValue
= value
? value
: 1;
184 template <typename POS
>
185 FillResult
<Sci::Position
> DecorationList
<POS
>::FillRange(Sci::Position position
, int value
, Sci::Position fillLength
) {
187 current
= DecorationFromIndicator(currentIndicator
);
189 current
= Create(currentIndicator
, lengthDocument
);
192 // Converting result from POS to Sci::Position as callers not polymorphic.
193 const FillResult
<POS
> frInPOS
= current
->rs
.FillRange(static_cast<POS
>(position
), value
, static_cast<POS
>(fillLength
));
194 const FillResult
<Sci::Position
> fr
{ frInPOS
.changed
, frInPOS
.position
, frInPOS
.fillLength
};
195 if (current
->Empty()) {
196 Delete(currentIndicator
);
201 template <typename POS
>
202 void DecorationList
<POS
>::InsertSpace(Sci::Position position
, Sci::Position insertLength
) {
203 const bool atEnd
= position
== lengthDocument
;
204 lengthDocument
+= insertLength
;
205 for (const std::unique_ptr
<Decoration
<POS
>> &deco
: decorationList
) {
206 deco
->rs
.InsertSpace(static_cast<POS
>(position
), static_cast<POS
>(insertLength
));
208 deco
->rs
.FillRange(static_cast<POS
>(position
), 0, static_cast<POS
>(insertLength
));
213 template <typename POS
>
214 void DecorationList
<POS
>::DeleteRange(Sci::Position position
, Sci::Position deleteLength
) {
215 lengthDocument
-= deleteLength
;
216 for (const std::unique_ptr
<Decoration
<POS
>> &deco
: decorationList
) {
217 deco
->rs
.DeleteRange(static_cast<POS
>(position
), static_cast<POS
>(deleteLength
));
220 if (decorationList
.size() != decorationView
.size()) {
221 // One or more empty decorations deleted so update view.
227 template <typename POS
>
228 void DecorationList
<POS
>::DeleteLexerDecorations() {
229 decorationList
.erase(std::remove_if(decorationList
.begin(), decorationList
.end(),
230 [](const std::unique_ptr
<Decoration
<POS
>> &deco
) {
231 return deco
->Indicator() < INDIC_CONTAINER
;
232 }), decorationList
.end());
237 template <typename POS
>
238 void DecorationList
<POS
>::DeleteAnyEmpty() {
239 if (lengthDocument
== 0) {
240 decorationList
.clear();
242 decorationList
.erase(std::remove_if(decorationList
.begin(), decorationList
.end(),
243 [](const std::unique_ptr
<Decoration
<POS
>> &deco
) {
244 return deco
->Empty();
245 }), decorationList
.end());
249 template <typename POS
>
250 void DecorationList
<POS
>::SetView() {
251 decorationView
.clear();
252 for (const std::unique_ptr
<Decoration
<POS
>> &deco
: decorationList
) {
253 decorationView
.push_back(deco
.get());
257 template <typename POS
>
258 int DecorationList
<POS
>::AllOnFor(Sci::Position position
) const {
260 for (const std::unique_ptr
<Decoration
<POS
>> &deco
: decorationList
) {
261 if (deco
->rs
.ValueAt(static_cast<POS
>(position
))) {
262 if (deco
->Indicator() < INDIC_IME
) {
263 mask
|= 1 << deco
->Indicator();
270 template <typename POS
>
271 int DecorationList
<POS
>::ValueAt(int indicator
, Sci::Position position
) {
272 const Decoration
<POS
> *deco
= DecorationFromIndicator(indicator
);
274 return deco
->rs
.ValueAt(static_cast<POS
>(position
));
279 template <typename POS
>
280 Sci::Position DecorationList
<POS
>::Start(int indicator
, Sci::Position position
) {
281 const Decoration
<POS
> *deco
= DecorationFromIndicator(indicator
);
283 return deco
->rs
.StartRun(static_cast<POS
>(position
));
288 template <typename POS
>
289 Sci::Position DecorationList
<POS
>::End(int indicator
, Sci::Position position
) {
290 const Decoration
<POS
> *deco
= DecorationFromIndicator(indicator
);
292 return deco
->rs
.EndRun(static_cast<POS
>(position
));
299 namespace Scintilla
{
301 std::unique_ptr
<IDecoration
> DecorationCreate(bool largeDocument
, int indicator
) {
303 return std::unique_ptr
<Decoration
<Sci::Position
>>(new Decoration
<Sci::Position
>(indicator
));
305 return std::unique_ptr
<Decoration
<int>>(new Decoration
<int>(indicator
));
308 std::unique_ptr
<IDecorationList
> DecorationListCreate(bool largeDocument
) {
310 return std::unique_ptr
<DecorationList
<Sci::Position
>>(new DecorationList
<Sci::Position
>());
312 return std::unique_ptr
<DecorationList
<int>>(new DecorationList
<int>());