expandTabs now handles multiline strings
authorClaus Gittinger <cg@exept.de>
Mon, 11 Dec 1995 18:25:23 +0100
changeset 735 362ce9e28d89
parent 734 a4378f483a86
child 736 9129846af5ca
expandTabs now handles multiline strings
CharArray.st
CharacterArray.st
String.st
--- a/CharArray.st	Mon Dec 11 18:23:54 1995 +0100
+++ b/CharArray.st	Mon Dec 11 18:25:23 1995 +0100
@@ -11,10 +11,10 @@
 "
 
 ByteArray subclass:#CharacterArray
-	 instanceVariableNames:''
-	 classVariableNames:'PreviousMatch'
-	 poolDictionaries:''
-	 category:'Collections-Text'
+	instanceVariableNames:''
+	classVariableNames:'PreviousMatch'
+	poolDictionaries:''
+	category:'Collections-Text'
 !
 
 !CharacterArray class methodsFor:'documentation'!
@@ -1790,8 +1790,13 @@
 !
 
 withTabs
-    "return a copy of the receiver where leading spaces are
-     replaced by tabulator characters (assuming 8-col tabs)"
+    "return a string consisting of the receivers characters
+     where leading spaces are replaced by tabulator characters (assuming 8-col tabs).
+     Notice: if the receiver does not contain any tabs, it is returned unchanged;
+     otherwise a new string is returned.
+     Limitation: only the very first spaces are replaced 
+		 (i.e. if the receiver contains newLine characters,
+		  no tabs are inserted after those lineBreaks)"
 
     |idx   "{ SmallInteger }" 
      nTabs "{ SmallInteger }" 
@@ -1818,8 +1823,11 @@
 !
 
 withTabsExpanded
-    "return a copy of the receiver where all tabulator characters
-     are expanded into spaces (assuming 8-col tabs)"
+    "return a string consisting of the receivers characters,
+     where all tabulator characters are expanded into spaces (assuming 8-col tabs). 
+     Notice: if the receiver does not contain any tabs, it is returned unchanged;
+     otherwise a new string is returned.
+     This does handle multiline strings."
 
     |idx "{ SmallInteger }" str|
 
@@ -1829,18 +1837,28 @@
     idx := 1.
     self do:[:ch |
 	ch == Character tab ifFalse:[
+	    idx := idx + 1.
+	    ch == Character cr ifTrue:[
+		idx := 1
+	    ].
 	    str nextPut:ch.
-	    idx := idx + 1
 	] ifTrue:[
 	    (idx \\ 8) to:8 do:[:ii |
 		str space.
 		idx := idx + 1
-	    ]
+	    ].
 	]
     ].
     ^ str contents
 
     "
+     ('1' , Character tab asString , 'x') withTabsExpanded          
+     ('12345' , Character tab asString , 'x') withTabsExpanded      
+     ('123456' , Character tab asString , 'x') withTabsExpanded     
+     ('1234567' , Character tab asString , 'x') withTabsExpanded   
+     ('12345678' , Character tab asString , 'x') withTabsExpanded   
+     ('123456789' , Character tab asString , 'x') withTabsExpanded 
+
      (String with:Character tab
 	     with:Character tab
 	     with:$1) withTabsExpanded
@@ -1849,7 +1867,15 @@
 	     with:$1
 	     with:Character tab
 	     with:$2) withTabsExpanded  
+
+     (String with:Character tab
+	     with:$1
+	     with:Character cr
+	     with:Character tab
+	     with:$2) withTabsExpanded  
     "
+
+    "Modified: 11.12.1995 / 15:27:50 / cg"
 !
 
 withoutCRs
@@ -2357,5 +2383,5 @@
 !CharacterArray class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Attic/CharArray.st,v 1.44 1995-12-04 17:19:49 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Attic/CharArray.st,v 1.45 1995-12-11 17:24:58 cg Exp $'
 ! !
--- a/CharacterArray.st	Mon Dec 11 18:23:54 1995 +0100
+++ b/CharacterArray.st	Mon Dec 11 18:25:23 1995 +0100
@@ -11,10 +11,10 @@
 "
 
 ByteArray subclass:#CharacterArray
-	 instanceVariableNames:''
-	 classVariableNames:'PreviousMatch'
-	 poolDictionaries:''
-	 category:'Collections-Text'
+	instanceVariableNames:''
+	classVariableNames:'PreviousMatch'
+	poolDictionaries:''
+	category:'Collections-Text'
 !
 
 !CharacterArray class methodsFor:'documentation'!
@@ -1790,8 +1790,13 @@
 !
 
 withTabs
-    "return a copy of the receiver where leading spaces are
-     replaced by tabulator characters (assuming 8-col tabs)"
+    "return a string consisting of the receivers characters
+     where leading spaces are replaced by tabulator characters (assuming 8-col tabs).
+     Notice: if the receiver does not contain any tabs, it is returned unchanged;
+     otherwise a new string is returned.
+     Limitation: only the very first spaces are replaced 
+		 (i.e. if the receiver contains newLine characters,
+		  no tabs are inserted after those lineBreaks)"
 
     |idx   "{ SmallInteger }" 
      nTabs "{ SmallInteger }" 
@@ -1818,8 +1823,11 @@
 !
 
 withTabsExpanded
-    "return a copy of the receiver where all tabulator characters
-     are expanded into spaces (assuming 8-col tabs)"
+    "return a string consisting of the receivers characters,
+     where all tabulator characters are expanded into spaces (assuming 8-col tabs). 
+     Notice: if the receiver does not contain any tabs, it is returned unchanged;
+     otherwise a new string is returned.
+     This does handle multiline strings."
 
     |idx "{ SmallInteger }" str|
 
@@ -1829,18 +1837,28 @@
     idx := 1.
     self do:[:ch |
 	ch == Character tab ifFalse:[
+	    idx := idx + 1.
+	    ch == Character cr ifTrue:[
+		idx := 1
+	    ].
 	    str nextPut:ch.
-	    idx := idx + 1
 	] ifTrue:[
 	    (idx \\ 8) to:8 do:[:ii |
 		str space.
 		idx := idx + 1
-	    ]
+	    ].
 	]
     ].
     ^ str contents
 
     "
+     ('1' , Character tab asString , 'x') withTabsExpanded          
+     ('12345' , Character tab asString , 'x') withTabsExpanded      
+     ('123456' , Character tab asString , 'x') withTabsExpanded     
+     ('1234567' , Character tab asString , 'x') withTabsExpanded   
+     ('12345678' , Character tab asString , 'x') withTabsExpanded   
+     ('123456789' , Character tab asString , 'x') withTabsExpanded 
+
      (String with:Character tab
 	     with:Character tab
 	     with:$1) withTabsExpanded
@@ -1849,7 +1867,15 @@
 	     with:$1
 	     with:Character tab
 	     with:$2) withTabsExpanded  
+
+     (String with:Character tab
+	     with:$1
+	     with:Character cr
+	     with:Character tab
+	     with:$2) withTabsExpanded  
     "
+
+    "Modified: 11.12.1995 / 15:27:50 / cg"
 !
 
 withoutCRs
@@ -2357,5 +2383,5 @@
 !CharacterArray class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.44 1995-12-04 17:19:49 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.45 1995-12-11 17:24:58 cg Exp $'
 ! !
--- a/String.st	Mon Dec 11 18:23:54 1995 +0100
+++ b/String.st	Mon Dec 11 18:25:23 1995 +0100
@@ -1064,10 +1064,13 @@
 !
 
 withTabsExpanded
-    "return a copy of the receiver where all tabulator characters
+    "return a string with the characters of the receiver where all tabulator characters
      are expanded into spaces (assuming 8-col tabs).
-     rewritten for speed - this is very heavily used when reading
-     big files in the FileBrowser."
+     Notice: if the receiver does not contain any tabs, it is returned unchanged;
+     otherwise a new string is returned.
+     This does handle multiline strings.
+     Rewritten for speed - because this is very heavily used when reading
+     big files in the FileBrowser (and therefore speeds up fileReading considerably)."
 %{  
     char buffer[80*8 + 10];
     char *srcP, *dstP, *cp0;
@@ -1080,18 +1083,26 @@
     if (__qClass(self) == String) {
 	/*
 	 * for small strings (< 80), do it without a prescan ...
+	 * the buffer is large enough to even convert a
+	 * receiver consisting fully of tabs.
 	 */
 	if (__stringSize(self) < 80) {
+	    idx = 1;
 	    for (srcP = __stringVal(self), dstP = buffer; (c = *srcP); srcP++) {
 		if (c == '\t') {
 		    any = 1;
-		    idx = (dstP-buffer+1) % 8;
-		    while (idx <= 8) {
+		    while (idx % 8) {
 			idx++;
 			*dstP++ = ' ';
 		    }
+		    idx++;
+		    *dstP++ = ' ';
 		} else {
 		    *dstP++ = c;
+		    idx++;
+		    if (c == '\n') {
+			idx = 1;
+		    }
 		}
 	    }
 	    if (! any) RETURN(self);
@@ -1099,18 +1110,25 @@
 	    RETURN (__MKSTRING_L(buffer, (dstP-buffer)));
 	}
 	/*
-	 * scan for size ...
+	 * for large strings, we compute the new size, allocate a new string
+	 * and expand it.
+	 *
+	 * first, scan for size ...
 	 */
+	idx = 1;
 	for (srcP = __stringVal(self), sz = 0; (c = *srcP); srcP++) {
 	    if (c == '\t') {
 		any = 1;
-		idx = (sz+1) % 8;
-		while (idx <= 8) {
+		while (idx % 8) {
 		    idx++;
 		    sz++;
 		}
+		idx++; sz ++;
 	    } else {
-		sz++;
+		sz++; idx++;
+		if (c == '\n') {
+		    idx = 1;
+		}
 	    }
 	}
 	if (! any) RETURN(self);
@@ -1122,15 +1140,24 @@
 	_qNew(newString, sz, __context);
 	if (newString != nil) {
 	    _InstPtr(newString)->o_class = String;
+
+	    /*
+	     * expand
+	     */
+	    idx = 1;
 	    for (srcP = __stringVal(self), dstP = cp0 = __stringVal(newString); (c = *srcP); srcP++) {
 		if (c == '\t') {
-		    idx = (dstP-cp0+1) % 8;
-		    while (idx <= 8) {
+		    while (idx % 8) {
 			idx++;
 			*dstP++ = ' ';
 		    }
+		    idx++;
+		    *dstP++ = ' ';
 		} else {
-		    *dstP++ = c;
+		    *dstP++ = c; idx++;
+		    if (c == '\n') {
+			idx = 1;
+		    }
 		}
 	    }
 	    *dstP++ = '\0';
@@ -2171,5 +2198,5 @@
 !String class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/String.st,v 1.55 1995-11-23 17:29:00 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/String.st,v 1.56 1995-12-11 17:25:23 cg Exp $'
 ! !