diff options
| -rw-r--r-- | include/Scintilla.h | 1 | ||||
| -rw-r--r-- | include/Scintilla.iface | 4 | ||||
| -rw-r--r-- | src/Editor.cxx | 106 | ||||
| -rw-r--r-- | src/Editor.h | 6 | 
4 files changed, 81 insertions, 36 deletions
| diff --git a/include/Scintilla.h b/include/Scintilla.h index 664d11879..dcfa4303d 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -58,6 +58,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,  #define SCI_GETVIEWWS 2020  #define SCI_SETVIEWWS 2021  #define SCI_POSITIONFROMPOINT 2022 +#define SCI_POSITIONFROMPOINTCLOSE 2023  #define SCI_GOTOLINE 2024  #define SCI_GOTOPOS 2025  #define SCI_SETANCHOR 2026 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 5baee89fc..0b0177291 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -134,6 +134,10 @@ set void SetViewWS=2021(int viewWS,)  # Find the position from a point within the window.  fun int PositionFromPoint=2022(int x, int y) +# Find the position from a point within the window but return  +# INVALID_POSITION if not close to text. +fun int PositionFromPointClose=2023(int x, int y) +  # Set caret to start of a line and ensure it is visible.  fun void GotoLine=2024(int line,) diff --git a/src/Editor.cxx b/src/Editor.cxx index 880d417d5..fb765d430 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -231,15 +231,17 @@ const char *ControlCharacterString(unsigned char ch) {  	}  } -Point Editor::LocationFromPosition(unsigned int pos) { +Point Editor::LocationFromPosition(int pos) { +	Point pt;  	RefreshStyleData(); +	if (pos == INVALID_POSITION) +		return pt;  	int line = pdoc->LineFromPosition(pos);  	int lineVisible = cs.DisplayFromDoc(line);  	//Platform::DebugPrintf("line=%d\n", line);  	Surface surface;  	surface.Init();  	surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); -	Point pt;  	pt.y = (lineVisible - topLine) * vs.lineHeight;  	// + half a lineheight?  	unsigned int posLineStart = pdoc->LineStart(line);  	LineLayout ll; @@ -253,7 +255,7 @@ Point Editor::LocationFromPosition(unsigned int pos) {  	return pt;  } -int Editor::XFromPosition(unsigned int pos) { +int Editor::XFromPosition(int pos) {  	Point pt = LocationFromPosition(pos);  	return pt.x - vs.fixedColumnWidth + xOffset;  } @@ -278,7 +280,6 @@ int Editor::PositionFromLocation(Point pt) {  		return 0;  	if (line >= pdoc->LinesTotal())  		return pdoc->Length(); -	//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);  	Surface surface;  	surface.Init();  	surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); @@ -296,6 +297,42 @@ int Editor::PositionFromLocation(Point pt) {  	return ll.numCharsInLine + posLineStart;  } +// Like PositionFromLocation but INVALID_POSITION returned when not near any text. +int Editor::PositionFromLocationClose(Point pt) { +	RefreshStyleData(); +	PRectangle rcClient = GetTextRectangle(); +	if (!rcClient.Contains(pt)) +		return INVALID_POSITION; +	if (pt.x < vs.fixedColumnWidth) +		return INVALID_POSITION; +	if (pt.y < 0) +		return INVALID_POSITION; +	pt.x = pt.x - vs.fixedColumnWidth + xOffset; +	int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine); +	if (pt.y < 0) {	// Division rounds towards 0 +		line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine); +	} +	if (line < 0) +		return INVALID_POSITION; +	if (line >= pdoc->LinesTotal()) +		return INVALID_POSITION; +	Surface surface; +	surface.Init(); +	surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); +	unsigned int posLineStart = pdoc->LineStart(line); + +	LineLayout ll; +	LayoutLine(line, &surface, vs, ll); +	for (int i = 0; i < ll.numCharsInLine; i++) { +		if (pt.x < ((ll.positions[i] + ll.positions[i + 1]) / 2) || +		        ll.chars[i] == '\r' || ll.chars[i] == '\n') { +			return i + posLineStart; +		} +	} + +	return INVALID_POSITION; +} +  int Editor::PositionFromLineX(int line, int x) {  	RefreshStyleData();  	if (line >= pdoc->LinesTotal()) @@ -400,7 +437,6 @@ int Editor::SelectionStart(int line) {  			return -1;  		} else {  			int minX = Platform::Minimum(xStartSelect, xEndSelect); -			//return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);  			return PositionFromLineX(line, minX);  		}  	} @@ -657,7 +693,7 @@ void Editor::ShowCaretAtCurrentPosition() {  	if (!hasFocus) {  		caret.active = false;  		caret.on = false; -		return ; +		return;  	}  	caret.active = true;  	caret.on = true; @@ -684,13 +720,13 @@ int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) {  void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {  	if (vs.fixedColumnWidth == 0) -		return ; +		return;  	PRectangle rcMargin = GetClientRectangle();  	rcMargin.right = vs.fixedColumnWidth;  	if (!rc.Intersects(rcMargin)) -		return ; +		return;  	Surface *surface;  	if (bufferedDraw) { @@ -1273,7 +1309,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {  		// Either styling or NotifyUpdateUI noticed that painting is needed  		// outside the current painting rectangle  		//Platform::DebugPrintf("Abandoning paint\n"); -		return ; +		return;  	}  	//Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); @@ -1627,8 +1663,6 @@ void Editor::SetScrollBarsTo(PRectangle) {  	//Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);  } - -  void Editor::SetScrollBars() {  	PRectangle rsClient = GetClientRectangle();  	SetScrollBarsTo(rsClient); @@ -1748,7 +1782,7 @@ void Editor::Cut() {  void Editor::PasteRectangular(int pos, const char *ptr, int len) {  	if (pdoc->IsReadOnly()) { -		return ; +		return;  	}  	currentPos = pos;  	int insertPos = currentPos; @@ -1950,7 +1984,7 @@ void Editor::NotifyNeedShown(int pos, int len) {  void Editor::NotifyDwelling(Point pt, bool state) {  	SCNotification scn;  	scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND; -	scn.position = PositionFromLocation(pt); +	scn.position = PositionFromLocationClose(pt);  	scn.x = pt.x;  	scn.y = pt.y;  	NotifyParent(scn); @@ -2181,10 +2215,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long  	case SCI_NEWLINE:  	default:  		//		printf("Filtered out %ld of macro recording\n", iMessage); - - - -		return ; +		return;  	}  	// Send notification @@ -2530,6 +2561,7 @@ int Editor::KeyDefault(int, int) {  }  int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) { +	DwellEnd();  	int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |  	                (alt ? SCI_ALT : 0);  	int msg = kmap.Find(key, modifiers); @@ -2975,6 +3007,14 @@ void Editor::LineSelection(int lineCurrent_, int lineAnchor_) {  	}  } +void Editor::DwellEnd() { +	ticksToDwell = dwellDelay; +	if (dwelling && (dwellDelay < SC_TIME_FOREVER)) { +		dwelling = false; +		NotifyDwelling(ptMouseLast, dwelling); +	} +} +  void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {  	//Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);  	ptMouseLast = pt; @@ -2984,7 +3024,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b  	bool processed = NotifyMarginClick(pt, shift, ctrl, alt);  	if (processed) -		return ; +		return;  	bool inSelMargin = PointInSelMargin(pt);  	if (shift & !inSelMargin) { @@ -3033,7 +3073,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b  			if (ctrl) {  				SelectAll();  				lastClickTime = curTime; -				return ; +				return;  			}  			if (!shift) {  				lineAnchor = LineFromLocation(pt); @@ -3084,11 +3124,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b  void Editor::ButtonMove(Point pt) {  	if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) { -		ticksToDwell = dwellDelay; -		if (dwelling && (dwellDelay < SC_TIME_FOREVER)) { -			dwelling = false; -			NotifyDwelling(ptMouseLast, dwelling); -		} +		DwellEnd();  	}  	ptMouseLast = pt;  	//Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); @@ -3097,7 +3133,7 @@ void Editor::ButtonMove(Point pt) {  		// Slow down autoscrolling/selection  		autoScrollTimer.ticksToWait -= timer.tickSize;  		if (autoScrollTimer.ticksToWait > 0) -			return ; +			return;  		autoScrollTimer.ticksToWait = autoScrollDelay;  		// Adjust selection @@ -3142,11 +3178,8 @@ void Editor::ButtonMove(Point pt) {  		if (vs.fixedColumnWidth > 0) {	// There is a margin  			if (PointInSelMargin(pt)) {  				DisplayCursor(Window::cursorReverseArrow); -				return ; 	// No need to test for selection +				return; 	// No need to test for selection  			} - - -  		}  		// Display regular (drag) cursor over selection  		if (PointInSelection(pt)) @@ -3224,7 +3257,9 @@ void Editor::Tick() {  			InvalidateCaret();  		}  	} -	if ((dwellDelay < SC_TIME_FOREVER) && (ticksToDwell > 0)) { +	if ((dwellDelay < SC_TIME_FOREVER) &&  +		(ticksToDwell > 0) && +		(!HaveMouseCapture())) {  		ticksToDwell -= timer.tickSize;  		if (ticksToDwell <= 0) {  			dwelling = true; @@ -3260,7 +3295,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) {  	if (paintState == painting && !paintingAllText) {  		//Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);  		if (!r.Valid()) -			return ; +			return;  		PRectangle rcText = GetTextRectangle();  		// Determine number of lines displayed including a possible partially displayed last line @@ -3272,7 +3307,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) {  		if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {  			//Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",  			//		lineRangeStart, lineRangeEnd, topLine, bottomLine); -			return ; +			return;  		}  		// Assert rcPaint contained within or equal to rcText @@ -3284,7 +3319,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) {  				//Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",  				//	lineRangeStart, lineRangeEnd, topLine, paintTopLine);  				paintState = paintAbandoned; -				return ; +				return;  			}  		}  		if (rcPaint.bottom < rcText.bottom) { @@ -3295,7 +3330,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) {  				//Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",  				//	lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);  				paintState = paintAbandoned; -				return ; +				return;  			}  		}  	} @@ -4155,6 +4190,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_POSITIONFROMPOINT:  		return PositionFromLocation(Point(wParam, lParam)); +	case SCI_POSITIONFROMPOINTCLOSE: +		return PositionFromLocationClose(Point(wParam, lParam)); +  	case SCI_GOTOLINE:  		GoToLine(wParam);  		break; diff --git a/src/Editor.h b/src/Editor.h index 5fdbbfae7..7b2c0e0a9 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -182,9 +182,10 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	int LinesOnScreen();  	int LinesToScroll();  	int MaxScrollPos(); -	Point LocationFromPosition(unsigned int pos); -	int XFromPosition(unsigned int pos); +	Point LocationFromPosition(int pos); +	int XFromPosition(int pos);  	int PositionFromLocation(Point pt); +	int PositionFromLocationClose(Point pt);  	int PositionFromLineX(int line, int x);  	int LineFromLocation(Point pt);  	void SetTopLine(int topLineNew); @@ -308,6 +309,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	bool PointInSelection(Point pt);  	bool PointInSelMargin(Point pt);  	void LineSelection(int lineCurrent_, int lineAnchor_); +	void DwellEnd();  	virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);  	void ButtonMove(Point pt);  	void ButtonUp(Point pt, unsigned int curTime, bool ctrl); | 
