From ba86864699997b0da780e15fd6be33c8a556e927 Mon Sep 17 00:00:00 2001
From: Rob Landley <rob@landley.net>
Date: Sun, 17 Jan 2016 17:16:03 -0600
Subject: Extend utf8 fontmetrics so ps can use them.

Also, I forgot to check in uuid_show() last time.
---
 lib/lib.c            | 11 +++++++++++
 lib/lib.h            |  5 ++++-
 lib/linestack.c      | 36 +++++++++++++++++++++++++++++-------
 toys/other/hexedit.c |  2 +-
 toys/posix/ps.c      | 31 +++++++++++++++++--------------
 5 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/lib/lib.c b/lib/lib.c
index 871eda7e..955960ca 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -988,3 +988,14 @@ void create_uuid(char *uuid)
   // should never collide with anybody actually using a macaddr.
   uuid[11] |= 128;
 }
+
+char *show_uuid(char *uuid)
+{
+  char *out = libbuf;
+  int i;
+
+  for (i=0; i<16; i++) out+=sprintf(out, "-%02x"+!(0x550&(1<<i)), uuid[i]);
+  *out = 0;
+
+  return libbuf;
+}
diff --git a/lib/lib.h b/lib/lib.h
index 2338037c..f1cea22e 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -195,6 +195,7 @@ void base64_init(char *p);
 int yesno(int def);
 int qstrcmp(const void *a, const void *b);
 void create_uuid(char *uuid);
+char *show_uuid(char *uuid);
 
 #define HR_SPACE 1 // Space between number and units
 #define HR_B     2 // Use "B" for single byte units
@@ -216,7 +217,9 @@ struct linestack *linestack_load(char *name);
 int crunch_str(char **str, int width, FILE *out,
   int (*escout)(FILE *out, int cols, char **buf));
 int draw_str(char *start, int width);
-int draw_rstr(char *start, int width);
+int utf8len(char *str);
+int utf8skip(char *str, int width);
+int draw_trim(char *str, int padto, int width);
 
 // interestingtimes.c
 int xgettty(void);
diff --git a/lib/linestack.c b/lib/linestack.c
index 83b0e276..241a437d 100644
--- a/lib/linestack.c
+++ b/lib/linestack.c
@@ -127,13 +127,35 @@ int draw_str(char *start, int width)
   return crunch_str(&start, width, stdout, 0);
 }
 
-// Write width chars at end of string to stdout with standard escapes
-int draw_rstr(char *start, int width)
+// Return utf8 columns
+int utf8len(char *str)
 {
-  char *s = start;
-  int len = crunch_str(&s, INT_MAX, 0, 0);
+  return crunch_str(&str, INT_MAX, 0, 0);
+}
+
+// Return bytes used by (up to) this many columns
+int utf8skip(char *str, int width)
+{
+  char *s = str;
+
+  crunch_str(&s, width, 0, 0);
+
+  return s-str;
+}
+
+// Print utf8 to stdout with standard escapes,trimmed to width and padded
+// out to padto. If padto<0 left justify. Returns columns printed
+int draw_trim(char *str, int padto, int width)
+{
+  int apad = abs(padto), len = utf8len(str);
+
+  if (padto<0 && len>width) str += utf8skip(str, len-width);
+  if (len>width) len = width;
+
+  // Left pad if right justified 
+  if (padto>0 && apad>len) printf("%*s", apad-len, "");
+  crunch_str(&str, len, stdout, 0);
+  if (padto<0 && apad>len) printf("%*s", apad-len, "");
 
-  s = start;
-  if (len > width) crunch_str(&s, len-width, 0, 0);
-  return crunch_str(&s, width, stdout, 0);
+  return (apad > len) ? apad : len;
 }
diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c
index b2e32c0e..ff13b513 100644
--- a/toys/other/hexedit.c
+++ b/toys/other/hexedit.c
@@ -56,7 +56,7 @@ static void draw_tail(void)
   tty_jump(0, TT.height);
   tty_esc("K");
 
-  draw_rstr(*toys.optargs, 71);
+  draw_trim(*toys.optargs, -1, 71);
 }
 
 static void draw_line(long long yy)
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index 8dbc0984..a7ba5b37 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -36,9 +36,9 @@
  *       at right edge? (Not adjusting to screen size at all? Header wraps?)
  * TODO: utf8 fontmetrics
 
-USE_PS(NEWTOY(ps, "k(sort)*P(ppid)*aAdeflno*p(pid)*s*t*u*U*g*G*wZ[!ol][+Ae]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PS(NEWTOY(ps, "k(sort)*P(ppid)*aAdeflno*p(pid)*s*t*u*U*g*G*wZ[!ol][+Ae]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_TTOP(NEWTOY(ttop, ">0d#=3n#<1mb", TOYFLAG_USR|TOYFLAG_BIN))
-USE_IOTOP(NEWTOY(iotop, "Aabkoqp*u*d#n#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_IOTOP(NEWTOY(iotop, "Aabkoqp*u*d#n#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
 USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PKILL(NEWTOY(pkill,      "u*U*t*s*P*g*G*fnovxl:", TOYFLAG_USR|TOYFLAG_BIN))
 
@@ -506,22 +506,24 @@ static char *string_field(struct carveup *tb, struct strawberry *field)
 static void show_ps(struct carveup *tb)
 {
   struct strawberry *field;
-  int i, len, width = TT.width;
+  int pad, len, width = TT.width;
 
   // Loop through fields to display
   for (field = TT.fields; field; field = field->next) {
     char *out = string_field(tb, field);
 
     // Output the field, appropriately padded
-    len = width - (field != TT.fields);
-    if (!field->next && field->len<0) i = 0;
-    else {
-      i = len<abs(field->len) ? len : field->len;
-      len = abs(i);
+    if (field != TT.fields) {
+      putchar(' ');
+      width--;
     }
+    len = width;
+    pad = 0;
+    if (field->next || field->len>0)
+      len = abs(pad = width<abs(field->len) ? width : field->len);
 
-    // TODO test utf8 fontmetrics
-    width -= printf(" %*.*s" + (field == TT.fields), i, len, out);
+    if (TT.tty) width -= draw_trim(out, pad, len);
+    else width -= printf("%*.*s", pad, len, out);
     if (!width) break;
   }
   xputc('\n');
@@ -569,9 +571,10 @@ static int get_ps(struct dirtree *new)
   for (j = 1; j<50; j++) if (1>sscanf(s += i, " %lld%n", slot+j, &i)) break;
 
   // Now we've read the data, move status and name right after slot[] array,
-  // and convert low chars to ? while we're at it.
+  // and convert low chars to ? for non-tty display while we're at it.
   for (i = 0; i<end-name; i++)
-    if ((tb->str[i] = name[i]) < ' ') tb->str[i] = '?';
+    if ((tb->str[i] = name[i]) < ' ')
+      if (!TT.tty) tb->str[i] = '?';
   buf = tb->str+i;
   *buf++ = 0;
   len = sizeof(toybuf)-(buf-toybuf);
@@ -714,14 +717,14 @@ static int get_ps(struct dirtree *new)
 
         if (buf[len-1]=='\n') buf[--len] = 0;
 
-        // Turn NUL to space, other low ascii to ?
+        // Turn NUL to space, other low ascii to ? (in non-tty mode)
         for (i=0; i<len; i++) {
           char c = buf[i];
 
           if (!c) {
             if (!temp) temp = i;
             c = ' ';
-          } else if (c<' ') c = '?';
+          } else if (!TT.tty && c<' ') c = '?';
           buf[i] = c;
         }
         len = temp; // position of _first_ NUL
-- 
cgit v1.2.3