1 // Scintilla source code edit control
2 /** @file LineMarker.cxx
3 ** Defines the look of a line marker in the margin .
5 // Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
12 #include "Scintilla.h"
14 #include "LineMarker.h"
17 using namespace Scintilla
;
20 void LineMarker::RefreshColourPalette(Palette
&pal
, bool want
) {
21 pal
.WantFind(fore
, want
);
22 pal
.WantFind(back
, want
);
23 pal
.WantFind(backSelected
, want
);
25 pxpm
->RefreshColourPalette(pal
, want
);
29 void LineMarker::SetXPM(const char *textForm
) {
31 pxpm
= new XPM(textForm
);
32 markType
= SC_MARK_PIXMAP
;
35 void LineMarker::SetXPM(const char *const *linesForm
) {
37 pxpm
= new XPM(linesForm
);
38 markType
= SC_MARK_PIXMAP
;
41 static void DrawBox(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
43 rc
.left
= centreX
- armSize
;
44 rc
.top
= centreY
- armSize
;
45 rc
.right
= centreX
+ armSize
+ 1;
46 rc
.bottom
= centreY
+ armSize
+ 1;
47 surface
->RectangleDraw(rc
, back
, fore
);
50 static void DrawCircle(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
52 rcCircle
.left
= centreX
- armSize
;
53 rcCircle
.top
= centreY
- armSize
;
54 rcCircle
.right
= centreX
+ armSize
+ 1;
55 rcCircle
.bottom
= centreY
+ armSize
+ 1;
56 surface
->Ellipse(rcCircle
, back
, fore
);
59 static void DrawPlus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
60 PRectangle
rcV(centreX
, centreY
- armSize
+ 2, centreX
+ 1, centreY
+ armSize
- 2 + 1);
61 surface
->FillRectangle(rcV
, fore
);
62 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
63 surface
->FillRectangle(rcH
, fore
);
66 static void DrawMinus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
67 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
68 surface
->FillRectangle(rcH
, fore
);
71 void LineMarker::Draw(Surface
*surface
, PRectangle
&rcWhole
, Font
&fontForCharacter
, typeOfFold tFold
) {
72 ColourPair head
= back
;
73 ColourPair body
= back
;
74 ColourPair tail
= back
;
77 case LineMarker::head
:
80 if (markType
== SC_MARK_VLINE
)
83 case LineMarker::body
:
87 case LineMarker::tail
:
92 // LineMarker::undefined
97 if ((markType
== SC_MARK_PIXMAP
) && (pxpm
)) {
98 pxpm
->Draw(surface
, rcWhole
);
101 // Restrict most shapes a bit
102 PRectangle rc
= rcWhole
;
105 int minDim
= Platform::Minimum(rc
.Width(), rc
.Height());
106 minDim
--; // Ensure does not go beyond edge
107 int centreX
= (rc
.right
+ rc
.left
) / 2;
108 int centreY
= (rc
.bottom
+ rc
.top
) / 2;
109 int dimOn2
= minDim
/ 2;
110 int dimOn4
= minDim
/ 4;
111 int blobSize
= dimOn2
-1;
112 int armSize
= dimOn2
-2;
113 if (rc
.Width() > (rc
.Height() * 2)) {
114 // Wide column is line number so move to left to try to avoid overlapping number
115 centreX
= rc
.left
+ dimOn2
+ 1;
117 if (markType
== SC_MARK_ROUNDRECT
) {
118 PRectangle rcRounded
= rc
;
119 rcRounded
.left
= rc
.left
+ 1;
120 rcRounded
.right
= rc
.right
- 1;
121 surface
->RoundedRectangle(rcRounded
, fore
.allocated
, back
.allocated
);
122 } else if (markType
== SC_MARK_CIRCLE
) {
124 rcCircle
.left
= centreX
- dimOn2
;
125 rcCircle
.top
= centreY
- dimOn2
;
126 rcCircle
.right
= centreX
+ dimOn2
;
127 rcCircle
.bottom
= centreY
+ dimOn2
;
128 surface
->Ellipse(rcCircle
, fore
.allocated
, back
.allocated
);
129 } else if (markType
== SC_MARK_ARROW
) {
131 Point(centreX
- dimOn4
, centreY
- dimOn2
),
132 Point(centreX
- dimOn4
, centreY
+ dimOn2
),
133 Point(centreX
+ dimOn2
- dimOn4
, centreY
),
135 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
136 fore
.allocated
, back
.allocated
);
138 } else if (markType
== SC_MARK_ARROWDOWN
) {
140 Point(centreX
- dimOn2
, centreY
- dimOn4
),
141 Point(centreX
+ dimOn2
, centreY
- dimOn4
),
142 Point(centreX
, centreY
+ dimOn2
- dimOn4
),
144 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
145 fore
.allocated
, back
.allocated
);
147 } else if (markType
== SC_MARK_PLUS
) {
149 Point(centreX
- armSize
, centreY
- 1),
150 Point(centreX
- 1, centreY
- 1),
151 Point(centreX
- 1, centreY
- armSize
),
152 Point(centreX
+ 1, centreY
- armSize
),
153 Point(centreX
+ 1, centreY
- 1),
154 Point(centreX
+ armSize
, centreY
-1),
155 Point(centreX
+ armSize
, centreY
+1),
156 Point(centreX
+ 1, centreY
+ 1),
157 Point(centreX
+ 1, centreY
+ armSize
),
158 Point(centreX
- 1, centreY
+ armSize
),
159 Point(centreX
- 1, centreY
+ 1),
160 Point(centreX
- armSize
, centreY
+ 1),
162 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
163 fore
.allocated
, back
.allocated
);
165 } else if (markType
== SC_MARK_MINUS
) {
167 Point(centreX
- armSize
, centreY
- 1),
168 Point(centreX
+ armSize
, centreY
-1),
169 Point(centreX
+ armSize
, centreY
+1),
170 Point(centreX
- armSize
, centreY
+ 1),
172 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
173 fore
.allocated
, back
.allocated
);
175 } else if (markType
== SC_MARK_SMALLRECT
) {
177 rcSmall
.left
= rc
.left
+ 1;
178 rcSmall
.top
= rc
.top
+ 2;
179 rcSmall
.right
= rc
.right
- 1;
180 rcSmall
.bottom
= rc
.bottom
- 2;
181 surface
->RectangleDraw(rcSmall
, fore
.allocated
, back
.allocated
);
183 } else if (markType
== SC_MARK_EMPTY
|| markType
== SC_MARK_BACKGROUND
||
184 markType
== SC_MARK_UNDERLINE
|| markType
== SC_MARK_AVAILABLE
) {
185 // An invisible marker so don't draw anything
187 } else if (markType
== SC_MARK_VLINE
) {
188 surface
->PenColour(body
.allocated
);
189 surface
->MoveTo(centreX
, rcWhole
.top
+ blobSize
- (rcWhole
.bottom
- rcWhole
.top
)/2);
190 surface
->LineTo(centreX
, rcWhole
.bottom
);
192 } else if (markType
== SC_MARK_LCORNER
) {
193 surface
->PenColour(tail
.allocated
);
194 surface
->MoveTo(centreX
, rcWhole
.top
);
195 surface
->LineTo(centreX
, rc
.top
+ dimOn2
);
196 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
198 } else if (markType
== SC_MARK_TCORNER
) {
199 surface
->PenColour(tail
.allocated
);
200 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
);
201 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
203 surface
->PenColour(body
.allocated
);
204 surface
->MoveTo(centreX
, rcWhole
.top
);
205 surface
->LineTo(centreX
, rc
.top
+ dimOn2
+ 1);
207 surface
->PenColour(head
.allocated
);
208 surface
->LineTo(centreX
, rcWhole
.bottom
);
210 } else if (markType
== SC_MARK_LCORNERCURVE
) {
211 surface
->PenColour(tail
.allocated
);
212 surface
->MoveTo(centreX
, rcWhole
.top
);
213 surface
->LineTo(centreX
, rc
.top
+ dimOn2
-3);
214 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
215 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
217 } else if (markType
== SC_MARK_TCORNERCURVE
) {
218 surface
->PenColour(tail
.allocated
);
219 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
-3);
220 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
221 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
223 surface
->PenColour(body
.allocated
);
224 surface
->MoveTo(centreX
, rcWhole
.top
);
225 surface
->LineTo(centreX
, rc
.top
+ dimOn2
-2);
227 surface
->PenColour(head
.allocated
);
228 surface
->LineTo(centreX
, rcWhole
.bottom
);
230 } else if (markType
== SC_MARK_BOXPLUS
) {
231 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
232 DrawPlus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
234 } else if (markType
== SC_MARK_BOXPLUSCONNECTED
) {
235 surface
->PenColour(body
.allocated
);
236 surface
->MoveTo(centreX
, centreY
+ blobSize
);
237 surface
->LineTo(centreX
, rcWhole
.bottom
);
239 surface
->PenColour(body
.allocated
);
240 surface
->MoveTo(centreX
, rcWhole
.top
);
241 surface
->LineTo(centreX
, centreY
- blobSize
);
243 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
244 DrawPlus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
246 if (tFold
== LineMarker::body
) {
247 surface
->PenColour(tail
.allocated
);
248 surface
->MoveTo(centreX
+ 1, centreY
+ blobSize
);
249 surface
->LineTo(centreX
+ blobSize
+ 1, centreY
+ blobSize
);
251 surface
->MoveTo(centreX
+ blobSize
, centreY
+ blobSize
);
252 surface
->LineTo(centreX
+ blobSize
, centreY
- blobSize
);
254 surface
->MoveTo(centreX
+ 1, centreY
- blobSize
);
255 surface
->LineTo(centreX
+ blobSize
+ 1, centreY
- blobSize
);
257 } else if (markType
== SC_MARK_BOXMINUS
) {
258 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
259 DrawMinus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
261 surface
->PenColour(head
.allocated
);
262 surface
->MoveTo(centreX
, centreY
+ blobSize
);
263 surface
->LineTo(centreX
, rcWhole
.bottom
);
265 } else if (markType
== SC_MARK_BOXMINUSCONNECTED
) {
266 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
267 DrawMinus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
269 surface
->PenColour(head
.allocated
);
270 surface
->MoveTo(centreX
, centreY
+ blobSize
);
271 surface
->LineTo(centreX
, rcWhole
.bottom
);
273 surface
->PenColour(body
.allocated
);
274 surface
->MoveTo(centreX
, rcWhole
.top
);
275 surface
->LineTo(centreX
, centreY
- blobSize
);
277 if (tFold
== LineMarker::body
) {
278 surface
->PenColour(tail
.allocated
);
279 surface
->MoveTo(centreX
+ 1, centreY
+ blobSize
);
280 surface
->LineTo(centreX
+ blobSize
+ 1, centreY
+ blobSize
);
282 surface
->MoveTo(centreX
+ blobSize
, centreY
+ blobSize
);
283 surface
->LineTo(centreX
+ blobSize
, centreY
- blobSize
);
285 surface
->MoveTo(centreX
+ 1, centreY
- blobSize
);
286 surface
->LineTo(centreX
+ blobSize
+ 1, centreY
- blobSize
);
288 } else if (markType
== SC_MARK_CIRCLEPLUS
) {
289 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
290 DrawPlus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
292 } else if (markType
== SC_MARK_CIRCLEPLUSCONNECTED
) {
293 surface
->PenColour(body
.allocated
);
294 surface
->MoveTo(centreX
, centreY
+ blobSize
);
295 surface
->LineTo(centreX
, rcWhole
.bottom
);
297 surface
->MoveTo(centreX
, rcWhole
.top
);
298 surface
->LineTo(centreX
, centreY
- blobSize
);
300 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
301 DrawPlus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
303 } else if (markType
== SC_MARK_CIRCLEMINUS
) {
304 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
305 DrawMinus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
307 surface
->PenColour(head
.allocated
);
308 surface
->MoveTo(centreX
, centreY
+ blobSize
);
309 surface
->LineTo(centreX
, rcWhole
.bottom
);
311 } else if (markType
== SC_MARK_CIRCLEMINUSCONNECTED
) {
312 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, head
.allocated
);
313 DrawMinus(surface
, centreX
, centreY
, blobSize
, tail
.allocated
);
315 surface
->PenColour(head
.allocated
);
316 surface
->MoveTo(centreX
, centreY
+ blobSize
);
317 surface
->LineTo(centreX
, rcWhole
.bottom
);
319 surface
->PenColour(body
.allocated
);
320 surface
->MoveTo(centreX
, rcWhole
.top
);
321 surface
->LineTo(centreX
, centreY
- blobSize
);
323 } else if (markType
>= SC_MARK_CHARACTER
) {
325 character
[0] = static_cast<char>(markType
- SC_MARK_CHARACTER
);
326 int width
= surface
->WidthText(fontForCharacter
, character
, 1);
327 rc
.left
+= (rc
.Width() - width
) / 2;
328 rc
.right
= rc
.left
+ width
;
329 surface
->DrawTextClipped(rc
, fontForCharacter
, rc
.bottom
- 2,
330 character
, 1, fore
.allocated
, back
.allocated
);
332 } else if (markType
== SC_MARK_DOTDOTDOT
) {
333 int right
= centreX
- 6;
334 for (int b
=0; b
<3; b
++) {
335 PRectangle
rcBlob(right
, rc
.bottom
- 4, right
+ 2, rc
.bottom
-2);
336 surface
->FillRectangle(rcBlob
, fore
.allocated
);
339 } else if (markType
== SC_MARK_ARROWS
) {
340 surface
->PenColour(fore
.allocated
);
341 int right
= centreX
- 2;
342 for (int b
=0; b
<3; b
++) {
343 surface
->MoveTo(right
- 4, centreY
- 4);
344 surface
->LineTo(right
, centreY
);
345 surface
->LineTo(right
- 5, centreY
+ 5);
348 } else if (markType
== SC_MARK_SHORTARROW
) {
350 Point(centreX
, centreY
+ dimOn2
),
351 Point(centreX
+ dimOn2
, centreY
),
352 Point(centreX
, centreY
- dimOn2
),
353 Point(centreX
, centreY
- dimOn4
),
354 Point(centreX
- dimOn4
, centreY
- dimOn4
),
355 Point(centreX
- dimOn4
, centreY
+ dimOn4
),
356 Point(centreX
, centreY
+ dimOn4
),
357 Point(centreX
, centreY
+ dimOn2
),
359 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
360 fore
.allocated
, back
.allocated
);
361 } else if (markType
== SC_MARK_LEFTRECT
) {
362 PRectangle rcLeft
= rcWhole
;
363 rcLeft
.right
= rcLeft
.left
+ 4;
364 surface
->FillRectangle(rcLeft
, back
.allocated
);
365 } else { // SC_MARK_FULLRECT
366 surface
->FillRectangle(rcWhole
, back
.allocated
);