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 // An invisible marker so don't draw anything
160 } else if (markType
== SC_MARK_VLINE
) {
161 surface
->PenColour(back
.allocated
);
162 surface
->MoveTo(centreX
, rcWhole
.top
);
163 surface
->LineTo(centreX
, rcWhole
.bottom
);
165 } else if (markType
== SC_MARK_LCORNER
) {
166 surface
->PenColour(back
.allocated
);
167 surface
->MoveTo(centreX
, rcWhole
.top
);
168 surface
->LineTo(centreX
, rc
.top
+ dimOn2
);
169 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
171 } else if (markType
== SC_MARK_TCORNER
) {
172 surface
->PenColour(back
.allocated
);
173 surface
->MoveTo(centreX
, rcWhole
.top
);
174 surface
->LineTo(centreX
, rcWhole
.bottom
);
175 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
);
176 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
178 } else if (markType
== SC_MARK_LCORNERCURVE
) {
179 surface
->PenColour(back
.allocated
);
180 surface
->MoveTo(centreX
, rcWhole
.top
);
181 surface
->LineTo(centreX
, rc
.top
+ dimOn2
-3);
182 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
183 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
185 } else if (markType
== SC_MARK_TCORNERCURVE
) {
186 surface
->PenColour(back
.allocated
);
187 surface
->MoveTo(centreX
, rcWhole
.top
);
188 surface
->LineTo(centreX
, rcWhole
.bottom
);
190 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
-3);
191 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
192 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
194 } else if (markType
== SC_MARK_BOXPLUS
) {
195 surface
->PenColour(back
.allocated
);
196 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
197 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
199 } else if (markType
== SC_MARK_BOXPLUSCONNECTED
) {
200 surface
->PenColour(back
.allocated
);
201 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
202 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
204 surface
->MoveTo(centreX
, centreY
+ blobSize
);
205 surface
->LineTo(centreX
, rcWhole
.bottom
);
207 surface
->MoveTo(centreX
, rcWhole
.top
);
208 surface
->LineTo(centreX
, centreY
- blobSize
);
210 } else if (markType
== SC_MARK_BOXMINUS
) {
211 surface
->PenColour(back
.allocated
);
212 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
213 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
215 surface
->MoveTo(centreX
, centreY
+ blobSize
);
216 surface
->LineTo(centreX
, rcWhole
.bottom
);
218 } else if (markType
== SC_MARK_BOXMINUSCONNECTED
) {
219 surface
->PenColour(back
.allocated
);
220 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
221 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
223 surface
->MoveTo(centreX
, centreY
+ blobSize
);
224 surface
->LineTo(centreX
, rcWhole
.bottom
);
226 surface
->MoveTo(centreX
, rcWhole
.top
);
227 surface
->LineTo(centreX
, centreY
- blobSize
);
229 } else if (markType
== SC_MARK_CIRCLEPLUS
) {
230 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
231 surface
->PenColour(back
.allocated
);
232 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
234 } else if (markType
== SC_MARK_CIRCLEPLUSCONNECTED
) {
235 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
236 surface
->PenColour(back
.allocated
);
237 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
239 surface
->MoveTo(centreX
, centreY
+ blobSize
);
240 surface
->LineTo(centreX
, rcWhole
.bottom
);
242 surface
->MoveTo(centreX
, rcWhole
.top
);
243 surface
->LineTo(centreX
, centreY
- blobSize
);
245 } else if (markType
== SC_MARK_CIRCLEMINUS
) {
246 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
247 surface
->PenColour(back
.allocated
);
248 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
250 surface
->MoveTo(centreX
, centreY
+ blobSize
);
251 surface
->LineTo(centreX
, rcWhole
.bottom
);
253 } else if (markType
== SC_MARK_CIRCLEMINUSCONNECTED
) {
254 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
255 surface
->PenColour(back
.allocated
);
256 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
258 surface
->MoveTo(centreX
, centreY
+ blobSize
);
259 surface
->LineTo(centreX
, rcWhole
.bottom
);
261 surface
->MoveTo(centreX
, rcWhole
.top
);
262 surface
->LineTo(centreX
, centreY
- blobSize
);
264 } else if (markType
>= SC_MARK_CHARACTER
) {
266 character
[0] = static_cast<char>(markType
- SC_MARK_CHARACTER
);
267 int width
= surface
->WidthText(fontForCharacter
, character
, 1);
268 rc
.left
+= (rc
.Width() - width
) / 2;
269 rc
.right
= rc
.left
+ width
;
270 surface
->DrawTextClipped(rc
, fontForCharacter
, rc
.bottom
- 2,
271 character
, 1, fore
.allocated
, back
.allocated
);
273 } else if (markType
== SC_MARK_DOTDOTDOT
) {
274 int right
= centreX
- 6;
275 for (int b
=0; b
<3; b
++) {
276 PRectangle
rcBlob(right
, rc
.bottom
- 4, right
+ 2, rc
.bottom
-2);
277 surface
->FillRectangle(rcBlob
, fore
.allocated
);
280 } else if (markType
== SC_MARK_ARROWS
) {
281 surface
->PenColour(fore
.allocated
);
282 int right
= centreX
- 2;
283 for (int b
=0; b
<3; b
++) {
284 surface
->MoveTo(right
- 4, centreY
- 4);
285 surface
->LineTo(right
, centreY
);
286 surface
->LineTo(right
- 5, centreY
+ 5);
289 } else if (markType
== SC_MARK_SHORTARROW
) {
291 Point(centreX
, centreY
+ dimOn2
),
292 Point(centreX
+ dimOn2
, centreY
),
293 Point(centreX
, centreY
- dimOn2
),
294 Point(centreX
, centreY
- dimOn4
),
295 Point(centreX
- dimOn4
, centreY
- dimOn4
),
296 Point(centreX
- dimOn4
, centreY
+ dimOn4
),
297 Point(centreX
, centreY
+ dimOn4
),
298 Point(centreX
, centreY
+ dimOn2
),
300 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
301 fore
.allocated
, back
.allocated
);
302 } else { // SC_MARK_FULLRECT
303 surface
->FillRectangle(rcWhole
, back
.allocated
);