diff options
-rw-r--r-- | src/Editor.cxx | 64 | ||||
-rw-r--r-- | src/Editor.h | 1 |
2 files changed, 41 insertions, 24 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 21184d387..f748bacc1 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -85,6 +85,7 @@ LineLayout::LineLayout(int maxLineLength_) : edgeColumn(0), chars(0), styles(0), + styleBitsSet(0), indicators(0), positions(0), hsStart(0), @@ -1929,39 +1930,39 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou posLineEnd = posLineStart + ll->maxLineLength; } if (ll->validity == LineLayout::llCheckTextAndStyle) { - int lineLength = 0; - for (int cid = posLineStart; cid < posLineEnd; cid++) { - char chDoc = pdoc->CharAt(cid); - if (vstyle.viewEOL || (!IsEOLChar(chDoc))) { - lineLength++; + int lineLength = posLineEnd - posLineStart; + if (!vstyle.viewEOL) { + int cid = posLineEnd - 1; + while ((cid > posLineStart) && IsEOLChar(pdoc->CharAt(cid))) { + cid--; + lineLength--; } } if (lineLength == ll->numCharsInLine) { - int numCharsInLine = 0; // See if chars, styles, indicators, are all the same bool allSame = true; const int styleMask = pdoc->stylingBitsMask; // Check base line layout char styleByte = 0; - for (int charInDoc = posLineStart; allSame && (charInDoc < posLineEnd); charInDoc++) { + int numCharsInLine = 0; + while (numCharsInLine < lineLength) { + int charInDoc = numCharsInLine + posLineStart; char chDoc = pdoc->CharAt(charInDoc); styleByte = pdoc->StyleAt(charInDoc); - if (vstyle.viewEOL || (!IsEOLChar(chDoc))) { + allSame = allSame && + (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask)); + allSame = allSame && + (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask)); + if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) allSame = allSame && - (ll->styles[numCharsInLine] == static_cast<char>(styleByte & styleMask)); + (ll->chars[numCharsInLine] == chDoc); + else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) allSame = allSame && - (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask)); - if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper) - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc))); - else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc))); - else - allSame = allSame && - (ll->chars[numCharsInLine] == chDoc); - numCharsInLine++; - } + (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc))); + else // Style::caseUpper + allSame = allSame && + (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc))); + numCharsInLine++; } allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled if (allSame) { @@ -1988,10 +1989,12 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou char styleByte = 0; int styleMask = pdoc->stylingBitsMask; + ll->styleBitsSet = 0; // Fill base line layout for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) { char chDoc = pdoc->CharAt(charInDoc); styleByte = pdoc->StyleAt(charInDoc); + ll->styleBitsSet |= styleByte; if (vstyle.viewEOL || (!IsEOLChar(chDoc))) { ll->chars[numCharsInLine] = chDoc; ll->styles[numCharsInLine] = static_cast<char>(styleByte & styleMask); @@ -2018,6 +2021,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou bool lastSegItalics = false; Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font; + int ctrlCharWidth[32] = {0}; bool isControlNext = IsControlCharacter(ll->chars[0]); for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) { bool isControl = isControlNext; @@ -2031,9 +2035,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll->positions[charInLine + 1] = ((((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx; } else if (controlCharSymbol < 32) { - const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]); - // +3 For a blank on front and rounded edge each side: - ll->positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3; + if (ctrlCharWidth[ll->chars[charInLine]] == 0) { + const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]); + // +3 For a blank on front and rounded edge each side: + ctrlCharWidth[ll->chars[charInLine]] = + surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3; + } + ll->positions[charInLine + 1] = ctrlCharWidth[ll->chars[charInLine]]; } else { char cc[2] = { static_cast<char>(controlCharSymbol), '\0' }; surface->MeasureWidths(ctrlCharsFont, cc, 1, @@ -2422,6 +2430,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } } + } else if (rcSegment.left > rcLine.right) { + break; } startseg = i + 1; } @@ -2584,6 +2594,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis rcUL.bottom = rcUL.top + 1; surface->FillRectangle(rcUL, textFore); } + } else if (rcSegment.left > rcLine.right) { + break; } startseg = i + 1; } @@ -2592,6 +2604,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // Draw indicators // foreach indicator... for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) { + if (!(mask & ll->styleBitsSet)) { + mask <<= 1; + continue; + } int startPos = -1; // foreach style pos in line... for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) { diff --git a/src/Editor.h b/src/Editor.h index 5370f5b2e..f779e21cc 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -64,6 +64,7 @@ public: int edgeColumn; char *chars; unsigned char *styles; + int styleBitsSet; char *indicators; int *positions; char bracePreviousStyles[2]; |