diff --git a/check.t b/check.t
index 89eec88..081cf82 100644
--- a/check.t
+++ b/check.t
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.t,v 1.336 2009/10/30 00:57:35 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.337 2009/11/09 23:35:07 tg Exp $
 # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
 # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
 # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@@ -25,7 +25,7 @@
 # http://www.research.att.com/~gsf/public/ifs.sh
 
 expected-stdout:
-	@(#)MIRBSD KSH R39 2009/10/30
+	@(#)MIRBSD KSH R39 2009/11/09
 description:
 	Check version of shell.
 stdin:
diff --git a/exec.c b/exec.c
index ddb0f95..073e837 100644
--- a/exec.c
+++ b/exec.c
@@ -22,7 +22,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.67 2009/10/15 16:25:15 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.68 2009/11/09 23:35:09 tg Exp $");
 
 static int comexec(struct op *, struct tbl *volatile, const char **,
     int volatile, volatile int *);
@@ -1338,16 +1338,15 @@ do_selectargs(const char **ap, bool print_menu)
 }
 
 struct select_menu_info {
-	const char *const *args;
-	int arg_width;
+	const char * const *args;
 	int num_width;
 };
 
-static char *select_fmt_entry(const void *, int, char *, int);
+static char *select_fmt_entry(char *, int, int, const void *);
 
 /* format a single select menu item */
 static char *
-select_fmt_entry(const void *arg, int i, char *buf, int buflen)
+select_fmt_entry(char *buf, int buflen, int i, const void *arg)
 {
 	const struct select_menu_info *smi =
 	    (const struct select_menu_info *)arg;
@@ -1361,66 +1360,73 @@ select_fmt_entry(const void *arg, int i, char *buf, int buflen)
  *	print a select style menu
  */
 int
-pr_menu(const char *const *ap)
+pr_menu(const char * const *ap)
 {
 	struct select_menu_info smi;
-	const char *const *pp;
-	int nwidth, dwidth, i, n;
+	const char * const *pp;
+	int acols = 0, aocts = 0, i, n;
 
-	/* Width/column calculations were done once and saved, but this
-	 * means select can't be used recursively so we re-calculate each
-	 * time (could save in a structure that is returned, but its probably
-	 * not worth the bother).
+	/*
+	 * width/column calculations were done once and saved, but this
+	 * means select can't be used recursively so we re-calculate
+	 * each time (could save in a structure that is returned, but
+	 * it's probably not worth the bother)
 	 */
 
 	/*
 	 * get dimensions of the list
 	 */
-	for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) {
+	for (n = 0, pp = ap; *pp; n++, pp++) {
+		i = strlen(*pp);
+		if (i > aocts)
+			aocts = i;
 		i = utf_mbswidth(*pp);
-		nwidth = (i > nwidth) ? i : nwidth;
+		if (i > acols)
+			acols = i;
 	}
+
 	/*
-	 * we will print an index of the form
-	 *	%d)
-	 * in front of each entry
-	 * get the max width of this
+	 * we will print an index of the form "%d) " in front of
+	 * each entry, so get the maximum width of this
 	 */
-	for (i = n, dwidth = 1; i >= 10; i /= 10)
-		dwidth++;
+	for (i = n, smi.num_width = 1; i >= 10; i /= 10)
+		smi.num_width++;
 
 	smi.args = ap;
-	smi.arg_width = nwidth;
-	smi.num_width = dwidth;
 	print_columns(shl_out, n, select_fmt_entry, (void *)&smi,
-	    dwidth + nwidth + 2, 1);
+	    smi.num_width + 2 + aocts, smi.num_width + 2 + acols,
+	    true);
 
 	return (n);
 }
 
 /* XXX: horrible kludge to fit within the framework */
-
-static char *plain_fmt_entry(const void *, int, char *, int);
+static char *plain_fmt_entry(char *, int, int, const void *);
 
 static char *
-plain_fmt_entry(const void *arg, int i, char *buf, int buflen)
+plain_fmt_entry(char *buf, int buflen, int i, const void *arg)
 {
 	shf_snprintf(buf, buflen, "%s", ((const char * const *)arg)[i]);
 	return (buf);
 }
 
 int
-pr_list(char *const *ap)
+pr_list(char * const *ap)
 {
-	char *const *pp;
-	int nwidth, i, n;
+	int acols = 0, aocts = 0, i, n;
+	char * const *pp;
 
-	for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) {
+	for (n = 0, pp = ap; *pp; n++, pp++) {
+		i = strlen(*pp);
+		if (i > aocts)
+			aocts = i;
 		i = utf_mbswidth(*pp);
-		nwidth = (i > nwidth) ? i : nwidth;
+		if (i > acols)
+			acols = i;
 	}
+
 	print_columns(shl_out, n, plain_fmt_entry, (const void *)ap,
-	    nwidth + 1, 0);
+	    aocts, acols, false);
 
 	return (n);
 }
diff --git a/funcs.c b/funcs.c
index 4c336aa..2a8b786 100644
--- a/funcs.c
+++ b/funcs.c
@@ -25,7 +25,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.141 2009/10/27 17:00:01 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.142 2009/11/09 23:35:09 tg Exp $");
 
 #if HAVE_KILLPG
 /*
@@ -171,7 +171,7 @@ static int test_primary(Test_env *, bool);
 static int ptest_isa(Test_env *, Test_meta);
 static const char *ptest_getopnd(Test_env *, Test_op, bool);
 static void ptest_error(Test_env *, int, const char *);
-static char *kill_fmt_entry(const void *, int, char *, int);
+static char *kill_fmt_entry(char *, int, int, const void *);
 static void p_time(struct shf *, bool, long, int, int,
     const char *, const char *) __attribute__((nonnull (6, 7)));
 static char *do_realpath(const char *);
@@ -1467,7 +1467,7 @@ c_fgbg(const char **wp)
 
 /* format a single kill item */
 static char *
-kill_fmt_entry(const void *arg, int i, char *buf, int buflen)
+kill_fmt_entry(char *buf, int buflen, int i, const void *arg)
 {
 	const struct kill_info *ki = (const struct kill_info *)arg;
 
@@ -1538,25 +1538,29 @@ c_kill(const char **wp)
 					shprintf("%d\n", n);
 			}
 		} else {
-			int w, j;
-			int mess_width;
+			int w, j, mess_cols, mess_octs;
 			struct kill_info ki;
 
 			for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10)
 				ki.num_width++;
-			ki.name_width = mess_width = 0;
+			ki.name_width = mess_cols = mess_octs = 0;
 			for (j = 0; j < NSIG; j++) {
 				w = strlen(sigtraps[j].name);
 				if (w > ki.name_width)
 					ki.name_width = w;
 				w = strlen(sigtraps[j].mess);
-				if (w > mess_width)
-					mess_width = w;
+				if (w > mess_octs)
+					mess_octs = w;
+				w = utf_mbswidth(sigtraps[j].mess);
+				if (w > mess_cols)
+					mess_cols = w;
 			}
 
 			print_columns(shl_stdout, NSIG - 1,
 			    kill_fmt_entry, (void *)&ki,
-			    ki.num_width + ki.name_width + mess_width + 3, 1);
+			    ki.num_width + 1 + ki.name_width + 1 + mess_octs,
+			    ki.num_width + 1 + ki.name_width + 1 + mess_cols,
+			    true);
 		}
 		return (0);
 	}
diff --git a/misc.c b/misc.c
index 8313660..f49a39c 100644
--- a/misc.c
+++ b/misc.c
@@ -29,7 +29,7 @@
 #include <grp.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.128 2009/10/30 14:37:43 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.129 2009/11/09 23:35:10 tg Exp $");
 
 unsigned char chtypes[UCHAR_MAX + 1];	/* type bits for unsigned char */
 
@@ -120,12 +120,12 @@ struct options_info {
 	int opts[NELEM(options)];
 };
 
-static char *options_fmt_entry(const void *arg, int, char *, int);
-static void printoptions(int);
+static char *options_fmt_entry(char *, int, int, const void *);
+static void printoptions(bool);
 
 /* format a single select menu item */
 static char *
-options_fmt_entry(const void *arg, int i, char *buf, int buflen)
+options_fmt_entry(char *buf, int buflen, int i, const void *arg)
 {
 	const struct options_info *oi = (const struct options_info *)arg;
 
@@ -136,32 +136,40 @@ options_fmt_entry(const void *arg, int i, char *buf, int buflen)
 }
 
 static void
-printoptions(int verbose)
+printoptions(bool verbose)
 {
-	unsigned int i;
+	int i = 0;
 
 	if (verbose) {
+		int n = 0, len, octs = 0;
 		struct options_info oi;
-		int n, len;
 
 		/* verbose version */
 		shf_puts("Current option settings\n", shl_stdout);
 
-		for (i = n = oi.opt_width = 0; i < NELEM(options); i++)
+		oi.opt_width = 0;
+		while (i < (int)NELEM(options)) {
 			if (options[i].name) {
-				len = strlen(options[i].name);
 				oi.opts[n++] = i;
+				len = strlen(options[i].name);
+				if (len > octs)
+					octs = len;
+				len = utf_mbswidth(options[i].name);
 				if (len > oi.opt_width)
 					oi.opt_width = len;
 			}
+			++i;
+		}
 		print_columns(shl_stdout, n, options_fmt_entry, &oi,
-		    oi.opt_width + 5, 1);
+		    octs + 4, oi.opt_width + 4, true);
 	} else {
-		/* short version ala ksh93 */
+		/* short version รก la AT&T ksh93 */
 		shf_puts("set", shl_stdout);
-		for (i = 0; i < NELEM(options); i++)
+		while (i < (int)NELEM(options)) {
 			if (Flag(i) && options[i].name)
 				shprintf(" -o %s", options[i].name);
+			++i;
+		}
 		shf_putc('\n', shl_stdout);
 	}
 }
@@ -899,53 +907,64 @@ print_value_quoted(const char *s)
 		shf_putc('\'', shl_stdout);
 }
 
-/* Print things in columns and rows - func() is called to format the ith
- * element
+/*
+ * Print things in columns and rows - func() is called to format
+ * the i-th element
  */
 void
 print_columns(struct shf *shf, int n,
-    char *(*func) (const void *, int, char *, int),
-    const void *arg, int max_width, int prefcol)
+    char *(*func)(char *, int, int, const void *),
+    const void *arg, int max_oct, int max_col, bool prefcol)
 {
-	char *str = alloc(max_width + 1, ATEMP);
 	int i, r, c, rows, cols, nspace;
+	char *str;
+
+	if (n <= 0) {
+#ifndef MKSH_SMALL
+		internal_warningf("print_columns called with n=%d <= 0", n);
+#endif
+		return;
+	}
+
+	++max_oct;
+	str = alloc(max_oct, ATEMP);
 
 	/* ensure x_cols is valid first */
 	if (x_cols < MIN_COLS)
 		change_winsz();
 
-	/* max_width + 1 for the space. Note that no space
-	 * is printed after the last column to avoid problems
-	 * with terminals that have auto-wrap.
+	/*
+	 * We use (max_col + 1) to consider the space separator.
+	 * Note that no space is printed after the last column
+	 * to avoid problems with terminals that have auto-wrap.
 	 */
-	cols = x_cols / (max_width + 1);
+	cols = x_cols / (max_col + 1);
+
 	/* if we can only print one column anyway, skip the goo */
 	if (cols < 2) {
 		for (i = 0; i < n; ++i)
 			shf_fprintf(shf, "%s \n",
-			    (*func)(arg, i, str, max_width + 1));
+			    (*func)(str, max_oct, i, arg));
 		goto out;
 	}
-	rows = (n + cols - 1) / cols;
-	if (prefcol && n && cols > rows) {
-		int tmp = rows;
 
-		rows = cols;
-		cols = tmp;
-		if (rows > n)
-			rows = n;
+	rows = (n + cols - 1) / cols;
+	if (prefcol && cols > rows) {
+		i = rows;
+		rows = cols > n ? n : cols;
+		cols = i;
 	}
 
-	nspace = (x_cols - max_width * cols) / cols;
+	max_col = -max_col;
+	nspace = (x_cols + max_col * cols) / cols;
 	if (nspace <= 0)
 		nspace = 1;
 	for (r = 0; r < rows; r++) {
 		for (c = 0; c < cols; c++) {
 			i = c * rows + r;
 			if (i < n) {
-				shf_fprintf(shf, "%-*s",
-				    max_width,
-				    (*func)(arg, i, str, max_width + 1));
+				shf_fprintf(shf, "%*s", max_col,
+				    (*func)(str, max_oct, i, arg));
 				if (c + 1 < cols)
 					shf_fprintf(shf, "%*s", nspace, null);
 			}
diff --git a/sh.h b/sh.h
index 5d83391..5ce64af 100644
--- a/sh.h
+++ b/sh.h
@@ -134,9 +134,9 @@
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.359 2009/10/30 00:57:38 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.360 2009/11/09 23:35:11 tg Exp $");
 #endif
-#define MKSH_VERSION "R39 2009/10/30"
+#define MKSH_VERSION "R39 2009/11/09"
 
 #ifndef MKSH_INCLUDES_ONLY
 
@@ -1352,8 +1352,8 @@ struct tbl *findcom(const char *, int);
 void flushcom(int);
 const char *search(const char *, const char *, int, int *);
 int search_access(const char *, int, int *);
-int pr_menu(const char *const *);
-int pr_list(char *const *);
+int pr_menu(const char * const *);
+int pr_list(char * const *);
 /* expr.c */
 int evaluate(const char *, mksh_ari_t *, int, bool);
 int v_evaluate(struct tbl *, const char *, volatile int, bool);
@@ -1546,8 +1546,8 @@ void ksh_getopt_reset(Getopt *, int);
 int ksh_getopt(const char **, Getopt *, const char *);
 void print_value_quoted(const char *);
 void print_columns(struct shf *, int,
-    char *(*)(const void *, int, char *, int),
-    const void *, int, int prefcol);
+    char *(*)(char *, int, int, const void *),
+    const void *, int, int, bool);
 void strip_nuls(char *, int);
 int blocking_read(int, char *, int)
     __bound_att__((bounded (buffer, 2, 3)));