1 // Scintilla source code edit control
\r
2 /** @file LineMarker.cxx
\r
3 ** Defines the look of a line marker in the margin .
\r
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
\r
6 // The License.txt file describes the conditions under which this software may be distributed.
\r
10 #include "Platform.h"
\r
12 #include "Scintilla.h"
\r
14 #include "LineMarker.h"
\r
16 #ifdef SCI_NAMESPACE
\r
17 using namespace Scintilla;
\r
20 void LineMarker::RefreshColourPalette(Palette &pal, bool want) {
\r
21 pal.WantFind(fore, want);
\r
22 pal.WantFind(back, want);
\r
24 pxpm->RefreshColourPalette(pal, want);
\r
28 void LineMarker::SetXPM(const char *textForm) {
\r
30 pxpm = new XPM(textForm);
\r
31 markType = SC_MARK_PIXMAP;
\r
34 void LineMarker::SetXPM(const char * const *linesForm) {
\r
36 pxpm = new XPM(linesForm);
\r
37 markType = SC_MARK_PIXMAP;
\r
40 static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
\r
42 rc.left = centreX - armSize;
\r
43 rc.top = centreY - armSize;
\r
44 rc.right = centreX + armSize + 1;
\r
45 rc.bottom = centreY + armSize + 1;
\r
46 surface->RectangleDraw(rc, back, fore);
\r
49 static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
\r
50 PRectangle rcCircle;
\r
51 rcCircle.left = centreX - armSize;
\r
52 rcCircle.top = centreY - armSize;
\r
53 rcCircle.right = centreX + armSize + 1;
\r
54 rcCircle.bottom = centreY + armSize + 1;
\r
55 surface->Ellipse(rcCircle, back, fore);
\r
58 static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
\r
59 PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
\r
60 surface->FillRectangle(rcV, fore);
\r
61 PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
\r
62 surface->FillRectangle(rcH, fore);
\r
65 static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
\r
66 PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
\r
67 surface->FillRectangle(rcH, fore);
\r
70 void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) {
\r
71 if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
\r
72 pxpm->Draw(surface, rcWhole);
\r
75 // Restrict most shapes a bit
\r
76 PRectangle rc = rcWhole;
\r
79 int minDim = Platform::Minimum(rc.Width(), rc.Height());
\r
80 minDim--; // Ensure does not go beyond edge
\r
81 int centreX = (rc.right + rc.left) / 2;
\r
82 int centreY = (rc.bottom + rc.top) / 2;
\r
83 int dimOn2 = minDim / 2;
\r
84 int dimOn4 = minDim / 4;
\r
85 int blobSize = dimOn2-1;
\r
86 int armSize = dimOn2-2;
\r
87 if (rc.Width() > (rc.Height() * 2)) {
\r
88 // Wide column is line number so move to left to try to avoid overlapping number
\r
89 centreX = rc.left + dimOn2 + 1;
\r
91 if (markType == SC_MARK_ROUNDRECT) {
\r
92 PRectangle rcRounded = rc;
\r
93 rcRounded.left = rc.left + 1;
\r
94 rcRounded.right = rc.right - 1;
\r
95 surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
\r
96 } else if (markType == SC_MARK_CIRCLE) {
\r
97 PRectangle rcCircle;
\r
98 rcCircle.left = centreX - dimOn2;
\r
99 rcCircle.top = centreY - dimOn2;
\r
100 rcCircle.right = centreX + dimOn2;
\r
101 rcCircle.bottom = centreY + dimOn2;
\r
102 surface->Ellipse(rcCircle, fore.allocated, back.allocated);
\r
103 } else if (markType == SC_MARK_ARROW) {
\r
105 Point(centreX - dimOn4, centreY - dimOn2),
\r
106 Point(centreX - dimOn4, centreY + dimOn2),
\r
107 Point(centreX + dimOn2 - dimOn4, centreY),
\r
109 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
\r
110 fore.allocated, back.allocated);
\r
112 } else if (markType == SC_MARK_ARROWDOWN) {
\r
114 Point(centreX - dimOn2, centreY - dimOn4),
\r
115 Point(centreX + dimOn2, centreY - dimOn4),
\r
116 Point(centreX, centreY + dimOn2 - dimOn4),
\r
118 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
\r
119 fore.allocated, back.allocated);
\r
121 } else if (markType == SC_MARK_PLUS) {
\r
123 Point(centreX - armSize, centreY - 1),
\r
124 Point(centreX - 1, centreY - 1),
\r
125 Point(centreX - 1, centreY - armSize),
\r
126 Point(centreX + 1, centreY - armSize),
\r
127 Point(centreX + 1, centreY - 1),
\r
128 Point(centreX + armSize, centreY -1),
\r
129 Point(centreX + armSize, centreY +1),
\r
130 Point(centreX + 1, centreY + 1),
\r
131 Point(centreX + 1, centreY + armSize),
\r
132 Point(centreX - 1, centreY + armSize),
\r
133 Point(centreX - 1, centreY + 1),
\r
134 Point(centreX - armSize, centreY + 1),
\r
136 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
\r
137 fore.allocated, back.allocated);
\r
139 } else if (markType == SC_MARK_MINUS) {
\r
141 Point(centreX - armSize, centreY - 1),
\r
142 Point(centreX + armSize, centreY -1),
\r
143 Point(centreX + armSize, centreY +1),
\r
144 Point(centreX - armSize, centreY + 1),
\r
146 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
\r
147 fore.allocated, back.allocated);
\r
149 } else if (markType == SC_MARK_SMALLRECT) {
\r
150 PRectangle rcSmall;
\r
151 rcSmall.left = rc.left + 1;
\r
152 rcSmall.top = rc.top + 2;
\r
153 rcSmall.right = rc.right - 1;
\r
154 rcSmall.bottom = rc.bottom - 2;
\r
155 surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);
\r
157 } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND) {
\r
158 // An invisible marker so don't draw anything
\r
160 } else if (markType == SC_MARK_VLINE) {
\r
161 surface->PenColour(back.allocated);
\r
162 surface->MoveTo(centreX, rcWhole.top);
\r
163 surface->LineTo(centreX, rcWhole.bottom);
\r
165 } else if (markType == SC_MARK_LCORNER) {
\r
166 surface->PenColour(back.allocated);
\r
167 surface->MoveTo(centreX, rcWhole.top);
\r
168 surface->LineTo(centreX, rc.top + dimOn2);
\r
169 surface->LineTo(rc.right - 2, rc.top + dimOn2);
\r
171 } else if (markType == SC_MARK_TCORNER) {
\r
172 surface->PenColour(back.allocated);
\r
173 surface->MoveTo(centreX, rcWhole.top);
\r
174 surface->LineTo(centreX, rcWhole.bottom);
\r
175 surface->MoveTo(centreX, rc.top + dimOn2);
\r
176 surface->LineTo(rc.right - 2, rc.top + dimOn2);
\r
178 } else if (markType == SC_MARK_LCORNERCURVE) {
\r
179 surface->PenColour(back.allocated);
\r
180 surface->MoveTo(centreX, rcWhole.top);
\r
181 surface->LineTo(centreX, rc.top + dimOn2-3);
\r
182 surface->LineTo(centreX+3, rc.top + dimOn2);
\r
183 surface->LineTo(rc.right - 1, rc.top + dimOn2);
\r
185 } else if (markType == SC_MARK_TCORNERCURVE) {
\r
186 surface->PenColour(back.allocated);
\r
187 surface->MoveTo(centreX, rcWhole.top);
\r
188 surface->LineTo(centreX, rcWhole.bottom);
\r
190 surface->MoveTo(centreX, rc.top + dimOn2-3);
\r
191 surface->LineTo(centreX+3, rc.top + dimOn2);
\r
192 surface->LineTo(rc.right - 1, rc.top + dimOn2);
\r
194 } else if (markType == SC_MARK_BOXPLUS) {
\r
195 surface->PenColour(back.allocated);
\r
196 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
197 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
\r
199 } else if (markType == SC_MARK_BOXPLUSCONNECTED) {
\r
200 surface->PenColour(back.allocated);
\r
201 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
202 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
\r
204 surface->MoveTo(centreX, centreY + blobSize);
\r
205 surface->LineTo(centreX, rcWhole.bottom);
\r
207 surface->MoveTo(centreX, rcWhole.top);
\r
208 surface->LineTo(centreX, centreY - blobSize);
\r
210 } else if (markType == SC_MARK_BOXMINUS) {
\r
211 surface->PenColour(back.allocated);
\r
212 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
213 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
\r
215 surface->MoveTo(centreX, centreY + blobSize);
\r
216 surface->LineTo(centreX, rcWhole.bottom);
\r
218 } else if (markType == SC_MARK_BOXMINUSCONNECTED) {
\r
219 surface->PenColour(back.allocated);
\r
220 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
221 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
\r
223 surface->MoveTo(centreX, centreY + blobSize);
\r
224 surface->LineTo(centreX, rcWhole.bottom);
\r
226 surface->MoveTo(centreX, rcWhole.top);
\r
227 surface->LineTo(centreX, centreY - blobSize);
\r
229 } else if (markType == SC_MARK_CIRCLEPLUS) {
\r
230 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
231 surface->PenColour(back.allocated);
\r
232 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
\r
234 } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
\r
235 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
236 surface->PenColour(back.allocated);
\r
237 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
\r
239 surface->MoveTo(centreX, centreY + blobSize);
\r
240 surface->LineTo(centreX, rcWhole.bottom);
\r
242 surface->MoveTo(centreX, rcWhole.top);
\r
243 surface->LineTo(centreX, centreY - blobSize);
\r
245 } else if (markType == SC_MARK_CIRCLEMINUS) {
\r
246 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
247 surface->PenColour(back.allocated);
\r
248 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
\r
250 surface->MoveTo(centreX, centreY + blobSize);
\r
251 surface->LineTo(centreX, rcWhole.bottom);
\r
253 } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
\r
254 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
\r
255 surface->PenColour(back.allocated);
\r
256 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
\r
258 surface->MoveTo(centreX, centreY + blobSize);
\r
259 surface->LineTo(centreX, rcWhole.bottom);
\r
261 surface->MoveTo(centreX, rcWhole.top);
\r
262 surface->LineTo(centreX, centreY - blobSize);
\r
264 } else if (markType >= SC_MARK_CHARACTER) {
\r
266 character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
\r
267 int width = surface->WidthText(fontForCharacter, character, 1);
\r
268 rc.left += (rc.Width() - width) / 2;
\r
269 rc.right = rc.left + width;
\r
270 surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
\r
271 character, 1, fore.allocated, back.allocated);
\r
273 } else if (markType == SC_MARK_DOTDOTDOT) {
\r
274 int right = centreX - 6;
\r
275 for (int b=0; b<3; b++) {
\r
276 PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
\r
277 surface->FillRectangle(rcBlob, fore.allocated);
\r
280 } else if (markType == SC_MARK_ARROWS) {
\r
281 surface->PenColour(fore.allocated);
\r
282 int right = centreX - 2;
\r
283 for (int b=0; b<3; b++) {
\r
284 surface->MoveTo(right - 4, centreY - 4);
\r
285 surface->LineTo(right, centreY);
\r
286 surface->LineTo(right - 5, centreY + 5);
\r
289 } else if (markType == SC_MARK_SHORTARROW) {
\r
291 Point(centreX, centreY + dimOn2),
\r
292 Point(centreX + dimOn2, centreY),
\r
293 Point(centreX, centreY - dimOn2),
\r
294 Point(centreX, centreY - dimOn4),
\r
295 Point(centreX - dimOn4, centreY - dimOn4),
\r
296 Point(centreX - dimOn4, centreY + dimOn4),
\r
297 Point(centreX, centreY + dimOn4),
\r
298 Point(centreX, centreY + dimOn2),
\r
300 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
\r
301 fore.allocated, back.allocated);
\r
302 } else if (markType == SC_MARK_LEFTRECT) {
\r
303 PRectangle rcLeft = rcWhole;
\r
304 rcLeft.right = rcLeft.left + 4;
\r
305 surface->FillRectangle(rcLeft, back.allocated);
\r
306 } else { // SC_MARK_FULLRECT
\r
307 surface->FillRectangle(rcWhole, back.allocated);
\r