OSDN Git Service

Commit DialogBox compile Okay
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / RunStyles.cxx
1 /** @file RunStyles.cxx\r
2  ** Data structure used to store sparse styles.\r
3  **/\r
4 // Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>\r
5 // The License.txt file describes the conditions under which this software may be distributed.\r
6 \r
7 #include <stdio.h>\r
8 #include <string.h>\r
9 #include <stdlib.h>\r
10 #include <stdarg.h>\r
11 \r
12 #include "Platform.h"\r
13 \r
14 #include "Scintilla.h"\r
15 #include "SplitVector.h"\r
16 #include "Partitioning.h"\r
17 #include "RunStyles.h"\r
18 \r
19 #ifdef SCI_NAMESPACE\r
20 using namespace Scintilla;\r
21 #endif\r
22 \r
23 // Find the first run at a position\r
24 int RunStyles::RunFromPosition(int position) {\r
25         int run = starts->PartitionFromPosition(position);\r
26         // Go to first element with this position\r
27         while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {\r
28                 run--;\r
29         }\r
30         return run;\r
31 }\r
32 \r
33 // If there is no run boundary at position, insert one continuing style.\r
34 int RunStyles::SplitRun(int position) {\r
35         int run = RunFromPosition(position);\r
36         int posRun = starts->PositionFromPartition(run);\r
37         if (posRun < position) {\r
38                 int runStyle = ValueAt(position);\r
39                 run++;\r
40                 starts->InsertPartition(run, position);\r
41                 styles->InsertValue(run, 1, runStyle);\r
42         }\r
43         return run;\r
44 }\r
45 \r
46 void RunStyles::RemoveRun(int run) {\r
47         starts->RemovePartition(run);\r
48         styles->DeleteRange(run, 1);\r
49 }\r
50 \r
51 void RunStyles::RemoveRunIfEmpty(int run) {\r
52         if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {\r
53                 if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {\r
54                         RemoveRun(run);\r
55                 }\r
56         }\r
57 }\r
58 \r
59 void RunStyles::RemoveRunIfSameAsPrevious(int run) {\r
60         if ((run > 0) && (run < starts->Partitions())) {\r
61                 if (styles->ValueAt(run-1) == styles->ValueAt(run)) {\r
62                         RemoveRun(run);\r
63                 }\r
64         }\r
65 }\r
66 \r
67 RunStyles::RunStyles() {\r
68         starts = new Partitioning(8);\r
69         styles = new SplitVector<int>();\r
70         styles->InsertValue(0, 2, 0);\r
71 }\r
72 \r
73 RunStyles::~RunStyles() {\r
74         delete starts;\r
75         starts = NULL;\r
76         delete styles;\r
77         styles = NULL;\r
78 }\r
79 \r
80 int RunStyles::Length() const {\r
81         return starts->PositionFromPartition(starts->Partitions());\r
82 }\r
83 \r
84 int RunStyles::ValueAt(int position) const {\r
85         return styles->ValueAt(starts->PartitionFromPosition(position));\r
86 }\r
87 \r
88 int RunStyles::FindNextChange(int position, int end) {\r
89         int run = starts->PartitionFromPosition(position);\r
90         if (run < starts->Partitions()) {\r
91                 int runChange = starts->PositionFromPartition(run);\r
92                 if (runChange > position)\r
93                         return runChange;\r
94                 int nextChange = starts->PositionFromPartition(run + 1);\r
95                 if (nextChange > position) {\r
96                         return nextChange;\r
97                 } else if (position < end) {\r
98                         return end;\r
99                 } else {\r
100                         return end + 1;\r
101                 }\r
102         } else {\r
103                 return end + 1;\r
104         }\r
105 }\r
106 \r
107 int RunStyles::StartRun(int position) {\r
108         return starts->PositionFromPartition(starts->PartitionFromPosition(position));\r
109 }\r
110 \r
111 int RunStyles::EndRun(int position) {\r
112         return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);\r
113 }\r
114 \r
115 bool RunStyles::FillRange(int &position, int value, int &fillLength) {\r
116         int end = position + fillLength;\r
117         int runEnd = RunFromPosition(end);\r
118         if (styles->ValueAt(runEnd) == value) {\r
119                 // End already has value so trim range.\r
120                 end = starts->PositionFromPartition(runEnd);\r
121                 if (position >= end) {\r
122                         // Whole range is already same as value so no action\r
123                         return false;\r
124                 }\r
125                 fillLength = end - position;\r
126         } else {\r
127                 runEnd = SplitRun(end);\r
128         }\r
129         int runStart = RunFromPosition(position);\r
130         if (styles->ValueAt(runStart) == value) {\r
131                 // Start is in expected value so trim range.\r
132                 runStart++;\r
133                 position = starts->PositionFromPartition(runStart);\r
134                 fillLength = end - position;\r
135         } else {\r
136                 if (starts->PositionFromPartition(runStart) < position) {\r
137                         runStart = SplitRun(position);\r
138                         runEnd++;\r
139                 }\r
140         }\r
141         if (runStart < runEnd) {\r
142                 styles->SetValueAt(runStart, value);\r
143                 // Remove each old run over the range\r
144                 for (int run=runStart+1; run<runEnd; run++) {\r
145                         RemoveRun(runStart+1);\r
146                 }\r
147                 runEnd = RunFromPosition(end);\r
148                 RemoveRunIfSameAsPrevious(runEnd);\r
149                 RemoveRunIfSameAsPrevious(runStart);\r
150         }\r
151         return true;\r
152 }\r
153 \r
154 void RunStyles::SetValueAt(int position, int value) {\r
155         int len = 1;\r
156         FillRange(position, value, len);\r
157 }\r
158 \r
159 void RunStyles::InsertSpace(int position, int insertLength) {\r
160         int runStart = RunFromPosition(position);\r
161         if (starts->PositionFromPartition(runStart) == position) {\r
162                 int runStyle = ValueAt(position);\r
163                 // Inserting at start of run so make previous longer\r
164                 if (runStart == 0) {\r
165                         // Inserting at start of document so ensure 0\r
166                         if (runStyle) {\r
167                                 styles->SetValueAt(0, 0);\r
168                                 starts->InsertPartition(1, 0);\r
169                                 styles->InsertValue(1, 1, runStyle);\r
170                                 starts->InsertText(0, insertLength);\r
171                         } else {\r
172                                 starts->InsertText(runStart, insertLength);\r
173                         }\r
174                 } else {\r
175                         if (runStyle) {\r
176                                 starts->InsertText(runStart-1, insertLength);\r
177                         } else {\r
178                                 // Insert at end of run so do not extend style\r
179                                 starts->InsertText(runStart, insertLength);\r
180                         }\r
181                 }\r
182         } else {\r
183                 starts->InsertText(runStart, insertLength);\r
184         }\r
185 }\r
186 \r
187 void RunStyles::DeleteAll() {\r
188         delete starts;\r
189         starts = NULL;\r
190         delete styles;\r
191         styles = NULL;\r
192         starts = new Partitioning(8);\r
193         styles = new SplitVector<int>();\r
194         styles->InsertValue(0, 2, 0);\r
195 }\r
196 \r
197 void RunStyles::DeleteRange(int position, int deleteLength) {\r
198         int end = position + deleteLength;\r
199         int runStart = RunFromPosition(position);\r
200         int runEnd = RunFromPosition(end);\r
201         if (runStart == runEnd) {\r
202                 // Deleting from inside one run\r
203                 starts->InsertText(runStart, -deleteLength);\r
204         } else {\r
205                 runStart = SplitRun(position);\r
206                 runEnd = SplitRun(end);\r
207                 starts->InsertText(runStart, -deleteLength);\r
208                 // Remove each old run over the range\r
209                 for (int run=runStart; run<runEnd; run++) {\r
210                         RemoveRun(runStart);\r
211                 }\r
212                 RemoveRunIfEmpty(runStart);\r
213                 RemoveRunIfSameAsPrevious(runStart);\r
214         }\r
215 }\r
216 \r