Index: libcfa/src/containers/string.cfa
===================================================================
--- libcfa/src/containers/string.cfa	(revision 09a767ee36e9fca3ac909693ca7c5ee1cf681871)
+++ libcfa/src/containers/string.cfa	(revision 9ca5e56e849c1f5d92f3eb82c58fb599933090d4)
@@ -10,6 +10,6 @@
 // Created On       : Fri Sep 03 11:00:00 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Aug  7 10:07:26 2023
-// Update Count     : 2
+// Last Modified On : Sat Aug 12 15:24:18 2023
+// Update Count     : 6
 //
 
@@ -102,10 +102,10 @@
 // Output
 
-ofstream & ?|?( ofstream & fs, const string & this ) {
-    return fs | (*this.inner);
-}
-
-void ?|?( ofstream & fs, const string & this ) {
-    fs | (*this.inner);
+ofstream & ?|?( ofstream & out, const string & this ) {
+    return out | (*this.inner); // print internal string_res
+}
+
+void ?|?( ofstream & out, const string & this ) {
+    (ofstream &)(out | (*this.inner)); ends( out );
 }
 
Index: libcfa/src/containers/string_res.cfa
===================================================================
--- libcfa/src/containers/string_res.cfa	(revision 09a767ee36e9fca3ac909693ca7c5ee1cf681871)
+++ libcfa/src/containers/string_res.cfa	(revision 9ca5e56e849c1f5d92f3eb82c58fb599933090d4)
@@ -10,6 +10,6 @@
 // Created On       : Fri Sep 03 11:00:00 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jun 29 09:29:06 2023
-// Update Count     : 2
+// Last Modified On : Sat Aug 12 15:37:47 2023
+// Update Count     : 10
 //
 
@@ -134,5 +134,5 @@
 	serr | nlOff;
 	serr | " lnth:" | lnth | " s:" | (void *)s | ",\"";
-	for ( int i = 0; i < lnth; i += 1 ) {
+	for ( i; lnth ) {
 	    serr | s[i];
 	} // for
@@ -198,29 +198,11 @@
 // Output operator
 ofstream & ?|?(ofstream &out, const string_res &s) {
-    // Store auto-newline state so it can be restored
-    bool anl = getANL$(out);
-    nlOff(out);
-    for (size_t i = 0; i < s.Handle.lnth; i++) {
-        out | s[i];
-    }
-    out | sepVal;
-    // Re-apply newlines after done, for chaining version
-    if (anl) nlOn(out);
+	// CFA string is NOT null terminated, so print exactly lnth characters in a minimum width of 0.
+	out | wd( 0, s.Handle.lnth, s.Handle.s ) | nonl;
     return out;
 }
 
 void ?|?(ofstream &out, const string_res &s) {
-    // Store auto-newline state so it can be restored
-    bool anl = getANL$(out);
-    if( s.Handle.lnth == 0 ) {
-        sout | "";
-    } else {
-        nlOff(out);
-        for (size_t i = 0; i < s.Handle.lnth; i++) {
-            // Need to re-apply on the last output operator, for whole-statement version
-            if (anl && i == s.Handle.lnth-1) nlOn(out);
-            out | s[i];
-        }
-    }
+	(ofstream &)(out | s); ends( out );
 }
 
@@ -338,5 +320,5 @@
     // adjust all substring string and handle locations, and check if any substring strings are outside the new base string
     char *limit = resultSesStart + resultSesLnth;
-    for (string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next) {
+    for ( string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next ) {
         verify (p->Handle.s >= beforeBegin);
         if ( p->Handle.s >= afterBegin ) {
@@ -396,5 +378,5 @@
     string_res * shareEditSetStartPeer = & this;
     string_res * shareEditSetEndPeer = & this;
-    for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) {
+    for ( string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next ) {
         if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) {
             shareEditSetStartPeer = editPeer;
@@ -589,5 +571,5 @@
 
 bool contains(const string_res &s, char ch) {
-    for (i; size(s)) {
+    for ( i; size(s) ) {
         if (s[i] == ch) return true;
     }
@@ -643,5 +625,5 @@
     }
 
-    for (size_t i = fromPos; i < s.Handle.lnth; i++) {
+    for ( i; fromPos ~ s.Handle.lnth ) {
         size_t remaining = s.Handle.lnth - i;
         // Never going to find the search string if the remaining string is
@@ -652,5 +634,5 @@
 
         bool matched = true;
-        for (size_t j = 0; j < searchsize; j++) {
+        for ( j; searchsize ) {
             if (search[j] != s.Handle.s[i + j]) {
                 matched = false;
@@ -740,5 +722,5 @@
 
 int exclude(const string_res &s, const charclass_res &mask) {
-    for (int i = 0; i < size(s); i++) {
+    for ( i; size(s) ) {
         if ( test(mask, s[i]) ) return i;
     }
@@ -747,5 +729,5 @@
 
 int include(const string_res &s, const charclass_res &mask) {
-    for (int i = 0; i < size(s); i++) {
+    for ( i; size(s) ) {
         if ( ! test(mask, s[i]) ) return i;
     }
@@ -775,5 +757,5 @@
 		for ( HandleNode *ni = HeaderPtr->flink; ni != HeaderPtr; ni = ni->flink ) {
 			serr | "\tnode:" | ni | " lnth:" | ni->lnth | " s:" | (void *)ni->s | ",\"";
-			for ( int i = 0; i < ni->lnth; i += 1 ) {
+			for ( i; ni->lnth ) {
 				serr | ni->s[i];
 			} // for
@@ -881,6 +863,6 @@
 	for ( HandleNode *n = HeaderPtr->flink; n != HeaderPtr; n = n->flink ) {
 	    serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
-	    for ( int i = 0; i < n->lnth; i += 1 ) {
-		serr | n->s[i];
+	    for ( i; n->lnth ) {
+			serr | n->s[i];
 	    } // for
 	    serr | "\" flink:" | n->flink | " blink:" | n->blink | nl;
@@ -960,5 +942,5 @@
     EndVbyte = StartVbyte;
     h = Header.flink;					// ignore header node
-    for (;;) {
+    for () {
 		memmove( EndVbyte, h->s, h->lnth );
 		obase = h->s;
@@ -971,5 +953,5 @@
 		// check if any substrings are allocated within a string
 		
-		for (;;) {
+		for () {
 			if ( h == &Header ) break;			// end of header list ?
 			if ( h->s >= limit ) break;			// outside of current string ?
@@ -1001,5 +983,5 @@
 			serr | nlOff;
 			serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
-			for ( int i = 0; i < n->lnth; i += 1 ) {
+			for ( i; n->lnth ) {
 				serr | n->s[i];
 			} // for
@@ -1036,5 +1018,5 @@
 			serr | nlOff;
 			serr | "\tnode:" | n | " lnth:" | n->lnth | " s:" | (void *)n->s | ",\"";
-			for ( int i = 0; i < n->lnth; i += 1 ) {
+			for ( i; n->lnth ) {
 				serr | n->s[i];
 			} // for
Index: libcfa/src/containers/string_res.hfa
===================================================================
--- libcfa/src/containers/string_res.hfa	(revision 09a767ee36e9fca3ac909693ca7c5ee1cf681871)
+++ libcfa/src/containers/string_res.hfa	(revision 9ca5e56e849c1f5d92f3eb82c58fb599933090d4)
@@ -9,7 +9,7 @@
 // Author           : Michael L. Brooks
 // Created On       : Fri Sep 03 11:00:00 2021
-// Last Modified By : Michael L. Brooks
-// Last Modified On : Fri Sep 03 11:00:00 2021
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat Aug 12 15:45:47 2023
+// Update Count     : 2
 //
 
@@ -30,5 +30,5 @@
     VbyteHeap *ulink;                   // upward link
 
-    char *s;						// pointer to byte string
+    char *s;							// pointer to byte string
     unsigned int lnth;					// length of byte string
 }; // HandleNode
