Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 765ee420c66cf84b7f8a2e1174845a6ad5e2fafe)
+++ libcfa/src/iostream.cfa	(revision baa1d5dcfe059fec982d2f0351950afe46056e2a)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jan 25 08:39:31 2024
-// Update Count     : 1901
+// Last Modified On : Sat Jan 27 18:02:40 2024
+// Update Count     : 1909
 //
 
@@ -1002,5 +1002,6 @@
 			return is | *(_Istream_Cstr *)&f;
 		} // fini
-		if ( ! flags.ignore && args == 0 ) s[0] = '\0';	// read failed => no pattern match => set string to null
+		// read failed => no pattern match => set string to null
+		if ( ! flags.ignore && s != 0p && args == 0 ) s[0] = '\0';
 		if ( args == 1 && eof( is ) ) {					// data but scan ended at EOF
 			clear( is );								// => reset EOF => detect again on next read
@@ -1055,5 +1056,9 @@
 			if ( flags.delimiter ) {					// getline
 				int len = 0;							// may not be set in fmt
-				sprintf( &fmtstr[pos], "[^%c]%%n", delimiters[0] );
+				if ( delimiters[2] != '\0' ) {			// read single character ?
+					sprintf( &fmtstr[pos], "c%%n" );
+				} else {
+					sprintf( &fmtstr[pos], "[^%c]%%n", delimiters[0] );
+				} // if
 				if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
 				else args = fmt( is, fmtstr, s, &len );
@@ -1097,13 +1102,13 @@
 	} // ?|?
 
-	istype & ?|?( istype & is, _Istream_Char f ) with(f) {
-		if ( ignore ) {
-			fmt( is, "%*c" );							// argument variable unused
-		} else {
-			int len = -1, args = fmt( is, fmt, &c, &len );
-			if ( args != -1 && len == -1 ) throwResume ExceptionInst( missing_data );
-		} // if
-		return is;
-	} // ?|?
+	// istype & ?|?( istype & is, _Istream_Char f ) with(f) {
+	// 	if ( ignore ) {
+	// 		fmt( is, "%*c" );							// argument variable unused
+	// 	} else {
+	// 		int len = -1, args = fmt( is, fmt, &c, &len );
+	// 		if ( args != -1 && len == -1 ) throwResume ExceptionInst( missing_data );
+	// 	} // if
+	// 	return is;
+	// } // ?|?
 } // distribution
 
@@ -1124,4 +1129,5 @@
 } // distribution
 
+INPUT_FMT_IMPL( char, "c" )
 INPUT_FMT_IMPL( signed char, "hhi" )
 INPUT_FMT_IMPL( unsigned char, "hhi" )
Index: libcfa/src/iostream.hfa
===================================================================
--- libcfa/src/iostream.hfa	(revision 765ee420c66cf84b7f8a2e1174845a6ad5e2fafe)
+++ libcfa/src/iostream.hfa	(revision baa1d5dcfe059fec982d2f0351950afe46056e2a)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jan 25 08:39:04 2024
-// Update Count     : 696
+// Last Modified On : Sat Jan 27 17:55:22 2024
+// Update Count     : 732
 //
 
@@ -366,5 +366,4 @@
 	istype & nlOn( istype & );
 	istype & nlOff( istype & );
-	istype & quoted( istype &, char & c );
 } // distribution
 
@@ -398,5 +397,5 @@
 			unsigned char ignore:1;						// do not change input argument
 			unsigned char inex:1;						// include/exclude characters in scanset
-			unsigned char delimiter:1;					// delimit character
+			unsigned char delimiter:1;					// delimit character(s)
 			unsigned char rwd:1;						// read width
 		} flags;
@@ -429,4 +428,7 @@
 		return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : rwd, {.flags.rwd : true} } };
 	}
+	_Istream_Cquoted quoted( char & ch, const char Ldelimiter = '\'', const char Rdelimiter = '\0' ) {
+		return (_Istream_Cquoted)@{ { .s : &ch, { {.delimiters : { Ldelimiter, Rdelimiter, '\1' }}, .wd : 1, {.flags.rwd : true} } } };
+	}
 	_Istream_Cquoted & quoted( _Istream_Cwidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
 		f.delimiters[0] = Ldelimiter;  f.delimiters[1] = Rdelimiter;  f.delimiters[2] = '\0';
@@ -438,5 +440,5 @@
 	_Istream_Cstr & incl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Cstr &)f; }
 	_Istream_Cstr & excl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Cstr &)f; }
-	_Istream_Cstr ignore( char s[] ) { return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : -1, {.flags.ignore : true} } }; }
+	_Istream_Cstr ignore( const char s[] ) { return (_Istream_Cwidth)@{ .s : (char *)s, { {.scanset : 0p}, .wd : -1, {.flags.ignore : true} } }; }
 	_Istream_Cstr & ignore( _Istream_Cwidth & f ) { f.flags.ignore = true; return (_Istream_Cstr &)f; }
 	_Istream_Cquoted & ignore( _Istream_Cquoted & f ) { f.cstr.flags.ignore = true; return (_Istream_Cquoted &)f; }
@@ -453,24 +455,24 @@
 } // distribution
 
-struct _Istream_Char {
-	char & c;
-	bool ignore;										// do not change input argument
-	char fmt[7];										// \L%c\R%n\0
-}; // _Istream_Char
-
-static inline {
-	_Istream_Char quoted( char & c, const char Ldelimiter = '\'', const char Rdelimiter = '\0' ) {
-		return (_Istream_Char)@{ .c : c, .ignore : false,
-				fmt : { Ldelimiter, '%', 'c', (Rdelimiter == '\0' ? Ldelimiter : Rdelimiter), '%', 'n', '\0' } };
-	}
-	_Istream_Char ignore( char ) {
-		return (_Istream_Char)@{ .c : *0p, .ignore : true };
-	}
-	_Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
-} // distribution
-
-forall( istype & | basic_istream( istype ) ) {
-	istype & ?|?( istype & is, _Istream_Char f );
-}
+// struct _Istream_Char {
+// 	char & c;
+// 	bool ignore;										// do not change input argument
+// 	char fmt[7];										// \L%c\R%n\0
+// }; // _Istream_Char
+
+// static inline {
+// 	_Istream_Char quoted( char & c, const char Ldelimiter = '\'', const char Rdelimiter = '\0' ) {
+// 		return (_Istream_Char)@{ .c : c, .ignore : false,
+// 				fmt : { Ldelimiter, '%', 'c', (Rdelimiter == '\0' ? Ldelimiter : Rdelimiter), '%', 'n', '\0' } };
+// 	}
+// 	_Istream_Char ignore( char ) {
+// 		return (_Istream_Char)@{ .c : *0p, .ignore : true };
+// 	}
+// 	_Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
+// } // distribution
+
+// forall( istype & | basic_istream( istype ) ) {
+// 	istype & ?|?( istype & is, _Istream_Char f );
+// }
 
 forall( T & | sized( T ) )
@@ -483,8 +485,7 @@
 #define INPUT_FMT_DECL( T ) \
 static inline { \
+	_Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ .val : val, .wd : wd, .ignore : false }; } \
 	_Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ .val : (T &)val, .wd : -1, .ignore : true }; } \
 	_Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \
-	_Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ .val : val, .wd : wd, .ignore : false }; } \
-	_Istream_Manip(T) & wdi( unsigned int wd, _Istream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \
 } /* distribution */ \
 forall( istype & | basic_istream( istype ) ) { \
@@ -492,4 +493,5 @@
 } // ?|?
 
+INPUT_FMT_DECL( char )
 INPUT_FMT_DECL( signed char )
 INPUT_FMT_DECL( unsigned char )
Index: tests/io/.in/manipulatorsInput.txt
===================================================================
--- tests/io/.in/manipulatorsInput.txt	(revision 765ee420c66cf84b7f8a2e1174845a6ad5e2fafe)
+++ tests/io/.in/manipulatorsInput.txt	(revision baa1d5dcfe059fec982d2f0351950afe46056e2a)
@@ -20,4 +20,9 @@
 X		ZC44%Y
 X		ZC55%Y
+'x'
+"x"
+{x}
+XxY
+XyY
 abc 
 cccccb 
@@ -37,5 +42,11 @@
 X		ZC44%Y
 X		ZC55%Y
+'x'
+"x"
+{x}
+XxY
+XyY
 ab
+xxxyyy
 0xff 017 15-15
 0xff 017 15-15
Index: tests/io/manipulatorsInput.cfa
===================================================================
--- tests/io/manipulatorsInput.cfa	(revision 765ee420c66cf84b7f8a2e1174845a6ad5e2fafe)
+++ tests/io/manipulatorsInput.cfa	(revision baa1d5dcfe059fec982d2f0351950afe46056e2a)
@@ -7,6 +7,6 @@
 // Created On       : Sat Jun  8 17:58:54 2019
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jan 24 18:36:32 2024
-// Update Count     : 104
+// Last Modified On : Sat Jan 27 18:47:42 2024
+// Update Count     : 122
 // 
 
@@ -55,43 +55,56 @@
 	}
 	{
-		char s[] = "yyyyyyyyyyyyyyyyyyyy";                                                     // Input characters consumed:
+		char s[] = "yyyyyyyyyyyyyyyyyyyy";													// Input characters consumed:
 		const char sk_fmt[] = "%*[abc]";
-		scanf( "abc " ); scanf( sk_fmt ); for ( 5 ) scanf( "%*c" ); printf( "1 %s\n", s );     // |abc |\ncccccb| \nxx\n|
-		scanf( "%s", s );								printf( "2 %s\n", s );                 // |abcxxx|
-		scanf( "%*s" );									printf( "3 %s\n", s );                 // |\nabcyyy|
-		scanf( "%8s", s );								printf( "4 %s\n", s );                 // |\naaaaaaaa|
-		scanf( "%*8s" );								printf( "5 %s\n", s );                 // |xxxxxxxx|
-
-		scanf( "%[abc]", s );							printf( "6 %s\n", s );                 // |aabbccbb|
-		scanf( "%[^abc]", s );							printf( "7 %s\n", s );                 // |dddwww|
-		scanf( "%*[abc]" );								printf( "8 %s\n", s );                 // |bbbbbbbb|
-		scanf( "%*[^abc]" );							printf( "9 %s\n", s );                 // |wwwwwwww|
-		scanf( "%8[abc]", s );							printf( "10 %s\n", s );                // |aaaaaaaa|
-		scanf( "%8[^abc]", s );							printf( "11 %s\n", s );                // |wwwwwwww|
-		scanf( "%*8[abc]" );							printf( "12 %s\n", s );                // |aaaaaaaa|
-		scanf( "%*8[^abc]" );							printf( "13 %s\n", s );                // |wwwwwwww|
-		scanf( "\n" );									// must start next line                // |\n|
+		scanf( "abc " ); scanf( sk_fmt ); for ( 5 ) scanf( "%*c" ); printf( "1 %s\n", s );	// |abc |\ncccccb| \nxx\n|
+		scanf( "%s", s );								printf( "2 %s\n", s );				// |abcxxx|
+		scanf( "%*s" );									printf( "3 %s\n", s );				// |\nabcyyy|
+		scanf( "%8s", s );								printf( "4 %s\n", s );				// |\naaaaaaaa|
+		scanf( "%*8s" );								printf( "5 %s\n", s );				// |xxxxxxxx|
+
+		scanf( "%[abc]", s );							printf( "6 %s\n", s );				// |aabbccbb|
+		scanf( "%[^abc]", s );							printf( "7 %s\n", s );				// |dddwww|
+		scanf( "%*[abc]" );								printf( "8 %s\n", s );				// |bbbbbbbb|
+		scanf( "%*[^abc]" );							printf( "9 %s\n", s );				// |wwwwwwww|
+		scanf( "%8[abc]", s );							printf( "10 %s\n", s );				// |aaaaaaaa|
+		scanf( "%8[^abc]", s );							printf( "11 %s\n", s );				// |wwwwwwww|
+		scanf( "%*8[abc]" );							printf( "12 %s\n", s );				// |aaaaaaaa|
+		scanf( "%*8[^abc]" );							printf( "13 %s\n", s );				// |wwwwwwww|
+		scanf( "\n" );									// must start next line				// |\n|
 
 		int rc;
 		s[0] = 'q'; s[1] = '\0'; rc = 99;
-		rc = scanf( "%[abc]", s );						printf( "14 rc=%d, %s\n", rc, s );     // ||
+		rc = scanf( "%[abc]", s );						printf( "14 rc=%d, %s\n", rc, s );	// ||
 		s[0] = 'q'; s[1] = '\0'; rc = 99;
-		rc = scanf( "%[^u]", s );						printf( "15 rc=%d, %s\n", rc, s );     // ||
-		scanf( "%*[u]\n" );                                                                    // |uuuuu\n|
-		scanf( "%[^\n]\n", s );							printf( "16 %s\n", s );                // |get this line\n|
-		scanf( "%[^%%]%%\n", s );						printf( "17 %s\n", s );                // |@# this line 1)-{}%\n|
-		scanf( "%*[^%%]%%\n", s );						printf( "18 %s\n", s );                // |@# this line 1)-{}%\n|
-
-		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace                   // ||
-		scanf( "\"%[^\"]\"", s );						printf( "19 %s\n", s );                // |"abc"|
-		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace                   // |\n|
-		scanf( "'%[^']'", s );							printf( "20 %s\n", s );                // |'abc  '|
-		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace                   // |\n|
-		scanf( "{%[^}]}", s );							printf( "21 %s\n", s );                // |{ d d\n\nd }|
-		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace                   // |\n|
-		scanf( "X%[^Y]Y", s );							printf( "22 %s\n", s );                // |X		ZC44%Y|
-		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace                   // |\n|
-		scanf( "X%*[^Y]Y", s );							printf( "23 %s\n", s );                // |X		ZC44%Y|
-		scanf( "\n" );									// must start next line                // |\n|
+		rc = scanf( "%[^u]", s );						printf( "15 rc=%d, %s\n", rc, s );	// ||
+		scanf( "%*[u]\n" );																	// |uuuuu\n|
+		scanf( "%[^\n]\n", s );							printf( "16 %s\n", s );				// |get this line\n|
+		scanf( "%[^%%]%%\n", s );						printf( "17 %s\n", s );				// |@# this line 1)-{}%\n|
+		scanf( "%*[^%%]%%\n", s );						printf( "18 %s\n", s );				// |@# this line 1)-{}%\n|
+
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// ||
+		scanf( "\"%[^\"]\"", s );						printf( "19 %s\n", s );				// |"abc"|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "'%[^']'", s );							printf( "20 %s\n", s );				// |'abc  '|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "{%[^}]}", s );							printf( "21 %s\n", s );				// |{ d d\n\nd }|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "X%[^Y]Y", s );							printf( "22 %s\n", s );				// |X		ZC44%Y|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "X%*[^Y]Y", s );							printf( "23 %s\n", s );				// |X		ZC44%Y|
+		scanf( "\n" );									// must start next line				// |\n|
+
+		char ch;
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "'%c'", &ch );							printf( "24 %c\n", ch );			// |x|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "\"%c\"", &ch );							printf( "25 %c\n", ch );			// |x|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "{%c}", &ch );							printf( "26 %c\n", ch );			// |x|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "X%cY", &ch );							printf( "27 %c\n", ch );			// |x|
+		scanf( "%*[ \f\n\r\t\v]" );						// ignore whitespace				// |\n|
+		scanf( "X%*cY", &ch );							printf( "28 %c\n", ch );			// |x|
+		scanf( "\n" );									// must start next line				// |\n|
 	}
 	{
@@ -128,10 +141,22 @@
 		sin | quoted( wdi( sizeof(s), s ), 'X', 'Y' );	sout | "22" | s;
 		sin | ignore( quoted( wdi( sizeof(s), s ), 'X', 'Y' ) ); sout | "23" | s;
-	}
-    // Keep harmonized with collections/string-istream-manip
+
+		char ch;
+		sin | quoted( ch );								sout | "24 " | ch;
+		sin | quoted( ch, '\"' );						sout | "25 " | ch;
+		sin | quoted( ch, '{', '}' );					sout | "26 " | ch;
+		sin | quoted( ch, 'X', 'Y' );					sout | "27 " | ch;
+		sin | ignore( quoted( ch, 'X', 'Y' ) );			sout | "28 " | ch;
+		sin | "\n";
+	}
+	// Keep harmonized with collections/string-istream-manip
 	{
 		char c;
 		sin | c;										sout | c;
 		sin | ignore( c );								sout | c;
+
+		char ca[3] = { 'a', 'b', 'c' };
+		sin | wdi( 4, (char &)*&ca[0] );					sout | ca[0] | ca[1] | ca[2];
+		sin | ignore( wdi( 4, (char &)*&ca[0] ) );		sout | ca[0] | ca[1] | ca[2];
 
 		signed char sc;
