1 // Unit Tests for Scintilla internal data structures
2 
3 #include <cstring>
4 #include <stdexcept>
5 #include <algorithm>
6 
7 #include "Platform.h"
8 
9 #include "SplitVector.h"
10 #include "Partitioning.h"
11 #include "RunStyles.h"
12 #include "CellBuffer.h"
13 
14 #include "catch.hpp"
15 
16 // Test CellBuffer.
17 
18 TEST_CASE("CellBuffer") {
19 
20 	const char sText[] = "Scintilla";
21 	const size_t sLength = strlen(sText);
22 
23 	CellBuffer cb;
24 
25 	SECTION("InsertOneLine") {
26 		bool startSequence = false;
27 		const char *cpChange = cb.InsertString(0, sText, sLength, startSequence);
28 		REQUIRE(startSequence);
29 		REQUIRE(sLength == cb.Length());
30 		REQUIRE(memcmp(cpChange, sText, sLength) == 0);
31 		REQUIRE(1 == cb.Lines());
32 		REQUIRE(0 == cb.LineStart(0));
33 		REQUIRE(0 == cb.LineFromPosition(0));
34 		REQUIRE(sLength == cb.LineStart(1));
35 		REQUIRE(0 == cb.LineFromPosition(sLength));
36 		REQUIRE(cb.CanUndo());
37 		REQUIRE(!cb.CanRedo());
38 	}
39 
40 	SECTION("InsertTwoLines") {
41 		const char sText2[] = "Two\nLines";
42 		const size_t sLength2 = strlen(sText2);
43 		bool startSequence = false;
44 		const char *cpChange = cb.InsertString(0, sText2, sLength2, startSequence);
45 		REQUIRE(startSequence);
46 		REQUIRE(sLength2 == cb.Length());
47 		REQUIRE(memcmp(cpChange, sText2, sLength2) == 0);
48 		REQUIRE(2 == cb.Lines());
49 		REQUIRE(0 == cb.LineStart(0));
50 		REQUIRE(0 == cb.LineFromPosition(0));
51 		REQUIRE(4 == cb.LineStart(1));
52 		REQUIRE(1 == cb.LineFromPosition(5));
53 		REQUIRE(sLength2 == cb.LineStart(2));
54 		REQUIRE(1 == cb.LineFromPosition(sLength2));
55 		REQUIRE(cb.CanUndo());
56 		REQUIRE(!cb.CanRedo());
57 	}
58 
59 	SECTION("UndoOff") {
60 		REQUIRE(cb.IsCollectingUndo());
61 		cb.SetUndoCollection(false);
62 		REQUIRE(!cb.IsCollectingUndo());
63 		bool startSequence = false;
64 		const char *cpChange = cb.InsertString(0, sText, sLength, startSequence);
65 		REQUIRE(!startSequence);
66 		REQUIRE(sLength == cb.Length());
67 		REQUIRE(memcmp(cpChange, sText, sLength) == 0);
68 		REQUIRE(!cb.CanUndo());
69 		REQUIRE(!cb.CanRedo());
70 	}
71 
72 	SECTION("UndoRedo") {
73 		const char sTextDeleted[] = "ci";
74 		const char sTextAfterDeletion[] = "Sntilla";
75 		bool startSequence = false;
76 		const char *cpChange = cb.InsertString(0, sText, sLength, startSequence);
77 		REQUIRE(startSequence);
78 		REQUIRE(sLength == cb.Length());
79 		REQUIRE(memcmp(cpChange, sText, sLength) == 0);
80 		REQUIRE(memcmp(cb.BufferPointer(), sText, sLength) == 0);
81 		REQUIRE(cb.CanUndo());
82 		REQUIRE(!cb.CanRedo());
83 		const char *cpDeletion = cb.DeleteChars(1, 2, startSequence);
84 		REQUIRE(startSequence);
85 		REQUIRE(memcmp(cpDeletion, sTextDeleted, strlen(sTextDeleted)) == 0);
86 		REQUIRE(memcmp(cb.BufferPointer(), sTextAfterDeletion, strlen(sTextAfterDeletion)) == 0);
87 		REQUIRE(cb.CanUndo());
88 		REQUIRE(!cb.CanRedo());
89 
90 		int steps = cb.StartUndo();
91 		REQUIRE(steps == 1);
92 		cb.PerformUndoStep();
93 		REQUIRE(memcmp(cb.BufferPointer(), sText, sLength) == 0);
94 		REQUIRE(cb.CanUndo());
95 		REQUIRE(cb.CanRedo());
96 
97 		steps = cb.StartUndo();
98 		REQUIRE(steps == 1);
99 		cb.PerformUndoStep();
100 		REQUIRE(cb.Length() == 0);
101 		REQUIRE(!cb.CanUndo());
102 		REQUIRE(cb.CanRedo());
103 
104 		steps = cb.StartRedo();
105 		REQUIRE(steps == 1);
106 		cb.PerformRedoStep();
107 		REQUIRE(memcmp(cb.BufferPointer(), sText, sLength) == 0);
108 		REQUIRE(cb.CanUndo());
109 		REQUIRE(cb.CanRedo());
110 
111 		steps = cb.StartRedo();
112 		REQUIRE(steps == 1);
113 		cb.PerformRedoStep();
114 		REQUIRE(memcmp(cb.BufferPointer(), sTextAfterDeletion, strlen(sTextAfterDeletion)) == 0);
115 		REQUIRE(cb.CanUndo());
116 		REQUIRE(!cb.CanRedo());
117 
118 		cb.DeleteUndoHistory();
119 		REQUIRE(!cb.CanUndo());
120 		REQUIRE(!cb.CanRedo());
121 	}
122 
123 	SECTION("LineEndTypes") {
124 		REQUIRE(cb.GetLineEndTypes() == 0);
125 		cb.SetLineEndTypes(1);
126 		REQUIRE(cb.GetLineEndTypes() == 1);
127 		cb.SetLineEndTypes(0);
128 		REQUIRE(cb.GetLineEndTypes() == 0);
129 	}
130 
131 	SECTION("ReadOnly") {
132 		REQUIRE(!cb.IsReadOnly());
133 		cb.SetReadOnly(true);
134 		REQUIRE(cb.IsReadOnly());
135 		bool startSequence = false;
136 		cb.InsertString(0, sText, sLength, startSequence);
137 		REQUIRE(cb.Length() == 0);
138 	}
139 
140 }
141