"======================================================================
|
|   A write stream which automatically indents
|
|   $Revision: 1.7.5$
|   $Date: 2000/05/28 16:56:52$
|   $Author: pb$
|
 ======================================================================"


"======================================================================
|
| Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc.
| Written by Steve Byrne.
|
| This file is part of GNU Smalltalk.
|
| GNU Smalltalk is free software; you can redistribute it and/or modify it
| under the terms of the GNU General Public License as published by the Free
| Software Foundation; either version 2, or (at your option) any later version.
| 
| GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
| FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
| details.
| 
| You should have received a copy of the GNU General Public License along with
| GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
|
 ======================================================================"


Stream subclass: #IndentedStream
	   instanceVariableNames: 'stream level amount tabAmount column'
	   classVariableNames: ''
	   poolDictionaries: ''
	   category: 'Examples-Useful'
!


!IndentedStream class methodsFor: 'instance creation'!

on: aStream
    ^self new init: aStream

! !

!IndentedStream methodsFor: 'writing'!

nextPut: aChar
    column == 0 ifTrue: [ self indentLine ].
    stream nextPut: aChar.
    aChar == (Character nl) 
	ifTrue: [ column := 0. ^self ].
    aChar == (Character tab) 
	ifTrue: [ column := self nextTab.  ^self ].
    column := column + 1.
!

nextPutAll: aString
    | stringSize index start nl tab ch |
    index := 1.
    stringSize := aString size.
    nl := Character nl.
    tab := Character tab.
    
    ch := aString at: index.
    [ index <= stringSize ] whileTrue: [
	"Either the first character, or a newline, or a tab"
	self nextPut: ch.
	index := index + 1.
	  
	[ (index > stringSize) or: [
	    ch := aString at: index.
	    (ch = nl) | (ch = tab) 
	]] whileFalse: [ index := index + 1 ].

	column == 0 ifTrue: [ self indentLine ].
	stream nextPutAll: (aString copyFrom: start to: index - 1).
	column := column + (index - start)
    ].
!

tabTo: col
    | nextTab |
    nextTab := self nextTab.
    [ nextTab < col ] whileTrue: 
	[ self tab. nextTab := nextTab + 8 ].
    [ column < col ] whileTrue: 
	[ self space ].
! !



!IndentedStream methodsFor: 'accessing'!

column
    ^column
!

level
    ^level
!

level: anInteger
    level := anInteger.
    self computeIndent.
!

indentAmount
    ^amount
!

indentAmount: anInteger
    amount := anInteger.
!

popLevel
    self level: ((self level - 1) max: 0)
!

pushLevel
    self level: self level + 1
!

tabAmount
    ^tabAmount
!

tabAmount: anInteger
    tabAmount := anInteger.
! !



!IndentedStream methodsFor: 'private'!

init: aStream
    stream := aStream.
    column := 0.
    self
	amount: 4;
	tabAmount: 8;
	level: 0
!

indentLine
    self tabTo: amount * level.
!

nextTab
    ^(column + tabAmount) truncateTo: tabAmount.
! !


    
"

| s t |
    s := IndentedStream on: (t := String new: 0).
    s pushLevel.
    s nl.
    s nextPutAll: 'hello there you rabbit'.
    s nl.
    s contents printNl.
!

"
