mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-27 23:20:40 +00:00
568 lines
15 KiB
C
568 lines
15 KiB
C
/* radare - LGPL - Copyright 2013-2017 - pancake, sghctoma */
|
|
|
|
#include <r_cons.h>
|
|
|
|
R_API void r_cons_pal_free () {
|
|
int i;
|
|
RCons *cons = r_cons_singleton ();
|
|
for (i = 0; i < R_CONS_PALETTE_LIST_SIZE; i++) {
|
|
if (cons->pal.list[i]) R_FREE (cons->pal.list[i]);
|
|
}
|
|
}
|
|
|
|
R_API void r_cons_pal_init (const char *foo) {
|
|
RCons *cons = r_cons_singleton ();
|
|
memset (&cons->pal, 0, sizeof (cons->pal));
|
|
cons->pal.rainbow = NULL;
|
|
cons->pal.rainbow_sz = 0;
|
|
cons->pal.b0x00 = Color_GREEN;
|
|
cons->pal.b0x7f = Color_CYAN;
|
|
cons->pal.b0xff = Color_RED;
|
|
cons->pal.args = Color_YELLOW;
|
|
cons->pal.bin = Color_CYAN;
|
|
cons->pal.btext = Color_YELLOW;
|
|
cons->pal.call = Color_BGREEN;
|
|
cons->pal.cjmp = Color_GREEN;
|
|
cons->pal.cmp = Color_CYAN;
|
|
cons->pal.comment = Color_RED;
|
|
cons->pal.usercomment = Color_WHITE;
|
|
cons->pal.creg = Color_CYAN;
|
|
cons->pal.flag = Color_CYAN;
|
|
cons->pal.fline = Color_CYAN;
|
|
cons->pal.floc = Color_CYAN;
|
|
cons->pal.flow = Color_CYAN;
|
|
cons->pal.flow2 = Color_BLUE;
|
|
cons->pal.fname = Color_RED;
|
|
cons->pal.help = Color_GREEN;
|
|
cons->pal.input = Color_WHITE;
|
|
cons->pal.invalid = Color_BRED;
|
|
cons->pal.jmp = Color_GREEN;
|
|
cons->pal.label = Color_CYAN;
|
|
cons->pal.math = Color_YELLOW;
|
|
cons->pal.mov = Color_WHITE;
|
|
cons->pal.nop = Color_BLUE;
|
|
cons->pal.num = Color_YELLOW;
|
|
cons->pal.offset = Color_GREEN;
|
|
cons->pal.other = Color_WHITE;
|
|
cons->pal.pop = Color_BMAGENTA;
|
|
cons->pal.prompt = Color_YELLOW;
|
|
cons->pal.push = Color_MAGENTA;
|
|
cons->pal.crypto = Color_BGBLUE;
|
|
cons->pal.reg = Color_CYAN;
|
|
cons->pal.reset = Color_RESET;
|
|
cons->pal.ret = Color_RED;
|
|
cons->pal.swi = Color_MAGENTA;
|
|
cons->pal.trap = Color_BRED;
|
|
|
|
cons->pal.ai_read = Color_GREEN;
|
|
cons->pal.ai_write = Color_BLUE;
|
|
cons->pal.ai_exec = Color_RED;
|
|
cons->pal.ai_seq = Color_MAGENTA;
|
|
cons->pal.ai_ascii = Color_YELLOW;
|
|
|
|
cons->pal.gui_cflow = Color_YELLOW;
|
|
cons->pal.gui_dataoffset = Color_YELLOW;
|
|
cons->pal.gui_background = Color_BLACK;
|
|
cons->pal.gui_alt_background = Color_WHITE;
|
|
cons->pal.gui_border = Color_BLACK;
|
|
cons->pal.highlight = Color_BGRED;
|
|
|
|
cons->pal.graph_box = Color_RESET;
|
|
cons->pal.graph_box2 = Color_BLUE;
|
|
cons->pal.graph_box3 = Color_MAGENTA;
|
|
cons->pal.graph_box4 = Color_GRAY;
|
|
cons->pal.graph_true = Color_GREEN;
|
|
cons->pal.graph_false = Color_RED;
|
|
cons->pal.graph_trufae = Color_BLUE; // single jump
|
|
cons->pal.graph_traced = Color_YELLOW;
|
|
cons->pal.graph_current = Color_BLUE;
|
|
|
|
r_cons_pal_free ();
|
|
cons->pal.list[0] = strdup (Color_RED);
|
|
cons->pal.list[1] = strdup (Color_YELLOW);
|
|
cons->pal.list[2] = strdup (Color_BGREEN);
|
|
cons->pal.list[3] = strdup (Color_CYAN);
|
|
cons->pal.list[4] = strdup (Color_MAGENTA);
|
|
cons->pal.list[5] = strdup (Color_GRAY);
|
|
cons->pal.list[6] = strdup (Color_BLUE);
|
|
cons->pal.list[7] = strdup (Color_GREEN);
|
|
|
|
r_cons_pal_update_event();
|
|
}
|
|
|
|
struct {
|
|
const char *name;
|
|
const char *code;
|
|
const char *bgcode;
|
|
} colors[] = {
|
|
{ "black", Color_BLACK, Color_BGBLACK },
|
|
{ "red", Color_RED, Color_BGRED },
|
|
{ "bred", Color_BRED, Color_BGRED },
|
|
{ "white", Color_WHITE, Color_BGWHITE },
|
|
{ "green", Color_GREEN, Color_BGGREEN },
|
|
{ "bgreen", Color_BGREEN, Color_BGGREEN },
|
|
{ "magenta", Color_MAGENTA, Color_BGMAGENTA },
|
|
{ "bmagenta", Color_BMAGENTA, Color_BGMAGENTA },
|
|
{ "yellow", Color_YELLOW, Color_BGYELLOW },
|
|
{ "byellow", Color_BYELLOW, Color_BGBYELLOW },
|
|
{ "cyan", Color_CYAN, Color_BGCYAN },
|
|
{ "bcyan", Color_BCYAN, Color_BGCYAN },
|
|
{ "blue", Color_BLUE, Color_BGBLUE },
|
|
{ "bblue", Color_BBLUE, Color_BGBLUE },
|
|
{ "gray", Color_GRAY, Color_BGGRAY },
|
|
{ "bgray", Color_BGRAY, Color_BGGRAY },
|
|
{ "none", Color_RESET, Color_RESET },
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
static inline ut8 rgbnum (const char ch1, const char ch2) {
|
|
ut8 r = 0, r2 = 0;
|
|
r_hex_to_byte (&r, ch1);
|
|
r_hex_to_byte (&r2, ch2);
|
|
return r << 4 | r2;
|
|
}
|
|
|
|
R_API void r_cons_pal_random () {
|
|
RCons *cons = r_cons_singleton ();
|
|
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;
|
|
if (cons->truecolor > 0) {
|
|
r = r_num_rand (0xff);
|
|
g = r_num_rand (0xff);
|
|
b = r_num_rand (0xff);
|
|
sprintf (val, "rgb:%02x%02x%02x", r, g, b);
|
|
r_cons_pal_set (k, val);
|
|
} else {
|
|
char *s = r_cons_color_random_string (0);
|
|
if (s) {
|
|
r_cons_pal_set (k, s);
|
|
free (s);
|
|
} else {
|
|
r_cons_pal_set (k, "red");
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < R_CONS_PALETTE_LIST_SIZE; i++) {
|
|
if (cons->pal.list[i]) R_FREE (cons->pal.list[i]);
|
|
cons->pal.list[i] = r_cons_color_random (0);
|
|
}
|
|
r_cons_pal_update_event();
|
|
}
|
|
|
|
R_API char *r_cons_pal_parse (const char *str) {
|
|
int i;
|
|
ut8 r, g, b;
|
|
char out[128];
|
|
char *s = strdup (str);
|
|
if (!s) return NULL;
|
|
char *p = strchr (s + 1, ' ');
|
|
out[0] = 0;
|
|
if (p) *p++ = 0;
|
|
if (!strcmp (str, "random")) {
|
|
free (s);
|
|
return r_cons_color_random (0);
|
|
}
|
|
if (!strncmp (s, "#", 1)) {
|
|
if (strlen (s) == 7) {
|
|
#define C(x) (x >> 4)
|
|
int R, G, B;
|
|
sscanf (s, "%02x%02x%02x", &R, &G, &B);
|
|
r_cons_rgb_str (out, C(R), C(G), C(B), 0);
|
|
} else {
|
|
eprintf ("Invalid html color code\n");
|
|
}
|
|
} else if (!strncmp (s, "rgb:", 4)) {
|
|
if (strlen (s) == 7) {
|
|
r = rgbnum (s[4], '0');
|
|
g = rgbnum (s[5], '0');
|
|
b = rgbnum (s[6], '0');
|
|
r_cons_rgb_str (out, r, g, b, 0);
|
|
} else if (strlen (s) == 10) {
|
|
r = rgbnum (s[4], s[5]);
|
|
g = rgbnum (s[6], s[7]);
|
|
b = rgbnum (s[8], s[9]);
|
|
r_cons_rgb_str (out, r, g, b, 0);
|
|
}
|
|
}
|
|
if (p && !strncmp (p, "rgb:", 4)) {
|
|
if (strlen (s) == 7) {
|
|
r = rgbnum (p[4], '0');
|
|
g = rgbnum (p[5], '0');
|
|
b = rgbnum (p[6], '0');
|
|
r_cons_rgb_str (out + strlen (out), r, g, b, 1);
|
|
} else if (strlen (s) == 10) {
|
|
r = rgbnum (p[4], p[5]);
|
|
g = rgbnum (p[6], p[7]);
|
|
b = rgbnum (p[8], p[9]);
|
|
r_cons_rgb_str (out + strlen (out), r, g, b, 1);
|
|
}
|
|
}
|
|
for (i = 0; colors[i].name; i++) {
|
|
if (!strcmp (s, colors[i].name)) {
|
|
strncat (out, colors[i].code,
|
|
sizeof (out) - strlen (out) - 1);
|
|
}
|
|
if (p && !strcmp (p, colors[i].name)) {
|
|
strncat (out, colors[i].bgcode,
|
|
sizeof (out) - strlen (out) - 1);
|
|
}
|
|
}
|
|
free (s);
|
|
return *out ? strdup (out) : NULL;
|
|
}
|
|
|
|
static struct {
|
|
const char *name;
|
|
int off;
|
|
} keys[] = {
|
|
{ "comment", r_offsetof (RConsPalette, comment) },
|
|
{ "usrcmt", r_offsetof (RConsPalette, usercomment) },
|
|
{ "args", r_offsetof (RConsPalette, args) },
|
|
{ "fname", r_offsetof (RConsPalette, fname) },
|
|
{ "floc", r_offsetof (RConsPalette, floc) },
|
|
{ "fline", r_offsetof (RConsPalette, fline) },
|
|
{ "flag", r_offsetof (RConsPalette, flag) },
|
|
{ "label", r_offsetof (RConsPalette, label) },
|
|
{ "help", r_offsetof (RConsPalette, help) },
|
|
{ "flow", r_offsetof (RConsPalette, flow) },
|
|
{ "flow2", r_offsetof (RConsPalette, flow2) },
|
|
{ "prompt", r_offsetof (RConsPalette, prompt) },
|
|
{ "offset", r_offsetof (RConsPalette, offset) },
|
|
{ "input", r_offsetof (RConsPalette, input) },
|
|
{ "invalid", r_offsetof (RConsPalette, invalid) },
|
|
{ "other", r_offsetof (RConsPalette, other) },
|
|
{ "b0x00", r_offsetof (RConsPalette, b0x00) },
|
|
{ "b0x7f", r_offsetof (RConsPalette, b0x7f) },
|
|
{ "b0xff", r_offsetof (RConsPalette, b0xff) },
|
|
{ "math", r_offsetof (RConsPalette, math) },
|
|
{ "bin", r_offsetof (RConsPalette, bin) },
|
|
{ "btext", r_offsetof (RConsPalette, btext) },
|
|
{ "push", r_offsetof (RConsPalette, push) },
|
|
{ "pop", r_offsetof (RConsPalette, pop) },
|
|
{ "crypto", r_offsetof (RConsPalette, crypto) },
|
|
{ "jmp", r_offsetof (RConsPalette, jmp) },
|
|
{ "cjmp", r_offsetof (RConsPalette, cjmp) },
|
|
{ "call", r_offsetof (RConsPalette, call) },
|
|
{ "nop", r_offsetof (RConsPalette, nop) },
|
|
{ "ret", r_offsetof (RConsPalette, ret) },
|
|
{ "trap", r_offsetof (RConsPalette, trap) },
|
|
{ "swi", r_offsetof (RConsPalette, swi) },
|
|
{ "cmp", r_offsetof (RConsPalette, cmp) },
|
|
{ "reg", r_offsetof (RConsPalette, reg) },
|
|
{ "creg", r_offsetof (RConsPalette, creg) },
|
|
{ "num", r_offsetof (RConsPalette, num) },
|
|
{ "mov", r_offsetof (RConsPalette, mov) },
|
|
|
|
{ "ai.read", r_offsetof (RConsPalette, ai_read) },
|
|
{ "ai.write", r_offsetof (RConsPalette, ai_write) },
|
|
{ "ai.exec", r_offsetof (RConsPalette, ai_exec) },
|
|
{ "ai.seq", r_offsetof (RConsPalette, ai_seq) },
|
|
{ "ai.ascii", r_offsetof (RConsPalette, ai_ascii) },
|
|
|
|
{ "graph.box", r_offsetof (RConsPalette, graph_box) },
|
|
{ "graph.box2", r_offsetof (RConsPalette, graph_box2) },
|
|
{ "graph.box3", r_offsetof (RConsPalette, graph_box3) },
|
|
{ "graph.box4", r_offsetof (RConsPalette, graph_box4) },
|
|
{ "graph.true", r_offsetof (RConsPalette, graph_true) },
|
|
{ "graph.false", r_offsetof (RConsPalette, graph_false) },
|
|
{ "graph.trufae", r_offsetof (RConsPalette, graph_trufae) },
|
|
{ "graph.current", r_offsetof (RConsPalette, graph_current) },
|
|
{ "graph.traced", r_offsetof (RConsPalette, graph_traced) },
|
|
|
|
{ "gui.cflow", r_offsetof (RConsPalette, gui_cflow) },
|
|
{ "gui.dataoffset", r_offsetof (RConsPalette, gui_dataoffset) },
|
|
{ "gui.background", r_offsetof (RConsPalette, gui_background) },
|
|
{ "gui.alt_background", r_offsetof (RConsPalette, gui_alt_background) },
|
|
{ "gui.border", r_offsetof (RConsPalette, gui_border) },
|
|
{ "highlight", r_offsetof (RConsPalette, highlight) },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
static void r_cons_pal_show_gs () {
|
|
int i, n;
|
|
r_cons_print ("\nGreyscale:\n");
|
|
for (i = 0x08, n = 0; i <= 0xee; i += 0xa) {
|
|
char fg[32], bg[32];
|
|
|
|
if (i < 0x76) strcpy (fg, Color_WHITE);
|
|
else strcpy (fg, Color_BLACK);
|
|
r_cons_rgb_str (bg, i, i, i, 1);
|
|
r_cons_printf ("%s%s rgb:%02x%02x%02x "Color_RESET,
|
|
fg, bg, i, i, i);
|
|
if (n++ == 5) {
|
|
n = 0;
|
|
r_cons_newline ();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void r_cons_pal_show_256 () {
|
|
int r, g, b;
|
|
r_cons_print ("\n\nXTerm colors:\n");
|
|
for (r = 0x00; r <= 0xff; r += 0x28) {
|
|
if (r == 0x28) {
|
|
r = 0x5f;
|
|
}
|
|
for (b = 0x00; b <= 0xff; b += 0x28) {
|
|
if (b == 0x28) {
|
|
b = 0x5f;
|
|
}
|
|
for (g = 0x00; g <= 0xff; g += 0x28) {
|
|
char fg[32], bg[32];
|
|
if (g == 0x28) {
|
|
g = 0x5f;
|
|
}
|
|
if ((r <= 0x5f) && (g <= 0x5f)) {
|
|
strcpy (fg, Color_WHITE);
|
|
} else {
|
|
strcpy (fg, Color_BLACK);
|
|
}
|
|
r_cons_rgb_str (bg, r, g, b, 1);
|
|
r_cons_printf ("%s%s rgb:%02x%02x%02x "
|
|
Color_RESET, fg, bg, r, g, b);
|
|
if (g == 0xff) {
|
|
r_cons_newline ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void r_cons_pal_show_rgb () {
|
|
const int inc = 3;
|
|
int i, j, k, n = 0;
|
|
r_cons_print ("\n\nRGB:\n");
|
|
for (i = n = 0; i <= 0xf; i += inc) {
|
|
for (k = 0; k <= 0xf; k += inc) {
|
|
for (j = 0; j <= 0xf; j += inc) {
|
|
char fg[32], bg[32];
|
|
int r = i * 16;
|
|
int g = j * 16;
|
|
int b = k * 16;
|
|
strcpy (fg, ((i < 6) && (j < 5))
|
|
? Color_WHITE: Color_BLACK);
|
|
r_cons_rgb_str (bg, r, g, b, 1);
|
|
r_cons_printf ("%s%s rgb:%02x%02x%02x "
|
|
Color_RESET, fg, bg, r, g, b);
|
|
//if (n++==7) {
|
|
if (n ++== 5) {
|
|
n = 0;
|
|
r_cons_newline ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
R_API void r_cons_pal_show () {
|
|
int i;
|
|
for (i = 0; colors[i].name; i++) {
|
|
r_cons_printf ("%s%s__"Color_RESET" %s\n",
|
|
colors[i].code,
|
|
colors[i].bgcode,
|
|
colors[i].name);
|
|
}
|
|
switch (r_cons_singleton ()->truecolor) {
|
|
case 1: // 256 color palette
|
|
r_cons_pal_show_gs ();
|
|
r_cons_pal_show_256 ();
|
|
break;
|
|
case 2: // 16M
|
|
r_cons_pal_show_gs ();
|
|
r_cons_pal_show_rgb ();
|
|
break;
|
|
}
|
|
}
|
|
|
|
R_API const char *r_cons_pal_get_color (int n) {
|
|
RConsPalette *pal = & (r_cons_singleton ()->pal);
|
|
ut8 *p = (ut8*)pal;
|
|
int i;
|
|
for (i = 0; keys[i].name; i++) {
|
|
if (i >= n) {
|
|
const char **color = (const char**) (p + keys[i].off);
|
|
color = (const char**)*color;
|
|
return (const char *)color;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
R_API void r_cons_pal_list (int rad, const char *arg) {
|
|
RConsPalette *pal = & (r_cons_singleton ()->pal);
|
|
ut8 r, g, b, *p = (ut8*)pal;
|
|
char *name, **color, rgbstr[32];
|
|
const char *hasnext;
|
|
int i;
|
|
if (rad == 'j') {
|
|
r_cons_print ("{");
|
|
}
|
|
for (i = 0; keys[i].name; i++) {
|
|
color = (char**) (p + keys[i].off);
|
|
switch (rad) {
|
|
case 'j':
|
|
r = g = b = 0;
|
|
r_cons_rgb_parse (*color, &r, &g, &b, NULL);
|
|
hasnext = (keys[i + 1].name) ? "," : "";
|
|
r_cons_printf ("\"%s\":[%d,%d,%d]%s",
|
|
keys[i].name, r, g, b, hasnext);
|
|
break;
|
|
case 'c': {
|
|
const char *prefix = r_str_chop_ro (arg);
|
|
if (!prefix) {
|
|
prefix = "";
|
|
}
|
|
r = g = b = 0;
|
|
r_cons_rgb_parse (*color, &r, &g, &b, NULL);
|
|
hasnext = (keys[i + 1].name) ? "\n" : "";
|
|
//Need to replace the '.' char because this is not
|
|
//valid CSS
|
|
char *name = strdup (keys[i].name);
|
|
int j, len = strlen (name);
|
|
for (j = 0; j < len; j++) {
|
|
if (name[j] == '.') {
|
|
name[j] = '_';
|
|
}
|
|
}
|
|
r_cons_printf (".%s%s { color: rgb(%d, %d, %d); }%s",
|
|
prefix, name, r, g, b, hasnext);
|
|
free (name);
|
|
}
|
|
break;
|
|
case 'h':
|
|
r = g = b = 0;
|
|
r_cons_rgb_parse (*color, &r, &g, &b, NULL);
|
|
rgbstr[0] = 0;
|
|
name = strdup (keys[i].name);
|
|
r_str_replace_char (name, '.', '_');
|
|
r_cons_printf (".%s { color:#%02x%02x%02x }\n",
|
|
name, r, g, b);
|
|
free (name);
|
|
break;
|
|
case '*':
|
|
case 'r':
|
|
case 1:
|
|
r = g = b = 0;
|
|
r_cons_rgb_parse (*color, &r, &g, &b, NULL);
|
|
rgbstr[0] = 0;
|
|
r_cons_rgb_str (rgbstr, r, g, b, 0);
|
|
r_cons_printf ("ec %s rgb:%02x%02x%02x\n",
|
|
keys[i].name, r, g, b);
|
|
break;
|
|
default:
|
|
r_cons_printf (" %s##"Color_RESET" %s\n", *color,
|
|
keys[i].name);
|
|
}
|
|
}
|
|
if (rad == 'j') {
|
|
r_cons_print ("}\n");
|
|
}
|
|
}
|
|
|
|
R_API int r_cons_pal_set(const char *key, const char *val) {
|
|
int i;
|
|
char **p;
|
|
for (i = 0; keys[i].name; i++) {
|
|
if (!strcmp (key, keys[i].name)) {
|
|
p = (char **) ((char *)& (r_cons_singleton ()->pal) + keys[i].off);
|
|
*p = r_cons_pal_parse (val);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
R_API const char *r_cons_pal_get_i(int n) {
|
|
int i;
|
|
for (i = 0; i < n && keys[i].name; i++) {}
|
|
return (i == n) ? keys[n].name : NULL;
|
|
}
|
|
|
|
R_API const char *r_cons_pal_get (const char *key) {
|
|
int i;
|
|
for (i = 0; keys[i].name; i++) {
|
|
if (!strcmp (key, keys[i].name)) {
|
|
char **p = (char **) ((char *)& (r_cons_singleton ()->pal) + keys[i].off);
|
|
return p? *p: "";
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
R_API void r_cons_pal_update_event() {
|
|
RConsPalette *pal = & (r_cons_singleton ()->pal);
|
|
ut8 *p = (ut8*)pal;
|
|
Sdb *db = sdb_new0 ();
|
|
RCons *cons = r_cons_singleton ();
|
|
int i, n = 0;
|
|
for (i = 0; keys[i].name; i++) {
|
|
char **color = (char**) (p + keys[i].off);
|
|
ut8 r, g, b;
|
|
r = g = b = 0;
|
|
r_cons_rgb_parse (*color, &r, &g, &b, NULL);
|
|
if (r <= 0x50 && g <= 0x50 && b < 0x50) {
|
|
continue;
|
|
}
|
|
if (r >= 0xe0 && g >= 0xe0 && b >= 0xe0) {
|
|
continue;
|
|
}
|
|
const char *rgb = sdb_fmt (0, "rgb:%02x%02x%02x", r, g, b);
|
|
sdb_set (db, rgb, "1", 0);
|
|
}
|
|
SdbList *list = sdb_foreach_list (db, true);
|
|
SdbListIter *iter;
|
|
SdbKv *kv;
|
|
r_cons_rainbow_free ();
|
|
r_cons_rainbow_new (list->length);
|
|
ls_foreach (list, iter, kv) {
|
|
cons->pal.rainbow[n++] = strdup (kv->key);
|
|
}
|
|
cons->pal.rainbow_sz = n;
|
|
ls_free (list);
|
|
sdb_free (db);
|
|
}
|
|
|
|
R_API void r_cons_rainbow_new(int sz) {
|
|
RCons *cons = r_cons_singleton ();
|
|
cons->pal.rainbow_sz = sz;
|
|
free (cons->pal.rainbow);
|
|
cons->pal.rainbow = calloc (sizeof (char *), sz);
|
|
}
|
|
|
|
R_API void r_cons_rainbow_free() {
|
|
RCons *cons = r_cons_singleton ();
|
|
int i, sz = cons->pal.rainbow_sz;
|
|
if (cons->pal.rainbow) {
|
|
for (i = 0; i < sz ; i++) {
|
|
free (cons->pal.rainbow[i]);
|
|
}
|
|
}
|
|
cons->pal.rainbow_sz = 0;
|
|
R_FREE (cons->pal.rainbow);
|
|
}
|
|
|
|
R_API char *r_cons_rainbow_get(int idx, int last, bool bg) {
|
|
RCons *cons = r_cons_singleton ();
|
|
if (last < 0) {
|
|
last = cons->pal.rainbow_sz;
|
|
}
|
|
if (idx < 0 || idx >= last || !cons->pal.rainbow) {
|
|
return NULL;
|
|
}
|
|
int x = (last == cons->pal.rainbow_sz)
|
|
? idx : (cons->pal.rainbow_sz * idx) / (last + 1);
|
|
const char *a = cons->pal.rainbow[x];
|
|
if (bg) {
|
|
char *dup = r_str_newf ("%s %s", a, a);
|
|
char *res = r_cons_pal_parse (dup);
|
|
free (dup);
|
|
return res;
|
|
}
|
|
return r_cons_pal_parse (a);
|
|
}
|