StringCollection.st
author claus
Mon, 06 Feb 1995 00:38:45 +0100
changeset 235 d8e62525bfdf
parent 203 3d88fa870de0
child 246 f13be3ba45a0
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1989 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

VariableArray subclass:#Text
       instanceVariableNames:''
       classVariableNames:''
       poolDictionaries:''
       category:'Collections-Text'
!

Text comment:'
COPYRIGHT (c) 1989 by Claus Gittinger
	      All Rights Reserved

$Header: /cvs/stx/stx/libbasic/StringCollection.st,v 1.11 1995-02-05 23:38:42 claus Exp $
'!

!Text class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1989 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

version
"
$Header: /cvs/stx/stx/libbasic/StringCollection.st,v 1.11 1995-02-05 23:38:42 claus Exp $
"
!

documentation
"
    Text is an array of lines which are strings.
    WARNING:
	This class is temporary (a historic leftover) - it may change or
	even vanish in the future. Use OrderedCollections or other standard
	classes to represent collections of strings.

    Also, Text is a very bad name - there is something totally different 
    also named Text in ST-80 ...

    So, even if kept, it will be definitely be renamed to something like
    StringCollection in one of the next versions.
"
! !

!Text class methodsFor:'instance creation'!

from:aString
    "return a new text object with lines taken from the argument, aString"

    ^ (self new:1) from:aString
!

fromArray:anArray
    "return a new text object with lines taken from the argument, an array
     of strings"

    |newText
     size "{ Class: SmallInteger }" |

    size := anArray size.
    newText := self new:size.
    1 to:size do:[:line |
	newText at:line put:(anArray at:line)
    ].
    ^ newText
! !

!Text methodsFor:'growing'!

grow:newSize
    "grow to newsize - new elements are initialized with empty strings -
     not nil"

    |oldSize "{ Class:SmallInteger }"|

    oldSize := tally.
    super grow:newSize.
    (oldSize < newSize) ifTrue:[
	contentsArray from:(oldSize + 1) to:newSize put:''
    ]
!

add:aString
    "append the argument, aString to myself -
     we increase physical size by 50 to avoid lots of copying around"

    |oldSize "{ Class:SmallInteger }"|

    oldSize := tally.
    super grow:(oldSize + 50).
    tally := oldSize + 1.
    contentsArray at:tally put:aString
! !

!Text methodsFor:'converting'!

asString
    "return myself as a string with embedded cr's"

    ^ self asStringFrom:1 to:(self size)
!

asStringFrom:firstLine to:lastLine
    "return part of myself as a string with embedded cr's"

    ^ self asStringFrom:firstLine to:lastLine compressTabs:false withCR:true
!

asStringFrom:firstLine to:lastLine compressTabs:compressTabs
    "return part of myself as a string with embedded cr's.
     If the argument compressTabs is true, leading spaces are converted
     to tab-characters (8col tabs)"

    ^ self asStringFrom:firstLine to:lastLine compressTabs:compressTabs withCR:true
!

asStringFrom:firstLine to:lastLine compressTabs:compressTabs withCR:withCR
    "return part of myself as a string with embedded cr's.
     If the argument compressTabs is true, leading spaces are converted
     to tab-characters (8col tabs). WithCR controls whether the last line
     should be followed by a cr or not."

    |totalLength "{ Class:SmallInteger }"
     pos         "{ Class:SmallInteger }"
     newString lineString spaces idx nTabs cutOff|

    "
     first accumulate the size of the string, to avoid
     countless reallocations. The size is not exact, but gives
     an upper bound ...
    "
    totalLength := 0.
    firstLine to:lastLine do:[:lineIndex |
	lineString := self at:lineIndex.
	lineString isNil ifTrue:[
	    totalLength := totalLength + 1
	] ifFalse: [
	    totalLength := totalLength + lineString size + 1
	].
	0
    ].
    withCR ifFalse:[
	totalLength := totalLength - 1
    ].
    spaces := '        '.
    newString := String new:totalLength.
    pos := 1.
    firstLine to:lastLine do:[:lineIndex |
	lineString := self at:lineIndex.
	lineString isNil ifFalse:[
	    compressTabs ifTrue:[
		"
		 mhmh: could use withTabs from String-class here,
		 but we should avoid creating too many temporary strings
		 (especially, since this method is typically used when converting
		 big texts such as when saving in the filebrowser ...).
		 Therefore, we convert tabs inline here doing a direct replace
		 in newString."

		idx := lineString findFirst:[:c | (c ~~ Character space)].
		nTabs := (idx-1) // 8.
		nTabs ~~ 0 ifTrue:[
		    "any tabs"
		    newString atAll:(pos to:pos+nTabs-1) put:(Character tab).
		    pos := pos + nTabs.
		    newString replaceFrom:pos with:lineString startingAt:(nTabs * 8 + 1).
		    pos := pos + lineString size - (nTabs * 8).
		] ifFalse:[
		    newString replaceFrom:pos with:lineString.
		    pos := pos + (lineString size)
		].
	    ] ifFalse:[
		newString replaceFrom:pos with:lineString.
		pos := pos + (lineString size)
	    ]
	].
	(lineIndex ~~ lastLine
	or:[withCR]) ifTrue:[
	    newString at:pos put:(Character cr).
	    pos := pos + 1
	]
    ].
    pos ~~ totalLength ifTrue:[
	^ newString copyTo:(pos - 1)
    ].
    ^ newString
!

from:aString
    "setup my contents from the argument, aString"

    |numberOfLines "{ Class:SmallInteger }"
     start         "{ Class:SmallInteger }"
     stop          "{ Class:SmallInteger }" |

    numberOfLines := aString occurrencesOf:(Character cr).
    (aString endsWith:(Character cr)) ifFalse:[
	numberOfLines := numberOfLines + 1.
    ].
    self grow:numberOfLines.
    start := 1.
    1 to:numberOfLines do:[:lineNr |
	stop := aString indexOf:(Character cr) startingAt:start.
	stop == 0 ifTrue:[
	    stop := aString size
	] ifFalse: [
	    stop := stop - 1.
	].

	(stop < start) ifTrue: [
	    self at:lineNr put:(String new:0)
	] ifFalse: [
	    self at:lineNr put:(aString copyFrom:start to:stop)
	].
	start := stop + 2
    ]
!

asText
    ^ self
! !

!Text methodsFor:'printing'!

printString
    ^ self asString
! !

!Text methodsFor:'searching'!

indexOfLineStartingWith:aString
    "return the index of the first line starting with the argument, aString"

    |index "{ Class:SmallInteger }" |

    index := 1.
    [index <= self size] whileTrue:[
	((self at:index) startsWith:aString) ifTrue:[
	    ^ index
	].
	index := index + 1
    ].
    ^ 0
! !