[squeak-dev] [5.2a] styled text in a class comment spawns endless subscript out-of-bounds

David T. Lewis lewis at mail.msen.com
Thu Jul 5 00:00:49 UTC 2018


Indeed, a text with runs that refer to positions beyond the end of
the string does not seem right. Possibly a bug in text editing that
permits this condition to occur?

Meanwhile, I was looking at your tip about the runStopIndex being 71
for the funky styled text and 70 otherwise. Attached is an update to
CharacterBlockScanner>>characterBlockAtPoint:index:in: that prevents
the out of range condition and fixes the FooClient class comment display.

This might be just a band-aid over a problem elsewhere, but it does
seem to work.

Dave


On Wed, Jul 04, 2018 at 06:55:20PM -0400, Bob Arning wrote:
> A little more...
> 
> This problem may ultimately be due to something broken in the text being 
> displayed. If I look at the funky class comment, it has these runs
> 
> a RunArray runs: #(1 35 18 20 3) values: {#() . {a TextFontChange font: 
> 1} . #() . {a TextEmphasis code: 1} . #()}
> 
> The total length of the run sizes is 77, yet the string is only 70 bytes 
> long.
> 
> If I copy that text out and paste into a workspace, the runs now look like:
> 
> a RunArray runs: #(1 35 18 16) values: {#() . {a TextFontChange font: 1} 
> . #() . {a TextEmphasis code: 1}}
> 
> and the size of the runs matches the size of the string at 70. I wonder 
> if other occurrences of this problem might have a similar cause.
> 
> 
> On 7/4/18 4:20 PM, David T. Lewis wrote:
> >On Wed, Jul 04, 2018 at 03:46:16PM -0400, Bob Arning wrote:
> >>Here is a side-by-side comparison with the styled version on the right
> >>and the same text unstyled on the left. Note the difference in 
> >>runStopIndex
> >>
> >I see it now. Thanks!
> >
> >Dave
> >
> >
> >>On 7/4/18 2:49 PM, David T. Lewis wrote:
> >>>I tried reverting #scanCharactersFrom:to:in:rightX:stopConditions:kern:
> >>>to the earlier version (cmm 6/12/2010 11:52), but I still get failures
> >>>with cursor and mouse in the class comment text when browsing the 
> >>>FooClient
> >>>class. There must be something else going on here, and it is certainly
> >>>not obvious to me why it is happening only with the FooClient test
> >>>example.
> >>>
> >>>Dave
> >>>
> >>>On Wed, Jul 04, 2018 at 02:10:00PM -0400, Bob Arning wrote:
> >>>>perhaps this will help:
> >>>>
> >>>>This version does not seem to exhibit the error and it limits stopIndex
> >>>>to the size of the string
> >>>>
> >>>>!CharacterScanner methodsFor: 'scanning' stamp: 'cmm 6/12/2010 11:52'!
> >>>>scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX:
> >>>>rightX stopConditions: stops kern: kernDelta
> >>>>
> >>>>?????? | startEncoding selector |
> >>>>?????? (sourceString isByteString) ifTrue: [^ self
> >>>>basicScanCharactersFrom: startIndex *to: (stopIndex min: sourceString
> >>>>size)* in: sourceString rightX: rightX stopConditions: stops kern:
> >>>>kernDelta.].
> >>>>
> >>>>?????? (sourceString isWideString) ifTrue: [
> >>>>?????? ?????? startIndex > stopIndex ifTrue: [lastIndex := stopIndex. ^
> >>>>stops endOfRun].
> >>>>?????? ?????? startEncoding :=?? (sourceString at: startIndex)
> >>>>leadingChar.
> >>>>?????? ?????? selector := EncodedCharSet scanSelectorAt: startEncoding.
> >>>>?????? ?????? ^ self perform: selector withArguments: (Array with:
> >>>>startIndex with: stopIndex with: sourceString with: rightX with: stops
> >>>>with: kernDelta).
> >>>>?????? ].
> >>>>
> >>>>?????? ^ stops endOfRun
> >>>>! !
> >>>>
> >>>>This version fails and does not limit the stopIndex.
> >>>>
> >>>>!CharacterScanner methodsFor: 'scanning' stamp: 'nice 10/22/2013 20:49'!
> >>>>scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX:
> >>>>rightX
> >>>>?????? ^sourceString scanCharactersFrom: startIndex *to: stopIndex* 
> >>>>with:
> >>>>self rightX: rightX font: font! !
> >>>>
> >>>>
> >>>>On 7/4/18 11:53 AM, David T. Lewis wrote:
> >>>>>On Wed, Jul 04, 2018 at 02:35:59PM +0200, karl ramberg wrote:
> >>>>>>On Wed, Jul 4, 2018 at 11:10 AM K K Subbu <kksubbu.ml at gmail.com> 
> >>>>>>wrote:
> >>>>>>
> >>>>>>>On Tuesday 03 July 2018 04:40 AM, Tim Johnson wrote:
> >>>>>>>>1. File-in the .cs as attached*.
> >>>>>>>>2. In a system browser, click on the class, then click on the [?]
> >>>>>>>>button
> >>>>>>>>to view class comment.
> >>>>>>>>3. Notice the styled text in the comment.
> >>>>>>>>4. Click around the comment pane a bit.
> >>>>>>>>5. Eventually, see "Error: subscript is out of bounds: 71" appear 
> >>>>>>>>over
> >>>>>>>>and over until you interrupt.
> >>>>>>>In step 4, it is sufficient to click once near the bottom of the pane
> >>>>>>>when the cursor changes from I-bar to arrow and then wait. This will
> >>>>>>>trigger the error, but the error window triggers itself recursively
> >>>>>>>around 50 times before stopping and displaying the windows.
> >>>>>>>
> >>>>>>>I added an assert to catch it before recursion:
> >>>>>>>
> >>>>>>>     self assert: lastIndex < sourceString size.
> >>>>>>>
> >>>>>>>The assert window itself throws up another error, but that is a topic
> >>>>>>>for another thread ;-).
> >>>>>>>
> >>>>>>>Regards .. Subbu
> >>>>>>Hi,
> >>>>>>See class comment i NewParagraph for a hint of what happens.
> >>>>>>A empty lineSpan 71 to: 70 is added to the end of the paragraph, when
> >>>>>>you
> >>>>>>double click below the text.
> >>>>>>When the character scanner looks for characters outside of the string 
> >>>>>>at
> >>>>>>index 71 it cause a recursion.
> >>>>>>
> >>>>>>Best,
> >>>>>>Karl
> >>>>>>
> >>>>>Good tiip to look at the NewParagraph class comment, there is 
> >>>>>apparently
> >>>>>some left over messiness in here somewhere.
> >>>>>
> >>>>>Another way to trigger the bug using the test case with FooClient is
> >>>>>to position the cursor in the comment pane and use keyboard right 
> >>>>>cursor
> >>>>>to move to the end of the comment. This causes the same bounds error 
> >>>>>but
> >>>>>takes a different path through the code leading to the error.
> >>>>>
> >>>>>Looking through the stack in a debugger after triggering the error with
> >>>>>the mouse, here are a few notes (but no conclusions):
> >>>>>
> >>>>>On mouseUp: we enter Editor>>selectWord then call
> >>>>>Editor>>selectWordLeftDelimiters:rightDelimiters:
> >>>>>which has this:
> >>>>>
> >>>>>	"Select the whole text when clicking before first or after last
> >>>>>	character"
> >>>>>	(here > string size or: [here < 2]) ifTrue: [^self selectFrom: 1 to:
> >>>>>	string size].
> >>>>>
> >>>>>where string is the 70 character String derived from the Text.
> >>>>>
> >>>>>At this point we are trying to select from 1 to 70 (the whole string 
> >>>>>for
> >>>>>the entire text) in TextEditor>>selectFrom:to:
> >>>>>
> >>>>>This calls Editor>>selectInvisiblyFrom:to: and here the stop index is
> >>>>>set past the size of the string:
> >>>>>
> >>>>>   selectInvisiblyFrom: start to: stop
> >>>>>      "Select the designated characters, inclusive.  Make no visual
> >>>>>      changes."
> >>>>>
> >>>>>      self markIndex: start pointIndex: stop + 1
> >>>>>
> >>>>> From this point we are trying to go from index 1 to index 71 over a
> >>>>>string
> >>>>>of size 70, and eventually end up with the out of bounds exception.
> >>>>>
> >>>>>A clue that this might be accumulation of kludges: Looking at senders 
> >>>>>of
> >>>>>selectInvisiblyFrom:to: (such as TextEditor>>addText:event:) shows a
> >>>>>number
> >>>>>of methods that subtract 1 from the stop index when before calling the
> >>>>>method
> >>>>>that adds 1 back to the stop index. This certainly does not have a good
> >>>>>smell.
> >>>>>
> >>>>>It is not clear to me why selectInvisiblyFrom:to: would be adding one 
> >>>>>to
> >>>>>the
> >>>>>stop index, but I see that the method stamp is jmv 5/27/2011, which
> >>>>>suggests
> >>>>>to me that we should take a look at Cuis to figure out how this is
> >>>>>intended
> >>>>>to function. Cuis does not show any cases of senders of
> >>>>>selectInvisiblyFrom:to:
> >>>>>that subtract 1 from the stop index, and the Cuis implementation of
> >>>>>selectInvisiblyFrom:to: is that same as Squeak.
> >>>>>
> >>>>>Dave
> >>>>>
> >>>>>
> >
> 

> 

-------------- next part --------------
'From Squeak5.2alpha of 3 July 2018 [latest update: #18137] on 4 July 2018 at 7:17:12 pm'!

!CharacterBlockScanner methodsFor: 'scanning' stamp: 'dtl 7/4/2018 19:10'!
characterBlockAtPoint: aPoint index: index in: textLine
	"This method is the Morphic characterBlock finder.  It combines
	MVC's characterBlockAtPoint:, -ForIndex:, and buildCharacterBlockIn:"
	| runLength lineStop stopCondition |
	line := textLine.
	rightMargin := line rightMargin.
	lastIndex := line first.
	self setStopConditions.		"also sets font"
	characterIndex := index.  " == nil means scanning for point"
	characterPoint := aPoint.
	(characterPoint isNil or: [characterPoint y > line bottom])
		ifTrue: [characterPoint := line bottomRight].
	destX := leftMargin := line leftMarginForAlignment: alignment.
	destY := line top.
	(text isEmpty or: [(characterPoint y < destY or: [characterPoint x < destX])
				or: [characterIndex notNil and: [characterIndex < line first]]])
		ifTrue:	[^ (CharacterBlock new stringIndex: line first text: text
					topLeft: destX at destY extent: 0 @ textStyle lineGrid)
					textLine: line].
	runLength := text runLengthFor: line first.
	lineStop := (characterIndex		"scanning for index"
					ifNil: [ line last ])	"scanning for point"
						min: text size.	"stay within bounds of text"
	runStopIndex := lastIndex + (runLength - 1) min: lineStop.
	lastCharacterWidth := 0.
	spaceCount := 0.

	[
		stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex
			in: text string rightX: characterPoint x.
		"see setStopConditions for stopping conditions for character block operations."
		self perform: stopCondition
	] whileFalse.
	characterIndex
		ifNil: ["Result for characterBlockAtPoint: "
				^ (CharacterBlock new
					stringIndex: lastIndex
					text: text topLeft: characterPoint + (font descentKern @ 0)
					extent: lastCharacterWidth @ line lineHeight - (font baseKern @ 0))
							textLine: line]
		ifNotNil: ["Result for characterBlockForIndex: "
				^ (CharacterBlock new
					stringIndex: characterIndex
					text: text topLeft: characterPoint + ((font descentKern) - kern @ 0)
					extent: lastCharacterWidth @ line lineHeight)
							textLine: line]! !


More information about the Squeak-dev mailing list