aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2007-05-29 12:39:35 +0000
committernyamatongwe <unknown>2007-05-29 12:39:35 +0000
commit1ac62f75e51df6fd1521c0bb7633ff20a128e169 (patch)
tree4528e55558ba91dde9709755cc5a1abec6540425
parent38ae0852c15b8c2475f5f78b4e678379ce0be3de (diff)
downloadscintilla-mirror-1ac62f75e51df6fd1521c0bb7633ff20a128e169.tar.gz
Block caret feature added by Todd Whiteman.
-rw-r--r--doc/ScintillaDoc.html22
-rw-r--r--include/Scintilla.h5
-rw-r--r--include/Scintilla.iface11
-rw-r--r--src/Editor.cxx135
-rw-r--r--src/Editor.h1
-rw-r--r--src/ViewStyle.cxx2
-rw-r--r--src/ViewStyle.h1
7 files changed, 153 insertions, 24 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 6ded35d2c..053a49fe9 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -2158,6 +2158,8 @@ struct TextToFind {
<a class="message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA</a><br />
<a class="message" href="#SCI_SETCARETPERIOD">SCI_SETCARETPERIOD(int milliseconds)</a><br />
<a class="message" href="#SCI_GETCARETPERIOD">SCI_GETCARETPERIOD</a><br />
+ <a class="message" href="#SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</a><br />
+ <a class="message" href="#SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</a><br />
<a class="message" href="#SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</a><br />
<a class="message" href="#SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</a><br />
<a class="message" href="#SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useSetting,
@@ -2228,12 +2230,26 @@ struct TextToFind {
state. Setting the period to 0 stops the caret blinking. The default value is 500 milliseconds.
<code>SCI_GETCARETPERIOD</code> returns the current setting.</p>
+ <p><b id="SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</b><br />
+ <b id="SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</b><br />
+ The style of the caret can be set with <code>SCI_SETCARETSTYLE</code> to be a line caret
+ (CARETSTYLE_LINE=1), a block caret (CARETSTYLE_BLOCK=2) or to not draw at all
+ (CARETSTYLE_INVISIBLE=0). The default value is the line caret (CARETSTYLE_LINE=1).
+ You can determine the current caret style setting using <code>SCI_GETCARETSTYLE</code>.</p>
+
+ <p>The block character draws most combining and multibyte character sequences successfully,
+ though some fonts like Thai Fonts (and possibly others) can sometimes appear strange when
+ the cursor is positioned at these characters, which may result in only drawing a part of the
+ cursor character sequence. This is most notable on Windows platforms.</p>
+
<p><b id="SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</b><br />
<b id="SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</b><br />
- The width of the caret can be set with <code>SCI_SETCARETWIDTH</code> to a value of 0, 1, 2 or
- 3 pixels. The default width is 1 pixel. You can read back the current width with
+ The width of the line caret can be set with <code>SCI_SETCARETWIDTH</code> to a value of
+ 0, 1, 2 or 3 pixels. The default width is 1 pixel. You can read back the current width with
<code>SCI_GETCARETWIDTH</code>. A width of 0 makes the caret invisible (added at version
- 1.50).</p>
+ 1.50), similar to setting the caret style to CARETSTYLE_INVISIBLE (though not interchangable).
+ This setting only affects the width of the cursor when the cursor style is set to line caret
+ mode, it does not affect the width for a block caret.</p>
<p><b id="SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useHotSpotForeColour, int <a class="jump"
href="#colour">colour</a>)</b><br />
diff --git a/include/Scintilla.h b/include/Scintilla.h
index e7730b68c..ab5f05d76 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -642,6 +642,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_ALPHA_NOALPHA 256
#define SCI_SETCARETLINEBACKALPHA 2470
#define SCI_GETCARETLINEBACKALPHA 2471
+#define CARETSTYLE_INVISIBLE 0
+#define CARETSTYLE_LINE 1
+#define CARETSTYLE_BLOCK 2
+#define SCI_SETCARETSTYLE 2950
+#define SCI_GETCARETSTYLE 2951
#define SCI_SETINDICATORCURRENT 2500
#define SCI_GETINDICATORCURRENT 2501
#define SCI_SETINDICATORVALUE 2502
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 85d45780e..c46d8dbd7 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -1734,6 +1734,17 @@ set void SetCaretLineBackAlpha=2470(int alpha,)
# Get the background alpha of the caret line.
get int GetCaretLineBackAlpha=2471(,)
+enu CaretStyle=CARETSTYLE_
+val CARETSTYLE_INVISIBLE=0
+val CARETSTYLE_LINE=1
+val CARETSTYLE_BLOCK=2
+
+# Set the style of the caret to be drawn.
+set void SetCaretStyle=2950(int caretStyle,)
+
+# Returns the current style of the caret.
+get int GetCaretStyle=2951(,)
+
# Set the indicator used for IndicatorFillRange and IndicatorClearRange
set void SetIndicatorCurrent=2500(int indicator,)
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;