summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream.c42
-rw-r--r--txr.126
2 files changed, 59 insertions, 9 deletions
diff --git a/stream.c b/stream.c
index 1ecf5400..bf50220f 100644
--- a/stream.c
+++ b/stream.c
@@ -2081,21 +2081,51 @@ static void vformat_num(val stream, const char *str,
vformat_align_post(stream, align, slack);
}
+static cnum calc_fitlen(const wchar_t *cstr, int precision, int width)
+{
+ cnum i, fitlen;
+ wchar_t ch;
+
+ if (width == 0 && precision == 0)
+ return INT_PTR_MAX;
+
+ for (i = 0, fitlen = 0; (ch = cstr[i]) != 0; i++) {
+ int chw = iswcntrl(ch) ? 0 : 1 + wide_display_char_p(ch);
+
+ if (precision && fitlen + chw > precision)
+ break;
+
+ if (width && fitlen + chw > width)
+ return INT_PTR_MAX;
+
+ fitlen += chw;
+ }
+
+ return fitlen;
+}
+
static void vformat_str(val stream, val str, int width, enum align align,
int precision)
{
const wchar_t *cstr = c_str(str);
- int len = c_num(length_str(str));
- int truelen = (precision && precision < len) ? precision : len;
- int slack = (truelen < width) ? width - truelen : 0;
- int i;
+ cnum fitlen = calc_fitlen(cstr, precision, width);
+ cnum slack = (fitlen < width) ? width - fitlen : 0;
+ cnum i, w;
+ wchar_t wc;
prot1(&str);
vformat_align_pre(stream, align, slack);
- for (i = 0; i < truelen; i++)
- put_char(chr(cstr[i]), stream);
+ if (fitlen == INT_PTR_MAX) {
+ put_string(str, stream);
+ } else for (i = 0, w = 0; (wc = cstr[i]) != 0; i++) {
+ int cw = iswcntrl(wc) ? 0 : 1 + wide_display_char_p(wc);
+ if (w + cw > fitlen)
+ break;
+ put_char(chr(wc), stream);
+ w += cw;
+ }
vformat_align_post(stream, align, slack);
diff --git a/txr.1 b/txr.1
index d788c6bb..fe7a8536 100644
--- a/txr.1
+++ b/txr.1
@@ -26945,6 +26945,20 @@ or
prefix character is present in the width
specifier, then the field is adjusted according to that character.
+The padding calculations for alignment and centering take into account
+character display width, as defined by the
+.code display-width
+function. For instance, a character string containing four Chinese
+characters (kanji) has a display width of 8, not 4.
+
+The width specification does not restrict the printed portion of a datum.
+Rather, for some kinds of conversions, it is the precision specification that
+performs such truncation. A datum's display width (or that of its printed
+portion, after such truncation is applied) can equal or exceed the specified
+field width. In this situation it overflows the field: the printed portion is
+rendered in its entirety without any padding applied on either side for
+alignment or centering.
+
.meIP < precision
The precision specifier is introduced by a leading comma. If this comma appears
immediately after the directive's
@@ -27007,9 +27021,15 @@ numbers are unconditionally prefixed with a
.code -
sign.
-For all other objects, the precision specifies the maximum number of characters
-to print. The object's printed representation is crudely truncated at that
-number of characters.
+For all other objects, the precision specifies the maximum number of
+print positions to occupy, taking into account the display width of each
+character of the printed representation of the object, as according
+to the
+.code display-width
+function. The object's printed representation is truncated, if necessary, to
+the maximum number of characters which will not exceed the specified number of
+print positions.
+
.RE
.TP* "Format directives:"