Use g->x and g->y to rebase x/y got with r_str_str_xy

* Use RVector instead of RPVector
* Use RAGraph instead of the fixed core->agraph which may be wrong
* Fix infinite loop and remove unused functions
This commit is contained in:
Riccardo Schirone 2020-05-03 13:52:16 +02:00 committed by pancake
parent 4b0e25caeb
commit 79bee09fc3
6 changed files with 82 additions and 122 deletions

View File

@ -218,49 +218,6 @@ R_API bool r_cons_canvas_gotoxy(RConsCanvas *c, int x, int y) {
return ret;
}
static char *canvas_string(RConsCanvas *c, size_t pos) {
int x, y;
char *s = calloc (c->w, c->h);
if (!s) {
return NULL;
}
char *p = s;
int ox = c->x;
int oy = c->y;
for (y = oy; y < c->h; y ++) {
for (x = (y == oy)? ox: 0; x < c->w; x ++) {
char ch = c->b[y][x];
const char *rune = r_cons_get_rune ((const ut8)ch);
if (rune) {
size_t rune_len = strlen (rune);
memcpy (p, rune, rune_len + 1);
p += rune_len;
} else {
*p = c->b[y][x];
}
}
}
return s;
}
static int count_newlines(char *s, size_t len, size_t *col) {
size_t nl = 0;
size_t nc = 0;
size_t i;
for (i = 0; i < len; i++) {
if (s[i] == '\n') {
nl++;
nc = 0;
} else {
nc ++;
}
}
if (col) {
*col = nc;
}
return nl;
}
R_API RConsCanvas *r_cons_canvas_new(int w, int h) {
if (w < 1 || h < 1) {
return NULL;

View File

@ -100,6 +100,11 @@ struct agraph_refresh_data {
int fs;
};
struct r_agraph_location {
int x;
int y;
};
#define G(x, y) r_cons_canvas_gotoxy (g->can, x, y)
#define W(x) r_cons_canvas_write (g->can, x)
#define F(x, y, x2, y2, c) r_cons_canvas_fill (g->can, x, y, x2, y2, c)
@ -3570,6 +3575,7 @@ static void agraph_init(RAGraph *g) {
g->hints = 1;
g->movspeed = DEFAULT_SPEED;
g->db = sdb_new0 ();
r_vector_init (&g->ghits.word_list, sizeof (struct r_agraph_location), NULL, NULL);
}
static void free_anode(RANode *n) {
@ -4038,39 +4044,12 @@ static bool toggle_bb(RCore *core, ut64 addr) {
return false;
}
typedef struct r_canvas_location {
int x;
int y;
} RPosition;
static const char *strstr_xy(const char *p, const char *s, int *x, int *y) {
const char *d = strstr (p, s);
if (!d) {
return NULL;
}
const char *q;
int nl = 0;
int nc = *x;
for (q = p; q < d; q++) {
if (*q == '\n') {
nl++;
*x = 0;
nc = 0;
} else {
nc++;
}
}
*x += nc;
*y += nl;
return d;
}
static char *get_graph_string(RCore *core) {
static char *get_graph_string(RCore *core, RAGraph *g) {
int c = r_config_get_i (core->config, "scr.color");
int u = r_config_get_i (core->config, "scr.utf8");
r_config_set_i (core->config, "scr.color", 0);
r_config_set_i (core->config, "scr.utf8", 0);
r_core_visual_graph (core, NULL, NULL, false);
r_core_visual_graph (core, g, NULL, false);
char *s = strdup (r_cons_get_buffer ());
r_cons_reset ();
r_config_set_i (core->config, "scr.color", c);
@ -4078,72 +4057,53 @@ static char *get_graph_string(RCore *core) {
return s;
}
static void nextword(RCore *core, RConsCanvas *can, const char *word) {
r_return_if_fail (core && core->graph && can && word);
static void nextword(RCore *core, RAGraph *g, const char *word) {
r_return_if_fail (core && core->graph && g && g->can && word);
if (R_STR_ISEMPTY (word)) {
return;
}
RAGraphHits *gh = &core->graph->ghits;
if (gh->word_list.v.len && gh->old_word && !strcmp (word, gh->old_word)) {
RPosition *pos = r_pvector_at (&gh->word_list, gh->word_nth);
if (pos) {
gh->word_nth++;
} else {
RAGraphHits *gh = &g->ghits;
RConsCanvas *can = g->can;
if (gh->word_list.len && gh->old_word && !strcmp (word, gh->old_word)) {
if (gh->word_nth >= gh->word_list.len) {
gh->word_nth = 0;
pos = r_pvector_at (&gh->word_list, gh->word_nth);
}
struct r_agraph_location *pos = r_vector_index_ptr (&gh->word_list, gh->word_nth);
gh->word_nth++;
if (pos) {
can->sx = pos->x;
can->sy = pos->y;
can->sx = -pos->x + can->w / 2;
can->sy = -pos->y + can->h / 2;
}
return;
} else {
r_pvector_fini (&gh->word_list);
r_pvector_init (&gh->word_list, free);
r_vector_clear (&gh->word_list);
}
char *s = get_graph_string (core);
const char *p = s;
char *s = get_graph_string (core, g);
r_cons_clear00 ();
r_cons_flush ();
int ox = 0;
int oy = 0;
size_t count = 0;
const size_t MAX_COUNT = 4096;
int x = 0;
int y = 0;
bool first_x = true;
const char *a = NULL;
size_t count = 0;
int x = 0, y = 0;
for (count = 0; count < MAX_COUNT; count++) {
x = 0;
const char *a = strstr_xy (p, word, &x, &y);
a = r_str_str_xy (s, word, a, &x, &y);
if (!a) {
break;
}
RPosition *pos = R_NEW0 (RPosition);
if (!pos) {
break;
struct r_agraph_location *pos = r_vector_push (&gh->word_list, NULL);
if (pos) {
pos->x = x + g->x;
pos->y = y + g->y;
}
if (first_x) {
gh->x_origin = x;
first_x = false;
}
const size_t yhalf = can->h / 6;
pos->y = -y + yhalf;
if (oy == pos->y) {
const size_t xhalf = can->w / 2;
pos->x = - (x - (ox * 2) - xhalf);
} else {
const size_t nhalf = can->w / 3;
pos->x = gh->x_origin - x + nhalf;
}
oy = pos->y;
ox = pos->x;
r_pvector_push (&gh->word_list, pos);
p = a + 1;
}
free (gh->old_word);
gh->old_word = strdup (word);
free (s);
return nextword (core, can, word);
if (!a && count == 0) {
return;
}
nextword (core, g, word);
}
R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int is_interactive) {
@ -4343,7 +4303,7 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int
}
break;
case '\\':
nextword (core, can, r_config_get (core->config, "scr.highlight"));
nextword (core, g, r_config_get (core->config, "scr.highlight"));
break;
case 'b':
r_core_visual_browse (core, "");
@ -4942,8 +4902,7 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int
break;
}
}
RAGraphHits *gh = &core->graph->ghits;
r_pvector_fini (&gh->word_list);
r_vector_fini (&g->ghits.word_list);
r_cons_break_pop ();
r_config_set (core->config, "asm.comments", r_str_bool (asm_comments));
core->cons->event_resize = NULL;

View File

@ -28,9 +28,8 @@ typedef struct r_ascii_node_t {
typedef struct r_core_graph_hits_t {
char *old_word ;
RPVector word_list;
RVector word_list;
int word_nth;
int x_origin;
} RAGraphHits;

View File

@ -135,6 +135,7 @@ R_API wchar_t *r_str_mb_to_wc(const char *buf);
R_API char *r_str_wc_to_mb(const wchar_t *buf);
R_API wchar_t *r_str_mb_to_wc_l(const char *buf, int len);
R_API char *r_str_wc_to_mb_l(const wchar_t *buf, int len);
R_API const char *r_str_str_xy(const char *s, const char *word, const char *prev, int *x, int *y);
typedef void(*str_operation)(char *c);

View File

@ -3646,6 +3646,27 @@ R_API char *r_str_scale(const char *s, int w, int h) {
return r_str_list_join (out, "\n");
}
R_API const char *r_str_str_xy(const char *s, const char *word, const char *prev, int *x, int *y) {
r_return_val_if_fail (s && word && x && y, NULL);
r_return_val_if_fail (word[0] != '\0' && word[0] != '\n', NULL);
const char *src = prev ? prev + 1 : s;
const char *d = strstr (src, word);
if (!d) {
return NULL;
}
const char *q;
for (q = prev ? prev : s; q < d; q++) {
if (*q == '\n') {
(*y)++;
*x = 0;
} else {
(*x)++;
}
}
return d;
}
// version.c
#include <r_userconf.h>
#include <r_util.h>

View File

@ -430,7 +430,29 @@ bool test_r_str_format_msvc_argv() {
mu_end;
}
bool all_tests() {
bool test_r_str_str_xy(void) {
char *canvas = "Hello World\n"
"This World is World\n"
"World is Hello\n";
int x = 0, y = 0;
const char *next = r_str_str_xy (canvas, "World", NULL, &x, &y);
mu_assert_eq (x, 6, "x of first occurrence");
mu_assert_eq (y, 0, "y of first occurrence");
next = r_str_str_xy (canvas, "World", next, &x, &y);
mu_assert_eq (x, 5, "x of second occurrence");
mu_assert_eq (y, 1, "y of second occurrence");
next = r_str_str_xy (canvas, "World", next, &x, &y);
mu_assert_eq (x, 14, "x of third occurrence");
mu_assert_eq (y, 1, "y of third occurrence");
next = r_str_str_xy (canvas, "World", next, &x, &y);
mu_assert_eq (x, 0, "x of fourth occurrence");
mu_assert_eq (y, 2, "y of fourth occurrence");
next = r_str_str_xy (canvas, "World", next, &x, &y);
mu_assert_null (next, "no more occurences");
mu_end;
}
bool all_tests () {
mu_run_test (test_r_str_newf);
mu_run_test (test_r_str_replace_char_once);
mu_run_test (test_r_str_replace_char);
@ -458,6 +480,7 @@ bool all_tests() {
mu_run_test (test_r_str_unescape);
mu_run_test (test_r_str_constpool);
mu_run_test (test_r_str_format_msvc_argv);
mu_run_test (test_r_str_str_xy);
return tests_passed != tests_run;
}