2014-04-28 23:55:10 +00:00
|
|
|
/* radare - LGPL - Copyright 2013-2014 - pancake */
|
2013-08-25 22:51:36 +00:00
|
|
|
|
|
|
|
#include <r_cons.h>
|
|
|
|
|
2014-04-29 01:53:48 +00:00
|
|
|
#define W(y) r_cons_canvas_write(c,y)
|
|
|
|
#define G(x,y) r_cons_canvas_gotoxy(c,x,y)
|
|
|
|
|
2013-08-25 22:51:36 +00:00
|
|
|
R_API void r_cons_canvas_free (RConsCanvas *c) {
|
|
|
|
free (c->b);
|
|
|
|
free (c);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_clear (RConsCanvas *c) {
|
|
|
|
int y;
|
2014-09-24 01:17:43 +00:00
|
|
|
if (c && c->b) {
|
2014-09-08 15:10:53 +00:00
|
|
|
memset (c->b, '\n', c->blen);
|
|
|
|
c->b[c->blen] = 0;
|
|
|
|
for (y = 0; y<c->h; y++)
|
|
|
|
c->b[ y * c->w ] = '\n';
|
|
|
|
}
|
2013-08-25 22:51:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API RConsCanvas* r_cons_canvas_new (int w, int h) {
|
|
|
|
RConsCanvas *c;
|
|
|
|
if (w<1||h<1)
|
|
|
|
return NULL;
|
|
|
|
c = R_NEW0 (RConsCanvas);
|
|
|
|
if (!c) return NULL;
|
2014-05-05 01:15:28 +00:00
|
|
|
c->sx = 0;
|
|
|
|
c->sy = 0;
|
2013-08-25 22:51:36 +00:00
|
|
|
c->blen = (w+1)*h;
|
|
|
|
c->b = malloc (c->blen+1);
|
|
|
|
if (!c->b) {
|
|
|
|
free (c);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
c->w = w;
|
|
|
|
c->h = h;
|
|
|
|
c->x = c->y = 0;
|
|
|
|
r_cons_canvas_clear (c);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2014-05-05 01:15:28 +00:00
|
|
|
R_API int r_cons_canvas_gotoxy(RConsCanvas *c, int x, int y) {
|
|
|
|
int ret = R_TRUE;
|
2014-09-24 01:17:43 +00:00
|
|
|
if (!c) return 0;
|
2014-05-05 01:15:28 +00:00
|
|
|
x += c->sx;
|
|
|
|
y += c->sy;
|
2014-07-31 22:54:04 +00:00
|
|
|
if (x >= c->w) {
|
2014-05-05 01:15:28 +00:00
|
|
|
c->x = c->w;
|
|
|
|
ret = R_FALSE;
|
|
|
|
}
|
2014-07-31 22:54:04 +00:00
|
|
|
if (y >= c->h) {
|
2014-05-05 01:15:28 +00:00
|
|
|
c->y = c->h;
|
|
|
|
ret = R_FALSE;
|
|
|
|
}
|
2014-07-31 22:54:04 +00:00
|
|
|
if (x <0) {
|
2015-01-11 01:28:59 +00:00
|
|
|
//c->x = 0;
|
2014-05-05 01:15:28 +00:00
|
|
|
ret = R_FALSE;
|
|
|
|
}
|
2014-07-31 22:54:04 +00:00
|
|
|
if (y <0) {
|
2014-05-08 00:26:42 +00:00
|
|
|
c->y = 0;
|
2014-05-05 01:15:28 +00:00
|
|
|
ret = R_FALSE;
|
|
|
|
}
|
|
|
|
if (x<c->w && x>=0) c->x = x;
|
|
|
|
if (y<c->h && y>=0) c->y = y;
|
|
|
|
return ret;
|
2013-08-25 22:51:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static char *getptr(RConsCanvas *c, int *left) {
|
|
|
|
if (left) *left = c->w - c->x;
|
|
|
|
return c->b + (c->y * c->w) + c->x;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static char *getrow (char *p, char **n) {
|
|
|
|
char *q = strchr (p, '\n');
|
|
|
|
if (n) *n = NULL;
|
|
|
|
if (q) {
|
|
|
|
*q = 0;
|
|
|
|
if (n) *n = q+1;
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *prefixline(RConsCanvas *c, int *left) {
|
|
|
|
int x;
|
2014-09-24 01:17:43 +00:00
|
|
|
char *p;
|
|
|
|
if (!c)
|
|
|
|
return NULL;
|
|
|
|
p = c->b + (c->y * c->w);
|
2013-08-25 22:51:36 +00:00
|
|
|
for (x = 0; x<c->x; x++) {
|
|
|
|
if (p[x] == '\n')
|
|
|
|
p[x] = ' ';
|
|
|
|
}
|
|
|
|
if (left) *left = c->w - c->x;
|
|
|
|
return p+x;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_write(RConsCanvas *c, const char *_s) {
|
2015-01-11 01:28:59 +00:00
|
|
|
int left, slen, i, linenum = 0;
|
2013-08-25 22:51:36 +00:00
|
|
|
char *p, *s, *str;
|
2014-05-16 12:34:36 +00:00
|
|
|
char *line, *n;
|
|
|
|
|
2014-09-08 15:10:53 +00:00
|
|
|
if (!c || !_s)
|
|
|
|
return;
|
2013-08-25 22:51:36 +00:00
|
|
|
str = s = strdup (_s);
|
2014-07-31 23:09:05 +00:00
|
|
|
for (i=0; ; i++) {
|
2013-08-25 22:51:36 +00:00
|
|
|
line = getrow (s, &n);
|
|
|
|
p = prefixline (c, &left);
|
2015-01-10 03:21:10 +00:00
|
|
|
slen = R_MIN (left-1, strlen (line));
|
2015-01-11 01:28:59 +00:00
|
|
|
if (slen<1) {
|
2014-07-31 23:09:05 +00:00
|
|
|
break;
|
2015-01-11 01:28:59 +00:00
|
|
|
}
|
2014-05-09 01:06:05 +00:00
|
|
|
if (!G (c->x-c->sx+slen, c->y-c->sy)) {
|
|
|
|
// TODO : chop slen
|
|
|
|
slen = (c->w - (c->x-c->sx));
|
2014-07-31 23:09:05 +00:00
|
|
|
if (slen<1)
|
|
|
|
break;
|
2014-05-16 12:34:36 +00:00
|
|
|
continue;
|
2014-05-09 01:06:05 +00:00
|
|
|
}
|
2015-01-11 01:28:59 +00:00
|
|
|
// top border skipping lines
|
|
|
|
//if ((c->y-1-c->sy)<-40) {
|
|
|
|
// continue;
|
|
|
|
//}
|
|
|
|
int delta = 0;
|
2014-05-09 01:06:05 +00:00
|
|
|
if (!G (c->x-c->sx-slen, c->y-c->sy))
|
2014-05-16 12:34:36 +00:00
|
|
|
continue;
|
2015-01-11 01:28:59 +00:00
|
|
|
memcpy (p, line+delta, slen-delta);
|
2013-08-25 22:51:36 +00:00
|
|
|
if (!n) break;
|
|
|
|
s = n;
|
2015-01-11 01:28:59 +00:00
|
|
|
if (!G (c->x-c->sx, c->y+1-c->sy)) {
|
2014-05-05 01:15:28 +00:00
|
|
|
break;
|
2015-01-11 01:28:59 +00:00
|
|
|
}
|
|
|
|
linenum ++;
|
2013-08-25 22:51:36 +00:00
|
|
|
}
|
|
|
|
free (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API char *r_cons_canvas_to_string(RConsCanvas *c) {
|
|
|
|
int x, y, olen = 0;
|
2014-09-24 01:17:43 +00:00
|
|
|
char *o, *b;
|
|
|
|
if (!c) return NULL;
|
|
|
|
b = c->b;
|
|
|
|
o = malloc (c->w*(c->h+1));
|
|
|
|
if (!o) return NULL;
|
2013-08-25 22:51:36 +00:00
|
|
|
for (y = 0; y<c->h; y++) {
|
|
|
|
for (x = 0; x<c->w; x++) {
|
|
|
|
int p = x + (y*c->w);
|
|
|
|
if (!b[p] || b[p]=='\n')
|
|
|
|
break;
|
|
|
|
o[olen++] = b[p];
|
|
|
|
}
|
|
|
|
o[olen++] = '\n';
|
|
|
|
}
|
|
|
|
o[olen] = 0;
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_print(RConsCanvas *c) {
|
|
|
|
char *o = r_cons_canvas_to_string (c);
|
2014-09-08 15:10:53 +00:00
|
|
|
if (o) {
|
|
|
|
r_cons_strcat (o);
|
|
|
|
free (o);
|
|
|
|
}
|
2013-08-25 22:51:36 +00:00
|
|
|
}
|
2014-04-28 23:55:10 +00:00
|
|
|
|
2014-05-05 01:15:28 +00:00
|
|
|
R_API int r_cons_canvas_resize(RConsCanvas *c, int w, int h) {
|
2014-09-08 15:10:53 +00:00
|
|
|
int blen = (w+1)*h;
|
2014-05-05 21:28:57 +00:00
|
|
|
char *b = NULL;
|
2014-09-24 01:17:43 +00:00
|
|
|
if (!c || w < 0) return R_FALSE;
|
2014-09-08 15:10:53 +00:00
|
|
|
b = realloc (c->b, blen+1);
|
2014-05-05 01:15:28 +00:00
|
|
|
if (!b) return R_FALSE;
|
2014-09-08 15:10:53 +00:00
|
|
|
c->blen = blen;
|
2014-05-05 01:15:28 +00:00
|
|
|
c->b = b;
|
|
|
|
c->w = w;
|
|
|
|
c->h = h;
|
|
|
|
c->x = 0;
|
|
|
|
c->y = 0;
|
|
|
|
r_cons_canvas_clear (c);
|
|
|
|
return R_TRUE;
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_box(RConsCanvas *c, int x, int y, int w, int h) {
|
|
|
|
int i;
|
2014-04-29 01:53:48 +00:00
|
|
|
int roundcorners = 0;
|
2014-05-05 21:28:57 +00:00
|
|
|
char *row = NULL;
|
2014-04-29 01:53:48 +00:00
|
|
|
char corner = '=';
|
|
|
|
|
2014-05-05 21:28:57 +00:00
|
|
|
if (w < 0) return;
|
|
|
|
|
|
|
|
row = malloc (w+1);
|
2014-04-29 01:53:48 +00:00
|
|
|
row[0] = roundcorners?'.':corner;
|
2014-04-28 23:55:10 +00:00
|
|
|
memset (row+1, '-', w-2);
|
2014-04-29 01:53:48 +00:00
|
|
|
row[w-1] = roundcorners?'.':corner;
|
2014-04-28 23:55:10 +00:00
|
|
|
row[w] = 0;
|
2014-05-05 01:15:28 +00:00
|
|
|
if (G(x, y)) W(row);
|
|
|
|
if (G(x, y+h-1)) {
|
|
|
|
row[0] = roundcorners?'\'':corner;
|
|
|
|
row[w-1] = roundcorners?'\'':corner;
|
|
|
|
W(row);
|
|
|
|
}
|
2014-04-28 23:55:10 +00:00
|
|
|
|
|
|
|
for (i=1;i<h-1;i++) {
|
2014-05-05 01:15:28 +00:00
|
|
|
if (G(x, y+i)) W("|");
|
|
|
|
if (G(x+w-1, y+i)) W("|");
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
2014-05-05 21:28:57 +00:00
|
|
|
free (row);
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_fill(RConsCanvas *c, int x, int y, int w, int h, char ch, int replace) {
|
|
|
|
int i;
|
2014-05-05 21:28:57 +00:00
|
|
|
char *row = NULL;
|
|
|
|
|
|
|
|
if (w < 0) return;
|
|
|
|
|
|
|
|
row = malloc (w+1);
|
2014-04-29 01:53:48 +00:00
|
|
|
memset (row, ch, w);
|
2014-04-28 23:55:10 +00:00
|
|
|
row[w] = 0;
|
|
|
|
|
2014-04-29 01:53:48 +00:00
|
|
|
for (i=0;i<h;i++) {
|
2014-05-05 01:15:28 +00:00
|
|
|
if (G(x, y+i))
|
|
|
|
W(row);
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
2014-05-05 21:28:57 +00:00
|
|
|
free (row);
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_canvas_line (RConsCanvas *c, int x, int y, int x2, int y2, int style) {
|
2014-05-08 00:26:42 +00:00
|
|
|
int i, onscreen;
|
2014-04-28 23:55:10 +00:00
|
|
|
switch (style) {
|
2015-01-09 10:38:00 +00:00
|
|
|
case 0:
|
2014-05-05 01:15:28 +00:00
|
|
|
if (G (x, y))
|
|
|
|
W ("v");
|
|
|
|
if (G (x2, y2))
|
|
|
|
W ("V");
|
2015-01-09 10:38:00 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (G (x, y))
|
|
|
|
W ("t"); //\\");
|
|
|
|
if (G (x2, y2))
|
|
|
|
W ("\\");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (G (x, y))
|
|
|
|
W ("f");
|
|
|
|
if (G (x2, y2))
|
|
|
|
W ("/");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (x==x2) {
|
|
|
|
int min = R_MIN (y,y2)+1;
|
|
|
|
int max = R_MAX (y,y2);
|
|
|
|
for (i=min; i<max; i++) {
|
|
|
|
if (G (x,i))
|
|
|
|
W ("|");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// --
|
|
|
|
// TODO: find if there's any collision in this line
|
|
|
|
int hl = R_ABS (y-y2) / 2;
|
|
|
|
int hl2 = R_ABS (y-y2)-hl;
|
|
|
|
hl--;
|
|
|
|
if (y2 > (y+1)) {
|
|
|
|
for (i=0;i<hl;i++) {
|
|
|
|
if (G (x,y+i+1))
|
2014-05-05 01:15:28 +00:00
|
|
|
W ("|");
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
2015-01-09 10:38:00 +00:00
|
|
|
for (i=0;i<hl2;i++) {
|
|
|
|
if (G (x2, y+hl+i+1))
|
|
|
|
W ("|");
|
|
|
|
}
|
|
|
|
int w = R_ABS (x-x2);
|
|
|
|
char *row = malloc (w+2);
|
|
|
|
if (x>x2) {
|
|
|
|
w++;
|
|
|
|
row[0] = '.';
|
|
|
|
if (w>2)
|
|
|
|
memset (row+1, '-', w-2);
|
|
|
|
row[w-1] = '\'';
|
|
|
|
row[w] = 0;
|
|
|
|
onscreen = G (x2+w,y+hl+1);
|
|
|
|
i = G (x2, y+hl+1);
|
|
|
|
if (!onscreen)
|
|
|
|
onscreen = i;
|
|
|
|
} else {
|
|
|
|
row[0] = '`';
|
|
|
|
row[0] = '\'';
|
|
|
|
if (w>1)
|
|
|
|
memset (row+1, '-', w-1);
|
|
|
|
row[w] = '.';
|
|
|
|
row[w+1] = 0;
|
|
|
|
onscreen = G (x+w,y+1+hl);
|
|
|
|
i = G (x,y+1+hl);
|
|
|
|
if (!onscreen)
|
|
|
|
onscreen = i;
|
|
|
|
}
|
|
|
|
if (onscreen)
|
|
|
|
W (row);
|
|
|
|
free (row);
|
|
|
|
} else {
|
|
|
|
int minx = R_MIN (x, x2);
|
|
|
|
//if (y >= y2)
|
|
|
|
int rl = R_ABS (x-x2)/2;
|
|
|
|
int rl2 = R_ABS (x-x2)-rl+1;
|
|
|
|
int vl = (R_ABS(y-y2))+1;
|
|
|
|
if (y+1==y2)
|
|
|
|
vl--;
|
2014-04-28 23:55:10 +00:00
|
|
|
|
2015-01-09 10:38:00 +00:00
|
|
|
for (i=0;i<vl; i++) {
|
|
|
|
if (G (minx+rl,y2+i))
|
|
|
|
W ("|");
|
|
|
|
}
|
2014-04-28 23:55:10 +00:00
|
|
|
|
2015-01-09 10:38:00 +00:00
|
|
|
int w = rl;
|
|
|
|
char *row = malloc (w+1);
|
|
|
|
if (x>x2) {
|
|
|
|
row[0] = '.';
|
|
|
|
if (w>2)
|
2014-04-28 23:55:10 +00:00
|
|
|
memset (row+1, '-', w-2);
|
2015-01-09 10:38:00 +00:00
|
|
|
if (w>0)
|
2014-04-28 23:55:10 +00:00
|
|
|
row[w-1] = '.';
|
2015-01-09 10:38:00 +00:00
|
|
|
row[w] = 0;
|
|
|
|
onscreen = G (x2,y2-1);
|
|
|
|
} else {
|
|
|
|
row[0] = '`';
|
|
|
|
if (w>2)
|
|
|
|
memset (row+1, '-', w-2);
|
|
|
|
if (w>0)
|
|
|
|
row[w-1] = '\'';
|
|
|
|
row[w] = 0;
|
|
|
|
onscreen = G (x+1,y+1);
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
2015-01-09 10:38:00 +00:00
|
|
|
if (onscreen)
|
|
|
|
W (row);
|
|
|
|
w = rl2;
|
|
|
|
free (row);
|
|
|
|
row = malloc (rl2+1);
|
|
|
|
if (x>x2) {
|
|
|
|
row[0] = '`';
|
|
|
|
memset (row+1, '-', w-2);
|
|
|
|
row[w-1] = '\'';
|
|
|
|
row[w] = 0;
|
|
|
|
onscreen = G (x2+rl, y+1);
|
|
|
|
} else {
|
|
|
|
row[0] = '.';
|
|
|
|
memset (row+1, '-', w-2);
|
|
|
|
row[w-1] = '.';
|
|
|
|
row[w] = 0;
|
|
|
|
onscreen = G (x+rl, y2-1);
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
2015-01-09 10:38:00 +00:00
|
|
|
if (onscreen)
|
|
|
|
W (row);
|
|
|
|
free (row);
|
|
|
|
}
|
2014-04-28 23:55:10 +00:00
|
|
|
}
|
|
|
|
}
|