make print_columns() aware that octets≠characters≠columns

This commit is contained in:
tg 2009-11-09 23:35:11 +00:00
parent 6e9d7f33e8
commit fe853065bb
5 changed files with 111 additions and 82 deletions

View File

@ -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:

70
exec.c
View File

@ -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);
}

22
funcs.c
View File

@ -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);
}

85
misc.c
View File

@ -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);
}

12
sh.h
View File

@ -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)));