[FIX] Indented text and selection

Hans-Martin Mosner hm.mosner at cityweb.de
Wed Jan 5 19:04:22 UTC 2000


This changeset fixes a bug with selection to the left of indented text
(the virtual tabs used for indenting would cause a crossedX condition,
which leads to wrong cursor positioning)

Hans-Martin
-------------- next part --------------
'From Squeak2.7alpha of 11 October 1999 [latest update: #1716] on 5 January 2000 at 5:40:55 pm'!
"Change Set:		Indentation-hmm
Date:			5 January 2000
Author:			Hans-Martin Mosner

Fixes a bug with selecting to the left of text with a TextIndent attribute"!


!CharacterBlockScanner methodsFor: 'scanning' stamp: 'hmm 1/5/2000 07:13'!
characterBlockAtPoint: aPoint index: index in: textLine
	| runLength lineStop done stopCondition |
	line _ textLine.
	characterIndex _ index.  " == nil means scanning for point"
	characterPoint _ aPoint.
	(characterPoint == nil or: [characterPoint y > line bottom])
		ifTrue: [characterPoint _ line bottomRight].
	(text isEmpty or: [(characterPoint y < line top or: [characterPoint x < line left])
				or: [characterIndex ~~ nil and: [characterIndex < line first]]])
		ifTrue:	[^ (CharacterBlock new stringIndex: line first text: text
					topLeft: line leftMargin at line top extent: 0 @ textStyle lineGrid)
					textLine: line].
	rightMargin _ line rightMargin.
	destX _ leftMargin _ line leftMarginForAlignment: textStyle alignment.
	destY _ line top.
	lastIndex _ line first.
	self setStopConditions.		"also sets font"
	self adjustForIndentationLevel.
	runLength _ text runLengthFor: line first.
	characterIndex ~~ nil
		ifTrue:	[lineStop _ characterIndex  "scanning for index"]
		ifFalse:	[lineStop _ line last  "scanning for point"].
	runStopIndex _ lastIndex + (runLength - 1) min: lineStop.
	lastCharacterExtent _ 0 @ line lineHeight.
	spaceCount _ 0.

	done  _ false.
	[done] whileFalse:
		[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
			in: text string rightX: characterPoint x
			stopConditions: stopConditions kern: kern displaying: false.
		"see setStopConditions for stopping conditions for character block 	operations."
		self lastCharacterExtentSetX: (specialWidth == nil
			ifTrue: [font widthOf: (text at: lastIndex)]
			ifFalse: [specialWidth]).
		(self perform: stopCondition) ifTrue:
			[^ (CharacterBlock new
				stringIndex: (characterIndex==nil ifTrue: [lastIndex] ifFalse: [characterIndex])
				text: text topLeft: characterPoint extent: lastCharacterExtent)
				textLine: line]]! !

!CharacterBlockScanner methodsFor: 'private' stamp: 'hmm 1/5/2000 07:05'!
adjustForIndentationLevel
	"Advance destX to the indented position without executing the tab action. IndentationLevel is cleared to suppress its effect later.
	This is needed to fix a bug when a selection is made to the left of indented text. - hmm"
	self indentationLevel timesRepeat: [
		destX _ textStyle
			nextTabXFrom: destX
			leftMargin: leftMargin
			rightMargin: rightMargin].
	indentationLevel _ 0! !

!CharacterBlockScanner methodsFor: 'private' stamp: 'hmm 1/2/2000 20:56'!
buildCharacterBlockIn: para
	| lineIndex runLength lineStop done stopCondition |
	"handle nullText"
	(para numberOfLines = 0 or: [text size = 0])
		ifTrue:	[^ CharacterBlock new stringIndex: 1  "like being off end of string"
					text: para text
					topLeft: (para leftMarginForDisplayForLine: 1)
								@ para compositionRectangle top
					extent: 0 @ textStyle lineGrid].
	"find the line"
	lineIndex _ para lineIndexOfTop: characterPoint y.
	destY _ para topAtLineIndex: lineIndex.
	line _ para lines at: lineIndex.
	rightMargin _ para rightMarginForDisplay.

	(lineIndex = para numberOfLines and:
		[(destY + line lineHeight) < characterPoint y])
			ifTrue:	["if beyond lastLine, force search to last character"
					self characterPointSetX: rightMargin]
			ifFalse:	[characterPoint y < (para compositionRectangle) top
						ifTrue: ["force search to first line"
								characterPoint _ (para compositionRectangle) topLeft].
					characterPoint x > rightMargin
						ifTrue:	[self characterPointSetX: rightMargin]].
	destX _ leftMargin _ para leftMarginForDisplayForLine: lineIndex.
	nextLeftMargin_ para leftMarginForDisplayForLine: lineIndex+1.
	lastIndex _ line first.

	self setStopConditions.		"also sets font"
	self adjustForIndentationLevel.
	runLength _ (text runLengthFor: line first).
	characterIndex ~~ nil
		ifTrue:	[lineStop _ characterIndex	"scanning for index"]
		ifFalse:	[lineStop _ line last].
	(runStopIndex _ lastIndex + (runLength - 1)) > lineStop
		ifTrue:	[runStopIndex _ lineStop].
	lastCharacterExtent _ 0 @ line lineHeight.
	spaceCount _ 0. done  _ false.

	[done]
	whileFalse:
	[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
			in: text string rightX: characterPoint x
			stopConditions: stopConditions kern: kern displaying: false.

	"see setStopConditions for stopping conditions for character block 	operations."
	self lastCharacterExtentSetX: (font widthOf: (text at: lastIndex)).
	(self perform: stopCondition)
		ifTrue:	[^ CharacterBlock new stringIndex: lastIndex text: text
					topLeft: characterPoint extent: lastCharacterExtent]]! !




More information about the Squeak-dev mailing list