'From Squeak6.0alpha of 20 August 2020 [latest update: #19812] on 20 August 2020 at 3:03:26 pm'!

!Object methodsFor: 'copying' stamp: 'ct 8/20/2020 15:00'!
copySameFrom: otherObject
	"Copy to myself all instance variables named the same in otherObject.
	This ignores otherObject's control over its own inst vars."

	| myInstVars otherInstVars |
	myInstVars := self class allInstVarNames.
	otherInstVars := otherObject class allInstVarNames.
	myInstVars withIndexDo: [:each :index |
		| match |
		(match := otherInstVars indexOf: each) > 0 ifTrue:
			[self instVarAt: index put: (otherObject instVarAt: match)]].
	1 to: (self basicSize min: otherObject basicSize) do: [:i |
		self basicAt: i put: (otherObject basicAt: i)].
! !

!Object methodsFor: 'printing' stamp: 'ct 8/20/2020 15:00'!
longPrintOn: aStream
	"Append to the argument, aStream, the names and values of all 
	of the receiver's instance variables."

	self class allInstVarNames withIndexDo:
		[:title :index |
		aStream nextPutAll: title;
		 nextPut: $:;
		 space;
		 tab;
		 print: (self instVarAt: index);
		 cr]! !

!Object methodsFor: 'printing' stamp: 'ct 8/20/2020 15:00'!
longPrintOn: aStream limitedTo: sizeLimit indent: indent
	"Append to the argument, aStream, the names and values of all of the receiver's instance variables.  Limit is the length limit for each inst var."

	self class allInstVarNames withIndexDo:
		[:title :index |
		indent timesRepeat: [aStream tab].
		aStream nextPutAll: title;
		 nextPut: $:;
		 space;
		 tab;
		 nextPutAll: 
			((self instVarAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1));
		 cr]! !


!BookMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 14:59'!
getAllText
	"Collect the text for each page.  Just point at strings so don't have to recopy them.  Parallel array of urls for ID of pages.
	allText = Array (pages size) of arrays (fields in it) of strings of text.
	allTextUrls = Array (pages size) of urls or page numbers.
	For any page that is out, text data came from .bo file on server.  
	Is rewritten when one or all pages are stored."

	| oldUrls oldStringLists allText allTextUrls |
	oldUrls := self valueOfProperty: #allTextUrls ifAbsent: [#()].
	oldStringLists := self valueOfProperty: #allText ifAbsent: [#()].
	allText := pages collect: [:pg | OrderedCollection new].
	allTextUrls := Array new: pages size.
	pages withIndexDo: [:aPage :ind | | which aUrl |
		aUrl := aPage url.  aPage isInMemory 
			ifTrue: [(allText at: ind) addAll: (aPage allStringsAfter: nil).
				aUrl ifNil: [aUrl := ind].
				allTextUrls at: ind put: aUrl]
			ifFalse: ["Order of pages on server may be different.  (later keep up to date?)"
				which := oldUrls indexOf: aUrl.
				allTextUrls at: ind put: aUrl.
				which = 0 ifFalse: [allText at: ind put: (oldStringLists at: which)]]].
	self setProperty: #allText toValue: allText.
	self setProperty: #allTextUrls toValue: allTextUrls.
	^ allText! !

!BookMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 14:59'!
getStemUrl
	"Try to find the old place where this book was stored. Confirm with the 
	user. Else ask for new place."
	| initial pg url knownURL |

	knownURL := false.
	initial := ''.
	(pg := currentPage valueOfProperty: #SqueakPage)
		ifNotNil: [pg contentsMorph == currentPage
				ifTrue: [initial := pg url.
					knownURL := true]].
	"If this page has a url"
	pages
		withIndexDo: [:aPage :ind | initial isEmpty
				ifTrue: [aPage isInMemory
						ifTrue: [(pg := aPage valueOfProperty: #SqueakPage)
								ifNotNil: [initial := pg url]]]].
	"any page with a url"
	initial isEmpty
		ifTrue: [initial := ServerDirectory defaultStemUrl , '1.sp'].
	"A new legal place"
	url := knownURL
		ifTrue: [initial]
		ifFalse: [UIManager default request: 'url of the place to store a typical page in this book.
Must begin with file:// or ftp://' translated initialAnswer: initial].
	^ SqueakPage stemUrl: url! !

!BookMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 14:59'!
reserveUrls
	"Save a dummy version of the book first, assign all pages URLs, write dummy files to reserve the url, and write the index.  Good when I have pages with interpointing bookmarks."

	| stem |
	(stem := self getStemUrl) isEmpty ifTrue: [^self].
	pages withIndexDo: 
			[:pg :ind | 
			"does write the current page too"

			pg url ifNil: [pg reserveUrl: stem , ind printString , '.sp']]

	"self saveIndexOnURL."! !

!BookMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 14:59'!
saveAsNumberedURLs
	"Write out all pages in this book that are not showing, onto a server.  The local disk could be the server.  For any page that does not have a SqueakPage and a url already, name that page file by its page number.  Any pages that are already totally out will stay that way."

	| stem list firstTime |
	firstTime := (self valueOfProperty: #url) isNil.
	stem := self getStemUrl.	"user must approve"
	stem isEmpty ifTrue: [^self].
	firstTime ifTrue: [self setProperty: #futureUrl toValue: stem , '.bo'].
	self reserveUrlsIfNeeded.
	pages withIndexDo: 
			[:aPage :ind | 
			"does write the current page too"

			aPage isInMemory 
				ifTrue: 
					["not out now"

					aPage presenter ifNotNil: [aPage presenter flushPlayerListCache].
					aPage saveOnURL: stem , ind printString , '.sp']].
	list := pages collect: [:aPage | aPage sqkPage prePurge].
	"knows not to purge the current page"
	list := (list select: [:each | each notNil]) asArray.
	"do bulk become:"
	(list collect: [:each | each contentsMorph]) 
		elementsExchangeIdentityWith: (list 
				collect: [:spg | MorphObjectOut new xxxSetUrl: spg url page: spg]).
	self saveIndexOnURL.
	self presenter ifNotNil: [self presenter flushPlayerListCache].
	firstTime 
		ifTrue: 
			["Put a thumbnail into the hand"

			URLMorph grabForBook: self.
			self setProperty: #futureUrl toValue: nil	"clean up"]! !

!BookMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 14:59'!
saveIndexOnURL
	"Make up an index to the pages of this book, with thumbnails, and store it on the server.  (aDictionary, aMorphObjectOut, aMorphObjectOut, aMorphObjectOut).  The last part corresponds exactly to what pages looks like when they are all out.  Each holds onto a SqueakPage, which holds a url and a thumbnail."

	| dict mine sf urlList list |
	pages isEmpty ifTrue: [^self].
	dict := Dictionary new.
	dict at: #modTime put: Time totalSeconds.
	"self getAllText MUST have been called at start of this operation."
	dict at: #allText put: (self valueOfProperty: #allText).
	#(#color #borderWidth #borderColor #pageSize) 
		do: [:sel | dict at: sel put: (self perform: sel)].
	self reserveUrlsIfNeeded.	"should already be done"
	list := pages copy.	"paste dict on front below"
	"Fix up the entries, should already be done"
	list withIndexDo: 
			[:out :ind | 
			out isInMemory 
				ifTrue: 
					[(out valueOfProperty: #SqueakPage) ifNil: [out saveOnURLbasic].
					list at: ind put: out sqkPage copyForSaving]].
	urlList := list collect: [:ppg | ppg url].
	self setProperty: #allTextUrls toValue: urlList.
	dict at: #allTextUrls put: urlList.
	list := (Array with: dict) , list.
	mine := self valueOfProperty: #url.
	mine ifNil: 
			[mine := self getStemUrl , '.bo'.
			self setProperty: #url toValue: mine].
	sf := ServerDirectory new fullPath: mine.
	Cursor wait showWhile: 
			[ | remoteFile |
			remoteFile := sf fileNamed: mine.
			remoteFile dataIsValid.
			remoteFile fileOutClass: nil andObject: list
			"remoteFile close"]! !

!BookMorph methodsFor: 'sorting' stamp: 'ct 8/20/2020 14:59'!
acceptSortedContentsFrom: aHolder 
	"Update my page list from the given page sorter."

	| goodPages rejects |
	goodPages := OrderedCollection new.
	rejects := OrderedCollection new.
	aHolder submorphs withIndexDo: 
			[:m :i | | toAdd sqPage | 
			toAdd := nil.
			(m isKindOf: PasteUpMorph) ifTrue: [toAdd := m].
			(m isKindOf: BookPageThumbnailMorph) 
				ifTrue: 
					[toAdd := m page.
					m bookMorph == self 
						ifFalse: 
							["borrowed from another book. preserve the original"

							toAdd := toAdd veryDeepCopy.

							"since we came from elsewhere, cached strings are wrong"
							self removeProperty: #allTextUrls.
							self removeProperty: #allText]].
			toAdd isString 
				ifTrue: 
					["a url"

					toAdd := pages detect: [:aPage | aPage url = toAdd] ifNone: [toAdd]].
			toAdd isString 
				ifTrue: 
					[sqPage := SqueakPageCache atURL: toAdd.
					toAdd := sqPage contentsMorph 
								ifNil: [sqPage copyForSaving	"a MorphObjectOut"]
								ifNotNil: [sqPage contentsMorph]].
			toAdd ifNil: [rejects add: m] ifNotNil: [goodPages add: toAdd]].
	self newPages: goodPages.
	goodPages isEmpty ifTrue: [self insertPage].
	rejects notEmpty 
		ifTrue: 
			[self 
				inform: rejects size printString , ' objects vanished in this process.']! !

!BookMorph methodsFor: '*Etoys-Squeakland-master pages' stamp: 'ct 8/20/2020 14:59'!
saveBookForRevert
	"Consider this the master version of the book, with regard to which pages are in it, what their order is, and what their content is"

	| forRevert |
	forRevert := OrderedCollection new.
	pages withIndexDo: 
		[: pg :index | 
			pg setProperty: #revertKey toValue: index.
			forRevert add: (index -> pg copy)].
	self setProperty:# pagesForRevert toValue: forRevert! !


!Chess960Morph methodsFor: 'resizing' stamp: 'ct 8/20/2020 14:59'!
reinstallPieces

	board whitePlayer pieces withIndexDo: [:pc :n |
		pc isZero ifFalse: [
			self addedPiece: pc at: n white: true]].

	board blackPlayer pieces withIndexDo: [:pc :n |
		pc isZero ifFalse: [
			self addedPiece: pc at: n white: false]].! !


!Chess960Player methodsFor: 'adding/removing' stamp: 'ct 8/20/2020 14:59'!
addBlackPieces: aChess960Configuration

	self configuration: aChess960Configuration.

	configuration positions withIndexDo: [:p :n | self addPiece: p at: 56+n].
	49 to: 56 do:[:i| self addPiece: Pawn at: i].! !

!Chess960Player methodsFor: 'adding/removing' stamp: 'ct 8/20/2020 15:00'!
addWhitePieces: aChess960Configuration

	self configuration: aChess960Configuration.

	configuration positions withIndexDo: [:p :n | self addPiece: p at: n].
	9 to: 16 do:[:i| self addPiece: Pawn at: i].
! !


!ChineseCheckers methodsFor: 'drawing' stamp: 'ct 8/20/2020 15:00'!
drawOn: aCanvas 

	| row1 row2 offset dotExtent |
	super drawOn: aCanvas.   "Draw square board"

	"Only draw rows in the clipping region"
	dotExtent := (self width//25) asPoint.
	offset := self pieceSize - dotExtent + 1 // 2.  "Offset of smaller dots rel to larger"
	row1 := (self boardLocAt: aCanvas clipRect topLeft) x max: 1.
	row2 := (self boardLocAt: aCanvas clipRect bottomRight) x min: board size.
	row1 to: row2 do:
		[:row | (board at: row) withIndexDo:
			[:cell :i | cell ifNotNil:
				[aCanvas fillOval: ((self cellPointAt: (row@i)) + offset extent: dotExtent)
					color: (colors at: cell+1)]]]! !


!CipherPanel methodsFor: 'initialization' stamp: 'ct 8/20/2020 14:59'!
encodedQuote: aString 
	"World addMorph: CipherPanel new"
	| morph prev |
	aString isEmpty
		ifTrue: [^ self].
	(letterMorphs isNil
			or: [self isClean])
		ifFalse: [(self confirm: 'Are you sure you want to discard all typing?' translated)
				ifFalse: [^ self]].
	haveTypedHere := false.
	quote := aString asUppercase.
	prev := nil.
	originalMorphs := quote asArray
				withIndexCollect: [:c :i | WordGameLetterMorph new plain indexInQuote: i id1: nil;
						
						setLetter: (quote at: i)].
	letterMorphs := OrderedCollection new.
	decodingMorphs := quote asArray
				withIndexCollect: [:c :i | (quote at: i) isLetter
						ifTrue: [morph := WordGameLetterMorph new underlined indexInQuote: i id1: nil.
							morph
								on: #mouseDown
								send: #mouseDownEvent:letterMorph:
								to: self.
							morph
								on: #keyStroke
								send: #keyStrokeEvent:letterMorph:
								to: self.
							letterMorphs addLast: morph.
							morph predecessor: prev.
							prev
								ifNotNil: [prev successor: morph].
							prev := morph]
						ifFalse: [WordGameLetterMorph new plain indexInQuote: i id1: nil;
								
								setLetter: (quote at: i)]].
	self color: originalMorphs first color.
	self extent: 500 @ 500! !


!ClassDescription methodsFor: 'instance variables' stamp: 'ct 8/20/2020 15:00'!
forceNewFrom: anArray
    "Create a new instance of the class and fill
    its instance variables up with the array."
    | object max |

    object := self new.
    max := self instSize.
    anArray withIndexDo: [:each :index |
        index > max ifFalse:
            [object instVarAt: index put: each]].
    ^ object! !


!BalloonEngineConstants class methodsFor: 'pool definition' stamp: 'ct 8/20/2020 14:59'!
initializeInstVarNames: aClass prefixedBy: aString

	| token |
	aClass instVarNames withIndexDo:[:instVarName :index| | value |
		token := (aString, instVarName first asUppercase asString, (instVarName copyFrom: 2 to: instVarName size),'Index') asSymbol.
		value := index - 1.
		(self bindingOf: token) ifNil:[self addClassVarName: token].
		(self bindingOf: token) value: value.
	].
	token := (aString, aClass name,'Size') asSymbol.
	(self bindingOf: token) ifNil:[self addClassVarName: token].
	(self bindingOf: token) value: aClass instSize.! !


!CodeHolder methodsFor: 'message list' stamp: 'ct 8/20/2020 15:00'!
messageHelpTruncated: aText
	"Show only the first n lines of the text."
	| formatted lineCount |
	formatted := aText.
	lineCount := 0.
	aText withIndexDo: [:char :index |
		char = Character cr ifTrue: [lineCount := lineCount + 1].
		lineCount > 10 ifTrue: [
			formatted := formatted copyFrom: 1 to: index-1.
			formatted append: ' [...]'.
			^ formatted]].
	^ formatted! !


!ChangedMessageSet methodsFor: 'acceptance' stamp: 'ct 8/20/2020 14:59'!
contents: aString notifying: aController
	"Accept the string as new source for the current method, and make certain the annotation pane gets invalidated"

	| existingSelector existingClass superResult newSelector |
	existingSelector := self selectedMessageName.
	existingClass := self selectedClassOrMetaClass.

	superResult := super contents: aString notifying: aController.
	superResult ifTrue:  "succeeded"
		[newSelector := existingClass newParser parseSelector: aString.
		newSelector ~= existingSelector
			ifTrue:   "Selector changed -- maybe an addition"
				[self reformulateList.
				self changed: #messageList.
				self messageList withIndexDo:
					[:aMethodReference :anIndex |
						(aMethodReference actualClass == existingClass and:
									[aMethodReference methodSymbol == newSelector])
							ifTrue:
								[self messageListIndex: anIndex]]]].
	^ superResult! !


!Color class methodsFor: 'instance creation' stamp: 'ct 8/20/2020 15:00'!
colorFrom: parm
	"Return an instantiated color from parm.  If parm is already a color, return it, else return the result of my performing it if it's a symbol or, if it is a list, it can either be an array of three numbers, which will be interpreted as RGB values, or a list of symbols, the first of which is sent to me and then the others of which are in turn sent to the prior result, thus allowing entries of the form #(blue darker).  Else just return the thing"

	| aColor firstParm |
	(parm isKindOf: Color) ifTrue: [^ parm].
	(parm isSymbol) ifTrue: [^ self perform: parm].
	(parm isString) ifTrue: [^ self fromString: parm].
	((parm isKindOf: SequenceableCollection) and: [parm size > 0])
		ifTrue:
			[firstParm := parm first.
			(firstParm isKindOf: Number) ifTrue:
				[^ self fromRgbTriplet: parm].
			aColor := self colorFrom: firstParm.
			parm withIndexDo:
				[:sym :ind | ind > 1 ifTrue:
					[aColor := aColor perform: sym]].
			^ aColor].
	^ parm

"
Color colorFrom: #(blue darker)
Color colorFrom: Color blue darker
Color colorFrom: #blue
Color colorFrom: #(0.0 0.0 1.0)
"! !


!Context methodsFor: '*Tools-debugger access' stamp: 'ct 8/20/2020 15:00'!
tempsAndValuesLimitedTo: sizeLimit indent: indent
	"Return a string of the temporary variabls and their current values"

	| aStream |
	aStream := WriteStream on: (String new: 100).
	self tempNames
		withIndexDo: [:title :index |
			indent timesRepeat: [aStream tab].
			aStream nextPutAll: title; nextPut: $:; space; tab.
			aStream nextPutAll: 
				((self tempAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1)).
			aStream cr].
	^aStream contents! !


!ContextInspectorTest methodsFor: 'tests' stamp: 'ct 8/20/2020 15:00'!
testValuePaneModify
	"Try to change the values of all arguments and temporary variables. Check if the object-under-inspection receives those changes."

	| testObjectFound |
	testObjectFound := false.
	
	self object tempNames withIndexDo: [:temp :index |
		| prior current input |
		self inspector selectFieldSuchThat: [:field | field type = #tempVar and: [field key = temp]].
		self assertFieldSelected: '*', temp, '*'. "allow bells and whistles"
		
		prior := self object namedTempAt: index.
		self assert: (prior isNumber or: [prior == InnerTestObject]).

		testObjectFound := testObjectFound or: [prior == InnerTestObject].
		current := (prior isNumber ifTrue: [prior + 1] ifFalse: [#smith]).
		input := prior isNumber ifTrue: [self inspector contents, ' +1'] ifFalse: ['#smith'].
		
		self deny: current equals: (self object namedTempAt: index).
		self inValuePaneTypeAndAccept: input.
		self assert: current equals: (self object namedTempAt: index)].
	
	self assert: testObjectFound.! !


!DebuggerMethodMap methodsFor: 'accessing' stamp: 'ct 8/20/2020 15:00'!
tempsAndValuesForContext: aContext
	"Return a string of the temporary variabls and their current values"
	| aStream |
	aStream := WriteStream on: (String new: 100).
	(self tempNamesForContext: aContext) withIndexDo:
		[:title :index |
		 aStream nextPutAll: title; nextPut: $:; space; tab.
		 aContext print: (self namedTempAt: index in: aContext) on: aStream.
		 aStream cr].
	^aStream contents! !


!DictionaryTest methodsFor: 'tests - integrity' stamp: 'ct 8/20/2020 15:00'!
testIntegrityOfDictionaries
	#(
		Dictionary
		IdentityDictionary
		SystemDictionary
		LiteralDictionary
		PluggableDictionary
		WeakValueDictionary) do: [ :dictionaryClassName |
			Smalltalk at: dictionaryClassName ifPresent: [ :dictionaryClass |
				dictionaryClass allInstancesDo: [ :dictionary |
					dictionary keysAndValuesDo: [ :key :value |
						self assert: (dictionary at: key) == value ].
					dictionary array withIndexDo: [ :association :index |
		                        association ifNotNil: [
	 	                               self assert: (dictionary scanFor: association key) = index ] ] ] ] ]! !


!DocLibrary methodsFor: 'doc pane' stamp: 'ct 8/20/2020 15:00'!
saveDocCheck: aMorph
	"Make sure the document gets attached to the version of the code that the user was looking at.  Is there a version of this method in a changeSet beyond the updates we know about?  Works even when the user has internal update numbers and the documentation is for external updates (It always is)."

	| classAndMethod parts selector class lastUp beyond ours docFor unNum ok key verList ext response |
	classAndMethod := aMorph valueOfProperty: #classAndMethod.
	classAndMethod ifNil: [
		^ self error: 'need to know the class and method'].	"later let user set it"
	parts := classAndMethod findTokens: ' .'.
	selector := parts last asSymbol.
	class := Smalltalk at: (parts first asSymbol) ifAbsent: [^ self saveDoc: aMorph].
	parts size = 3 ifTrue: [class := class class].
	"Four indexes we are looking for:
		docFor = highest numbered below lastUpdate that has method.
		unNum = a higher unnumbered set that has method.
		lastUp = lastUpdate we know about in methodVersions
		beyond = any set about lastUp that has the method."
	ChangeSet allChangeSets withIndexDo: [:cs :ind | "youngest first"
		(cs name includesSubstring: lastUpdateName) ifTrue: [lastUp := ind].
		(cs atSelector: selector class: class) ~~ #none ifTrue: [
			lastUp ifNotNil: [beyond := ind. ours := cs name]
				ifNil: [cs name first isDigit ifTrue: [docFor := ind] 
						ifFalse: [unNum := ind. ours := cs name]]]].
	"See if version the user sees is the version he is documenting"
	ok := beyond == nil.
	unNum ifNotNil: [docFor ifNotNil: [ok := docFor > unNum]
						ifNil: [ok := false]].  "old changeSets gone"
	ok ifTrue: [^ self saveDoc: aMorph].

	key := DocLibrary properStemFor: classAndMethod.
	verList := (methodVersions at: key ifAbsent: [#()]), #(0 0).
	ext := verList first.	"external update number we will write to"
	response := (PopUpMenu labels: 'Cancel\Broadcast Page' withCRs)
				startUpWithCaption: 'You are documenting a method in External Update ', ext asString, '.\There is a more recent version of that method in ' withCRs, ours, 
'.\If you are explaining the newer version, please Cancel.\Wait until that version appears in an External Update.' withCRs.
	response = 2 ifTrue: [self saveDoc: aMorph].
! !


!EventRollMorph methodsFor: 'display' stamp: 'ct 8/20/2020 15:00'!
setMediaEventMorphs
	"Place morphs representing the media track on the roll."

	| aMorph aWheel |
	mediaTrack ifEmpty: [^ self].
	aWheel := Color wheel: mediaTrack size.
	mediaTrack withIndexDo:
		[:evt :index |
			aMorph := MediaEventMorph new.
			aMorph hResizing: #shrinkWrap.
			aMorph vResizing: #shrinkWrap.
			aMorph color: ((aWheel at: index) alpha: 0.5).
			aMorph event: evt.
			aMorph extent: ((evt durationInMilliseconds / millisecondsPerPixel) @ 32).
			aMorph left: ((evt timeStamp - startTime)/ millisecondsPerPixel).
			aMorph top: 84.
			actualRoll addMorphBack: aMorph]! !


!Form methodsFor: 'analyzing' stamp: 'ct 8/20/2020 15:00'!
cgForPixelValue: pv orNot: not
	"Return the center of gravity for all pixels of value pv.
	Note:  If orNot is true, then produce the center of gravity for all pixels
	that are DIFFERENT from the supplied (background) value"
	| xAndY |
	xAndY := (Array with: (self xTallyPixelValue: pv orNot: not)
					with: (self yTallyPixelValue: pv orNot: not)) collect:
		[:profile | | pixCount weighted |	"For both x and y profiles..."
		pixCount := 0.  weighted := 0.
		profile withIndexDo:
			[:t :i | pixCount := pixCount + t.
			weighted := weighted + (t*i)].
		pixCount = 0  "Produce average of nPixels weighted by coordinate"
			ifTrue: [0.0]
			ifFalse: [weighted asFloat / pixCount asFloat - 1.0]].

	^ xAndY first @ xAndY last
"
| f cg |
[Sensor anyButtonPressed] whileFalse:
	[f := Form fromDisplay: (Sensor cursorPoint extent: 50@50).
	cg := f cgForPixelValue: (Color black pixelValueForDepth: f depth) orNot: false.
	f displayAt: 0@0.
	Display fill: (cg extent: 2@2) fillColor: Color red].
	ScheduledControllers restore
"! !

!Form methodsFor: 'analyzing' stamp: 'ct 8/20/2020 15:00'!
colorsUsed
	"Return a list of the Colors this form uses."

	| tallies tallyDepth usedColors |
	tallies := self tallyPixelValues.
	tallyDepth := (tallies size log: 2) asInteger.
	usedColors := OrderedCollection new.
	tallies withIndexDo: [:count :i |
		count > 0 ifTrue: [
			usedColors add: (Color colorFromPixelValue: i - 1 depth: tallyDepth)]].
	^ usedColors asArray
! !


!ColorForm methodsFor: 'color manipulation' stamp: 'ct 8/20/2020 15:00'!
colorsUsed
	"Return a list of the colors actually used by this ColorForm."

	| myColor list |
	myColor := self colors.
	list := OrderedCollection new.
	self tallyPixelValues withIndexDo: [:count :i |
		count > 0 ifTrue: [list add: (myColor at: i)]].
	^ list asArray
! !


!FormSetFont methodsFor: 'initialize-release' stamp: 'ct 8/20/2020 15:00'!
fromFormArray: formArray asciiStart: asciiStart ascent: ascentVal
	| height width x badChar |
	type := 2.
	name := 'aFormFont'.
	minAscii := asciiStart.
	maxAscii := minAscii + formArray size - 1.
	ascent := ascentVal.
	subscript := superscript := emphasis := 0.
	height := width := 0.
	maxWidth := 0.
	formArray do:
		[:f | width := width + f width.
		maxWidth := maxWidth max: f width.
		height := height max: f height + f offset y].
	badChar := (Form extent: 7@height) borderWidth: 1.
	width := width + badChar width.
	descent := height - ascent.
	pointSize := height.
	glyphs := Form extent: width @ height depth: formArray first depth.
	xTable := Array new: maxAscii + 3 withAll: 0.
	x := 0.
	formArray withIndexDo:
		[:f :i | f displayOn: glyphs at: x@0.
		xTable at: minAscii + i+1 put: (x := x + f width)].
	badChar displayOn: glyphs at: x@0.
	xTable at: maxAscii + 3 put: x + badChar width.
	characterToGlyphMap := nil.! !


!HashedCollection methodsFor: '*60Deprecated-enumerating' stamp: 'ct 8/20/2020 14:29'!
doWithIndex: elementAndIndexBlock

	self deprecated: 'Use #withIndexDo: instead'.
	^ self withIndexDo: elementAndIndexBlock! !


!Inspector methodsFor: 'fields - streaming' stamp: 'ct 8/20/2020 15:00'!
streamInstanceVariablesOn: aStream

	(self object perform: #class "do not inline send of #class, receiver could be a proxy") allInstVarNames withIndexDo: [:name :index |		
		aStream nextPut: ((self newFieldForType: #instVar key: name)
			shouldStyleName: true;
			valueGetter: [:object | object instVarNamed: name];
			valueSetter: [:object :value | object instVarNamed: name put: value];
			yourself)].! !


!BasicInspector methodsFor: 'fields - streaming' stamp: 'ct 8/20/2020 14:59'!
streamInstanceVariablesOn: aStream

	(thisContext objectClass: self object) allInstVarNames withIndexDo: [:name :index |		
		aStream nextPut: ((self newFieldForType: #instVar key: name)
			name: name asString;
			shouldStyleName: true;
			valueGetter: [:object | thisContext object: object instVarAt: index];
			valueGetterExpression: ('thisContext object: {1} instVarAt: {2}' format: { 'self'. index }); 
			valueSetter: [:object :value | thisContext object: object instVarAt: index put: value];
			yourself)].! !


!ClassInspector methodsFor: 'fields - streaming' stamp: 'ct 8/20/2020 15:00'!
streamSharedPoolsOn: aStream

	self object sharedPools withIndexDo: [:pool :index |
		aStream nextPut: ((self newFieldForType: #poolDictionary key: (self environment keyAtIdentityValue: pool))
			shouldStyleName: true;
			valueGetter: [:object | object sharedPools at: index];
			valueSetter: [:object :value | object sharedPools at: index put: value];
			yourself)].! !


!ContextInspector methodsFor: 'fields - streaming' stamp: 'ct 8/20/2020 15:00'!
streamTemporaryVariablesOn: aStream

	| tempNames |
	tempNames := [self object tempNames] ifError: [
		^ self streamError: 'Invalid temporaries' translated on: aStream].
	
	tempNames withIndexDo: [:name :index |
		aStream nextPut: ((self newFieldForType: #tempVar key: name)
			name: ('[{1}]' format: {name});
			valueGetter: [:context | context namedTempAt: index];
			valueSetter: [:context :value | context namedTempAt: index put: value];
			yourself)]! !


!ContextVariablesInspector methodsFor: 'fields - streaming' stamp: 'ct 8/20/2020 15:00'!
streamTemporaryVariablesOn: aStream
	"Overwritten to change the visuals of temps in debuggers."
	
	| tempNames |
	tempNames := [self object tempNames] ifError: [
		^ self streamError: 'Invalid temporaries' translated on: aStream].
	
	tempNames withIndexDo: [:name :index |
		aStream nextPut: ((self newFieldForType: #tempVar key: name)
			shouldStyleName: true;
			valueGetter: [:context | context namedTempAt: index];
			valueSetter: [:context :value | context namedTempAt: index put: value];
			yourself)].! !


!InternalThreadNavigationMorph methodsFor: 'sorting' stamp: 'ct 8/20/2020 15:00'!
acceptSortedContentsFrom: aHolder
	"Update my page list from the given page sorter."

	

	threadName isEmpty ifTrue: [threadName := 'I need a name' translated].
	threadName := UIManager default 
		request: 'Name this thread.' translated 
		initialAnswer: threadName.
	threadName isEmptyOrNil ifTrue: [^self].
	listOfPages := OrderedCollection new.
	aHolder submorphs withIndexDo: [:m :i | | cachedData proj nameOfThisProject |
		(nameOfThisProject := m valueOfProperty: #nameOfThisProject) ifNotNil: [
			cachedData := {nameOfThisProject}.
			proj := Project named: nameOfThisProject.
			(proj isNil or: [proj thumbnail isNil]) ifFalse: [
				cachedData := cachedData, {proj thumbnail scaledToSize: self myThumbnailSize}.
			].
			listOfPages add: cachedData.
		].
	].
	self class know: listOfPages as: threadName.
	self removeAllMorphs; addButtons.
	self world ifNil: [
		self openInWorld; positionAppropriately.
	].
! !


!MCTool methodsFor: 'toolbuilder' stamp: 'ct 8/20/2020 15:00'!
buildWith: builder
	|  windowBuilder |

	windowBuilder := MCToolWindowBuilder builder: builder tool: self.
	self widgetSpecs do:
		[:spec | | send fractions offsets |
		send := spec first.
		fractions := (spec at: 2 ifAbsent: [#(0 0 1 1)]) copy.
		offsets := (spec at: 3 ifAbsent: [#(0 0 0 0)]) copy.
		
		fractions withIndexDo: [:numberOrSymbol :index |
			numberOrSymbol isSymbol
				ifTrue: [fractions at: index put: (self perform: numberOrSymbol)]].
		offsets withIndexDo: [:numberOrSymbol :index |
			numberOrSymbol isSymbol
				ifTrue: [offsets at: index put: (self perform: numberOrSymbol)]].
					
		windowBuilder frame: (LayoutFrame
			fractions: (fractions first @ fractions second corner: fractions third @ fractions fourth)
			offsets: (offsets first @ offsets second corner: offsets third @ offsets fourth)).
		windowBuilder perform: send first withArguments: send allButFirst].

	^ windowBuilder build
! !


!MatrixTransform2x3 class methodsFor: '*nebraska-instance creation' stamp: 'ct 8/20/2020 15:00'!
fromRemoteCanvasEncoding: encoded
	"DisplayTransform fromRemoteCanvasEncoding:  'Matrix,1065353216,0,1137541120,0,1065353216,1131610112,'"
	| nums transform encodedNums |
	"split the numbers up"
	encodedNums := encoded findTokens: ','.

	"remove the initial 'Matrix' specification"
	encodedNums := encodedNums asOrderedCollection.
	encodedNums removeFirst.

	"parse the numbers"
	nums := encodedNums collect: [ :enum |
		Integer readFromString: enum ].

	"create an instance"
	transform := self new.

	"plug in the numbers"
	nums withIndexDo: [ :num :i |
		transform basicAt: i put: num ].

	^transform! !


!MentoringEventRecorder methodsFor: 'event handling' stamp: 'ct 8/20/2020 15:00'!
mergeMediaEvent: anEvent
	"Merge the event, presently time-stamped with a relative time-stamp., with my existing tape.  Answer the merged tape.  It is the responsibility of the sender to notify other objects that may be interested in the change, such as an event roll."

	| itsTimeStamp eventFollowingIt newTape anIndex itsCopy copysTimeStamp |
	itsTimeStamp :=  anEvent timeStamp.
	itsCopy := anEvent copy.
	itsCopy timeStamp: (copysTimeStamp := itsTimeStamp + tape first timeStamp).

	eventFollowingIt := tape detect: [:evt | evt timeStamp > copysTimeStamp]  ifNone: [nil].
	anIndex := eventFollowingIt
		ifNil:
			[tape size + 1]
		ifNotNil:
			[tape indexOf: eventFollowingIt].

	newTape := Array streamContents:
		[:aStream | 
			tape withIndexDo:
				[:evt :index |
					index = anIndex ifTrue:
						[aStream nextPut: itsCopy].
					aStream nextPut: evt].
			anIndex > tape size ifTrue: [aStream nextPut: itsCopy]].

	tape := newTape! !


!Message methodsFor: '*Tools-Debugger' stamp: 'ct 8/20/2020 15:00'!
createStubMethod
	| argNames |
	argNames := Set new.
	^ String streamContents: [ :s |
		self selector keywords withIndexDo: [ :key :i |
			| aOrAn argName arg argClassName |
			s nextPutAll: key.
			((key last = $:) or: [self selector isInfix]) ifTrue: [
				arg := self arguments at: i.
				argClassName := arg canonicalArgumentName.
				aOrAn := argClassName first isVowel ifTrue: ['an'] ifFalse: ['a'].
				argName := aOrAn, argClassName.
				[argNames includes: argName] whileTrue: [argName := argName, i asString].
				argNames add: argName.
				s nextPutAll: ' '; nextPutAll: argName; space
			].
		].
		s cr; tab.
		s nextPutAll: 'self shouldBeImplemented'
	].! !


!MethodFinder methodsFor: 'initialize' stamp: 'ct 8/20/2020 14:59'!
initialize
	"The methods we are allowed to use.  (MethodFinder new initialize) "

	Approved := Set new.
	AddAndRemove := Set new.
	Blocks := Set new.
	"These modify an argument and are not used by the MethodFinder: longPrintOn: printOn: storeOn: sentTo: storeOn:base: printOn:base: absPrintExactlyOn:base: absPrintOn:base: absPrintOn:base:digitCount: writeOn: writeScanOn: possibleVariablesFor:continuedFrom: printOn:format:"

"Object"  
	#("in class, instance creation" categoryForUniclasses chooseUniqueClassName initialInstance isSystemDefined newFrom: officialClass readCarefullyFrom:
"accessing" at: basicAt: basicSize bindWithTemp: in: size yourself 
"testing" basicType ifNil: ifNil:ifNotNil: ifNotNil: ifNotNil:ifNil: isColor isFloat isFraction isInMemory isInteger isMorph isNil isNumber isPoint isText isTransparent isWebBrowser knownName notNil pointsTo: wantsSteps 
"comparing" = == closeTo: hash identityHash identityHashPrintString ~= ~~ 
"copying" copy shallowCopy 
"dependents access" canDiscardEdits dependents hasUnacceptedEdits 
"updating" changed changed: okToChange update: windowIsClosing 
"printing" fullPrintString isLiteral longPrintString printString storeString stringForReadout stringRepresentation 
"class membership" class isKindOf: isKindOf:orOf: isMemberOf: respondsTo: xxxClass 
"error handling" 
"user interface" addModelMenuItemsTo:forMorph:hand: defaultLabelForInspector fullScreenSize initialExtent modelWakeUp mouseUpBalk: newTileMorphRepresentative windowActiveOnFirstClick windowReqNewLabel: 
"system primitives" asOop instVarAt: instVarNamed: 
"private" 
"associating" -> 
"converting" as: asOrderedCollection asString 
"casing" caseOf: caseOf:otherwise: 
"binding" bindingOf: 
"macpal" contentsChanged currentEvent currentHand currentWorld flash instanceVariableValues scriptPerformer 
"flagging" flag: 
"translation support" "objects from disk" "finalization" ) do: [:sel | Approved add: sel].
	#(at:add: at:modify: at:put: basicAt:put: "NOT instVar:at:"
"message handling" perform: perform:orSendTo: perform:with: perform:with:with: perform:with:with:with: perform:withArguments: perform:withArguments:inSuperclass: 
) do: [:sel | AddAndRemove add: sel].

"Boolean, True, False, UndefinedObject"  
	#("logical operations" & eqv: not xor: |
"controlling" and: ifFalse: ifFalse:ifTrue: ifTrue: ifTrue:ifFalse: or:
"copying" 
"testing" isEmptyOrNil) do: [:sel | Approved add: sel].

"Behavior" 
	#("initialize-release"
"accessing" compilerClass decompilerClass evaluatorClass format methodDict parserClass sourceCodeTemplate subclassDefinerClass
"testing" instSize instSpec isBits isBytes isFixed isPointers isVariable isWeak isWords
"copying"
"printing" defaultNameStemForInstances printHierarchy
"creating class hierarchy"
"creating method dictionary"
"instance creation" basicNew basicNew: new new:
"accessing class hierarchy" allSubclasses allSubclassesWithLevelDo:startingLevel: allSuperclasses subclasses superclass withAllSubclasses withAllSuperclasses
"accessing method dictionary" allSelectors changeRecordsAt: compiledMethodAt: compiledMethodAt:ifAbsent: firstCommentAt: lookupSelector: selectors selectorsDo: selectorsWithArgs: "slow but useful ->" sourceCodeAt: sourceCodeAt:ifAbsent: sourceMethodAt: sourceMethodAt:ifAbsent:
"accessing instances and variables" allClassVarNames allInstVarNames allSharedPools classVarNames instVarNames instanceCount sharedPools someInstance subclassInstVarNames
"testing class hierarchy" inheritsFrom: kindOfSubclass
"testing method dictionary" canUnderstand: classThatUnderstands: hasMethods includesSelector: whichClassIncludesSelector: whichSelectorsAccess: whichSelectorsReferTo: whichSelectorsReferTo:special:byte: whichMethodsStoreInto:
"enumerating"
"user interface") do: [:sel | Approved add: sel].

"ClassDescription"
	#("initialize-release" 
"accessing" classVersion isMeta name theNonMetaClass
"copying" 
"printing" classVariablesString instanceVariablesString sharedPoolsString
"instance variables" checkForInstVarsOK: 
"method dictionary" 
"organization" category organization whichCategoryIncludesSelector:
"compiling" acceptsLoggingOfCompilation wantsChangeSetLogging
"fileIn/Out" definition
"private" ) do: [:sel | Approved add: sel].

"Class"
	#("initialize-release" 
"accessing" classPool
"testing"
"copying" 
"class name" 
"instance variables" 
"class variables" classVarAt: classVariableAssociationAt:
"pool variables" 
"compiling" 
"subclass creation" 
"fileIn/Out" ) do: [:sel | Approved add: sel]. 

"Metaclass"
	#("initialize-release" 
"accessing" isSystemDefined soleInstance
"copying" "instance creation" "instance variables"  "pool variables" "class hierarchy"  "compiling"
"fileIn/Out"  nonTrivial ) do: [:sel | Approved add: sel].

"Context, BlockContext"
	#(receiver client method receiver tempAt: 
"debugger access" pc selector sender shortStack sourceCode tempNames tempsAndValues
"controlling"  "printing" "system simulation" 
"initialize-release" 
"accessing" hasMethodReturn home numArgs
"evaluating" value value:ifError: value:value: value:value:value: value:value:value:value: valueWithArguments:
"controlling"  "scheduling"  "instruction decoding"  "printing" "private"  "system simulation" ) do: [:sel | Approved add: sel].
	#(value: "<- Association has it as a store" ) do: [:sel | AddAndRemove add: sel].

"Message"
	#("inclass, instance creation" selector: selector:argument: selector:arguments:
"accessing" argument argument: arguments sends:
"printing" "sending" ) do: [:sel | Approved add: sel].
	#("private" setSelector:arguments:) do: [:sel | AddAndRemove add: sel].

"Magnitude"
	#("comparing" < <= > >= between:and:
"testing" max: min: min:max: ) do: [:sel | Approved add: sel].

"Date, Time"
	#("in class, instance creation" fromDays: fromSeconds: fromString: newDay:month:year: newDay:year: today
	"in class, general inquiries" dateAndTimeNow dayOfWeek: daysInMonth:forYear: daysInYear: firstWeekdayOfMonth:year: indexOfMonth: leapYear: nameOfDay: nameOfMonth:
"accessing" day leap monthIndex monthName weekday year
"arithmetic" addDays: subtractDate: subtractDays:
"comparing"
"inquiries" dayOfMonth daysInMonth daysInYear daysLeftInYear firstDayOfMonth previous:
"converting" asSeconds
"printing"  mmddyyyy printFormat: 
"private" weekdayIndex 
	"in class, instance creation" fromSeconds: now 
	"in class, general inquiries" dateAndTimeFromSeconds: dateAndTimeNow millisecondClockValue millisecondsToRun: totalSeconds
"accessing" hours minutes seconds
"arithmetic" addTime: subtractTime:
"comparing"
"printing" intervalString print24 
"converting") do: [:sel | Approved add: sel].
	#("private" 
		 ) do: [:sel | AddAndRemove add: sel].

"Number"
	#("in class" readFrom:base: 
"arithmetic" * + - / // \\ abs negated quo: reciprocal rem:
"mathematical functions" arcCos arcSin arcTan arcTan: cos exp floorLog: ln log log: raisedTo: raisedToInteger: sin sqrt squared tan
"truncation and round off" ceiling detentBy:atMultiplesOf:snap: floor roundTo: roundUpTo: rounded truncateTo: truncated
"comparing"
"testing" even isDivisibleBy: isInfinite isNaN isZero negative odd positive sign strictlyPositive
"converting" @ asInteger asNumber asPoint asSmallAngleDegrees degreesToRadians radiansToDegrees
"intervals" to: to:by: 
"printing" printStringBase: storeStringBase: ) do: [:sel | Approved add: sel].

"Integer"
	#("in class" primesUpTo:
"testing" isPowerOfTwo
"arithmetic" alignedTo:
"comparing"
"truncation and round off" atRandom normalize
"enumerating" timesRepeat:
"mathematical functions" degreeCos degreeSin factorial gcd: lcm: take:
"bit manipulation" << >> allMask: anyMask: bitAnd: bitClear: bitInvert bitInvert32 bitOr: bitShift: bitXor: lowBit noMask:
"converting" asCharacter asColorOfDepth: asFloat asFraction asHexDigit
"printing" asStringWithCommas hex hex8 radix:
"system primitives" lastDigit replaceFrom:to:with:startingAt:
"private" "benchmarks" ) do: [:sel | Approved add: sel].

"SmallInteger, LargeNegativeInteger, LargePositiveInteger"
	#("arithmetic" "bit manipulation" highBit "testing" "comparing" "copying" "converting" "printing" 
"system primitives" digitAt: digitLength 
"private" fromString:radix: ) do: [:sel | Approved add: sel].
	#(digitAt:put: ) do: [:sel | AddAndRemove add: sel].

"Float"
	#("arithmetic"
"mathematical functions" reciprocalLogBase2 timesTwoPower:
"comparing" "testing"
"truncation and round off" exponent fractionPart integerPart significand significandAsInteger
"converting" asApproximateFraction asIEEE32BitWord asTrueFraction
"copying") do: [:sel | Approved add: sel].

"Fraction, Random"
	#(denominator numerator reduced next nextValue) do: [:sel | Approved add: sel].
	#(setNumerator:denominator:) do: [:sel | AddAndRemove add: sel].

"Collection"
	#("accessing" anyOne
"testing" includes: includesAllOf: includesAnyOf: includesSubstringAnywhere: isEmpty isSequenceable occurrencesOf:
"enumerating" collect: collect:thenSelect: count: detect: detect:ifNone: detectMax: detectMin: detectSum: inject:into: reject: select: select:thenCollect: intersection:
"converting" asBag asCharacterSet asSet asSortedArray asSortedCollection asSortedCollection:
"printing"
"private" maxSize
"arithmetic"
"math functions" average max median min range sum) do: [:sel | Approved add: sel].
	#("adding" add: addAll: addIfNotPresent:
"removing" remove: remove:ifAbsent: removeAll: removeAllFoundIn: removeAllSuchThat: remove:ifAbsent:) do: [:sel | AddAndRemove add: sel].

"SequenceableCollection"
	#("comparing" hasEqualElements:
"accessing" allButFirst allButLast at:ifAbsent: atAll: atPin: atRandom: atWrap: fifth first fourth identityIndexOf: identityIndexOf:ifAbsent: indexOf: indexOf:ifAbsent: indexOf:startingAt:ifAbsent: indexOfSubCollection:startingAt: indexOfSubCollection:startingAt:ifAbsent: last second sixth third
"removing"
"copying" , copyAfterLast: copyAt:put: copyFrom:to: copyReplaceAll:with: copyReplaceFrom:to:with: copyUpTo: copyUpToLast: copyWith: copyWithout: copyWithoutAll: forceTo:paddingWith: shuffled sorted:
"enumerating" withIndexCollect: findFirst: findLast: pairsCollect: with:collect: withIndexCollect: polynomialEval:
"converting" asArray asDictionary asFloat32Array asFloat64Array asIntegerArray asStringWithCr asWordArray reversed
"private" copyReplaceAll:with:asTokens: ) do: [:sel | Approved add: sel].
	#( swap:with:) do: [:sel | AddAndRemove add: sel].

"ArrayedCollection, Bag"
	#("private" defaultElement 
"sorting" isSorted
"accessing" cumulativeCounts sortedCounts sortedElements "testing" "adding" add:withOccurrences: "removing" "enumerating" 
	) do: [:sel | Approved add: sel].
	#( mergeSortFrom:to:by: sort sort: add: add:withOccurrences:
"private" setDictionary ) do: [:sel | AddAndRemove add: sel].

"Other messages that modify the receiver"
	#(atAll:put: atAll:putAll: atAllPut: atWrap:put: replaceAll:with: replaceFrom:to:with:  removeFirst removeLast) do: [:sel | AddAndRemove add: sel].

	self initialize2.

"
MethodFinder new initialize.
MethodFinder new organizationFiltered: Set
"

! !

!MethodFinder methodsFor: 'initialize' stamp: 'ct 8/20/2020 14:59'!
initialize2
	"The methods we are allowed to use.  (MethodFinder new initialize) "

"Set"
	#("in class" sizeFor:
"testing" "adding" "removing" "enumerating"
"private" array scanFor: 
"accessing" someElement) do: [:sel | Approved add: sel].

"Dictionary, IdentityDictionary, IdentitySet"
	#("accessing" associationAt: associationAt:ifAbsent: at:ifPresent: keyAtIdentityValue: keyAtIdentityValue:ifAbsent: keyAtValue: keyAtValue:ifAbsent: keys
"testing" includesKey: ) do: [:sel | Approved add: sel].
	#(removeKey: removeKey:ifAbsent:
) do: [:sel | AddAndRemove add: sel].

"LinkedList, Interval, MappedCollection"
	#("in class"  from:to: from:to:by:
"accessing" contents) do: [:sel | Approved add: sel].
	#(
"adding" addFirst: addLast:) do: [:sel | AddAndRemove add: sel].

"OrderedCollection, SortedCollection"
	#("accessing" after: before:
"copying" copyEmpty
"adding"  growSize
"removing" "enumerating" "private" 
"accessing" sortBlock) do: [:sel | Approved add: sel].
	#("adding" add:after: add:afterIndex: add:before: addAllFirst: addAllLast: addFirst: addLast:
"removing" removeAt: removeFirst removeLast
"accessing" sortBlock:) do: [:sel | AddAndRemove add: sel].

"Character"
	#("in class, instance creation" allByteCharacters digitValue: new separators
	"accessing untypeable characters" backspace cr enter lf linefeed nbsp newPage space tab
	"constants" alphabet characterTable
"accessing" asciiValue digitValue
"comparing"
"testing" isAlphaNumeric isDigit isLetter isLowercase isSafeForHTTP isSeparator isSpecial isUppercase isVowel tokenish
"copying"
"converting" asIRCLowercase asLowercase asUppercase
	) do: [:sel | Approved add: sel].

"String"
	#("in class, instance creation" crlf fromPacked:
	"primitives" findFirstInString:inSet:startingAt: indexOfAscii:inString:startingAt: 	"internet" valueOfHtmlEntity:
"accessing" byteAt: endsWithDigit findAnySubStr:startingAt: findBetweenSubStrs: findDelimiters:startingAt: findString:startingAt: findString:startingAt:caseSensitive: findTokens: findTokens:includes: findTokens:keep: includesSubstring: includesSubstring:caseSensitive: indexOf:startingAt: indexOfAnyOf: indexOfAnyOf:ifAbsent: indexOfAnyOf:startingAt: indexOfAnyOf:startingAt:ifAbsent: lineCorrespondingToIndex: lineCount lineNumber: skipAnySubStr:startingAt: skipDelimiters:startingAt: startsWithDigit
"comparing" alike: beginsWith: caseSensitiveLessOrEqual: charactersExactlyMatching: compare: crc16 endsWith: endsWithAnyOf: sameAs: startingAt:match:startingAt:
"copying" copyReplaceTokens:with: padded:to:with:
"converting" asByteArray asDate asDisplayText asFileName asHtml asLegalSelector asPacked asParagraph asText asTime asUnHtml asUrl asUrlRelativeTo: capitalized compressWithTable: contractTo: correctAgainst: encodeForHTTP initialIntegerOrNil keywords quoted sansPeriodSuffix splitInteger stemAndNumericSuffix substrings surroundedBySingleQuotes truncateWithElipsisTo: withBlanksTrimmed withFirstCharacterDownshifted withNoLineLongerThan: withSeparatorsCompacted withoutLeadingDigits withoutTrailingBlanks
"displaying" "printing"
"system primitives" compare:with:collated: 
"Celeste" withCRs
"internet" decodeMimeHeader decodeQuotedPrintable unescapePercents withInternetLineEndings withSqueakLineEndings withoutQuoting
"testing" isAllSeparators lastSpacePosition
"paragraph support" indentationIfBlank:
"arithmetic" ) do: [:sel | Approved add: sel].
	#(byteAt:put: translateToLowercase match:) do: [:sel | AddAndRemove add: sel].

"Symbol"
	#("in class, private" hasInterned:ifTrue:
	"access" morePossibleSelectorsFor: possibleSelectorsFor: selectorsContaining: thatStarts:skipping:
"accessing" "comparing" "copying" "converting" "printing" 
"testing" isInfix isKeyword isPvtSelector isUnary) do: [:sel | Approved add: sel].

"Array"
	#("comparing" "converting" evalStrings 
"printing" "private" hasLiteralSuchThat:) do: [:sel | Approved add: sel].

"Array2D"
	#("access" at:at: atCol: atCol:put: atRow: extent extent:fromArray: height width width:height:type:) do: [:sel | Approved add: sel].
	#(at:at:add: at:at:put: atRow:put: ) do: [:sel | AddAndRemove add: sel].

"ByteArray"
	#("accessing" doubleWordAt: wordAt: 
"platform independent access" longAt:bigEndian: shortAt:bigEndian: unsignedLongAt:bigEndian: unsignedShortAt:bigEndian: 
"converting") do: [:sel | Approved add: sel].
	#(doubleWordAt:put: wordAt:put: longAt:put:bigEndian: shortAt:put:bigEndian: unsignedLongAt:put:bigEndian: unsignedShortAt:put:bigEndian:
	) do: [:sel | AddAndRemove add: sel].

"FloatArray"		"Dont know what happens when prims not here"
	false ifTrue: [#("accessing" "arithmetic" *= += -= /=
"comparing"
"primitives-plugin" primAddArray: primAddScalar: primDivArray: primDivScalar: primMulArray: primMulScalar: primSubArray: primSubScalar:
"primitives-translated" primAddArray:withArray:from:to: primMulArray:withArray:from:to: primSubArray:withArray:from:to:
"converting" "private" "user interface") do: [:sel | Approved add: sel].
	].

"IntegerArray, WordArray"
"RunArray"
	#("in class, instance creation" runs:values: scanFrom:
"accessing" runLengthAt: 
"adding" "copying"
"private" runs values) do: [:sel | Approved add: sel].
	#(coalesce repeatLast:ifEmpty: repeatLastIfEmpty:
		) do: [:sel | AddAndRemove add: sel].

"Stream  -- many operations change its state"
	#("testing" atEnd) do: [:sel | Approved add: sel].
	#("accessing" next: nextMatchAll: nextMatchFor: upToEnd
next:put: nextPut: nextPutAll: "printing" print: printHtml:
	) do: [:sel | AddAndRemove add: sel].

"PositionableStream"
	#("accessing" contentsOfEntireFile originalContents peek peekFor: "testing"
"positioning" position ) do: [:sel | Approved add: sel].
	#(nextDelimited: nextLine upTo: position: reset resetContents setToEnd skip: skipTo: upToAll: ) do: [:sel | AddAndRemove add: sel].
	"Because it is so difficult to test the result of an operation on a Stream (you have to supply another Stream in the same state), we don't support Streams beyond the basics.  We want to find the messages that convert Streams to other things."

"ReadWriteStream"
	#("file status" closed) do: [:sel | Approved add: sel].
	#("accessing" next: on: ) do: [:sel | AddAndRemove add: sel].

"WriteStream"
	#("in class, instance creation" on:from:to: with: with:from:to:
		) do: [:sel | Approved add: sel].
	#("positioning" resetToStart
"character writing" crtab crtab:) do: [:sel | AddAndRemove add: sel].

"LookupKey, Association, Link"
	#("accessing" key nextLink) do: [:sel | Approved add: sel].
	#(key: key:value: nextLink:) do: [:sel | AddAndRemove add: sel].

"Point"
	#("in class, instance creation" r:degrees: x:y:
"accessing" x y "comparing" "arithmetic" "truncation and round off"
"polar coordinates" degrees r theta
"point functions" bearingToPoint: crossProduct: dist: dotProduct: eightNeighbors flipBy:centerAt: fourNeighbors grid: nearestPointAlongLineFrom:to: nearestPointOnLineFrom:to: normal normalized octantOf: onLineFrom:to: onLineFrom:to:within: quadrantOf: rotateBy:centerAt: transposed unitVector
"converting" asFloatPoint asIntegerPoint corner: extent: rect:
"transforming" adhereTo: rotateBy:about: scaleBy: scaleFrom:to: translateBy: "copying"
"interpolating" interpolateTo:at:) do: [:sel | Approved add: sel].

"Rectangle"
	#("in class, instance creation" center:extent: encompassing: left:right:top:bottom: 
	merging: origin:corner: origin:extent: 
"accessing" area bottom bottomCenter bottomLeft bottomRight boundingBox center corner corners innerCorners left leftCenter origin right rightCenter top topCenter topLeft topRight
"comparing"
"rectangle functions" adjustTo:along: amountToTranslateWithin: areasOutside: bordersOn:along: encompass: expandBy: extendBy: forPoint:closestSideDistLen: insetBy: insetOriginBy:cornerBy: intersect: merge: pointNearestTo: quickMerge: rectanglesAt:height: sideNearestTo: translatedToBeWithin: withBottom: withHeight: withLeft: withRight: withSide:setTo: withTop: withWidth:
"testing" containsPoint: containsRect: hasPositiveExtent intersects: isTall isWide
"truncation and round off"
"transforming" align:with: centeredBeneath: newRectFrom: squishedWithin: "copying"
	) do: [:sel | Approved add: sel].

"Color"
	#("in class, instance creation" colorFrom: colorFromPixelValue:depth: fromRgbTriplet: gray: h:s:v: r:g:b: r:g:b:alpha: r:g:b:range:
	"named colors" black blue brown cyan darkGray gray green lightBlue lightBrown lightCyan lightGray lightGreen lightMagenta lightOrange lightRed lightYellow magenta orange red transparent veryDarkGray veryLightGray veryVeryDarkGray veryVeryLightGray white yellow
	"other" colorNames indexedColors pixelScreenForDepth: quickHighLight:
"access" alpha blue brightness green hue luminance red saturation
"equality"
"queries" isBitmapFill isBlack isGray isSolidFill isTranslucent isTranslucentColor
"transformations" alpha: dansDarker darker lighter mixed:with: muchLighter slightlyDarker slightlyLighter veryMuchLighter alphaMixed:with:
"groups of shades" darkShades: lightShades: mix:shades: wheel:
"printing" shortPrintString
"other" colorForInsets rgbTriplet
"conversions" asB3DColor asColor balancedPatternForDepth: bitPatternForDepth: closestPixelValue1 closestPixelValue2 closestPixelValue4 closestPixelValue8 dominantColor halfTonePattern1 halfTonePattern2 indexInMap: pixelValueForDepth: pixelWordFor:filledWith: pixelWordForDepth: scaledPixelValue32
"private" privateAlpha privateBlue privateGreen privateRGB privateRed "copying"
	) do: [:sel | Approved add: sel].

"	For each selector that requires a block argument, add (selector argNum) 
		to the set Blocks."
"ourClasses := #(Object Boolean True False UndefinedObject Behavior ClassDescription Class Metaclass MethodContext BlockContext Message Magnitude Date Time Number Integer SmallInteger LargeNegativeInteger LargePositiveInteger Float Fraction Random Collection SequenceableCollection ArrayedCollection Bag Set Dictionary IdentityDictionary IdentitySet LinkedList Interval MappedCollection OrderedCollection SortedCollection Character String Symbol Array Array2D ByteArray FloatArray IntegerArray WordArray RunArray Stream PositionableStream ReadWriteStream WriteStream LookupKey Association Link Point Rectangle Color).
ourClasses do: [:clsName | cls := Smalltalk at: clsName.
	(cls selectors) do: [:aSel |
		((Approved includes: aSel) or: [AddAndRemove includes: aSel]) ifTrue: [
			(cls formalParametersAt: aSel) withIndexDo: [:tName :ind |
				(tName endsWith: 'Block') ifTrue: [
					Blocks add: (Array with: aSel with: ind)]]]]].
"
#((timesRepeat: 1 ) (indexOf:ifAbsent: 2 ) (pairsCollect: 1 ) (mergeSortFrom:to:by: 3 ) (ifNotNil:ifNil: 1 ) (ifNotNil:ifNil: 2 ) (ifNil: 1 ) (at:ifAbsent: 2 ) (ifNil:ifNotNil: 1 ) (ifNil:ifNotNil: 2 ) (ifNotNil: 1 ) (at:modify: 2 ) (identityIndexOf:ifAbsent: 2 ) (sort: 1 ) (sortBlock: 1 ) (detectMax: 1 ) (repeatLastIfEmpty: 1 ) (allSubclassesWithLevelDo:startingLevel: 1 ) (keyAtValue:ifAbsent: 2 ) (in: 1 ) (ifTrue: 1 ) (or: 1 ) (select: 1 ) (inject:into: 2 )  (forPoint:closestSideDistLen: 2 ) (value:ifError: 2 ) (selectorsDo: 1 ) (removeAllSuchThat: 1 ) (keyAtIdentityValue:ifAbsent: 2 ) (detectMin: 1 ) (detect:ifNone: 1 ) (ifTrue:ifFalse: 1 ) (ifTrue:ifFalse: 2 ) (detect:ifNone: 2 ) (hasLiteralSuchThat: 1 ) (indexOfAnyOf:ifAbsent: 2 ) (reject: 1 ) (newRectFrom: 1 ) (removeKey:ifAbsent: 2 ) (at:ifPresent: 2 ) (associationAt:ifAbsent: 2 ) (withIndexCollect: 1 ) (repeatLast:ifEmpty: 2 ) (findLast: 1 ) (indexOf:startingAt:ifAbsent: 3 ) (remove:ifAbsent: 2 ) (ifFalse:ifTrue: 1 ) (ifFalse:ifTrue: 2 ) (caseOf:otherwise: 2 ) (count: 1 ) (collect: 1 ) (sorted: 1 ) (and: 1 ) (asSortedCollection: 1 ) (with:collect: 2 ) (sourceCodeAt:ifAbsent: 2 ) (detect: 1 ) (withIndexCollect: 1 ) (compiledMethodAt:ifAbsent: 2 ) (bindWithTemp: 1 ) (detectSum: 1 ) (indexOfSubCollection:startingAt:ifAbsent: 3 ) (findFirst: 1 ) (sourceMethodAt:ifAbsent: 2 ) (collect:thenSelect: 1 ) (collect:thenSelect: 2 ) (select:thenCollect: 1 ) (select:thenCollect: 2 ) (ifFalse: 1 ) (indexOfAnyOf:startingAt:ifAbsent: 3 ) (indentationIfBlank: 1 ) ) do: [:anArray |
	Blocks add: anArray].

self initialize3.

"
MethodFinder new initialize.
MethodFinder new organizationFiltered: TranslucentColor class 
"
"Do not forget class messages for each of these classes"
! !

!MethodFinder methodsFor: 'initialize' stamp: 'ct 8/20/2020 15:00'!
noteDangerous
	"Remember the methods with really bad side effects."

	Dangerous := Set new.
"Object accessing, testing, copying, dependent access, macpal, flagging"
	#(addInstanceVarNamed:withValue: haltIfNil copyAddedStateFrom: veryDeepCopy veryDeepCopyWith: veryDeepFixupWith: veryDeepInner: addDependent: evaluate:wheneverChangeIn: codeStrippedOut: playSoundNamed: isThisEverCalled isThisEverCalled: logEntry logExecution logExit)
		do: [:sel | Dangerous add: sel].

"Object error handling"
	#(cannotInterpret: caseError confirm: confirm:orCancel: doesNotUnderstand: error: halt halt: notify: notify:at: primitiveFailed shouldNotImplement subclassResponsibility)
		do: [:sel | Dangerous add: sel].

"Object user interface"
	#(basicInspect beep inform: inspect inspectWithLabel: notYetImplemented inspectElement )
		do: [:sel | Dangerous add: sel].

"Object system primitives"
	#(become: becomeForward: instVarAt:put: instVarNamed:put: nextInstance nextObject rootStubInImageSegment: someObject tryPrimitive:withArgs:)
		do: [:sel | Dangerous add: sel].

"Object private"
	#(errorImproperStore errorNonIntegerIndex errorNotIndexable errorSubscriptBounds: mustBeBoolean primitiveError: species storeAt:inTempFrame:)
		do: [:sel | Dangerous add: sel].

"Object, translation support"
	#(cCode: cCode:inSmalltalk: cCoerce:to: export: inline: returnTypeC: sharedCodeNamed:inCase: var:declareC:)
		do: [:sel | Dangerous add: sel].

"Object, objects from disk, finalization.  And UndefinedObject"
	#(comeFullyUpOnReload: objectForDataStream: readDataFrom:size: rehash saveOnFile storeDataOn: actAsExecutor executor finalize retryWithGC:until:   suspend)
		do: [:sel | Dangerous add: sel].

"No Restrictions:   Boolean, False, True, "

"Morph"
	#()
		do: [:sel | Dangerous add: sel].

"Behavior"
	#(obsolete confirmRemovalOf: copyOfMethodDictionary storeLiteral:on: addSubclass: removeSubclass: superclass: 
"creating method dictionary" addSelector:withMethod: compile: compile:notifying: compileAll compileAllFrom: compress decompile: defaultSelectorForMethod: methodDictionary: recompile:from: recompileChanges removeSelector: compressedSourceCodeAt: selectorAtMethod:setClass: allInstances allSubInstances inspectAllInstances inspectSubInstances thoroughWhichSelectorsReferTo:special:byte: "enumerating" allInstancesDo: allSubInstancesDo: allSubclassesDo: allSuperclassesDo: selectSubclasses: selectSuperclasses: subclassesDo: withAllSubclassesDo:
   "too slow->" crossReference removeUninstantiatedSubclassesSilently "too slow->" unreferencedInstanceVariables
"private" flushCache format:variable:words:pointers: format:variable:words:pointers:weak: format:variable:bitsUnitSize:pointers:weak: printSubclassesOn:level: basicRemoveSelector: addSelector:withMethod:notifying: addSelectorSilently:withMethod:)
		do: [:sel | Dangerous add: sel].

"CompiledMethod"
	#(defaultSelector)
		do: [:sel | Dangerous add: sel].

"Others "
	#("no tangible result" do: associationsDo:  
"private" adaptToCollection:andSend: adaptToNumber:andSend: adaptToPoint:andSend: adaptToString:andSend: instVarAt:put: asDigitsToPower:do: combinations:atATimeDo: withIndexDo: pairsDo: permutationsDo: reverseDo: reverseWith:do: with:do: withIndexDo: asDigitsAt:in:do: combinationsAt:in:after:do: errorOutOfBounds permutationsStartingAt:do: fromUser)
		do: [:sel | Dangerous add: sel].


	#(    fileOutPrototype addSpareFields makeFileOutFile )
		do: [:sel | Dangerous add: sel].
	#(recompile:from: recompileAllFrom: recompileChanges asPrototypeWithFields: asPrototype addInstanceVarNamed:withValue: addInstanceVariable addClassVarName: removeClassVarName: findOrAddClassVarName: instanceVariableNames: )
		do: [:sel | Dangerous add: sel].

 ! !

!MethodFinder methodsFor: 'search' stamp: 'ct 8/20/2020 15:00'!
exceptions
	"Handle some very slippery selectors.
	asSymbol -- want to be able to produce it, but do not want to make every string submitted into a Symbol!!" 

	| aSel |
	answers first isSymbol ifFalse: [^ self].
	thisData first first isString ifFalse: [^ self].
	aSel := #asSymbol.
	(self testPerfect: aSel) ifTrue: [
		selector add: aSel.
		expressions add: (String streamContents: [:strm | 
			strm nextPutAll: 'data', argMap first printString.
			aSel keywords withIndexDo: [:key :ind |
				strm nextPutAll: ' ',key.
				(key last == $:) | (key first isLetter not)
					ifTrue: [strm nextPutAll: ' data', 
						(argMap at: ind+1) printString]]])].
! !

!MethodFinder methodsFor: 'search' stamp: 'ct 8/20/2020 15:00'!
simpleSearch
	"Run through first arg's class' selectors, looking for one that works."

| class supers listOfLists |
self exceptions.
class := thisData first first class.
"Cache the selectors for the receiver class"
(class == cachedClass and: [cachedArgNum = ((argMap size) - 1)]) 
	ifTrue: [listOfLists := cachedSelectorLists]
	ifFalse: [supers := class withAllSuperclasses.
		listOfLists := OrderedCollection new.
		supers do: [:cls |
			listOfLists add: (cls selectorsWithArgs: (argMap size) - 1)].
		cachedClass := class.
		cachedArgNum := (argMap size) - 1.
		cachedSelectorLists := listOfLists].
listOfLists do: [:selectorList |
	selectorList do: [:aSel |
		(selector includes: aSel) ifFalse: [
			((Approved includes: aSel) or: [AddAndRemove includes: aSel]) ifTrue: [
				(self testPerfect: aSel) ifTrue: [
					selector add: aSel.
					expressions add: (String streamContents: [:strm | 
						strm nextPutAll: 'data', argMap first printString.
						aSel keywords withIndexDo: [:key :ind |
							strm nextPutAll: ' ',key.
							(key last == $:) | (key first isLetter not)
								ifTrue: [strm nextPutAll: ' data', 
									(argMap at: ind+1) printString]]])
					]]]]].
! !


!MethodInterface methodsFor: 'printing' stamp: 'ct 8/20/2020 15:00'!
printOn: aStream
	"print the receiver on a stream.  Overridden to provide details about wording, selector, result type, and companion setter."

	super printOn: aStream.
	aStream nextPutAll: ' - wording: ';
		print: self wording;
		nextPutAll: ' selector: ';
		print: selector.
	self argumentVariables size > 0 ifTrue:
		[aStream nextPutAll: ' Arguments: '.
		argumentVariables withIndexDo:
			[:aVariable :anIndex | 
				aStream nextPutAll: 'argument #', anIndex printString, ' name = ', aVariable variableName asString, ', type = ', aVariable variableType]].
	resultSpecification ifNotNil:
		[aStream nextPutAll: ' result type = ', resultSpecification resultType asString.
		resultSpecification companionSetterSelector ifNotNil:
			[aStream nextPutAll: ' setter = ', resultSpecification companionSetterSelector asString]]
	! !


!MorphicModel methodsFor: 'compilation' stamp: 'ct 8/20/2020 15:00'!
use: cachedSelector orMakeModelSelectorFor: selectorBody in: selectorBlock
	| selector |
	model ifNil: [^ nil].
	cachedSelector ifNil:
			["Make up selector from slotname if any"
			selector := (slotName ifNil: [selectorBody]
								ifNotNil: [slotName , selectorBody]) asSymbol.
			(model class canUnderstand: selector) ifFalse:
				[(self confirm: 'Shall I compile a null response for'
							, Character cr asString
							, model class name , '>>' , selector)
						ifFalse: [self halt].
				model class compile: (String streamContents:
								[:s | selector keywords withIndexDo:
										[:k :i | s nextPutAll: k , ' arg' , i printString].
								s cr; nextPutAll: '"Automatically generated null response."'.
								s cr; nextPutAll: '"Add code below for appropriate behavior..."'.])
							classified: 'input events'
							notifying: nil]]
		ifNotNil:
			[selector := cachedSelector].
	^ selectorBlock value: selector! !


!MorphicUIManager methodsFor: 'ui requests' stamp: 'ct 8/20/2020 15:00'!
chooseFrom: aList lines: linesArray title: aString 
	"Choose an item from the given list. Answer the index of the selected item. Cancel value is 0.
	
	There are several (historical) reasons for building a button dialog instead of a list chooser for small lists:
	1) Unfortunately, there is existing code that uses this call to create simple confirmation dialogs with a list of #(yes no cancel).
	2) Unfortunately, there is existing code that uses this call to mimick a drop-down menu with a (compact) pop-up menu."
	self askForProvidedAnswerTo: aString ifSupplied: [:answer | 
		(answer = #cancel or: [answer isNil]) ifTrue: [^ 0].
		^ aList indexOf: answer].
	
	aList ifEmpty: [^ 0].
	aList size <= 7 ifTrue: [
		| dialog |
		dialog := DialogWindow new
			title: 'Please Choose';
			message: aString;
			filterEnabled: true;
			autoCancel: true; "Like a pop-up menu, click anywhere to dismiss."
			yourself.
		aList withIndexDo: [:ea :index |
			dialog createButton: ea value: index].
		dialog selectedButtonIndex: 1.
		^ dialog getUserResponseAtHand ifNil: [0]].
	
	^ ListChooser chooseFrom: aList title: aString! !


!MouseEventEditor methodsFor: 'initialization' stamp: 'ct 8/20/2020 15:00'!
initializeFor: aMouseEventSequenceMorph forEventRoll: aRoll
	"Initialize the receiver as an editor for the given mouse-event-sequence and event-roll."

	| aTheatre aMorph |
	self color: (Color green muchLighter alpha: 0.7).
	aTheatre := aRoll eventTheatre.
	mouseEventSequenceMorph := aMouseEventSequenceMorph.
	self extent: aTheatre initialContentArea extent.
	self setNameTo: 'mouse event editor'.
	mouseEventSequenceMorph events withIndexDo:
		[:evt :index |
			aMorph := self discRepresentingEvent: evt index: index.
			aMorph center: evt position - aTheatre initialContentArea topLeft.
			self addMorphFront: aMorph]! !


!NativeImageSegment class methodsFor: 'testing' stamp: 'ct 8/20/2020 15:00'!
swapOutProjects  "NativeImageSegment swapOutProjects"  
	"Swap out segments for all projects other than the current one."

	| spaceLeft |
	spaceLeft := Smalltalk garbageCollect.
	Project allProjects withIndexDo:
		[:p :i | | newSpaceLeft | p couldBeSwappedOut ifTrue:
			[Transcript cr; cr; nextPutAll: p name.
			(NativeImageSegment new copyFromRoots: (Array with: p) sizeHint: 0)
				extract; writeToFile: 'project' , i printString.
			newSpaceLeft := Smalltalk garbageCollect.
			Transcript cr; print: newSpaceLeft - spaceLeft; endEntry.
			spaceLeft := newSpaceLeft]].! !


!Player methodsFor: 'scripts-kernel' stamp: 'ct 8/20/2020 15:00'!
universalTilesForInterface: aMethodInterface
	"Return universal tiles for the given method interface.  Record who self is."

	| ms itsSelector argList makeSelfGlobal phrase aType |
	itsSelector := aMethodInterface selector.
	argList := OrderedCollection new.
	aMethodInterface argumentVariables withIndexDo:
		[:anArgumentVariable :anIndex | | argTile | 
			argTile := ScriptingSystem tileForArgType: (aType := aMethodInterface typeForArgumentNumber: anIndex).
			argList add: (aType == #Player 
				ifTrue: [argTile actualObject]
				ifFalse: [argTile literal]).	"default value for each type"].

	ms := MessageSend receiver: self selector: itsSelector arguments: argList asArray.
	"For CardPlayers, use 'self'.  For others, name me, and use my global name."
	makeSelfGlobal := self class officialClass ~~ CardPlayer.
	phrase := ms asTilesIn: self class globalNames: makeSelfGlobal.
	makeSelfGlobal ifFalse: [phrase setProperty: #scriptedPlayer toValue: self].
	^ phrase
! !

!Player methodsFor: 'slots-kernel' stamp: 'ct 8/20/2020 15:00'!
absorbBackgroundDataFrom: aLine forInstanceVariables: slotNames
	"Fill my background fields from the substrings in a tab-delimited line of data.  At the moment this only really cateres to string-valued items"

	slotNames withIndexDo:
		[:aSlotName :anIndex |
			aLine do:
				[:aValue |
					self instVarNamed: aSlotName put: aValue] toFieldNumber: anIndex]! !


!PluggableListMorph methodsFor: 'filtering' stamp: 'ct 8/20/2020 15:00'!
filterList: someItems matching: aPattern
	"Filter someStrings according to aPattern. Prepend best matches in the result. Update the model-to-view map."
	
	| frontMatching substringMatching tmp |
	aPattern ifEmpty: [ ^ someItems ].
	someItems ifEmpty: [ ^ someItems ].
	
	frontMatching := OrderedCollection new.
	substringMatching := OrderedCollection new.
	
	self assert: modelToView isEmpty.
	self assert: viewToModel isEmpty.
	tmp := OrderedCollection new.
	
	someItems withIndexDo:
		[ :each :n | | foundPos |
		foundPos := self filterListItem: each matching: aPattern.
		foundPos = 1
			ifTrue:
				[ frontMatching add: each.
				modelToView at: n put: frontMatching size.
				viewToModel at: frontMatching size put: n ]
			ifFalse:
				[ foundPos > 1 ifTrue:
					[ substringMatching add: each.
					tmp add: n; add:  substringMatching size ] ] ].

	tmp pairsDo: [:modelIndex :viewIndex |
		modelToView at: modelIndex put: viewIndex + frontMatching size.
		viewToModel at: viewIndex + frontMatching size put: modelIndex].
	
	^ frontMatching, substringMatching! !


!PluggableMultiColumnListMorph methodsFor: 'selection' stamp: 'ct 8/20/2020 15:00'!
selection: someObjects
	
	| found |
	someObjects size ~= self columnCount ifTrue: [^ self].
	
	1 to: self listSize do: [:row |
		found := true.
		self getList withIndexDo: [:items :column |
			found := found and: [(items at: row) = (someObjects at: column)]].
		found ifTrue: [^ self selectionIndex: row]].! !

!PluggableMultiColumnListMorph methodsFor: 'model access - cached' stamp: 'ct 8/20/2020 15:00'!
getFullList
	"The full list arranges all items column-first."
	
	fullList ifNotNil: [^ fullList].
	
	fullList := getListSelector
		ifNotNil: [:selector | "A) Fetch the list column-first from the model."
			model perform: selector]
		ifNil: [
			(getListSizeSelector notNil and: [getListElementSelector notNil])
				ifFalse: ["X) We cannot fetch the list from the model. Make it empty."
					#()]
				ifTrue: [ "B) Fetch the list row-first from the model:" 
					| listSize |
					listSize := self getListSize.
					listSize = 0 ifTrue: [#() "Empty list"] ifFalse: [
						| firstRow columns |
						firstRow := self getListItem: 1.
						columns := Array new: firstRow size.
						1 to: columns size do: [:columnIndex |
							"Initialize all columns."
							columns at: columnIndex put: (Array new: listSize).
							"Put the first row in."
							(columns at: columnIndex) at: 1 put: (firstRow at: columnIndex)].
						"Put all other rows in."
						2 to: listSize do: [:rowIndex | (self getListItem: rowIndex)
							withIndexDo: [:item :columnIndex |
								(columns at: columnIndex) at: rowIndex put: item]].
						columns]]].

	self updateColumns.
	
	^ fullList! !

!PluggableMultiColumnListMorph methodsFor: 'updating' stamp: 'ct 8/20/2020 15:00'!
updateColumns
	"The number of columns must match the number of list morphs."
	
	| columnsChanged |
	columnsChanged := self columnCount ~= listMorphs size.
	
	[self columnCount < listMorphs size]
		whileTrue: [
			listMorphs removeLast delete].
	
	[self columnCount > listMorphs size]
		whileTrue: [
			listMorphs addLast: self createListMorph.
			self scroller addMorphBack: listMorphs last].
	
	listMorphs withIndexDo: [:listMorph :columnIndex |
		listMorph
			columnIndex: columnIndex;
			color: self textColor;
			cellPositioning: (self cellPositioningAtColumn: columnIndex);
			cellInset: (self cellInsetAtColumn: columnIndex);
			hResizing: (self hResizingAtColumn: columnIndex);
			spaceFillWeight: (self spaceFillWeightAtColumn: columnIndex)].
		
	columnsChanged ifTrue: [self setListParameters].! !

!PluggableMultiColumnListMorph methodsFor: 'updating' stamp: 'ct 8/20/2020 15:00'!
verifyContents
	"Verify the contents of the receiver, reconstituting if necessary.  Called whenever window is reactivated, to react to possible structural changes.  Also called periodically in morphic if the smartUpdating preference is true"

	| changed currentList modelList modelIndex |
	self flag: #performance. "mt: We do have changed/update. Why can't the tools communicate through an appropriate notifier such as the SystemChangeNotifier?"

	"1) Is the list still up to date?"
	currentList := fullList. fullList := nil.
	modelList := self getFullList.
	changed := false.
	modelList withIndexDo: [:column :index |
		changed := changed or: [(currentList at: index) ~= column]].
	changed ifFalse: [^ self].
	self updateList: modelList.
	
	"2) Is the selection still up to date?"
	modelIndex := self getCurrentSelectionIndex.
	(self modelIndexFor: self selectionIndex) = modelIndex ifTrue: [^ self].
	self updateListSelection: modelIndex.! !


!PluggableMultiColumnListMorphByItem methodsFor: 'model access' stamp: 'ct 8/20/2020 15:00'!
getCurrentSelectionIndex
	"Answer the index of the current selection. Similar to #selection: but with the full list instead of the (maybe) filtered list."

	getIndexSelector ifNil: [^ 0].
	
	(model perform: getIndexSelector) in: [:row |
		row ifNil: [^ 0].
		row ifEmpty: [^ 0].
		
		1 to: self fullListSize do: [:rowIndex |
			| match |
			match := true.
			self getFullList withIndexDo: [:column :columnIndex |
				match := match and: [(column at: rowIndex) = (row at: columnIndex)]].
			match ifTrue: [^ rowIndex]]].
	
	^ 0! !


!PluggableTest methodsFor: 'artist pane' stamp: 'ct 8/20/2020 15:00'!
artistKeystroke: aCharacter

	self artistList withIndexDo: [:artist :i |
		(artist first asLowercase = aCharacter asLowercase) ifTrue: [
			self artist: i]].
! !

!PluggableTest methodsFor: 'music type pane' stamp: 'ct 8/20/2020 15:00'!
musicTypeKeystroke: aCharacter

	musicTypeList withIndexDo: [:type :i |
		(type first asLowercase = aCharacter asLowercase)
			ifTrue: [self musicType: i]].
! !


!PluggableTreeMorph methodsFor: 'node access' stamp: 'ct 8/20/2020 14:59'!
nodesForChildren: aCollection inNode: anObject

	^ aCollection isSequenceable
		ifTrue: [aCollection withIndexCollect: 
			[:item :index |
				self instantiateNodeWithContents: item index: index parent: anObject]]
		ifFalse: [ | count |
			count := 0. "artificial index."
			aCollection collect: 
				[:item |
					count := count + 1.
					self instantiateNodeWithContents: item index: count parent: anObject]]! !


!PolygonMorph methodsFor: 'geometry' stamp: 'ct 8/20/2020 15:00'!
nextDuplicateVertexIndex
	vertices
		withIndexDo: [:vert :index | ((index between: 2 and: vertices size - 1)
					and: [| epsilon v1 v2 | 
						v1 := vertices at: index - 1.
						v2 := vertices at: index + 1.
						epsilon := ((v1 x - v2 x) abs max: (v1 y - v2 y) abs)
									// 32 max: 1.
						vert
							onLineFrom: v1
							to: v2
							within: epsilon])
				ifTrue: [^ index]].
	^ 0! !


!QuickGuideMorph class methodsFor: 'initialization' stamp: 'ct 8/20/2020 15:00'!
getWordyName: guideName forCategory: guideCategory
	"With guideName and category already filled in, make a name in words.  Remove the cat name, and trailing digits.  Separate words at capital letters.  NavBarHowToUse3 -> 'How To Use'  "

	| gn mm tt |
	gn := guideName allButFirst: guideCategory size.
	gn := gn withoutTrailingDigits.
	mm := gn size.
	gn reversed withIndexDo: [:cc :ind | 
		ind < mm  ifTrue: [
			cc isUppercase ifTrue: [ 
				tt := mm + 1 - ind.
				gn := (gn copyFrom: 1 to: tt-1), ' ', (gn copyFrom: tt to: gn size)].
			cc == $- ifTrue: [
				tt := mm + 1 - ind.
				gn at: tt put: $ ].	"convert dash to space"
			]].
	^ gn! !


!ScriptEditorMorph methodsFor: 'dropping/grabbing' stamp: 'ct 8/20/2020 15:00'!
indexOfMorphAbove: aPoint
	"Return index of lowest morph whose bottom is above aPoint.
	Will return 0 if the first morph is not above aPoint"
	submorphs withIndexDo:
		[:m :i | m fullBounds bottom >= aPoint y ifTrue:
					[^ (i max: firstTileRow) - 1]].
	^ submorphs size! !

!ScriptEditorMorph methodsFor: 'other' stamp: 'ct 8/20/2020 15:00'!
reinsertSavedTiles: savedTiles
	"Revert the scriptor to show the saved tiles"

	self submorphs withIndexDo: [:m :i | i > 1 ifTrue: [m delete]].
	self addAllMorphs: savedTiles.
	self allMorphsDo: [:m | m isTileScriptingElement ifTrue: [m bringUpToDate]].
	self install.
	self showingMethodPane: false! !


!SequenceableCollection methodsFor: '*Morphic-NewCurves-cubic support' stamp: 'ct 8/20/2020 14:59'!
segmentedSlopes
	"For a collection of floats. Returns the slopes for straight 
	segments between vertices."
	"last slope closes the polygon. Always return same size as 
	self. "
	^ self
		withIndexCollect: [:x :i | (self atWrap: i + 1)
				- x]! !

!SequenceableCollection methodsFor: '*60Deprecated-enumerating' stamp: 'ct 8/20/2020 14:30'!
collectWithIndex: elementAndIndexBlock

	self deprecated: 'Use #withIndexCollect: instead'.
	^ self withIndexCollect: elementAndIndexBlock! !

!SequenceableCollection methodsFor: '*60Deprecated-enumerating' stamp: 'ct 8/20/2020 14:29'!
doWithIndex: elementAndIndexBlock

	self deprecated: 'Use #withIndexDo: instead'.
	^ self withIndexDo: elementAndIndexBlock! !


!ServerDirectory methodsFor: '*UpdateStream-updating' stamp: 'ct 8/20/2020 15:00'!
putUpdateMulti: list fromDirectory: updateDirectory 
	"Put these files out as an Update on the servers of my group.  List is an array of local file names with or without number prefixes.  Each version of the system has its own set of update files.  'updates.list' holds the master list.  Each update is a fileIn whose name begins with a number.  See Utilities class absorbUpdatesFromServer."

	| myServers updateStrm lastNum response newNames numStr indexPrefix version versIndex listContents |
	(self checkNames: (list collect: "Check the names without their numbers"
		[:each | each copyFrom: (each findFirst: [:c | c isDigit not]) to: each size]))
		ifFalse: [^ nil].
	response := UIManager default chooseFrom: #('Install update' 'Cancel update')
		title: 'Do you really want to broadcast ', list size printString, ' updates',
			'\to every Squeak user who updates from ' withCRs, self groupName, '?'.
	response = 1 ifFalse: [^ nil].	"abort"

	self openGroup.
	indexPrefix := (self groupName includes: $*) 
		ifTrue: [(self groupName findTokens: ' ') first]	"special for internal updates"
		ifFalse: ['']. 	"normal"
	myServers := self checkServersWithPrefix: indexPrefix
					andParseListInto: [:x | listContents := x].
	myServers size = 0 ifTrue: [self closeGroup.  ^ self].

	version := SystemVersion current version.
	versIndex := (listContents collect: [:pair | pair first]) indexOf: version.
	versIndex = 0 ifTrue:
		[self inform: 'There is no section in updates.list for your version'.
		self closeGroup.  ^ nil].	"abort"
	lastNum := (listContents at: versIndex) last last initialIntegerOrNil.
	versIndex < listContents size ifTrue:
		[response := UIManager default chooseFrom: #('Make update for an older version' 'Cancel update')
			title: 'This system, ', SystemVersion current version,
				' is not the latest version'.
		response = 1 ifFalse: [self closeGroup.  ^ nil].
		numStr := UIManager default 
			request: 'Please confirm or change the starting update number' 
			initialAnswer: (lastNum+1) printString.
		lastNum := numStr asNumber - 1].	"abort"
	"Save old copy of updates.list on local disk"
	FileDirectory default deleteFileNamed: indexPrefix , 'updates.list.bk'.
	UpdateStreamDownloader default writeList: listContents toStream: (FileStream fileNamed: indexPrefix , 'updates.list.bk').

	"Append names to updates with new sequence numbers"
	newNames := list with: (lastNum+1 to: lastNum+list size) collect:
		[:each :num | | stripped seq | seq := num printString padded: #left to: 4 with: $0.
		"strip off any old seq number"
		stripped := each copyFrom: (each  findFirst: [:c | c isDigit not]) to: each size.
		seq , stripped].
	listContents at: versIndex put:
		{version. (listContents at: versIndex) second , newNames}.

	"Write a new copy on all servers..."
	updateStrm := ReadStream on:
		(String streamContents: [:s | UpdateStreamDownloader default writeList: listContents toStream: s]).
	myServers do:
		[:aServer |
		list withIndexDo: [:local :ind | | file |
			file := updateDirectory oldFileNamed: local.
			aServer putFile: file named: (newNames at: ind) retry: true.
			file close].
		updateStrm reset.
		aServer putFile: updateStrm named: indexPrefix , 'updates.list' retry: true.
		Transcript show: 'Update succeeded on server ', aServer moniker; cr].
	self closeGroup.

	Transcript cr; show: 'Be sure to test your new update!!'; cr.
	"rename the file locally"
	list with: newNames do:
		[:local :newName | updateDirectory rename: local toBe: newName].
! !


!ServiceGui methodsFor: 'servicecategory' stamp: 'ct 8/20/2020 15:00'!
subMenuFor: aServiceCategory 
	self pushMenu.
	aServiceCategory enabledServices
		ifEmpty: [self menuItemFor: ServiceAction new].
	aServiceCategory enabledServices
		withIndexDo: [:each :i | self n: i. self menuItemFor: each].
	^ self popMenu! !


!ServiceProvider methodsFor: 'persistence' stamp: 'ct 8/20/2020 15:00'!
savePreferencesFor: aService 
	
	"pref := ServicePreferences preferenceAt: aService shortcutPreference.
	strm := WriteStream with: ''.
	strm nextPutAll: aService id;
		 nextPutAll: 'shortcut';
		 cr;
		 tab;
		 nextPutAll: '^ ';
		 nextPutAll: {pref name. pref preferenceValue. 1000} storeString.
	self class compileSilently: strm contents classified: 'saved preferences'."
	aService isCategory
		ifTrue: [aService externalPreferences
				withIndexDo: [:e :i | | strm | 
					strm := WriteStream with: aService id asString.
					strm nextPutAll: e id asString;
						 cr;
						 tab;
						 nextPutAll: '^ ';
						 nextPutAll: {aService childrenPreferences. e id. i} storeString.
					e provider class compileSilently: strm contents classified: 'saved preferences']]! !


!SetInspector methodsFor: 'private' stamp: 'ct 8/20/2020 15:00'!
elementIndices
	"In the set's internal array, extract the indices that point to actual elements."
	
	| numIndices |
	(numIndices := self objectSize) = 0
		ifTrue: [^#()].
	
	^ Array
		new: numIndices
		streamContents: [:stream |
			self object array withIndexDo: [:element :index |
				(self isElementValid: element) ifTrue: [stream nextPut: index]]]! !


!SmalltalkImage methodsFor: '*Etoys-Squeakland-system attribute' stamp: 'ct 8/20/2020 14:59'!
macVmMajorMinorBuildVersion	
	"SmalltalkImage current macVmMajorMinorBuildVersion"
	| aString rawTokens versionPart versionTokens versionArray |
	aString := self vmVersion.
	aString ifNil: [^ #(0 0 0)].
	rawTokens := ((aString copyAfterLast: $])
				findTokens: $ ).
	versionPart := rawTokens detect: [:each | each includes: $.] ifNone: [^#(0 0 0)]. 
	versionTokens := versionPart findTokens: $..
	versionArray := #(0 0 0) withIndexCollect: [:each :index |
		(versionTokens at: index ifAbsent:['']) initialIntegerOrNil ifNil: [each]].
	^versionArray! !


!SmartRefStream methodsFor: 'class changed shape' stamp: 'ct 8/20/2020 15:00'!
storeInstVarsIn: anObject from: dict
	"For instance variables with the same names, store them in the new instance.  Values in variable-length part also.  This is NOT the normal inst var transfer!!  See Object.readDataFrom:size:.  This is for when inst var names have changed and some additional conversion is needed.  Here we handle the unchanged vars.  "

	(anObject class allInstVarNames) withIndexDo: [:varName :index |
		(dict includesKey: varName) ifTrue: [
			anObject instVarAt: index put: (dict at: varName)]].
	"variable part"
	(dict includesKey: #SizeOfVariablePart) ifFalse: [^ anObject].
	1 to: (dict at: #SizeOfVariablePart) do: [:index | 
		anObject basicAt: index put: (dict at: index)].
	^ anObject! !


!StackMorph methodsFor: 'menu' stamp: 'ct 8/20/2020 15:00'!
getAllText
	"Collect the text for each card.  Just point at strings so don't have to recopy them.  (Parallel array of urls for ID of cards.  Remote cards not working yet.)
	allText = Array (cards size) of arrays (fields in it) of strings of text.
	allTextUrls = Array (cards size) of urls or card numbers."

	| oldUrls oldStringLists allText allTextUrls |
	self writeSingletonData.
	oldUrls := self valueOfProperty: #allTextUrls ifAbsent: [#()].
	oldStringLists := self valueOfProperty: #allText ifAbsent: [#()].
	allText := self privateCards collect: [:pg | OrderedCollection new].
	allTextUrls := Array new: self privateCards size.
	self privateCards withIndexDo: [:aCard :ind | | aUrl which |
		aUrl := aCard url.  aCard isInMemory 
			ifTrue: [(allText at: ind) addAll: (aCard allStringsAfter: nil).
				aUrl ifNil: [aUrl := ind].
				allTextUrls at: ind put: aUrl]
			ifFalse: ["Order of cards on server may be different.  (later keep up to date?)"
				"*** bug in this algorithm if delete a page?"
				which := oldUrls indexOf: aUrl.
				allTextUrls at: ind put: aUrl.
				which = 0 ifFalse: [allText at: ind put: (oldStringLists at: which)]]].
	self setProperty: #allText toValue: allText.
	self setProperty: #allTextUrls toValue: allTextUrls.
	^ allText! !


!StandardFileMenu methodsFor: 'menu building' stamp: 'ct 8/20/2020 15:00'!
menuSelectionsArray: aDirectory
"Answer a menu selections object corresponding to aDirectory.  The object is an array corresponding to each item, each element itself constituting a two-element array, the first element of which contains a selector to operate on and the second element of which contains the parameters for that selector."

	|dirSize|
	dirSize := aDirectory pathParts size.
	^Array streamContents: [:s |
		canTypeFileName ifTrue:
			[s nextPut: (StandardFileMenuResult
				directory: aDirectory
				name: nil)].
		s nextPut: (StandardFileMenuResult
			directory: (FileDirectory root)
			name: '').
		aDirectory pathParts withIndexDo: 
			[:d :i | s nextPut: (StandardFileMenuResult
					directory: (self 
						advance: dirSize - i
						containingDirectoriesFrom: aDirectory)
					name: '')].
		aDirectory directoryNames do: 
			[:dn |  s nextPut: (StandardFileMenuResult
						directory: (FileDirectory on: (aDirectory fullNameFor: dn))
						name: '')].
		aDirectory fileNames do: 
			[:fn | pattern do: [:pat | (pat match: fn) ifTrue: [
					s nextPut: (StandardFileMenuResult
						directory: aDirectory
						name: fn)]]]]! !

!StandardFileMenu methodsFor: 'menu building' stamp: 'ct 8/20/2020 15:00'!
pathPartsString: aDirectory
"Answer a string concatenating the path parts strings in aDirectory, each string followed by a cr."

	^String streamContents:
		[:s | 
			s nextPutAll: '[]'; cr.
			aDirectory pathParts asArray withIndexDo: 
				[:part :i |
					s next: i put: $ .
					s nextPutAll: part withBlanksTrimmed; cr]]! !


!String methodsFor: 'converting' stamp: 'ct 8/20/2020 15:00'!
compressWithTable: tokens
	"Return a string with all substrings that occur in tokens replaced
	by a character with ascii code = 127 + token index.
	This will work best if tokens are sorted by size.
	Assumes this string contains no characters > 127, or that they
	are intentionally there and will not interfere with this process."
	| str null finalSize result ri c |
	null := Character null.
	str := self copyFrom: 1 to: self size.  "Working string will get altered"
	finalSize := str size.
	tokens withIndexDo:
		[:token :tIndex |
		| start ts |
		start := 1.
		[(start := str findString: token startingAt: start) > 0]
			whileTrue:
			[ts := token size.
			((start + ts) <= str size
				and: [(str at: start + ts) = $  and: [tIndex*2 <= 128]])
				ifTrue: [ts := token size + 1.  "include training blank"
						str at: start put: (Character value: tIndex*2 + 127)]
				ifFalse: [str at: start put: (Character value: tIndex + 127)].
			str at: start put: (Character value: tIndex + 127).
			1 to: ts-1 do: [:i | str at: start+i put: null].
			finalSize := finalSize - (ts - 1).
			start := start + ts]].
	result := String new: finalSize.
	ri := 0.
	1 to: str size do:
		[:i | (c := str at: i) = null ifFalse: [result at: (ri := ri+1) put: c]].
	^ result! !


!StringType methodsFor: 'initialization' stamp: 'ct 8/20/2020 14:59'!
initialize
	"Initialize the receiver (automatically called when instances are created via 'new')"

	
	super initialize.
	self vocabularyName: #String.

#((accessing 			'The basic info'
		(at: at:put: size endsWithDigit findString: findTokens: includesSubstring: indexOf: indexOf:startingAt: indexOf:startingAt:ifAbsent: lineCorrespondingToIndex: lineCount lineNumber: startsWithDigit numArgs))
(#'more accessing' 		'More basic info'
		(allButFirst allButFirst: allButLast allButLast: at:ifAbsent: atAllPut: atPin: atRandom: atWrap: atWrap:put: fifth first first: fourth from:to:put: last last: lastIndexOf: lastIndexOf:ifAbsent: middle replaceAll:with: replaceFrom:to:with: replaceFrom:to:with:startingAt: second sixth third))
(comparing				'Determining which comes first alphabeticly'
		(< <= = > >= beginsWith: endsWith: endsWithAnyOf: howManyMatch: match:))
(testing 				'Testing'
		(includes: isEmpty ifNil: ifNotNil: isAllDigits isAllSeparators isString lastSpacePosition))
(converting 			'Converting it to another form'
		(asCharacter asDate asInteger asLowercase asNumber asString asStringOrText asSymbol asText asTime asUppercase asUrl capitalized keywords numericSuffix romanNumber reversed splitInteger surroundedBySingleQuotes withBlanksTrimmed withSeparatorsCompacted withoutTrailingBlanks withoutTrailingDigits asSortedCollection))
(copying 				'Make another one like me'
		(copy copyFrom:to: copyUpTo: copyUpToLast: shuffled))
(enumerating		'Passing over the letters'
		(collect: withIndexCollect: do: from:to:do: reverseDo: select: withIndexDo: detect: detect:ifNone:))
) do: [:item | | aMethodCategory | 
			aMethodCategory := ElementCategory new categoryName: item first.
			aMethodCategory documentation: item second.
			item third do:
				[:aSelector | | aMethodInterface | 
					aMethodInterface := MethodInterface new initializeFor: aSelector.
					self atKey: aSelector putMethodInterface: aMethodInterface.
					aMethodCategory elementAt: aSelector put: aMethodInterface].
			self addCategory: aMethodCategory].
! !


!TabSorterMorph methodsFor: 'buttons' stamp: 'ct 8/20/2020 15:00'!
acceptSort
	"Reconstitute the palette based on what is found in the sorter"

	| rejects oldOwner tabsToUse oldTop |
	tabsToUse := OrderedCollection new.
	rejects := OrderedCollection new.
	pageHolder submorphs withIndexDo: 
			[:m :i | | appearanceMorph toAdd aMenu | 
			toAdd := nil.
			(m isKindOf: BookMorph) ifTrue: [toAdd := SorterTokenMorph forMorph: m].
			(m isKindOf: SorterTokenMorph) 
				ifTrue: 
					[toAdd := m morphRepresented.
					(toAdd referent isKindOf: MenuMorph) 
						ifTrue: 
							[(aMenu := toAdd referent) setProperty: #paletteMenu toValue: true.
							(aMenu submorphs size > 1 and: 
									[(aMenu submorphs second isKindOf: MenuItemMorph) 
										and: [aMenu submorphs second contents = 'dismiss this menu']]) 
								ifTrue: 
									[aMenu submorphs first delete.	"delete title"
									aMenu submorphs first delete.	"delete stay-up item"
									(aMenu submorphs first knownName = #line) 
										ifTrue: [aMenu submorphs first delete]]].
					toAdd removeAllMorphs.
					toAdd addMorph: (appearanceMorph := m submorphs first).
					appearanceMorph position: toAdd position.
					appearanceMorph lock.
					toAdd fitContents].
			toAdd ifNil: [rejects add: m] ifNotNil: [tabsToUse add: toAdd]].
	tabsToUse isEmpty 
		ifTrue: [^self inform: 'Sorry, must have at least one tab'].
	book newTabs: tabsToUse.
	book tabsMorph color: pageHolder color.
	oldTop := self topRendererOrSelf.	"in case some maniac has flexed the sorter"
	oldOwner := oldTop owner.
	oldTop delete.
	oldOwner addMorphFront: book! !


!TextEditor methodsFor: 'attributes' stamp: 'ct 8/20/2020 14:59'!
changeEmphasisOrAlignment
	| aList reply  code align menuList startIndex |
	startIndex := self startIndex.
	aList := #(normal bold italic narrow underlined struckOut leftFlush centered rightFlush justified).	
	align := paragraph text alignmentAt: startIndex 
		ifAbsent: [ paragraph textStyle alignment ].
	code := paragraph text emphasisAt: startIndex.
	menuList := WriteStream on: Array new.
	menuList nextPut: (code isZero ifTrue:['<on>'] ifFalse:['<off>']), 'normal' translated.
	menuList nextPutAll: (#(bold italic underlined struckOut) collect:[:emph|
		(code anyMask: (TextEmphasis perform: emph) emphasisCode)
			ifTrue: [ '<on>', emph asString translated ]
			ifFalse: [ '<off>',emph asString translated ]]).
	((paragraph text attributesAt: startIndex)
		anySatisfy: [ :attr | attr isKern and: [attr kern < 0 ]]) 
			ifTrue: [ menuList nextPut:'<on>', 'narrow' translated ]
			ifFalse: [ menuList nextPut:'<off>', 'narrow' translated ].
	menuList nextPutAll: (#(leftFlush centered rightFlush justified) withIndexCollect: [ :type :i |
		align = (i-1)
			ifTrue: [ '<on>',type asString translated ]
			ifFalse: [ '<off>',type asString translated ]]).
	aList := #(normal bold italic underlined struckOut narrow leftFlush centered rightFlush justified).
	reply := UIManager default chooseFrom: menuList contents values: aList lines: #(1 6).
	reply notNil ifTrue: [
		(#(leftFlush centered rightFlush justified) includes: reply)
			ifTrue: [
				self setAlignment: reply.
				paragraph composeAll.
				self recomputeSelection]
			ifFalse: [
				self setEmphasis: reply.
				paragraph composeAll.
				self recomputeSelection]].
	^ true! !


!SequenceableCollection reorganize!
('accessing' after: after:ifAbsent: allButFirst allButFirst: allButLast allButLast: any: anyOne at:ifPresent:ifAbsent: atAllPut: atAll: atAll:putAll: atAll:put: atLast: atLast:ifAbsent: atLast:put: atPin: atRandom: atWrap: atWrap:put: at:ifAbsent: at:incrementBy: before: before:ifAbsent: eighth fifth first first: fourth from:to:put: identityIndexOf: identityIndexOf:ifAbsent: identityIndexOf:startingAt: identityIndexOf:startingAt:ifAbsent: indexOf:startingAt: indexOfAnyOf: indexOfAnyOf:ifAbsent: indexOfAnyOf:startingAt: indexOfAnyOf:startingAt:ifAbsent: indexOfSubCollection: indexOfSubCollection:startingAt: indexOfSubCollection:startingAt:ifAbsent: indexOf: indexOf:ifAbsent: indexOf:startingAt:ifAbsent: indicesOfSubCollection: indicesOfSubCollection:startingAt: integerAt: integerAt:put: last lastIndexOf: lastIndexOf:ifAbsent: lastIndexOf:startingAt: lastIndexOf:startingAt:ifAbsent: last: lastIndexOfAnyOf: lastIndexOfAnyOf:ifAbsent: lastIndexOfAnyOf:startingAt: lastIndexOfAnyOf:startingAt:ifAbsent: middle ninth replaceAll:with: replaceFrom:to:with: replaceFrom:to:with:startingAt: second seventh sixth size swap:with: third)
('comparing' hasEqualElements: hash =)
('converting' asArray asByteArray asColorArray asFloa32tArray asFloat32Array asFloat64Array asFloatA64rray asFloatArray asIntegerArray asStringWithCr asWordArray concatenation flatten flattened join joinSeparatedBy: readStream reverse reverseInPlace reversed writeStream @)
('copying' copyAfterLast: copyAfter: copyEmpty copyFrom:to: copyLast: copyReplaceAll:with: copyReplaceFrom:to:with: copyUpThrough: copyUpToLast: copyUpTo: copyWithFirst: copyWithoutFirst copyWithoutIndex: copyWith: forceTo:paddingStartWith: forceTo:paddingWith: grownBy: , withoutDuplicates)
('enumerating' allButFirstDo: allButLastDo: asDigitsToPower:do: collect: collect:from:to: combinations:atATimeDo: do: do:separatedBy: do:without: findBinary:do:ifNone: findBinaryIndex: findBinaryIndex:do:ifNone: findBinaryIndex:ifNone: findBinary: findBinary:ifNone: findFirst: findLast: findLast:startingAt: findNearbyBinaryIndex: from:to:do: groupsDo: groupsOf:atATimeCollect: groupsOf:atATimeDo: keysAndValuesDo: nextToLast overlappingPairsCollect: overlappingPairsDo: overlappingPairsWithIndexDo: paddedWith:do: pairsCollect: pairsDo: permutationsDo: piecesCutWhere: piecesCutWhere:do: polynomialEval: replace: reverseDo: reverseWith:do: select: splitBy: splitBy:do: upTo: withIndexCollect: withIndexDo: with:collect: with:do:)
('removing' remove:ifAbsent:)
('testing' beginsWith: beginsWithAnyOf: endsWith: endsWithAnyOf: includes: isSequenceable)
('*services-base' startsWith:)
('*Traits' asTraitComposition)
('private' asDigitsAt:in:do: checkedAt: combinationsAt:in:after:do: copyReplaceAll:with:asTokens: errorFirstObject: errorLastObject: errorOutOfBounds permutationsStartingAt:do:)
('*Morphic-NewCurves-cubic support' asCubic assertSlopesWith:from:to: changeInSlopes: changeOfChangesInSlopes: closedCubicSlopes closedCubicSlopes: closedFillinList cubicPointPolynomialAt: naturalCubicSlopes naturalCubicSlopes: naturalFillinList nilTransitions segmentedSlopes slopesWith:from:to: transitions transitions:)
('*Morphic-fliprotate' flipRotated:)
('*Morphic-Explorer' explorerContents)
('filter streaming' putOn:)
('shuffling' shuffle shuffleBy: shuffled shuffledBy:)
('*Balloon' asPointArray)
('adding' addAllFirstTo:)
('*51Deprecated-copying')
('*Etoys-Squeakland-accessing' customizeExplorerContents)
('printing' joinOn: joinOn:separatedBy:)
('*60Deprecated-enumerating' collectWithIndex: doWithIndex:)
!

