]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/ViewStyle.cxx
a4894ef58bcb943e12d6719fcba7ecf72bcf1c2a
[wxWidgets.git] / src / stc / scintilla / src / ViewStyle.cxx
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.
7
8 #include <string.h>
9
10 #include <vector>
11 #include <map>
12
13 #include "Platform.h"
14
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"
24
25 #ifdef SCI_NAMESPACE
26 using namespace Scintilla;
27 #endif
28
29 MarginStyle::MarginStyle() :
30 style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
31 }
32
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;
38 }
39
40 FontNames::~FontNames() {
41 Clear();
42 delete []names;
43 names = 0;
44 }
45
46 void FontNames::Clear() {
47 for (int i=0; i<max; i++) {
48 delete []names[i];
49 }
50 max = 0;
51 }
52
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];
59 }
60 }
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];
67 }
68 delete []names;
69 names = namesNew;
70 size = sizeNew;
71 }
72 names[max] = new char[strlen(name) + 1];
73 strcpy(names[max], name);
74 max++;
75 return names[max-1];
76 }
77
78 FontRealised::FontRealised(const FontSpecification &fs) {
79 frNext = NULL;
80 (FontSpecification &)(*this) = fs;
81 }
82
83 FontRealised::~FontRealised() {
84 font.Release();
85 delete frNext;
86 frNext = 0;
87 }
88
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;
94
95 float deviceHeight = surface.DeviceHeightFont(sizeZoomed);
96 FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet);
97 font.Create(fp);
98
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);
105 }
106 }
107
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;
116 }
117 return 0;
118 }
119
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;
128 }
129 }
130
131 ViewStyle::ViewStyle() {
132 Init();
133 }
134
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);
142 }
143 for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
144 markers[mrk] = source.markers[mrk];
145 }
146 CalcLargestMarkerHeight();
147 for (int ind=0; ind<=INDIC_MAX; ind++) {
148 indicators[ind] = source.indicators[ind];
149 }
150
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;
161
162 foldmarginColourSet = source.foldmarginColourSet;
163 foldmarginColour = source.foldmarginColour;
164 foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
165 foldmarginHighlightColour = source.foldmarginHighlightColour;
166
167 hotspotForegroundSet = source.hotspotForegroundSet;
168 hotspotForeground = source.hotspotForeground;
169 hotspotBackgroundSet = source.hotspotBackgroundSet;
170 hotspotBackground = source.hotspotBackground;
171 hotspotUnderline = source.hotspotUnderline;
172 hotspotSingleLine = source.hotspotSingleLine;
173
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 caretLineBackground = source.caretLineBackground;
184 caretLineAlpha = source.caretLineAlpha;
185 edgecolour = source.edgecolour;
186 edgeState = source.edgeState;
187 caretStyle = source.caretStyle;
188 caretWidth = source.caretWidth;
189 someStylesProtected = false;
190 someStylesForceCase = false;
191 leftMarginWidth = source.leftMarginWidth;
192 rightMarginWidth = source.rightMarginWidth;
193 for (int i=0; i < margins; i++) {
194 ms[i] = source.ms[i];
195 }
196 maskInLine = source.maskInLine;
197 fixedColumnWidth = source.fixedColumnWidth;
198 zoomLevel = source.zoomLevel;
199 viewWhitespace = source.viewWhitespace;
200 whitespaceSize = source.whitespaceSize;
201 viewIndentationGuides = source.viewIndentationGuides;
202 viewEOL = source.viewEOL;
203 extraFontFlag = source.extraFontFlag;
204 extraAscent = source.extraAscent;
205 extraDescent = source.extraDescent;
206 marginStyleOffset = source.marginStyleOffset;
207 annotationVisible = source.annotationVisible;
208 annotationStyleOffset = source.annotationStyleOffset;
209 braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;
210 braceHighlightIndicator = source.braceHighlightIndicator;
211 braceBadLightIndicatorSet = source.braceBadLightIndicatorSet;
212 braceBadLightIndicator = source.braceBadLightIndicator;
213 }
214
215 ViewStyle::~ViewStyle() {
216 delete []styles;
217 styles = NULL;
218 delete frFirst;
219 frFirst = NULL;
220 }
221
222 void ViewStyle::Init(size_t stylesSize_) {
223 frFirst = NULL;
224 stylesSize = 0;
225 styles = NULL;
226 AllocStyles(stylesSize_);
227 fontNames.Clear();
228 ResetDefaultStyle();
229
230 // There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
231 largestMarkerHeight = 0;
232
233 indicators[0].style = INDIC_SQUIGGLE;
234 indicators[0].under = false;
235 indicators[0].fore = ColourDesired(0, 0x7f, 0);
236 indicators[1].style = INDIC_TT;
237 indicators[1].under = false;
238 indicators[1].fore = ColourDesired(0, 0, 0xff);
239 indicators[2].style = INDIC_PLAIN;
240 indicators[2].under = false;
241 indicators[2].fore = ColourDesired(0xff, 0, 0);
242
243 technology = SC_TECHNOLOGY_DEFAULT;
244 lineHeight = 1;
245 maxAscent = 1;
246 maxDescent = 1;
247 aveCharWidth = 8;
248 spaceWidth = 8;
249
250 selforeset = false;
251 selforeground = ColourDesired(0xff, 0, 0);
252 selAdditionalForeground = ColourDesired(0xff, 0, 0);
253 selbackset = true;
254 selbackground = ColourDesired(0xc0, 0xc0, 0xc0);
255 selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7);
256 selbackground2 = ColourDesired(0xb0, 0xb0, 0xb0);
257 selAlpha = SC_ALPHA_NOALPHA;
258 selAdditionalAlpha = SC_ALPHA_NOALPHA;
259 selEOLFilled = false;
260
261 foldmarginColourSet = false;
262 foldmarginColour = ColourDesired(0xff, 0, 0);
263 foldmarginHighlightColourSet = false;
264 foldmarginHighlightColour = ColourDesired(0xc0, 0xc0, 0xc0);
265
266 whitespaceForegroundSet = false;
267 whitespaceForeground = ColourDesired(0, 0, 0);
268 whitespaceBackgroundSet = false;
269 whitespaceBackground = ColourDesired(0xff, 0xff, 0xff);
270 selbar = Platform::Chrome();
271 selbarlight = Platform::ChromeHighlight();
272 styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0);
273 styles[STYLE_LINENUMBER].back = Platform::Chrome();
274 caretcolour = ColourDesired(0, 0, 0);
275 additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
276 showCaretLineBackground = false;
277 caretLineBackground = ColourDesired(0xff, 0xff, 0);
278 caretLineAlpha = SC_ALPHA_NOALPHA;
279 edgecolour = ColourDesired(0xc0, 0xc0, 0xc0);
280 edgeState = EDGE_NONE;
281 caretStyle = CARETSTYLE_LINE;
282 caretWidth = 1;
283 someStylesProtected = false;
284 someStylesForceCase = false;
285
286 hotspotForegroundSet = false;
287 hotspotForeground = ColourDesired(0, 0, 0xff);
288 hotspotBackgroundSet = false;
289 hotspotBackground = ColourDesired(0xff, 0xff, 0xff);
290 hotspotUnderline = true;
291 hotspotSingleLine = true;
292
293 leftMarginWidth = 1;
294 rightMarginWidth = 1;
295 ms[0].style = SC_MARGIN_NUMBER;
296 ms[0].width = 0;
297 ms[0].mask = 0;
298 ms[1].style = SC_MARGIN_SYMBOL;
299 ms[1].width = 16;
300 ms[1].mask = ~SC_MASK_FOLDERS;
301 ms[2].style = SC_MARGIN_SYMBOL;
302 ms[2].width = 0;
303 ms[2].mask = 0;
304 fixedColumnWidth = leftMarginWidth;
305 maskInLine = 0xffffffff;
306 for (int margin=0; margin < margins; margin++) {
307 fixedColumnWidth += ms[margin].width;
308 if (ms[margin].width > 0)
309 maskInLine &= ~ms[margin].mask;
310 }
311 zoomLevel = 0;
312 viewWhitespace = wsInvisible;
313 whitespaceSize = 1;
314 viewIndentationGuides = ivNone;
315 viewEOL = false;
316 extraFontFlag = 0;
317 extraAscent = 0;
318 extraDescent = 0;
319 marginStyleOffset = 0;
320 annotationVisible = ANNOTATION_HIDDEN;
321 annotationStyleOffset = 0;
322 braceHighlightIndicatorSet = false;
323 braceHighlightIndicator = 0;
324 braceBadLightIndicatorSet = false;
325 braceBadLightIndicator = 0;
326 }
327
328 void ViewStyle::CreateFont(const FontSpecification &fs) {
329 if (fs.fontName) {
330 for (FontRealised *cur=frFirst; cur; cur=cur->frNext) {
331 if (cur->EqualTo(fs))
332 return;
333 if (!cur->frNext) {
334 cur->frNext = new FontRealised(fs);
335 return;
336 }
337 }
338 frFirst = new FontRealised(fs);
339 }
340 }
341
342 void ViewStyle::Refresh(Surface &surface) {
343 delete frFirst;
344 frFirst = NULL;
345 selbar = Platform::Chrome();
346 selbarlight = Platform::ChromeHighlight();
347
348 for (unsigned int i=0; i<stylesSize; i++) {
349 styles[i].extraFontFlag = extraFontFlag;
350 }
351
352 CreateFont(styles[STYLE_DEFAULT]);
353 for (unsigned int j=0; j<stylesSize; j++) {
354 CreateFont(styles[j]);
355 }
356
357 frFirst->Realise(surface, zoomLevel, technology);
358
359 for (unsigned int k=0; k<stylesSize; k++) {
360 FontRealised *fr = frFirst->Find(styles[k]);
361 styles[k].Copy(fr->font, *fr);
362 }
363 maxAscent = 1;
364 maxDescent = 1;
365 frFirst->FindMaxAscentDescent(maxAscent, maxDescent);
366 maxAscent += extraAscent;
367 maxDescent += extraDescent;
368 lineHeight = maxAscent + maxDescent;
369
370 someStylesProtected = false;
371 someStylesForceCase = false;
372 for (unsigned int l=0; l<stylesSize; l++) {
373 if (styles[l].IsProtected()) {
374 someStylesProtected = true;
375 }
376 if (styles[l].caseForce != Style::caseMixed) {
377 someStylesForceCase = true;
378 }
379 }
380
381 aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
382 spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
383
384 fixedColumnWidth = leftMarginWidth;
385 maskInLine = 0xffffffff;
386 for (int margin=0; margin < margins; margin++) {
387 fixedColumnWidth += ms[margin].width;
388 if (ms[margin].width > 0)
389 maskInLine &= ~ms[margin].mask;
390 }
391 }
392
393 void ViewStyle::AllocStyles(size_t sizeNew) {
394 Style *stylesNew = new Style[sizeNew];
395 size_t i=0;
396 for (; i<stylesSize; i++) {
397 stylesNew[i] = styles[i];
398 stylesNew[i].fontName = styles[i].fontName;
399 }
400 if (stylesSize > STYLE_DEFAULT) {
401 for (; i<sizeNew; i++) {
402 if (i != STYLE_DEFAULT) {
403 stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
404 }
405 }
406 }
407 delete []styles;
408 styles = stylesNew;
409 stylesSize = sizeNew;
410 }
411
412 void ViewStyle::EnsureStyle(size_t index) {
413 if (index >= stylesSize) {
414 size_t sizeNew = stylesSize * 2;
415 while (sizeNew <= index)
416 sizeNew *= 2;
417 AllocStyles(sizeNew);
418 }
419 }
420
421 void ViewStyle::ResetDefaultStyle() {
422 styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
423 ColourDesired(0xff,0xff,0xff),
424 Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
425 SC_CHARSET_DEFAULT,
426 SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
427 }
428
429 void ViewStyle::ClearStyles() {
430 // Reset all styles to be like the default style
431 for (unsigned int i=0; i<stylesSize; i++) {
432 if (i != STYLE_DEFAULT) {
433 styles[i].ClearTo(styles[STYLE_DEFAULT]);
434 }
435 }
436 styles[STYLE_LINENUMBER].back = Platform::Chrome();
437
438 // Set call tip fore/back to match the values previously set for call tips
439 styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff);
440 styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80);
441 }
442
443 void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
444 styles[styleIndex].fontName = fontNames.Save(name);
445 }
446
447 bool ViewStyle::ProtectionActive() const {
448 return someStylesProtected;
449 }
450
451 bool ViewStyle::ValidStyle(size_t styleIndex) const {
452 return styleIndex < stylesSize;
453 }
454
455 void ViewStyle::CalcLargestMarkerHeight() {
456 largestMarkerHeight = 0;
457 for (int m = 0; m <= MARKER_MAX; ++m) {
458 switch (markers[m].markType) {
459 case SC_MARK_PIXMAP:
460 if (markers[m].pxpm->GetHeight() > largestMarkerHeight)
461 largestMarkerHeight = markers[m].pxpm->GetHeight();
462 break;
463 case SC_MARK_RGBAIMAGE:
464 if (markers[m].image->GetHeight() > largestMarkerHeight)
465 largestMarkerHeight = markers[m].image->GetHeight();
466 break;
467 }
468 }
469 }
470