OSDN Git Service

Factor out draw_str() and friends.
authorRob Landley <rob@landley.net>
Thu, 24 Dec 2015 00:16:23 +0000 (18:16 -0600)
committerRob Landley <rob@landley.net>
Thu, 24 Dec 2015 00:16:23 +0000 (18:16 -0600)
lib/lib.h
lib/linestack.c [new file with mode: 0644]
toys/other/hexedit.c
toys/pending/vi.c

index 750e124..b0d7f36 100644 (file)
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -3,6 +3,16 @@
  * Copyright 2006 Rob Landley <rob@landley.net>
  */
 
+struct ptr_len {
+  void *ptr;
+  long len;
+};
+
+struct str_len {
+  char *str;
+  long len;
+};
+
 // llist.c
 
 // All these list types can be handled by the same code because first element
@@ -24,11 +34,6 @@ struct double_list {
   char *data;
 };
 
-struct ptr_len {
-  void *ptr;
-  long len;
-};
-
 void llist_free_arg(void *node);
 void llist_free_double(void *node);
 void llist_traverse(void *list, void (*using)(void *node));
@@ -193,6 +198,23 @@ int xpoll(struct pollfd *fds, int nfds, int timeout);
 #define HR_1000  4 // Use decimal instead of binary units
 int human_readable(char *buf, unsigned long long num, int style);
 
+// linestack.c
+
+struct linestack {
+  long len, max;
+  struct ptr_len idx[];
+};
+
+void linestack_addstack(struct linestack **lls, struct linestack *throw,
+  long pos);
+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));
+
 // interestingtimes.c
 int xgettty(void);
 int terminal_size(unsigned *xx, unsigned *yy);
@@ -234,6 +256,8 @@ struct mtab_list {
   char type[0];
 };
 
+void comma_args(struct arg_list *al, void *data, char *err,
+  char *(*callback)(void *data, char *str, int len));
 void comma_collate(char **old, char *new);
 char *comma_iterate(char **list, int *len);
 int comma_scan(char *optlist, char *opt, int clean);
@@ -256,6 +280,8 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name));
 pid_t xvforkwrap(pid_t pid);
 #define XVFORK() xvforkwrap(vfork())
 
+// Wrapper to make xfuncs() return (via longjmp) instead of exiting.
+// Assigns true/false "did it exit" value to first argument.
 #define WOULD_EXIT(y, x) do { jmp_buf _noexit; \
   int _noexit_res; \
   toys.rebound = &_noexit; \
@@ -265,6 +291,7 @@ pid_t xvforkwrap(pid_t pid);
   y = _noexit_res; \
 } while(0);
 
+// Wrapper that discards true/false "did it exit" value.
 #define NOEXIT(x) WOULD_EXIT(_noexit_res, x)
 
 // Functions in need of further review/cleanup
diff --git a/lib/linestack.c b/lib/linestack.c
new file mode 100644 (file)
index 0000000..b06c97e
--- /dev/null
@@ -0,0 +1,118 @@
+#include "toys.h"
+
+// Insert one stack into another before position in old stack.
+// (Does not copy contents of strings, just shuffles index array contents.)
+void linestack_addstack(struct linestack **lls, struct linestack *throw,
+  long pos)
+{
+  struct linestack *catch = *lls;
+
+  if (CFG_TOYBOX_DEBUG)
+    if (pos > catch->len) error_exit("linestack_addstack past end.");
+
+  // Make a hole, allocating more space if necessary.
+  if (catch->len+throw->len >= catch->max) {
+    // New size rounded up to next multiple of 64, allocate and copy start.
+    catch->max = ((catch->len+throw->len)|63)+1;
+    *lls = xmalloc(sizeof(struct linestack)+catch->max*sizeof(struct ptr_len));
+    memcpy(*lls, catch, sizeof(struct linestack)+pos*sizeof(struct ptr_len));
+  }
+
+  // Copy end (into new allocation if necessary)
+  if (pos != catch->len)
+    memmove((*lls)->idx+pos+throw->len, catch->idx+pos,
+      (catch->len-pos)*sizeof(struct ptr_len));
+
+  // Cleanup if we had to realloc.
+  if (catch != *lls) {
+    free(catch);
+    catch = *lls;
+  }
+
+  memcpy(catch->idx+pos, throw->idx, throw->len*sizeof(struct ptr_len));
+  catch->len += throw->len;
+}
+
+void linestack_insert(struct linestack **lls, long pos, char *line, long len)
+{
+  // alloca() was in 32V and Turbo C for DOS, but isn't in posix or c99.
+  // I'm not thrashing the heap for this, but this should work even if
+  // a broken compiler adds gratuitous padding.
+  struct {
+    struct linestack ls;
+    struct ptr_len pl;
+  } ls;
+
+  ls.ls.len = ls.ls.max = 1;
+  ls.ls.idx[0].ptr = line;
+  ls.ls.idx[0].len = len;
+  linestack_addstack(lls, &ls.ls, pos);
+}
+
+void linestack_append(struct linestack **lls, char *line)
+{
+  linestack_insert(lls, (*lls)->len, line, strlen(line));
+}
+
+struct linestack *linestack_load(char *name)
+{
+  FILE *fp = fopen(name, "r");
+  struct linestack *ls;
+
+  if (!fp) return 0;
+
+  ls = xzalloc(sizeof(struct linestack));
+
+  for (;;) {
+    char *line = 0;
+    ssize_t len;
+
+    if ((len = getline(&line, (void *)&len, fp))<1) break;
+    if (line[len-1]=='\n') len--;
+    linestack_insert(&ls, ls->len, line, len);
+  }
+  fclose(fp);
+
+  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.
+int crunch_str(char **str, int width, FILE *out,
+  int (*escout)(FILE *out, wchar_t wc))
+{
+  int columns = 0, col, bytes, lowlen = escout(0, 0);
+  char *start, *end;
+
+  for (end = start = *str; *end;) {
+    wchar_t wc;
+
+    if (width>=0 && 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);
+    end += bytes;
+  }
+  *str = end;
+
+  return columns;
+}
+
+int draw_str(char *start, int width, int (*escout)(FILE *out, wchar_t wc))
+{
+  return crunch_str(&start, width, stdout, escout);
+}
+
+int draw_rstr(char *start, int width, int (*escout)(FILE *out, wchar_t wc))
+{
+  char *s = start;
+  int len = crunch_str(&s, -1, 0, escout);
+
+  s = start;
+  if (len > width) crunch_str(&s, len-width, 0, escout);
+  return crunch_str(&s, width, stdout, escout);
+}
index a52d66d..1c2ad88 100644 (file)
@@ -30,55 +30,33 @@ GLOBALS(
 #define UNDO_LEN (sizeof(toybuf)/(sizeof(long long)+1))
 
 // Render all characters printable, using color to distinguish.
-static void draw_char(char broiled)
+static int draw_char(FILE *fp, wchar_t broiled)
 {
-  if (broiled<32 || broiled>=127) {
-    if (broiled>127) {
-      tty_esc("2m");
-      broiled &= 127;
-    }
-    if (broiled<32 || broiled==127) {
-      tty_esc("7m");
-      if (broiled==127) broiled = 32;
-      else broiled += 64;
-    }
-    printf("%c", broiled);
-    tty_esc("0m");
-  } else printf("%c", broiled);
+  if (fp) {
+    if (broiled<32 || broiled>=127) {
+      if (broiled>127) {
+        tty_esc("2m");
+        broiled &= 127;
+      }
+      if (broiled<32 || broiled==127) {
+        tty_esc("7m");
+        if (broiled==127) broiled = 32;
+        else broiled += 64;
+      }
+      printf("%c", broiled);
+      tty_esc("0m");
+    } else printf("%c", broiled);
+  }
+
+  return 1;
 }
 
 static void draw_tail(void)
 {
-  int i = 0, width = 0, w, len;
-  char *start = *toys.optargs, *end;
-
   tty_jump(0, TT.height);
   tty_esc("K");
 
-  // First time, make sure we fit in 71 chars (advancing start as necessary).
-  // Second time, print from start to end, escaping nonprintable chars.
-  for (i=0; i<2; i++) {
-    for (end = start; *end;) {
-      wchar_t wc;
-
-      len = mbrtowc(&wc, end, 99, 0);
-      if (len<0 || wc<32 || (w = wcwidth(wc))<0) {
-        len = w = 1;
-        if (i) draw_char(*end);
-      } else if (i) fwrite(end, len, 1, stdout);
-      end += len;
-
-      if (!i) {
-        width += w;
-        while (width > 71) {
-          len = mbrtowc(&wc, start, 99, 0);
-          if (len<0 || wc<32 || (w = wcwidth(wc))<0) len = w = 1;
-          width -= w;
-          start += len;
-        }
-      }
-    }
-  }
+  draw_rstr(*toys.optargs, 71, draw_char);
 }
 
 static void draw_line(long long yy)
@@ -92,7 +70,7 @@ static void draw_line(long long yy)
     printf("\r%0*llX ", TT.numlen, yy);
     for (x=0; x<xx; x++) printf(" %02X", TT.data[yy+x]);
     printf("%*s", 2+3*(16-xx), "");
-    for (x=0; x<xx; x++) draw_char(TT.data[yy+x]);
+    for (x=0; x<xx; x++) draw_char(stdout, TT.data[yy+x]);
     printf("%*s", 16-xx, "");
   }
   tty_esc("K");
@@ -127,7 +105,7 @@ static void highlight(int xx, int yy, int side)
   }
   tty_esc("0m");
   tty_jump(TT.numlen+17*3+xx, yy);
-  draw_char(cc);
+  draw_char(stdout, cc);
 }
 
 void hexedit_main(void)
index 20d765c..bf8db84 100644 (file)
@@ -24,85 +24,16 @@ GLOBALS(
   char *statline;
 )
 
-struct linestack {
-  long len, max;
-  struct ptr_len idx[];
+struct linestack_show {
+  struct linestack_show *next;
+  long top, left;
+  int x, width, y, height;
 };
 
-// Insert one stack into another before position in old stack.
-// (Does not copy contents of strings, just shuffles index array contents.)
-void linestack_addstack(struct linestack **lls, struct linestack *throw,
-  long pos)
+// linestack, what to show, where to show it
+void linestack_show(struct linestack *ls, struct linestack_show *lss)
 {
-  struct linestack *catch = *lls;
-
-  if (CFG_TOYBOX_DEBUG)
-    if (pos > catch->len) error_exit("linestack_addstack past end.");
-
-  // Make a hole, allocating more space if necessary.
-  if (catch->len+throw->len >= catch->max) {
-    // New size rounded up to next multiple of 64, allocate and copy start.
-    catch->max = ((catch->len+throw->len)|63)+1;
-    *lls = xmalloc(sizeof(struct linestack)+catch->max*sizeof(struct ptr_len));
-    memcpy(*lls, catch, sizeof(struct linestack)+pos*sizeof(struct ptr_len));
-  }
-
-  // Copy end (into new allocation if necessary)
-  if (pos != catch->len)
-    memmove((*lls)->idx+pos+throw->len, catch->idx+pos,
-      (catch->len-pos)*sizeof(struct ptr_len));
-
-  // Cleanup if we had to realloc.
-  if (catch != *lls) {
-    free(catch);
-    catch = *lls;
-  }
-
-  memcpy(catch->idx+pos, throw->idx, throw->len*sizeof(struct ptr_len));
-  catch->len += throw->len;
-}
-
-void linestack_insert(struct linestack **lls, long pos, char *line, long len)
-{
-  // alloca() was in 32V and Turbo C for DOS, but isn't in posix or c99.
-  // I'm not thrashing the heap for this, but this should work even if
-  // a broken compiler adds gratuitous padding.
-  struct {
-    struct linestack ls;
-    struct ptr_len pl;
-  } ls;
-
-  ls.ls.len = ls.ls.max = 1;
-  ls.ls.idx[0].ptr = line;
-  ls.ls.idx[0].len = len;
-  linestack_addstack(lls, &ls.ls, pos);
-}
-
-void linestack_append(struct linestack **lls, char *line)
-{
-  linestack_insert(lls, (*lls)->len, line, strlen(line));
-}
-
-struct linestack *linestack_load(char *name)
-{
-  FILE *fp = fopen(name, "r");
-  struct linestack *ls;
-
-  if (!fp) return 0;
-
-  ls = xzalloc(sizeof(struct linestack));
-
-  for (;;) {
-    char *line = 0;
-    ssize_t len;
-
-    if ((len = getline(&line, (void *)&len, fp))<1) break;
-    if (line[len-1]=='\n') len--;
-    linestack_insert(&ls, ls->len, line, len);
-  }
-  fclose(fp);
-
-  return ls;
+  return;
 }
 
 void vi_main(void)