Rizin
unix-like reverse engineering framework and cli tools
canvas_line.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_cons.h>
5 
6 #define W(y) rz_cons_canvas_write(c, y)
7 #define G(x, y) rz_cons_canvas_gotoxy(c, x, y)
8 
9 #define useUtf8 (rz_cons_singleton()->use_utf8)
10 #define useUtf8Curvy (rz_cons_singleton()->use_utf8_curvy)
11 
12 #define DOTTED_LINE_HORIZ "┄"
13 #define DOTTED_LINE_VERT "┊"
14 
15 #define DASHED_LINE_VERT "╵"
16 #define DASHED_LINE_HORIZ "╴"
17 
18 enum {
19  APEX_DOT = 0,
27  NRM_NRM
28 };
29 
30 static char *utf8_line_vert(int dot_style) {
31  if (rz_cons_singleton()->dotted_lines) {
32  switch (dot_style) {
36  }
37  }
38  return RUNECODESTR_LINE_VERT;
39 }
40 
41 static char *utf8_line_horiz(int dot_style) {
42  if (rz_cons_singleton()->dotted_lines) {
43  switch (dot_style) {
47  }
48  }
50 }
51 
52 static void apply_line_style(RzConsCanvas *c, int x, int y, int x2, int y2,
53  RzCanvasLineStyle *style, int isvert) {
54  RzCons *cons = rz_cons_singleton();
55  switch (style->color) {
56  case LINE_UNCJMP:
57  c->attr = cons->context->pal.graph_ujump;
58  break;
59  case LINE_TRUE:
60  c->attr = cons->context->pal.graph_true;
61  break;
62  case LINE_FALSE:
63  c->attr = cons->context->pal.graph_false;
64  break;
65  case LINE_NONE:
66  default:
67  c->attr = cons->context->pal.graph_ujump;
68  break;
69  }
70  if (!c->color) {
71  c->attr = Color_RESET;
72  }
73  switch (style->symbol) {
74  case LINE_UNCJMP:
75  if (G(x, y)) {
76  if (isvert) {
77  W("v");
78  } else {
79  W(">");
80  }
81  }
82  break;
83  case LINE_TRUE:
84  if (G(x, y)) {
85  W("t"); //\\");
86  }
87  break;
88  case LINE_FALSE:
89  if (G(x, y)) {
90  W("f");
91  }
92  break;
93  case LINE_NOSYM_VERT:
94  if (G(x, y)) {
95  W(useUtf8 ? utf8_line_vert(style->dot_style) : "|");
96  }
97  break;
98  case LINE_NOSYM_HORIZ:
99  if (G(x, y)) {
100  W(useUtf8 ? utf8_line_horiz(style->dot_style) : "-");
101  }
102  break;
103  case LINE_NONE:
104  default:
105  break;
106  }
107 }
108 
109 static void draw_horizontal_line(RzConsCanvas *c, int x, int y, int width, int style, int dot_style) {
110  const char *l_corner = "?", *rz_corner = "?";
111  int i;
112 
113  if (width < 1) {
114  return;
115  }
116  /* do not render offscreen horizontal lines */
117  if (y + c->sy < 0) {
118  return;
119  }
120  if (y + c->sy > c->h) {
121  return;
122  }
123 
124  switch (style) {
125  case APEX_DOT:
126  if (useUtf8) {
127  if (useUtf8Curvy) {
128  l_corner = RUNECODESTR_CURVE_CORNER_BL;
129  rz_corner = RUNECODESTR_CURVE_CORNER_TR;
130  } else {
131  l_corner = RUNECODESTR_CORNER_BL;
132  rz_corner = RUNECODESTR_CORNER_TR;
133  }
134  } else {
135  l_corner = "'";
136  rz_corner = ".";
137  }
138  break;
139  case DOT_APEX:
140  if (useUtf8) {
141  if (useUtf8Curvy) {
142  l_corner = RUNECODESTR_CURVE_CORNER_TL;
143  rz_corner = RUNECODESTR_CURVE_CORNER_BR;
144  } else {
145  l_corner = RUNECODESTR_CORNER_TL;
146  rz_corner = RUNECODESTR_CORNER_BR;
147  }
148  } else {
149  l_corner = ".";
150  rz_corner = "'";
151  }
152  break;
153  case REV_APEX_APEX:
154  if (useUtf8) {
155  if (useUtf8Curvy) {
156  l_corner = RUNECODESTR_CURVE_CORNER_BL;
157  rz_corner = RUNECODESTR_CURVE_CORNER_BR;
158  } else {
159  l_corner = RUNECODESTR_CORNER_BL;
160  rz_corner = RUNECODESTR_CORNER_BR;
161  }
162  } else {
163  l_corner = "`";
164  rz_corner = "'";
165  }
166  break;
167  case DOT_DOT:
168  if (useUtf8) {
169  if (useUtf8Curvy) {
170  l_corner = RUNECODESTR_CURVE_CORNER_TL;
171  rz_corner = RUNECODESTR_CURVE_CORNER_TR;
172  } else {
173  l_corner = RUNECODESTR_CORNER_TL;
174  rz_corner = RUNECODESTR_CORNER_TR;
175  }
176  } else {
177  l_corner = rz_corner = ".";
178  }
179  break;
180  case NRM_DOT:
181  if (useUtf8) {
182  l_corner = utf8_line_horiz(dot_style);
183  if (useUtf8Curvy) {
184  rz_corner = RUNECODESTR_CURVE_CORNER_TR;
185  } else {
186  rz_corner = RUNECODESTR_CORNER_TR;
187  }
188  } else {
189  l_corner = "-";
190  rz_corner = ".";
191  }
192  break;
193  case NRM_APEX:
194  if (useUtf8) {
195  l_corner = utf8_line_horiz(dot_style);
196  if (useUtf8Curvy) {
197  rz_corner = RUNECODESTR_CURVE_CORNER_BR;
198  } else {
199  rz_corner = RUNECODESTR_CORNER_BR;
200  }
201  } else {
202  l_corner = "-";
203  rz_corner = "'";
204  }
205  break;
206  case DOT_NRM:
207  if (useUtf8) {
208  if (useUtf8Curvy) {
209  l_corner = RUNECODESTR_CURVE_CORNER_TL;
210  } else {
211  l_corner = RUNECODESTR_CORNER_TL;
212  }
213  rz_corner = utf8_line_horiz(dot_style);
214  } else {
215  l_corner = ".";
216  rz_corner = "-";
217  }
218  break;
219  case REV_APEX_NRM:
220  if (useUtf8) {
221  if (useUtf8Curvy) {
222  l_corner = RUNECODESTR_CURVE_CORNER_BL;
223  } else {
224  l_corner = RUNECODESTR_CORNER_BL;
225  }
226  rz_corner = utf8_line_horiz(dot_style);
227  } else {
228  l_corner = "`";
229  rz_corner = "-";
230  }
231  break;
232  case NRM_NRM:
233  default:
234  if (useUtf8) {
235  l_corner = rz_corner = utf8_line_horiz(dot_style);
236  } else {
237  l_corner = rz_corner = "-";
238  }
239  break;
240  }
241 
242  if (G(x, y)) {
243  W(l_corner);
244  }
245 
246  const char *hline = useUtf8 ? utf8_line_horiz(dot_style) : "-";
248  for (i = x + 1; i < x + width - 1; i++) {
249  if (rz_cons_is_breaked()) {
250  break;
251  }
252  if (G(i, y)) {
253  W(hline);
254  }
255  }
257 
258  if (G(x + width - 1, y)) {
259  W(rz_corner);
260  }
261 }
262 
263 static void draw_vertical_line(RzConsCanvas *c, int x, int y, int height, int dot_style) {
264  int i;
265  /* do not render offscreen vertical lines */
266  if (x + c->sx < 0) {
267  return;
268  }
269  if (x + c->sx > c->w) {
270  return;
271  }
272  const char *vline = useUtf8 ? utf8_line_vert(dot_style) : "|";
274  for (i = y; i < y + height; i++) {
275  if (rz_cons_is_breaked()) {
276  break;
277  }
278  if (G(x, i)) {
279  W(vline);
280  }
281  }
283 }
284 
285 RZ_API void rz_cons_canvas_line_diagonal(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style) {
286  if (x == x2 || y == y2) {
287  style->dot_style = DOT_STYLE_NORMAL;
288  rz_cons_canvas_line_square(c, x, y + 1, x2, y2, style);
289  return;
290  }
291  apply_line_style(c, x, y, x2, y2, style, 1);
292  if (y2 < y) {
293  int tmp = y2;
294  y2 = y;
295  y = tmp;
296  tmp = x2;
297  x2 = x;
298  x = tmp;
299  }
300  char chizzle[2] = { 0 }; // = '.';//my nizzle
301  // destination
302  int dx = abs(x2 - x);
303  int dy = abs(y2 - y);
304  // source
305  int sx = (x < x2) ? 1 : -1;
306  int sy = (y < y2) ? 1 : -1;
307 
308  int err = (dx > (dy ? dx : -dy)) / 2;
309  int e2;
310 
311  // TODO: find if there's any collision in this line
312 loop:
313  e2 = err;
314  if (e2 > -dx) {
315  *chizzle = '_';
316  err -= dy;
317  x += sx;
318  }
319  if (e2 < dy) {
320  *chizzle = '|';
321  err += dx;
322  y += sy;
323  }
324  if ((e2 < dy) && (e2 > -dx)) {
325  if (sy > 0) {
326  *chizzle = (sx > 0) ? '\\' : '/';
327  } else {
328  *chizzle = (sx > 0) ? '/' : '\\';
329  }
330  }
331  if (!(x == x2 && y == y2)) {
332  int i = (*chizzle == '_' && sy < 0) ? 1 : 0;
333  if (G(x, y - i)) {
334  if (useUtf8) {
335  switch (*chizzle) {
336  case '/':
337  W("╯");
338  break;
339  case '\\':
340  W("└");
341  break;
342  case '|':
343  W("│");
344  break;
345  case '_':
346  W("─");
347  break;
348  default:
349  W("?");
350  break;
351  }
352  } else {
353  W(chizzle);
354  }
355  }
356  goto loop;
357  }
358  if (dx) {
359  if (dy && (dx / dy) < 1) {
360  if (G(x, y)) {
361  W("|");
362  }
363  }
364  if (G(x, y + 1)) {
365  W("|");
366  }
367  }
368  c->attr = Color_RESET;
369 }
370 
371 RZ_API void rz_cons_canvas_line_square(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style) {
372  int min_x = RZ_MIN(x, x2);
373  int diff_x = RZ_ABS(x - x2);
374  int diff_y = RZ_ABS(y - y2);
375 
376  apply_line_style(c, x, y, x2, y2, style, 1);
377 
378  // --
379  // TODO: find if there's any collision in this line
380  if (y2 - y > 1) {
381  int hl = diff_y / 2 - 1;
382  int hl2 = diff_y - hl;
383  int w = diff_x == 0 ? 0 : diff_x + 1;
384  int apex_style = min_x == x ? APEX_DOT : DOT_APEX;
385  draw_vertical_line(c, x, y + 1, hl, style->dot_style);
386  draw_vertical_line(c, x2, y + hl + 1, hl2, style->dot_style);
387  draw_horizontal_line(c, min_x, y + hl + 1, w, apex_style, style->dot_style);
388  } else {
389  if (y2 == y) {
390  draw_horizontal_line(c, min_x, y, diff_x + 1, DOT_DOT, style->dot_style);
391  } else {
392  if (x != x2) {
393  draw_horizontal_line(c, min_x, y, diff_x + 1, REV_APEX_APEX, style->dot_style);
394  }
395  draw_vertical_line(c, x2, y2, diff_y, style->dot_style);
396  }
397  }
398  c->attr = Color_RESET;
399 }
400 
401 RZ_API void rz_cons_canvas_line_square_defined(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int bendpoint, int isvert) {
402  if (!c->linemode) {
403  rz_cons_canvas_line(c, x, y, x2, y2, style);
404  return;
405  }
406  int min_x = RZ_MIN(x, x2);
407  int diff_x = RZ_ABS(x - x2);
408  int diff_y = RZ_ABS(y - y2);
409  int min_y = RZ_MIN(y, y2);
410 
411  apply_line_style(c, x, y, x2, y2, style, isvert);
412 
413  if (isvert) {
414  if (x2 == x) {
415  draw_vertical_line(c, x, y + 1, diff_y + 1, style->dot_style);
416  } else if (y2 - y > 1) {
417  int h1 = 1 + bendpoint;
418  int h2 = diff_y - h1;
419  int w = diff_x == 0 ? 0 : diff_x + 1;
420  int apex_style = min_x == x ? APEX_DOT : DOT_APEX;
421  draw_vertical_line(c, x, y + 1, h1, style->dot_style);
422  draw_horizontal_line(c, min_x, y + bendpoint + 2, w, apex_style, style->dot_style);
423  draw_vertical_line(c, x2, y + h1 + 1 + 1, h2, style->dot_style);
424  } else {
425  // TODO: currently copy-pasted
426  if (y2 == y) {
427  draw_horizontal_line(c, min_x, y, diff_x + 1, DOT_DOT, style->dot_style);
428  } else {
429  if (x != x2) {
430  draw_horizontal_line(c, min_x, y, diff_x + 1, REV_APEX_APEX, style->dot_style);
431  }
432  draw_vertical_line(c, x2, y2, diff_y - 2, style->dot_style);
433  }
434  }
435  } else {
436  if (y2 == y) {
437  draw_horizontal_line(c, min_x + 1, y, diff_x, NRM_NRM, style->dot_style);
438  } else if (x2 - x > 1) {
439  int w1 = 1 + bendpoint;
440  int w2 = diff_x - w1;
441  // int h = diff_x;// == 0 ? 0 : diff_x + 1;
442  // int style = min_x == x ? APEX_DOT : DOT_APEX;
443  // draw_vertical_line (c, x, y + 1, h1);
444  draw_horizontal_line(c, x + 1, y, w1 + 1, y2 > y ? NRM_DOT : NRM_APEX, style->dot_style);
445  // draw_horizontal_line (c, min_x, y + bendpoint + 2, w, style);
446  draw_vertical_line(c, x + 1 + w1, min_y + 1, diff_y - 1, style->dot_style);
447  // draw_vertical_line (c, x2, y + h1 + 1 + 1, h2);
448  draw_horizontal_line(c, x + 1 + w1, y2, w2, y2 < y ? DOT_NRM : REV_APEX_NRM, style->dot_style);
449  }
450  }
451  c->attr = Color_RESET;
452 }
453 
454 RZ_API void rz_cons_canvas_line_back_edge(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int ybendpoint1, int xbendpoint, int ybendpoint2, int isvert) {
455  if (!c->linemode) {
456  rz_cons_canvas_line(c, x, y, x2, y2, style);
457  return;
458  }
459  int min_x1 = RZ_MIN(x, xbendpoint);
460  int min_x2 = RZ_MIN(x2, xbendpoint);
461 
462  int diff_x1 = RZ_ABS(x - xbendpoint);
463  int diff_x2 = RZ_ABS(x2 - xbendpoint);
464 
465  int diff_y = RZ_ABS((y + ybendpoint1 + 1) - (y2 - ybendpoint2 - 1));
466 
467  int w1 = diff_x1 == 0 ? 0 : diff_x1 + 1;
468  int w2 = diff_x2 == 0 ? 0 : diff_x2 + 1;
469 
470  apply_line_style(c, x, y, x2, y2, style, isvert);
471 
472  if (isvert) {
473  draw_vertical_line(c, x, y + 1, ybendpoint1 + 1, style->dot_style);
474  draw_horizontal_line(c, min_x1, y + ybendpoint1 + 2, w1, REV_APEX_APEX, style->dot_style);
475  draw_vertical_line(c, xbendpoint, y2 - ybendpoint2 + 1, diff_y - 1, style->dot_style);
476  draw_horizontal_line(c, min_x2, y2 - ybendpoint2, w2, DOT_DOT, style->dot_style);
477  draw_vertical_line(c, x2, y2 - ybendpoint2 + 1, ybendpoint2 + 1, style->dot_style);
478  } else {
479  int miny1 = RZ_MIN(y, xbendpoint);
480  int miny2 = RZ_MIN(y2, xbendpoint);
481  int diff_y1 = RZ_ABS(y - xbendpoint);
482  int diff_y2 = RZ_ABS(y2 - xbendpoint);
483 
484  draw_horizontal_line(c, x + 1, y, 1 + ybendpoint1 + 1, xbendpoint > y ? NRM_DOT : NRM_APEX, style->dot_style);
485  draw_vertical_line(c, x + 1 + ybendpoint1 + 1, miny1 + 1, diff_y1 - 1, style->dot_style);
486  draw_horizontal_line(c, x2 - ybendpoint2, xbendpoint, (x + 1 + ybendpoint1 + 1) - (x2 - ybendpoint2) + 1, xbendpoint > y ? REV_APEX_APEX : DOT_DOT, style->dot_style);
487  draw_vertical_line(c, x2 - ybendpoint2, miny2 + 1, diff_y2 - 1, style->dot_style);
488  draw_horizontal_line(c, x2 - ybendpoint2, y2, ybendpoint2 + 1, xbendpoint > y ? DOT_NRM : REV_APEX_NRM, style->dot_style);
489  }
490 }
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
RZ_API void rz_cons_canvas_line(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style)
Definition: canvas.c:570
static char * utf8_line_vert(int dot_style)
Definition: canvas_line.c:30
static char * utf8_line_horiz(int dot_style)
Definition: canvas_line.c:41
#define useUtf8Curvy
Definition: canvas_line.c:10
RZ_API void rz_cons_canvas_line_square_defined(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int bendpoint, int isvert)
Definition: canvas_line.c:401
static void apply_line_style(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int isvert)
Definition: canvas_line.c:52
RZ_API void rz_cons_canvas_line_square(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style)
Definition: canvas_line.c:371
#define DOTTED_LINE_HORIZ
Definition: canvas_line.c:12
static void draw_horizontal_line(RzConsCanvas *c, int x, int y, int width, int style, int dot_style)
Definition: canvas_line.c:109
#define W(y)
Definition: canvas_line.c:6
#define useUtf8
Definition: canvas_line.c:9
static void draw_vertical_line(RzConsCanvas *c, int x, int y, int height, int dot_style)
Definition: canvas_line.c:263
@ NRM_APEX
Definition: canvas_line.c:24
@ DOT_NRM
Definition: canvas_line.c:25
@ REV_APEX_NRM
Definition: canvas_line.c:26
@ DOT_APEX
Definition: canvas_line.c:20
@ DOT_DOT
Definition: canvas_line.c:22
@ NRM_NRM
Definition: canvas_line.c:27
@ REV_APEX_APEX
Definition: canvas_line.c:21
@ NRM_DOT
Definition: canvas_line.c:23
@ APEX_DOT
Definition: canvas_line.c:19
RZ_API void rz_cons_canvas_line_diagonal(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style)
Definition: canvas_line.c:285
#define DASHED_LINE_HORIZ
Definition: canvas_line.c:16
RZ_API void rz_cons_canvas_line_back_edge(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int ybendpoint1, int xbendpoint, int ybendpoint2, int isvert)
Definition: canvas_line.c:454
#define DOTTED_LINE_VERT
Definition: canvas_line.c:13
#define G(x, y)
Definition: canvas_line.c:7
#define DASHED_LINE_VERT
Definition: canvas_line.c:15
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
@ RZ_ABS
int x
Definition: mipsasm.c:20
v0.v4.v8.v15.v3.v30.v14.v1. h2
#define Color_RESET
Definition: rz_cons.h:617
#define DOT_STYLE_CONDITIONAL
Definition: rz_cons.h:784
#define RUNECODESTR_CURVE_CORNER_TL
Definition: rz_cons.h:395
#define DOT_STYLE_NORMAL
Definition: rz_cons.h:783
#define RUNECODESTR_LINE_HORIZ
Definition: rz_cons.h:391
#define RUNECODESTR_CORNER_BL
Definition: rz_cons.h:388
#define DOT_STYLE_BACKEDGE
Definition: rz_cons.h:785
#define RUNECODESTR_CORNER_TL
Definition: rz_cons.h:392
#define RUNECODESTR_CORNER_BR
Definition: rz_cons.h:387
#define RUNECODESTR_CURVE_CORNER_BL
Definition: rz_cons.h:398
#define RUNECODESTR_CORNER_TR
Definition: rz_cons.h:393
#define RUNECODESTR_CURVE_CORNER_TR
Definition: rz_cons.h:396
@ LINE_NOSYM_HORIZ
Definition: rz_cons.h:775
@ LINE_NOSYM_VERT
Definition: rz_cons.h:774
@ LINE_TRUE
Definition: rz_cons.h:771
@ LINE_NONE
Definition: rz_cons.h:770
@ LINE_FALSE
Definition: rz_cons.h:772
@ LINE_UNCJMP
Definition: rz_cons.h:773
#define RUNECODESTR_CURVE_CORNER_BR
Definition: rz_cons.h:397
#define RUNECODESTR_LINE_VERT
Definition: rz_cons.h:385
#define RZ_MIN(x, y)
#define c(i)
Definition: sha256.c:43
RzConsPrintablePalette pal
Definition: rz_cons.h:491
RzConsContext * context
Definition: rz_cons.h:502
uv_loop_t * loop
Definition: main.c:7
int width
Definition: main.c:10
int height
Definition: main.c:10