diff options
author | nyamatongwe <unknown> | 2007-05-29 12:39:35 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2007-05-29 12:39:35 +0000 |
commit | 1ac62f75e51df6fd1521c0bb7633ff20a128e169 (patch) | |
tree | 4528e55558ba91dde9709755cc5a1abec6540425 /src | |
parent | 38ae0852c15b8c2475f5f78b4e678379ce0be3de (diff) | |
download | scintilla-mirror-1ac62f75e51df6fd1521c0bb7633ff20a128e169.tar.gz |
Block caret feature added by Todd Whiteman.
Diffstat (limited to 'src')
-rw-r--r-- | src/Editor.cxx | 135 | ||||
-rw-r--r-- | src/Editor.h | 1 | ||||
-rw-r--r-- | src/ViewStyle.cxx | 2 | ||||
-rw-r--r-- | src/ViewStyle.h | 1 |
4 files changed, 118 insertions, 21 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index acea1f463..0147308ad 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1441,6 +1441,10 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { xOffsetNew = pt.x + xOffset - rcClient.left; } else if (pt.x + xOffset >= rcClient.right + xOffsetNew) { xOffsetNew = pt.x + xOffset - rcClient.right + 1; + if (vs.caretStyle == CARETSTYLE_BLOCK) { + // Ensure we can see a good portion of the block caret + xOffsetNew += vs.aveCharWidth; + } } if (xOffsetNew < 0) { xOffsetNew = 0; @@ -2766,6 +2770,61 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } +void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret) { + + int lineStart = ll->LineStart(subLine); + int posBefore = posCaret; + int posAfter = MovePositionOutsideChar(posCaret+1, 1); + int numCharsToDraw = posAfter - posCaret; + + // Work out where the starting and ending offsets are. We need to + // see if the previous character shares horizontal space, such as a + // glyph / combining character. If so we'll need to draw that too. + int offsetFirstChar = offset; + int offsetLastChar = offset + (posAfter - posCaret); + while ((offsetLastChar - numCharsToDraw) >= lineStart) { + if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { + // The char does not share horizontal space + break; + } + // Char shares horizontal space, update the numChars to draw + // Update posBefore to point to the prev char + posBefore = MovePositionOutsideChar(posBefore-1, -1); + numCharsToDraw = posAfter - posBefore; + offsetFirstChar = offset - (posCaret - posBefore); + } + + // See if the next character shares horizontal space, if so we'll + // need to draw that too. + numCharsToDraw = offsetLastChar - offsetFirstChar; + while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { + // Update posAfter to point to the 2nd next char, this is where + // the next character ends, and 2nd next begins. We'll need + // to compare these two + posBefore = posAfter; + posAfter = MovePositionOutsideChar(posAfter+1, 1); + offsetLastChar = offset + (posAfter - posCaret); + if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { + // The char does not share horizontal space + break; + } + // Char shares horizontal space, update the numChars to draw + numCharsToDraw = offsetLastChar - offsetFirstChar; + } + + // We now know what to draw, update the caret drawing rectangle + rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[ll->LineStart(subLine)] + xStart; + rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[ll->LineStart(subLine)] + xStart; + + // This character is where the caret block is, we override the colours + // (inversed) for drawing the caret here. + int styleMain = ll->styles[offsetFirstChar]; + surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font, + rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, + numCharsToDraw, vsDraw.styles[styleMain].back.allocated, + vsDraw.caretcolour.allocated); +} + void Editor::RefreshPixMaps(Surface *surfaceWindow) { if (!pixmapSelPattern->Initialised()) { const int patternSize = 8; @@ -3067,35 +3126,57 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { if (lineStart != 0) // Wrapped xposCaret += actualWrapVisualStartIndent * vs.aveCharWidth; } - int widthOverstrikeCaret; - if (posCaret == pdoc->Length()) { // At end of document - widthOverstrikeCaret = vs.aveCharWidth; - } else if ((posCaret - rangeLine.start) >= ll->numCharsInLine) { // At end of line - widthOverstrikeCaret = vs.aveCharWidth; - } else { - widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; - } - if (widthOverstrikeCaret < 3) // Make sure its visible - widthOverstrikeCaret = 3; - if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) { - PRectangle rcCaret = rcLine; + if ((xposCaret >= 0) && (vs.caretWidth > 0) && (vs.caretStyle != CARETSTYLE_INVISIBLE) && + ((posDrag >= 0) || (caret.active && caret.on))) { + bool caretAtEOF = false; + bool caretAtEOL = false; + bool drawBlockCaret = false; + int widthOverstrikeCaret; int caretWidthOffset = 0; - if ((offset > 0) && (vs.caretWidth > 1)) + PRectangle rcCaret = rcLine; + + if (posCaret == pdoc->Length()) { // At end of document + caretAtEOF = true; + widthOverstrikeCaret = vs.aveCharWidth; + } else if ((posCaret - rangeLine.start) >= ll->numCharsInLine) { // At end of line + caretAtEOL = true; + widthOverstrikeCaret = vs.aveCharWidth; + } else { + widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; + } + if (widthOverstrikeCaret < 3) // Make sure its visible + widthOverstrikeCaret = 3; + + if (offset > 0) caretWidthOffset = 1; // Move back so overlaps both character cells. if (posDrag >= 0) { + /* Dragging text, use a line caret */ rcCaret.left = xposCaret - caretWidthOffset; rcCaret.right = rcCaret.left + vs.caretWidth; - } else { - if (inOverstrike) { - rcCaret.top = rcCaret.bottom - 2; - rcCaret.left = xposCaret + 1; - rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; + } else if (inOverstrike) { + /* Overstrike (insert mode), use a modified bar caret */ + rcCaret.top = rcCaret.bottom - 2; + rcCaret.left = xposCaret + 1; + rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; + } else if (vs.caretStyle == CARETSTYLE_BLOCK) { + /* Block caret */ + rcCaret.left = xposCaret; + if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { + drawBlockCaret = true; + rcCaret.right = xposCaret + widthOverstrikeCaret; } else { - rcCaret.left = xposCaret - caretWidthOffset; - rcCaret.right = rcCaret.left + vs.caretWidth; + rcCaret.right = xposCaret + vs.aveCharWidth; } + } else { + /* Line caret */ + rcCaret.left = xposCaret - caretWidthOffset; + rcCaret.right = rcCaret.left + vs.caretWidth; + } + if (drawBlockCaret) { + DrawBlockCaret(surface, vs, ll, subLine, xStart, offset, posCaret, rcCaret); + } else { + surface->FillRectangle(rcCaret, vs.caretcolour.allocated); } - surface->FillRectangle(rcCaret, vs.caretcolour.allocated); } } } @@ -7114,6 +7195,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCARETFORE: return vs.caretcolour.desired.AsLong(); + case SCI_SETCARETSTYLE: + if (wParam >= CARETSTYLE_INVISIBLE && wParam <= CARETSTYLE_BLOCK) + vs.caretStyle = wParam; + else + /* Default to the line caret */ + vs.caretStyle = CARETSTYLE_LINE; + InvalidateStyleRedraw(); + break; + + case SCI_GETCARETSTYLE: + return vs.caretStyle; + case SCI_SETCARETWIDTH: if (wParam <= 0) vs.caretWidth = 0; diff --git a/src/Editor.h b/src/Editor.h index ef061e46f..0ce6f27fb 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -399,6 +399,7 @@ protected: // ScintillaBase subclass needs access to much of Editor PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine=0); + void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret); void RefreshPixMaps(Surface *surfaceWindow); void Paint(Surface *surfaceWindow, PRectangle rcArea); long FormatRange(bool draw, RangeToFormat *pfr); diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 1cf95cca2..071171e68 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -118,6 +118,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) { caretLineAlpha = source.caretLineAlpha; edgecolour.desired = source.edgecolour.desired; edgeState = source.edgeState; + caretStyle = source.caretStyle; caretWidth = source.caretWidth; someStylesProtected = false; leftMarginWidth = source.leftMarginWidth; @@ -186,6 +187,7 @@ void ViewStyle::Init() { caretLineAlpha = SC_ALPHA_NOALPHA; edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0); edgeState = EDGE_NONE; + caretStyle = CARETSTYLE_LINE; caretWidth = 1; someStylesProtected = false; diff --git a/src/ViewStyle.h b/src/ViewStyle.h index eb4e8dc11..61ebe85ee 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -91,6 +91,7 @@ public: int caretLineAlpha; ColourPair edgecolour; int edgeState; + int caretStyle; int caretWidth; bool someStylesProtected; bool extraFontFlag; |