'From Cuis 1.0 of 14 April 2009 [latest update: #182] on 19 April 2009 at 7:00:45 pm'!
!classDefinition: #String category: #'Kernel-Text'!
ArrayedCollection variableByteSubclass: #String
	instanceVariableNames: ''
	classVariableNames: 'AsciiOrder CSLineEnders CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder HtmlEntities LowercasingTable Tokenish UppercasingTable Latin1ToUtf8Encodings Latin1ToUtf8Map '
	poolDictionaries: ''
	category: 'Kernel-Text'!

!Character methodsFor: 'converting' stamp: 'jmv 4/18/2009 07:45'!
latin1ToMacRoman
	"Convert the receiver from ISO 8895-1 Latin-1 to MacRoman encoding."
	
	value < 128 ifTrue: [^ self].
	^ Character value: (Character latin1ToMacRoman: value)! !

!Character methodsFor: 'converting' stamp: 'jmv 4/19/2009 19:00'!
macRomanToLatin1
	"Convert the receiver from MacRoman to  ISO 8895-1 Latin-1 encoding"
	
	value < 128 ifTrue: [^ self].
	^ Character value: (Character macRomanToLatin1: value)! !


!Character class methodsFor: 'converting' stamp: 'jmv 4/18/2009 07:45'!
latin1ToMacRoman: charCode
	"Convert the receiver from ISO 8895-1 Latin-1 to MacRoman encoding."
	
	charCode < 128 ifTrue: [^ charCode].
	^ #(
		173 176 226 196 227 201 160 224 246 228 178 220 206 179 182 183	"80-8F"
		184 212 213 210 211 165 208 209 247 170 185 221 207 186 189 217		"90-9F"
		202 193 162 163 219 180 195 164 172 169 187 199 194 197 168 248	"	A0-AF"
		161 177 198 215 171 181 166 225 252 218 188 200 222 223 240 192 	"B0-BF"
		203 231 229 204 128 129 174 130 233 131 230 232 237 234 235 236 	"C0-CF"
		245 132 241 238 239 205 133 249 175 244 242 243 134 250 251 167	"D0-DF"
		136 135 137 139 138 140 190 141 143 142 144 145 147 146 148 149		"E0-EF"
		253 150 152 151 153 155 154 214 191 157 156 158 159 254 255 216		"F0-FF"
	) at: charCode - 127! !

!Character class methodsFor: 'converting' stamp: 'jmv 4/18/2009 07:43'!
macRomanToLatin1: charCode
	"Convert the receiver from MacRoman to  ISO 8895-1 Latin-1 encoding"
	
	charCode < 128 ifTrue: [^ charCode].
	^ #(
		196 197 199 201 209 214 220 225 224 226 228 227 229 231 233 232 
		234 235 237 236 238 239 241 243 242 244 246 245 250 249 251 252 
		134 176 162 163 167 149 182 223 174 169 153 180 168 128 198 216 
		129 177 138 141 165 181 142 143 144 154 157 170 186 158 230 248 
		191 161 172 166 131 173 178 171 187 133 160 192 195 213 140 156 
		150 151 147 148 145 146 247 179 255 159 185 164 139 155 188 189 
		135 183 130 132 137 194 202 193 203 200 205 206 207 204 211 212 
		190 210 218 219 217 208 136 152 175 215 221 222 184 240 253 254
	) at: charCode - 127! !


!Clipboard methodsFor: 'accessing' stamp: 'jmv 4/18/2009 07:02'!
clipboardText
	"Return the text currently in the clipboard. If the system clipboard is empty, or if it differs from the Smalltalk clipboard text, use the Smalltalk clipboard. This is done since (a) the Mac clipboard gives up on very large chunks of text and (b) since not all platforms support the notion of a clipboard."

	| latin1Format |
	"Windows uses UTF-8 for clipboard. Other platforms use MacRoman"
	latin1Format _ Smalltalk platformName = 'Win32'
		ifTrue: [ self primitiveClipboardText utf8ToLatin1 ]
		ifFalse: [ self primitiveClipboardText macRomanToLatin1 ].
	(latin1Format isEmpty or: [latin1Format = contents asString])
		ifTrue: [^ contents]
		ifFalse: [^ latin1Format asText]! !

!Clipboard methodsFor: 'accessing' stamp: 'jmv 4/18/2009 07:03'!
clipboardText: text
	"Set text currently on the clipboard.  Also export to OS"
	| primitiveFormat |
	contents _ text.
	self noteRecentClipping: text asText.
	"Windows uses UTF-8 for clipboard. Other platforms use MacRoman"
	primitiveFormat _ Smalltalk platformName = 'Win32'
		ifTrue: [ text asString latin1ToUtf8 ]
		ifFalse: [ text asString latin1ToMacRoman ].
	self primitiveClipboardText: primitiveFormat! !

!Clipboard methodsFor: 'primitives' stamp: 'jmv 4/17/2009 22:47'!
primitiveClipboardText
	"Get the current clipboard text. Return the empty string if the primitive fails.
	Warning: Returns a String, not a Text!!"
	<primitive: 141>
	^ ''! !


!HandMorph methodsFor: 'private events' stamp: 'jmv 4/18/2009 07:47'!
generateKeyboardEvent: evtBuf 
	"Generate the appropriate mouse event for the given raw event buffer"

	| buttons modifiers type keyValue pressType stamp |
	stamp _ evtBuf second.
	stamp = 0 ifTrue: [stamp _ Time millisecondClockValue].
	keyValue _ Character macRomanToLatin1: evtBuf third.
	pressType _ evtBuf fourth.
	pressType = EventKeyDown ifTrue: [type _ #keyDown].
	pressType = EventKeyUp ifTrue: [type _ #keyUp].
	pressType = EventKeyChar ifTrue: [type _ #keystroke].
	modifiers _ evtBuf fifth.
	buttons _ modifiers bitShift: 3.
	^KeyboardEvent new 
		setType: type
		buttons: buttons
		position: self position
		keyValue: keyValue
		hand: self
		stamp: stamp! !


!MethodFinder methodsFor: 'initialize' stamp: 'jmv 4/17/2009 22:31'!
initialize2
	"The methods we are allowed to use.  (MethodFinder new initialize) "

"Set"
	#("in class" sizeFor:
"testing" "adding" "removing" "enumerating"
"private" array findElementOrNil: 
"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" allCharacters 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" 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 asLegalSelector asPacked asText asTime capitalized compressWithTable: contractTo: correctAgainst: 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].

"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 addLast:times: 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:	) 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 ) (ifKindOf:thenDo: 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 ) (sortBy: 1 ) (and: 1 ) (asSortedCollection: 1 ) (with:collect: 2 ) (sourceCodeAt:ifAbsent: 2 ) (detect: 1 ) (scopeHas:ifTrue: 2 ) (collectWithIndex: 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"
! !


!String methodsFor: 'converting' stamp: 'jmv 4/18/2009 06:49'!
latin1ToMacRoman
	^ self collect: [:each | each latin1ToMacRoman]! !

!String methodsFor: 'converting' stamp: 'jmv 4/18/2009 08:17'!
latin1ToUtf8
	"Convert the given string from UTF-8 using the fast path if converting to Latin-1"
	"Originally by Andreas Raab, as #squeakToUtf8"
	
	| outStream lastIndex nextIndex |
	lastIndex := 1.
	nextIndex := String findFirstInString: self inSet: Latin1ToUtf8Map startingAt: lastIndex.
	nextIndex = 0 ifTrue:[^self].
	outStream := (String new: self size * 2) writeStream.
	[
		outStream next: nextIndex-lastIndex putAll: self startingAt: lastIndex.
		outStream nextPutAll: (Latin1ToUtf8Encodings at: (self byteAt: nextIndex)+1).
		lastIndex := nextIndex + 1.
		nextIndex := String findFirstInString: self inSet: Latin1ToUtf8Map startingAt: lastIndex.
		nextIndex = 0] whileFalse.
	outStream next: self size-lastIndex+1 putAll: self startingAt: lastIndex.
	^outStream contents
! !

!String methodsFor: 'converting' stamp: 'jmv 4/18/2009 06:51'!
macRomanToLatin1

	^self collect: [:c | c macRomanToLatin1 ]! !

!String methodsFor: 'converting' stamp: 'jmv 4/18/2009 08:24'!
utf8ToLatin1
	"Convert the given string from UTF-8 using the fast path if converting to Latin-1"
	"Originally by Andreas Raab as #utf8ToSqueak
	(this version does notsupport unicode chars outside the Latin-1 range: 0..255,
	but the code for doing it is there. we just don't create Characters with values > 255)"
	
	| outStream lastIndex nextIndex byte1 byte2 byte3 byte4 unicode |
	lastIndex := 1.
	nextIndex := String findFirstInString: self inSet: Latin1ToUtf8Map startingAt: lastIndex.
	nextIndex = 0 ifTrue:[^self].
	outStream := (String new: self size) writeStream.
	[
		outStream next: nextIndex-lastIndex putAll: self startingAt: lastIndex.
		byte1 := self byteAt: nextIndex.
		(byte1 bitAnd: 16rE0) = 192 ifTrue: [ "two bytes"
			byte2 := self byteAt: (nextIndex := nextIndex+1).
			(byte2 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			unicode := ((byte1 bitAnd: 31) bitShift: 6) + (byte2 bitAnd: 63)].
		(byte1 bitAnd: 16rF0) = 224 ifTrue: [ "three bytes"
			byte2 := self byteAt: (nextIndex := nextIndex+1).
			(byte2 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			byte3 := self byteAt: (nextIndex := nextIndex+1).
			(byte3 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			unicode := ((byte1 bitAnd: 15) bitShift: 12) + ((byte2 bitAnd: 63) bitShift: 6)
				+ (byte3 bitAnd: 63)].
		(byte1 bitAnd: 16rF8) = 240 ifTrue: [ "four bytes"
			byte2 := self byteAt: (nextIndex := nextIndex+1).
			(byte2 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			byte3 := self byteAt: (nextIndex := nextIndex+1).
			(byte3 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			byte4 := self byteAt: (nextIndex := nextIndex+1).
			(byte4 bitAnd: 16rC0) = 16r80 ifFalse:[^self]. "invalid UTF-8; presume Latin-1"
			unicode := ((byte1 bitAnd: 16r7) bitShift: 18) +
							((byte2 bitAnd: 63) bitShift: 12) + 
							((byte3 bitAnd: 63) bitShift: 6) +
							(byte4 bitAnd: 63)].
		unicode ifNil:[^self]. "invalid UTF-8; presume Latin-1"
		unicode > 255 ifTrue: [^self].										"We do not support chars above 255 in Cuis"
		outStream nextPut: (Character value: unicode).
		lastIndex := nextIndex + 1.
		nextIndex := String findFirstInString: self inSet: Latin1ToUtf8Map startingAt: lastIndex.
		nextIndex = 0] whileFalse.
	outStream next: self size-lastIndex+1 putAll: self startingAt: lastIndex.
	^outStream contents
! !


!String class methodsFor: 'initialization' stamp: 'jmv 4/18/2009 06:39'!
initialize   "String initialize"

	| order |
	AsciiOrder _ (0 to: 255) as: ByteArray.

	CaseInsensitiveOrder _ AsciiOrder copy.
	($a to: $z) do:
		[:c | CaseInsensitiveOrder at: c asciiValue + 1
				put: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)].

	"Case-sensitive compare sorts space, digits, letters, all the rest..."
	CaseSensitiveOrder _ ByteArray new: 256 withAll: 255.
	order _ -1.
	' 0123456789' do:  "0..10"
		[:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].
	($a to: $z) do:     "11-64"
		[:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order _ order+1).
		CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].
	1 to: CaseSensitiveOrder size do:
		[:i | (CaseSensitiveOrder at: i) = 255 ifTrue:
			[CaseSensitiveOrder at: i put: (order _ order+1)]].
	order = 255 ifFalse: [self error: 'order problem'].

	"a table for translating to lower case"
	LowercasingTable _ String withAll: (Character allCharacters collect: [:c | c asLowercase]).

	"a table for translating to upper case"
	UppercasingTable _ String withAll: (Character allCharacters collect: [:c | c asUppercase]).

	"a table for testing tokenish (for fast numArgs)"
	Tokenish _ String withAll: (Character allCharacters collect:
									[:c | c tokenish ifTrue: [c] ifFalse: [$~]]).

	"CR and LF--characters that terminate a line"
	CSLineEnders _ CharacterSet empty.
	CSLineEnders add: Character cr.
	CSLineEnders add: Character lf.

 	"separators and non-separators"
	CSSeparators _ CharacterSet separators.
	CSNonSeparators _ CSSeparators complement.
	
	"UTF-8 support for VM interface for clipboard, files and directories at least on Windows"
	self initializeUtf8ConversionMaps! !

!String class methodsFor: 'initialization' stamp: 'jmv 4/18/2009 11:05'!
initializeUtf8ConversionMaps
	"Originally by Andreas Raab"

	| utf8 |
	Latin1ToUtf8Map _ (ByteArray new: 128 withAll: 0), (ByteArray new: 128 withAll: 1).
	Latin1ToUtf8Encodings _ Array new: 256.
	128 to: 191 do: [ :i |
		utf8 _ (ByteArray with: 194 with: i) asString.
		Latin1ToUtf8Encodings at: i+1 put: utf8.
		utf8 _ (ByteArray with: 195 with: i) asString.
		Latin1ToUtf8Encodings at: i+64+1 put: utf8.
	].! !

Text removeSelector: #isoToSqueak!
Text removeSelector: #squeakToIso!
String initialize!
String class removeSelector: #initializeHtmlEntities!
String removeSelector: #asIRCLowercase!
String removeSelector: #escapeEntities!
String removeSelector: #isoToSqueak!
String removeSelector: #isoToUtf8!
String removeSelector: #squeakToIso!
String removeSelector: #utf8ToIso!
!classDefinition: #String category: #'Kernel-Text'!
ArrayedCollection variableByteSubclass: #String
	instanceVariableNames: ''
	classVariableNames: 'AsciiOrder CSLineEnders CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder Latin1ToUtf8Encodings Latin1ToUtf8Map LowercasingTable Tokenish UppercasingTable'
	poolDictionaries: ''
	category: 'Kernel-Text'!

!String reorganize!
('accessing' at: at:put: byteAt: byteAt:put: byteSize do:toFieldNumber: endsWithDigit findAnySubStr:startingAt: findBetweenSubStrs: findCloseParenthesisFor: findDelimiters:startingAt: findString: findString:startingAt: findString:startingAt:caseSensitive: findTokens: findTokens:includes: findTokens:keep: findWordStart:startingAt: includesSubString: includesSubstring:caseSensitive: indexOf: indexOf:startingAt: indexOf:startingAt:ifAbsent: indexOfAnyOf: indexOfAnyOf:ifAbsent: indexOfAnyOf:startingAt: indexOfAnyOf:startingAt:ifAbsent: indexOfSubCollection:startingAt:ifAbsent: lastIndexOfPKSignature: lineCorrespondingToIndex: lineCount lineNumber: linesDo: skipAnySubStr:startingAt: skipDelimiters:startingAt: startsWithDigit tabDelimitedFieldsDo:)
('comparing' < <= = > >= alike: beginsWith: caseInsensitiveLessOrEqual: caseSensitiveLessOrEqual: charactersExactlyMatching: compare: crc16 endsWith: endsWithAnyOf: hash hashMappedBy: howManyMatch: match: sameAs: startingAt:match:startingAt:)
('copying' copyReplaceTokens:with: deepCopy padded:to:with:)
('converting' adaptToCollection:andSend: adaptToNumber:andSend: adaptToPoint:andSend: adaptToString:andSend: asCharacter asDate asDateAndTime asDisplayText asDuration asFileName asFourCode asHex asIdentifier: asInteger asLegalSelector asLowercase asMorph asNumber asPacked asParagraph asSignedInteger asSmalltalkComment asString asStringOrText asSymbol asText asTime asTimeStamp asUppercase askIfAddStyle:req: capitalized compressWithTable: contractTo: correctAgainst: correctAgainst:continuedFrom: correctAgainstDictionary:continuedFrom: findSelector initialIntegerOrNil keywords latin1ToMacRoman latin1ToUtf8 macRomanToLatin1 numericSuffix onlyLetters openAsMorph periodPrefixAndSuffix romanNumber sansPeriodSuffix splitInteger stemAndNumericSuffix substrings surroundedBySingleQuotes translateFrom:to:table: translateToLowercase translateToUppercase translateWith: truncateTo: truncateWithElipsisTo: unparenthetically unzipped utf8ToLatin1 withBlanksCondensed withBlanksTrimmed withFirstCharacterDownshifted withNoLineLongerThan: withSeparatorsCompacted withoutLeadingDigits withoutTrailingBlanks withoutTrailingDigits)
('displaying' displayAt: displayOn: displayOn:at: displayOn:at:textColor: displayProgressAt:from:to:during:)
('printing' encodeDoublingQuoteOn: isLiteral printOn: storeOn: stringRepresentation)
('private' correctAgainstEnumerator:continuedFrom: evaluateExpression:parameters: getEnclosedExpressionFrom: replaceFrom:to:with:startingAt: stringhash)
('system primitives' compare:with:collated: findSubstring:in:startingAt:matchTable: numArgs)
('Celeste' withCRs)
('internet' decodeMimeHeader decodeQuotedPrintable unescapePercents withInternetLineEndings withSqueakLineEndings withoutQuoting)
('testing' hasContentsInExplorer isAllDigits isAllSeparators isString lastSpacePosition)
('paragraph support' indentationIfBlank:)
('arithmetic' * + - / // \\)
('filter streaming' byteEncode: putOn:)
('encoding' getInteger32: putInteger32:at:)
('user interface' asExplorerString openInWorkspaceWithTitle:)
('Camp Smalltalk' sunitAsSymbol sunitMatch: sunitSubStrings)
('translating' translated)
('formatting' format:)
('*swhttpclient' trimBlanks)
!

Character removeSelector: #asIRCLowercase!
Character removeSelector: #escapeEntities!
Character removeSelector: #isoToSqueak!
Character removeSelector: #squeakToIso!

!Character reorganize!
('accessing' asciiValue digitValue)
('comparing' < = > hash)
('testing' isAlphaNumeric isDigit isLetter isLowercase isSafeForHTTP isSeparator isSpecial isUppercase isVowel tokenish)
('copying' clone copy deepCopy veryDeepCopyWith:)
('printing' hex isLiteral printOn: printOnStream: storeOn:)
('converting' asCharacter asInteger asLowercase asString asSymbol asText asUppercase latin1ToMacRoman macRomanToLatin1 to:)
('object fileIn' comeFullyUpOnReload: objectForDataStream:)
!

