diff options
Diffstat (limited to 'src/Editor.cxx')
-rw-r--r-- | src/Editor.cxx | 161 |
1 files changed, 127 insertions, 34 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 8ac091e8d..0c540d513 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -297,6 +297,7 @@ Editor::Editor() { mouseDownCaptures = true; bufferedDraw = true; + twoPhaseDraw = true; lastClickTime = 0; dwellDelay = SC_TIME_FOREVER; @@ -1764,6 +1765,34 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou } } +ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground, + ColourAllocated background, bool inSelection, int styleMain, int i, LineLayout *ll) { + if (inSelection) { + if (vsDraw.selbackset) { + if (primarySelection) + return vsDraw.selbackground.allocated; + else + return vsDraw.selbackground2.allocated; + } + } else { + if ((vsDraw.edgeState == EDGE_BACKGROUND) && + (i >= ll->edgeColumn) && + (ll->chars[i] != '\n') && + (ll->chars[i] != '\r')) + return vsDraw.edgecolour.allocated; + if (overrideBackground) + return background; + } + return vsDraw.styles[styleMain].back.allocated; +} + +void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { + Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); + PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom); + surface->Copy(rcCopyArea, from, + highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); +} + void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine) { @@ -1810,6 +1839,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } + bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) && + (!overrideBackground) && (vsDraw.whitespaceBackgroundSet); + bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. int indentWidth = pdoc->indentInChars * vsDraw.spaceWidth; if (indentWidth == 0) @@ -1818,7 +1850,6 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis int posLineStart = pdoc->LineStart(line); int posLineEnd = pdoc->LineStart(line + 1); - int styleMask = pdoc->stylingBitsMask; int startseg = ll->LineStart(subLine); int subLineStart = ll->positions[startseg]; int lineStart = 0; @@ -1827,7 +1858,63 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis lineStart = ll->LineStart(subLine); lineEnd = ll->LineStart(subLine+1); } - for (int i = lineStart; i < lineEnd; i++) { + int i; + + // Background drawing loop + for (i = lineStart; twoPhaseDraw && (i < lineEnd); i++) { + + int iDoc = i + posLineStart; + // If there is the end of a style run for any reason + if ((ll->styles[i] != ll->styles[i + 1]) || + i == (lineEnd-1) || + IsControlCharacter(ll->chars[i]) || IsControlCharacter(ll->chars[i + 1]) || + ((ll->selStart != ll->selEnd) && ((iDoc + 1 == ll->selStart) || (iDoc + 1 == ll->selEnd))) || + (i == (ll->edgeColumn - 1))) { + rcSegment.left = ll->positions[startseg] + xStart - subLineStart; + rcSegment.right = ll->positions[i + 1] + xStart - subLineStart; + // Only try to draw if really visible - enhances performance by not calling environment to + // draw strings that are completely past the right side of the window. + if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { + int styleMain = ll->styles[i]; + bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd); + ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, styleMain, i, ll); + if (ll->chars[i] == '\t') { + // Tab display + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) + textBack = vsDraw.whitespaceBackground.allocated; + surface->FillRectangle(rcSegment, textBack); + } else if (IsControlCharacter(ll->chars[i])) { + // Control character display + inIndentation = false; + surface->FillRectangle(rcSegment, textBack); + } else { + // Normal text display + surface->FillRectangle(rcSegment, textBack); + if (vsDraw.viewWhitespace != wsInvisible || + (inIndentation && vsDraw.viewIndentationGuides)) { + for (int cpos = 0; cpos <= i - startseg; cpos++) { + if (ll->chars[cpos + startseg] == ' ') { + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { + PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top, + ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom); + surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated); + } + } else { + inIndentation = false; + } + } + } + } + } + startseg = i + 1; + } + } + inIndentation = subLine == 0; // Do not handle indentation except on first subline. + startseg = ll->LineStart(subLine); + // Foreground drawing loop + for (i = lineStart; i < lineEnd; i++) { int iDoc = i + posLineStart; // If there is the end of a style run for any reason @@ -1842,30 +1929,21 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // draw strings that are completely past the right side of the window. if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { int styleMain = ll->styles[i]; - ColourAllocated textBack = vsDraw.styles[styleMain].back.allocated; ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated; Font &textFont = vsDraw.styles[styleMain].font; bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd); - if (inSelection) { - if (vsDraw.selbackset) { - if (primarySelection) - textBack = vsDraw.selbackground.allocated; - else - textBack = vsDraw.selbackground2.allocated; - } - if (vsDraw.selforeset) - textFore = vsDraw.selforeground.allocated; - } else { - if (overrideBackground) - textBack = background; - if ((vsDraw.edgeState == EDGE_BACKGROUND) && (i >= ll->edgeColumn) && (ll->chars[i] != '\n') && (ll->chars[i] != '\r')) - textBack = vsDraw.edgecolour.allocated; + if (inSelection && (vsDraw.selforeset)) { + textFore = vsDraw.selforeground.allocated; } + ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, styleMain, i, ll); if (ll->chars[i] == '\t') { - // Manage tab display - if (!overrideBackground && vsDraw.whitespaceBackgroundSet && (vsDraw.viewWhitespace != wsInvisible) && (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceBackground.allocated; - surface->FillRectangle(rcSegment, textBack); + // Tab display + if (!twoPhaseDraw) { + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) + textBack = vsDraw.whitespaceBackground.allocated; + surface->FillRectangle(rcSegment, textBack); + } if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) { if (vsDraw.whitespaceForegroundSet) textFore = vsDraw.whitespaceForeground.allocated; @@ -1874,10 +1952,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (inIndentation && vsDraw.viewIndentationGuides) { for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) { if (xIG >= ll->positions[i] && xIG > 0) { - Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); - PRectangle rcCopyArea(xIG + xStart + 1, rcSegment.top, xIG + xStart + 2, rcSegment.bottom); - surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == xIG) ? - *pixmapIndentGuideHighlight : *pixmapIndentGuide); + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment, + (ll->xHighlightGuide == xIG)); } } } @@ -1889,12 +1965,14 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } } else if (IsControlCharacter(ll->chars[i])) { - // Manage control character display + // Control character display inIndentation = false; if (controlCharSymbol < 32) { // Draw the character const char *ctrlChar = ControlCharacterString(ll->chars[i]); - surface->FillRectangle(rcSegment, textBack); + if (!twoPhaseDraw) { + surface->FillRectangle(rcSegment, textBack); + } int normalCharHeight = surface->Ascent(ctrlCharsFont) - surface->InternalLeading(ctrlCharsFont); PRectangle rcCChar = rcSegment; @@ -1918,10 +1996,16 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis cc, 1, textBack, textFore); } } else { - // Manage normal display - surface->DrawTextNoClip(rcSegment, textFont, + // Normal text display + 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)) { for (int cpos = 0; cpos <= i - startseg; cpos++) { @@ -1931,7 +2015,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis textFore = vsDraw.whitespaceForeground.allocated; if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2; - if (!overrideBackground && vsDraw.whitespaceBackgroundSet) { + if (!twoPhaseDraw && drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { textBack = vsDraw.whitespaceBackground.allocated; PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top, ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom); surface->FillRectangle(rcSpace, textBack); @@ -1945,10 +2030,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (inIndentation && vsDraw.viewIndentationGuides) { int startSpace = ll->positions[cpos + startseg]; if (startSpace > 0 && (startSpace % indentWidth == 0)) { - Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); - PRectangle rcCopyArea(startSpace + xStart + 1, rcSegment.top, startSpace + xStart + 2, rcSegment.bottom); - surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == ll->positions[cpos + startseg]) ? - *pixmapIndentGuideHighlight : *pixmapIndentGuide); + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment, + (ll->xHighlightGuide == ll->positions[cpos + startseg])); } } } else { @@ -1994,6 +2077,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } // End of the drawing of the current line + int styleMask = pdoc->stylingBitsMask; + // Fill in a PRectangle representing the end of line characters int xEol = ll->positions[lineEnd] - subLineStart; rcSegment.left = xEol + xStart; @@ -5114,6 +5199,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETBUFFEREDDRAW: return bufferedDraw; + case SCI_GETTWOPHASEDRAW: + return twoPhaseDraw; + + case SCI_SETTWOPHASEDRAW: + twoPhaseDraw = wParam != 0; + InvalidateStyleRedraw(); + break; + case SCI_SETTABWIDTH: if (wParam > 0) pdoc->tabInChars = wParam; |