aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Editor.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/Editor.cxx')
-rw-r--r--src/Editor.cxx230
1 files changed, 101 insertions, 129 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 75c1336d7..276326877 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -2279,74 +2279,54 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
XYPOSITION tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
bool lastSegItalics = false;
- EncodingFamily encodingFamily = pdoc->CodePageFamily();
-
- XYPOSITION positionsRepr[256]; // Should expand when needed
- int charWidthNext = 1;
- if (encodingFamily == efUnicode)
- charWidthNext = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars), numCharsInLine);
- else if (encodingFamily == efDBCS)
- charWidthNext = pdoc->IsDBCSLeadByte(ll->chars[0]) ? 2 : 1;
- Representation *reprNext = reprs.RepresentationFromCharacter(ll->chars, charWidthNext);
- int charWidth = 1;
-
- for (int charInLine = 0; charInLine < numCharsInLine; charInLine += charWidth) {
-
- charWidth = charWidthNext;
- Representation *repr = reprNext;
-
- charWidthNext = 1;
- if (encodingFamily == efUnicode)
- charWidthNext = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars+charInLine + charWidth), numCharsInLine - charInLine - charWidth);
- else if (encodingFamily == efDBCS)
- charWidthNext = pdoc->IsDBCSLeadByte(ll->chars[charInLine + charWidth]) ? 2 : 1;
- reprNext = reprs.RepresentationFromCharacter(ll->chars+charInLine + charWidth, charWidthNext);
-
- if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
- repr || reprNext || ((charInLine+charWidth) >= numCharsBeforeEOL)) {
- ll->positions[startseg] = 0;
- if (vstyle.styles[ll->styles[charInLine]].visible) {
- if (repr) {
- if (ll->chars[charInLine] == '\t') {
- // Tab is a special case of repr, taking a variable amount of space
- ll->positions[charInLine + 1] =
- ((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx;
- } else if (controlCharSymbol < 32) {
- posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, repr->stringRep.c_str(),
- static_cast<unsigned int>(repr->stringRep.length()), positionsRepr, pdoc);
- XYPOSITION endRepr = positionsRepr[repr->stringRep.length()-1] + 3;
- for (int ii=0; ii < charWidth; ii++)
- ll->positions[startseg + 1 + ii] = endRepr;
- } else {
- char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
- surface->MeasureWidths(vstyle.styles[STYLE_CONTROLCHAR].font, cc, 1,
- ll->positions + startseg + 1);
- }
+ BreakFinder bfLayout(ll, 0, numCharsInLine, posLineStart, 0, false, pdoc, &reprs);
+ while (bfLayout.More()) {
+
+ TextSegment ts = bfLayout.Next();
+ startseg = ts.start;
+
+ ll->positions[startseg] = 0;
+ if (vstyle.styles[ll->styles[startseg]].visible) {
+ if (ts.repr) {
+ if (ll->chars[startseg] == '\t') {
+ // Tab is a special case of repr, taking a variable amount of space
+ ll->positions[startseg + 1] =
+ ((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx;
+ } else if (controlCharSymbol < 32) {
+ XYPOSITION positionsRepr[256]; // Should expand when needed
+ posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.repr->stringRep.c_str(),
+ static_cast<unsigned int>(ts.repr->stringRep.length()), positionsRepr, pdoc);
+ XYPOSITION endRepr = positionsRepr[ts.repr->stringRep.length()-1] + 3;
+ for (int ii=0; ii < ts.length; ii++)
+ ll->positions[startseg + 1 + ii] = endRepr;
+ } else {
+ char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
+ surface->MeasureWidths(vstyle.styles[STYLE_CONTROLCHAR].font, cc, 1,
+ ll->positions + startseg + 1);
+ }
+ lastSegItalics = false;
+ } else {
+ if ((ts.length == 1) && (' ' == ll->chars[startseg])) {
lastSegItalics = false;
+ // Over half the segments are single characters and of these about half are space characters.
+ ll->positions[startseg + 1] = vstyle.styles[ll->styles[startseg]].spaceWidth;
} else {
- int lenSeg = charInLine - startseg + charWidth;
- if ((lenSeg == 1) && (' ' == ll->chars[startseg])) {
- lastSegItalics = false;
- // Over half the segments are single characters and of these about half are space characters.
- ll->positions[charInLine + 1] = vstyle.styles[ll->styles[charInLine]].spaceWidth;
- } else {
- lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic;
- posCache.MeasureWidths(surface, vstyle, ll->styles[charInLine], ll->chars + startseg,
- lenSeg, ll->positions + startseg + 1, pdoc);
- }
- }
- } else { // invisible
- for (int posToZero = startseg; posToZero <= (charInLine + charWidth); posToZero++) {
- ll->positions[posToZero] = 0;
+ lastSegItalics = vstyle.styles[ll->styles[startseg]].italic;
+ posCache.MeasureWidths(surface, vstyle, ll->styles[startseg], ll->chars + startseg,
+ ts.length, ll->positions + startseg + 1, pdoc);
}
}
- for (int posToIncrease = startseg; posToIncrease <= (charInLine + charWidth); posToIncrease++) {
- ll->positions[posToIncrease] += startsegx;
+ } else { // invisible
+ for (int posToZero = startseg; posToZero <= (startseg + ts.length); posToZero++) {
+ ll->positions[posToZero] = 0;
}
- startsegx = ll->positions[charInLine + charWidth];
- startseg = charInLine + charWidth;
}
+ for (int posToIncrease = startseg; posToIncrease <= (startseg + ts.length); posToIncrease++) {
+ ll->positions[posToIncrease] += startsegx;
+ }
+ startsegx = ll->positions[startseg + ts.length];
}
+
// Small hack to make lines that end with italics not cut off the edge of the last character
if ((startseg > 0) && lastSegItalics) {
ll->positions[startseg] += lastSegItalicsOffset;
@@ -2968,14 +2948,13 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
ll->psel = &sel;
BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc, &reprs);
- int next = bfBack.First();
// Background drawing loop
- while (twoPhaseDraw && (next < lineEnd)) {
+ while (twoPhaseDraw && bfBack.More()) {
- startseg = next;
- next = bfBack.Next();
- int i = next - 1;
+ TextSegment ts = bfBack.Next();
+ startseg = ts.start;
+ int i = ts.start + ts.length - 1;
int iDoc = i + posLineStart;
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
@@ -3063,14 +3042,12 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
// Foreground drawing loop
BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible,
((!twoPhaseDraw && selBackDrawn) || vsDraw.selforeset), pdoc, &reprs);
- next = bfFore.First();
-
- while (next < lineEnd) {
- startseg = next;
- next = bfFore.Next();
- int i = next - 1;
+ while (bfFore.More()) {
+ TextSegment ts = bfFore.Next();
+ startseg = ts.start;
+ int i = ts.start + ts.length - 1;
int iDoc = i + posLineStart;
rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
@@ -3121,71 +3098,66 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
}
}
+ } else if (ts.repr) {
+ inIndentation = false;
+ if (controlCharSymbol < 32) {
+ DrawTextBlob(surface, vsDraw, rcSegment, ts.repr->stringRep.c_str(), textBack, textFore, twoPhaseDraw);
+ } else {
+ char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
+ surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent,
+ cc, 1, textBack, textFore);
+ }
} else {
- Representation *repr = 0;
- if ((i - startseg + 1) <= 4)
- repr = reprs.RepresentationFromCharacter(ll->chars + startseg, i - startseg + 1);
- if (repr) {
- inIndentation = false; // May need to special case ' '.
- if (controlCharSymbol < 32) {
- DrawTextBlob(surface, vsDraw, rcSegment, repr->stringRep.c_str(), textBack, textFore, twoPhaseDraw);
+ // Normal text display
+ if (vsDraw.styles[styleMain].visible) {
+ if (twoPhaseDraw) {
+ surface->DrawTextTransparent(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+ i - startseg + 1, textFore);
} else {
- char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
- surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
- rcSegment.top + vsDraw.maxAscent,
- cc, 1, textBack, textFore);
+ surface->DrawTextNoClip(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+ i - startseg + 1, textFore, textBack);
}
- } else {
- // Normal text display
- if (vsDraw.styles[styleMain].visible) {
- if (twoPhaseDraw) {
- surface->DrawTextTransparent(rcSegment, textFont,
- rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
- i - startseg + 1, textFore);
- } else {
- surface->DrawTextNoClip(rcSegment, textFont,
- rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
- i - startseg + 1, textFore, textBack);
- }
- }
- if (vsDraw.viewWhitespace != wsInvisible ||
- (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
- for (int cpos = 0; cpos <= i - startseg; cpos++) {
- if (ll->chars[cpos + startseg] == ' ') {
- if (vsDraw.viewWhitespace != wsInvisible) {
- if (vsDraw.whitespaceForegroundSet)
- textFore = vsDraw.whitespaceForeground;
- if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
- XYPOSITION xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
- if (!twoPhaseDraw && drawWhitespaceBackground &&
- (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
- textBack = vsDraw.whitespaceBackground;
- PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
- rcSegment.top,
- ll->positions[cpos + startseg + 1] + xStart - subLineStart,
- rcSegment.bottom);
- surface->FillRectangle(rcSpace, textBack);
- }
- PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
- rcDot.right = rcDot.left + vs.whitespaceSize;
- rcDot.bottom = rcDot.top + vs.whitespaceSize;
- surface->FillRectangle(rcDot, textFore);
+ }
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
+ for (int cpos = 0; cpos <= i - startseg; cpos++) {
+ if (ll->chars[cpos + startseg] == ' ') {
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (vsDraw.whitespaceForegroundSet)
+ textFore = vsDraw.whitespaceForeground;
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ XYPOSITION xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
+ if (!twoPhaseDraw && drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ textBack = vsDraw.whitespaceBackground;
+ PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
+ rcSegment.top,
+ ll->positions[cpos + startseg + 1] + xStart - subLineStart,
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, textBack);
}
+ PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+ rcDot.right = rcDot.left + vs.whitespaceSize;
+ rcDot.bottom = rcDot.top + vs.whitespaceSize;
+ surface->FillRectangle(rcDot, textFore);
}
- if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
- for (int indentCount = (ll->positions[cpos + startseg] + epsilon) / indentWidth;
- indentCount <= (ll->positions[cpos + startseg + 1] - epsilon) / indentWidth;
- indentCount++) {
- if (indentCount > 0) {
- int xIndent = indentCount * indentWidth;
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
- (ll->xHighlightGuide == xIndent));
- }
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int indentCount = (ll->positions[cpos + startseg] + epsilon) / indentWidth;
+ indentCount <= (ll->positions[cpos + startseg + 1] - epsilon) / indentWidth;
+ indentCount++) {
+ if (indentCount > 0) {
+ int xIndent = indentCount * indentWidth;
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
}
}
- } else {
- inIndentation = false;
}
+ } else {
+ inIndentation = false;
}
}
}