geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

CellBuffer.cxx
Go to the documentation of this file.
1// Scintilla source code edit control
2/** @file CellBuffer.cxx
3 ** Manages a buffer of cells.
4 **/
5// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6// The License.txt file describes the conditions under which this software may be distributed.
7
8#include <cstddef>
9#include <cstdlib>
10#include <cassert>
11#include <cstring>
12#include <cstdio>
13#include <cstdarg>
14
15#include <stdexcept>
16#include <string>
17#include <vector>
18#include <algorithm>
19#include <memory>
20
21#include "Platform.h"
22
23#include "Scintilla.h"
24#include "Position.h"
25#include "SplitVector.h"
26#include "Partitioning.h"
27#include "CellBuffer.h"
28#include "UniConversion.h"
29
30namespace Scintilla {
31
33 // Measures the number of characters in a string divided into those
34 // from the Base Multilingual Plane and those from other planes.
37 CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept :
38 countBasePlane(countBasePlane_),
39 countOtherPlanes(countOtherPlanes_) {
40 }
41 CountWidths operator-() const noexcept {
43 }
44 Sci::Position WidthUTF32() const noexcept {
45 // All code points take one code unit in UTF-32.
47 }
48 Sci::Position WidthUTF16() const noexcept {
49 // UTF-16 takes 2 code units for other planes
51 }
52 void CountChar(int lenChar) noexcept {
53 if (lenChar == 4) {
55 } else {
57 }
58 }
59};
60
62public:
63 virtual void Init() = 0;
64 virtual void SetPerLine(PerLine *pl) noexcept = 0;
65 virtual void InsertText(Sci::Line line, Sci::Position delta) noexcept = 0;
66 virtual void InsertLine(Sci::Line line, Sci::Position position, bool lineStart) = 0;
67 virtual void InsertLines(Sci::Line line, const Sci::Position *positions, size_t lines, bool lineStart) = 0;
68 virtual void SetLineStart(Sci::Line line, Sci::Position position) noexcept = 0;
69 virtual void RemoveLine(Sci::Line line) = 0;
70 virtual Sci::Line Lines() const noexcept = 0;
71 virtual Sci::Line LineFromPosition(Sci::Position pos) const noexcept = 0;
72 virtual Sci::Position LineStart(Sci::Line line) const noexcept = 0;
73 virtual void InsertCharacters(Sci::Line line, CountWidths delta) noexcept = 0;
74 virtual void SetLineCharactersWidth(Sci::Line line, CountWidths width) noexcept = 0;
75 virtual int LineCharacterIndex() const noexcept = 0;
76 virtual bool AllocateLineCharacterIndex(int lineCharacterIndex, Sci::Line lines) = 0;
77 virtual bool ReleaseLineCharacterIndex(int lineCharacterIndex) = 0;
78 virtual Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept = 0;
79 virtual Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept = 0;
80 virtual ~ILineVector() {}
81};
82
83}
84
85using namespace Scintilla;
86
87template <typename POS>
89public:
92
94 // Minimal initial allocation
95 }
96 // Deleted so LineStartIndex objects can not be copied.
97 LineStartIndex(const LineStartIndex &) = delete;
99 void operator=(const LineStartIndex &) = delete;
100 void operator=(LineStartIndex &&) = delete;
101 virtual ~LineStartIndex() {
102 }
104 refCount++;
105 Sci::Position length = starts.PositionFromPartition(starts.Partitions());
106 for (Sci::Line line = starts.Partitions(); line < lines; line++) {
107 // Produce an ascending sequence that will be filled in with correct widths later
108 length++;
109 starts.InsertPartition(static_cast<POS>(line), static_cast<POS>(length));
110 }
111 return refCount == 1;
112 }
113 bool Release() {
114 if (refCount == 1) {
115 starts.DeleteAll();
116 }
117 refCount--;
118 return refCount == 0;
119 }
120 bool Active() const noexcept {
121 return refCount > 0;
122 }
124 return starts.PositionFromPartition(static_cast<POS>(line) + 1) -
125 starts.PositionFromPartition(static_cast<POS>(line));
126 }
127 void SetLineWidth(Sci::Line line, Sci::Position width) noexcept {
128 const Sci::Position widthCurrent = LineWidth(line);
129 starts.InsertText(static_cast<POS>(line), static_cast<POS>(width - widthCurrent));
130 }
132 // Insert multiple lines with each temporarily 1 character wide.
133 // The line widths will be fixed up by later measuring code.
134 const POS lineAsPos = static_cast<POS>(line);
135 const POS lineStart = starts.PositionFromPartition(lineAsPos - 1) + 1;
136 for (POS l = 0; l < static_cast<POS>(lines); l++) {
137 starts.InsertPartition(lineAsPos + l, lineStart + l);
138 }
139 }
140};
141
142template <typename POS>
143class LineVector : public ILineVector {
149
150 void SetActiveIndices() noexcept {
152 | (startsUTF16.Active() ? SC_LINECHARACTERINDEX_UTF16 : 0);
153 }
154
155public:
156 LineVector() : starts(256), perLine(nullptr), activeIndices(0) {
157 }
158 // Deleted so LineVector objects can not be copied.
159 LineVector(const LineVector &) = delete;
160 LineVector(LineVector &&) = delete;
161 LineVector &operator=(const LineVector &) = delete;
163 ~LineVector() override {
164 }
165 void Init() override {
166 starts.DeleteAll();
167 if (perLine) {
168 perLine->Init();
169 }
170 startsUTF32.starts.DeleteAll();
171 startsUTF16.starts.DeleteAll();
172 }
173 void SetPerLine(PerLine *pl) noexcept override {
174 perLine = pl;
175 }
176 void InsertText(Sci::Line line, Sci::Position delta) noexcept override {
177 starts.InsertText(static_cast<POS>(line), static_cast<POS>(delta));
178 }
179 void InsertLine(Sci::Line line, Sci::Position position, bool lineStart) override {
180 const POS lineAsPos = static_cast<POS>(line);
181 starts.InsertPartition(lineAsPos, static_cast<POS>(position));
182 if (activeIndices) {
184 startsUTF32.InsertLines(line, 1);
185 }
187 startsUTF16.InsertLines(line, 1);
188 }
189 }
190 if (perLine) {
191 if ((line > 0) && lineStart)
192 line--;
194 }
195 }
196 void InsertLines(Sci::Line line, const Sci::Position *positions, size_t lines, bool lineStart) override {
197 const POS lineAsPos = static_cast<POS>(line);
198 if (sizeof(Sci::Position) == sizeof(POS)) {
199 starts.InsertPartitions(lineAsPos, reinterpret_cast<const POS *>(positions), lines);
200 } else {
201 starts.InsertPartitionsWithCast(lineAsPos, positions, lines);
202 }
203 if (activeIndices) {
205 startsUTF32.InsertLines(line, lines);
206 }
208 startsUTF16.InsertLines(line, lines);
209 }
210 }
211 if (perLine) {
212 if ((line > 0) && lineStart)
213 line--;
215 }
216 }
218 starts.SetPartitionStartPosition(static_cast<POS>(line), static_cast<POS>(position));
219 }
220 void RemoveLine(Sci::Line line) override {
221 starts.RemovePartition(static_cast<POS>(line));
223 startsUTF32.starts.RemovePartition(static_cast<POS>(line));
224 }
226 startsUTF16.starts.RemovePartition(static_cast<POS>(line));
227 }
228 if (perLine) {
230 }
231 }
232 Sci::Line Lines() const noexcept override {
233 return static_cast<Sci::Line>(starts.Partitions());
234 }
235 Sci::Line LineFromPosition(Sci::Position pos) const noexcept override {
236 return static_cast<Sci::Line>(starts.PartitionFromPosition(static_cast<POS>(pos)));
237 }
238 Sci::Position LineStart(Sci::Line line) const noexcept override {
239 return starts.PositionFromPartition(static_cast<POS>(line));
240 }
241 void InsertCharacters(Sci::Line line, CountWidths delta) noexcept override {
243 startsUTF32.starts.InsertText(static_cast<POS>(line), static_cast<POS>(delta.WidthUTF32()));
244 }
246 startsUTF16.starts.InsertText(static_cast<POS>(line), static_cast<POS>(delta.WidthUTF16()));
247 }
248 }
249 void SetLineCharactersWidth(Sci::Line line, CountWidths width) noexcept override {
251 assert(startsUTF32.starts.Partitions() == starts.Partitions());
252 startsUTF32.SetLineWidth(line, width.WidthUTF32());
253 }
255 assert(startsUTF16.starts.Partitions() == starts.Partitions());
256 startsUTF16.SetLineWidth(line, width.WidthUTF16());
257 }
258 }
259
260 int LineCharacterIndex() const noexcept override {
261 return activeIndices;
262 }
263 bool AllocateLineCharacterIndex(int lineCharacterIndex, Sci::Line lines) override {
264 const int activeIndicesStart = activeIndices;
265 if ((lineCharacterIndex & SC_LINECHARACTERINDEX_UTF32) != 0) {
266 startsUTF32.Allocate(lines);
267 assert(startsUTF32.starts.Partitions() == starts.Partitions());
268 }
269 if ((lineCharacterIndex & SC_LINECHARACTERINDEX_UTF16) != 0) {
270 startsUTF16.Allocate(lines);
271 assert(startsUTF16.starts.Partitions() == starts.Partitions());
272 }
274 return activeIndicesStart != activeIndices;
275 }
276 bool ReleaseLineCharacterIndex(int lineCharacterIndex) override {
277 const int activeIndicesStart = activeIndices;
278 if ((lineCharacterIndex & SC_LINECHARACTERINDEX_UTF32) != 0) {
279 startsUTF32.Release();
280 }
281 if ((lineCharacterIndex & SC_LINECHARACTERINDEX_UTF16) != 0) {
282 startsUTF16.Release();
283 }
285 return activeIndicesStart != activeIndices;
286 }
287 Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept override {
288 if (lineCharacterIndex == SC_LINECHARACTERINDEX_UTF32) {
289 return startsUTF32.starts.PositionFromPartition(static_cast<POS>(line));
290 } else {
291 return startsUTF16.starts.PositionFromPartition(static_cast<POS>(line));
292 }
293 }
294 Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept override {
295 if (lineCharacterIndex == SC_LINECHARACTERINDEX_UTF32) {
296 return static_cast<Sci::Line>(startsUTF32.starts.PartitionFromPosition(static_cast<POS>(pos)));
297 } else {
298 return static_cast<Sci::Line>(startsUTF16.starts.PartitionFromPosition(static_cast<POS>(pos)));
299 }
300 }
301};
302
303Action::Action() noexcept {
304 at = startAction;
305 position = 0;
306 lenData = 0;
307 mayCoalesce = false;
308}
309
311}
312
313void Action::Create(actionType at_, Sci::Position position_, const char *data_, Sci::Position lenData_, bool mayCoalesce_) {
314 data = nullptr;
315 position = position_;
316 at = at_;
317 if (lenData_) {
318 data = Sci::make_unique<char[]>(lenData_);
319 memcpy(&data[0], data_, lenData_);
320 }
321 lenData = lenData_;
322 mayCoalesce = mayCoalesce_;
323}
324
325void Action::Clear() noexcept {
326 data = nullptr;
327 lenData = 0;
328}
329
330// The undo history stores a sequence of user operations that represent the user's view of the
331// commands executed on the text.
332// Each user operation contains a sequence of text insertion and text deletion actions.
333// All the user operations are stored in a list of individual actions with 'start' actions used
334// as delimiters between user operations.
335// Initially there is one start action in the history.
336// As each action is performed, it is recorded in the history. The action may either become
337// part of the current user operation or may start a new user operation. If it is to be part of the
338// current operation, then it overwrites the current last action. If it is to be part of a new
339// operation, it is appended after the current last action.
340// After writing the new action, a new start action is appended at the end of the history.
341// The decision of whether to start a new user operation is based upon two factors. If a
342// compound operation has been explicitly started by calling BeginUndoAction and no matching
343// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
344// operation. If there is no outstanding BeginUndoAction call then a new operation is started
345// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
346// Sequences that look like typing or deletion are coalesced into a single user operation.
347
349
350 actions.resize(3);
351 maxAction = 0;
352 currentAction = 0;
354 savePoint = 0;
355 tentativePoint = -1;
356
358}
359
361}
362
364 // Have to test that there is room for 2 more actions in the array
365 // as two actions may be created by the calling function
366 if (static_cast<size_t>(currentAction) >= (actions.size() - 2)) {
367 // Run out of undo nodes so extend the array
368 actions.resize(actions.size() * 2);
369 }
370}
371
372const char *UndoHistory::AppendAction(actionType at, Sci::Position position, const char *data, Sci::Position lengthData,
373 bool &startSequence, bool mayCoalesce) {
375 //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
376 //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
377 // actions[currentAction - 1].position, actions[currentAction - 1].lenData);
378 if (currentAction < savePoint) {
379 savePoint = -1;
380 }
381 int oldCurrentAction = currentAction;
382 if (currentAction >= 1) {
383 if (0 == undoSequenceDepth) {
384 // Top level actions may not always be coalesced
385 int targetAct = -1;
386 const Action *actPrevious = &(actions[currentAction + targetAct]);
387 // Container actions may forward the coalesce state of Scintilla Actions.
388 while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) {
389 targetAct--;
390 actPrevious = &(actions[currentAction + targetAct]);
391 }
392 // See if current action can be coalesced into previous action
393 // Will work if both are inserts or deletes and position is same
396 } else if (!actions[currentAction].mayCoalesce) {
397 // Not allowed to coalesce if this set
399 } else if (!mayCoalesce || !actPrevious->mayCoalesce) {
401 } else if (at == containerAction || actions[currentAction].at == containerAction) {
402 ; // A coalescible containerAction
403 } else if ((at != actPrevious->at) && (actPrevious->at != startAction)) {
405 } else if ((at == insertAction) &&
406 (position != (actPrevious->position + actPrevious->lenData))) {
407 // Insertions must be immediately after to coalesce
409 } else if (at == removeAction) {
410 if ((lengthData == 1) || (lengthData == 2)) {
411 if ((position + lengthData) == actPrevious->position) {
412 ; // Backspace -> OK
413 } else if (position == actPrevious->position) {
414 ; // Delete -> OK
415 } else {
416 // Removals must be at same position to coalesce
418 }
419 } else {
420 // Removals must be of one character to coalesce
422 }
423 } else {
424 // Action coalesced.
425 }
426
427 } else {
428 // Actions not at top level are always coalesced unless this is after return to top level
429 if (!actions[currentAction].mayCoalesce)
431 }
432 } else {
434 }
435 startSequence = oldCurrentAction != currentAction;
436 const int actionWithData = currentAction;
437 actions[currentAction].Create(at, position, data, lengthData, mayCoalesce);
441 return actions[actionWithData].data.get();
442}
443
446 if (undoSequenceDepth == 0) {
447 if (actions[currentAction].at != startAction) {
451 }
452 actions[currentAction].mayCoalesce = false;
453 }
455}
456
461 if (0 == undoSequenceDepth) {
462 if (actions[currentAction].at != startAction) {
466 }
467 actions[currentAction].mayCoalesce = false;
468 }
469}
470
473}
474
476 for (int i = 1; i < maxAction; i++)
477 actions[i].Clear();
478 maxAction = 0;
479 currentAction = 0;
481 savePoint = 0;
482 tentativePoint = -1;
483}
484
487}
488
489bool UndoHistory::IsSavePoint() const noexcept {
490 return savePoint == currentAction;
491}
492
495}
496
498 tentativePoint = -1;
499 // Truncate undo history
501}
502
503bool UndoHistory::TentativeActive() const noexcept {
504 return tentativePoint >= 0;
505}
506
508 // Drop any trailing startAction
511 if (tentativePoint >= 0)
513 else
514 return -1;
515}
516
517bool UndoHistory::CanUndo() const noexcept {
518 return (currentAction > 0) && (maxAction > 0);
519}
520
522 // Drop any trailing startAction
525
526 // Count the steps in this action
527 int act = currentAction;
528 while (actions[act].at != startAction && act > 0) {
529 act--;
530 }
531 return currentAction - act;
532}
533
535 return actions[currentAction];
536}
537
540}
541
542bool UndoHistory::CanRedo() const noexcept {
543 return maxAction > currentAction;
544}
545
547 // Drop any leading startAction
550
551 // Count the steps in this action
552 int act = currentAction;
553 while (act < maxAction && actions[act].at != startAction) {
554 act++;
555 }
556 return act - currentAction;
557}
558
560 return actions[currentAction];
561}
562
565}
566
567CellBuffer::CellBuffer(bool hasStyles_, bool largeDocument_) :
568 hasStyles(hasStyles_), largeDocument(largeDocument_) {
569 readOnly = false;
570 utf8Substance = false;
571 utf8LineEnds = 0;
572 collectingUndo = true;
573 if (largeDocument)
574 plv = Sci::make_unique<LineVector<Sci::Position>>();
575 else
576 plv = Sci::make_unique<LineVector<int>>();
577}
578
580}
581
583 return substance.ValueAt(position);
584}
585
586unsigned char CellBuffer::UCharAt(Sci::Position position) const noexcept {
587 return substance.ValueAt(position);
588}
589
590void CellBuffer::GetCharRange(char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
591 if (lengthRetrieve <= 0)
592 return;
593 if (position < 0)
594 return;
595 if ((position + lengthRetrieve) > substance.Length()) {
596 Platform::DebugPrintf("Bad GetCharRange %.0f for %.0f of %.0f\n",
597 static_cast<double>(position),
598 static_cast<double>(lengthRetrieve),
599 static_cast<double>(substance.Length()));
600 return;
601 }
602 substance.GetRange(buffer, position, lengthRetrieve);
603}
604
606 return hasStyles ? style.ValueAt(position) : 0;
607}
608
609void CellBuffer::GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
610 if (lengthRetrieve < 0)
611 return;
612 if (position < 0)
613 return;
614 if (!hasStyles) {
615 std::fill(buffer, buffer + lengthRetrieve, static_cast<unsigned char>(0));
616 return;
617 }
618 if ((position + lengthRetrieve) > style.Length()) {
619 Platform::DebugPrintf("Bad GetStyleRange %.0f for %.0f of %.0f\n",
620 static_cast<double>(position),
621 static_cast<double>(lengthRetrieve),
622 static_cast<double>(style.Length()));
623 return;
624 }
625 style.GetRange(reinterpret_cast<char *>(buffer), position, lengthRetrieve);
626}
627
629 return substance.BufferPointer();
630}
631
633 return substance.RangePointer(position, rangeLength);
634}
635
637 return substance.GapPosition();
638}
639
640// The char* returned is to an allocation owned by the undo history
641const char *CellBuffer::InsertString(Sci::Position position, const char *s, Sci::Position insertLength, bool &startSequence) {
642 // InsertString and DeleteChars are the bottleneck though which all changes occur
643 const char *data = s;
644 if (!readOnly) {
645 if (collectingUndo) {
646 // Save into the undo/redo stack, but only the characters - not the formatting
647 // This takes up about half load time
648 data = uh.AppendAction(insertAction, position, s, insertLength, startSequence);
649 }
650
651 BasicInsertString(position, s, insertLength);
652 }
653 return data;
654}
655
656bool CellBuffer::SetStyleAt(Sci::Position position, char styleValue) noexcept {
657 if (!hasStyles) {
658 return false;
659 }
660 const char curVal = style.ValueAt(position);
661 if (curVal != styleValue) {
662 style.SetValueAt(position, styleValue);
663 return true;
664 } else {
665 return false;
666 }
667}
668
669bool CellBuffer::SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) noexcept {
670 if (!hasStyles) {
671 return false;
672 }
673 bool changed = false;
674 PLATFORM_ASSERT(lengthStyle == 0 ||
675 (lengthStyle > 0 && lengthStyle + position <= style.Length()));
676 while (lengthStyle--) {
677 const char curVal = style.ValueAt(position);
678 if (curVal != styleValue) {
679 style.SetValueAt(position, styleValue);
680 changed = true;
681 }
682 position++;
683 }
684 return changed;
685}
686
687// The char* returned is to an allocation owned by the undo history
688const char *CellBuffer::DeleteChars(Sci::Position position, Sci::Position deleteLength, bool &startSequence) {
689 // InsertString and DeleteChars are the bottleneck though which all changes occur
690 PLATFORM_ASSERT(deleteLength > 0);
691 const char *data = nullptr;
692 if (!readOnly) {
693 if (collectingUndo) {
694 // Save into the undo/redo stack, but only the characters - not the formatting
695 // The gap would be moved to position anyway for the deletion so this doesn't cost extra
696 data = substance.RangePointer(position, deleteLength);
697 data = uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
698 }
699
700 BasicDeleteChars(position, deleteLength);
701 }
702 return data;
703}
704
706 return substance.Length();
707}
708
710 substance.ReAllocate(newSize);
711 if (hasStyles) {
712 style.ReAllocate(newSize);
713 }
714}
715
716void CellBuffer::SetUTF8Substance(bool utf8Substance_) noexcept {
717 utf8Substance = utf8Substance_;
718}
719
720void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
721 if (utf8LineEnds != utf8LineEnds_) {
722 const int indexes = plv->LineCharacterIndex();
723 utf8LineEnds = utf8LineEnds_;
726 }
727}
728
729bool CellBuffer::ContainsLineEnd(const char *s, Sci::Position length) const noexcept {
730 unsigned char chBeforePrev = 0;
731 unsigned char chPrev = 0;
732 for (Sci::Position i = 0; i < length; i++) {
733 const unsigned char ch = s[i];
734 if ((ch == '\r') || (ch == '\n')) {
735 return true;
736 } else if (utf8LineEnds) {
737 if (UTF8IsMultibyteLineEnd(chBeforePrev, chPrev, ch)) {
738 return true;
739 }
740 }
741 chBeforePrev = chPrev;
742 chPrev = ch;
743 }
744 return false;
745}
746
747void CellBuffer::SetPerLine(PerLine *pl) noexcept {
748 plv->SetPerLine(pl);
749}
750
751int CellBuffer::LineCharacterIndex() const noexcept {
752 return plv->LineCharacterIndex();
753}
754
755void CellBuffer::AllocateLineCharacterIndex(int lineCharacterIndex) {
756 if (utf8Substance) {
757 if (plv->AllocateLineCharacterIndex(lineCharacterIndex, Lines())) {
758 // Changed so recalculate whole file
760 }
761 }
762}
763
764void CellBuffer::ReleaseLineCharacterIndex(int lineCharacterIndex) {
765 plv->ReleaseLineCharacterIndex(lineCharacterIndex);
766}
767
768Sci::Line CellBuffer::Lines() const noexcept {
769 return plv->Lines();
770}
771
773 if (line < 0)
774 return 0;
775 else if (line >= Lines())
776 return Length();
777 else
778 return plv->LineStart(line);
779}
780
782 return plv->LineFromPosition(pos);
783}
784
785Sci::Position CellBuffer::IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept {
786 return plv->IndexLineStart(line, lineCharacterIndex);
787}
788
789Sci::Line CellBuffer::LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept {
790 return plv->LineFromPositionIndex(pos, lineCharacterIndex);
791}
792
793bool CellBuffer::IsReadOnly() const noexcept {
794 return readOnly;
795}
796
797void CellBuffer::SetReadOnly(bool set) noexcept {
798 readOnly = set;
799}
800
801bool CellBuffer::IsLarge() const noexcept {
802 return largeDocument;
803}
804
805bool CellBuffer::HasStyles() const noexcept {
806 return hasStyles;
807}
808
811}
812
813bool CellBuffer::IsSavePoint() const noexcept {
814 return uh.IsSavePoint();
815}
816
819}
820
823}
824
826 return uh.TentativeSteps();
827}
828
829bool CellBuffer::TentativeActive() const noexcept {
830 return uh.TentativeActive();
831}
832
833// Without undo
834
836 plv->InsertLine(line, position, lineStart);
837}
838
840 plv->RemoveLine(line);
841}
842
844 const unsigned char bytes[] = {
845 static_cast<unsigned char>(substance.ValueAt(position-2)),
846 static_cast<unsigned char>(substance.ValueAt(position-1)),
847 static_cast<unsigned char>(substance.ValueAt(position)),
848 static_cast<unsigned char>(substance.ValueAt(position+1)),
849 };
851}
852
854 assert(position >= 0 && position <= Length());
855 if (position > 0) {
856 std::string back;
857 for (int i = 0; i < UTF8MaxBytes; i++) {
858 const Sci::Position posBack = position - i;
859 if (posBack < 0) {
860 return false;
861 }
862 back.insert(0, 1, substance.ValueAt(posBack));
863 if (!UTF8IsTrailByte(back.front())) {
864 if (i > 0) {
865 // Have reached a non-trail
866 const int cla = UTF8Classify(reinterpret_cast<const unsigned char*>(back.data()), back.size());
867 if ((cla & UTF8MaskInvalid) || (cla != i)) {
868 return false;
869 }
870 }
871 break;
872 }
873 }
874 }
875 if (position < Length()) {
876 const unsigned char fore = substance.ValueAt(position);
877 if (UTF8IsTrailByte(fore)) {
878 return false;
879 }
880 }
881 return true;
882}
883
885 // Reinitialize line data -- too much work to preserve
886 plv->Init();
887
888 const Sci::Position position = 0;
889 const Sci::Position length = Length();
890 Sci::Line lineInsert = 1;
891 const bool atLineStart = true;
892 plv->InsertText(lineInsert-1, length);
893 unsigned char chBeforePrev = 0;
894 unsigned char chPrev = 0;
895 for (Sci::Position i = 0; i < length; i++) {
896 const unsigned char ch = substance.ValueAt(position + i);
897 if (ch == '\r') {
898 InsertLine(lineInsert, (position + i) + 1, atLineStart);
899 lineInsert++;
900 } else if (ch == '\n') {
901 if (chPrev == '\r') {
902 // Patch up what was end of line
903 plv->SetLineStart(lineInsert - 1, (position + i) + 1);
904 } else {
905 InsertLine(lineInsert, (position + i) + 1, atLineStart);
906 lineInsert++;
907 }
908 } else if (utf8LineEnds) {
909 if (UTF8IsMultibyteLineEnd(chBeforePrev, chPrev, ch)) {
910 InsertLine(lineInsert, (position + i) + 1, atLineStart);
911 lineInsert++;
912 }
913 }
914 chBeforePrev = chPrev;
915 chPrev = ch;
916 }
917}
918
919namespace {
920
921CountWidths CountCharacterWidthsUTF8(const char *s, size_t len) noexcept {
922 CountWidths cw;
923 size_t remaining = len;
924 while (remaining > 0) {
925 const int utf8Status = UTF8Classify(reinterpret_cast<const unsigned char*>(s), len);
926 const int lenChar = utf8Status & UTF8MaskWidth;
927 cw.CountChar(lenChar);
928 s += lenChar;
929 remaining -= lenChar;
930 }
931 return cw;
932}
933
934}
935
937 return plv->LineCharacterIndex() != SC_LINECHARACTERINDEX_NONE;
938}
939
941 std::string text;
942 Sci::Position posLineEnd = LineStart(lineFirst);
943 for (Sci::Line line = lineFirst; line <= lineLast; line++) {
944 // Find line start and end, retrieve text of line, count characters and update line width
945 const Sci::Position posLineStart = posLineEnd;
946 posLineEnd = LineStart(line+1);
947 const Sci::Position width = posLineEnd - posLineStart;
948 text.resize(width);
949 GetCharRange(const_cast<char *>(text.data()), posLineStart, width);
950 const CountWidths cw = CountCharacterWidthsUTF8(text.data(), text.size());
951 plv->SetLineCharactersWidth(line, cw);
952 }
953}
954
956 if (insertLength == 0)
957 return;
958 PLATFORM_ASSERT(insertLength > 0);
959
960 const unsigned char chAfter = substance.ValueAt(position);
961 bool breakingUTF8LineEnd = false;
962 if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
963 breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
964 }
965
966 const Sci::Line linePosition = plv->LineFromPosition(position);
967 Sci::Line lineInsert = linePosition + 1;
968
969 // A simple insertion is one that inserts valid text on a single line at a character boundary
970 bool simpleInsertion = false;
971
972 const bool maintainingIndex = MaintainingLineCharacterIndex();
973
974 // Check for breaking apart a UTF-8 sequence and inserting invalid UTF-8
975 if (utf8Substance && maintainingIndex) {
976 // Actually, don't need to check that whole insertion is valid just that there
977 // are no potential fragments at ends.
978 simpleInsertion = UTF8IsCharacterBoundary(position) &&
979 UTF8IsValid(s, insertLength);
980 }
981
982 substance.InsertFromArray(position, s, 0, insertLength);
983 if (hasStyles) {
984 style.InsertValue(position, insertLength, 0);
985 }
986
987 const bool atLineStart = plv->LineStart(lineInsert-1) == position;
988 // Point all the lines after the insertion point further along in the buffer
989 plv->InsertText(lineInsert-1, insertLength);
990 unsigned char chBeforePrev = substance.ValueAt(position - 2);
991 unsigned char chPrev = substance.ValueAt(position - 1);
992 if (chPrev == '\r' && chAfter == '\n') {
993 // Splitting up a crlf pair at position
994 InsertLine(lineInsert, position, false);
995 lineInsert++;
996 }
997 if (breakingUTF8LineEnd) {
998 RemoveLine(lineInsert);
999 }
1000
1001 constexpr size_t PositionBlockSize = 128;
1002 Sci::Position positions[PositionBlockSize]{};
1003 size_t nPositions = 0;
1004 const Sci::Line lineStart = lineInsert;
1005
1006 // s may not NULL-terminated, ensure *ptr == '\n' or *next == '\n' is valid.
1007 const char * const end = s + insertLength - 1;
1008 const char *ptr = s;
1009 unsigned char ch = 0;
1010
1011 if (chPrev == '\r' && *ptr == '\n') {
1012 ++ptr;
1013 // Patch up what was end of line
1014 plv->SetLineStart(lineInsert - 1, (position + ptr - s));
1015 simpleInsertion = false;
1016 }
1017
1018 if (ptr < end) {
1019 uint8_t eolTable[256]{};
1020 eolTable[static_cast<uint8_t>('\n')] = 1;
1021 eolTable[static_cast<uint8_t>('\r')] = 2;
1022 if (utf8LineEnds) {
1023 // see UniConversion.h for LS, PS and NEL
1024 eolTable[0x85] = 4;
1025 eolTable[0xa8] = 3;
1026 eolTable[0xa9] = 3;
1027 }
1028
1029 do {
1030 // skip to line end
1031 ch = *ptr++;
1032 uint8_t type;
1033 while ((type = eolTable[ch]) == 0 && ptr < end) {
1034 chBeforePrev = chPrev;
1035 chPrev = ch;
1036 ch = *ptr++;
1037 }
1038 switch (type) {
1039 case 2: // '\r'
1040 if (*ptr == '\n') {
1041 ++ptr;
1042 }
1043 case 1: // '\n'
1044 positions[nPositions++] = position + ptr - s;
1045 if (nPositions == PositionBlockSize) {
1046 plv->InsertLines(lineInsert, positions, nPositions, atLineStart);
1047 lineInsert += nPositions;
1048 nPositions = 0;
1049 }
1050 break;
1051 case 3:
1052 case 4:
1053 // LS, PS and NEL
1054 if ((type == 3 && chPrev == 0x80 && chBeforePrev == 0xe2) || (type == 4 && chPrev == 0xc2)) {
1055 positions[nPositions++] = position + ptr - s;
1056 if (nPositions == PositionBlockSize) {
1057 plv->InsertLines(lineInsert, positions, nPositions, atLineStart);
1058 lineInsert += nPositions;
1059 nPositions = 0;
1060 }
1061 }
1062 break;
1063 }
1064
1065 chBeforePrev = chPrev;
1066 chPrev = ch;
1067 } while (ptr < end);
1068 }
1069
1070 if (nPositions != 0) {
1071 plv->InsertLines(lineInsert, positions, nPositions, atLineStart);
1072 lineInsert += nPositions;
1073 }
1074
1075 ch = *end;
1076 if (ptr == end) {
1077 ++ptr;
1078 if (ch == '\r' || ch == '\n') {
1079 InsertLine(lineInsert, (position + ptr - s), atLineStart);
1080 lineInsert++;
1081 } else if (utf8LineEnds && !UTF8IsAscii(ch)) {
1082 if (UTF8IsMultibyteLineEnd(chBeforePrev, chPrev, ch)) {
1083 InsertLine(lineInsert, (position + ptr - s), atLineStart);
1084 lineInsert++;
1085 }
1086 }
1087 }
1088
1089 // Joining two lines where last insertion is cr and following substance starts with lf
1090 if (chAfter == '\n') {
1091 if (ch == '\r') {
1092 // End of line already in buffer so drop the newly created one
1093 RemoveLine(lineInsert - 1);
1094 simpleInsertion = false;
1095 }
1096 } else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
1097 chBeforePrev = chPrev;
1098 chPrev = ch;
1099 // May have end of UTF-8 line end in buffer and start in insertion
1100 for (int j = 0; j < UTF8SeparatorLength-1; j++) {
1101 const unsigned char chAt = substance.ValueAt(position + insertLength + j);
1102 const unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
1103 if (UTF8IsSeparator(back3)) {
1104 InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
1105 lineInsert++;
1106 }
1107 if ((j == 0) && UTF8IsNEL(back3+1)) {
1108 InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
1109 lineInsert++;
1110 }
1111 chBeforePrev = chPrev;
1112 chPrev = chAt;
1113 }
1114 }
1115 if (maintainingIndex) {
1116 if (simpleInsertion && (lineInsert == lineStart)) {
1117 const CountWidths cw = CountCharacterWidthsUTF8(s, insertLength);
1118 plv->InsertCharacters(linePosition, cw);
1119 } else {
1120 RecalculateIndexLineStarts(linePosition, lineInsert - 1);
1121 }
1122 }
1123}
1124
1126 if (deleteLength == 0)
1127 return;
1128
1129 Sci::Line lineRecalculateStart = INVALID_POSITION;
1130
1131 if ((position == 0) && (deleteLength == substance.Length())) {
1132 // If whole buffer is being deleted, faster to reinitialise lines data
1133 // than to delete each line.
1134 plv->Init();
1135 } else {
1136 // Have to fix up line positions before doing deletion as looking at text in buffer
1137 // to work out which lines have been removed
1138
1139 const Sci::Line linePosition = plv->LineFromPosition(position);
1140 Sci::Line lineRemove = linePosition + 1;
1141
1142 plv->InsertText(lineRemove-1, - (deleteLength));
1143 const unsigned char chPrev = substance.ValueAt(position - 1);
1144 const unsigned char chBefore = chPrev;
1145 unsigned char chNext = substance.ValueAt(position);
1146
1147 // Check for breaking apart a UTF-8 sequence
1148 // Needs further checks that text is UTF-8 or that some other break apart is occurring
1150 const Sci::Position posEnd = position + deleteLength;
1151 const Sci::Line lineEndRemove = plv->LineFromPosition(posEnd);
1152 const bool simpleDeletion =
1153 (linePosition == lineEndRemove) &&
1155 if (simpleDeletion) {
1156 std::string text(deleteLength, '\0');
1157 GetCharRange(const_cast<char *>(text.data()), position, deleteLength);
1158 if (UTF8IsValid(text.data(), text.size())) {
1159 // Everything is good
1160 const CountWidths cw = CountCharacterWidthsUTF8(text.data(), text.size());
1161 plv->InsertCharacters(linePosition, -cw);
1162 } else {
1163 lineRecalculateStart = linePosition;
1164 }
1165 } else {
1166 lineRecalculateStart = linePosition;
1167 }
1168 }
1169
1170 bool ignoreNL = false;
1171 if (chPrev == '\r' && chNext == '\n') {
1172 // Move back one
1173 plv->SetLineStart(lineRemove, position);
1174 lineRemove++;
1175 ignoreNL = true; // First \n is not real deletion
1176 }
1177 if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
1179 RemoveLine(lineRemove);
1180 }
1181 }
1182
1183 unsigned char ch = chNext;
1184 for (Sci::Position i = 0; i < deleteLength; i++) {
1185 chNext = substance.ValueAt(position + i + 1);
1186 if (ch == '\r') {
1187 if (chNext != '\n') {
1188 RemoveLine(lineRemove);
1189 }
1190 } else if (ch == '\n') {
1191 if (ignoreNL) {
1192 ignoreNL = false; // Further \n are real deletions
1193 } else {
1194 RemoveLine(lineRemove);
1195 }
1196 } else if (utf8LineEnds) {
1197 if (!UTF8IsAscii(ch)) {
1198 const unsigned char next3[3] = {ch, chNext,
1199 static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
1200 if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
1201 RemoveLine(lineRemove);
1202 }
1203 }
1204 }
1205
1206 ch = chNext;
1207 }
1208 // May have to fix up end if last deletion causes cr to be next to lf
1209 // or removes one of a crlf pair
1210 const char chAfter = substance.ValueAt(position + deleteLength);
1211 if (chBefore == '\r' && chAfter == '\n') {
1212 // Using lineRemove-1 as cr ended line before start of deletion
1213 RemoveLine(lineRemove - 1);
1214 plv->SetLineStart(lineRemove - 1, position + 1);
1215 }
1216 }
1217 substance.DeleteRange(position, deleteLength);
1218 if (lineRecalculateStart >= 0) {
1219 RecalculateIndexLineStarts(lineRecalculateStart, lineRecalculateStart);
1220 }
1221 if (hasStyles) {
1222 style.DeleteRange(position, deleteLength);
1223 }
1224}
1225
1226bool CellBuffer::SetUndoCollection(bool collectUndo) {
1227 collectingUndo = collectUndo;
1229 return collectingUndo;
1230}
1231
1232bool CellBuffer::IsCollectingUndo() const noexcept {
1233 return collectingUndo;
1234}
1235
1238}
1239
1241 uh.EndUndoAction();
1242}
1243
1244void CellBuffer::AddUndoAction(Sci::Position token, bool mayCoalesce) {
1245 bool startSequence;
1246 uh.AppendAction(containerAction, token, nullptr, 0, startSequence, mayCoalesce);
1247}
1248
1251}
1252
1253bool CellBuffer::CanUndo() const noexcept {
1254 return uh.CanUndo();
1255}
1256
1258 return uh.StartUndo();
1259}
1260
1262 return uh.GetUndoStep();
1263}
1264
1266 const Action &actionStep = uh.GetUndoStep();
1267 if (actionStep.at == insertAction) {
1268 if (substance.Length() < actionStep.lenData) {
1269 throw std::runtime_error(
1270 "CellBuffer::PerformUndoStep: deletion must be less than document length.");
1271 }
1272 BasicDeleteChars(actionStep.position, actionStep.lenData);
1273 } else if (actionStep.at == removeAction) {
1274 BasicInsertString(actionStep.position, actionStep.data.get(), actionStep.lenData);
1275 }
1277}
1278
1279bool CellBuffer::CanRedo() const noexcept {
1280 return uh.CanRedo();
1281}
1282
1284 return uh.StartRedo();
1285}
1286
1288 return uh.GetRedoStep();
1289}
1290
1292 const Action &actionStep = uh.GetRedoStep();
1293 if (actionStep.at == insertAction) {
1294 BasicInsertString(actionStep.position, actionStep.data.get(), actionStep.lenData);
1295 } else if (actionStep.at == removeAction) {
1296 BasicDeleteChars(actionStep.position, actionStep.lenData);
1297 }
1299}
1300
Manages the text of the document.
Data structure used to partition an interval.
Interface to platform facilities.
#define PLATFORM_ASSERT(c)
Definition: Platform.h:544
Defines global type name Position in the Sci internal namespace.
Interface to the edit control.
#define SC_LINECHARACTERINDEX_UTF32
Definition: Scintilla.h:1160
#define INVALID_POSITION
Definition: Scintilla.h:44
#define SC_LINECHARACTERINDEX_NONE
Definition: Scintilla.h:1159
#define SC_LINECHARACTERINDEX_UTF16
Definition: Scintilla.h:1161
Main data structure for holding arrays that handle insertions and deletions efficiently.
Functions to handle UTF-8 and UTF-16 strings.
GeanyBuildCommand ** ptr
Definition: build.c:2679
virtual ~LineStartIndex()
Definition: CellBuffer.cxx:101
LineStartIndex(const LineStartIndex &)=delete
Sci::Position LineWidth(Sci::Line line) const noexcept
Definition: CellBuffer.cxx:123
void InsertLines(Sci::Line line, Sci::Line lines)
Definition: CellBuffer.cxx:131
bool Active() const noexcept
Definition: CellBuffer.cxx:120
void operator=(LineStartIndex &&)=delete
Partitioning< POS > starts
Definition: CellBuffer.cxx:91
void operator=(const LineStartIndex &)=delete
bool Allocate(Sci::Line lines)
Definition: CellBuffer.cxx:103
LineStartIndex(LineStartIndex &&)=delete
void SetLineWidth(Sci::Line line, Sci::Position width) noexcept
Definition: CellBuffer.cxx:127
bool AllocateLineCharacterIndex(int lineCharacterIndex, Sci::Line lines) override
Definition: CellBuffer.cxx:263
Sci::Position LineStart(Sci::Line line) const noexcept override
Definition: CellBuffer.cxx:238
void SetActiveIndices() noexcept
Definition: CellBuffer.cxx:150
void SetLineCharactersWidth(Sci::Line line, CountWidths width) noexcept override
Definition: CellBuffer.cxx:249
void SetPerLine(PerLine *pl) noexcept override
Definition: CellBuffer.cxx:173
void InsertLines(Sci::Line line, const Sci::Position *positions, size_t lines, bool lineStart) override
Definition: CellBuffer.cxx:196
void InsertCharacters(Sci::Line line, CountWidths delta) noexcept override
Definition: CellBuffer.cxx:241
LineVector(const LineVector &)=delete
bool ReleaseLineCharacterIndex(int lineCharacterIndex) override
Definition: CellBuffer.cxx:276
Sci::Line Lines() const noexcept override
Definition: CellBuffer.cxx:232
void InsertLine(Sci::Line line, Sci::Position position, bool lineStart) override
Definition: CellBuffer.cxx:179
void InsertText(Sci::Line line, Sci::Position delta) noexcept override
Definition: CellBuffer.cxx:176
int activeIndices
Definition: CellBuffer.cxx:148
Sci::Line LineFromPosition(Sci::Position pos) const noexcept override
Definition: CellBuffer.cxx:235
PerLine * perLine
Definition: CellBuffer.cxx:145
LineVector & operator=(const LineVector &)=delete
void SetLineStart(Sci::Line line, Sci::Position position) noexcept override
Definition: CellBuffer.cxx:217
Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept override
Definition: CellBuffer.cxx:294
~LineVector() override
Definition: CellBuffer.cxx:163
LineStartIndex< POS > startsUTF32
Definition: CellBuffer.cxx:147
int LineCharacterIndex() const noexcept override
Definition: CellBuffer.cxx:260
LineVector & operator=(LineVector &&)=delete
Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept override
Definition: CellBuffer.cxx:287
void Init() override
Definition: CellBuffer.cxx:165
void RemoveLine(Sci::Line line) override
Definition: CellBuffer.cxx:220
LineVector(LineVector &&)=delete
Partitioning< POS > starts
Definition: CellBuffer.cxx:144
LineStartIndex< POS > startsUTF16
Definition: CellBuffer.cxx:146
Actions are used to store all the information required to perform one undo/redo step.
Definition: CellBuffer.h:33
Sci::Position lenData
Definition: CellBuffer.h:38
Sci::Position position
Definition: CellBuffer.h:36
std::unique_ptr< char[]> data
Definition: CellBuffer.h:37
void Create(actionType at_, Sci::Position position_=0, const char *data_=nullptr, Sci::Position lenData_=0, bool mayCoalesce_=true)
Definition: CellBuffer.cxx:313
void Clear() noexcept
Definition: CellBuffer.cxx:325
actionType at
Definition: CellBuffer.h:35
void ReleaseLineCharacterIndex(int lineCharacterIndex)
Definition: CellBuffer.cxx:764
int TentativeSteps() noexcept
Definition: CellBuffer.cxx:825
bool IsSavePoint() const noexcept
Definition: CellBuffer.cxx:813
SplitVector< char > style
Definition: CellBuffer.h:115
unsigned char UCharAt(Sci::Position position) const noexcept
Definition: CellBuffer.cxx:586
bool SetStyleAt(Sci::Position position, char styleValue) noexcept
Setting styles for positions outside the range of the buffer is safe and has no effect.
Definition: CellBuffer.cxx:656
void Allocate(Sci::Position newSize)
Definition: CellBuffer.cxx:709
bool IsLarge() const noexcept
Definition: CellBuffer.cxx:801
void RemoveLine(Sci::Line line)
Definition: CellBuffer.cxx:839
void SetSavePoint()
The save point is a marker in the undo stack where the container has stated that the buffer was saved...
Definition: CellBuffer.cxx:809
Sci::Line LineFromPosition(Sci::Position pos) const noexcept
Definition: CellBuffer.cxx:781
bool SetUndoCollection(bool collectUndo)
bool IsCollectingUndo() const noexcept
bool ContainsLineEnd(const char *s, Sci::Position length) const noexcept
Definition: CellBuffer.cxx:729
SplitVector< char > substance
Definition: CellBuffer.h:114
bool HasStyles() const noexcept
Definition: CellBuffer.cxx:805
bool UTF8LineEndOverlaps(Sci::Position position) const noexcept
Definition: CellBuffer.cxx:843
std::unique_ptr< ILineVector > plv
Definition: CellBuffer.h:123
void SetLineEndTypes(int utf8LineEnds_)
Definition: CellBuffer.cxx:720
void RecalculateIndexLineStarts(Sci::Line lineFirst, Sci::Line lineLast)
Definition: CellBuffer.cxx:940
CellBuffer(bool hasStyles_, bool largeDocument_)
Definition: CellBuffer.cxx:567
Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept
Definition: CellBuffer.cxx:785
void SetReadOnly(bool set) noexcept
Definition: CellBuffer.cxx:797
void InsertLine(Sci::Line line, Sci::Position position, bool lineStart)
Definition: CellBuffer.cxx:835
void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const
Definition: CellBuffer.cxx:609
void GetCharRange(char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const
Definition: CellBuffer.cxx:590
const char * DeleteChars(Sci::Position position, Sci::Position deleteLength, bool &startSequence)
Definition: CellBuffer.cxx:688
void SetUTF8Substance(bool utf8Substance_) noexcept
Definition: CellBuffer.cxx:716
int LineCharacterIndex() const noexcept
Definition: CellBuffer.cxx:751
void SetPerLine(PerLine *pl) noexcept
Definition: CellBuffer.cxx:747
char CharAt(Sci::Position position) const noexcept
Retrieving positions outside the range of the buffer works and returns 0.
Definition: CellBuffer.cxx:582
const Action & GetRedoStep() const
const char * InsertString(Sci::Position position, const char *s, Sci::Position insertLength, bool &startSequence)
Definition: CellBuffer.cxx:641
bool SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) noexcept
Definition: CellBuffer.cxx:669
bool IsReadOnly() const noexcept
Definition: CellBuffer.cxx:793
Sci::Line Lines() const noexcept
Definition: CellBuffer.cxx:768
const char * RangePointer(Sci::Position position, Sci::Position rangeLength) noexcept
Definition: CellBuffer.cxx:632
const Action & GetUndoStep() const
const char * BufferPointer()
Definition: CellBuffer.cxx:628
void BasicDeleteChars(Sci::Position position, Sci::Position deleteLength)
Sci::Position LineStart(Sci::Line line) const noexcept
Definition: CellBuffer.cxx:772
void AllocateLineCharacterIndex(int lineCharacterIndex)
Definition: CellBuffer.cxx:755
bool CanUndo() const noexcept
To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is called that...
bool TentativeActive() const noexcept
Definition: CellBuffer.cxx:829
Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept
Definition: CellBuffer.cxx:789
Sci::Position Length() const noexcept
Definition: CellBuffer.cxx:705
Sci::Position GapPosition() const noexcept
Definition: CellBuffer.cxx:636
void AddUndoAction(Sci::Position token, bool mayCoalesce)
void BasicInsertString(Sci::Position position, const char *s, Sci::Position insertLength)
Actions without undo.
Definition: CellBuffer.cxx:955
bool MaintainingLineCharacterIndex() const noexcept
Definition: CellBuffer.cxx:936
bool CanRedo() const noexcept
bool UTF8IsCharacterBoundary(Sci::Position position) const
Definition: CellBuffer.cxx:853
char StyleAt(Sci::Position position) const noexcept
Definition: CellBuffer.cxx:605
virtual void SetPerLine(PerLine *pl) noexcept=0
virtual bool ReleaseLineCharacterIndex(int lineCharacterIndex)=0
virtual Sci::Line LineFromPosition(Sci::Position pos) const noexcept=0
virtual void Init()=0
virtual Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept=0
virtual Sci::Line Lines() const noexcept=0
virtual void SetLineCharactersWidth(Sci::Line line, CountWidths width) noexcept=0
virtual void InsertText(Sci::Line line, Sci::Position delta) noexcept=0
virtual int LineCharacterIndex() const noexcept=0
virtual void InsertLines(Sci::Line line, const Sci::Position *positions, size_t lines, bool lineStart)=0
virtual void SetLineStart(Sci::Line line, Sci::Position position) noexcept=0
virtual bool AllocateLineCharacterIndex(int lineCharacterIndex, Sci::Line lines)=0
virtual Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept=0
virtual Sci::Position LineStart(Sci::Line line) const noexcept=0
virtual void InsertLine(Sci::Line line, Sci::Position position, bool lineStart)=0
virtual void RemoveLine(Sci::Line line)=0
virtual void InsertCharacters(Sci::Line line, CountWidths delta) noexcept=0
Divide an interval into multiple partitions.
Definition: Partitioning.h:61
virtual void Init()=0
virtual void InsertLines(Sci::Line line, Sci::Line lines)=0
virtual void RemoveLine(Sci::Line line)=0
virtual void InsertLine(Sci::Line line)=0
static void DebugPrintf(const char *format,...)
Definition: PlatGTK.cxx:2032
int TentativeSteps() noexcept
Definition: CellBuffer.cxx:507
bool CanUndo() const noexcept
To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is called that...
Definition: CellBuffer.cxx:517
bool TentativeActive() const noexcept
Definition: CellBuffer.cxx:503
const Action & GetRedoStep() const
Definition: CellBuffer.cxx:559
std::vector< Action > actions
Definition: CellBuffer.h:57
const char * AppendAction(actionType at, Sci::Position position, const char *data, Sci::Position lengthData, bool &startSequence, bool mayCoalesce=true)
Definition: CellBuffer.cxx:372
bool CanRedo() const noexcept
Definition: CellBuffer.cxx:542
bool IsSavePoint() const noexcept
Definition: CellBuffer.cxx:489
const Action & GetUndoStep() const
Definition: CellBuffer.cxx:534
void SetSavePoint() noexcept
The save point is a marker in the undo stack where the container has stated that the buffer was saved...
Definition: CellBuffer.cxx:485
gchar * text
Definition: editor.c:83
gboolean set
Definition: editor.c:84
gint pos
Definition: editor.c:87
#define fill(Order, Group, Idx, Charset, Name)
Definition: encodings.c:62
vString * line
Definition: geany_cobol.c:133
A Position is a position within a document between two characters or at the beginning or end.
Definition: Position.h:17
ptrdiff_t Position
Definition: Position.h:19
ptrdiff_t Line
Definition: Position.h:20
Styling buffer using one element for each run rather than using a filled buffer.
Definition: Converter.h:9
constexpr int UTF8MaxBytes
Definition: UniConversion.h:13
bool UTF8IsValid(const char *s, size_t len) noexcept
constexpr bool UTF8IsAscii(int ch) noexcept
Definition: UniConversion.h:50
bool UTF8IsSeparator(const unsigned char *us) noexcept
Definition: UniConversion.h:64
@ startAction
Definition: CellBuffer.h:28
@ removeAction
Definition: CellBuffer.h:28
@ insertAction
Definition: CellBuffer.h:28
@ containerAction
Definition: CellBuffer.h:28
bool UTF8IsNEL(const unsigned char *us) noexcept
Definition: UniConversion.h:70
constexpr int UTF8SeparatorLength
Definition: UniConversion.h:63
int UTF8Classify(const unsigned char *us, size_t len) noexcept
constexpr bool UTF8IsMultibyteLineEnd(unsigned char ch0, unsigned char ch1, unsigned char ch2) noexcept
Definition: UniConversion.h:75
constexpr bool UTF8IsTrailByte(unsigned char ch) noexcept
Definition: UniConversion.h:46
gint position[2]
Definition: search.c:120
long bytes
Definition: stats.c:32
long lines
Definition: stats.c:32
Sci::Position countOtherPlanes
Definition: CellBuffer.cxx:36
CountWidths operator-() const noexcept
Definition: CellBuffer.cxx:41
Sci::Position countBasePlane
Definition: CellBuffer.cxx:35
CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept
Definition: CellBuffer.cxx:37
void CountChar(int lenChar) noexcept
Definition: CellBuffer.cxx:52
Sci::Position WidthUTF16() const noexcept
Definition: CellBuffer.cxx:48
Sci::Position WidthUTF32() const noexcept
Definition: CellBuffer.cxx:44