OSDN Git Service

Update draw_str() and friends to do standard escaping for ^X <AB> U+ABCD.
authorRob Landley <rob@landley.net>
Sun, 17 Jan 2016 20:08:10 +0000 (14:08 -0600)
committerRob Landley <rob@landley.net>
Sun, 17 Jan 2016 20:08:10 +0000 (14:08 -0600)
lib/lib.h
lib/linestack.c
toys/other/hexedit.c

index 0c6d379..2338037 100644 (file)
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -214,9 +214,9 @@ void linestack_insert(struct linestack **lls, long pos, char *line, long len);
 void linestack_append(struct linestack **lls, char *line);
 struct linestack *linestack_load(char *name);
 int crunch_str(char **str, int width, FILE *out,
-  int (*escout)(FILE *out, wchar_t wc));
-int draw_str(char *start, int width, int (*escout)(FILE *out, wchar_t wc));
-int draw_rstr(char *start, int width, int (*escout)(FILE *out, wchar_t wc));
+  int (*escout)(FILE *out, int cols, char **buf));
+int draw_str(char *start, int width);
+int draw_rstr(char *start, int width);
 
 // interestingtimes.c
 int xgettty(void);
index cc6b672..83b0e27 100644 (file)
@@ -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);
 }
index c86d75e..b2e32c0 100644 (file)
@@ -56,7 +56,7 @@ static void draw_tail(void)
   tty_jump(0, TT.height);
   tty_esc("K");
 
-  draw_rstr(*toys.optargs, 71, draw_char);
+  draw_rstr(*toys.optargs, 71);
 }
 
 static void draw_line(long long yy)
@@ -127,7 +127,7 @@ void hexedit_main(void)
   fflush(0);
   xset_terminal(1, 1, 0);
 
-  if ((TT.len = fdlength(fd))<0) error_exit("bad length");
+  if ((TT.len = fdlength(fd))<1) error_exit("bad length");
   if (sizeof(long)==32 && TT.len>SIZE_MAX) TT.len = SIZE_MAX;
   // count file length hex in digits, rounded up to multiple of 4
   for (pos = TT.len, TT.numlen = 0; pos; pos >>= 4, TT.numlen++);
@@ -139,7 +139,7 @@ void hexedit_main(void)
   for (;;) {
     // Scroll display if necessary
     if (pos<0) pos = 0;
-    if (pos>TT.len) pos = TT.len-1;
+    if (pos>=TT.len) pos = TT.len-1;
     x = pos&15;
     y = pos/16;
 
@@ -214,7 +214,7 @@ void hexedit_main(void)
         TT.data[pos] = toybuf[sizeof(long long)*UNDO_LEN+TT.undo];
       }
     }
-    if (key>256) {
+    if (key>=256) {
       key -= 256;
 
       if (key==KEY_UP) pos -= 16;