xref: /MusicPlayer2/scintilla/src/MarginView.cxx (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file MarginView.cxx
3*8af74909SZhong Yang  ** Defines the appearance of the editor margin.
4*8af74909SZhong Yang  **/
5*8af74909SZhong Yang // Copyright 1998-2014 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 <cstdlib>
10*8af74909SZhong Yang #include <cassert>
11*8af74909SZhong Yang #include <cstring>
12*8af74909SZhong Yang #include <cstdio>
13*8af74909SZhong Yang #include <cmath>
14*8af74909SZhong Yang 
15*8af74909SZhong Yang #include <stdexcept>
16*8af74909SZhong Yang #include <string>
17*8af74909SZhong Yang #include <string_view>
18*8af74909SZhong Yang #include <vector>
19*8af74909SZhong Yang #include <map>
20*8af74909SZhong Yang #include <algorithm>
21*8af74909SZhong Yang #include <memory>
22*8af74909SZhong Yang 
23*8af74909SZhong Yang #include "Platform.h"
24*8af74909SZhong Yang 
25*8af74909SZhong Yang #include "ILoader.h"
26*8af74909SZhong Yang #include "ILexer.h"
27*8af74909SZhong Yang #include "Scintilla.h"
28*8af74909SZhong Yang 
29*8af74909SZhong Yang #include "CharacterCategory.h"
30*8af74909SZhong Yang #include "Position.h"
31*8af74909SZhong Yang #include "IntegerRectangle.h"
32*8af74909SZhong Yang #include "UniqueString.h"
33*8af74909SZhong Yang #include "SplitVector.h"
34*8af74909SZhong Yang #include "Partitioning.h"
35*8af74909SZhong Yang #include "RunStyles.h"
36*8af74909SZhong Yang #include "ContractionState.h"
37*8af74909SZhong Yang #include "CellBuffer.h"
38*8af74909SZhong Yang #include "KeyMap.h"
39*8af74909SZhong Yang #include "Indicator.h"
40*8af74909SZhong Yang #include "LineMarker.h"
41*8af74909SZhong Yang #include "Style.h"
42*8af74909SZhong Yang #include "ViewStyle.h"
43*8af74909SZhong Yang #include "CharClassify.h"
44*8af74909SZhong Yang #include "Decoration.h"
45*8af74909SZhong Yang #include "CaseFolder.h"
46*8af74909SZhong Yang #include "Document.h"
47*8af74909SZhong Yang #include "UniConversion.h"
48*8af74909SZhong Yang #include "Selection.h"
49*8af74909SZhong Yang #include "PositionCache.h"
50*8af74909SZhong Yang #include "EditModel.h"
51*8af74909SZhong Yang #include "MarginView.h"
52*8af74909SZhong Yang #include "EditView.h"
53*8af74909SZhong Yang 
54*8af74909SZhong Yang using namespace Scintilla;
55*8af74909SZhong Yang 
56*8af74909SZhong Yang namespace Scintilla {
57*8af74909SZhong Yang 
DrawWrapMarker(Surface * surface,PRectangle rcPlace,bool isEndMarker,ColourDesired wrapColour)58*8af74909SZhong Yang void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
59*8af74909SZhong Yang 	bool isEndMarker, ColourDesired wrapColour) {
60*8af74909SZhong Yang 	surface->PenColour(wrapColour);
61*8af74909SZhong Yang 
62*8af74909SZhong Yang 	const IntegerRectangle ircPlace(rcPlace);
63*8af74909SZhong Yang 
64*8af74909SZhong Yang 	enum { xa = 1 }; // gap before start
65*8af74909SZhong Yang 	const int w = ircPlace.Width() - xa - 1;
66*8af74909SZhong Yang 
67*8af74909SZhong Yang 	const bool xStraight = isEndMarker;  // x-mirrored symbol for start marker
68*8af74909SZhong Yang 
69*8af74909SZhong Yang 	const int x0 = xStraight ? ircPlace.left : ircPlace.right - 1;
70*8af74909SZhong Yang 	const int y0 = ircPlace.top;
71*8af74909SZhong Yang 
72*8af74909SZhong Yang 	const int dy = ircPlace.Height() / 5;
73*8af74909SZhong Yang 	const int y = ircPlace.Height() / 2 + dy;
74*8af74909SZhong Yang 
75*8af74909SZhong Yang 	struct Relative {
76*8af74909SZhong Yang 		Surface *surface;
77*8af74909SZhong Yang 		int xBase;
78*8af74909SZhong Yang 		int xDir;
79*8af74909SZhong Yang 		int yBase;
80*8af74909SZhong Yang 		int yDir;
81*8af74909SZhong Yang 		void MoveTo(int xRelative, int yRelative) {
82*8af74909SZhong Yang 			surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
83*8af74909SZhong Yang 		}
84*8af74909SZhong Yang 		void LineTo(int xRelative, int yRelative) {
85*8af74909SZhong Yang 			surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
86*8af74909SZhong Yang 		}
87*8af74909SZhong Yang 	};
88*8af74909SZhong Yang 	Relative rel = { surface, x0, xStraight ? 1 : -1, y0, 1 };
89*8af74909SZhong Yang 
90*8af74909SZhong Yang 	// arrow head
91*8af74909SZhong Yang 	rel.MoveTo(xa, y);
92*8af74909SZhong Yang 	rel.LineTo(xa + 2 * w / 3, y - dy);
93*8af74909SZhong Yang 	rel.MoveTo(xa, y);
94*8af74909SZhong Yang 	rel.LineTo(xa + 2 * w / 3, y + dy);
95*8af74909SZhong Yang 
96*8af74909SZhong Yang 	// arrow body
97*8af74909SZhong Yang 	rel.MoveTo(xa, y);
98*8af74909SZhong Yang 	rel.LineTo(xa + w, y);
99*8af74909SZhong Yang 	rel.LineTo(xa + w, y - 2 * dy);
100*8af74909SZhong Yang 	rel.LineTo(xa - 1,   // on windows lineto is exclusive endpoint, perhaps GTK not...
101*8af74909SZhong Yang 		y - 2 * dy);
102*8af74909SZhong Yang }
103*8af74909SZhong Yang 
MarginView()104*8af74909SZhong Yang MarginView::MarginView() noexcept {
105*8af74909SZhong Yang 	wrapMarkerPaddingRight = 3;
106*8af74909SZhong Yang 	customDrawWrapMarker = nullptr;
107*8af74909SZhong Yang }
108*8af74909SZhong Yang 
DropGraphics(bool freeObjects)109*8af74909SZhong Yang void MarginView::DropGraphics(bool freeObjects) {
110*8af74909SZhong Yang 	if (freeObjects) {
111*8af74909SZhong Yang 		pixmapSelMargin.reset();
112*8af74909SZhong Yang 		pixmapSelPattern.reset();
113*8af74909SZhong Yang 		pixmapSelPatternOffset1.reset();
114*8af74909SZhong Yang 	} else {
115*8af74909SZhong Yang 		if (pixmapSelMargin)
116*8af74909SZhong Yang 			pixmapSelMargin->Release();
117*8af74909SZhong Yang 		if (pixmapSelPattern)
118*8af74909SZhong Yang 			pixmapSelPattern->Release();
119*8af74909SZhong Yang 		if (pixmapSelPatternOffset1)
120*8af74909SZhong Yang 			pixmapSelPatternOffset1->Release();
121*8af74909SZhong Yang 	}
122*8af74909SZhong Yang }
123*8af74909SZhong Yang 
AllocateGraphics(const ViewStyle & vsDraw)124*8af74909SZhong Yang void MarginView::AllocateGraphics(const ViewStyle &vsDraw) {
125*8af74909SZhong Yang 	if (!pixmapSelMargin)
126*8af74909SZhong Yang 		pixmapSelMargin.reset(Surface::Allocate(vsDraw.technology));
127*8af74909SZhong Yang 	if (!pixmapSelPattern)
128*8af74909SZhong Yang 		pixmapSelPattern.reset(Surface::Allocate(vsDraw.technology));
129*8af74909SZhong Yang 	if (!pixmapSelPatternOffset1)
130*8af74909SZhong Yang 		pixmapSelPatternOffset1.reset(Surface::Allocate(vsDraw.technology));
131*8af74909SZhong Yang }
132*8af74909SZhong Yang 
RefreshPixMaps(Surface * surfaceWindow,WindowID wid,const ViewStyle & vsDraw)133*8af74909SZhong Yang void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
134*8af74909SZhong Yang 	if (!pixmapSelPattern->Initialised()) {
135*8af74909SZhong Yang 		const int patternSize = 8;
136*8af74909SZhong Yang 		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
137*8af74909SZhong Yang 		pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
138*8af74909SZhong Yang 		// This complex procedure is to reproduce the checkerboard dithered pattern used by windows
139*8af74909SZhong Yang 		// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
140*8af74909SZhong Yang 		// way between the chrome colour and the chrome highlight colour making a nice transition
141*8af74909SZhong Yang 		// between the window chrome and the content area. And it works in low colour depths.
142*8af74909SZhong Yang 		const PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize);
143*8af74909SZhong Yang 
144*8af74909SZhong Yang 		// Initialize default colours based on the chrome colour scheme.  Typically the highlight is white.
145*8af74909SZhong Yang 		ColourDesired colourFMFill = vsDraw.selbar;
146*8af74909SZhong Yang 		ColourDesired colourFMStripes = vsDraw.selbarlight;
147*8af74909SZhong Yang 
148*8af74909SZhong Yang 		if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
149*8af74909SZhong Yang 			// User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
150*8af74909SZhong Yang 			// (Typically, the highlight colour is white.)
151*8af74909SZhong Yang 			colourFMFill = vsDraw.selbarlight;
152*8af74909SZhong Yang 		}
153*8af74909SZhong Yang 
154*8af74909SZhong Yang 		if (vsDraw.foldmarginColour.isSet) {
155*8af74909SZhong Yang 			// override default fold margin colour
156*8af74909SZhong Yang 			colourFMFill = vsDraw.foldmarginColour;
157*8af74909SZhong Yang 		}
158*8af74909SZhong Yang 		if (vsDraw.foldmarginHighlightColour.isSet) {
159*8af74909SZhong Yang 			// override default fold margin highlight colour
160*8af74909SZhong Yang 			colourFMStripes = vsDraw.foldmarginHighlightColour;
161*8af74909SZhong Yang 		}
162*8af74909SZhong Yang 
163*8af74909SZhong Yang 		pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
164*8af74909SZhong Yang 		pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
165*8af74909SZhong Yang 		for (int y = 0; y < patternSize; y++) {
166*8af74909SZhong Yang 			for (int x = y % 2; x < patternSize; x += 2) {
167*8af74909SZhong Yang 				const PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1);
168*8af74909SZhong Yang 				pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
169*8af74909SZhong Yang 				pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
170*8af74909SZhong Yang 			}
171*8af74909SZhong Yang 		}
172*8af74909SZhong Yang 	}
173*8af74909SZhong Yang }
174*8af74909SZhong Yang 
SubstituteMarkerIfEmpty(int markerCheck,int markerDefault,const ViewStyle & vs)175*8af74909SZhong Yang static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) noexcept {
176*8af74909SZhong Yang 	if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
177*8af74909SZhong Yang 		return markerDefault;
178*8af74909SZhong Yang 	return markerCheck;
179*8af74909SZhong Yang }
180*8af74909SZhong Yang 
PaintMargin(Surface * surface,Sci::Line topLine,PRectangle rc,PRectangle rcMargin,const EditModel & model,const ViewStyle & vs)181*8af74909SZhong Yang void MarginView::PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
182*8af74909SZhong Yang 	const EditModel &model, const ViewStyle &vs) {
183*8af74909SZhong Yang 
184*8af74909SZhong Yang 	PRectangle rcSelMargin = rcMargin;
185*8af74909SZhong Yang 	rcSelMargin.right = rcMargin.left;
186*8af74909SZhong Yang 	if (rcSelMargin.bottom < rc.bottom)
187*8af74909SZhong Yang 		rcSelMargin.bottom = rc.bottom;
188*8af74909SZhong Yang 
189*8af74909SZhong Yang 	const Point ptOrigin = model.GetVisibleOriginInMain();
190*8af74909SZhong Yang 	FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font;
191*8af74909SZhong Yang 	for (size_t margin = 0; margin < vs.ms.size(); margin++) {
192*8af74909SZhong Yang 		if (vs.ms[margin].width > 0) {
193*8af74909SZhong Yang 
194*8af74909SZhong Yang 			rcSelMargin.left = rcSelMargin.right;
195*8af74909SZhong Yang 			rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
196*8af74909SZhong Yang 
197*8af74909SZhong Yang 			if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
198*8af74909SZhong Yang 				if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
199*8af74909SZhong Yang 					// Required because of special way brush is created for selection margin
200*8af74909SZhong Yang 					// Ensure patterns line up when scrolling with separate margin view
201*8af74909SZhong Yang 					// by choosing correctly aligned variant.
202*8af74909SZhong Yang 					const bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
203*8af74909SZhong Yang 					surface->FillRectangle(rcSelMargin,
204*8af74909SZhong Yang 						invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
205*8af74909SZhong Yang 				} else {
206*8af74909SZhong Yang 					ColourDesired colour;
207*8af74909SZhong Yang 					switch (vs.ms[margin].style) {
208*8af74909SZhong Yang 					case SC_MARGIN_BACK:
209*8af74909SZhong Yang 						colour = vs.styles[STYLE_DEFAULT].back;
210*8af74909SZhong Yang 						break;
211*8af74909SZhong Yang 					case SC_MARGIN_FORE:
212*8af74909SZhong Yang 						colour = vs.styles[STYLE_DEFAULT].fore;
213*8af74909SZhong Yang 						break;
214*8af74909SZhong Yang 					case SC_MARGIN_COLOUR:
215*8af74909SZhong Yang 						colour = vs.ms[margin].back;
216*8af74909SZhong Yang 						break;
217*8af74909SZhong Yang 					default:
218*8af74909SZhong Yang 						colour = vs.styles[STYLE_LINENUMBER].back;
219*8af74909SZhong Yang 						break;
220*8af74909SZhong Yang 					}
221*8af74909SZhong Yang 					surface->FillRectangle(rcSelMargin, colour);
222*8af74909SZhong Yang 				}
223*8af74909SZhong Yang 			} else {
224*8af74909SZhong Yang 				surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
225*8af74909SZhong Yang 			}
226*8af74909SZhong Yang 
227*8af74909SZhong Yang 			const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
228*8af74909SZhong Yang 			Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
229*8af74909SZhong Yang 			Sci::Position yposScreen = lineStartPaint * vs.lineHeight - static_cast<Sci::Position>(ptOrigin.y);
230*8af74909SZhong Yang 			// Work out whether the top line is whitespace located after a
231*8af74909SZhong Yang 			// lessening of fold level which implies a 'fold tail' but which should not
232*8af74909SZhong Yang 			// be displayed until the last of a sequence of whitespace.
233*8af74909SZhong Yang 			bool needWhiteClosure = false;
234*8af74909SZhong Yang 			if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
235*8af74909SZhong Yang 				const int level = model.pdoc->GetLevel(model.pcs->DocFromDisplay(visibleLine));
236*8af74909SZhong Yang 				if (level & SC_FOLDLEVELWHITEFLAG) {
237*8af74909SZhong Yang 					Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
238*8af74909SZhong Yang 					int levelPrev = level;
239*8af74909SZhong Yang 					while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
240*8af74909SZhong Yang 						lineBack--;
241*8af74909SZhong Yang 						levelPrev = model.pdoc->GetLevel(lineBack);
242*8af74909SZhong Yang 					}
243*8af74909SZhong Yang 					if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
244*8af74909SZhong Yang 						if (LevelNumber(level) < LevelNumber(levelPrev))
245*8af74909SZhong Yang 							needWhiteClosure = true;
246*8af74909SZhong Yang 					}
247*8af74909SZhong Yang 				}
248*8af74909SZhong Yang 				if (highlightDelimiter.isEnabled) {
249*8af74909SZhong Yang 					const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
250*8af74909SZhong Yang 					model.pdoc->GetHighlightDelimiters(highlightDelimiter,
251*8af74909SZhong Yang 						model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
252*8af74909SZhong Yang 				}
253*8af74909SZhong Yang 			}
254*8af74909SZhong Yang 
255*8af74909SZhong Yang 			// Old code does not know about new markers needed to distinguish all cases
256*8af74909SZhong Yang 			const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
257*8af74909SZhong Yang 				SC_MARKNUM_FOLDEROPEN, vs);
258*8af74909SZhong Yang 			const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
259*8af74909SZhong Yang 				SC_MARKNUM_FOLDER, vs);
260*8af74909SZhong Yang 
261*8af74909SZhong Yang 			while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
262*8af74909SZhong Yang 
263*8af74909SZhong Yang 				PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
264*8af74909SZhong Yang 				const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
265*8af74909SZhong Yang 				PLATFORM_ASSERT(model.pcs->GetVisible(lineDoc));
266*8af74909SZhong Yang 				const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
267*8af74909SZhong Yang 				const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
268*8af74909SZhong Yang 				const bool firstSubLine = visibleLine == firstVisibleLine;
269*8af74909SZhong Yang 				const bool lastSubLine = visibleLine == lastVisibleLine;
270*8af74909SZhong Yang 
271*8af74909SZhong Yang 				int marks = model.pdoc->GetMark(lineDoc);
272*8af74909SZhong Yang 				if (!firstSubLine)
273*8af74909SZhong Yang 					marks = 0;
274*8af74909SZhong Yang 
275*8af74909SZhong Yang 				bool headWithTail = false;
276*8af74909SZhong Yang 
277*8af74909SZhong Yang 				if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
278*8af74909SZhong Yang 					// Decide which fold indicator should be displayed
279*8af74909SZhong Yang 					const int level = model.pdoc->GetLevel(lineDoc);
280*8af74909SZhong Yang 					const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
281*8af74909SZhong Yang 					const int levelNum = LevelNumber(level);
282*8af74909SZhong Yang 					const int levelNextNum = LevelNumber(levelNext);
283*8af74909SZhong Yang 					if (level & SC_FOLDLEVELHEADERFLAG) {
284*8af74909SZhong Yang 						if (firstSubLine) {
285*8af74909SZhong Yang 							if (levelNum < levelNextNum) {
286*8af74909SZhong Yang 								if (model.pcs->GetExpanded(lineDoc)) {
287*8af74909SZhong Yang 									if (levelNum == SC_FOLDLEVELBASE)
288*8af74909SZhong Yang 										marks |= 1 << SC_MARKNUM_FOLDEROPEN;
289*8af74909SZhong Yang 									else
290*8af74909SZhong Yang 										marks |= 1 << folderOpenMid;
291*8af74909SZhong Yang 								} else {
292*8af74909SZhong Yang 									if (levelNum == SC_FOLDLEVELBASE)
293*8af74909SZhong Yang 										marks |= 1 << SC_MARKNUM_FOLDER;
294*8af74909SZhong Yang 									else
295*8af74909SZhong Yang 										marks |= 1 << folderEnd;
296*8af74909SZhong Yang 								}
297*8af74909SZhong Yang 							} else if (levelNum > SC_FOLDLEVELBASE) {
298*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
299*8af74909SZhong Yang 							}
300*8af74909SZhong Yang 						} else {
301*8af74909SZhong Yang 							if (levelNum < levelNextNum) {
302*8af74909SZhong Yang 								if (model.pcs->GetExpanded(lineDoc)) {
303*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERSUB;
304*8af74909SZhong Yang 								} else if (levelNum > SC_FOLDLEVELBASE) {
305*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERSUB;
306*8af74909SZhong Yang 								}
307*8af74909SZhong Yang 							} else if (levelNum > SC_FOLDLEVELBASE) {
308*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
309*8af74909SZhong Yang 							}
310*8af74909SZhong Yang 						}
311*8af74909SZhong Yang 						needWhiteClosure = false;
312*8af74909SZhong Yang 						const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
313*8af74909SZhong Yang 						const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine);
314*8af74909SZhong Yang 						const int secondFollowupLineLevelNum = LevelNumber(model.pdoc->GetLevel(firstFollowupLine + 1));
315*8af74909SZhong Yang 						if (!model.pcs->GetExpanded(lineDoc)) {
316*8af74909SZhong Yang 							if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
317*8af74909SZhong Yang 								(levelNum > secondFollowupLineLevelNum))
318*8af74909SZhong Yang 								needWhiteClosure = true;
319*8af74909SZhong Yang 
320*8af74909SZhong Yang 							if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
321*8af74909SZhong Yang 								headWithTail = true;
322*8af74909SZhong Yang 						}
323*8af74909SZhong Yang 					} else if (level & SC_FOLDLEVELWHITEFLAG) {
324*8af74909SZhong Yang 						if (needWhiteClosure) {
325*8af74909SZhong Yang 							if (levelNext & SC_FOLDLEVELWHITEFLAG) {
326*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
327*8af74909SZhong Yang 							} else if (levelNextNum > SC_FOLDLEVELBASE) {
328*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
329*8af74909SZhong Yang 								needWhiteClosure = false;
330*8af74909SZhong Yang 							} else {
331*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERTAIL;
332*8af74909SZhong Yang 								needWhiteClosure = false;
333*8af74909SZhong Yang 							}
334*8af74909SZhong Yang 						} else if (levelNum > SC_FOLDLEVELBASE) {
335*8af74909SZhong Yang 							if (levelNextNum < levelNum) {
336*8af74909SZhong Yang 								if (levelNextNum > SC_FOLDLEVELBASE) {
337*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
338*8af74909SZhong Yang 								} else {
339*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERTAIL;
340*8af74909SZhong Yang 								}
341*8af74909SZhong Yang 							} else {
342*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
343*8af74909SZhong Yang 							}
344*8af74909SZhong Yang 						}
345*8af74909SZhong Yang 					} else if (levelNum > SC_FOLDLEVELBASE) {
346*8af74909SZhong Yang 						if (levelNextNum < levelNum) {
347*8af74909SZhong Yang 							needWhiteClosure = false;
348*8af74909SZhong Yang 							if (levelNext & SC_FOLDLEVELWHITEFLAG) {
349*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
350*8af74909SZhong Yang 								needWhiteClosure = true;
351*8af74909SZhong Yang 							} else if (lastSubLine) {
352*8af74909SZhong Yang 								if (levelNextNum > SC_FOLDLEVELBASE) {
353*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
354*8af74909SZhong Yang 								} else {
355*8af74909SZhong Yang 									marks |= 1 << SC_MARKNUM_FOLDERTAIL;
356*8af74909SZhong Yang 								}
357*8af74909SZhong Yang 							} else {
358*8af74909SZhong Yang 								marks |= 1 << SC_MARKNUM_FOLDERSUB;
359*8af74909SZhong Yang 							}
360*8af74909SZhong Yang 						} else {
361*8af74909SZhong Yang 							marks |= 1 << SC_MARKNUM_FOLDERSUB;
362*8af74909SZhong Yang 						}
363*8af74909SZhong Yang 					}
364*8af74909SZhong Yang 				}
365*8af74909SZhong Yang 
366*8af74909SZhong Yang 				marks &= vs.ms[margin].mask;
367*8af74909SZhong Yang 
368*8af74909SZhong Yang 				PRectangle rcMarker(
369*8af74909SZhong Yang 					rcSelMargin.left,
370*8af74909SZhong Yang 					static_cast<XYPOSITION>(yposScreen),
371*8af74909SZhong Yang 					rcSelMargin.right,
372*8af74909SZhong Yang 					static_cast<XYPOSITION>(yposScreen + vs.lineHeight));
373*8af74909SZhong Yang 				if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
374*8af74909SZhong Yang 					if (firstSubLine) {
375*8af74909SZhong Yang 						std::string sNumber;
376*8af74909SZhong Yang 						if (lineDoc >= 0) {
377*8af74909SZhong Yang 							sNumber = std::to_string(lineDoc + 1);
378*8af74909SZhong Yang 						}
379*8af74909SZhong Yang 						if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) {
380*8af74909SZhong Yang 							char number[100] = "";
381*8af74909SZhong Yang 							if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
382*8af74909SZhong Yang 								const int lev = model.pdoc->GetLevel(lineDoc);
383*8af74909SZhong Yang 								sprintf(number, "%c%c %03X %03X",
384*8af74909SZhong Yang 									(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
385*8af74909SZhong Yang 									(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
386*8af74909SZhong Yang 									LevelNumber(lev),
387*8af74909SZhong Yang 									lev >> 16
388*8af74909SZhong Yang 									);
389*8af74909SZhong Yang 							} else {
390*8af74909SZhong Yang 								const int state = model.pdoc->GetLineState(lineDoc);
391*8af74909SZhong Yang 								sprintf(number, "%0X", state);
392*8af74909SZhong Yang 							}
393*8af74909SZhong Yang 							sNumber = number;
394*8af74909SZhong Yang 						}
395*8af74909SZhong Yang 						PRectangle rcNumber = rcMarker;
396*8af74909SZhong Yang 						// Right justify
397*8af74909SZhong Yang 						const XYPOSITION width = surface->WidthText(fontLineNumber, sNumber);
398*8af74909SZhong Yang 						const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
399*8af74909SZhong Yang 						rcNumber.left = xpos;
400*8af74909SZhong Yang 						DrawTextNoClipPhase(surface, rcNumber, vs.styles[STYLE_LINENUMBER],
401*8af74909SZhong Yang 							rcNumber.top + vs.maxAscent, sNumber, drawAll);
402*8af74909SZhong Yang 					} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
403*8af74909SZhong Yang 						PRectangle rcWrapMarker = rcMarker;
404*8af74909SZhong Yang 						rcWrapMarker.right -= wrapMarkerPaddingRight;
405*8af74909SZhong Yang 						rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
406*8af74909SZhong Yang 						if (!customDrawWrapMarker) {
407*8af74909SZhong Yang 							DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
408*8af74909SZhong Yang 						} else {
409*8af74909SZhong Yang 							customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
410*8af74909SZhong Yang 						}
411*8af74909SZhong Yang 					}
412*8af74909SZhong Yang 				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
413*8af74909SZhong Yang 					const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
414*8af74909SZhong Yang 					if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
415*8af74909SZhong Yang 						if (firstSubLine) {
416*8af74909SZhong Yang 							surface->FillRectangle(rcMarker,
417*8af74909SZhong Yang 								vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
418*8af74909SZhong Yang 							PRectangle rcText = rcMarker;
419*8af74909SZhong Yang 							if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
420*8af74909SZhong Yang 								const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
421*8af74909SZhong Yang 								rcText.left = rcText.right - width - 3;
422*8af74909SZhong Yang 							}
423*8af74909SZhong Yang 							DrawStyledText(surface, vs, vs.marginStyleOffset, rcText,
424*8af74909SZhong Yang 								stMargin, 0, stMargin.length, drawAll);
425*8af74909SZhong Yang 						} else {
426*8af74909SZhong Yang 							// if we're displaying annotation lines, colour the margin to match the associated document line
427*8af74909SZhong Yang 							const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
428*8af74909SZhong Yang 							if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
429*8af74909SZhong Yang 								surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
430*8af74909SZhong Yang 							}
431*8af74909SZhong Yang 						}
432*8af74909SZhong Yang 					}
433*8af74909SZhong Yang 				}
434*8af74909SZhong Yang 
435*8af74909SZhong Yang 				if (marks) {
436*8af74909SZhong Yang 					for (int markBit = 0; (markBit < 32) && marks; markBit++) {
437*8af74909SZhong Yang 						if (marks & 1) {
438*8af74909SZhong Yang 							LineMarker::FoldPart part = LineMarker::FoldPart::undefined;
439*8af74909SZhong Yang 							if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
440*8af74909SZhong Yang 								if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
441*8af74909SZhong Yang 									part = LineMarker::FoldPart::body;
442*8af74909SZhong Yang 								} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
443*8af74909SZhong Yang 									if (firstSubLine) {
444*8af74909SZhong Yang 										part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
445*8af74909SZhong Yang 									} else {
446*8af74909SZhong Yang 										if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
447*8af74909SZhong Yang 											part = LineMarker::FoldPart::body;
448*8af74909SZhong Yang 										} else {
449*8af74909SZhong Yang 											part = LineMarker::FoldPart::undefined;
450*8af74909SZhong Yang 										}
451*8af74909SZhong Yang 									}
452*8af74909SZhong Yang 								} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
453*8af74909SZhong Yang 									part = LineMarker::FoldPart::tail;
454*8af74909SZhong Yang 								}
455*8af74909SZhong Yang 							}
456*8af74909SZhong Yang 							vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, part, vs.ms[margin].style);
457*8af74909SZhong Yang 						}
458*8af74909SZhong Yang 						marks >>= 1;
459*8af74909SZhong Yang 					}
460*8af74909SZhong Yang 				}
461*8af74909SZhong Yang 
462*8af74909SZhong Yang 				visibleLine++;
463*8af74909SZhong Yang 				yposScreen += vs.lineHeight;
464*8af74909SZhong Yang 			}
465*8af74909SZhong Yang 		}
466*8af74909SZhong Yang 	}
467*8af74909SZhong Yang 
468*8af74909SZhong Yang 	PRectangle rcBlankMargin = rcMargin;
469*8af74909SZhong Yang 	rcBlankMargin.left = rcSelMargin.right;
470*8af74909SZhong Yang 	surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);
471*8af74909SZhong Yang }
472*8af74909SZhong Yang 
473*8af74909SZhong Yang }
474*8af74909SZhong Yang 
475