aboutsummaryrefslogtreecommitdiff
path: root/lib/linestack.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2016-01-17 14:08:10 -0600
committerRob Landley <rob@landley.net>2016-01-17 14:08:10 -0600
commit544c1ec1614cd9a8dcedac3478701e4b97b0f8a0 (patch)
treeb2f0672f0f10be0de36d6a52d51fc78d215413dc /lib/linestack.c
parent5493916370c74944cc796cc91d058fb4ccabe140 (diff)
downloadtoybox-544c1ec1614cd9a8dcedac3478701e4b97b0f8a0.tar.gz
Update draw_str() and friends to do standard escaping for ^X <AB> U+ABCD.
Diffstat (limited to 'lib/linestack.c')
-rw-r--r--lib/linestack.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/lib/linestack.c b/lib/linestack.c
index cc6b6724..83b0e276 100644
--- a/lib/linestack.c
+++ b/lib/linestack.c
@@ -76,25 +76,43 @@ struct linestack *linestack_load(char *name)
return ls;
}
-// Show width many columns, negative means from right edge. Write unprintable
-// chars through escout() instead of write(). If out=0 just measure.
-// Returns width in columns.
+// Show width many columns, negative means from right edge.
+// If out=0 just measure
+// if escout, send it unprintable chars, returns columns output or -1 for
+// standard escape: ^X if <32, <XX> if invliad UTF8, U+XXXX if UTF8 !iswprint()
+// Returns width in columns, moves *str to end of data consumed.
int crunch_str(char **str, int width, FILE *out,
- int (*escout)(FILE *out, wchar_t wc))
+ int (*escout)(FILE *out, int cols, char **buf))
{
- int columns = 0, col, bytes, lowlen = escout(0, 0);
+ int columns = 0, col, bytes;
char *start, *end;
for (end = start = *str; *end;) {
- wchar_t wc;
-
- if (columns+lowlen>width) break;
-
- bytes = mbrtowc(&wc, end, 99, 0);
- if (bytes<0 || wc<32 || (col = wcwidth(wc))<0) {
- bytes = 1;
- col = escout(out, *end);
- } else if (out) fwrite(end, bytes, 1, out);
+ wchar_t wc = *end;
+
+ bytes = 0;
+ if (*end >= ' ' && (bytes = mbrtowc(&wc, end, 99,0))>0
+ && (col = wcwidth(wc))>=0)
+ {
+ if (width-columns<col) break;
+ if (out) fwrite(end, bytes, 1, out);
+ } else if (!escout || 0>(col = escout(out, width-columns, &end))) {
+ char buf[32];
+
+ tty_esc("7m");
+ if (*end < ' ') {
+ bytes = 1;
+ sprintf(buf, "^%c", '@'+*end);
+ } else if (bytes<1) {
+ bytes = 1;
+ sprintf(buf, "<%02X>", *end);
+ } else sprintf(buf, "U+%04X", wc);
+ col = strlen(buf);
+ if (width-columns<col) buf[col = width-columns] = 0;
+ if (out) fputs(buf, out);
+ tty_esc("27m");
+ } else continue;
+ columns += col;
end += bytes;
}
*str = end;
@@ -102,17 +120,20 @@ int crunch_str(char **str, int width, FILE *out,
return columns;
}
-int draw_str(char *start, int width, int (*escout)(FILE *out, wchar_t wc))
+// Write width chars at start of string to strdout with standard escapes
+// Returns length in columns so caller can pad it out with spaces.
+int draw_str(char *start, int width)
{
- return crunch_str(&start, width, stdout, escout);
+ return crunch_str(&start, width, stdout, 0);
}
-int draw_rstr(char *start, int width, int (*escout)(FILE *out, wchar_t wc))
+// Write width chars at end of string to stdout with standard escapes
+int draw_rstr(char *start, int width)
{
char *s = start;
- int len = crunch_str(&s, -1, 0, escout);
+ int len = crunch_str(&s, INT_MAX, 0, 0);
s = start;
- if (len > width) crunch_str(&s, len-width, 0, escout);
- return crunch_str(&s, width, stdout, escout);
+ if (len > width) crunch_str(&s, len-width, 0, 0);
+ return crunch_str(&s, width, stdout, 0);
}