ls: unicode fixes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/libbb/Kbuild b/libbb/Kbuild
index 243626d..7e79310 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -73,6 +73,7 @@
 lib-y += pidfile.o
 lib-y += platform.o
 lib-y += printable.o
+lib-y += printable_string.o
 lib-y += print_flags.o
 lib-y += process_escape_sequence.o
 lib-y += procps.o
diff --git a/libbb/printable_string.c b/libbb/printable_string.c
new file mode 100644
index 0000000..47565de
--- /dev/null
+++ b/libbb/printable_string.c
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Unicode support routines.
+ *
+ * Copyright (C) 2010 Denys Vlasenko
+ *
+ * Licensed under GPL version 2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "unicode.h"
+
+const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
+{
+	static char *saved[4];
+	static unsigned cur_saved; /* = 0 */
+
+	char *dst;
+	const char *s;
+
+	s = str;
+	while (1) {
+		unsigned char c = *s;
+		if (c == '\0') {
+			/* 99+% of inputs do not need conversion */
+			if (stats) {
+				stats->byte_count = (s - str);
+				stats->unicode_count = (s - str);
+				stats->unicode_width = (s - str);
+			}
+			return str;
+		}
+		if (c < ' ')
+			break;
+		if (c >= 0x7f)
+			break;
+		s++;
+	}
+
+#if ENABLE_FEATURE_ASSUME_UNICODE
+	dst = unicode_conv_to_printable(stats, str);
+#else
+	{
+		char *d = dst = xstrdup(str);
+		while (1) {
+			unsigned char c = *d;
+			if (c == '\0')
+				break;
+			if (c < ' ' || c >= 0x7f)
+				*d = '?';
+			d++;
+		}
+		if (stats) {
+			stats->byte_count = (d - dst);
+			stats->unicode_count = (d - dst);
+			stats->unicode_width = (d - dst);
+		}
+	}
+#endif
+
+	free(saved[cur_saved]);
+	saved[cur_saved] = dst;
+	cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);
+
+	return dst;
+}