1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file ViewStyle.cxx
3*8af74909SZhong Yang ** Store information on how the document is to be viewed.
4*8af74909SZhong Yang **/
5*8af74909SZhong Yang // Copyright 1998-2003 by Neil Hodgson <[email protected]>
6*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
7*8af74909SZhong Yang
8*8af74909SZhong Yang #include <cstddef>
9*8af74909SZhong Yang #include <cassert>
10*8af74909SZhong Yang #include <cstring>
11*8af74909SZhong Yang
12*8af74909SZhong Yang #include <stdexcept>
13*8af74909SZhong Yang #include <string_view>
14*8af74909SZhong Yang #include <vector>
15*8af74909SZhong Yang #include <map>
16*8af74909SZhong Yang #include <algorithm>
17*8af74909SZhong Yang #include <memory>
18*8af74909SZhong Yang
19*8af74909SZhong Yang #include "Platform.h"
20*8af74909SZhong Yang
21*8af74909SZhong Yang #include "Scintilla.h"
22*8af74909SZhong Yang #include "Position.h"
23*8af74909SZhong Yang #include "UniqueString.h"
24*8af74909SZhong Yang #include "Indicator.h"
25*8af74909SZhong Yang #include "XPM.h"
26*8af74909SZhong Yang #include "LineMarker.h"
27*8af74909SZhong Yang #include "Style.h"
28*8af74909SZhong Yang #include "ViewStyle.h"
29*8af74909SZhong Yang
30*8af74909SZhong Yang using namespace Scintilla;
31*8af74909SZhong Yang
MarginStyle(int style_,int width_,int mask_)32*8af74909SZhong Yang MarginStyle::MarginStyle(int style_, int width_, int mask_) noexcept :
33*8af74909SZhong Yang style(style_), width(width_), mask(mask_), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
34*8af74909SZhong Yang }
35*8af74909SZhong Yang
36*8af74909SZhong Yang FontRealised::FontRealised() noexcept = default;
37*8af74909SZhong Yang
~FontRealised()38*8af74909SZhong Yang FontRealised::~FontRealised() {
39*8af74909SZhong Yang font.Release();
40*8af74909SZhong Yang }
41*8af74909SZhong Yang
Realise(Surface & surface,int zoomLevel,int technology,const FontSpecification & fs)42*8af74909SZhong Yang void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) {
43*8af74909SZhong Yang PLATFORM_ASSERT(fs.fontName);
44*8af74909SZhong Yang sizeZoomed = fs.size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
45*8af74909SZhong Yang if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
46*8af74909SZhong Yang sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
47*8af74909SZhong Yang
48*8af74909SZhong Yang const float deviceHeight = static_cast<float>(surface.DeviceHeightFont(sizeZoomed));
49*8af74909SZhong Yang const FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet);
50*8af74909SZhong Yang font.Create(fp);
51*8af74909SZhong Yang
52*8af74909SZhong Yang ascent = static_cast<unsigned int>(surface.Ascent(font));
53*8af74909SZhong Yang descent = static_cast<unsigned int>(surface.Descent(font));
54*8af74909SZhong Yang capitalHeight = surface.Ascent(font) - surface.InternalLeading(font);
55*8af74909SZhong Yang aveCharWidth = surface.AverageCharWidth(font);
56*8af74909SZhong Yang spaceWidth = surface.WidthText(font, " ");
57*8af74909SZhong Yang }
58*8af74909SZhong Yang
ViewStyle()59*8af74909SZhong Yang ViewStyle::ViewStyle() : markers(MARKER_MAX + 1), indicators(INDICATOR_MAX + 1) {
60*8af74909SZhong Yang Init();
61*8af74909SZhong Yang }
62*8af74909SZhong Yang
63*8af74909SZhong Yang // Copy constructor only called when printing copies the screen ViewStyle so it can be
64*8af74909SZhong Yang // modified for printing styles.
ViewStyle(const ViewStyle & source)65*8af74909SZhong Yang ViewStyle::ViewStyle(const ViewStyle &source) : markers(MARKER_MAX + 1), indicators(INDICATOR_MAX + 1) {
66*8af74909SZhong Yang Init(source.styles.size());
67*8af74909SZhong Yang styles = source.styles;
68*8af74909SZhong Yang for (size_t sty=0; sty<source.styles.size(); sty++) {
69*8af74909SZhong Yang // Can't just copy fontName as its lifetime is relative to its owning ViewStyle
70*8af74909SZhong Yang styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
71*8af74909SZhong Yang }
72*8af74909SZhong Yang nextExtendedStyle = source.nextExtendedStyle;
73*8af74909SZhong Yang markers = source.markers;
74*8af74909SZhong Yang CalcLargestMarkerHeight();
75*8af74909SZhong Yang
76*8af74909SZhong Yang indicators = source.indicators;
77*8af74909SZhong Yang
78*8af74909SZhong Yang indicatorsDynamic = source.indicatorsDynamic;
79*8af74909SZhong Yang indicatorsSetFore = source.indicatorsSetFore;
80*8af74909SZhong Yang
81*8af74909SZhong Yang selColours = source.selColours;
82*8af74909SZhong Yang selAdditionalForeground = source.selAdditionalForeground;
83*8af74909SZhong Yang selAdditionalBackground = source.selAdditionalBackground;
84*8af74909SZhong Yang selBackground2 = source.selBackground2;
85*8af74909SZhong Yang selAlpha = source.selAlpha;
86*8af74909SZhong Yang selAdditionalAlpha = source.selAdditionalAlpha;
87*8af74909SZhong Yang selEOLFilled = source.selEOLFilled;
88*8af74909SZhong Yang
89*8af74909SZhong Yang foldmarginColour = source.foldmarginColour;
90*8af74909SZhong Yang foldmarginHighlightColour = source.foldmarginHighlightColour;
91*8af74909SZhong Yang
92*8af74909SZhong Yang hotspotColours = source.hotspotColours;
93*8af74909SZhong Yang hotspotUnderline = source.hotspotUnderline;
94*8af74909SZhong Yang hotspotSingleLine = source.hotspotSingleLine;
95*8af74909SZhong Yang
96*8af74909SZhong Yang whitespaceColours = source.whitespaceColours;
97*8af74909SZhong Yang controlCharSymbol = source.controlCharSymbol;
98*8af74909SZhong Yang controlCharWidth = source.controlCharWidth;
99*8af74909SZhong Yang selbar = source.selbar;
100*8af74909SZhong Yang selbarlight = source.selbarlight;
101*8af74909SZhong Yang caretcolour = source.caretcolour;
102*8af74909SZhong Yang additionalCaretColour = source.additionalCaretColour;
103*8af74909SZhong Yang caretLineFrame = source.caretLineFrame;
104*8af74909SZhong Yang showCaretLineBackground = source.showCaretLineBackground;
105*8af74909SZhong Yang alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
106*8af74909SZhong Yang caretLineBackground = source.caretLineBackground;
107*8af74909SZhong Yang caretLineAlpha = source.caretLineAlpha;
108*8af74909SZhong Yang caretStyle = source.caretStyle;
109*8af74909SZhong Yang caretWidth = source.caretWidth;
110*8af74909SZhong Yang someStylesProtected = false;
111*8af74909SZhong Yang someStylesForceCase = false;
112*8af74909SZhong Yang leftMarginWidth = source.leftMarginWidth;
113*8af74909SZhong Yang rightMarginWidth = source.rightMarginWidth;
114*8af74909SZhong Yang ms = source.ms;
115*8af74909SZhong Yang maskInLine = source.maskInLine;
116*8af74909SZhong Yang maskDrawInText = source.maskDrawInText;
117*8af74909SZhong Yang fixedColumnWidth = source.fixedColumnWidth;
118*8af74909SZhong Yang marginInside = source.marginInside;
119*8af74909SZhong Yang textStart = source.textStart;
120*8af74909SZhong Yang zoomLevel = source.zoomLevel;
121*8af74909SZhong Yang viewWhitespace = source.viewWhitespace;
122*8af74909SZhong Yang tabDrawMode = source.tabDrawMode;
123*8af74909SZhong Yang whitespaceSize = source.whitespaceSize;
124*8af74909SZhong Yang viewIndentationGuides = source.viewIndentationGuides;
125*8af74909SZhong Yang viewEOL = source.viewEOL;
126*8af74909SZhong Yang extraFontFlag = source.extraFontFlag;
127*8af74909SZhong Yang extraAscent = source.extraAscent;
128*8af74909SZhong Yang extraDescent = source.extraDescent;
129*8af74909SZhong Yang marginStyleOffset = source.marginStyleOffset;
130*8af74909SZhong Yang annotationVisible = source.annotationVisible;
131*8af74909SZhong Yang annotationStyleOffset = source.annotationStyleOffset;
132*8af74909SZhong Yang eolAnnotationVisible = source.eolAnnotationVisible;
133*8af74909SZhong Yang eolAnnotationStyleOffset = source.eolAnnotationStyleOffset;
134*8af74909SZhong Yang braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;
135*8af74909SZhong Yang braceHighlightIndicator = source.braceHighlightIndicator;
136*8af74909SZhong Yang braceBadLightIndicatorSet = source.braceBadLightIndicatorSet;
137*8af74909SZhong Yang braceBadLightIndicator = source.braceBadLightIndicator;
138*8af74909SZhong Yang
139*8af74909SZhong Yang edgeState = source.edgeState;
140*8af74909SZhong Yang theEdge = source.theEdge;
141*8af74909SZhong Yang theMultiEdge = source.theMultiEdge;
142*8af74909SZhong Yang
143*8af74909SZhong Yang marginNumberPadding = source.marginNumberPadding;
144*8af74909SZhong Yang ctrlCharPadding = source.ctrlCharPadding;
145*8af74909SZhong Yang lastSegItalicsOffset = source.lastSegItalicsOffset;
146*8af74909SZhong Yang
147*8af74909SZhong Yang wrapState = source.wrapState;
148*8af74909SZhong Yang wrapVisualFlags = source.wrapVisualFlags;
149*8af74909SZhong Yang wrapVisualFlagsLocation = source.wrapVisualFlagsLocation;
150*8af74909SZhong Yang wrapVisualStartIndent = source.wrapVisualStartIndent;
151*8af74909SZhong Yang wrapIndentMode = source.wrapIndentMode;
152*8af74909SZhong Yang }
153*8af74909SZhong Yang
~ViewStyle()154*8af74909SZhong Yang ViewStyle::~ViewStyle() {
155*8af74909SZhong Yang styles.clear();
156*8af74909SZhong Yang fonts.clear();
157*8af74909SZhong Yang }
158*8af74909SZhong Yang
CalculateMarginWidthAndMask()159*8af74909SZhong Yang void ViewStyle::CalculateMarginWidthAndMask() noexcept {
160*8af74909SZhong Yang fixedColumnWidth = marginInside ? leftMarginWidth : 0;
161*8af74909SZhong Yang maskInLine = 0xffffffff;
162*8af74909SZhong Yang int maskDefinedMarkers = 0;
163*8af74909SZhong Yang for (const MarginStyle &m : ms) {
164*8af74909SZhong Yang fixedColumnWidth += m.width;
165*8af74909SZhong Yang if (m.width > 0)
166*8af74909SZhong Yang maskInLine &= ~m.mask;
167*8af74909SZhong Yang maskDefinedMarkers |= m.mask;
168*8af74909SZhong Yang }
169*8af74909SZhong Yang maskDrawInText = 0;
170*8af74909SZhong Yang for (int markBit = 0; markBit < 32; markBit++) {
171*8af74909SZhong Yang const int maskBit = 1U << markBit;
172*8af74909SZhong Yang switch (markers[markBit].markType) {
173*8af74909SZhong Yang case SC_MARK_EMPTY:
174*8af74909SZhong Yang maskInLine &= ~maskBit;
175*8af74909SZhong Yang break;
176*8af74909SZhong Yang case SC_MARK_BACKGROUND:
177*8af74909SZhong Yang case SC_MARK_UNDERLINE:
178*8af74909SZhong Yang maskInLine &= ~maskBit;
179*8af74909SZhong Yang maskDrawInText |= maskDefinedMarkers & maskBit;
180*8af74909SZhong Yang break;
181*8af74909SZhong Yang }
182*8af74909SZhong Yang }
183*8af74909SZhong Yang }
184*8af74909SZhong Yang
Init(size_t stylesSize_)185*8af74909SZhong Yang void ViewStyle::Init(size_t stylesSize_) {
186*8af74909SZhong Yang AllocStyles(stylesSize_);
187*8af74909SZhong Yang nextExtendedStyle = 256;
188*8af74909SZhong Yang fontNames.Clear();
189*8af74909SZhong Yang ResetDefaultStyle();
190*8af74909SZhong Yang
191*8af74909SZhong Yang // There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
192*8af74909SZhong Yang largestMarkerHeight = 0;
193*8af74909SZhong Yang
194*8af74909SZhong Yang indicators[0] = Indicator(INDIC_SQUIGGLE, ColourDesired(0, 0x7f, 0));
195*8af74909SZhong Yang indicators[1] = Indicator(INDIC_TT, ColourDesired(0, 0, 0xff));
196*8af74909SZhong Yang indicators[2] = Indicator(INDIC_PLAIN, ColourDesired(0xff, 0, 0));
197*8af74909SZhong Yang
198*8af74909SZhong Yang technology = SC_TECHNOLOGY_DEFAULT;
199*8af74909SZhong Yang indicatorsDynamic = false;
200*8af74909SZhong Yang indicatorsSetFore = false;
201*8af74909SZhong Yang lineHeight = 1;
202*8af74909SZhong Yang lineOverlap = 0;
203*8af74909SZhong Yang maxAscent = 1;
204*8af74909SZhong Yang maxDescent = 1;
205*8af74909SZhong Yang aveCharWidth = 8;
206*8af74909SZhong Yang spaceWidth = 8;
207*8af74909SZhong Yang tabWidth = spaceWidth * 8;
208*8af74909SZhong Yang
209*8af74909SZhong Yang selColours.fore = ColourOptional(ColourDesired(0xff, 0, 0));
210*8af74909SZhong Yang selColours.back = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0), true);
211*8af74909SZhong Yang selAdditionalForeground = ColourDesired(0xff, 0, 0);
212*8af74909SZhong Yang selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7);
213*8af74909SZhong Yang selBackground2 = ColourDesired(0xb0, 0xb0, 0xb0);
214*8af74909SZhong Yang selAlpha = SC_ALPHA_NOALPHA;
215*8af74909SZhong Yang selAdditionalAlpha = SC_ALPHA_NOALPHA;
216*8af74909SZhong Yang selEOLFilled = false;
217*8af74909SZhong Yang
218*8af74909SZhong Yang foldmarginColour = ColourOptional(ColourDesired(0xff, 0, 0));
219*8af74909SZhong Yang foldmarginHighlightColour = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0));
220*8af74909SZhong Yang
221*8af74909SZhong Yang whitespaceColours.fore = ColourOptional();
222*8af74909SZhong Yang whitespaceColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff));
223*8af74909SZhong Yang controlCharSymbol = 0; /* Draw the control characters */
224*8af74909SZhong Yang controlCharWidth = 0;
225*8af74909SZhong Yang selbar = Platform::Chrome();
226*8af74909SZhong Yang selbarlight = Platform::ChromeHighlight();
227*8af74909SZhong Yang styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0);
228*8af74909SZhong Yang styles[STYLE_LINENUMBER].back = Platform::Chrome();
229*8af74909SZhong Yang caretcolour = ColourDesired(0, 0, 0);
230*8af74909SZhong Yang additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
231*8af74909SZhong Yang caretLineFrame = 0;
232*8af74909SZhong Yang showCaretLineBackground = false;
233*8af74909SZhong Yang alwaysShowCaretLineBackground = false;
234*8af74909SZhong Yang caretLineBackground = ColourDesired(0xff, 0xff, 0);
235*8af74909SZhong Yang caretLineAlpha = SC_ALPHA_NOALPHA;
236*8af74909SZhong Yang caretStyle = CARETSTYLE_LINE;
237*8af74909SZhong Yang caretWidth = 1;
238*8af74909SZhong Yang someStylesProtected = false;
239*8af74909SZhong Yang someStylesForceCase = false;
240*8af74909SZhong Yang
241*8af74909SZhong Yang hotspotColours.fore = ColourOptional(ColourDesired(0, 0, 0xff));
242*8af74909SZhong Yang hotspotColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff));
243*8af74909SZhong Yang hotspotUnderline = true;
244*8af74909SZhong Yang hotspotSingleLine = true;
245*8af74909SZhong Yang
246*8af74909SZhong Yang leftMarginWidth = 1;
247*8af74909SZhong Yang rightMarginWidth = 1;
248*8af74909SZhong Yang ms.resize(SC_MAX_MARGIN + 1);
249*8af74909SZhong Yang ms[0] = MarginStyle(SC_MARGIN_NUMBER);
250*8af74909SZhong Yang ms[1] = MarginStyle(SC_MARGIN_SYMBOL, 16, ~SC_MASK_FOLDERS);
251*8af74909SZhong Yang ms[2] = MarginStyle(SC_MARGIN_SYMBOL);
252*8af74909SZhong Yang marginInside = true;
253*8af74909SZhong Yang CalculateMarginWidthAndMask();
254*8af74909SZhong Yang textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
255*8af74909SZhong Yang zoomLevel = 0;
256*8af74909SZhong Yang viewWhitespace = wsInvisible;
257*8af74909SZhong Yang tabDrawMode = tdLongArrow;
258*8af74909SZhong Yang whitespaceSize = 1;
259*8af74909SZhong Yang viewIndentationGuides = ivNone;
260*8af74909SZhong Yang viewEOL = false;
261*8af74909SZhong Yang extraFontFlag = 0;
262*8af74909SZhong Yang extraAscent = 0;
263*8af74909SZhong Yang extraDescent = 0;
264*8af74909SZhong Yang marginStyleOffset = 0;
265*8af74909SZhong Yang annotationVisible = ANNOTATION_HIDDEN;
266*8af74909SZhong Yang annotationStyleOffset = 0;
267*8af74909SZhong Yang eolAnnotationVisible = EOLANNOTATION_HIDDEN;
268*8af74909SZhong Yang eolAnnotationStyleOffset = 0;
269*8af74909SZhong Yang braceHighlightIndicatorSet = false;
270*8af74909SZhong Yang braceHighlightIndicator = 0;
271*8af74909SZhong Yang braceBadLightIndicatorSet = false;
272*8af74909SZhong Yang braceBadLightIndicator = 0;
273*8af74909SZhong Yang
274*8af74909SZhong Yang edgeState = EDGE_NONE;
275*8af74909SZhong Yang theEdge = EdgeProperties(0, ColourDesired(0xc0, 0xc0, 0xc0));
276*8af74909SZhong Yang
277*8af74909SZhong Yang marginNumberPadding = 3;
278*8af74909SZhong Yang ctrlCharPadding = 3; // +3 For a blank on front and rounded edge each side
279*8af74909SZhong Yang lastSegItalicsOffset = 2;
280*8af74909SZhong Yang
281*8af74909SZhong Yang wrapState = WrapMode::none;
282*8af74909SZhong Yang wrapVisualFlags = 0;
283*8af74909SZhong Yang wrapVisualFlagsLocation = 0;
284*8af74909SZhong Yang wrapVisualStartIndent = 0;
285*8af74909SZhong Yang wrapIndentMode = SC_WRAPINDENT_FIXED;
286*8af74909SZhong Yang }
287*8af74909SZhong Yang
Refresh(Surface & surface,int tabInChars)288*8af74909SZhong Yang void ViewStyle::Refresh(Surface &surface, int tabInChars) {
289*8af74909SZhong Yang fonts.clear();
290*8af74909SZhong Yang
291*8af74909SZhong Yang selbar = Platform::Chrome();
292*8af74909SZhong Yang selbarlight = Platform::ChromeHighlight();
293*8af74909SZhong Yang
294*8af74909SZhong Yang // Apply the extra font flag which controls text drawing quality to each style.
295*8af74909SZhong Yang for (Style &style : styles) {
296*8af74909SZhong Yang style.extraFontFlag = extraFontFlag;
297*8af74909SZhong Yang }
298*8af74909SZhong Yang
299*8af74909SZhong Yang // Create a FontRealised object for each unique font in the styles.
300*8af74909SZhong Yang CreateAndAddFont(styles[STYLE_DEFAULT]);
301*8af74909SZhong Yang for (const Style &style : styles) {
302*8af74909SZhong Yang CreateAndAddFont(style);
303*8af74909SZhong Yang }
304*8af74909SZhong Yang
305*8af74909SZhong Yang // Ask platform to allocate each unique font.
306*8af74909SZhong Yang for (std::pair<const FontSpecification, std::unique_ptr<FontRealised>> &font : fonts) {
307*8af74909SZhong Yang font.second->Realise(surface, zoomLevel, technology, font.first);
308*8af74909SZhong Yang }
309*8af74909SZhong Yang
310*8af74909SZhong Yang // Set the platform font handle and measurements for each style.
311*8af74909SZhong Yang for (Style &style : styles) {
312*8af74909SZhong Yang FontRealised *fr = Find(style);
313*8af74909SZhong Yang style.Copy(fr->font, *fr);
314*8af74909SZhong Yang }
315*8af74909SZhong Yang
316*8af74909SZhong Yang indicatorsDynamic = std::any_of(indicators.cbegin(), indicators.cend(),
317*8af74909SZhong Yang [](const Indicator &indicator) noexcept { return indicator.IsDynamic(); });
318*8af74909SZhong Yang
319*8af74909SZhong Yang indicatorsSetFore = std::any_of(indicators.cbegin(), indicators.cend(),
320*8af74909SZhong Yang [](const Indicator &indicator) noexcept { return indicator.OverridesTextFore(); });
321*8af74909SZhong Yang
322*8af74909SZhong Yang maxAscent = 1;
323*8af74909SZhong Yang maxDescent = 1;
324*8af74909SZhong Yang FindMaxAscentDescent();
325*8af74909SZhong Yang maxAscent += extraAscent;
326*8af74909SZhong Yang maxDescent += extraDescent;
327*8af74909SZhong Yang lineHeight = maxAscent + maxDescent;
328*8af74909SZhong Yang lineOverlap = lineHeight / 10;
329*8af74909SZhong Yang if (lineOverlap < 2)
330*8af74909SZhong Yang lineOverlap = 2;
331*8af74909SZhong Yang if (lineOverlap > lineHeight)
332*8af74909SZhong Yang lineOverlap = lineHeight;
333*8af74909SZhong Yang
334*8af74909SZhong Yang someStylesProtected = std::any_of(styles.cbegin(), styles.cend(),
335*8af74909SZhong Yang [](const Style &style) noexcept { return style.IsProtected(); });
336*8af74909SZhong Yang
337*8af74909SZhong Yang someStylesForceCase = std::any_of(styles.cbegin(), styles.cend(),
338*8af74909SZhong Yang [](const Style &style) noexcept { return style.caseForce != Style::caseMixed; });
339*8af74909SZhong Yang
340*8af74909SZhong Yang aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
341*8af74909SZhong Yang spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
342*8af74909SZhong Yang tabWidth = spaceWidth * tabInChars;
343*8af74909SZhong Yang
344*8af74909SZhong Yang controlCharWidth = 0.0;
345*8af74909SZhong Yang if (controlCharSymbol >= 32) {
346*8af74909SZhong Yang const char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
347*8af74909SZhong Yang controlCharWidth = surface.WidthText(styles[STYLE_CONTROLCHAR].font, cc);
348*8af74909SZhong Yang }
349*8af74909SZhong Yang
350*8af74909SZhong Yang CalculateMarginWidthAndMask();
351*8af74909SZhong Yang textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
352*8af74909SZhong Yang }
353*8af74909SZhong Yang
ReleaseAllExtendedStyles()354*8af74909SZhong Yang void ViewStyle::ReleaseAllExtendedStyles() noexcept {
355*8af74909SZhong Yang nextExtendedStyle = 256;
356*8af74909SZhong Yang }
357*8af74909SZhong Yang
AllocateExtendedStyles(int numberStyles)358*8af74909SZhong Yang int ViewStyle::AllocateExtendedStyles(int numberStyles) {
359*8af74909SZhong Yang const int startRange = nextExtendedStyle;
360*8af74909SZhong Yang nextExtendedStyle += numberStyles;
361*8af74909SZhong Yang EnsureStyle(nextExtendedStyle);
362*8af74909SZhong Yang for (int i=startRange; i<nextExtendedStyle; i++) {
363*8af74909SZhong Yang styles[i].ClearTo(styles[STYLE_DEFAULT]);
364*8af74909SZhong Yang }
365*8af74909SZhong Yang return startRange;
366*8af74909SZhong Yang }
367*8af74909SZhong Yang
EnsureStyle(size_t index)368*8af74909SZhong Yang void ViewStyle::EnsureStyle(size_t index) {
369*8af74909SZhong Yang if (index >= styles.size()) {
370*8af74909SZhong Yang AllocStyles(index+1);
371*8af74909SZhong Yang }
372*8af74909SZhong Yang }
373*8af74909SZhong Yang
ResetDefaultStyle()374*8af74909SZhong Yang void ViewStyle::ResetDefaultStyle() {
375*8af74909SZhong Yang styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
376*8af74909SZhong Yang ColourDesired(0xff,0xff,0xff),
377*8af74909SZhong Yang Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
378*8af74909SZhong Yang SC_CHARSET_DEFAULT,
379*8af74909SZhong Yang SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
380*8af74909SZhong Yang }
381*8af74909SZhong Yang
ClearStyles()382*8af74909SZhong Yang void ViewStyle::ClearStyles() {
383*8af74909SZhong Yang // Reset all styles to be like the default style
384*8af74909SZhong Yang for (size_t i=0; i<styles.size(); i++) {
385*8af74909SZhong Yang if (i != STYLE_DEFAULT) {
386*8af74909SZhong Yang styles[i].ClearTo(styles[STYLE_DEFAULT]);
387*8af74909SZhong Yang }
388*8af74909SZhong Yang }
389*8af74909SZhong Yang styles[STYLE_LINENUMBER].back = Platform::Chrome();
390*8af74909SZhong Yang
391*8af74909SZhong Yang // Set call tip fore/back to match the values previously set for call tips
392*8af74909SZhong Yang styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff);
393*8af74909SZhong Yang styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80);
394*8af74909SZhong Yang }
395*8af74909SZhong Yang
SetStyleFontName(int styleIndex,const char * name)396*8af74909SZhong Yang void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
397*8af74909SZhong Yang styles[styleIndex].fontName = fontNames.Save(name);
398*8af74909SZhong Yang }
399*8af74909SZhong Yang
ProtectionActive() const400*8af74909SZhong Yang bool ViewStyle::ProtectionActive() const noexcept {
401*8af74909SZhong Yang return someStylesProtected;
402*8af74909SZhong Yang }
403*8af74909SZhong Yang
ExternalMarginWidth() const404*8af74909SZhong Yang int ViewStyle::ExternalMarginWidth() const noexcept {
405*8af74909SZhong Yang return marginInside ? 0 : fixedColumnWidth;
406*8af74909SZhong Yang }
407*8af74909SZhong Yang
MarginFromLocation(Point pt) const408*8af74909SZhong Yang int ViewStyle::MarginFromLocation(Point pt) const noexcept {
409*8af74909SZhong Yang int margin = -1;
410*8af74909SZhong Yang int x = marginInside ? 0 : -fixedColumnWidth;
411*8af74909SZhong Yang for (size_t i = 0; i < ms.size(); i++) {
412*8af74909SZhong Yang if ((pt.x >= x) && (pt.x < x + ms[i].width))
413*8af74909SZhong Yang margin = static_cast<int>(i);
414*8af74909SZhong Yang x += ms[i].width;
415*8af74909SZhong Yang }
416*8af74909SZhong Yang return margin;
417*8af74909SZhong Yang }
418*8af74909SZhong Yang
ValidStyle(size_t styleIndex) const419*8af74909SZhong Yang bool ViewStyle::ValidStyle(size_t styleIndex) const noexcept {
420*8af74909SZhong Yang return styleIndex < styles.size();
421*8af74909SZhong Yang }
422*8af74909SZhong Yang
CalcLargestMarkerHeight()423*8af74909SZhong Yang void ViewStyle::CalcLargestMarkerHeight() noexcept {
424*8af74909SZhong Yang largestMarkerHeight = 0;
425*8af74909SZhong Yang for (const LineMarker &marker : markers) {
426*8af74909SZhong Yang switch (marker.markType) {
427*8af74909SZhong Yang case SC_MARK_PIXMAP:
428*8af74909SZhong Yang if (marker.pxpm && marker.pxpm->GetHeight() > largestMarkerHeight)
429*8af74909SZhong Yang largestMarkerHeight = marker.pxpm->GetHeight();
430*8af74909SZhong Yang break;
431*8af74909SZhong Yang case SC_MARK_RGBAIMAGE:
432*8af74909SZhong Yang if (marker.image && marker.image->GetHeight() > largestMarkerHeight)
433*8af74909SZhong Yang largestMarkerHeight = marker.image->GetHeight();
434*8af74909SZhong Yang break;
435*8af74909SZhong Yang }
436*8af74909SZhong Yang }
437*8af74909SZhong Yang }
438*8af74909SZhong Yang
GetFrameWidth() const439*8af74909SZhong Yang int ViewStyle::GetFrameWidth() const noexcept {
440*8af74909SZhong Yang return std::clamp(caretLineFrame, 1, lineHeight / 3);
441*8af74909SZhong Yang }
442*8af74909SZhong Yang
IsLineFrameOpaque(bool caretActive,bool lineContainsCaret) const443*8af74909SZhong Yang bool ViewStyle::IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const noexcept {
444*8af74909SZhong Yang return caretLineFrame && (caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground &&
445*8af74909SZhong Yang (caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret;
446*8af74909SZhong Yang }
447*8af74909SZhong Yang
448*8af74909SZhong Yang // See if something overrides the line background colour: Either if caret is on the line
449*8af74909SZhong Yang // and background colour is set for that, or if a marker is defined that forces its background
450*8af74909SZhong Yang // colour onto the line, or if a marker is defined but has no selection margin in which to
451*8af74909SZhong Yang // display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order
452*8af74909SZhong Yang // with the earlier taking precedence. When multiple markers cause background override,
453*8af74909SZhong Yang // the colour for the highest numbered one is used.
Background(int marksOfLine,bool caretActive,bool lineContainsCaret) const454*8af74909SZhong Yang ColourOptional ViewStyle::Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const noexcept {
455*8af74909SZhong Yang ColourOptional background;
456*8af74909SZhong Yang if (!caretLineFrame && (caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground &&
457*8af74909SZhong Yang (caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret) {
458*8af74909SZhong Yang background = ColourOptional(caretLineBackground, true);
459*8af74909SZhong Yang }
460*8af74909SZhong Yang if (!background.isSet && marksOfLine) {
461*8af74909SZhong Yang int marks = marksOfLine;
462*8af74909SZhong Yang for (int markBit = 0; (markBit < 32) && marks; markBit++) {
463*8af74909SZhong Yang if ((marks & 1) && (markers[markBit].markType == SC_MARK_BACKGROUND) &&
464*8af74909SZhong Yang (markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
465*8af74909SZhong Yang background = ColourOptional(markers[markBit].back, true);
466*8af74909SZhong Yang }
467*8af74909SZhong Yang marks >>= 1;
468*8af74909SZhong Yang }
469*8af74909SZhong Yang }
470*8af74909SZhong Yang if (!background.isSet && maskInLine) {
471*8af74909SZhong Yang int marksMasked = marksOfLine & maskInLine;
472*8af74909SZhong Yang if (marksMasked) {
473*8af74909SZhong Yang for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
474*8af74909SZhong Yang if ((marksMasked & 1) &&
475*8af74909SZhong Yang (markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
476*8af74909SZhong Yang background = ColourOptional(markers[markBit].back, true);
477*8af74909SZhong Yang }
478*8af74909SZhong Yang marksMasked >>= 1;
479*8af74909SZhong Yang }
480*8af74909SZhong Yang }
481*8af74909SZhong Yang }
482*8af74909SZhong Yang return background;
483*8af74909SZhong Yang }
484*8af74909SZhong Yang
SelectionBackgroundDrawn() const485*8af74909SZhong Yang bool ViewStyle::SelectionBackgroundDrawn() const noexcept {
486*8af74909SZhong Yang return selColours.back.isSet &&
487*8af74909SZhong Yang ((selAlpha == SC_ALPHA_NOALPHA) || (selAdditionalAlpha == SC_ALPHA_NOALPHA));
488*8af74909SZhong Yang }
489*8af74909SZhong Yang
WhitespaceBackgroundDrawn() const490*8af74909SZhong Yang bool ViewStyle::WhitespaceBackgroundDrawn() const noexcept {
491*8af74909SZhong Yang return (viewWhitespace != wsInvisible) && (whitespaceColours.back.isSet);
492*8af74909SZhong Yang }
493*8af74909SZhong Yang
WhiteSpaceVisible(bool inIndent) const494*8af74909SZhong Yang bool ViewStyle::WhiteSpaceVisible(bool inIndent) const noexcept {
495*8af74909SZhong Yang return (!inIndent && viewWhitespace == wsVisibleAfterIndent) ||
496*8af74909SZhong Yang (inIndent && viewWhitespace == wsVisibleOnlyInIndent) ||
497*8af74909SZhong Yang viewWhitespace == wsVisibleAlways;
498*8af74909SZhong Yang }
499*8af74909SZhong Yang
WrapColour() const500*8af74909SZhong Yang ColourDesired ViewStyle::WrapColour() const noexcept {
501*8af74909SZhong Yang if (whitespaceColours.fore.isSet)
502*8af74909SZhong Yang return whitespaceColours.fore;
503*8af74909SZhong Yang else
504*8af74909SZhong Yang return styles[STYLE_DEFAULT].fore;
505*8af74909SZhong Yang }
506*8af74909SZhong Yang
507*8af74909SZhong Yang // Insert new edge in sorted order.
AddMultiEdge(uptr_t wParam,sptr_t lParam)508*8af74909SZhong Yang void ViewStyle::AddMultiEdge(uptr_t wParam, sptr_t lParam) {
509*8af74909SZhong Yang const int column = static_cast<int>(wParam);
510*8af74909SZhong Yang theMultiEdge.insert(
511*8af74909SZhong Yang std::upper_bound(theMultiEdge.begin(), theMultiEdge.end(), column,
512*8af74909SZhong Yang [](const EdgeProperties &a, const EdgeProperties &b) {
513*8af74909SZhong Yang return a.column < b.column;
514*8af74909SZhong Yang }),
515*8af74909SZhong Yang EdgeProperties(column, lParam));
516*8af74909SZhong Yang }
517*8af74909SZhong Yang
SetWrapState(int wrapState_)518*8af74909SZhong Yang bool ViewStyle::SetWrapState(int wrapState_) noexcept {
519*8af74909SZhong Yang WrapMode wrapStateWanted;
520*8af74909SZhong Yang switch (wrapState_) {
521*8af74909SZhong Yang case SC_WRAP_WORD:
522*8af74909SZhong Yang wrapStateWanted = WrapMode::word;
523*8af74909SZhong Yang break;
524*8af74909SZhong Yang case SC_WRAP_CHAR:
525*8af74909SZhong Yang wrapStateWanted = WrapMode::character;
526*8af74909SZhong Yang break;
527*8af74909SZhong Yang case SC_WRAP_WHITESPACE:
528*8af74909SZhong Yang wrapStateWanted = WrapMode::whitespace;
529*8af74909SZhong Yang break;
530*8af74909SZhong Yang default:
531*8af74909SZhong Yang wrapStateWanted = WrapMode::none;
532*8af74909SZhong Yang break;
533*8af74909SZhong Yang }
534*8af74909SZhong Yang const bool changed = wrapState != wrapStateWanted;
535*8af74909SZhong Yang wrapState = wrapStateWanted;
536*8af74909SZhong Yang return changed;
537*8af74909SZhong Yang }
538*8af74909SZhong Yang
SetWrapVisualFlags(int wrapVisualFlags_)539*8af74909SZhong Yang bool ViewStyle::SetWrapVisualFlags(int wrapVisualFlags_) noexcept {
540*8af74909SZhong Yang const bool changed = wrapVisualFlags != wrapVisualFlags_;
541*8af74909SZhong Yang wrapVisualFlags = wrapVisualFlags_;
542*8af74909SZhong Yang return changed;
543*8af74909SZhong Yang }
544*8af74909SZhong Yang
SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_)545*8af74909SZhong Yang bool ViewStyle::SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_) noexcept {
546*8af74909SZhong Yang const bool changed = wrapVisualFlagsLocation != wrapVisualFlagsLocation_;
547*8af74909SZhong Yang wrapVisualFlagsLocation = wrapVisualFlagsLocation_;
548*8af74909SZhong Yang return changed;
549*8af74909SZhong Yang }
550*8af74909SZhong Yang
SetWrapVisualStartIndent(int wrapVisualStartIndent_)551*8af74909SZhong Yang bool ViewStyle::SetWrapVisualStartIndent(int wrapVisualStartIndent_) noexcept {
552*8af74909SZhong Yang const bool changed = wrapVisualStartIndent != wrapVisualStartIndent_;
553*8af74909SZhong Yang wrapVisualStartIndent = wrapVisualStartIndent_;
554*8af74909SZhong Yang return changed;
555*8af74909SZhong Yang }
556*8af74909SZhong Yang
SetWrapIndentMode(int wrapIndentMode_)557*8af74909SZhong Yang bool ViewStyle::SetWrapIndentMode(int wrapIndentMode_) noexcept {
558*8af74909SZhong Yang const bool changed = wrapIndentMode != wrapIndentMode_;
559*8af74909SZhong Yang wrapIndentMode = wrapIndentMode_;
560*8af74909SZhong Yang return changed;
561*8af74909SZhong Yang }
562*8af74909SZhong Yang
IsBlockCaretStyle() const563*8af74909SZhong Yang bool ViewStyle::IsBlockCaretStyle() const noexcept {
564*8af74909SZhong Yang return ((caretStyle & CARETSTYLE_INS_MASK) == CARETSTYLE_BLOCK) ||
565*8af74909SZhong Yang (caretStyle & CARETSTYLE_OVERSTRIKE_BLOCK) != 0;
566*8af74909SZhong Yang }
567*8af74909SZhong Yang
IsCaretVisible() const568*8af74909SZhong Yang bool ViewStyle::IsCaretVisible() const noexcept {
569*8af74909SZhong Yang return caretWidth > 0 && caretStyle != CARETSTYLE_INVISIBLE;
570*8af74909SZhong Yang }
571*8af74909SZhong Yang
DrawCaretInsideSelection(bool inOverstrike,bool imeCaretBlockOverride) const572*8af74909SZhong Yang bool ViewStyle::DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept {
573*8af74909SZhong Yang if (caretStyle & CARETSTYLE_BLOCK_AFTER)
574*8af74909SZhong Yang return false;
575*8af74909SZhong Yang return ((caretStyle & CARETSTYLE_INS_MASK) == CARETSTYLE_BLOCK) ||
576*8af74909SZhong Yang (inOverstrike && (caretStyle & CARETSTYLE_OVERSTRIKE_BLOCK) != 0) ||
577*8af74909SZhong Yang imeCaretBlockOverride;
578*8af74909SZhong Yang }
579*8af74909SZhong Yang
CaretShapeForMode(bool inOverstrike) const580*8af74909SZhong Yang ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike) const noexcept {
581*8af74909SZhong Yang if (inOverstrike) {
582*8af74909SZhong Yang return (caretStyle & CARETSTYLE_OVERSTRIKE_BLOCK) ? CaretShape::block : CaretShape::bar;
583*8af74909SZhong Yang }
584*8af74909SZhong Yang
585*8af74909SZhong Yang const int caret = caretStyle & CARETSTYLE_INS_MASK;
586*8af74909SZhong Yang return (caret <= CARETSTYLE_BLOCK) ? static_cast<CaretShape>(caret) : CaretShape::line;
587*8af74909SZhong Yang }
588*8af74909SZhong Yang
AllocStyles(size_t sizeNew)589*8af74909SZhong Yang void ViewStyle::AllocStyles(size_t sizeNew) {
590*8af74909SZhong Yang size_t i=styles.size();
591*8af74909SZhong Yang styles.resize(sizeNew);
592*8af74909SZhong Yang if (styles.size() > STYLE_DEFAULT) {
593*8af74909SZhong Yang for (; i<sizeNew; i++) {
594*8af74909SZhong Yang if (i != STYLE_DEFAULT) {
595*8af74909SZhong Yang styles[i].ClearTo(styles[STYLE_DEFAULT]);
596*8af74909SZhong Yang }
597*8af74909SZhong Yang }
598*8af74909SZhong Yang }
599*8af74909SZhong Yang }
600*8af74909SZhong Yang
CreateAndAddFont(const FontSpecification & fs)601*8af74909SZhong Yang void ViewStyle::CreateAndAddFont(const FontSpecification &fs) {
602*8af74909SZhong Yang if (fs.fontName) {
603*8af74909SZhong Yang FontMap::iterator it = fonts.find(fs);
604*8af74909SZhong Yang if (it == fonts.end()) {
605*8af74909SZhong Yang fonts[fs] = std::make_unique<FontRealised>();
606*8af74909SZhong Yang }
607*8af74909SZhong Yang }
608*8af74909SZhong Yang }
609*8af74909SZhong Yang
Find(const FontSpecification & fs)610*8af74909SZhong Yang FontRealised *ViewStyle::Find(const FontSpecification &fs) {
611*8af74909SZhong Yang if (!fs.fontName) // Invalid specification so return arbitrary object
612*8af74909SZhong Yang return fonts.begin()->second.get();
613*8af74909SZhong Yang FontMap::iterator it = fonts.find(fs);
614*8af74909SZhong Yang if (it != fonts.end()) {
615*8af74909SZhong Yang // Should always reach here since map was just set for all styles
616*8af74909SZhong Yang return it->second.get();
617*8af74909SZhong Yang }
618*8af74909SZhong Yang return nullptr;
619*8af74909SZhong Yang }
620*8af74909SZhong Yang
FindMaxAscentDescent()621*8af74909SZhong Yang void ViewStyle::FindMaxAscentDescent() {
622*8af74909SZhong Yang for (FontMap::const_iterator it = fonts.cbegin(); it != fonts.cend(); ++it) {
623*8af74909SZhong Yang if (maxAscent < it->second->ascent)
624*8af74909SZhong Yang maxAscent = it->second->ascent;
625*8af74909SZhong Yang if (maxDescent < it->second->descent)
626*8af74909SZhong Yang maxDescent = it->second->descent;
627*8af74909SZhong Yang }
628*8af74909SZhong Yang }
629