Merge pull request #2212 from TwlyY29/bibtex-parser
[geany-mirror.git] / scintilla / src / Decoration.cxx
blob104f75ae2458a03db2437905529acaef2249d76b
1 /** @file Decoration.cxx
2 ** Visual elements added over text.
3 **/
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.
7 #include <cstddef>
8 #include <cstdlib>
9 #include <cstring>
10 #include <cstdio>
11 #include <cstdarg>
13 #include <stdexcept>
14 #include <vector>
15 #include <algorithm>
16 #include <memory>
18 #include "Platform.h"
20 #include "Scintilla.h"
21 #include "Position.h"
22 #include "SplitVector.h"
23 #include "Partitioning.h"
24 #include "RunStyles.h"
25 #include "Decoration.h"
27 using namespace Scintilla;
29 namespace {
31 template <typename POS>
32 class Decoration : public IDecoration {
33 int indicator;
34 public:
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 {
46 return indicator;
48 Sci::Position Length() const override {
49 return rs.Length();
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 {
67 return rs.Runs();
71 template <typename POS>
72 class DecorationList : public IDecorationList {
73 int currentIndicator;
74 int currentValue;
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
80 bool clickNotified;
82 Decoration<POS> *DecorationFromIndicator(int indicator);
83 Decoration<POS> *Create(int indicator, Sci::Position length);
84 void Delete(int indicator);
85 void DeleteAnyEmpty();
86 void SetView();
87 public:
89 DecorationList();
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() {
130 current = nullptr;
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) {
137 return deco.get();
140 return nullptr;
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));
157 SetView();
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());
168 current = nullptr;
169 SetView();
172 template <typename POS>
173 void DecorationList<POS>::SetCurrentIndicator(int indicator) {
174 currentIndicator = indicator;
175 current = DecorationFromIndicator(indicator);
176 currentValue = 1;
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) {
186 if (!current) {
187 current = DecorationFromIndicator(currentIndicator);
188 if (!current) {
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);
198 return fr;
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));
207 if (atEnd) {
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));
219 DeleteAnyEmpty();
220 if (decorationList.size() != decorationView.size()) {
221 // One or more empty decorations deleted so update view.
222 current = nullptr;
223 SetView();
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());
233 current = nullptr;
234 SetView();
237 template <typename POS>
238 void DecorationList<POS>::DeleteAnyEmpty() {
239 if (lengthDocument == 0) {
240 decorationList.clear();
241 } else {
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 {
259 int mask = 0;
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();
267 return mask;
270 template <typename POS>
271 int DecorationList<POS>::ValueAt(int indicator, Sci::Position position) {
272 const Decoration<POS> *deco = DecorationFromIndicator(indicator);
273 if (deco) {
274 return deco->rs.ValueAt(static_cast<POS>(position));
276 return 0;
279 template <typename POS>
280 Sci::Position DecorationList<POS>::Start(int indicator, Sci::Position position) {
281 const Decoration<POS> *deco = DecorationFromIndicator(indicator);
282 if (deco) {
283 return deco->rs.StartRun(static_cast<POS>(position));
285 return 0;
288 template <typename POS>
289 Sci::Position DecorationList<POS>::End(int indicator, Sci::Position position) {
290 const Decoration<POS> *deco = DecorationFromIndicator(indicator);
291 if (deco) {
292 return deco->rs.EndRun(static_cast<POS>(position));
294 return 0;
299 namespace Scintilla {
301 std::unique_ptr<IDecoration> DecorationCreate(bool largeDocument, int indicator) {
302 if (largeDocument)
303 return std::unique_ptr<Decoration<Sci::Position>>(new Decoration<Sci::Position>(indicator));
304 else
305 return std::unique_ptr<Decoration<int>>(new Decoration<int>(indicator));
308 std::unique_ptr<IDecorationList> DecorationListCreate(bool largeDocument) {
309 if (largeDocument)
310 return std::unique_ptr<DecorationList<Sci::Position>>(new DecorationList<Sci::Position>());
311 else
312 return std::unique_ptr<DecorationList<int>>(new DecorationList<int>());