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"
16 void LineMarker::RefreshColourPalette(Palette
&pal
, bool want
) {
17 pal
.WantFind(fore
, want
);
18 pal
.WantFind(back
, want
);
20 pxpm
->RefreshColourPalette(pal
, want
);
24 void LineMarker::SetXPM(const char *textForm
) {
26 pxpm
= new XPM(textForm
);
27 markType
= SC_MARK_PIXMAP
;
30 void LineMarker::SetXPM(const char * const *linesForm
) {
32 pxpm
= new XPM(linesForm
);
33 markType
= SC_MARK_PIXMAP
;
36 static void DrawBox(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
38 rc
.left
= centreX
- armSize
;
39 rc
.top
= centreY
- armSize
;
40 rc
.right
= centreX
+ armSize
+ 1;
41 rc
.bottom
= centreY
+ armSize
+ 1;
42 surface
->RectangleDraw(rc
, back
, fore
);
45 static void DrawCircle(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
, ColourAllocated back
) {
47 rcCircle
.left
= centreX
- armSize
;
48 rcCircle
.top
= centreY
- armSize
;
49 rcCircle
.right
= centreX
+ armSize
+ 1;
50 rcCircle
.bottom
= centreY
+ armSize
+ 1;
51 surface
->Ellipse(rcCircle
, back
, fore
);
54 static void DrawPlus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
55 PRectangle
rcV(centreX
, centreY
- armSize
+ 2, centreX
+ 1, centreY
+ armSize
- 2 + 1);
56 surface
->FillRectangle(rcV
, fore
);
57 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
58 surface
->FillRectangle(rcH
, fore
);
61 static void DrawMinus(Surface
*surface
, int centreX
, int centreY
, int armSize
, ColourAllocated fore
) {
62 PRectangle
rcH(centreX
- armSize
+ 2, centreY
, centreX
+ armSize
- 2 + 1, centreY
+1);
63 surface
->FillRectangle(rcH
, fore
);
66 void LineMarker::Draw(Surface
*surface
, PRectangle
&rcWhole
, Font
&fontForCharacter
) {
67 if ((markType
== SC_MARK_PIXMAP
) && (pxpm
)) {
68 pxpm
->Draw(surface
, rcWhole
);
71 // Restrict most shapes a bit
72 PRectangle rc
= rcWhole
;
75 int minDim
= Platform::Minimum(rc
.Width(), rc
.Height());
76 minDim
--; // Ensure does not go beyond edge
77 int centreX
= (rc
.right
+ rc
.left
) / 2;
78 int centreY
= (rc
.bottom
+ rc
.top
) / 2;
79 int dimOn2
= minDim
/ 2;
80 int dimOn4
= minDim
/ 4;
81 int blobSize
= dimOn2
-1;
82 int armSize
= dimOn2
-2;
83 if (rc
.Width() > (rc
.Height() * 2)) {
84 // Wide column is line number so move to left to try to avoid overlapping number
85 centreX
= rc
.left
+ dimOn2
+ 1;
87 if (markType
== SC_MARK_ROUNDRECT
) {
88 PRectangle rcRounded
= rc
;
89 rcRounded
.left
= rc
.left
+ 1;
90 rcRounded
.right
= rc
.right
- 1;
91 surface
->RoundedRectangle(rcRounded
, fore
.allocated
, back
.allocated
);
92 } else if (markType
== SC_MARK_CIRCLE
) {
94 rcCircle
.left
= centreX
- dimOn2
;
95 rcCircle
.top
= centreY
- dimOn2
;
96 rcCircle
.right
= centreX
+ dimOn2
;
97 rcCircle
.bottom
= centreY
+ dimOn2
;
98 surface
->Ellipse(rcCircle
, fore
.allocated
, back
.allocated
);
99 } else if (markType
== SC_MARK_ARROW
) {
101 Point(centreX
- dimOn4
, centreY
- dimOn2
),
102 Point(centreX
- dimOn4
, centreY
+ dimOn2
),
103 Point(centreX
+ dimOn2
- dimOn4
, centreY
),
105 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
106 fore
.allocated
, back
.allocated
);
108 } else if (markType
== SC_MARK_ARROWDOWN
) {
110 Point(centreX
- dimOn2
, centreY
- dimOn4
),
111 Point(centreX
+ dimOn2
, centreY
- dimOn4
),
112 Point(centreX
, centreY
+ dimOn2
- dimOn4
),
114 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
115 fore
.allocated
, back
.allocated
);
117 } else if (markType
== SC_MARK_PLUS
) {
119 Point(centreX
- armSize
, centreY
- 1),
120 Point(centreX
- 1, centreY
- 1),
121 Point(centreX
- 1, centreY
- armSize
),
122 Point(centreX
+ 1, centreY
- armSize
),
123 Point(centreX
+ 1, centreY
- 1),
124 Point(centreX
+ armSize
, centreY
-1),
125 Point(centreX
+ armSize
, centreY
+1),
126 Point(centreX
+ 1, centreY
+ 1),
127 Point(centreX
+ 1, centreY
+ armSize
),
128 Point(centreX
- 1, centreY
+ armSize
),
129 Point(centreX
- 1, centreY
+ 1),
130 Point(centreX
- armSize
, centreY
+ 1),
132 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
133 fore
.allocated
, back
.allocated
);
135 } else if (markType
== SC_MARK_MINUS
) {
137 Point(centreX
- armSize
, centreY
- 1),
138 Point(centreX
+ armSize
, centreY
-1),
139 Point(centreX
+ armSize
, centreY
+1),
140 Point(centreX
- armSize
, centreY
+ 1),
142 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
143 fore
.allocated
, back
.allocated
);
145 } else if (markType
== SC_MARK_SMALLRECT
) {
147 rcSmall
.left
= rc
.left
+ 1;
148 rcSmall
.top
= rc
.top
+ 2;
149 rcSmall
.right
= rc
.right
- 1;
150 rcSmall
.bottom
= rc
.bottom
- 2;
151 surface
->RectangleDraw(rcSmall
, fore
.allocated
, back
.allocated
);
153 } else if (markType
== SC_MARK_EMPTY
|| markType
== SC_MARK_BACKGROUND
) {
154 // An invisible marker so don't draw anything
156 } else if (markType
== SC_MARK_VLINE
) {
157 surface
->PenColour(back
.allocated
);
158 surface
->MoveTo(centreX
, rcWhole
.top
);
159 surface
->LineTo(centreX
, rcWhole
.bottom
);
161 } else if (markType
== SC_MARK_LCORNER
) {
162 surface
->PenColour(back
.allocated
);
163 surface
->MoveTo(centreX
, rcWhole
.top
);
164 surface
->LineTo(centreX
, rc
.top
+ dimOn2
);
165 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
167 } else if (markType
== SC_MARK_TCORNER
) {
168 surface
->PenColour(back
.allocated
);
169 surface
->MoveTo(centreX
, rcWhole
.top
);
170 surface
->LineTo(centreX
, rcWhole
.bottom
);
171 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
);
172 surface
->LineTo(rc
.right
- 2, rc
.top
+ dimOn2
);
174 } else if (markType
== SC_MARK_LCORNERCURVE
) {
175 surface
->PenColour(back
.allocated
);
176 surface
->MoveTo(centreX
, rcWhole
.top
);
177 surface
->LineTo(centreX
, rc
.top
+ dimOn2
-3);
178 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
179 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
181 } else if (markType
== SC_MARK_TCORNERCURVE
) {
182 surface
->PenColour(back
.allocated
);
183 surface
->MoveTo(centreX
, rcWhole
.top
);
184 surface
->LineTo(centreX
, rcWhole
.bottom
);
186 surface
->MoveTo(centreX
, rc
.top
+ dimOn2
-3);
187 surface
->LineTo(centreX
+3, rc
.top
+ dimOn2
);
188 surface
->LineTo(rc
.right
- 1, rc
.top
+ dimOn2
);
190 } else if (markType
== SC_MARK_BOXPLUS
) {
191 surface
->PenColour(back
.allocated
);
192 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
193 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
195 } else if (markType
== SC_MARK_BOXPLUSCONNECTED
) {
196 surface
->PenColour(back
.allocated
);
197 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
198 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
200 surface
->MoveTo(centreX
, centreY
+ blobSize
);
201 surface
->LineTo(centreX
, rcWhole
.bottom
);
203 surface
->MoveTo(centreX
, rcWhole
.top
);
204 surface
->LineTo(centreX
, centreY
- blobSize
);
206 } else if (markType
== SC_MARK_BOXMINUS
) {
207 surface
->PenColour(back
.allocated
);
208 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
209 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
211 surface
->MoveTo(centreX
, centreY
+ blobSize
);
212 surface
->LineTo(centreX
, rcWhole
.bottom
);
214 } else if (markType
== SC_MARK_BOXMINUSCONNECTED
) {
215 surface
->PenColour(back
.allocated
);
216 DrawBox(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
217 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
219 surface
->MoveTo(centreX
, centreY
+ blobSize
);
220 surface
->LineTo(centreX
, rcWhole
.bottom
);
222 surface
->MoveTo(centreX
, rcWhole
.top
);
223 surface
->LineTo(centreX
, centreY
- blobSize
);
225 } else if (markType
== SC_MARK_CIRCLEPLUS
) {
226 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
227 surface
->PenColour(back
.allocated
);
228 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
230 } else if (markType
== SC_MARK_CIRCLEPLUSCONNECTED
) {
231 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
232 surface
->PenColour(back
.allocated
);
233 DrawPlus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
235 surface
->MoveTo(centreX
, centreY
+ blobSize
);
236 surface
->LineTo(centreX
, rcWhole
.bottom
);
238 surface
->MoveTo(centreX
, rcWhole
.top
);
239 surface
->LineTo(centreX
, centreY
- blobSize
);
241 } else if (markType
== SC_MARK_CIRCLEMINUS
) {
242 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
243 surface
->PenColour(back
.allocated
);
244 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
246 surface
->MoveTo(centreX
, centreY
+ blobSize
);
247 surface
->LineTo(centreX
, rcWhole
.bottom
);
249 } else if (markType
== SC_MARK_CIRCLEMINUSCONNECTED
) {
250 DrawCircle(surface
, centreX
, centreY
, blobSize
, fore
.allocated
, back
.allocated
);
251 surface
->PenColour(back
.allocated
);
252 DrawMinus(surface
, centreX
, centreY
, blobSize
, back
.allocated
);
254 surface
->MoveTo(centreX
, centreY
+ blobSize
);
255 surface
->LineTo(centreX
, rcWhole
.bottom
);
257 surface
->MoveTo(centreX
, rcWhole
.top
);
258 surface
->LineTo(centreX
, centreY
- blobSize
);
260 } else if (markType
>= SC_MARK_CHARACTER
) {
262 character
[0] = static_cast<char>(markType
- SC_MARK_CHARACTER
);
263 int width
= surface
->WidthText(fontForCharacter
, character
, 1);
264 rc
.left
+= (rc
.Width() - width
) / 2;
265 rc
.right
= rc
.left
+ width
;
266 surface
->DrawTextClipped(rc
, fontForCharacter
, rc
.bottom
- 2,
267 character
, 1, fore
.allocated
, back
.allocated
);
269 } else if (markType
== SC_MARK_DOTDOTDOT
) {
270 int right
= centreX
- 6;
271 for (int b
=0; b
<3; b
++) {
272 PRectangle
rcBlob(right
, rc
.bottom
- 4, right
+ 2, rc
.bottom
-2);
273 surface
->FillRectangle(rcBlob
, fore
.allocated
);
276 } else if (markType
== SC_MARK_ARROWS
) {
277 surface
->PenColour(fore
.allocated
);
278 int right
= centreX
- 2;
279 for (int b
=0; b
<3; b
++) {
280 surface
->MoveTo(right
- 4, centreY
- 4);
281 surface
->LineTo(right
, centreY
);
282 surface
->LineTo(right
- 5, centreY
+ 5);
285 } else { // SC_MARK_SHORTARROW
287 Point(centreX
, centreY
+ dimOn2
),
288 Point(centreX
+ dimOn2
, centreY
),
289 Point(centreX
, centreY
- dimOn2
),
290 Point(centreX
, centreY
- dimOn4
),
291 Point(centreX
- dimOn4
, centreY
- dimOn4
),
292 Point(centreX
- dimOn4
, centreY
+ dimOn4
),
293 Point(centreX
, centreY
+ dimOn4
),
294 Point(centreX
, centreY
+ dimOn2
),
296 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]),
297 fore
.allocated
, back
.allocated
);