From be46b9da31c7d2b6ac30ea3c62a32016f9482177 Mon Sep 17 00:00:00 2001 From: pancake Date: Wed, 17 Jul 2013 19:34:27 +0200 Subject: [PATCH] Initial support for truecolor (xterm only) Add e scr.truecolor variable Add !! command to save history Add ec: command to randomize palette Minor rgb trash fix, --- libr/cons/cons.c | 1 + libr/cons/d/Makefile | 1 + libr/cons/d/{xvilka => dark} | 0 libr/cons/pal.c | 34 ++++++++++++++----- libr/cons/rgb.c | 65 ++++++++++++++++++++++++++---------- libr/core/cmd.c | 64 ++++++++++++++++------------------- libr/core/config.c | 7 ++++ libr/core/disasm.c | 5 ++- libr/core/file.c | 3 +- libr/core/vmenus.c | 36 ++++++++------------ libr/include/r_cons.h | 6 ++-- libr/util/str.c | 4 +-- 12 files changed, 135 insertions(+), 91 deletions(-) rename libr/cons/d/{xvilka => dark} (100%) diff --git a/libr/cons/cons.c b/libr/cons/cons.c index 87b4f2c66a9b4..0bda1882e44ad 100644 --- a/libr/cons/cons.c +++ b/libr/cons/cons.c @@ -143,6 +143,7 @@ R_API RCons *r_cons_new () { eprintf ("r_cons: Cannot set control console handler\n"); #endif I.pager = NULL; /* no pager by default */ + I.truecolor = 0; r_cons_pal_init (NULL); r_cons_rgb_init (); r_cons_reset (); diff --git a/libr/cons/d/Makefile b/libr/cons/d/Makefile index 8b84b0642f232..db9331dc096e9 100644 --- a/libr/cons/d/Makefile +++ b/libr/cons/d/Makefile @@ -6,6 +6,7 @@ all clean: .PHONY: all clean install install-symlink symstall install: ${F_SDB} + rm -rf $P mkdir -p $P cp -f * $P diff --git a/libr/cons/d/xvilka b/libr/cons/d/dark similarity index 100% rename from libr/cons/d/xvilka rename to libr/cons/d/dark diff --git a/libr/cons/pal.c b/libr/cons/pal.c index f693e63f976ed..cdac2bd0b6fd7 100644 --- a/libr/cons/pal.c +++ b/libr/cons/pal.c @@ -14,6 +14,8 @@ R_API void r_cons_pal_init(const char *foo) { cons->pal.flag = Color_CYAN; cons->pal.label = Color_CYAN; cons->pal.flow = Color_CYAN; + cons->pal.math = Color_YELLOW; + cons->pal.bin = Color_RED; cons->pal.b0x00 = Color_GREEN; cons->pal.b0x7f = Color_CYAN; cons->pal.b0xff = Color_RED; @@ -48,6 +50,7 @@ struct { { "cyan", Color_CYAN, Color_BGCYAN }, { "blue", Color_BLUE, Color_BGBLUE }, { "gray", Color_GRAY, Color_BGGRAY }, + { "none", Color_RESET, Color_RESET }, { NULL, NULL, NULL } }; @@ -57,6 +60,22 @@ static inline ut8 rgbnum (const char ch) { return r*16; } +R_API void r_cons_pal_random() { + ut8 r, g, b; + char val[32]; + const char *k; + int i; + for (i=0;;i++) { + k = r_cons_pal_get_i (i); + if (!k) break; + r = r_num_rand (0xf); + g = r_num_rand (0xf); + b = r_num_rand (0xf); + sprintf (val, "rgb:%x%x%x", r, g, b); + r_cons_pal_set (k, val); + } +} + R_API char *r_cons_pal_parse(const char *str) { int i; ut8 r, g, b; @@ -107,8 +126,6 @@ static struct { { "math", r_offsetof (RConsPalette, math) }, { "bin", r_offsetof (RConsPalette, bin) }, { "btext", r_offsetof (RConsPalette, btext) }, - { "math", r_offsetof (RConsPalette, math) }, - { "bin", r_offsetof (RConsPalette, bin) }, { "push", r_offsetof (RConsPalette, push) }, { "pop", r_offsetof (RConsPalette, pop) }, { "jmp", r_offsetof (RConsPalette, jmp) }, @@ -203,17 +220,16 @@ R_API void r_cons_pal_list (int rad) { int i; for (i=0; keys[i].name; i++) { color = (char**)(p + keys[i].off); - color = (char**)*color; if (rad) { r = g = b = 0; - r_cons_rgb_parse (color, &r, &g, &b, NULL); + r_cons_rgb_parse (*color, &r, &g, &b, NULL); rgbstr[0] = 0; r_cons_rgb_str (rgbstr, r, g, b, 0); - r >>=4; - g >>=4; - b >>=4; - r_cons_printf ("ec %s %srgb:%x%x%x"Color_RESET " # vs %sTEST"Color_RESET"\n", - keys[i].name, color, r, g, b, rgbstr); + r >>= 4; + g >>= 4; + b >>= 4; + r_cons_printf ("ec %s rgb:%x%x%x\n", //Color_RESET " # vs %sTEST"Color_RESET"\n", + keys[i].name, r, g, b); } else r_cons_printf (" %s##"Color_RESET" %s\n", (color)? (char*)color: "", keys[i].name); diff --git a/libr/cons/rgb.c b/libr/cons/rgb.c index 00fdf2e343a36..4fdc467970299 100644 --- a/libr/cons/rgb.c +++ b/libr/cons/rgb.c @@ -1,5 +1,6 @@ /* radare - LGPL - Copyright 2013 - pancake */ /* ansi 256 color extension for r_cons */ +/* https://en.wikipedia.org/wiki/ANSI_color */ #include @@ -39,28 +40,52 @@ R_API void r_cons_rgb_init (void) { } R_API int r_cons_rgb_parse (const char *p, ut8 *r, ut8 *g, ut8 *b, int *is_bg) { + const char *q = 0; + int isbg = 0, bold=127; //const double k = (256/6); if (!p) return 0; if (*p==0x1b) p++; if (*p!='[') return 0; - if (p[3]==';') { - int R,G,B,n = atoi (p+6); - n-=16; - B = (n&3) * 2.3; - G = ((n>>3)&3) * 2.3; - R = ((n>>6)&3) * 2.3; - - if (r) *r = R* 42.2; - if (g) *g = G*42.2; - if (b) *b = B*42.2; - //n = (r*36) + (g*6) + b; - // b = n - (r*36) - (g*6) - // r = (n-b-(g*6))/36 - if (is_bg) *is_bg = (atoi (p+1) == 48)?1:0; + switch (p[1]) { + case '1': bold=255; p+=2; break; + case '3': isbg=0; break; + case '4': isbg=1; break; + } +#define SETRGB(x,y,z) if(r)*r=x;if(g)*g=y;if(b)*b=z + if (bold != 255 && strchr (p, ';')) { + if (p[4]=='5') { + /* indexed rgb cube */ + int x, y, z; + // TODO :Implement colors.txt + SETRGB (0,0,0); + } else { + /* truecolor */ + p += 6; + /* complex rgb */ + if (r) *r = atoi (p); + q = strchr (p, ';'); + if (!q) return 0; + if (g) *g = atoi (q+1); + q = strchr (q+1, ';'); + if (!q) return 0; + if (b) *b = atoi (q+1); + } return 1; + } else { + /* plain ansi */ + if (is_bg) is_bg = isbg; + switch (p[2]) { + case '0': SETRGB (0,0,0); break; + case '1': SETRGB (bold,0,0); break; + case '2': SETRGB (0,bold,0); break; + case '3': SETRGB (bold,bold,0); break; + case '4': SETRGB (0,0,bold); break; + case '5': SETRGB (bold,0,bold); break; + case '6': SETRGB (0,bold,bold); break; + case '7': SETRGB (bold,bold,bold); break; + } } - // TODO support ansi - return 0; + return 1; } R_API char *r_cons_rgb_str (char *outstr, ut8 r, ut8 g, ut8 b, int is_bg) { @@ -68,7 +93,13 @@ R_API char *r_cons_rgb_str (char *outstr, ut8 r, ut8 g, ut8 b, int is_bg) { k = (r == g && g == b)? gs (r): rgb (r, g, b); //k = rgb (r, g, b); if (!outstr) outstr = malloc (32); - sprintf (outstr, "\x1b[%d;5;%dm", fgbg, k); + + if (r_cons_singleton()->truecolor) // only for xterm + sprintf (outstr, "\x1b[%d;2;%d;%d;%dm", fgbg, + R_DIM (r, 0, 255), + R_DIM (g, 0, 255), + R_DIM (b, 0, 255)); + else sprintf (outstr, "\x1b[%d;5;%dm", fgbg, k); return outstr; } diff --git a/libr/core/cmd.c b/libr/core/cmd.c index 947a9ab0ab813..392818cb52406 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -442,7 +442,6 @@ static int cmd_resize(void *data, const char *input) { oldsize < core->offset+core->blocksize) { r_core_block_read (core, 0); } - return R_TRUE; } @@ -455,15 +454,20 @@ static int cmd_eval(void *data, const char *input) { case 'c': switch (input[1]) { case '?': - r_cons_printf ("Usage: ec[s?] [key][[=| ]fg] [bg]\n"); - r_cons_printf (" ec list all color keys\n"); - r_cons_printf (" ec* (TODO) same as above, but using r2 commands\n"); - r_cons_printf (" ecs show a colorful palette\n"); - r_cons_printf (" ecf white load white color scheme from $DATADIR/radare2/cons\n"); - r_cons_printf (" ec prompt red change coloro of prompt\n"); - r_cons_printf ("Available colors:\n"); - r_cons_printf (" rgb:000 24 bit hexadecimal rgb color\n"); - r_cons_printf (" red|green|blue|. well known ansi colors\n"); + r_cons_printf ("Usage: ec[s?] [key][[=| ]fg] [bg]\n" + " ec list all color keys\n" + " ec* (TODO) same as above, but using r2 commands\n" + " ec: set random palete\n" + " ecs show a colorful palette\n" + " ecf dark|white load white color scheme template\n" + " ec prompt red change coloro of prompt\n" + "Available colors:\n" + " rgb:000 24 bit hexadecimal rgb color\n" + " red|green|blue|. well known ansi colors\n" + "See:\n" + " e scr.rgbcolor = true|false for 256 color cube\n" + " e scr.truecolor = true|false for 256*256*256 colors\n" + " $DATADIR/radare2/cons ~/.config/radare2/cons ./\n"); break; case 'f': if (input[2] == ' ') { @@ -472,20 +476,20 @@ static int cmd_eval(void *data, const char *input) { home = r_str_home (path); snprintf (path, sizeof (path), R2_DATDIR"/radare2/" R2_VERSION"/cons/%s", input+3); - if (!r_core_cmd_file (core, home)) { - if (!r_core_cmd_file (core, path)) { - eprintf ("Oops. Cannot find cons %s\n", path); - } - } + if (!r_core_cmd_file (core, home)) + if (!r_core_cmd_file (core, path)) + if (!r_core_cmd_file (core, input+3)) + eprintf ("ecf: cannot open colorscheme profile\n"); free (home); } else { // TODO: lof stuff - eprintf ("Invalid argument.\n"); + eprintf ("Usage: ecf [themename].\n"); } break; case 's': r_cons_pal_show (); break; case '*': r_cons_pal_list (1); break; case '\0': r_cons_pal_list (0); break; + case ':': r_cons_pal_random (); break; default:{ char *p = strdup (input+2); char *q = strchr (p, '='); @@ -495,8 +499,8 @@ static int cmd_eval(void *data, const char *input) { *q++ = 0; r_cons_pal_set (p, q); } else { - // get - eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, r_cons_pal_get (p)); + const char *k = r_cons_pal_get (p); + if (k) eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k); } } } @@ -522,20 +526,12 @@ static int cmd_eval(void *data, const char *input) { r_core_config_init (core); eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n"); break; - case 'v': - eprintf ("Invalid command '%s'. Use 'e?'\n", input); - break; - case '*': - r_config_list (core->config, NULL, 1); - break; + case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); break; + case '*': r_config_list (core->config, NULL, 1); break; case '?': switch (input[1]) { - case '?': - r_config_list (core->config, input+2, 2); - break; - default: - r_config_list (core->config, input+1, 2); - break; + case '?': r_config_list (core->config, input+2, 2); break; + default: r_config_list (core->config, input+1, 2); break; case 0: r_cons_printf ( "Usage: e[?] [var[=value]]\n" @@ -559,11 +555,8 @@ static int cmd_eval(void *data, const char *input) { eprintf ("cannot find key '%s'\n", key); } else eprintf ("Usage: er [key]\n"); break; - case ' ': - r_config_eval (core->config, input+1); - break; - default: - r_config_eval (core->config, input); + case ' ': r_config_eval (core->config, input+1); break; + default: r_config_eval (core->config, input); break; } return 0; } @@ -599,6 +592,7 @@ static int cmd_system(void *data, const char *input) { free (cmd); } //else eprintf ("Error setting up system environment\n"); } else { + eprintf ("History saved to "R2_HOMEDIR"/history\n"); r_line_hist_save (R2_HOMEDIR"/history"); } break; diff --git a/libr/core/config.c b/libr/core/config.c index e16c47ba478ba..f627a918711c9 100644 --- a/libr/core/config.c +++ b/libr/core/config.c @@ -495,6 +495,12 @@ static int config_asmbits_callback(void *user, void *data) { return ret; } +static int config_truecolor_callback(void *user, void *data) { + RConfigNode *node = (RConfigNode *) data; + r_cons_singleton()->truecolor = (node->i_value)? 1: 0; + return R_TRUE; +} + static int config_color_callback(void *user, void *data) { RCore *core = (RCore *) user; RConfigNode *node = (RConfigNode *) data; @@ -761,6 +767,7 @@ r_config_set (cfg, "asm.arch", R_SYS_ARCH); r_config_set_cb (cfg, "scr.prompt", "true", &config_scrprompt_callback); r_config_set (cfg, "scr.pipecolor", "false"); r_config_desc (cfg, "scr.pipecolor", "enable colors when using pipes if true"); + r_config_set_cb (cfg, "scr.truecolor", "false", &config_truecolor_callback); r_config_set_cb (cfg, "scr.color", (core->print->flags&R_PRINT_FLAGS_COLOR)?"true":"false", &config_color_callback); diff --git a/libr/core/disasm.c b/libr/core/disasm.c index e991ab7565502..a6e082f2bc809 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1070,7 +1070,10 @@ R_API int r_core_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int l if (show_lines && analop.type == R_ANAL_OP_TYPE_RET) { if (strchr (line, '>')) memset (line, ' ', strlen (line)); - r_cons_printf (" %s; --\n", line); + if (show_color) { + r_cons_printf (" %s%s"Color_RESET"; --\n", color_flow, line); + } else + r_cons_printf (" %s; --\n", line); } free (line); free (refline); diff --git a/libr/core/file.c b/libr/core/file.c index 832c528eaaac9..d4a10f38dbf74 100644 --- a/libr/core/file.c +++ b/libr/core/file.c @@ -60,7 +60,8 @@ R_API void r_core_sysenv_help() { "Usage: !\n" " ! list all historic commands\n" " !ls execute 'ls' in shell\n" - " !!ls~txt printo utput of 'ls' and grep for 'txt'\n" + " !! save command history to hist file\n" + " !!ls~txt print output of 'ls' and grep for 'txt'\n" " .!rabin2 -rvi ${FILE} run each output line as a r2 cmd\n" " !echo $SIZE display file size\n" "Environment:\n" diff --git a/libr/core/vmenus.c b/libr/core/vmenus.c index d37d33afdf51f..62e163d96de05 100644 --- a/libr/core/vmenus.c +++ b/libr/core/vmenus.c @@ -1224,7 +1224,7 @@ R_API void r_core_visual_define (RCore *core) { int plen = core->blocksize; ut64 off = core->offset; int n, ch, ntotal = 0; - int cleanup = R_FALSE; + //int cleanup = R_FALSE; ut8 *p = core->block; RAnalFunction *f; char *name; @@ -1265,7 +1265,7 @@ R_API void r_core_visual_define (RCore *core) { if (n<2) break; ntotal+= n; } while (ntotalblocksize); - cleanup = R_TRUE; + //cleanup = R_TRUE; break; case 's': // TODO: r_core_cmd0 (core, "Cz"); @@ -1275,18 +1275,18 @@ R_API void r_core_visual_define (RCore *core) { strncpy (name+4, (const char *)p, n); r_flag_set (core->flags, name, off, n, 0); r_meta_add (core->anal->meta, R_META_TYPE_STRING, off, off+n, (const char *)p); - cleanup = R_TRUE; + //cleanup = R_TRUE; free (name); break; case 'd': // TODO: check r_meta_cleanup (core->anal->meta, off, off+plen); r_meta_add (core->anal->meta, R_META_TYPE_DATA, off, off+plen, ""); - cleanup = R_TRUE; + //cleanup = R_TRUE; break; case 'c': // TODO: check r_meta_cleanup (core->anal->meta, off, off+plen); r_meta_add (core->anal->meta, R_META_TYPE_CODE, off, off+plen, ""); - cleanup = R_TRUE; + //cleanup = R_TRUE; break; case 'u': r_flag_unset_i (core->flags, off, NULL); @@ -1312,7 +1312,7 @@ R_API void r_core_visual_define (RCore *core) { R_API void r_core_visual_colors(RCore *core) { char color[32], cstr[32]; const char *k, *kol; - int i, ch, opt = 0; + int ch, opt = 0; ut8 r, g, b; r = g = b = 0; @@ -1326,6 +1326,9 @@ R_API void r_core_visual_colors(RCore *core) { } r_cons_gotoxy (0, 0); r_cons_rgb_str (cstr, r, g, b, 0); + r&=0xf; + g&=0xf; + b&=0xf; sprintf (color, "rgb:%x%x%x", r, g, b); //r_cons_printf ("COLOR%s(%sXXX)"Color_RESET"\n", kol, kol?kol+1:""); r_cons_printf ("# Colorscheme %d - Use '.' and ':' to randomize palette\n" @@ -1343,14 +1346,8 @@ R_API void r_core_visual_colors(RCore *core) { CASE_RGB ('R','r',r); CASE_RGB ('G','g',g); CASE_RGB ('B','b',b); - case 'k': opt--; - kol = r_cons_pal_get_color (opt); - r_cons_rgb_parse (kol, &r, &g, &b, NULL); - break; - case 'j': opt++; - kol = r_cons_pal_get_color (opt); - r_cons_rgb_parse (kol, &r, &g, &b, NULL); - break; + case 'k': opt--; break; + case 'j': opt++; break; case 'K': opt=0; break; case 'J': opt=0; break; // XXX must go to end case 'q': return; @@ -1360,15 +1357,10 @@ R_API void r_core_visual_colors(RCore *core) { b = r_num_rand (0xf); break; case ':': - for (i=0;;i++) { - k = r_cons_pal_get_i (i); - if (!k) break; - r = r_num_rand (0xf); - g = r_num_rand (0xf); - b = r_num_rand (0xf); - r_core_cmdf (core, "ec %s rgb:%x%x%x", k, r,g,b); - } + r_cons_pal_random (); break; } + kol = r_cons_pal_get_color (opt); + r_cons_rgb_parse (kol, &r, &g, &b, NULL); } } diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index 9b2d6205c26d0..b8ddc83f8d953 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -124,6 +124,7 @@ typedef struct r_cons_t { char *pager; int blankline; int widthfix; + int truecolor; RConsPalette pal; } RCons; @@ -264,6 +265,8 @@ R_API int r_cons_eof(); R_API int r_cons_palette_init(const unsigned char *pal); R_API int r_cons_pal_set (const char *key, const char *val); +R_API void r_cons_pal_init(const char *foo); +R_API void r_cons_pal_random(); R_API const char *r_cons_pal_get (const char *key); R_API const char *r_cons_pal_get_i (int n); R_API const char *r_cons_pal_get_color(int n); @@ -361,9 +364,6 @@ R_API const char *r_line_hist_get(int n); #define R_CONS_INVERT(x,y) (y? (x?Color_INVERT: Color_INVERT_RESET): (x?"[":"]")) -/* palette */ -R_API void r_cons_pal_init(const char *foo); - #endif #ifdef __cplusplus diff --git a/libr/util/str.c b/libr/util/str.c index 4edd5d7aadf89..31b43ab95aefa 100644 --- a/libr/util/str.c +++ b/libr/util/str.c @@ -730,9 +730,7 @@ R_API int r_str_ansi_len(const char *str) { if (!strncmp (str+2+5, "rgb:", 4)) i += 18; } else if (ch2 == '[') { - for (++i; - str[i]&&str[i]!='J'&& - str[i]!='m'&&str[i]!='H';i++); + for (++i; str[i]&&str[i]!='J'&& str[i]!='m'&&str[i]!='H';i++); } } else len++; i++;