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 | |
| parent | 38ae0852c15b8c2475f5f78b4e678379ce0be3de (diff) | |
| download | scintilla-mirror-1ac62f75e51df6fd1521c0bb7633ff20a128e169.tar.gz | |
Block caret feature added by Todd Whiteman.
| -rw-r--r-- | doc/ScintillaDoc.html | 22 | ||||
| -rw-r--r-- | include/Scintilla.h | 5 | ||||
| -rw-r--r-- | include/Scintilla.iface | 11 | ||||
| -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 | 
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; | 
