make print_columns() aware that octets≠characters≠columns
This commit is contained in:
parent
6e9d7f33e8
commit
fe853065bb
4
check.t
4
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:
|
||||
|
70
exec.c
70
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);
|
||||
}
|
||||
|
22
funcs.c
22
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);
|
||||
}
|
||||
|
85
misc.c
85
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);
|
||||
}
|
||||
|
12
sh.h
12
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)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user