Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/Makefile	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -162,4 +162,5 @@
 	lib/block \
 	lib/clui \
+	lib/fmtutil \
 	lib/scsi \
 	lib/softint \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/Makefile.common	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -108,4 +108,5 @@
 LIBIMGMAP_PREFIX = $(LIB_PREFIX)/imgmap
 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
+LIBFMTUTIL_PREFIX = $(LIB_PREFIX)/fmtutil
 
 LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
Index: uspace/app/bdsh/Makefile
===================================================================
--- uspace/app/bdsh/Makefile	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/app/bdsh/Makefile	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -29,7 +29,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) -I. -Icmds/ \
-	-Icmds/builtins -Icmds/modules
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a \
+	$(LIBFMTUTIL_PREFIX)/libfmtutil.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) -I$(LIBFMTUTIL_PREFIX)\
+	-I. -Icmds/ -Icmds/builtins -Icmds/modules
 BINARY = bdsh
 
Index: uspace/app/bdsh/cmds/modules/help/help.c
===================================================================
--- uspace/app/bdsh/cmds/modules/help/help.c	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/app/bdsh/cmds/modules/help/help.c	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -30,4 +31,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <fmtutil.h>
 
 #include "config.h"
@@ -128,26 +130,28 @@
 static void help_survival(void)
 {
-	printf("Don't panic!\n\n");
-
-	printf("This is Bdsh, the Brain dead shell, currently "
+	print_wrapped_console(
+	    "Don't panic!\n\n"
+
+	    "This is Bdsh, the Brain dead shell, currently "
 	    "the primary user interface to HelenOS. Bdsh allows you to enter "
 	    "commands and supports history (Up, Down arrow keys), "
 	    "line editing (Left Arrow, Right Arrow, Home, End, Backspace), "
 	    "selection (Shift + movement keys), copy and paste (Ctrl-C, "
-	    "Ctrl-V), similar to common desktop environments.\n\n");
-
-	printf("The most basic filesystem commands are Bdsh builtins. Type "
+	    "Ctrl-V), similar to common desktop environments.\n\n"
+
+	    "The most basic filesystem commands are Bdsh builtins. Type "
 	    "'help commands' [Enter] to see the list of Bdsh builtin commands. "
 	    "Other commands are external executables located in the /app and "
 	    "/srv directories. Type 'ls /app' [Enter] and 'ls /srv' [Enter] "
 	    "to see their list. You can execute an external command simply "
-	    "by entering its name (e.g. type 'tetris' [Enter]).\n\n");
-
-	printf("HelenOS has virtual consoles (VCs). You can switch between "
-	    "these using the F1-F11 keys.\n\n");
-
-	printf("This is but a small glimpse of what you can do with HelenOS. "
+	    "by entering its name (e.g. type 'tetris' [Enter]).\n\n"
+
+	    "HelenOS has virtual consoles (VCs). You can switch between "
+	    "these using the F1-F11 keys.\n\n"
+
+	    "This is but a small glimpse of what you can do with HelenOS. "
 	    "To learn more please point your browser to the HelenOS User's "
-	    "Guide: http://trac.helenos.org/trac.fcgi/wiki/UsersGuide\n\n");
+	    "Guide: http://trac.helenos.org/trac.fcgi/wiki/UsersGuide\n\n",
+	     ALIGN_LEFT);
 }
 
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/lib/c/generic/str.c	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -2,4 +2,5 @@
  * Copyright (c) 2005 Martin Decky
  * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -718,4 +719,22 @@
 
 	dest[dlen - 1] = '\0';
+}
+
+/** Convert string to wide string.
+ *
+ * Convert string @a src to wide string. A new wide NULL-terminated
+ * string will be allocated on the heap.
+ *
+ * @param src	Source string.
+ */
+wchar_t *str_to_awstr(const char *str)
+{
+	size_t len = str_length(str);
+        wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
+        if (wstr == NULL) {
+                return NULL;
+        }
+        str_to_wstr(wstr, len+1, str);
+	return wstr;
 }
 
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision f41682c751e229b19ae656924a5ad4c43550f532)
+++ uspace/lib/c/include/str.h	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -83,4 +83,5 @@
 extern char *wstr_to_astr(const wchar_t *src);
 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
+extern wchar_t *str_to_awstr(const char *src);
 
 extern char *str_chr(const char *str, wchar_t ch);
Index: uspace/lib/fmtutil/Makefile
===================================================================
--- uspace/lib/fmtutil/Makefile	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
+++ uspace/lib/fmtutil/Makefile	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2011 Martin Sucha
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -I.
+LIBRARY = libfmtutil
+
+SOURCES = \
+	fmtutil.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/fmtutil/fmtutil.c
===================================================================
--- uspace/lib/fmtutil/fmtutil.c	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
+++ uspace/lib/fmtutil/fmtutil.c	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <io/console.h>
+#include <errno.h>
+#include <malloc.h>
+#include <fmtutil.h>
+
+typedef struct {
+	align_mode_t alignment;
+	bool newline_always;
+	size_t width;
+} printmode_t;
+
+int print_wrapped_console(const char *str, align_mode_t alignment)
+{
+	console_ctrl_t *console = console_init(stdin, stdout);
+	if (console == NULL) {
+		printf("%s", str);
+		return EOK;
+	}
+	sysarg_t con_rows, con_cols, con_col, con_row;
+	int rc = console_get_size(console, &con_cols, &con_rows);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = console_get_pos(console, &con_col, &con_row);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (con_col != 0) {
+		printf("\n");
+	}
+	return print_wrapped(str, con_cols, alignment);
+}
+
+static int print_line(wchar_t *wstr, size_t chars, void *data)
+{
+	//char *line = wstr_to_astr(wstr);
+	printmode_t *pm = (printmode_t *) data;
+	//if (line == NULL) {
+	//	return ENOMEM;
+	//}
+	wstr[chars] = 0;
+	return print_aligned_w(wstr, pm->width, pm->alignment);
+	//printf("%s", line);
+	//if (pm->newline_always || chars < pm->width)
+	//	printf("\n");
+	//free(line);
+	//return EOK;
+}
+
+int print_wrapped(const char *str, size_t width, align_mode_t mode)
+{
+	printmode_t pm;
+	pm.alignment = mode;
+	pm.newline_always = false;
+	pm.width = width;
+	wchar_t *wstr = str_to_awstr(str);
+	if (wstr == NULL) {
+		return ENOMEM;
+	}
+	int rc = wrap(wstr, width, print_line, &pm);
+	free(wstr);
+	return rc;
+}
+
+int print_aligned_w(const wchar_t *wstr, size_t width, align_mode_t mode)
+{
+	size_t i;
+	size_t len = wstr_length(wstr);
+	if (mode == ALIGN_LEFT) {
+		for (i = 0; i < width; i++) {
+			if (i < len)
+				putchar(wstr[i]);
+			else
+				putchar(' ');
+		}
+	}
+	else if (mode == ALIGN_RIGHT) {
+		for (i = 0; i < width; i++) {
+			if (i < width - len)
+				putchar(' ');
+			else
+				putchar(wstr[i- (width - len)]);
+		}
+	}
+	else if (mode == ALIGN_CENTER) {
+		size_t padding = (width - len) / 2;
+		for (i = 0; i < width; i++) {
+			if ((i < padding) || ((i - padding) >= len))
+				putchar(' ');
+			else
+				putchar(wstr[i-padding]);
+		}
+	}
+	else if (mode == ALIGN_JUSTIFY) {
+		size_t words = 0;
+		size_t word_chars = 0;
+		bool space = true;
+		for (i = 0; i < len; i++) {
+			if (space && wstr[i] != ' ') {
+				words++;
+			}
+			space = wstr[i] == ' ';
+			if (!space) word_chars++;
+		}
+		if (words == 0) {
+			return EOK;
+		}
+		size_t excess_spaces = width - word_chars - (words-1);
+		space = true;
+		i = 0;
+		size_t done_words = 0;
+		size_t done_chars = 0;
+		size_t j;
+		while (i < len) {
+			/* Find a word */
+			while (i < len && wstr[i] == ' ') i++;
+			if (i == len) break;
+			if (done_words) {
+				// TODO: use better formula
+				size_t spaces = 1 + (excess_spaces /
+				    (words - 1));
+				for (j = 0; j < spaces; j++) {
+					putchar(' ');
+				}
+				done_chars += spaces;
+			}
+			while (i < len && wstr[i] != ' ') {
+				putchar(wstr[i++]);
+				done_chars++;
+			}
+			done_words++;
+		}
+		while (done_chars < width) {
+			putchar(' ');
+			done_chars++;
+		}
+	}
+	
+	return EOK;
+}
+int print_aligned(const char *str, size_t width, align_mode_t mode)
+{
+	wchar_t *wstr = str_to_awstr(str);
+	if (wstr == NULL) {
+		return ENOMEM;
+	}
+	int rc = print_aligned_w(wstr, width, mode);
+	free(wstr);
+	return rc;
+}
+
+/**
+ */
+int wrap(wchar_t *wstr, size_t width, line_consumer_fn consumer, void *data)
+{
+	size_t word_start = 0;
+	size_t last_word_end = 0;
+	size_t line_start = 0;
+	size_t line_len = 0;
+	size_t pos = 0;
+	
+	/*
+	 * Invariants:
+	 *  * line_len = last_word_end - line_start
+	 *  * line_start <= last_word_end <= word_start <= pos
+	 */
+	
+	while (wstr[pos] != 0) {
+		/* Skip spaces and process newlines */
+		while (wstr[pos] == ' ' || wstr[pos] == '\n') {
+			if (wstr[pos] == '\n') {
+				consumer(wstr + line_start, line_len, data);
+				last_word_end = line_start = pos + 1;
+				line_len = 0;
+			}
+			pos++;
+		}
+		word_start = pos;
+		/* Find end of word */
+		while (wstr[pos] != 0 && wstr[pos] != ' ' &&
+		    wstr[pos] != '\n')
+			pos++;
+		/* Check if the line still fits width */
+		if (pos - line_start > width) {
+			if (line_len > 0)
+				consumer(wstr + line_start, line_len, data);
+			line_start = last_word_end = word_start;
+			line_len = 0;
+		}
+		/* Check if we need to force wrap of long word*/
+		if (pos - word_start > width) {
+			consumer(wstr + word_start, width, data);
+			pos = line_start = last_word_end = word_start + width;
+			line_len = 0;
+		}
+		last_word_end = pos;
+		line_len = last_word_end - line_start;
+	}
+	/* Here we have less than width chars starting from line_start.
+	 * Moreover, the last portion does not contain spaces or newlines 
+	 */
+	if (pos - line_start > 0)
+		consumer(wstr + line_start, pos - line_start, data);
+
+	return EOK;
+}
+
Index: uspace/lib/fmtutil/fmtutil.h
===================================================================
--- uspace/lib/fmtutil/fmtutil.h	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
+++ uspace/lib/fmtutil/fmtutil.h	(revision 22cf42d96305c1472aead44ed289906f0f0b0f13)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef enum {
+	ALIGN_LEFT,
+	ALIGN_RIGHT,
+	ALIGN_CENTER,
+	ALIGN_JUSTIFY
+} align_mode_t;
+
+/** Callback that processes a line of characters.
+ * (e.g. as a result of wrap operation)
+ * 
+ * @param content pointer to line data (note: this is NOT null-terminated)
+ * @param size number of characters in line
+ * @param data user data
+ * 
+ * @returns EOK on success or error code on failure
+ */
+typedef int (*line_consumer_fn)(wchar_t *, size_t, void *);
+
+extern int print_aligned_w(const wchar_t *, size_t, align_mode_t);
+extern int print_aligned(const char *, size_t, align_mode_t);
+extern int print_wrapped(const char *, size_t, align_mode_t);
+extern int print_wrapped_console(const char *, align_mode_t);
+
+/** Wrap characters in a wide string to the given length.
+ *
+ * @param wstr the null-terminated wide string to wrap
+ * @param size number of characters to wrap to
+ * @param consumer the function that receives wrapped lines
+ * @param data user data to pass to the consumer function
+ */
+extern int wrap(wchar_t *, size_t, line_consumer_fn, void *);
