1 // Scintilla source code edit control
2 /** @file ViewStyle.cxx
3 ** Store information on how the document is to be viewed.
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.
15 #include "Scintilla.h"
16 #include "SplitVector.h"
17 #include "Partitioning.h"
18 #include "RunStyles.h"
19 #include "Indicator.h"
21 #include "LineMarker.h"
23 #include "ViewStyle.h"
26 using namespace Scintilla
;
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() {
36 names
= new char *[size
];
40 FontNames::~FontNames() {
46 void FontNames::Clear() {
47 for (int i
=0; i
<max
; i
++) {
53 const char *FontNames::Save(const char *name
) {
56 for (int i
=0; i
<max
; i
++) {
57 if (strcmp(names
[i
], name
) == 0) {
63 int sizeNew
= size
* 2;
64 char **namesNew
= new char *[sizeNew
];
65 for (int j
=0; j
<max
; j
++) {
66 namesNew
[j
] = names
[j
];
72 names
[max
] = new char[strlen(name
) + 1];
73 strcpy(names
[max
], name
);
78 FontRealised::FontRealised(const FontSpecification
&fs
) {
80 (FontSpecification
&)(*this) = fs
;
83 FontRealised::~FontRealised() {
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
);
99 ascent
= surface
.Ascent(font
);
100 descent
= surface
.Descent(font
);
101 aveCharWidth
= surface
.AverageCharWidth(font
);
102 spaceWidth
= surface
.WidthChar(font
, ' ');
104 frNext
->Realise(surface
, zoomLevel
, technology
);
108 FontRealised
*FontRealised::Find(const FontSpecification
&fs
) {
111 FontRealised
*fr
= this;
120 void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent
, unsigned int &maxDescent
) {
121 FontRealised
*fr
= this;
123 if (maxAscent
< fr
->ascent
)
124 maxAscent
= fr
->ascent
;
125 if (maxDescent
< fr
->descent
)
126 maxDescent
= fr
->descent
;
131 ViewStyle::ViewStyle() {
135 ViewStyle::ViewStyle(const ViewStyle
&source
) {
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 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
];
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
;
215 ViewStyle::~ViewStyle() {
222 void ViewStyle::Init(size_t stylesSize_
) {
226 AllocStyles(stylesSize_
);
230 // There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
231 largestMarkerHeight
= 0;
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);
243 technology
= SC_TECHNOLOGY_DEFAULT
;
251 selforeground
= ColourDesired(0xff, 0, 0);
252 selAdditionalForeground
= ColourDesired(0xff, 0, 0);
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;
261 foldmarginColourSet
= false;
262 foldmarginColour
= ColourDesired(0xff, 0, 0);
263 foldmarginHighlightColourSet
= false;
264 foldmarginHighlightColour
= ColourDesired(0xc0, 0xc0, 0xc0);
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
;
283 someStylesProtected
= false;
284 someStylesForceCase
= false;
286 hotspotForegroundSet
= false;
287 hotspotForeground
= ColourDesired(0, 0, 0xff);
288 hotspotBackgroundSet
= false;
289 hotspotBackground
= ColourDesired(0xff, 0xff, 0xff);
290 hotspotUnderline
= true;
291 hotspotSingleLine
= true;
294 rightMarginWidth
= 1;
295 ms
[0].style
= SC_MARGIN_NUMBER
;
298 ms
[1].style
= SC_MARGIN_SYMBOL
;
300 ms
[1].mask
= ~SC_MASK_FOLDERS
;
301 ms
[2].style
= SC_MARGIN_SYMBOL
;
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
;
312 viewWhitespace
= wsInvisible
;
314 viewIndentationGuides
= ivNone
;
319 marginStyleOffset
= 0;
320 annotationVisible
= ANNOTATION_HIDDEN
;
321 annotationStyleOffset
= 0;
322 braceHighlightIndicatorSet
= false;
323 braceHighlightIndicator
= 0;
324 braceBadLightIndicatorSet
= false;
325 braceBadLightIndicator
= 0;
328 void ViewStyle::CreateFont(const FontSpecification
&fs
) {
330 for (FontRealised
*cur
=frFirst
; cur
; cur
=cur
->frNext
) {
331 if (cur
->EqualTo(fs
))
334 cur
->frNext
= new FontRealised(fs
);
338 frFirst
= new FontRealised(fs
);
342 void ViewStyle::Refresh(Surface
&surface
) {
345 selbar
= Platform::Chrome();
346 selbarlight
= Platform::ChromeHighlight();
348 for (unsigned int i
=0; i
<stylesSize
; i
++) {
349 styles
[i
].extraFontFlag
= extraFontFlag
;
352 CreateFont(styles
[STYLE_DEFAULT
]);
353 for (unsigned int j
=0; j
<stylesSize
; j
++) {
354 CreateFont(styles
[j
]);
357 frFirst
->Realise(surface
, zoomLevel
, technology
);
359 for (unsigned int k
=0; k
<stylesSize
; k
++) {
360 FontRealised
*fr
= frFirst
->Find(styles
[k
]);
361 styles
[k
].Copy(fr
->font
, *fr
);
365 frFirst
->FindMaxAscentDescent(maxAscent
, maxDescent
);
366 maxAscent
+= extraAscent
;
367 maxDescent
+= extraDescent
;
368 lineHeight
= maxAscent
+ maxDescent
;
370 someStylesProtected
= false;
371 someStylesForceCase
= false;
372 for (unsigned int l
=0; l
<stylesSize
; l
++) {
373 if (styles
[l
].IsProtected()) {
374 someStylesProtected
= true;
376 if (styles
[l
].caseForce
!= Style::caseMixed
) {
377 someStylesForceCase
= true;
381 aveCharWidth
= styles
[STYLE_DEFAULT
].aveCharWidth
;
382 spaceWidth
= styles
[STYLE_DEFAULT
].spaceWidth
;
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
;
393 void ViewStyle::AllocStyles(size_t sizeNew
) {
394 Style
*stylesNew
= new Style
[sizeNew
];
396 for (; i
<stylesSize
; i
++) {
397 stylesNew
[i
] = styles
[i
];
398 stylesNew
[i
].fontName
= styles
[i
].fontName
;
400 if (stylesSize
> STYLE_DEFAULT
) {
401 for (; i
<sizeNew
; i
++) {
402 if (i
!= STYLE_DEFAULT
) {
403 stylesNew
[i
].ClearTo(styles
[STYLE_DEFAULT
]);
409 stylesSize
= sizeNew
;
412 void ViewStyle::EnsureStyle(size_t index
) {
413 if (index
>= stylesSize
) {
414 size_t sizeNew
= stylesSize
* 2;
415 while (sizeNew
<= index
)
417 AllocStyles(sizeNew
);
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()),
426 SC_WEIGHT_NORMAL
, false, false, false, Style::caseMixed
, true, true, false);
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
]);
436 styles
[STYLE_LINENUMBER
].back
= Platform::Chrome();
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);
443 void ViewStyle::SetStyleFontName(int styleIndex
, const char *name
) {
444 styles
[styleIndex
].fontName
= fontNames
.Save(name
);
447 bool ViewStyle::ProtectionActive() const {
448 return someStylesProtected
;
451 bool ViewStyle::ValidStyle(size_t styleIndex
) const {
452 return styleIndex
< stylesSize
;
455 void ViewStyle::CalcLargestMarkerHeight() {
456 largestMarkerHeight
= 0;
457 for (int m
= 0; m
<= MARKER_MAX
; ++m
) {
458 switch (markers
[m
].markType
) {
460 if (markers
[m
].pxpm
->GetHeight() > largestMarkerHeight
)
461 largestMarkerHeight
= markers
[m
].pxpm
->GetHeight();
463 case SC_MARK_RGBAIMAGE
:
464 if (markers
[m
].image
->GetHeight() > largestMarkerHeight
)
465 largestMarkerHeight
= markers
[m
].image
->GetHeight();