Minor Scintilla update to 3.2.4
[TortoiseGit.git] / ext / scintilla / src / ViewStyle.cxx
blobcdad26839025c79861177dbfcf88368886d58451
1 // Scintilla source code edit control
2 /** @file ViewStyle.cxx
3 ** Store information on how the document is to be viewed.
4 **/
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <string.h>
10 #include <vector>
11 #include <map>
13 #include "Platform.h"
15 #include "Scintilla.h"
16 #include "SplitVector.h"
17 #include "Partitioning.h"
18 #include "RunStyles.h"
19 #include "Indicator.h"
20 #include "XPM.h"
21 #include "LineMarker.h"
22 #include "Style.h"
23 #include "ViewStyle.h"
25 #ifdef SCI_NAMESPACE
26 using namespace Scintilla;
27 #endif
29 MarginStyle::MarginStyle() :
30 style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
33 // A list of the fontnames - avoids wasting space in each style
34 FontNames::FontNames() {
35 size = 8;
36 names = new char *[size];
37 max = 0;
40 FontNames::~FontNames() {
41 Clear();
42 delete []names;
43 names = 0;
46 void FontNames::Clear() {
47 for (int i=0; i<max; i++) {
48 delete []names[i];
50 max = 0;
53 const char *FontNames::Save(const char *name) {
54 if (!name)
55 return 0;
56 for (int i=0; i<max; i++) {
57 if (strcmp(names[i], name) == 0) {
58 return names[i];
61 if (max >= size) {
62 // Grow array
63 int sizeNew = size * 2;
64 char **namesNew = new char *[sizeNew];
65 for (int j=0; j<max; j++) {
66 namesNew[j] = names[j];
68 delete []names;
69 names = namesNew;
70 size = sizeNew;
72 names[max] = new char[strlen(name) + 1];
73 strcpy(names[max], name);
74 max++;
75 return names[max-1];
78 FontRealised::FontRealised(const FontSpecification &fs) {
79 frNext = NULL;
80 (FontSpecification &)(*this) = fs;
83 FontRealised::~FontRealised() {
84 font.Release();
85 delete frNext;
86 frNext = 0;
89 void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) {
90 PLATFORM_ASSERT(fontName);
91 sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
92 if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
93 sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
95 float deviceHeight = surface.DeviceHeightFont(sizeZoomed);
96 FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet);
97 font.Create(fp);
99 ascent = surface.Ascent(font);
100 descent = surface.Descent(font);
101 aveCharWidth = surface.AverageCharWidth(font);
102 spaceWidth = surface.WidthChar(font, ' ');
103 if (frNext) {
104 frNext->Realise(surface, zoomLevel, technology);
108 FontRealised *FontRealised::Find(const FontSpecification &fs) {
109 if (!fs.fontName)
110 return this;
111 FontRealised *fr = this;
112 while (fr) {
113 if (fr->EqualTo(fs))
114 return fr;
115 fr = fr->frNext;
117 return 0;
120 void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) {
121 FontRealised *fr = this;
122 while (fr) {
123 if (maxAscent < fr->ascent)
124 maxAscent = fr->ascent;
125 if (maxDescent < fr->descent)
126 maxDescent = fr->descent;
127 fr = fr->frNext;
131 ViewStyle::ViewStyle() {
132 Init();
135 ViewStyle::ViewStyle(const ViewStyle &source) {
136 frFirst = NULL;
137 Init(source.stylesSize);
138 for (unsigned int sty=0; sty<source.stylesSize; sty++) {
139 styles[sty] = source.styles[sty];
140 // Can't just copy fontname as its lifetime is relative to its owning ViewStyle
141 styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
143 for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
144 markers[mrk] = source.markers[mrk];
146 CalcLargestMarkerHeight();
147 for (int ind=0; ind<=INDIC_MAX; ind++) {
148 indicators[ind] = source.indicators[ind];
151 selforeset = source.selforeset;
152 selforeground = source.selforeground;
153 selAdditionalForeground = source.selAdditionalForeground;
154 selbackset = source.selbackset;
155 selbackground = source.selbackground;
156 selAdditionalBackground = source.selAdditionalBackground;
157 selbackground2 = source.selbackground2;
158 selAlpha = source.selAlpha;
159 selAdditionalAlpha = source.selAdditionalAlpha;
160 selEOLFilled = source.selEOLFilled;
162 foldmarginColourSet = source.foldmarginColourSet;
163 foldmarginColour = source.foldmarginColour;
164 foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
165 foldmarginHighlightColour = source.foldmarginHighlightColour;
167 hotspotForegroundSet = source.hotspotForegroundSet;
168 hotspotForeground = source.hotspotForeground;
169 hotspotBackgroundSet = source.hotspotBackgroundSet;
170 hotspotBackground = source.hotspotBackground;
171 hotspotUnderline = source.hotspotUnderline;
172 hotspotSingleLine = source.hotspotSingleLine;
174 whitespaceForegroundSet = source.whitespaceForegroundSet;
175 whitespaceForeground = source.whitespaceForeground;
176 whitespaceBackgroundSet = source.whitespaceBackgroundSet;
177 whitespaceBackground = source.whitespaceBackground;
178 selbar = source.selbar;
179 selbarlight = source.selbarlight;
180 caretcolour = source.caretcolour;
181 additionalCaretColour = source.additionalCaretColour;
182 showCaretLineBackground = source.showCaretLineBackground;
183 alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
184 caretLineBackground = source.caretLineBackground;
185 caretLineAlpha = source.caretLineAlpha;
186 edgecolour = source.edgecolour;
187 edgeState = source.edgeState;
188 caretStyle = source.caretStyle;
189 caretWidth = source.caretWidth;
190 someStylesProtected = false;
191 someStylesForceCase = false;
192 leftMarginWidth = source.leftMarginWidth;
193 rightMarginWidth = source.rightMarginWidth;
194 for (int i=0; i < margins; i++) {
195 ms[i] = source.ms[i];
197 maskInLine = source.maskInLine;
198 fixedColumnWidth = source.fixedColumnWidth;
199 zoomLevel = source.zoomLevel;
200 viewWhitespace = source.viewWhitespace;
201 whitespaceSize = source.whitespaceSize;
202 viewIndentationGuides = source.viewIndentationGuides;
203 viewEOL = source.viewEOL;
204 extraFontFlag = source.extraFontFlag;
205 extraAscent = source.extraAscent;
206 extraDescent = source.extraDescent;
207 marginStyleOffset = source.marginStyleOffset;
208 annotationVisible = source.annotationVisible;
209 annotationStyleOffset = source.annotationStyleOffset;
210 braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;
211 braceHighlightIndicator = source.braceHighlightIndicator;
212 braceBadLightIndicatorSet = source.braceBadLightIndicatorSet;
213 braceBadLightIndicator = source.braceBadLightIndicator;
216 ViewStyle::~ViewStyle() {
217 delete []styles;
218 styles = NULL;
219 delete frFirst;
220 frFirst = NULL;
223 void ViewStyle::Init(size_t stylesSize_) {
224 frFirst = NULL;
225 stylesSize = 0;
226 styles = NULL;
227 AllocStyles(stylesSize_);
228 fontNames.Clear();
229 ResetDefaultStyle();
231 // There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
232 largestMarkerHeight = 0;
234 indicators[0].style = INDIC_SQUIGGLE;
235 indicators[0].under = false;
236 indicators[0].fore = ColourDesired(0, 0x7f, 0);
237 indicators[1].style = INDIC_TT;
238 indicators[1].under = false;
239 indicators[1].fore = ColourDesired(0, 0, 0xff);
240 indicators[2].style = INDIC_PLAIN;
241 indicators[2].under = false;
242 indicators[2].fore = ColourDesired(0xff, 0, 0);
244 technology = SC_TECHNOLOGY_DEFAULT;
245 lineHeight = 1;
246 maxAscent = 1;
247 maxDescent = 1;
248 aveCharWidth = 8;
249 spaceWidth = 8;
251 selforeset = false;
252 selforeground = ColourDesired(0xff, 0, 0);
253 selAdditionalForeground = ColourDesired(0xff, 0, 0);
254 selbackset = true;
255 selbackground = ColourDesired(0xc0, 0xc0, 0xc0);
256 selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7);
257 selbackground2 = ColourDesired(0xb0, 0xb0, 0xb0);
258 selAlpha = SC_ALPHA_NOALPHA;
259 selAdditionalAlpha = SC_ALPHA_NOALPHA;
260 selEOLFilled = false;
262 foldmarginColourSet = false;
263 foldmarginColour = ColourDesired(0xff, 0, 0);
264 foldmarginHighlightColourSet = false;
265 foldmarginHighlightColour = ColourDesired(0xc0, 0xc0, 0xc0);
267 whitespaceForegroundSet = false;
268 whitespaceForeground = ColourDesired(0, 0, 0);
269 whitespaceBackgroundSet = false;
270 whitespaceBackground = ColourDesired(0xff, 0xff, 0xff);
271 selbar = Platform::Chrome();
272 selbarlight = Platform::ChromeHighlight();
273 styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0);
274 styles[STYLE_LINENUMBER].back = Platform::Chrome();
275 caretcolour = ColourDesired(0, 0, 0);
276 additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
277 showCaretLineBackground = false;
278 alwaysShowCaretLineBackground = false;
279 caretLineBackground = ColourDesired(0xff, 0xff, 0);
280 caretLineAlpha = SC_ALPHA_NOALPHA;
281 edgecolour = ColourDesired(0xc0, 0xc0, 0xc0);
282 edgeState = EDGE_NONE;
283 caretStyle = CARETSTYLE_LINE;
284 caretWidth = 1;
285 someStylesProtected = false;
286 someStylesForceCase = false;
288 hotspotForegroundSet = false;
289 hotspotForeground = ColourDesired(0, 0, 0xff);
290 hotspotBackgroundSet = false;
291 hotspotBackground = ColourDesired(0xff, 0xff, 0xff);
292 hotspotUnderline = true;
293 hotspotSingleLine = true;
295 leftMarginWidth = 1;
296 rightMarginWidth = 1;
297 ms[0].style = SC_MARGIN_NUMBER;
298 ms[0].width = 0;
299 ms[0].mask = 0;
300 ms[1].style = SC_MARGIN_SYMBOL;
301 ms[1].width = 16;
302 ms[1].mask = ~SC_MASK_FOLDERS;
303 ms[2].style = SC_MARGIN_SYMBOL;
304 ms[2].width = 0;
305 ms[2].mask = 0;
306 fixedColumnWidth = leftMarginWidth;
307 maskInLine = 0xffffffff;
308 for (int margin=0; margin < margins; margin++) {
309 fixedColumnWidth += ms[margin].width;
310 if (ms[margin].width > 0)
311 maskInLine &= ~ms[margin].mask;
313 zoomLevel = 0;
314 viewWhitespace = wsInvisible;
315 whitespaceSize = 1;
316 viewIndentationGuides = ivNone;
317 viewEOL = false;
318 extraFontFlag = 0;
319 extraAscent = 0;
320 extraDescent = 0;
321 marginStyleOffset = 0;
322 annotationVisible = ANNOTATION_HIDDEN;
323 annotationStyleOffset = 0;
324 braceHighlightIndicatorSet = false;
325 braceHighlightIndicator = 0;
326 braceBadLightIndicatorSet = false;
327 braceBadLightIndicator = 0;
330 void ViewStyle::CreateFont(const FontSpecification &fs) {
331 if (fs.fontName) {
332 for (FontRealised *cur=frFirst; cur; cur=cur->frNext) {
333 if (cur->EqualTo(fs))
334 return;
335 if (!cur->frNext) {
336 cur->frNext = new FontRealised(fs);
337 return;
340 frFirst = new FontRealised(fs);
344 void ViewStyle::Refresh(Surface &surface) {
345 delete frFirst;
346 frFirst = NULL;
347 selbar = Platform::Chrome();
348 selbarlight = Platform::ChromeHighlight();
350 for (unsigned int i=0; i<stylesSize; i++) {
351 styles[i].extraFontFlag = extraFontFlag;
354 CreateFont(styles[STYLE_DEFAULT]);
355 for (unsigned int j=0; j<stylesSize; j++) {
356 CreateFont(styles[j]);
359 frFirst->Realise(surface, zoomLevel, technology);
361 for (unsigned int k=0; k<stylesSize; k++) {
362 FontRealised *fr = frFirst->Find(styles[k]);
363 styles[k].Copy(fr->font, *fr);
365 maxAscent = 1;
366 maxDescent = 1;
367 frFirst->FindMaxAscentDescent(maxAscent, maxDescent);
368 maxAscent += extraAscent;
369 maxDescent += extraDescent;
370 lineHeight = maxAscent + maxDescent;
372 someStylesProtected = false;
373 someStylesForceCase = false;
374 for (unsigned int l=0; l<stylesSize; l++) {
375 if (styles[l].IsProtected()) {
376 someStylesProtected = true;
378 if (styles[l].caseForce != Style::caseMixed) {
379 someStylesForceCase = true;
383 aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
384 spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
386 fixedColumnWidth = leftMarginWidth;
387 maskInLine = 0xffffffff;
388 for (int margin=0; margin < margins; margin++) {
389 fixedColumnWidth += ms[margin].width;
390 if (ms[margin].width > 0)
391 maskInLine &= ~ms[margin].mask;
395 void ViewStyle::AllocStyles(size_t sizeNew) {
396 Style *stylesNew = new Style[sizeNew];
397 size_t i=0;
398 for (; i<stylesSize; i++) {
399 stylesNew[i] = styles[i];
400 stylesNew[i].fontName = styles[i].fontName;
402 if (stylesSize > STYLE_DEFAULT) {
403 for (; i<sizeNew; i++) {
404 if (i != STYLE_DEFAULT) {
405 stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
409 delete []styles;
410 styles = stylesNew;
411 stylesSize = sizeNew;
414 void ViewStyle::EnsureStyle(size_t index) {
415 if (index >= stylesSize) {
416 size_t sizeNew = stylesSize * 2;
417 while (sizeNew <= index)
418 sizeNew *= 2;
419 AllocStyles(sizeNew);
423 void ViewStyle::ResetDefaultStyle() {
424 styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
425 ColourDesired(0xff,0xff,0xff),
426 Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
427 SC_CHARSET_DEFAULT,
428 SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
431 void ViewStyle::ClearStyles() {
432 // Reset all styles to be like the default style
433 for (unsigned int i=0; i<stylesSize; i++) {
434 if (i != STYLE_DEFAULT) {
435 styles[i].ClearTo(styles[STYLE_DEFAULT]);
438 styles[STYLE_LINENUMBER].back = Platform::Chrome();
440 // Set call tip fore/back to match the values previously set for call tips
441 styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff);
442 styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80);
445 void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
446 styles[styleIndex].fontName = fontNames.Save(name);
449 bool ViewStyle::ProtectionActive() const {
450 return someStylesProtected;
453 bool ViewStyle::ValidStyle(size_t styleIndex) const {
454 return styleIndex < stylesSize;
457 void ViewStyle::CalcLargestMarkerHeight() {
458 largestMarkerHeight = 0;
459 for (int m = 0; m <= MARKER_MAX; ++m) {
460 switch (markers[m].markType) {
461 case SC_MARK_PIXMAP:
462 if (markers[m].pxpm->GetHeight() > largestMarkerHeight)
463 largestMarkerHeight = markers[m].pxpm->GetHeight();
464 break;
465 case SC_MARK_RGBAIMAGE:
466 if (markers[m].image->GetHeight() > largestMarkerHeight)
467 largestMarkerHeight = markers[m].image->GetHeight();
468 break;