56
64
static bool IsLastStep(const DocModification& mh) {
58
(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0
59
&& (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
60
&& (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
61
&& (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
66
(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
67
&& (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
68
&& (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
69
&& (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
65
active(false), on(false), period(500) {}
73
active(false), on(false), period(500) {}
68
ticking(false), ticksToWait(0), tickerID(0) {}
76
ticking(false), ticksToWait(0), tickerID(0) {}
71
state(false), idlerID(0) {}
73
LineLayout::LineLayout(int maxLineLength_) :
94
widthLine(wrapWidthInfinite),
96
Resize(maxLineLength_);
99
LineLayout::~LineLayout() {
103
void LineLayout::Resize(int maxLineLength_) {
104
if (maxLineLength_ > maxLineLength) {
106
chars = new char[maxLineLength_ + 1];
107
styles = new unsigned char[maxLineLength_ + 1];
108
indicators = new char[maxLineLength_ + 1];
109
// Extra position allocated as sometimes the Windows
110
// GetTextExtentExPoint API writes an extra element.
111
positions = new int[maxLineLength_ + 1 + 1];
112
maxLineLength = maxLineLength_;
116
void LineLayout::Free() {
129
void LineLayout::Invalidate(validLevel validity_) {
130
if (validity > validity_)
131
validity = validity_;
134
void LineLayout::SetLineStart(int line, int start) {
135
if ((line >= lenLineStarts) && (line != 0)) {
136
int newMaxLines = line + 20;
137
int *newLineStarts = new int[newMaxLines];
140
for (int i = 0; i < newMaxLines; i++) {
141
if (i < lenLineStarts)
142
newLineStarts[i] = lineStarts[i];
144
newLineStarts[i] = 0;
147
lineStarts = newLineStarts;
148
lenLineStarts = newMaxLines;
150
lineStarts[line] = start;
153
void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[],
154
char bracesMatchStyle, int xHighlight) {
155
if (rangeLine.ContainsCharacter(braces[0])) {
156
int braceOffset = braces[0] - rangeLine.start;
157
if (braceOffset < numCharsInLine) {
158
bracePreviousStyles[0] = styles[braceOffset];
159
styles[braceOffset] = bracesMatchStyle;
162
if (rangeLine.ContainsCharacter(braces[1])) {
163
int braceOffset = braces[1] - rangeLine.start;
164
if (braceOffset < numCharsInLine) {
165
bracePreviousStyles[1] = styles[braceOffset];
166
styles[braceOffset] = bracesMatchStyle;
169
if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) ||
170
(braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) {
171
xHighlightGuide = xHighlight;
175
void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) {
176
if (rangeLine.ContainsCharacter(braces[0])) {
177
int braceOffset = braces[0] - rangeLine.start;
178
if (braceOffset < numCharsInLine) {
179
styles[braceOffset] = bracePreviousStyles[0];
182
if (rangeLine.ContainsCharacter(braces[1])) {
183
int braceOffset = braces[1] - rangeLine.start;
184
if (braceOffset < numCharsInLine) {
185
styles[braceOffset] = bracePreviousStyles[1];
191
LineLayoutCache::LineLayoutCache() :
192
level(0), length(0), size(0), cache(0),
193
allInvalidated(false), styleClock(-1), useCount(0) {
197
LineLayoutCache::~LineLayoutCache() {
201
void LineLayoutCache::Allocate(int length_) {
202
PLATFORM_ASSERT(cache == NULL);
203
allInvalidated = false;
207
size = (size / 16 + 1) * 16;
210
cache = new LineLayout * [size];
212
for (int i = 0; i < size; i++)
216
void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
217
PLATFORM_ASSERT(useCount == 0);
218
int lengthForLevel = 0;
219
if (level == llcCaret) {
221
} else if (level == llcPage) {
222
lengthForLevel = linesOnScreen + 1;
223
} else if (level == llcDocument) {
224
lengthForLevel = linesInDoc;
226
if (lengthForLevel > size) {
228
Allocate(lengthForLevel);
230
if (lengthForLevel < length) {
231
for (int i = lengthForLevel; i < length; i++) {
236
length = lengthForLevel;
238
PLATFORM_ASSERT(length == lengthForLevel);
239
PLATFORM_ASSERT(cache != NULL || length == 0);
242
void LineLayoutCache::Deallocate() {
243
PLATFORM_ASSERT(useCount == 0);
244
for (int i = 0; i < length; i++)
252
void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
253
if (cache && !allInvalidated) {
254
for (int i = 0; i < length; i++) {
256
cache[i]->Invalidate(validity_);
259
if (validity_ == LineLayout::llInvalid) {
260
allInvalidated = true;
265
void LineLayoutCache::SetLevel(int level_) {
266
allInvalidated = false;
267
if ((level_ != -1) && (level != level_)) {
273
LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
274
int linesOnScreen, int linesInDoc) {
275
AllocateForLevel(linesOnScreen, linesInDoc);
276
if (styleClock != styleClock_) {
277
Invalidate(LineLayout::llCheckTextAndStyle);
278
styleClock = styleClock_;
280
allInvalidated = false;
283
if (level == llcCaret) {
285
} else if (level == llcPage) {
286
if (lineNumber == lineCaret) {
288
} else if (length > 1) {
289
pos = 1 + (lineNumber % (length - 1));
291
} else if (level == llcDocument) {
295
PLATFORM_ASSERT(useCount == 0);
296
if (cache && (pos < length)) {
298
if ((cache[pos]->lineNumber != lineNumber) ||
299
(cache[pos]->maxLineLength < maxChars)) {
305
cache[pos] = new LineLayout(maxChars);
308
cache[pos]->lineNumber = lineNumber;
309
cache[pos]->inCache = true;
317
ret = new LineLayout(maxChars);
318
ret->lineNumber = lineNumber;
324
void LineLayoutCache::Dispose(LineLayout *ll) {
325
allInvalidated = false;
79
state(false), idlerID(0) {}
81
static inline bool IsControlCharacter(int ch) {
82
// iscntrl returns true for lots of chars > 127 which are displayable
83
return ch >= 0 && ch < ' ';
335
86
Editor::Editor() {
2392
2337
rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
2394
DrawWrapMarker(surface, rcPlace, false, vsDraw.whitespaceForeground.allocated);
2339
DrawWrapMarker(surface, rcPlace, false, wrapColour);
2397
2342
xStart += actualWrapVisualStartIndent * vsDraw.aveCharWidth;
2346
// Does not take margin into account but not significant
2347
int xStartVisible = subLineStart - xStart;
2349
BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
2350
int next = bfBack.First();
2403
2352
// Background drawing loop
2404
for (i = lineStart; twoPhaseDraw && (i < lineEnd); i++) {
2406
int iDoc = i + posLineStart;
2407
// If there is the end of a style run for any reason
2408
if ((ll->styles[i] != ll->styles[i + 1]) ||
2409
i == (lineEnd - 1) ||
2410
IsControlCharacter(ll->chars[i]) || IsControlCharacter(ll->chars[i + 1]) ||
2411
((ll->selStart != ll->selEnd) && ((iDoc + 1 == ll->selStart) || (iDoc + 1 == ll->selEnd))) ||
2412
(i == (ll->edgeColumn - 1))) {
2413
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
2414
rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
2415
// Only try to draw if really visible - enhances performance by not calling environment to
2416
// draw strings that are completely past the right side of the window.
2417
if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
2418
int styleMain = ll->styles[i];
2419
bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd);
2420
bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
2421
ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
2422
if (ll->chars[i] == '\t') {
2353
while (twoPhaseDraw && (next < lineEnd)) {
2356
next = bfBack.Next();
2358
int iDoc = i + posLineStart;
2360
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
2361
rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
2362
// Only try to draw if really visible - enhances performance by not calling environment to
2363
// draw strings that are completely past the right side of the window.
2364
if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
2365
// Clip to line rectangle, since may have a huge position which will not work with some platforms
2366
rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left);
2367
rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right);
2369
int styleMain = ll->styles[i];
2370
bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd);
2371
bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
2372
ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
2373
if (ll->chars[i] == '\t') {
2375
if (drawWhitespaceBackground &&
2376
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
2377
textBack = vsDraw.whitespaceBackground.allocated;
2378
surface->FillRectangle(rcSegment, textBack);
2379
} else if (IsControlCharacter(ll->chars[i])) {
2380
// Control character display
2381
inIndentation = false;
2382
surface->FillRectangle(rcSegment, textBack);
2384
// Normal text display
2385
surface->FillRectangle(rcSegment, textBack);
2386
if (vsDraw.viewWhitespace != wsInvisible ||
2387
(inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
2388
for (int cpos = 0; cpos <= i - startseg; cpos++) {
2389
if (ll->chars[cpos + startseg] == ' ') {
2390
if (drawWhitespaceBackground &&
2391
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
2392
PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
2394
ll->positions[cpos + startseg + 1] + xStart - subLineStart,
2396
surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated);
2399
inIndentation = false;
2404
} else if (rcSegment.left > rcLine.right) {
2410
DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
2411
xStart, subLine, subLineStart, overrideBackground, background,
2412
drawWrapMarkEnd, wrapColour);
2415
DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true);
2417
if (vsDraw.edgeState == EDGE_LINE) {
2418
int edgeX = theEdge * vsDraw.spaceWidth;
2419
rcSegment.left = edgeX + xStart;
2420
rcSegment.right = rcSegment.left + 1;
2421
surface->FillRectangle(rcSegment, vsDraw.edgecolour.allocated);
2424
inIndentation = subLine == 0; // Do not handle indentation except on first subline.
2425
// Foreground drawing loop
2426
BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
2427
next = bfFore.First();
2429
while (next < lineEnd) {
2432
next = bfFore.Next();
2435
int iDoc = i + posLineStart;
2437
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
2438
rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
2439
// Only try to draw if really visible - enhances performance by not calling environment to
2440
// draw strings that are completely past the right side of the window.
2441
if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
2442
int styleMain = ll->styles[i];
2443
ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated;
2444
Font &textFont = vsDraw.styles[styleMain].font;
2445
//hotspot foreground
2446
if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
2447
if (vsDraw.hotspotForegroundSet)
2448
textFore = vsDraw.hotspotForeground.allocated;
2450
bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd);
2451
if (inSelection && (vsDraw.selforeset)) {
2452
textFore = vsDraw.selforeground.allocated;
2454
bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
2455
ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
2456
if (ll->chars[i] == '\t') {
2458
if (!twoPhaseDraw) {
2424
2459
if (drawWhitespaceBackground &&
2425
2460
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
2426
2461
textBack = vsDraw.whitespaceBackground.allocated;
2427
2462
surface->FillRectangle(rcSegment, textBack);
2428
} else if (IsControlCharacter(ll->chars[i])) {
2429
// Control character display
2430
inIndentation = false;
2431
surface->FillRectangle(rcSegment, textBack);
2464
if ((vsDraw.viewWhitespace != wsInvisible) ||
2465
(inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
2466
if (vsDraw.whitespaceForegroundSet)
2467
textFore = vsDraw.whitespaceForeground.allocated;
2468
surface->PenColour(textFore);
2470
if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
2471
for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {
2472
if (xIG >= ll->positions[i] && xIG > 0) {
2473
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment,
2474
(ll->xHighlightGuide == xIG));
2478
if (vsDraw.viewWhitespace != wsInvisible) {
2479
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
2480
PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
2481
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
2482
DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
2485
} else if (IsControlCharacter(ll->chars[i])) {
2486
// Control character display
2487
inIndentation = false;
2488
if (controlCharSymbol < 32) {
2489
// Draw the character
2490
const char *ctrlChar = ControlCharacterString(ll->chars[i]);
2491
DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
2433
// Normal text display
2434
surface->FillRectangle(rcSegment, textBack);
2435
if (vsDraw.viewWhitespace != wsInvisible ||
2436
(inIndentation && vsDraw.viewIndentationGuides)) {
2437
for (int cpos = 0; cpos <= i - startseg; cpos++) {
2438
if (ll->chars[cpos + startseg] == ' ') {
2439
if (drawWhitespaceBackground &&
2440
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
2441
PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top,
2442
ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom);
2443
surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated);
2446
inIndentation = false;
2451
} else if (rcSegment.left > rcLine.right) {
2459
DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
2460
xStart, subLine, subLineStart, overrideBackground, background,
2461
drawWrapMarkEnd, vsDraw.whitespaceForeground.allocated);
2464
inIndentation = subLine == 0; // Do not handle indentation except on first subline.
2465
startseg = ll->LineStart(subLine);
2466
// Foreground drawing loop
2467
for (i = lineStart; i < lineEnd; i++) {
2469
int iDoc = i + posLineStart;
2470
// If there is the end of a style run for any reason
2471
if ((ll->styles[i] != ll->styles[i + 1]) ||
2472
i == (lineEnd - 1) ||
2473
IsControlCharacter(ll->chars[i]) || IsControlCharacter(ll->chars[i + 1]) ||
2474
((ll->selStart != ll->selEnd) && ((iDoc + 1 == ll->selStart) || (iDoc + 1 == ll->selEnd))) ||
2475
(i == (ll->edgeColumn - 1))) {
2476
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
2477
rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
2478
// Only try to draw if really visible - enhances performance by not calling environment to
2479
// draw strings that are completely past the right side of the window.
2480
if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
2481
int styleMain = ll->styles[i];
2482
ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated;
2483
Font &textFont = vsDraw.styles[styleMain].font;
2484
//hotspot foreground
2485
if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
2486
if (vsDraw.hotspotForegroundSet)
2487
textFore = vsDraw.hotspotForeground.allocated;
2489
bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd);
2490
if (inSelection && (vsDraw.selforeset)) {
2491
textFore = vsDraw.selforeground.allocated;
2493
bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
2494
ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
2495
if (ll->chars[i] == '\t') {
2497
if (!twoPhaseDraw) {
2498
if (drawWhitespaceBackground &&
2499
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
2500
textBack = vsDraw.whitespaceBackground.allocated;
2501
surface->FillRectangle(rcSegment, textBack);
2503
if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) {
2504
if (vsDraw.whitespaceForegroundSet)
2505
textFore = vsDraw.whitespaceForeground.allocated;
2506
surface->PenColour(textFore);
2508
if (inIndentation && vsDraw.viewIndentationGuides) {
2509
for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {
2510
if (xIG >= ll->positions[i] && xIG > 0) {
2511
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment,
2512
(ll->xHighlightGuide == xIG));
2516
if (vsDraw.viewWhitespace != wsInvisible) {
2517
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
2518
PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
2519
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
2520
DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
2523
} else if (IsControlCharacter(ll->chars[i])) {
2524
// Control character display
2525
inIndentation = false;
2526
if (controlCharSymbol < 32) {
2527
// Draw the character
2528
const char *ctrlChar = ControlCharacterString(ll->chars[i]);
2529
if (!twoPhaseDraw) {
2530
surface->FillRectangle(rcSegment, textBack);
2532
int normalCharHeight = surface->Ascent(ctrlCharsFont) -
2533
surface->InternalLeading(ctrlCharsFont);
2534
PRectangle rcCChar = rcSegment;
2535
rcCChar.left = rcCChar.left + 1;
2536
rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
2537
rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
2538
PRectangle rcCentral = rcCChar;
2541
surface->FillRectangle(rcCentral, textFore);
2542
PRectangle rcChar = rcCChar;
2545
surface->DrawTextClipped(rcChar, ctrlCharsFont,
2546
rcSegment.top + vsDraw.maxAscent, ctrlChar, istrlen(ctrlChar),
2547
textBack, textFore);
2493
char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
2494
surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
2495
rcSegment.top + vsDraw.maxAscent,
2496
cc, 1, textBack, textFore);
2498
} else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) {
2500
sprintf(hexits, "%2X", ll->chars[i] & 0xff);
2501
DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw);
2503
// Normal text display
2504
if (vsDraw.styles[styleMain].visible) {
2506
surface->DrawTextTransparent(rcSegment, textFont,
2507
rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
2508
i - startseg + 1, textFore);
2549
char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
2550
surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
2551
rcSegment.top + vsDraw.maxAscent,
2552
cc, 1, textBack, textFore);
2510
surface->DrawTextNoClip(rcSegment, textFont,
2511
rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
2512
i - startseg + 1, textFore, textBack);
2555
// Normal text display
2556
if (vsDraw.styles[styleMain].visible) {
2558
surface->DrawTextTransparent(rcSegment, textFont,
2559
rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
2560
i - startseg + 1, textFore);
2515
if (vsDraw.viewWhitespace != wsInvisible ||
2516
(inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
2517
for (int cpos = 0; cpos <= i - startseg; cpos++) {
2518
if (ll->chars[cpos + startseg] == ' ') {
2519
if (vsDraw.viewWhitespace != wsInvisible) {
2520
if (vsDraw.whitespaceForegroundSet)
2521
textFore = vsDraw.whitespaceForeground.allocated;
2522
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
2523
int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
2524
if (!twoPhaseDraw && drawWhitespaceBackground &&
2525
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
2526
textBack = vsDraw.whitespaceBackground.allocated;
2527
PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
2529
ll->positions[cpos + startseg + 1] + xStart - subLineStart,
2531
surface->FillRectangle(rcSpace, textBack);
2533
PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
2534
rcDot.right = rcDot.left + 1;
2535
rcDot.bottom = rcDot.top + 1;
2536
surface->FillRectangle(rcDot, textFore);
2539
if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
2540
int startSpace = ll->positions[cpos + startseg];
2541
if (startSpace > 0 && (startSpace % indentWidth == 0)) {
2542
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment,
2543
(ll->xHighlightGuide == ll->positions[cpos + startseg]));
2562
surface->DrawTextNoClip(rcSegment, textFont,
2563
rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
2564
i - startseg + 1, textFore, textBack);
2567
if (vsDraw.viewWhitespace != wsInvisible ||
2568
(inIndentation && vsDraw.viewIndentationGuides)) {
2569
for (int cpos = 0; cpos <= i - startseg; cpos++) {
2570
if (ll->chars[cpos + startseg] == ' ') {
2571
if (vsDraw.viewWhitespace != wsInvisible) {
2572
if (vsDraw.whitespaceForegroundSet)
2573
textFore = vsDraw.whitespaceForeground.allocated;
2574
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
2575
int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
2576
if (!twoPhaseDraw && drawWhitespaceBackground &&
2577
(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
2578
textBack = vsDraw.whitespaceBackground.allocated;
2579
PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top, ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom);
2580
surface->FillRectangle(rcSpace, textBack);
2582
PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
2583
rcDot.right = rcDot.left + 1;
2584
rcDot.bottom = rcDot.top + 1;
2585
surface->FillRectangle(rcDot, textFore);
2588
if (inIndentation && vsDraw.viewIndentationGuides) {
2589
int startSpace = ll->positions[cpos + startseg];
2590
if (startSpace > 0 && (startSpace % indentWidth == 0)) {
2591
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment,
2592
(ll->xHighlightGuide == ll->positions[cpos + startseg]));
2596
inIndentation = false;
2547
inIndentation = false;
2601
if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd ) {
2602
PRectangle rcUL = rcSegment;
2603
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
2604
rcUL.bottom = rcUL.top + 1;
2605
if (vsDraw.hotspotForegroundSet)
2606
surface->FillRectangle(rcUL, vsDraw.hotspotForeground.allocated);
2608
surface->FillRectangle(rcUL, textFore);
2609
} else if (vsDraw.styles[styleMain].underline) {
2610
PRectangle rcUL = rcSegment;
2611
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
2612
rcUL.bottom = rcUL.top + 1;
2552
if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd ) {
2553
PRectangle rcUL = rcSegment;
2554
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
2555
rcUL.bottom = rcUL.top + 1;
2556
if (vsDraw.hotspotForegroundSet)
2557
surface->FillRectangle(rcUL, vsDraw.hotspotForeground.allocated);
2613
2559
surface->FillRectangle(rcUL, textFore);
2615
} else if (rcSegment.left > rcLine.right) {
2623
// foreach indicator...
2624
for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
2625
if (!(mask & ll->styleBitsSet)) {
2630
// foreach style pos in line...
2631
for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
2632
// look for starts...
2634
// NOT in indicator run, looking for START
2635
if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
2636
startPos = indicPos;
2639
if (startPos >= 0) {
2640
// IN indicator run, looking for END
2641
if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
2642
// AT end of indicator run, DRAW it!
2644
ll->positions[startPos] + xStart - subLineStart,
2645
rcLine.top + vsDraw.maxAscent,
2646
ll->positions[indicPos] + xStart - subLineStart,
2647
rcLine.top + vsDraw.maxAscent + 3);
2648
vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine);
2649
// RESET control var
2560
} else if (vsDraw.styles[styleMain].underline) {
2561
PRectangle rcUL = rcSegment;
2562
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
2563
rcUL.bottom = rcUL.top + 1;
2564
surface->FillRectangle(rcUL, textFore);
2566
} else if (rcSegment.left > rcLine.right) {
2570
if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
2571
&& (subLine == 0)) {
2572
int indentSpace = pdoc->GetLineIndentation(line);
2573
// Find the most recent line with some text
2575
int lineLastWithText = line;
2576
while (lineLastWithText > 0 && pdoc->IsWhiteLine(lineLastWithText)) {
2579
if (lineLastWithText < line) {
2580
// This line is empty, so use indentation of last line with text
2581
int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
2582
int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
2584
// Level is one more level than parent
2585
indentLastWithText += pdoc->IndentSize();
2587
if (vsDraw.viewIndentationGuides == ivLookForward) {
2588
// In viLookForward mode, previous line only used if it is a fold header
2590
indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
2592
} else { // viLookBoth
2593
indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
2597
int lineNextWithText = line;
2598
while (lineNextWithText < pdoc->LinesTotal() && pdoc->IsWhiteLine(lineNextWithText)) {
2601
if (lineNextWithText > line) {
2602
// This line is empty, so use indentation of last line with text
2603
indentSpace = Platform::Maximum(indentSpace,
2604
pdoc->GetLineIndentation(lineNextWithText));
2607
for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
2608
int xIndent = indentPos * vsDraw.spaceWidth;
2609
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
2610
(ll->xHighlightGuide == xIndent));
2614
DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
2656
2616
// End of the drawing of the current line
2657
2617
if (!twoPhaseDraw) {
2658
2618
DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
2659
2619
xStart, subLine, subLineStart, overrideBackground, background,
2660
drawWrapMarkEnd, vsDraw.whitespaceForeground.allocated);
2620
drawWrapMarkEnd, wrapColour);
2662
2622
if ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) && (ll->selStart >= 0) && (ll->selEnd >= 0)) {
2663
2623
int startPosSel = (ll->selStart < posLineStart) ? posLineStart : ll->selStart;