1 // Scintilla source code edit control
2 /** @file LineMarker.cxx
3 ** Defines the look of a line marker in the margin .
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.
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
);
24 pxpm
->RefreshColourPalette(pal
, want
);
28 void LineMarker::SetXPM(const char *textForm
) {
30 pxpm
= new XPM(textForm
);
31 markType
= SC_MARK_PIXMAP
;
34 void LineMarker::SetXPM(const char * const *linesForm
) {
36 pxpm
= new XPM(linesForm
);
37 markType
= SC_MARK_PIXMAP
;
40 static void DrawBox(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
42 rc
.left
= centreX
- armSize
;
43 rc
.top
= centreY
- armSize
;
44 rc
.right
= centreX
+ armSize
+ 1;
45 rc
.bottom
= centreY
+ armSize
+ 1;
46 surface
->RectangleDraw(rc
, back
, fore
);
49 static void DrawCircle(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
51 rcCircle
.left
= centreX
- armSize
;
52 rcCircle
.top
= centreY
- armSize
;
53 rcCircle
.right
= centreX
+ armSize
+ 1;
54 rcCircle
.bottom
= centreY
+ armSize
+ 1;
55 surface
->Ellipse(rcCircle
, back
, fore
);
58 static void DrawPlus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
59 PRectangle
rcV(centreX
, centreY
- armSize
+ 2, centreX
+ 1, centreY
+ armSize
- 2 + 1);
60 surface
->FillRectangle(rcV
, fore
);
61 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
62 surface
->FillRectangle(rcH
, fore
);
65 static void DrawMinus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
66 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
67 surface
->FillRectangle(rcH
, fore
);
70 void LineMarker::Draw(Surface
*surface
, PRectangle
&rcWhole
, Font
&fontForCharacter
) {
71 if ((markType
== SC_MARK_PIXMAP
) && (pxpm
)) {
72 pxpm
->Draw(surface
, rcWhole
);
75 // Restrict most shapes a bit
76 PRectangle rc
= rcWhole
;
79 int minDim
= Platform::Minimum(rc
.Width(), rc
.Height());
80 minDim
--; // Ensure does not go beyond edge
81 int centreX
= (rc
.right
+ rc
.left
) / 2;
82 int centreY
= (rc
.bottom
+ rc
.top
) / 2;
83 int dimOn2
= minDim
/ 2;
84 int dimOn4
= minDim
/ 4;
85 int blobSize
= dimOn2
-1;
86 int armSize
= dimOn2
-2;
87 if (rc
.Width() > (rc
.Height() * 2)) {
88 // Wide column is line number so move to left to try to avoid overlapping number
89 centreX
= rc
.left
+ dimOn2
+ 1;
91 if (markType
== SC_MARK_ROUNDRECT
) {
92 PRectangle rcRounded
= rc
;
93 rcRounded
.left
= rc
.left
+ 1;
94 rcRounded
.right
= rc
.right
- 1;
95 surface
->RoundedRectangle(rcRounded
, fore
.allocated
, back
.allocated
);
96 } else if (markType
== SC_MARK_CIRCLE
) {
98 rcCircle
.left
= centreX
- dimOn2
;
99 rcCircle
.top
= centreY
- dimOn2
;
100 rcCircle
.right
= centreX
+ dimOn2
;
101 rcCircle
.bottom
= centreY
+ dimOn2
;
102 surface
->Ellipse(rcCircle
, fore
.allocated
, back
.allocated
);
103 } else if (markType
== SC_MARK_ARROW
) {
105 Point(centreX
- dimOn4
, centreY
- dimOn2
),
106 Point(centreX
- dimOn4
, centreY
+ dimOn2
),
107 Point(centreX
+ dimOn2
- dimOn4
, centreY
),
109 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
110 fore
.allocated
, back
.allocated
);
112 } else if (markType
== SC_MARK_ARROWDOWN
) {
114 Point(centreX
- dimOn2
, centreY
- dimOn4
),
115 Point(centreX
+ dimOn2
, centreY
- dimOn4
),
116 Point(centreX
, centreY
+ dimOn2
- dimOn4
),
118 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
119 fore
.allocated
, back
.allocated
);
121 } else if (markType
== SC_MARK_PLUS
) {
123 Point(centreX
- armSize
, centreY
- 1),
124 Point(centreX
- 1, centreY
- 1),
125 Point(centreX
- 1, centreY
- armSize
),
126 Point(centreX
+ 1, centreY
- armSize
),
127 Point(centreX
+ 1, centreY
- 1),
128 Point(centreX
+ armSize
, centreY
-1),
129 Point(centreX
+ armSize
, centreY
+1),
130 Point(centreX
+ 1, centreY
+ 1),
131 Point(centreX
+ 1, centreY
+ armSize
),
132 Point(centreX
- 1, centreY
+ armSize
),
133 Point(centreX
- 1, centreY
+ 1),
134 Point(centreX
- armSize
, centreY
+ 1),
136 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
137 fore
.allocated
, back
.allocated
);
139 } else if (markType
== SC_MARK_MINUS
) {
141 Point(centreX
- armSize
, centreY
- 1),
142 Point(centreX
+ armSize
, centreY
-1),
143 Point(centreX
+ armSize
, centreY
+1),
144 Point(centreX
- armSize
, centreY
+ 1),
146 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
147 fore
.allocated
, back
.allocated
);
149 } else if (markType
== SC_MARK_SMALLRECT
) {
151 rcSmall
.left
= rc
.left
+ 1;
152 rcSmall
.top
= rc
.top
+ 2;
153 rcSmall
.right
= rc
.right
- 1;
154 rcSmall
.bottom
= rc
.bottom
- 2;
155 surface
->RectangleDraw(rcSmall
, fore
.allocated
, back
.allocated
);
157 } else if (markType
== SC_MARK_EMPTY
|| markType
== SC_MARK_BACKGROUND
||
158 markType
== SC_MARK_UNDERLINE
|| markType
== SC_MARK_AVAILABLE
) {
159 // An invisible marker so don't draw anything
161 } else if (markType
== SC_MARK_VLINE
) {
162 surface
->PenColour(back
.allocated
);
163 surface
->MoveTo(centreX
, rcWhole
.top
);
164 surface
->LineTo(centreX
, rcWhole
.bottom
);
166 } else if (markType
== SC_MARK_LCORNER
) {
167 surface
->PenColour(back
.allocated
);
168 surface
->MoveTo(centreX
, rcWhole
.top
);
169 surface
->LineTo(centreX
, rc
.top
+ dimOn2
);
170 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
172 } else if (markType
== SC_MARK_TCORNER
) {
173 surface
->PenColour(back
.allocated
);
174 surface
->MoveTo(centreX
, rcWhole
.top
);
175 surface
->LineTo(centreX
, rcWhole
.bottom
);
176 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
);
177 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
179 } else if (markType
== SC_MARK_LCORNERCURVE
) {
180 surface
->PenColour(back
.allocated
);
181 surface
->MoveTo(centreX
, rcWhole
.top
);
182 surface
->LineTo(centreX
, rc
.top
+ dimOn2
-3);
183 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
184 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
186 } else if (markType
== SC_MARK_TCORNERCURVE
) {
187 surface
->PenColour(back
.allocated
);
188 surface
->MoveTo(centreX
, rcWhole
.top
);
189 surface
->LineTo(centreX
, rcWhole
.bottom
);
191 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
-3);
192 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
193 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
195 } else if (markType
== SC_MARK_BOXPLUS
) {
196 surface
->PenColour(back
.allocated
);
197 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
198 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
200 } else if (markType
== SC_MARK_BOXPLUSCONNECTED
) {
201 surface
->PenColour(back
.allocated
);
202 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
203 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
205 surface
->MoveTo(centreX
, centreY
+ blobSize
);
206 surface
->LineTo(centreX
, rcWhole
.bottom
);
208 surface
->MoveTo(centreX
, rcWhole
.top
);
209 surface
->LineTo(centreX
, centreY
- blobSize
);
211 } else if (markType
== SC_MARK_BOXMINUS
) {
212 surface
->PenColour(back
.allocated
);
213 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
214 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
216 surface
->MoveTo(centreX
, centreY
+ blobSize
);
217 surface
->LineTo(centreX
, rcWhole
.bottom
);
219 } else if (markType
== SC_MARK_BOXMINUSCONNECTED
) {
220 surface
->PenColour(back
.allocated
);
221 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
222 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
224 surface
->MoveTo(centreX
, centreY
+ blobSize
);
225 surface
->LineTo(centreX
, rcWhole
.bottom
);
227 surface
->MoveTo(centreX
, rcWhole
.top
);
228 surface
->LineTo(centreX
, centreY
- blobSize
);
230 } else if (markType
== SC_MARK_CIRCLEPLUS
) {
231 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
232 surface
->PenColour(back
.allocated
);
233 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
235 } else if (markType
== SC_MARK_CIRCLEPLUSCONNECTED
) {
236 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
237 surface
->PenColour(back
.allocated
);
238 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
240 surface
->MoveTo(centreX
, centreY
+ blobSize
);
241 surface
->LineTo(centreX
, rcWhole
.bottom
);
243 surface
->MoveTo(centreX
, rcWhole
.top
);
244 surface
->LineTo(centreX
, centreY
- blobSize
);
246 } else if (markType
== SC_MARK_CIRCLEMINUS
) {
247 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
248 surface
->PenColour(back
.allocated
);
249 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
251 surface
->MoveTo(centreX
, centreY
+ blobSize
);
252 surface
->LineTo(centreX
, rcWhole
.bottom
);
254 } else if (markType
== SC_MARK_CIRCLEMINUSCONNECTED
) {
255 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
256 surface
->PenColour(back
.allocated
);
257 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
259 surface
->MoveTo(centreX
, centreY
+ blobSize
);
260 surface
->LineTo(centreX
, rcWhole
.bottom
);
262 surface
->MoveTo(centreX
, rcWhole
.top
);
263 surface
->LineTo(centreX
, centreY
- blobSize
);
265 } else if (markType
>= SC_MARK_CHARACTER
) {
267 character
[0] = static_cast<char>(markType
- SC_MARK_CHARACTER
);
268 int width
= surface
->WidthText(fontForCharacter
, character
, 1);
269 rc
.left
+= (rc
.Width() - width
) / 2;
270 rc
.right
= rc
.left
+ width
;
271 surface
->DrawTextClipped(rc
, fontForCharacter
, rc
.bottom
- 2,
272 character
, 1, fore
.allocated
, back
.allocated
);
274 } else if (markType
== SC_MARK_DOTDOTDOT
) {
275 int right
= centreX
- 6;
276 for (int b
=0; b
<3; b
++) {
277 PRectangle
rcBlob(right
, rc
.bottom
- 4, right
+ 2, rc
.bottom
-2);
278 surface
->FillRectangle(rcBlob
, fore
.allocated
);
281 } else if (markType
== SC_MARK_ARROWS
) {
282 surface
->PenColour(fore
.allocated
);
283 int right
= centreX
- 2;
284 for (int b
=0; b
<3; b
++) {
285 surface
->MoveTo(right
- 4, centreY
- 4);
286 surface
->LineTo(right
, centreY
);
287 surface
->LineTo(right
- 5, centreY
+ 5);
290 } else if (markType
== SC_MARK_SHORTARROW
) {
292 Point(centreX
, centreY
+ dimOn2
),
293 Point(centreX
+ dimOn2
, centreY
),
294 Point(centreX
, centreY
- dimOn2
),
295 Point(centreX
, centreY
- dimOn4
),
296 Point(centreX
- dimOn4
, centreY
- dimOn4
),
297 Point(centreX
- dimOn4
, centreY
+ dimOn4
),
298 Point(centreX
, centreY
+ dimOn4
),
299 Point(centreX
, centreY
+ dimOn2
),
301 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
302 fore
.allocated
, back
.allocated
);
303 } else if (markType
== SC_MARK_LEFTRECT
) {
304 PRectangle rcLeft
= rcWhole
;
305 rcLeft
.right
= rcLeft
.left
+ 4;
306 surface
->FillRectangle(rcLeft
, back
.allocated
);
307 } else { // SC_MARK_FULLRECT
308 surface
->FillRectangle(rcWhole
, back
.allocated
);