summaryrefslogtreecommitdiffstats
path: root/scintilla/src/EditView.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'scintilla/src/EditView.cxx')
-rw-r--r--scintilla/src/EditView.cxx236
1 files changed, 196 insertions, 40 deletions
diff --git a/scintilla/src/EditView.cxx b/scintilla/src/EditView.cxx
index e6cd8fc..8ffc1bc 100644
--- a/scintilla/src/EditView.cxx
+++ b/scintilla/src/EditView.cxx
@@ -306,21 +306,25 @@ static const char *ControlCharacterString(unsigned char ch) {
}
}
-static void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
- int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2;
- int xhead = static_cast<int>(rcTab.right) - 1 - ydiff;
- if (xhead <= rcTab.left) {
- ydiff -= static_cast<int>(rcTab.left) - xhead - 1;
- xhead = static_cast<int>(rcTab.left) - 1;
- }
+static void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid, const ViewStyle &vsDraw) {
if ((rcTab.left + 2) < (rcTab.right - 1))
surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid);
else
surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid);
- surface->LineTo(xhead, ymid - ydiff);
- surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
- surface->LineTo(xhead, ymid + ydiff);
+
+ // Draw the arrow head if needed
+ if (vsDraw.tabDrawMode == tdLongArrow) {
+ int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2;
+ int xhead = static_cast<int>(rcTab.right) - 1 - ydiff;
+ if (xhead <= rcTab.left) {
+ ydiff -= static_cast<int>(rcTab.left) - xhead - 1;
+ xhead = static_cast<int>(rcTab.left) - 1;
+ }
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+ }
}
void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
@@ -596,19 +600,24 @@ void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, co
}
}
-Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs) {
+Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine,
+ const ViewStyle &vs, PointEnd pe) {
Point pt;
if (pos.Position() == INVALID_POSITION)
return pt;
- const int line = model.pdoc->LineFromPosition(pos.Position());
- const int lineVisible = model.cs.DisplayFromDoc(line);
- //Platform::DebugPrintf("line=%d\n", line);
- AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
+ int lineDoc = model.pdoc->LineFromPosition(pos.Position());
+ int posLineStart = model.pdoc->LineStart(lineDoc);
+ if ((pe & peLineEnd) && (lineDoc > 0) && (pos.Position() == posLineStart)) {
+ // Want point at end of first line
+ lineDoc--;
+ posLineStart = model.pdoc->LineStart(lineDoc);
+ }
+ const int lineVisible = model.cs.DisplayFromDoc(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
if (surface && ll) {
- const int posLineStart = model.pdoc->LineStart(line);
- LayoutLine(model, line, surface, vs, ll, model.wrapWidth);
+ LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth);
const int posInLine = pos.Position() - posLineStart;
- pt = ll->PointFromPosition(posInLine, vs.lineHeight);
+ pt = ll->PointFromPosition(posInLine, vs.lineHeight, pe);
pt.y += (lineVisible - topLine) * vs.lineHeight;
pt.x += vs.textStart - model.xOffset;
}
@@ -616,6 +625,31 @@ Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, S
return pt;
}
+Range EditView::RangeDisplayLine(Surface *surface, const EditModel &model, int lineVisible, const ViewStyle &vs) {
+ Range rangeSubLine = Range(0,0);
+ if (lineVisible < 0) {
+ return rangeSubLine;
+ }
+ const int lineDoc = model.cs.DocFromDisplay(lineVisible);
+ const int positionLineStart = model.pdoc->LineStart(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth);
+ const int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
+ const int subLine = lineVisible - lineStartSet;
+ if (subLine < ll->lines) {
+ rangeSubLine = ll->SubLineRange(subLine);
+ if (subLine == ll->lines-1) {
+ rangeSubLine.end = model.pdoc->LineStart(lineDoc + 1) -
+ positionLineStart;
+ }
+ }
+ }
+ rangeSubLine.start += positionLineStart;
+ rangeSubLine.end += positionLineStart;
+ return rangeSubLine;
+}
+
SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const ViewStyle &vs) {
pt.x = pt.x - vs.textStart;
int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight));
@@ -845,7 +879,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
int alpha = SC_ALPHA_NOALPHA;
if (!hideSelection) {
int posAfterLineEnd = model.pdoc->LineStart(line + 1);
- eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ eolInSelection = (lastSubLine == true) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
}
@@ -914,25 +948,15 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
}
- // Fill the remainder of the line
rcSegment.left = rcSegment.right;
if (rcSegment.left < rcLine.left)
rcSegment.left = rcLine.left;
rcSegment.right = rcLine.right;
- if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
- } else {
- if (background.isSet) {
- surface->FillRectangle(rcSegment, background);
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
- } else {
- surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
- }
- if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
- }
+ bool fillRemainder = !lastSubLine || model.foldDisplayTextStyle == SC_FOLDDISPLAYTEXT_HIDDEN || !model.cs.GetFoldDisplayTextShown(line);
+ if (fillRemainder) {
+ // Fill the remainder of the line
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcSegment, subLine);
}
bool drawWrapMarkEnd = false;
@@ -963,14 +987,23 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw,
- const LineLayout *ll, int xStart, PRectangle rcLine, int subLine, Indicator::DrawState drawState, int value) {
+ const LineLayout *ll, int xStart, PRectangle rcLine, int secondCharacter, int subLine, Indicator::DrawState drawState, int value) {
const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
PRectangle rcIndic(
ll->positions[startPos] + xStart - subLineStart,
rcLine.top + vsDraw.maxAscent,
ll->positions[endPos] + xStart - subLineStart,
rcLine.top + vsDraw.maxAscent + 3);
- vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine, drawState, value);
+ PRectangle rcFirstCharacter = rcIndic;
+ // Allow full descent space for character indicators
+ rcFirstCharacter.bottom = rcLine.top + vsDraw.maxAscent + vsDraw.maxDescent;
+ if (secondCharacter >= 0) {
+ rcFirstCharacter.right = ll->positions[secondCharacter] + xStart - subLineStart;
+ } else {
+ // Indicator continued from earlier line so make an empty box and don't draw
+ rcFirstCharacter.right = rcFirstCharacter.left;
+ }
+ vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine, rcFirstCharacter, drawState, value);
}
static void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
@@ -993,8 +1026,9 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS
rangeRun.ContainsCharacter(hoverIndicatorPos);
const int value = deco->rs.ValueAt(startPos);
Indicator::DrawState drawState = hover ? Indicator::drawHover : Indicator::drawNormal;
+ const int posSecond = model.pdoc->MovePositionOutsideChar(rangeRun.First() + 1, 1);
DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
- surface, vsDraw, ll, xStart, rcLine, subLine, drawState, value);
+ surface, vsDraw, ll, xStart, rcLine, posSecond - posLineStart, subLine, drawState, value);
startPos = endPos;
if (!deco->rs.ValueAt(startPos)) {
startPos = deco->rs.EndRun(startPos);
@@ -1012,19 +1046,110 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS
if (rangeLine.ContainsCharacter(model.braces[0])) {
int braceOffset = model.braces[0] - posLineStart;
if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1);
+ const int secondOffset = model.pdoc->MovePositionOutsideChar(model.braces[0] + 1, 1) - posLineStart;
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, secondOffset, subLine, Indicator::drawNormal, 1);
}
}
if (rangeLine.ContainsCharacter(model.braces[1])) {
int braceOffset = model.braces[1] - posLineStart;
if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1);
+ const int secondOffset = model.pdoc->MovePositionOutsideChar(model.braces[1] + 1, 1) - posLineStart;
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, secondOffset, subLine, Indicator::drawNormal, 1);
}
}
}
}
}
+void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int line, int xStart, PRectangle rcLine, int subLine, XYACCUMULATOR subLineStart, DrawPhase phase) {
+ const bool lastSubLine = subLine == (ll->lines - 1);
+ if (!lastSubLine)
+ return;
+
+ if ((model.foldDisplayTextStyle == SC_FOLDDISPLAYTEXT_HIDDEN) || !model.cs.GetFoldDisplayTextShown(line))
+ return;
+
+ PRectangle rcSegment = rcLine;
+ const char *foldDisplayText = model.cs.GetFoldDisplayText(line);
+ const int lengthFoldDisplayText = static_cast<int>(strlen(foldDisplayText));
+ FontAlias fontText = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].font;
+ const int widthFoldDisplayText = static_cast<int>(surface->WidthText(fontText, foldDisplayText, lengthFoldDisplayText));
+
+ int eolInSelection = 0;
+ int alpha = SC_ALPHA_NOALPHA;
+ if (!hideSelection) {
+ int posAfterLineEnd = model.pdoc->LineStart(line + 1);
+ eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ }
+
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ XYPOSITION virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth;
+ rcSegment.left = xStart + static_cast<XYPOSITION>(ll->positions[ll->numCharsInLine] - subLineStart) + spaceWidth + virtualSpace;
+ rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthFoldDisplayText);
+
+ ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret);
+ FontAlias textFont = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].font;
+ ColourDesired textFore = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].fore;
+ if (eolInSelection && (vsDraw.selColours.fore.isSet)) {
+ textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ ColourDesired textBack = TextBackground(model, vsDraw, ll, background, eolInSelection,
+ false, STYLE_FOLDDISPLAYTEXT, -1);
+
+ if (model.trackLineWidth) {
+ if (rcSegment.right + 1> lineWidthMaxSeen) {
+ // Fold display text border drawn on rcSegment.right with width 1 is the last visble object of the line
+ lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1);
+ }
+ }
+
+ if ((phasesDraw != phasesOne) && (phase & drawBack)) {
+ surface->FillRectangle(rcSegment, textBack);
+
+ // Fill Remainder of the line
+ PRectangle rcRemainder = rcSegment;
+ rcRemainder.left = rcRemainder.right + 1;
+ if (rcRemainder.left < rcLine.left)
+ rcRemainder.left = rcLine.left;
+ rcRemainder.right = rcLine.right;
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine);
+ }
+
+ if (phase & drawText) {
+ if (phasesDraw != phasesOne) {
+ surface->DrawTextTransparent(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, foldDisplayText,
+ lengthFoldDisplayText, textFore);
+ } else {
+ surface->DrawTextNoClip(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, foldDisplayText,
+ lengthFoldDisplayText, textFore, textBack);
+ }
+ }
+
+ if (phase & drawIndicatorsFore) {
+ if (model.foldDisplayTextStyle == SC_FOLDDISPLAYTEXT_BOXED) {
+ surface->PenColour(textFore);
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom));
+ surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom));
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1));
+ }
+ }
+
+ if (phase & drawSelectionTranslucent) {
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && alpha != SC_ALPHA_NOALPHA) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+}
+
static bool AnnotationBoxedOrIndented(int annotationVisible) {
return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED;
}
@@ -1537,7 +1662,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight,
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
if (customDrawTabArrow == NULL)
- DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
+ DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2), vsDraw);
else
customDrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
}
@@ -1743,6 +1868,8 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
xStart, subLine, subLineStart, background);
}
+ DrawFoldDisplayText(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, subLineStart, phase);
+
if (!hideSelection && (phase & drawSelectionTranslucent)) {
DrawTranslucentSelection(surface, model, vsDraw, ll, line, rcLine, subLine, lineRange, xStart);
}
@@ -1878,7 +2005,8 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle),
static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle);
- if (leftTextOverlap && bufferedDraw) {
+ if (leftTextOverlap && (bufferedDraw || ((phasesDraw < phasesMultiple) && (*it & drawBack)))) {
+ // Clear the left margin
PRectangle rcSpacer = rcLine;
rcSpacer.right = rcSpacer.left;
rcSpacer.left -= 1;
@@ -1955,6 +2083,34 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
}
}
+void EditView::FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int line, PRectangle rcArea, int subLine) {
+ int eolInSelection = 0;
+ int alpha = SC_ALPHA_NOALPHA;
+ if (!hideSelection) {
+ int posAfterLineEnd = model.pdoc->LineStart(line + 1);
+ eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ }
+
+ ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret);
+
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcArea, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ if (background.isSet) {
+ surface->FillRectangle(rcArea, background);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
+ surface->FillRectangle(rcArea, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else {
+ surface->FillRectangle(rcArea, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcArea, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+}
+
// Space (3 space characters) between line numbers and text when printing.
#define lineNumberPrintSpace " "