Update of German translation
[geany-mirror.git] / scintilla / src / LineMarker.cxx
blob6239d1c9d8839f30b12a49b0f2ed3d17945ba5eb
1 // Scintilla source code edit control
2 /** @file LineMarker.cxx
3 ** Defines the look of a line marker in the margin.
4 **/
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.
8 #include <string.h>
9 #include <math.h>
11 #include <stdexcept>
12 #include <vector>
13 #include <map>
15 #include "Platform.h"
17 #include "Scintilla.h"
19 #include "StringCopy.h"
20 #include "XPM.h"
21 #include "LineMarker.h"
23 #ifdef SCI_NAMESPACE
24 using namespace Scintilla;
25 #endif
27 void LineMarker::SetXPM(const char *textForm) {
28 delete pxpm;
29 pxpm = new XPM(textForm);
30 markType = SC_MARK_PIXMAP;
33 void LineMarker::SetXPM(const char *const *linesForm) {
34 delete pxpm;
35 pxpm = new XPM(linesForm);
36 markType = SC_MARK_PIXMAP;
39 void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) {
40 delete image;
41 image = new RGBAImage(static_cast<int>(sizeRGBAImage.x), static_cast<int>(sizeRGBAImage.y), scale, pixelsRGBAImage);
42 markType = SC_MARK_RGBAIMAGE;
45 static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
46 PRectangle rc = PRectangle::FromInts(
47 centreX - armSize,
48 centreY - armSize,
49 centreX + armSize + 1,
50 centreY + armSize + 1);
51 surface->RectangleDraw(rc, back, fore);
54 static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
55 PRectangle rcCircle = PRectangle::FromInts(
56 centreX - armSize,
57 centreY - armSize,
58 centreX + armSize + 1,
59 centreY + armSize + 1);
60 surface->Ellipse(rcCircle, back, fore);
63 static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
64 PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
65 surface->FillRectangle(rcV, fore);
66 PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
67 surface->FillRectangle(rcH, fore);
70 static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
71 PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
72 surface->FillRectangle(rcH, fore);
75 void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const {
76 if (customDraw != NULL) {
77 customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this);
78 return;
81 ColourDesired colourHead = back;
82 ColourDesired colourBody = back;
83 ColourDesired colourTail = back;
85 switch (tFold) {
86 case LineMarker::head :
87 case LineMarker::headWithTail :
88 colourHead = backSelected;
89 colourTail = backSelected;
90 break;
91 case LineMarker::body :
92 colourHead = backSelected;
93 colourBody = backSelected;
94 break;
95 case LineMarker::tail :
96 colourBody = backSelected;
97 colourTail = backSelected;
98 break;
99 default :
100 // LineMarker::undefined
101 break;
104 if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
105 pxpm->Draw(surface, rcWhole);
106 return;
108 if ((markType == SC_MARK_RGBAIMAGE) && (image)) {
109 // Make rectangle just large enough to fit image centred on centre of rcWhole
110 PRectangle rcImage;
111 rcImage.top = ((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2;
112 rcImage.bottom = rcImage.top + image->GetScaledHeight();
113 rcImage.left = ((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2;
114 rcImage.right = rcImage.left + image->GetScaledWidth();
115 surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels());
116 return;
118 // Restrict most shapes a bit
119 PRectangle rc = rcWhole;
120 rc.top++;
121 rc.bottom--;
122 int minDim = Platform::Minimum(static_cast<int>(rc.Width()), static_cast<int>(rc.Height()));
123 minDim--; // Ensure does not go beyond edge
124 int centreX = static_cast<int>(floor((rc.right + rc.left) / 2.0));
125 int centreY = static_cast<int>(floor((rc.bottom + rc.top) / 2.0));
126 int dimOn2 = minDim / 2;
127 int dimOn4 = minDim / 4;
128 int blobSize = dimOn2-1;
129 int armSize = dimOn2-2;
130 if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) {
131 // On textual margins move marker to the left to try to avoid overlapping the text
132 centreX = static_cast<int>(rc.left) + dimOn2 + 1;
134 if (markType == SC_MARK_ROUNDRECT) {
135 PRectangle rcRounded = rc;
136 rcRounded.left = rc.left + 1;
137 rcRounded.right = rc.right - 1;
138 surface->RoundedRectangle(rcRounded, fore, back);
139 } else if (markType == SC_MARK_CIRCLE) {
140 PRectangle rcCircle = PRectangle::FromInts(
141 centreX - dimOn2,
142 centreY - dimOn2,
143 centreX + dimOn2,
144 centreY + dimOn2);
145 surface->Ellipse(rcCircle, fore, back);
146 } else if (markType == SC_MARK_ARROW) {
147 Point pts[] = {
148 Point::FromInts(centreX - dimOn4, centreY - dimOn2),
149 Point::FromInts(centreX - dimOn4, centreY + dimOn2),
150 Point::FromInts(centreX + dimOn2 - dimOn4, centreY),
152 surface->Polygon(pts, ELEMENTS(pts), fore, back);
154 } else if (markType == SC_MARK_ARROWDOWN) {
155 Point pts[] = {
156 Point::FromInts(centreX - dimOn2, centreY - dimOn4),
157 Point::FromInts(centreX + dimOn2, centreY - dimOn4),
158 Point::FromInts(centreX, centreY + dimOn2 - dimOn4),
160 surface->Polygon(pts, ELEMENTS(pts), fore, back);
162 } else if (markType == SC_MARK_PLUS) {
163 Point pts[] = {
164 Point::FromInts(centreX - armSize, centreY - 1),
165 Point::FromInts(centreX - 1, centreY - 1),
166 Point::FromInts(centreX - 1, centreY - armSize),
167 Point::FromInts(centreX + 1, centreY - armSize),
168 Point::FromInts(centreX + 1, centreY - 1),
169 Point::FromInts(centreX + armSize, centreY -1),
170 Point::FromInts(centreX + armSize, centreY +1),
171 Point::FromInts(centreX + 1, centreY + 1),
172 Point::FromInts(centreX + 1, centreY + armSize),
173 Point::FromInts(centreX - 1, centreY + armSize),
174 Point::FromInts(centreX - 1, centreY + 1),
175 Point::FromInts(centreX - armSize, centreY + 1),
177 surface->Polygon(pts, ELEMENTS(pts), fore, back);
179 } else if (markType == SC_MARK_MINUS) {
180 Point pts[] = {
181 Point::FromInts(centreX - armSize, centreY - 1),
182 Point::FromInts(centreX + armSize, centreY -1),
183 Point::FromInts(centreX + armSize, centreY +1),
184 Point::FromInts(centreX - armSize, centreY + 1),
186 surface->Polygon(pts, ELEMENTS(pts), fore, back);
188 } else if (markType == SC_MARK_SMALLRECT) {
189 PRectangle rcSmall;
190 rcSmall.left = rc.left + 1;
191 rcSmall.top = rc.top + 2;
192 rcSmall.right = rc.right - 1;
193 rcSmall.bottom = rc.bottom - 2;
194 surface->RectangleDraw(rcSmall, fore, back);
196 } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
197 markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
198 // An invisible marker so don't draw anything
200 } else if (markType == SC_MARK_VLINE) {
201 surface->PenColour(colourBody);
202 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
203 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
205 } else if (markType == SC_MARK_LCORNER) {
206 surface->PenColour(colourTail);
207 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
208 surface->LineTo(centreX, centreY);
209 surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
211 } else if (markType == SC_MARK_TCORNER) {
212 surface->PenColour(colourTail);
213 surface->MoveTo(centreX, centreY);
214 surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
216 surface->PenColour(colourBody);
217 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
218 surface->LineTo(centreX, centreY + 1);
220 surface->PenColour(colourHead);
221 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
223 } else if (markType == SC_MARK_LCORNERCURVE) {
224 surface->PenColour(colourTail);
225 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
226 surface->LineTo(centreX, centreY-3);
227 surface->LineTo(centreX+3, centreY);
228 surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
230 } else if (markType == SC_MARK_TCORNERCURVE) {
231 surface->PenColour(colourTail);
232 surface->MoveTo(centreX, centreY-3);
233 surface->LineTo(centreX+3, centreY);
234 surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
236 surface->PenColour(colourBody);
237 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
238 surface->LineTo(centreX, centreY-2);
240 surface->PenColour(colourHead);
241 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
243 } else if (markType == SC_MARK_BOXPLUS) {
244 DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
245 DrawPlus(surface, centreX, centreY, blobSize, colourTail);
247 } else if (markType == SC_MARK_BOXPLUSCONNECTED) {
248 if (tFold == LineMarker::headWithTail)
249 surface->PenColour(colourTail);
250 else
251 surface->PenColour(colourBody);
252 surface->MoveTo(centreX, centreY + blobSize);
253 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
255 surface->PenColour(colourBody);
256 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
257 surface->LineTo(centreX, centreY - blobSize);
259 DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
260 DrawPlus(surface, centreX, centreY, blobSize, colourTail);
262 if (tFold == LineMarker::body) {
263 surface->PenColour(colourTail);
264 surface->MoveTo(centreX + 1, centreY + blobSize);
265 surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
267 surface->MoveTo(centreX + blobSize, centreY + blobSize);
268 surface->LineTo(centreX + blobSize, centreY - blobSize);
270 surface->MoveTo(centreX + 1, centreY - blobSize);
271 surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
273 } else if (markType == SC_MARK_BOXMINUS) {
274 DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
275 DrawMinus(surface, centreX, centreY, blobSize, colourTail);
277 surface->PenColour(colourHead);
278 surface->MoveTo(centreX, centreY + blobSize);
279 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
281 } else if (markType == SC_MARK_BOXMINUSCONNECTED) {
282 DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
283 DrawMinus(surface, centreX, centreY, blobSize, colourTail);
285 surface->PenColour(colourHead);
286 surface->MoveTo(centreX, centreY + blobSize);
287 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
289 surface->PenColour(colourBody);
290 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
291 surface->LineTo(centreX, centreY - blobSize);
293 if (tFold == LineMarker::body) {
294 surface->PenColour(colourTail);
295 surface->MoveTo(centreX + 1, centreY + blobSize);
296 surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
298 surface->MoveTo(centreX + blobSize, centreY + blobSize);
299 surface->LineTo(centreX + blobSize, centreY - blobSize);
301 surface->MoveTo(centreX + 1, centreY - blobSize);
302 surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
304 } else if (markType == SC_MARK_CIRCLEPLUS) {
305 DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
306 DrawPlus(surface, centreX, centreY, blobSize, colourTail);
308 } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
309 if (tFold == LineMarker::headWithTail)
310 surface->PenColour(colourTail);
311 else
312 surface->PenColour(colourBody);
313 surface->MoveTo(centreX, centreY + blobSize);
314 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
316 surface->PenColour(colourBody);
317 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
318 surface->LineTo(centreX, centreY - blobSize);
320 DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
321 DrawPlus(surface, centreX, centreY, blobSize, colourTail);
323 } else if (markType == SC_MARK_CIRCLEMINUS) {
324 surface->PenColour(colourHead);
325 surface->MoveTo(centreX, centreY + blobSize);
326 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
328 DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
329 DrawMinus(surface, centreX, centreY, blobSize, colourTail);
331 } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
332 surface->PenColour(colourHead);
333 surface->MoveTo(centreX, centreY + blobSize);
334 surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
336 surface->PenColour(colourBody);
337 surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
338 surface->LineTo(centreX, centreY - blobSize);
340 DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
341 DrawMinus(surface, centreX, centreY, blobSize, colourTail);
343 } else if (markType >= SC_MARK_CHARACTER) {
344 char character[1];
345 character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
346 XYPOSITION width = surface->WidthText(fontForCharacter, character, 1);
347 rc.left += (rc.Width() - width) / 2;
348 rc.right = rc.left + width;
349 surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
350 character, 1, fore, back);
352 } else if (markType == SC_MARK_DOTDOTDOT) {
353 XYPOSITION right = static_cast<XYPOSITION>(centreX - 6);
354 for (int b=0; b<3; b++) {
355 PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
356 surface->FillRectangle(rcBlob, fore);
357 right += 5.0f;
359 } else if (markType == SC_MARK_ARROWS) {
360 surface->PenColour(fore);
361 int right = centreX - 2;
362 const int armLength = dimOn2 - 1;
363 for (int b = 0; b<3; b++) {
364 surface->MoveTo(right, centreY);
365 surface->LineTo(right - armLength, centreY - armLength);
366 surface->MoveTo(right, centreY);
367 surface->LineTo(right - armLength, centreY + armLength);
368 right += 4;
370 } else if (markType == SC_MARK_SHORTARROW) {
371 Point pts[] = {
372 Point::FromInts(centreX, centreY + dimOn2),
373 Point::FromInts(centreX + dimOn2, centreY),
374 Point::FromInts(centreX, centreY - dimOn2),
375 Point::FromInts(centreX, centreY - dimOn4),
376 Point::FromInts(centreX - dimOn4, centreY - dimOn4),
377 Point::FromInts(centreX - dimOn4, centreY + dimOn4),
378 Point::FromInts(centreX, centreY + dimOn4),
379 Point::FromInts(centreX, centreY + dimOn2),
381 surface->Polygon(pts, ELEMENTS(pts), fore, back);
382 } else if (markType == SC_MARK_LEFTRECT) {
383 PRectangle rcLeft = rcWhole;
384 rcLeft.right = rcLeft.left + 4;
385 surface->FillRectangle(rcLeft, back);
386 } else if (markType == SC_MARK_BOOKMARK) {
387 int halfHeight = minDim / 3;
388 Point pts[] = {
389 Point::FromInts(static_cast<int>(rc.left), centreY-halfHeight),
390 Point::FromInts(static_cast<int>(rc.right) - 3, centreY - halfHeight),
391 Point::FromInts(static_cast<int>(rc.right) - 3 - halfHeight, centreY),
392 Point::FromInts(static_cast<int>(rc.right) - 3, centreY + halfHeight),
393 Point::FromInts(static_cast<int>(rc.left), centreY + halfHeight),
395 surface->Polygon(pts, ELEMENTS(pts), fore, back);
396 } else { // SC_MARK_FULLRECT
397 surface->FillRectangle(rcWhole, back);