1 /* Copyright radare2 2014-2020 - Author: pancake, vane11ope */
2
3 #include <r_core.h>
4
5 /* few remaining static functions */
6 static bool __init_panels_menu(RCore *core);
7 static bool __init_panels(RCore *core, RPanels *panels);
8 static void __init_menu_screen_settings_layout(void *_core, const char *parent);
9 static void __init_new_panels_root(RCore *core);
10 static void __init_menu_color_settings_layout(void *core, const char *parent);
11 static void __init_menu_disasm_asm_settings_layout(void *_core, const char *parent);
12 static void __set_dcb(RCore *core, RPanel *p);
13 static void __set_pcb(RPanel *p);
14 static void __panels_refresh(RCore *core);
15
16 #define MENU_Y 1
17 #define PANEL_NUM_LIMIT 9
18
19 #define PANEL_TITLE_SYMBOLS "Symbols"
20 #define PANEL_TITLE_STACK "Stack"
21 #define PANEL_TITLE_XREFS_HERE "Xrefs Here"
22 #define PANEL_TITLE_XREFS "Xrefs"
23 #define PANEL_TITLE_REGISTERS "Registers"
24 #define PANEL_TITLE_DISASSEMBLY "Disassembly"
25 #define PANEL_TITLE_DISASMSUMMARY "Disassemble Summary"
26 #define PANEL_TITLE_ALL_DECOMPILER "Show All Decompiler Output"
27 #define PANEL_TITLE_DECOMPILER "Decompiler"
28 #define PANEL_TITLE_DECOMPILER_O "Decompiler With Offsets"
29 #define PANEL_TITLE_GRAPH "Graph"
30 #define PANEL_TITLE_TINY_GRAPH "Tiny Graph"
31 #define PANEL_TITLE_FUNCTIONS "Functions"
32 #define PANEL_TITLE_FUNCTIONCALLS "Function Calls"
33 #define PANEL_TITLE_BREAKPOINTS "Breakpoints"
34 #define PANEL_TITLE_STRINGS_DATA "Strings in data sections"
35 #define PANEL_TITLE_STRINGS_BIN "Strings in the whole bin"
36 #define PANEL_TITLE_SECTIONS "Sections"
37 #define PANEL_TITLE_SEGMENTS "Segments"
38 #define PANEL_TITLE_COMMENTS "Comments"
39
40 #define PANEL_CMD_SYMBOLS "isq"
41 #define PANEL_CMD_XREFS_HERE "ax."
42 #define PANEL_CMD_XREFS "ax"
43 #define PANEL_CMD_STACK "px"
44 #define PANEL_CMD_REGISTERS "dr"
45 #define PANEL_CMD_DISASSEMBLY "pd"
46 #define PANEL_CMD_DISASMSUMMARY "pdsf"
47 #define PANEL_CMD_DECOMPILER "pdc"
48 #define PANEL_CMD_DECOMPILER_O "pddo"
49 #define PANEL_CMD_FUNCTION "afl"
50 #define PANEL_CMD_GRAPH "agf"
51 #define PANEL_CMD_TINYGRAPH "agft"
52 #define PANEL_CMD_HEXDUMP "xc"
53 #define PANEL_CMD_CONSOLE "$console"
54
55 #define PANEL_CONFIG_MENU_MAX 64
56 #define PANEL_CONFIG_PAGE 10
57 #define PANEL_CONFIG_SIDEPANEL_W 60
58 #define PANEL_CONFIG_RESIZE_W 4
59 #define PANEL_CONFIG_RESIZE_H 4
60
61 #define COUNT(x) (sizeof((x)) / sizeof((*x)) - 1)
62
63 // TODO: kill mutable globals
64 static bool firstRun = true;
65 static bool fromVisual = false;
66 static char *menus_Colors[128];
67
68 typedef enum {
69 LEFT,
70 RIGHT,
71 UP,
72 DOWN
73 } Direction;
74
75 static const char *panels_dynamic [] = {
76 "Disassembly", "Stack", "Registers",
77 NULL
78 };
79
80 static const char *panels_static [] = {
81 "Disassembly", "Functions", "Symbols",
82 NULL
83 };
84
85 static const char *menus[] = {
86 "File", "Settings", "Edit", "View", "Tools", "Search", "Emulate", "Debug", "Analyze", "Help",
87 NULL
88 };
89
90 static const char *menus_File[] = {
91 "New", "Open", "ReOpen", "Close", "Save Layout", "Load Layout", "Clear Saved Layouts", "Quit",
92 NULL
93 };
94
95 static const char *menus_Settings[] = {
96 "Colors", "Decompiler", "Disassembly", "Screen",
97 NULL
98 };
99
100 static const char *menus_ReOpen[] = {
101 "In RW", "In Debugger",
102 NULL
103 };
104
105 static const char *menus_loadLayout[] = {
106 "Saved", "Default",
107 NULL
108 };
109
110 static const char *menus_Edit[] = {
111 "Copy", "Paste", "Clipboard", "Write String", "Write Hex", "Write Value", "Assemble", "Fill", "io.cache",
112 NULL
113 };
114
115 static const char *menus_iocache[] = {
116 "On", "Off",
117 NULL
118 };
119
120 static const char *menus_View[] = {
121 "Console", "Hexdump", "Disassembly", "Disassemble Summary", "Decompiler", "Decompiler With Offsets", "Graph", "Tiny Graph",
122 "Functions", "Function Calls", "Sections", "Segments", PANEL_TITLE_STRINGS_DATA, PANEL_TITLE_STRINGS_BIN, "Symbols", "Imports",
123 "Info", "Database", "Breakpoints", "Comments", "Classes", "Entropy", "Entropy Fire", "Stack", "Xrefs Here", "Methods",
124 "Var READ address", "Var WRITE address", "Summary", "Relocs", "Headers", "File Hashes", PANEL_TITLE_ALL_DECOMPILER,
125 NULL
126 };
127
128 static const char *menus_Tools[] = {
129 "Calculator", "R2 Shell", "System Shell",
130 NULL
131 };
132
133 static const char *menus_Search[] = {
134 "String (Whole Bin)", "String (Data Sections)", "ROP", "Code", "Hexpairs",
135 NULL
136 };
137
138 static const char *menus_Emulate[] = {
139 "Step From", "Step To", "Step Range",
140 NULL
141 };
142
143 static const char *menus_Debug[] = {
144 "Registers", "RegisterRefs", "DRX", "Breakpoints", "Watchpoints",
145 "Maps", "Modules", "Backtrace", "Locals", "Continue",
146 "Step", "Step Over", "Reload",
147 NULL
148 };
149
150 static const char *menus_Analyze[] = {
151 "Function", "Symbols", "Program", "BasicBlocks", "Calls", "References",
152 NULL
153 };
154
155 static const char *menus_settings_disassembly[] = {
156 "asm", "hex.section", "io.cache", "hex.pairs", "emu.str",
157 NULL
158 };
159
160 static const char *menus_settings_disassembly_asm[] = {
161 "asm.bytes", "asm.section", "asm.cmt.right", "asm.emu", "asm.var.summary",
162 "asm.pseudo", "asm.flags.inbytes", "asm.arch", "asm.bits", "asm.cpu",
163 NULL
164 };
165
166 static const char *menus_settings_screen[] = {
167 "scr.bgfill", "scr.color", "scr.utf8", "scr.utf8.curvy", "scr.wheel",
168 NULL
169 };
170
171 static const char *menus_Help[] = {
172 "Toggle Help",
173 "License", "Version",
174 "Fortune", "2048",
175 NULL
176 };
177
178 static const char *entropy_rotate[] = {
179 "", "2", "b", "c", "d", "e", "F", "i", "j", "m", "p", "s", "z", "0",
180 NULL
181 };
182
183 static char *hexdump_rotate[] = {
184 "xc", "pxa", "pxr", "prx", "pxb", "pxh", "pxw", "pxq", "pxd", "pxr",
185 NULL
186 };
187
188 static const char *register_rotate[] = {
189 "", "=", "r", "??", "C", "i", "o",
190 NULL
191 };
192
193 static const char *function_rotate[] = {
194 "l", "i", "x",
195 NULL
196 };
197
198 static const char *cache_white_list_cmds[] = {
199 "pdc", "pddo", "agf", "Help",
200 NULL
201 };
202
203 static const char *help_msg_panels[] = {
204 "|", "split current panel vertically",
205 "-", "split current panel horizontally",
206 ":", "run r2 command in prompt",
207 ";", "add/remove comment",
208 "_", "show hud",
209 "\\", "show user-friendly hud",
210 "?", "show this help",
211 "!", "swap into visual mode",
212 ".", "seek to PC or entrypoint",
213 "*", "show decompiler in the current panel",
214 "\"", "create a panel from the list and replace the current one",
215 "/", "highlight the keyword",
216 "(", "toggle snow",
217 "&", "toggle cache",
218 "[1-9]", "follow jmp/call identified by shortcut (like ;[1])",
219 "' '", "(space) toggle graph / panels",
220 "tab", "go to the next panel",
221 "Enter", "maximize current panel in zoom mode",
222 "a", "toggle auto update for decompiler",
223 "b", "browse symbols, flags, configurations, classes, ...",
224 "c", "toggle cursor",
225 "C", "toggle color",
226 "d", "define in the current address. Same as Vd",
227 "D", "show disassembly in the current panel",
228 "e", "change title and command of current panel",
229 "f", "set/add filter keywords",
230 "F", "remove all the filters",
231 "g", "go/seek to given offset",
232 "G", "go/seek to highlight",
233 "i", "insert hex",
234 "hjkl", "move around (left-down-up-right)",
235 "HJKL", "move around (left-down-up-right) by page",
236 "m", "select the menu panel",
237 "M", "open new custom frame",
238 "n/N", "seek next/prev function/flag/hit (scr.nkey)",
239 "p/P", "rotate panel layout",
240 "q", "quit, or close a tab",
241 "Q", "close all the tabs and quit",
242 "r", "toggle callhints/jmphints/leahints",
243 "R", "randomize color palette (ecr)",
244 "s/S", "step in / step over",
245 "t/T", "tab prompt / close a tab",
246 "u/U", "undo / redo seek",
247 "w", "shuffle panels around in window mode",
248 "V", "go to the graph mode",
249 "xX", "show xrefs/refs of current function from/to data/code",
250 "z", "swap current panel with the first one",
251 NULL
252 };
253
254 static const char *help_msg_panels_window[] = {
255 ":", "run r2 command in prompt",
256 ";", "add/remove comment",
257 "\"", "create a panel from the list and replace the current one",
258 "?", "show this help",
259 "|", "split the current panel vertically",
260 "-", "split the current panel horizontally",
261 "tab", "go to the next panel",
262 "Enter", "maximize current panel in zoom mode",
263 "d", "define in the current address. Same as Vd",
264 "b", "browse symbols, flags, configurations, classes, ...",
265 "hjkl", "move around (left-down-up-right)",
266 "HJKL", "resize panels vertically/horizontally",
267 "Q/q/w", "quit window mode",
268 "p/P", "rotate panel layout",
269 "t/T", "rotate related commands in a panel",
270 "X", "close current panel",
271 NULL
272 };
273
274 static const char *help_msg_panels_zoom[] = {
275 "?", "show this help",
276 ":", "run r2 command in prompt",
277 ";", "add/remove comment",
278 "\"", "create a panel from the list and replace the current one",
279 "' '", "(space) toggle graph / panels",
280 "tab", "go to the next panel",
281 "b", "browse symbols, flags, configurations, classes, ...",
282 "d", "define in the current address. Same as Vd",
283 "c", "toggle cursor",
284 "C", "toggle color",
285 "hjkl", "move around (left-down-up-right)",
286 "p/P", "seek to next or previous scr.nkey",
287 "s/S", "step in / step over",
288 "t/T", "rotate related commands in a panel",
289 "xX", "show xrefs/refs of current function from/to data/code",
290 "q/Q/Enter","quit zoom mode",
291 NULL
292 };
293
__get_panel(RPanels * panels,int i)294 static RPanel *__get_panel(RPanels *panels, int i) {
295 return (panels && i < PANEL_NUM_LIMIT)? panels->panel[i]: NULL;
296 }
297
__update_edge_x(RCore * core,int x)298 static void __update_edge_x(RCore *core, int x) {
299 RPanels *panels = core->panels;
300 int i, j;
301 int tmp_x = 0;
302 for (i = 0; i < panels->n_panels; i++) {
303 RPanel *p0 = __get_panel (panels, i);
304 if (p0 && (p0->view->pos.x - 2 <= panels->mouse_orig_x &&
305 panels->mouse_orig_x <= p0->view->pos.x + 2)) {
306 tmp_x = p0->view->pos.x;
307 p0->view->pos.x += x;
308 p0->view->pos.w -= x;
309 for (j = 0; j < panels->n_panels; j++) {
310 RPanel *p1 = __get_panel (panels, j);
311 if (p1 && (p1->view->pos.x + p1->view->pos.w - 1 == tmp_x)) {
312 p1->view->pos.w += x;
313 }
314 }
315 }
316 }
317 }
318
__update_edge_y(RCore * core,int y)319 static void __update_edge_y(RCore *core, int y) {
320 RPanels *panels = core->panels;
321 size_t i, j;
322 int tmp_y = 0;
323 for (i = 0; i < panels->n_panels; i++) {
324 RPanel *p0 = __get_panel (panels, i);
325 if (p0 && (p0->view->pos.y - 2 <= panels->mouse_orig_y &&
326 panels->mouse_orig_y <= p0->view->pos.y + 2)) {
327 tmp_y = p0->view->pos.y;
328 p0->view->pos.y += y;
329 p0->view->pos.h -= y;
330 for (j = 0; j < panels->n_panels; j++) {
331 RPanel *p1 = __get_panel (panels, j);
332 if (p1 && (p1->view->pos.y + p1->view->pos.h - 1 == tmp_y)) {
333 p1->view->pos.h += y;
334 }
335 }
336 }
337 }
338 }
339
__check_if_mouse_x_illegal(RCore * core,int x)340 static bool __check_if_mouse_x_illegal(RCore *core, int x) {
341 RPanels *panels = core->panels;
342 RConsCanvas *can = panels->can;
343 const int edge_x = 1;
344 if (x <= edge_x || can->w - edge_x <= x) {
345 return true;
346 }
347 return false;
348 }
349
__check_if_mouse_y_illegal(RCore * core,int y)350 static bool __check_if_mouse_y_illegal(RCore *core, int y) {
351 RPanels *panels = core->panels;
352 RConsCanvas *can = panels->can;
353 const int edge_y = 0;
354 if (y <= edge_y || can->h - edge_y <= y) {
355 return true;
356 }
357 return false;
358 }
359
__check_if_mouse_x_on_edge(RCore * core,int x,int y)360 static bool __check_if_mouse_x_on_edge(RCore *core, int x, int y) {
361 RPanels *panels = core->panels;
362 const int edge_x = r_config_get_i (core->config, "scr.panelborder")? 3: 1;
363 int i = 0;
364 for (; i < panels->n_panels; i++) {
365 RPanel *panel = __get_panel (panels, i);
366 if (panel && (x > panel->view->pos.x - (edge_x - 1) && x <= panel->view->pos.x + edge_x)) {
367 panels->mouse_on_edge_x = true;
368 panels->mouse_orig_x = x;
369 return true;
370 }
371 }
372 return false;
373 }
374
__check_if_mouse_y_on_edge(RCore * core,int x,int y)375 static bool __check_if_mouse_y_on_edge(RCore *core, int x, int y) {
376 RPanels *panels = core->panels;
377 const int edge_y = r_config_get_i (core->config, "scr.panelborder")? 3: 1;
378 int i = 0;
379 for (; i < panels->n_panels; i++) {
380 RPanel *panel = __get_panel (panels, i);
381 if (panel && (x > panel->view->pos.x && x <= panel->view->pos.x + panel->view->pos.w + edge_y)) {
382 if (y > 2 && y >= panel->view->pos.y && y <= panel->view->pos.y + edge_y) {
383 panels->mouse_on_edge_y = true;
384 panels->mouse_orig_y = y;
385 return true;
386 }
387 }
388 }
389 return false;
390 }
391
__get_cur_panel(RPanels * panels)392 static RPanel *__get_cur_panel(RPanels *panels) {
393 return __get_panel (panels, panels->curnode);
394 }
395
__check_if_cur_panel(RCore * core,RPanel * panel)396 static bool __check_if_cur_panel(RCore *core, RPanel *panel) {
397 return __get_cur_panel (core->panels) == panel;
398 }
399
__check_if_addr(const char * c,int len)400 static bool __check_if_addr(const char *c, int len) {
401 if (len < 2) {
402 return false;
403 }
404 int i = 0;
405 for (; i < len; i++) {
406 if (R_STR_ISNOTEMPTY (c + i) && R_STR_ISNOTEMPTY (c+ i + 1) &&
407 c[i] == '0' && c[i + 1] == 'x') {
408 return true;
409 }
410 }
411 return false;
412 }
413
__check_edge(RCore * core)414 static void __check_edge(RCore *core) {
415 RPanels *panels = core->panels;
416 int i;
417 for (i = 0; i < panels->n_panels; i++) {
418 RPanel *panel = __get_panel (panels, i);
419 if (!panel) {
420 continue;
421 }
422 if (panel->view->pos.x + panel->view->pos.w == core->panels->can->w) {
423 panel->view->edge |= (1 << PANEL_EDGE_RIGHT);
424 } else {
425 panel->view->edge &= (1 << PANEL_EDGE_BOTTOM);
426 }
427 if (panel->view->pos.y + panel->view->pos.h == core->panels->can->h) {
428 panel->view->edge |= (1 << PANEL_EDGE_BOTTOM);
429 } else {
430 panel->view->edge &= (1 << PANEL_EDGE_RIGHT);
431 }
432 }
433 }
434
__shrink_panels_forward(RCore * core,int target)435 static void __shrink_panels_forward(RCore *core, int target) {
436 RPanels *panels = core->panels;
437 int i = target;
438 for (; i < panels->n_panels - 1; i++) {
439 panels->panel[i] = panels->panel[i + 1];
440 }
441 }
442
__shrink_panels_backward(RCore * core,int target)443 static void __shrink_panels_backward(RCore *core, int target) {
444 RPanels *panels = core->panels;
445 int i = target;
446 for (; i > 0; i--) {
447 panels->panel[i] = panels->panel[i - 1];
448 }
449 }
450
__cache_white_list(RCore * core,RPanel * panel)451 static void __cache_white_list(RCore *core, RPanel *panel) {
452 int i = 0;
453 for (; i < COUNT (cache_white_list_cmds); i++) {
454 if (!strcmp (panel->model->cmd, cache_white_list_cmds[i])) {
455 panel->model->cache = true;
456 return;
457 }
458 }
459 panel->model->cache = false;
460 }
461
__search_db(RCore * core,const char * title)462 static char *__search_db(RCore *core, const char *title) {
463 RPanels *panels = core->panels;
464 if (!panels->db) {
465 return NULL;
466 }
467 char *out = sdb_get (panels->db, title, 0);
468 if (out) {
469 return out;
470 }
471 return NULL;
472 }
473
__show_status(RCore * core,const char * msg)474 static int __show_status(RCore *core, const char *msg) {
475 r_cons_gotoxy (0, 0);
476 r_cons_printf (R_CONS_CLEAR_LINE"%s[Status] %s"Color_RESET, core->cons->context->pal.graph_box2, msg);
477 r_cons_flush ();
478 return r_cons_readchar ();
479 }
480
__show_status_yesno(RCore * core,int def,const char * msg)481 static bool __show_status_yesno(RCore *core, int def, const char *msg) {
482 r_cons_gotoxy (0, 0);
483 r_cons_flush ();
484 return r_cons_yesno (def, R_CONS_CLEAR_LINE"%s[Status] %s"Color_RESET, core->cons->context->pal.graph_box2, msg);
485 }
486
__show_status_input(RCore * core,const char * msg)487 static char *__show_status_input(RCore *core, const char *msg) {
488 char *n_msg = r_str_newf (R_CONS_CLEAR_LINE"%s[Status] %s"Color_RESET, core->cons->context->pal.graph_box2, msg);
489 r_cons_gotoxy (0, 0);
490 r_cons_flush ();
491 char *out = r_cons_input (n_msg);
492 free (n_msg);
493 return out;
494 }
495
__check_panel_type(RPanel * panel,const char * type)496 static bool __check_panel_type(RPanel *panel, const char *type) {
497 if (!panel || !panel->model->cmd || !type) {
498 return false;
499 }
500 char *tmp = r_str_new (panel->model->cmd);
501 int n = r_str_split (tmp, ' ');
502 if (!n) {
503 free (tmp);
504 return false;
505 }
506 const char *base = r_str_word_get0 (tmp, 0);
507 if (R_STR_ISEMPTY (base)) {
508 free (tmp);
509 return false;
510 }
511 int len = strlen (type);
512 if (!strcmp (type, PANEL_CMD_DISASSEMBLY)) {
513 if (!strncmp (tmp, type, len) &&
514 strcmp (panel->model->cmd, PANEL_CMD_DECOMPILER) &&
515 strcmp (panel->model->cmd, PANEL_CMD_DECOMPILER_O) &&
516 strcmp (panel->model->cmd, PANEL_CMD_DISASMSUMMARY)) {
517 free (tmp);
518 return true;
519 }
520 free (tmp);
521 return false;
522 }
523 if (!strcmp (type, PANEL_CMD_STACK)) {
524 if (!strcmp (tmp, PANEL_CMD_STACK)) {
525 free (tmp);
526 return true;
527 }
528 free (tmp);
529 return false;
530 }
531 if (!strcmp (type, PANEL_CMD_HEXDUMP)) {
532 int i = 0;
533 for (; i < COUNT (hexdump_rotate); i++) {
534 if (!strcmp (tmp, hexdump_rotate[i])) {
535 free (tmp);
536 return true;
537 }
538 }
539 free (tmp);
540 return false;
541 }
542 free (tmp);
543 return !strncmp (panel->model->cmd, type, len);
544 }
545
__check_root_state(RCore * core,RPanelsRootState state)546 static bool __check_root_state(RCore *core, RPanelsRootState state) {
547 return core->panels_root->root_state == state;
548 }
549
search_db_check_panel_type(RCore * core,RPanel * panel,const char * ch)550 static bool search_db_check_panel_type (RCore *core, RPanel *panel, const char *ch) {
551 char *str = __search_db (core, ch);
552 bool ret = str && __check_panel_type (panel, str);
553 free (str);
554 return ret;
555 }
556
557 //TODO: Refactroing
__is_abnormal_cursor_type(RCore * core,RPanel * panel)558 static bool __is_abnormal_cursor_type(RCore *core, RPanel *panel) {
559 if (__check_panel_type (panel, PANEL_CMD_SYMBOLS) || __check_panel_type (panel, PANEL_CMD_FUNCTION)) {
560 return true;
561 }
562 if (search_db_check_panel_type (core, panel, PANEL_TITLE_DISASMSUMMARY)) {
563 return true;
564 }
565 if (search_db_check_panel_type (core, panel, PANEL_TITLE_STRINGS_DATA)) {
566 return true;
567 }
568 if (search_db_check_panel_type (core, panel, PANEL_TITLE_STRINGS_BIN)) {
569 return true;
570 }
571 if (search_db_check_panel_type (core, panel, PANEL_TITLE_BREAKPOINTS)) {
572 return true;
573 }
574 if (search_db_check_panel_type (core, panel, PANEL_TITLE_SECTIONS)) {
575 return true;
576 }
577 if (search_db_check_panel_type (core, panel, PANEL_TITLE_SEGMENTS)) {
578 return true;
579 }
580 if (search_db_check_panel_type (core, panel, PANEL_TITLE_COMMENTS)) {
581 return true;
582 }
583 return false;
584 }
585
__is_normal_cursor_type(RPanel * panel)586 static bool __is_normal_cursor_type(RPanel *panel) {
587 return (__check_panel_type (panel, PANEL_CMD_STACK) ||
588 __check_panel_type (panel, PANEL_CMD_REGISTERS) ||
589 __check_panel_type (panel, PANEL_CMD_DISASSEMBLY) ||
590 __check_panel_type (panel, PANEL_CMD_HEXDUMP));
591 }
592
__set_cmd_str_cache(RCore * core,RPanel * p,char * s)593 static void __set_cmd_str_cache(RCore *core, RPanel *p, char *s) {
594 free (p->model->cmdStrCache);
595 p->model->cmdStrCache = s;
596 __set_dcb (core, p);
597 __set_pcb (p);
598 }
599
__set_decompiler_cache(RCore * core,char * s)600 static void __set_decompiler_cache(RCore *core, char *s) {
601 RAnalFunction *func = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
602 if (func) {
603 if (core->panels_root->cur_pdc_cache) {
604 sdb_ptr_set (core->panels_root->cur_pdc_cache, r_num_as_string (NULL, func->addr, false), r_str_new (s), 0);
605 } else {
606 Sdb *sdb = sdb_new0 ();
607 const char *pdc_now = r_config_get (core->config, "cmd.pdc");
608 sdb_ptr_set (sdb, r_num_as_string (NULL, func->addr, false), r_str_new (s), 0);
609 core->panels_root->cur_pdc_cache = sdb;
610 if (!sdb_exists (core->panels_root->pdc_caches, pdc_now)) {
611 sdb_ptr_set (core->panels_root->pdc_caches, r_str_new (pdc_now), sdb, 0);
612 }
613 }
614 }
615 }
616
__set_read_only(RCore * core,RPanel * p,char * s)617 static void __set_read_only(RCore *core, RPanel *p, char *s) {
618 free (p->model->readOnly);
619 p->model->readOnly = r_str_new (s);
620 __set_dcb (core, p);
621 __set_pcb (p);
622 }
623
__set_pos(RPanelPos * pos,int x,int y)624 static void __set_pos(RPanelPos *pos, int x, int y) {
625 pos->x = x;
626 pos->y = y;
627 }
628
__set_size(RPanelPos * pos,int w,int h)629 static void __set_size(RPanelPos *pos, int w, int h) {
630 pos->w = w;
631 pos->h = h;
632 }
633
__set_geometry(RPanelPos * pos,int x,int y,int w,int h)634 static void __set_geometry(RPanelPos *pos, int x, int y, int w, int h) {
635 __set_pos (pos, x, y);
636 __set_size (pos, w, h);
637 }
638
__set_panel_addr(RCore * core,RPanel * panel,ut64 addr)639 static void __set_panel_addr(RCore *core, RPanel *panel, ut64 addr) {
640 panel->model->addr = addr;
641 }
642
__get_panel_idx_in_pos(RCore * core,int x,int y)643 static int __get_panel_idx_in_pos(RCore *core, int x, int y) {
644 RPanels *panels = core->panels;
645 int i = -1;
646 for (i = 0; i < panels->n_panels; i++) {
647 RPanel *p = __get_panel (panels, i);
648 if (p && (x >= p->view->pos.x && x < p->view->pos.x + p->view->pos.w)) {
649 if (y >= p->view->pos.y && y < p->view->pos.y + p->view->pos.h) {
650 break;
651 }
652 }
653 }
654 return i;
655 }
656
__handlePrompt(RCore * core,RPanels * panels)657 static void __handlePrompt(RCore *core, RPanels *panels) {
658 r_core_visual_prompt_input (core);
659 int i;
660 for (i = 0; i < panels->n_panels; i++) {
661 RPanel *p = __get_panel (panels, i);
662 if (p && __check_panel_type (p, PANEL_CMD_DISASSEMBLY)) {
663 __set_panel_addr (core, p, core->offset);
664 break;
665 }
666 }
667 }
668
__menu_panel_print(RConsCanvas * can,RPanel * panel,int x,int y,int w,int h)669 static void __menu_panel_print(RConsCanvas *can, RPanel *panel, int x, int y, int w, int h) {
670 (void) r_cons_canvas_gotoxy (can, panel->view->pos.x + 2, panel->view->pos.y + 2);
671 char *text = r_str_ansi_crop (panel->model->title, x, y, w, h);
672 if (text) {
673 r_cons_canvas_write (can, text);
674 free (text);
675 } else {
676 r_cons_canvas_write (can, panel->model->title);
677 }
678 }
679
__update_help_contents(RCore * core,RPanel * panel)680 static void __update_help_contents(RCore *core, RPanel *panel) {
681 char *read_only = panel->model->readOnly;
682 char *text = NULL;
683 int sx = panel->view->sx;
684 int sy = R_MAX (panel->view->sy, 0);
685 int x = panel->view->pos.x;
686 int y = panel->view->pos.y;
687 int w = panel->view->pos.w;
688 int h = panel->view->pos.h;
689 RPanels *panels = core->panels;
690 RConsCanvas *can = panels->can;
691 (void) r_cons_canvas_gotoxy (can, x + 2, y + 2);
692 if (sx < 0) {
693 char *white = (char*)r_str_pad (' ', 128);
694 int idx = R_MIN (-sx, strlen (white) - 1);
695 white[idx] = 0;
696 text = r_str_ansi_crop (read_only,
697 0, sy, w + sx - 3, h - 2 + sy);
698 char *newText = r_str_prefix_all (text, white);
699 if (newText) {
700 free (text);
701 text = newText;
702 }
703 } else {
704 text = r_str_ansi_crop (read_only,
705 sx, sy, w + sx - 3, h - 2 + sy);
706 }
707 if (text) {
708 r_cons_canvas_write (can, text);
709 free (text);
710 }
711 }
712
__update_help_title(RCore * core,RPanel * panel)713 static void __update_help_title(RCore *core, RPanel *panel) {
714 RConsCanvas *can = core->panels->can;
715 RStrBuf *title = r_strbuf_new (NULL);
716 RStrBuf *cache_title = r_strbuf_new (NULL);
717 if (__check_if_cur_panel (core, panel)) {
718 r_strbuf_setf (title, "%s[X] %s"Color_RESET,
719 core->cons->context->pal.graph_box2, panel->model->title);
720 r_strbuf_setf (cache_title, "%s[Cache] N/A"Color_RESET,
721 core->cons->context->pal.graph_box2);
722 } else {
723 r_strbuf_setf (title, "[X] %s ", panel->model->title);
724 r_strbuf_setf (cache_title, "[Cache] N/A");
725 }
726 if (r_cons_canvas_gotoxy (can, panel->view->pos.x + 1, panel->view->pos.y + 1)) {
727 r_cons_canvas_write (can, r_strbuf_get (title));
728 }
729 if (r_cons_canvas_gotoxy (can, panel->view->pos.x + panel->view->pos.w
730 - r_str_ansi_len (r_strbuf_get (cache_title)) - 2, panel->view->pos.y + 1)) {
731 r_cons_canvas_write (can, r_strbuf_get (cache_title));
732 }
733 r_strbuf_free (cache_title);
734 r_strbuf_free (title);
735 }
736
__update_panel_contents(RCore * core,RPanel * panel,const char * cmdstr)737 static void __update_panel_contents(RCore *core, RPanel *panel, const char *cmdstr) {
738 bool b = __is_abnormal_cursor_type (core, panel) && core->print->cur_enabled;
739 int sx = b ? -2 :panel->view->sx;
740 int sy = R_MAX (panel->view->sy, 0);
741 int x = panel->view->pos.x;
742 int y = panel->view->pos.y;
743 if (x >= core->panels->can->w) {
744 return;
745 }
746 if (y >= core->panels->can->h) {
747 return;
748 }
749 int w = panel->view->pos.w;
750 int h = panel->view->pos.h;
751 int graph_pad = __check_panel_type (panel, PANEL_CMD_GRAPH) ? 1 : 0;
752 char *text = NULL;
753 RPanels *panels = core->panels;
754 RConsCanvas *can = panels->can;
755 (void) r_cons_canvas_gotoxy (can, x + 2, y + 2);
756 if (sx < 0) {
757 char *white = (char*)r_str_pad (' ', 128);
758 int idx = R_MIN (-sx, strlen (white) - 1);
759 white[idx] = 0;
760 text = r_str_ansi_crop (cmdstr,
761 0, sy + graph_pad, w + sx - 3, h - 2 + sy);
762 char *newText = r_str_prefix_all (text, white);
763 if (newText) {
764 free (text);
765 text = newText;
766 }
767 } else {
768 text = r_str_ansi_crop (cmdstr, sx, sy + graph_pad, w + sx - 3, h - 2 + sy);
769 }
770 if (text) {
771 r_cons_canvas_write (can, text);
772 free (text);
773 }
774 if (b) {
775 int sub = panel->view->curpos - panel->view->sy;
776 (void) r_cons_canvas_gotoxy (can, panel->view->pos.x + 2, panel->view->pos.y + 2 + sub);
777 r_cons_canvas_write (can, "*");
778 }
779 }
780
__apply_filter_cmd(RCore * core,RPanel * panel)781 static char *__apply_filter_cmd(RCore *core, RPanel *panel) {
782 char *out = r_str_ndup (panel->model->cmd, strlen (panel->model->cmd) + 1024);
783 if (!panel->model->filter) {
784 return out;
785 }
786 int i;
787 for (i = 0; i < panel->model->n_filter; i++) {
788 char *filter = panel->model->filter[i];
789 if (strlen (filter) > 1024) {
790 (void)__show_status (core, "filter is too big.");
791 return out;
792 }
793 strcat (out, "~");
794 strcat (out, filter);
795 }
796 return out;
797 }
798
__update_panel_title(RCore * core,RPanel * panel)799 static void __update_panel_title(RCore *core, RPanel *panel) {
800 RConsCanvas *can = core->panels->can;
801 RStrBuf *title = r_strbuf_new (NULL);
802 RStrBuf *cache_title = r_strbuf_new (NULL);
803 char *cmd_title = __apply_filter_cmd (core, panel);
804 if (__check_if_cur_panel (core, panel)) {
805 if (!strcmp (panel->model->title, cmd_title)) {
806 r_strbuf_setf (title, "%s[X] %s"Color_RESET, core->cons->context->pal.graph_box2, panel->model->title);
807 } else {
808 r_strbuf_setf (title, "%s[X] %s (%s)"Color_RESET, core->cons->context->pal.graph_box2, panel->model->title, cmd_title);
809 }
810 r_strbuf_setf (cache_title, "%s[Cache] %s"Color_RESET, core->cons->context->pal.graph_box2, panel->model->cache ? "On" : "Off");
811 } else {
812 if (!strcmp (panel->model->title, cmd_title)) {
813 r_strbuf_setf (title, "[X] %s ", panel->model->title);
814 } else {
815 r_strbuf_setf (title, "[X] %s (%s) ", panel->model->title, cmd_title);
816 }
817 r_strbuf_setf (cache_title, "[Cache] %s", panel->model->cache ? "On" : "Off");
818 }
819 r_strbuf_slice (title, 0, panel->view->pos.w);
820 r_strbuf_slice (cache_title, 0, panel->view->pos.w);
821 if (r_cons_canvas_gotoxy (can, panel->view->pos.x + 1, panel->view->pos.y + 1)) {
822 r_cons_canvas_write (can, r_strbuf_get (title));
823 }
824 if (r_cons_canvas_gotoxy (can, panel->view->pos.x + panel->view->pos.w - r_str_ansi_len (r_strbuf_get (cache_title)) - 2, panel->view->pos.y + 1)) {
825 r_cons_canvas_write (can, r_strbuf_get (cache_title));
826 }
827 r_strbuf_free (title);
828 r_strbuf_free (cache_title);
829 free (cmd_title);
830 }
831
832 //TODO: make this a task
__update_pdc_contents(RCore * core,RPanel * panel,char * cmdstr)833 static void __update_pdc_contents(RCore *core, RPanel *panel, char *cmdstr) {
834 RPanels *panels = core->panels;
835 RConsCanvas *can = panels->can;
836 int sx = panel->view->sx;
837 int sy = R_MAX (panel->view->sy, 0);
838 int x = panel->view->pos.x;
839 int y = panel->view->pos.y;
840 int w = panel->view->pos.w;
841 int h = panel->view->pos.h;
842 char *text = NULL;
843
844 (void) r_cons_canvas_gotoxy (can, x + 2, y + 2);
845
846 if (sx < 0) {
847 char *white = (char*)r_str_pad (' ', 128);
848 int idx = R_MIN (-sx, strlen (white) - 1);
849 white[idx] = 0;
850 text = r_str_ansi_crop (cmdstr, 0, sy, w + sx - 3, h - 2 + sy);
851 char *newText = r_str_prefix_all (text, white);
852 if (newText) {
853 free (text);
854 text = newText;
855 }
856 } else {
857 text = r_str_ansi_crop (cmdstr, sx, sy, w + sx - 3, h - 2 + sy);
858 }
859 if (text) {
860 r_cons_canvas_write (can, text);
861 free (text);
862 }
863 }
864
__find_cmd_str_cache(RCore * core,RPanel * panel)865 static char *__find_cmd_str_cache(RCore *core, RPanel* panel) {
866 if (panel->model->cache && panel->model->cmdStrCache) {
867 return panel->model->cmdStrCache;
868 }
869 return NULL;
870 }
871
__handle_cmd_str_cache(RCore * core,RPanel * panel,bool force_cache)872 static char *__handle_cmd_str_cache(RCore *core, RPanel *panel, bool force_cache) {
873 char *cmd = __apply_filter_cmd (core, panel);
874 bool b = core->print->cur_enabled && __get_cur_panel (core->panels) != panel;
875 if (b) {
876 core->print->cur_enabled = false;
877 }
878 char *out = (*cmd == '.')
879 ? r_core_cmd_str_pipe (core, cmd)
880 : r_core_cmd_str (core, cmd);
881 if (force_cache) {
882 panel->model->cache = true;
883 }
884 if (R_STR_ISNOTEMPTY (out)) {
885 __set_cmd_str_cache (core, panel, out);
886 } else {
887 R_FREE (out);
888 }
889 free (cmd);
890 if (b) {
891 core->print->cur_enabled = true;
892 }
893 return out;
894 }
895
__panel_all_clear(RPanels * panels)896 static void __panel_all_clear(RPanels *panels) {
897 if (!panels) {
898 return;
899 }
900 int i;
901 RPanel *panel = NULL;
902 for (i = 0; i < panels->n_panels; i++) {
903 panel = __get_panel (panels, i);
904 if (panel) {
905 r_cons_canvas_fill (panels->can, panel->view->pos.x, panel->view->pos.y, panel->view->pos.w, panel->view->pos.h, ' ');
906 }
907 }
908 r_cons_canvas_print (panels->can);
909 r_cons_flush ();
910 }
911
__layout_default(RPanels * panels)912 static void __layout_default(RPanels *panels) {
913 RPanel *p0 = __get_panel (panels, 0);
914 if (!p0){
915 eprintf("_get_panel (...,0) return null");
916 return;
917 }
918 int h, w = r_cons_get_size (&h);
919 if (panels->n_panels <= 1) {
920 __set_geometry (&p0->view->pos, 0, 1, w, h - 1);
921 return;
922 }
923
924 int ph = (h - 1) / (panels->n_panels - 1);
925 int colpos = w - panels->columnWidth;
926 __set_geometry (&p0->view->pos, 0, 1, colpos + 1, h - 1);
927
928 int pos_x = p0->view->pos.x + p0->view->pos.w - 1;
929 int i, total_h = 0;
930 for (i = 1; i < panels->n_panels; i++) {
931 RPanel *p = __get_panel (panels, i);
932 if (!p) {
933 continue;
934 }
935 int tmp_w = R_MAX (w - colpos, 0);
936 int tmp_h = 0;
937 if (i + 1 == panels->n_panels) {
938 tmp_h = h - total_h;
939 } else {
940 tmp_h = ph;
941 }
942 __set_geometry (&p->view->pos, pos_x, 2 + (ph * (i - 1)) - 1, tmp_w, tmp_h + 1);
943 total_h += 2 + (ph * (i - 1)) - 1 + tmp_h + 1;
944 }
945 }
946
__panels_layout(RPanels * panels)947 static void __panels_layout(RPanels *panels) {
948 panels->can->sx = 0;
949 panels->can->sy = 0;
950 __layout_default (panels);
951 }
952
__layout_equal_hor(RPanels * panels)953 static void __layout_equal_hor(RPanels *panels) {
954 int h, w = r_cons_get_size (&h);
955 int pw = w / panels->n_panels;
956 int i, cw = 0;
957 for (i = 0; i < panels->n_panels; i++) {
958 RPanel *p = __get_panel (panels, i);
959 if (!p) {
960 continue;
961 }
962 __set_geometry(&p->view->pos, cw, 1, pw, h - 1);
963 cw += pw - 1;
964 if (i == panels->n_panels - 2) {
965 pw = w - cw;
966 }
967 }
968 }
969
__adjust_side_panels(RCore * core)970 static void __adjust_side_panels(RCore *core) {
971 int i, h;
972 (void)r_cons_get_size (&h);
973 RPanels *panels = core->panels;
974 for (i = 0; i < panels->n_panels; i++) {
975 RPanel *p = __get_panel (panels, i);
976 if (p && (p->view->pos.x == 0)) {
977 if (p->view->pos.w >= PANEL_CONFIG_SIDEPANEL_W) {
978 p->view->pos.x += PANEL_CONFIG_SIDEPANEL_W - 1;
979 p->view->pos.w -= PANEL_CONFIG_SIDEPANEL_W - 1;
980 }
981 }
982 }
983 }
984
__update_help(RCore * core,RPanels * ps)985 static void __update_help(RCore *core, RPanels *ps) {
986 const char *help = "Help";
987 int i;
988 for (i = 0; i < ps->n_panels; i++) {
989 RPanel *p = __get_panel (ps, i);
990 if (!p) {
991 continue;
992 }
993 if (!strncmp (p->model->cmd, help, strlen (help))) {
994 RStrBuf *rsb = r_strbuf_new (NULL);
995 const char *title;
996 const char **msg;
997 switch (ps->mode) {
998 case PANEL_MODE_WINDOW:
999 title = "Panels Window Mode";
1000 msg = help_msg_panels_window;
1001 break;
1002 case PANEL_MODE_ZOOM:
1003 title = "Panels Zoom Mode";
1004 msg = help_msg_panels_zoom;
1005 break;
1006 default:
1007 title = "Panels Mode";
1008 msg = help_msg_panels;
1009 break;
1010 }
1011 // panel's title does not change, keep it short and simple
1012 p->model->title = r_str_dup (p->model->title, help);
1013 p->model->cmd = r_str_dup (p->model->cmd, help);
1014 r_core_visual_append_help (rsb, title, msg);
1015 if (!rsb) {
1016 break;
1017 }
1018 char *drained = r_strbuf_drain (rsb);
1019 __set_read_only (core, p, drained);
1020 free (drained);
1021 p->view->refresh = true;
1022 }
1023 }
1024 }
1025
__set_cursor(RCore * core,bool cur)1026 static void __set_cursor(RCore *core, bool cur) {
1027 RPanel *p = __get_cur_panel (core->panels);
1028 RPrint *print = core->print;
1029 print->cur_enabled = cur;
1030 if (__is_abnormal_cursor_type (core, p)) {
1031 return;
1032 }
1033 if (cur) {
1034 print->cur = p->view->curpos;
1035 } else {
1036 p->view->curpos = print->cur;
1037 }
1038 print->col = print->cur_enabled ? 1: 0;
1039 }
1040
__set_mode(RCore * core,RPanelsMode mode)1041 static void __set_mode(RCore *core, RPanelsMode mode) {
1042 RPanels *panels = core->panels;
1043 __set_cursor (core, false);
1044 panels->mode = mode;
1045 __update_help (core, panels);
1046 }
1047
__set_curnode(RCore * core,int idx)1048 static void __set_curnode(RCore *core, int idx) {
1049 RPanels *panels = core->panels;
1050 if (idx >= panels->n_panels) {
1051 idx = 0;
1052 }
1053 if (idx < 0) {
1054 idx = panels->n_panels - 1;
1055 }
1056 panels->curnode = idx;
1057
1058 RPanel *cur = __get_cur_panel (panels);
1059 cur->view->curpos = cur->view->sy;
1060 }
1061
__check_panel_num(RCore * core)1062 static bool __check_panel_num(RCore *core) {
1063 RPanels *panels = core->panels;
1064 if (panels->n_panels + 1 > PANEL_NUM_LIMIT) {
1065 const char *msg = "panel limit exceeded.";
1066 (void)__show_status (core, msg);
1067 return false;
1068 }
1069 return true;
1070 }
1071
__set_rcb(RPanels * ps,RPanel * p)1072 static void __set_rcb(RPanels *ps, RPanel *p) {
1073 SdbKv *kv;
1074 SdbListIter *sdb_iter;
1075 SdbList *sdb_list = sdb_foreach_list (ps->rotate_db, false);
1076 ls_foreach (sdb_list, sdb_iter, kv) {
1077 char *key = sdbkv_key (kv);
1078 if (!__check_panel_type (p, key)) {
1079 continue;
1080 }
1081 p->model->rotateCb = (RPanelRotateCallback)sdb_ptr_get (ps->rotate_db, key, 0);
1082 break;
1083 }
1084 ls_free (sdb_list);
1085 }
1086
__init_panel_param(RCore * core,RPanel * p,const char * title,const char * cmd)1087 static void __init_panel_param(RCore *core, RPanel *p, const char *title, const char *cmd) {
1088 if (!p) {
1089 return;
1090 }
1091 RPanelModel *m = p->model;
1092 RPanelView *v = p->view;
1093 m->type = PANEL_TYPE_DEFAULT;
1094 m->rotate = 0;
1095 v->curpos = 0;
1096 __set_panel_addr (core, p, core->offset);
1097 m->rotateCb = NULL;
1098 __set_cmd_str_cache (core, p, NULL);
1099 __set_read_only (core, p, NULL);
1100 m->funcName = NULL;
1101 v->refresh = true;
1102 v->edge = 0;
1103 if (title) {
1104 m->title = r_str_dup (m->title, title);
1105 if (cmd) {
1106 m->cmd = r_str_dup (m->cmd, cmd);
1107 } else {
1108 m->cmd = r_str_dup (m->cmd, "");
1109 }
1110 } else if (cmd) {
1111 m->title = r_str_dup (m->title, cmd);
1112 m->cmd = r_str_dup (m->cmd, cmd);
1113 } else {
1114 m->title = r_str_dup (m->title, "");
1115 m->cmd = r_str_dup (m->cmd, "");
1116 }
1117 __set_pcb (p);
1118 if (R_STR_ISNOTEMPTY (m->cmd)) {
1119 __set_dcb (core, p);
1120 __set_rcb (core->panels, p);
1121 if (__check_panel_type (p, PANEL_CMD_STACK)) {
1122 const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
1123 const ut64 stackbase = r_reg_getv (core->anal->reg, sp);
1124 m->baseAddr = stackbase;
1125 __set_panel_addr (core, p, stackbase - r_config_get_i (core->config, "stack.delta"));
1126 }
1127 }
1128 core->panels->n_panels++;
1129 __cache_white_list (core, p);
1130 return;
1131 }
1132
__insert_panel(RCore * core,int n,const char * name,const char * cmd)1133 static void __insert_panel(RCore *core, int n, const char *name, const char *cmd) {
1134 RPanels *panels = core->panels;
1135 if (panels->n_panels + 1 > PANEL_NUM_LIMIT) {
1136 return;
1137 }
1138 RPanel **panel = panels->panel;
1139 int i;
1140 RPanel *last = panel[panels->n_panels];
1141 for (i = panels->n_panels - 1; i >= n; i--) {
1142 panel[i + 1] = panel[i];
1143 }
1144 panel[n] = last;
1145 __init_panel_param (core, panel[n], name, cmd);
1146 }
1147
__add_cmd_panel(void * user)1148 static int __add_cmd_panel(void *user) {
1149 RCore *core = (RCore *)user;
1150 RPanels *panels = core->panels;
1151 if (!__check_panel_num (core)) {
1152 return 0;
1153 }
1154 RPanelsMenu *menu = core->panels->panels_menu;
1155 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
1156 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
1157 char *cmd = __search_db (core, child->name);
1158 if (!cmd) {
1159 return 0;
1160 }
1161 int h;
1162 (void)r_cons_get_size (&h);
1163 __adjust_side_panels (core);
1164 __insert_panel (core, 0, child->name, cmd);
1165 RPanel *p0 = __get_panel (panels, 0);
1166 __set_geometry (&p0->view->pos, 0, 1, PANEL_CONFIG_SIDEPANEL_W, h - 1);
1167 __set_curnode (core, 0);
1168 __set_mode (core, PANEL_MODE_DEFAULT);
1169 free (cmd);
1170 return 0;
1171 }
1172
__add_help_panel(RCore * core)1173 static void __add_help_panel(RCore *core) {
1174 //TODO: all these things done below are very hacky and refactoring needed
1175 RPanels *ps = core->panels;
1176 int h;
1177 const char *help = "Help";
1178 (void)r_cons_get_size (&h);
1179 __adjust_side_panels (core);
1180 __insert_panel (core, 0, help, help);
1181 RPanel *p0 = __get_panel (ps, 0);
1182 __set_geometry (&p0->view->pos, 0, 1, PANEL_CONFIG_SIDEPANEL_W, h - 1);
1183 __set_curnode (core, 0);
1184 }
1185
__load_cmdf(RCore * core,RPanel * p,char * input,char * str)1186 static char *__load_cmdf(RCore *core, RPanel *p, char *input, char *str) {
1187 char *ret = NULL;
1188 char *res = __show_status_input (core, input);
1189 if (res) {
1190 p->model->cmd = r_str_newf (str, res);
1191 ret = r_core_cmd_str (core, p->model->cmd);
1192 free (res);
1193 }
1194 return ret;
1195 }
1196
__add_cmdf_panel(RCore * core,char * input,char * str)1197 static int __add_cmdf_panel(RCore *core, char *input, char *str) {
1198 RPanels *panels = core->panels;
1199 if (!__check_panel_num (core)) {
1200 return 0;
1201 }
1202 int h;
1203 (void)r_cons_get_size (&h);
1204 RPanelsMenu *menu = core->panels->panels_menu;
1205 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
1206 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
1207 __adjust_side_panels (core);
1208 __insert_panel (core, 0, child->name, "");
1209 RPanel *p0 = __get_panel (panels, 0);
1210 __set_geometry (&p0->view->pos, 0, 1, PANEL_CONFIG_SIDEPANEL_W, h - 1);
1211 __set_cmd_str_cache (core, p0, __load_cmdf (core, p0, input, str));
1212 __set_curnode (core, 0);
1213 __set_mode (core, PANEL_MODE_DEFAULT);
1214 return 0;
1215 }
1216
__fix_layout_w(RCore * core)1217 static void __fix_layout_w(RCore *core) {
1218 RPanels *panels = core->panels;
1219 RList *list = r_list_new ();
1220 int i = 0;
1221 for (; i < panels->n_panels - 1; i++) {
1222 RPanel *p = __get_panel (panels, i);
1223 int64_t t = p->view->pos.x + p->view->pos.w;
1224 r_list_append (list, (void *)(t));
1225 }
1226 RListIter *iter;
1227 for (i = 0; i < panels->n_panels; i++) {
1228 RPanel *p = __get_panel (panels, i);
1229 int tx = p->view->pos.x;
1230 if (!tx) {
1231 continue;
1232 }
1233 int min = INT8_MAX;
1234 int target_num = INT8_MAX;
1235 bool found = false;
1236 void *num = NULL;
1237 r_list_foreach (list, iter, num) {
1238 if ((int64_t)num - 1 == tx) {
1239 found = true;
1240 break;
1241 }
1242 int sub = (int64_t)num - tx;
1243 if (min > R_ABS (sub)) {
1244 min = R_ABS (sub);
1245 target_num = (int64_t)num;
1246 }
1247 }
1248 if (!found) {
1249 int t = p->view->pos.x - target_num + 1;
1250 p->view->pos.x = target_num - 1;
1251 p->view->pos.w += t;
1252 }
1253 }
1254 }
1255
__fix_layout_h(RCore * core)1256 static void __fix_layout_h(RCore *core) {
1257 RPanels *panels = core->panels;
1258 RList *list = r_list_new ();
1259 int h;
1260 (void)r_cons_get_size (&h);
1261 int i = 0;
1262 for (; i < panels->n_panels - 1; i++) {
1263 RPanel *p = __get_panel (panels, i);
1264 int64_t t = p->view->pos.y + p->view->pos.h;
1265 r_list_append (list, (void *)(t));
1266 }
1267 RListIter *iter;
1268 for (i = 0; i < panels->n_panels; i++) {
1269 RPanel *p = __get_panel (panels, i);
1270 int ty = p->view->pos.y;
1271 int th = p->view->pos.h;
1272 if (ty == 1 || th == (h - 1)) {
1273 continue;
1274 }
1275 int min = INT8_MAX;
1276 int target_num = INT8_MAX;
1277 bool found = false;
1278 void *num = NULL;
1279 r_list_foreach (list, iter, num) {
1280 if ((int64_t)num - 1 == ty) {
1281 found = true;
1282 break;
1283 }
1284 int sub = (int64_t)num - ty;
1285 if (min > R_ABS (sub)) {
1286 min = R_ABS (sub);
1287 target_num = (int64_t)num;
1288 }
1289 }
1290 if (!found) {
1291 int t = p->view->pos.y - target_num + 1;
1292 p->view->pos.y = target_num - 1;
1293 p->view->pos.h += t;
1294 }
1295 }
1296 r_list_free (list);
1297 }
1298
__fix_layout(RCore * core)1299 static void __fix_layout(RCore *core) {
1300 __fix_layout_w (core);
1301 __fix_layout_h (core);
1302 }
1303
show_cursor(RCore * core)1304 static void show_cursor(RCore *core) {
1305 const bool keyCursor = r_config_get_i (core->config, "scr.cursor");
1306 if (keyCursor) {
1307 r_cons_gotoxy (core->cons->cpos.x, core->cons->cpos.y);
1308 r_cons_show_cursor (1);
1309 r_cons_flush ();
1310 }
1311 }
1312
__set_refresh_all(RCore * core,bool clearCache,bool force_refresh)1313 static void __set_refresh_all(RCore *core, bool clearCache, bool force_refresh) {
1314 RPanels *panels = core->panels;
1315 int i;
1316 for (i = 0; i < panels->n_panels; i++) {
1317 RPanel *panel = __get_panel (panels, i);
1318 if (!force_refresh && __check_panel_type (panel, PANEL_CMD_CONSOLE)) {
1319 continue;
1320 }
1321 panel->view->refresh = true;
1322 if (clearCache) {
1323 __set_cmd_str_cache (core, panel, NULL);
1324 }
1325 }
1326 }
1327
__split_panel_vertical(RCore * core,RPanel * p,const char * name,const char * cmd)1328 static void __split_panel_vertical(RCore *core, RPanel *p, const char *name, const char *cmd) {
1329 RPanels *panels = core->panels;
1330 if (!__check_panel_num (core)) {
1331 return;
1332 }
1333 __insert_panel (core, panels->curnode + 1, name, cmd);
1334 RPanel *next = __get_panel (panels, panels->curnode + 1);
1335 int owidth = p->view->pos.w;
1336 p->view->pos.w = owidth / 2 + 1;
1337 __set_geometry (&next->view->pos, p->view->pos.x + p->view->pos.w - 1,
1338 p->view->pos.y, owidth - p->view->pos.w + 1, p->view->pos.h);
1339 __fix_layout (core);
1340 __set_refresh_all (core, false, true);
1341 }
1342
__split_panel_horizontal(RCore * core,RPanel * p,const char * name,const char * cmd)1343 static void __split_panel_horizontal(RCore *core, RPanel *p, const char *name, const char *cmd) {
1344 RPanels *panels = core->panels;
1345 if (!__check_panel_num (core)) {
1346 return;
1347 }
1348 __insert_panel (core, panels->curnode + 1, name, cmd);
1349 RPanel *next = __get_panel (panels, panels->curnode + 1);
1350 int oheight = p->view->pos.h;
1351 p->view->curpos = 0;
1352 p->view->pos.h = oheight / 2 + 1;
1353 __set_geometry (&next->view->pos, p->view->pos.x, p->view->pos.y + p->view->pos.h - 1,
1354 p->view->pos.w, oheight - p->view->pos.h + 1);
1355 __fix_layout (core);
1356 __set_refresh_all (core, false, true);
1357 }
1358
__panels_check_stackbase(RCore * core)1359 static void __panels_check_stackbase(RCore *core) {
1360 if (!core || !core->panels) {
1361 return;
1362 }
1363 int i;
1364 const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
1365 if (!sp) {
1366 return;
1367 }
1368 const ut64 stackbase = r_reg_getv (core->anal->reg, sp);
1369 RPanels *panels = core->panels;
1370 for (i = 1; i < panels->n_panels; i++) {
1371 RPanel *panel = __get_panel (panels, i);
1372 if (panel->model->cmd && __check_panel_type (panel, PANEL_CMD_STACK) && panel->model->baseAddr != stackbase) {
1373 panel->model->baseAddr = stackbase;
1374 __set_panel_addr (core, panel, stackbase - r_config_get_i (core->config, "stack.delta") + core->print->cur);
1375 }
1376 }
1377 }
1378
__del_panel(RCore * core,int pi)1379 static void __del_panel(RCore *core, int pi) {
1380 int i;
1381 RPanels *panels = core->panels;
1382 RPanel *tmp = __get_panel (panels, pi);
1383 if (!tmp) {
1384 return;
1385 }
1386 for (i = pi; i < (panels->n_panels - 1); i++) {
1387 panels->panel[i] = panels->panel[i + 1];
1388 }
1389 panels->panel[panels->n_panels - 1] = tmp;
1390 panels->n_panels--;
1391 __set_curnode (core, panels->curnode);
1392 }
1393
__del_invalid_panels(RCore * core)1394 static void __del_invalid_panels(RCore *core) {
1395 RPanels *panels = core->panels;
1396 int i;
1397 for (i = 1; i < panels->n_panels; i++) {
1398 RPanel *panel = __get_panel (panels, i);
1399 if (panel->view->pos.w < 2) {
1400 __del_panel (core, i);
1401 __del_invalid_panels (core);
1402 break;
1403 }
1404 if (panel->view->pos.h < 2) {
1405 __del_panel (core, i);
1406 __del_invalid_panels (core);
1407 break;
1408 }
1409 }
1410 }
1411
__panels_layout_refresh(RCore * core)1412 static void __panels_layout_refresh(RCore *core) {
1413 __del_invalid_panels (core);
1414 __check_edge (core);
1415 __panels_check_stackbase (core);
1416 __panels_refresh (core);
1417 }
1418
__reset_scroll_pos(RPanel * p)1419 static void __reset_scroll_pos(RPanel *p) {
1420 p->view->sx = 0;
1421 p->view->sy = 0;
1422 }
1423
__activate_cursor(RCore * core)1424 static void __activate_cursor(RCore *core) {
1425 RPanels *panels = core->panels;
1426 RPanel *cur = __get_cur_panel (panels);
1427 bool normal = __is_normal_cursor_type (cur);
1428 bool abnormal = __is_abnormal_cursor_type (core, cur);
1429 if (normal || abnormal) {
1430 if (normal && cur->model->cache) {
1431 if (__show_status_yesno (core, 1, "You need to turn off cache to use cursor. Turn off now?(Y/n)")) {
1432 cur->model->cache = false;
1433 __set_cmd_str_cache (core, cur, NULL);
1434 (void)__show_status (core, "Cache is off and cursor is on");
1435 __set_cursor (core, !core->print->cur_enabled);
1436 cur->view->refresh = true;
1437 __reset_scroll_pos (cur);
1438 } else {
1439 (void)__show_status (core, "You can always toggle cache by \'&\' key");
1440 }
1441 return;
1442 }
1443 __set_cursor (core, !core->print->cur_enabled);
1444 cur->view->refresh = true;
1445 } else {
1446 (void)__show_status (core, "Cursor is not available for the current panel.");
1447 }
1448 }
1449
__parse_string_on_cursor(RCore * core,RPanel * panel,int idx)1450 ut64 __parse_string_on_cursor(RCore *core, RPanel *panel, int idx) {
1451 if (!panel->model->cmdStrCache) {
1452 return UT64_MAX;
1453 }
1454 RStrBuf *buf = r_strbuf_new (NULL);
1455 char *s = panel->model->cmdStrCache;
1456 int l = 0;
1457 while (R_STR_ISNOTEMPTY (s) && l != idx) {
1458 if (*s == '\n') {
1459 l++;
1460 }
1461 s++;
1462 }
1463 while (R_STR_ISNOTEMPTY (s) && R_STR_ISNOTEMPTY (s + 1)) {
1464 if (*s == '0' && *(s + 1) == 'x') {
1465 r_strbuf_append_n (buf, s, 2);
1466 while (*s != ' ') {
1467 r_strbuf_append_n (buf, s, 1);
1468 s++;
1469 }
1470 ut64 ret = r_num_math (core->num, r_strbuf_get (buf));
1471 r_strbuf_free (buf);
1472 return ret;
1473 }
1474 s++;
1475 }
1476 r_strbuf_free (buf);
1477 return UT64_MAX;
1478 }
1479
__fix_cursor_up(RCore * core)1480 static void __fix_cursor_up(RCore *core) {
1481 RPrint *print = core->print;
1482 if (print->cur >= 0) {
1483 return;
1484 }
1485 int sz = r_core_visual_prevopsz (core, core->offset + print->cur);
1486 if (sz < 1) {
1487 sz = 1;
1488 }
1489 r_core_seek_delta (core, -sz);
1490 print->cur += sz;
1491 if (print->ocur != -1) {
1492 print->ocur += sz;
1493 }
1494 }
1495
__cursor_left(RCore * core)1496 static void __cursor_left(RCore *core) {
1497 RPanel *cur = __get_cur_panel (core->panels);
1498 RPrint *print = core->print;
1499 if (__check_panel_type (cur, PANEL_CMD_REGISTERS)
1500 || __check_panel_type (cur, PANEL_CMD_STACK)) {
1501 if (print->cur > 0) {
1502 print->cur--;
1503 cur->model->addr--;
1504 }
1505 } else if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
1506 print->cur--;
1507 __fix_cursor_up (core);
1508 } else {
1509 print->cur--;
1510 }
1511 }
1512
__fix_cursor_down(RCore * core)1513 static void __fix_cursor_down(RCore *core) {
1514 RPrint *print = core->print;
1515 bool cur_is_visible = core->offset + print->cur + 32 < print->screen_bounds;
1516 if (!cur_is_visible) {
1517 int i = 0;
1518 //XXX: ugly hack
1519 for (i = 0; i < 2; i++) {
1520 RAsmOp op;
1521 int sz = r_asm_disassemble (core->rasm,
1522 &op, core->block, 32);
1523 if (sz < 1) {
1524 sz = 1;
1525 }
1526 r_core_seek_delta (core, sz);
1527 print->cur = R_MAX (print->cur - sz, 0);
1528 if (print->ocur != -1) {
1529 print->ocur = R_MAX (print->ocur - sz, 0);
1530 }
1531 }
1532 }
1533 }
1534
__cursor_right(RCore * core)1535 static void __cursor_right(RCore *core) {
1536 RPanel *cur = __get_cur_panel (core->panels);
1537 RPrint *print = core->print;
1538 if (__check_panel_type (cur, PANEL_CMD_STACK) && print->cur >= 15) {
1539 return;
1540 }
1541 if (__check_panel_type (cur, PANEL_CMD_REGISTERS)
1542 || __check_panel_type (cur, PANEL_CMD_STACK)) {
1543 print->cur++;
1544 cur->model->addr++;
1545 } else if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
1546 print->cur++;
1547 __fix_cursor_down (core);
1548 } else {
1549 print->cur++;
1550 }
1551 }
1552
__cursor_up(RCore * core)1553 static void __cursor_up(RCore *core) {
1554 RPrint *print = core->print;
1555 ut64 addr, oaddr = core->offset + print->cur;
1556 if (r_core_prevop_addr (core, oaddr, 1, &addr)) {
1557 const int delta = oaddr - addr;
1558 print->cur -= delta;
1559 } else {
1560 print->cur -= 4;
1561 }
1562 __fix_cursor_up (core);
1563 }
1564
__cursor_down(RCore * core)1565 static void __cursor_down(RCore *core) {
1566 RPrint *print = core->print;
1567 RAnalOp *aop = r_core_anal_op (core, core->offset + print->cur, R_ANAL_OP_MASK_BASIC);
1568 if (aop) {
1569 print->cur += aop->size;
1570 r_anal_op_free (aop);
1571 } else {
1572 print->cur += 4;
1573 }
1574 __fix_cursor_down (core);
1575 }
1576
__save_panel_pos(RPanel * panel)1577 static void __save_panel_pos(RPanel* panel) {
1578 if (!panel) {
1579 return;
1580 }
1581 __set_geometry (&panel->view->prevPos, panel->view->pos.x, panel->view->pos.y,
1582 panel->view->pos.w, panel->view->pos.h);
1583 }
1584
__restore_panel_pos(RPanel * panel)1585 static void __restore_panel_pos(RPanel* panel) {
1586 if(!panel){
1587 return;
1588 }
1589 __set_geometry (&panel->view->pos, panel->view->prevPos.x, panel->view->prevPos.y,
1590 panel->view->prevPos.w, panel->view->prevPos.h);
1591 }
1592
__maximize_panel_size(RPanels * panels)1593 static void __maximize_panel_size(RPanels *panels) {
1594 RPanel *cur = __get_cur_panel (panels);
1595 if(!cur){
1596 return;
1597 }
1598 __set_geometry (&cur->view->pos, 0, 1, panels->can->w, panels->can->h - 1);
1599 cur->view->refresh = true;
1600 }
1601
__dismantle_panel(RPanels * ps,RPanel * p)1602 static void __dismantle_panel(RPanels *ps, RPanel *p) {
1603 if (!p) {
1604 return;
1605 }
1606 RPanel *justLeftPanel = NULL, *justRightPanel = NULL, *justUpPanel = NULL, *justDownPanel = NULL;
1607 RPanel *tmpPanel = NULL;
1608 bool leftUpValid = false, leftDownValid = false, rightUpValid = false, rightDownValid = false,
1609 upLeftValid = false, upRightValid = false, downLeftValid = false, downRightValid = false;
1610 int left[PANEL_NUM_LIMIT], right[PANEL_NUM_LIMIT], up[PANEL_NUM_LIMIT], down[PANEL_NUM_LIMIT];
1611 memset (left, -1, sizeof (left));
1612 memset (right, -1, sizeof (right));
1613 memset (up, -1, sizeof (up));
1614 memset (down, -1, sizeof (down));
1615 int i, ox, oy, ow, oh;
1616 ox = p->view->pos.x;
1617 oy = p->view->pos.y;
1618 ow = p->view->pos.w;
1619 oh = p->view->pos.h;
1620 for (i = 0; i < ps->n_panels; i++) {
1621 tmpPanel = __get_panel (ps, i);
1622 if (tmpPanel->view->pos.x + tmpPanel->view->pos.w - 1 == ox) {
1623 left[i] = 1;
1624 if (oy == tmpPanel->view->pos.y) {
1625 leftUpValid = true;
1626 if (oh == tmpPanel->view->pos.h) {
1627 justLeftPanel = tmpPanel;
1628 break;
1629 }
1630 }
1631 if (oy + oh == tmpPanel->view->pos.y + tmpPanel->view->pos.h) {
1632 leftDownValid = true;
1633 }
1634 }
1635 if (tmpPanel->view->pos.x == ox + ow - 1) {
1636 right[i] = 1;
1637 if (oy == tmpPanel->view->pos.y) {
1638 rightUpValid = true;
1639 if (oh == tmpPanel->view->pos.h) {
1640 rightDownValid = true;
1641 justRightPanel = tmpPanel;
1642 }
1643 }
1644 if (oy + oh == tmpPanel->view->pos.y + tmpPanel->view->pos.h) {
1645 rightDownValid = true;
1646 }
1647 }
1648 if (tmpPanel->view->pos.y + tmpPanel->view->pos.h - 1 == oy) {
1649 up[i] = 1;
1650 if (ox == tmpPanel->view->pos.x) {
1651 upLeftValid = true;
1652 if (ow == tmpPanel->view->pos.w) {
1653 upRightValid = true;
1654 justUpPanel = tmpPanel;
1655 }
1656 }
1657 if (ox + ow == tmpPanel->view->pos.x + tmpPanel->view->pos.w) {
1658 upRightValid = true;
1659 }
1660 }
1661 if (tmpPanel->view->pos.y == oy + oh - 1) {
1662 down[i] = 1;
1663 if (ox == tmpPanel->view->pos.x) {
1664 downLeftValid = true;
1665 if (ow == tmpPanel->view->pos.w) {
1666 downRightValid = true;
1667 justDownPanel = tmpPanel;
1668 }
1669 }
1670 if (ox + ow == tmpPanel->view->pos.x + tmpPanel->view->pos.w) {
1671 downRightValid = true;
1672 }
1673 }
1674 }
1675 if (justLeftPanel) {
1676 justLeftPanel->view->pos.w += ox + ow - (justLeftPanel->view->pos.x + justLeftPanel->view->pos.w);
1677 } else if (justRightPanel) {
1678 justRightPanel->view->pos.w = justRightPanel->view->pos.x + justRightPanel->view->pos.w - ox;
1679 justRightPanel->view->pos.x = ox;
1680 } else if (justUpPanel) {
1681 justUpPanel->view->pos.h += oy + oh - (justUpPanel->view->pos.y + justUpPanel->view->pos.h);
1682 } else if (justDownPanel) {
1683 justDownPanel->view->pos.h = oh + justDownPanel->view->pos.y + justDownPanel->view->pos.h - (oy + oh);
1684 justDownPanel->view->pos.y = oy;
1685 } else if (leftUpValid && leftDownValid) {
1686 for (i = 0; i < ps->n_panels; i++) {
1687 if (left[i] != -1) {
1688 tmpPanel = __get_panel (ps, i);
1689 tmpPanel->view->pos.w += ox + ow - (tmpPanel->view->pos.x + tmpPanel->view->pos.w);
1690 }
1691 }
1692 } else if (rightUpValid && rightDownValid) {
1693 for (i = 0; i < ps->n_panels; i++) {
1694 if (right[i] != -1) {
1695 tmpPanel = __get_panel (ps, i);
1696 tmpPanel->view->pos.w = tmpPanel->view->pos.x + tmpPanel->view->pos.w - ox;
1697 tmpPanel->view->pos.x = ox;
1698 }
1699 }
1700 } else if (upLeftValid && upRightValid) {
1701 for (i = 0; i < ps->n_panels; i++) {
1702 if (up[i] != -1) {
1703 tmpPanel = __get_panel (ps, i);
1704 tmpPanel->view->pos.h += oy + oh - (tmpPanel->view->pos.y + tmpPanel->view->pos.h);
1705 }
1706 }
1707 } else if (downLeftValid && downRightValid) {
1708 for (i = 0; i < ps->n_panels; i++) {
1709 if (down[i] != -1) {
1710 tmpPanel = __get_panel (ps, i);
1711 tmpPanel->view->pos.h = oh + tmpPanel->view->pos.y + tmpPanel->view->pos.h - (oy + oh);
1712 tmpPanel->view->pos.y = oy;
1713 }
1714 }
1715 }
1716 }
1717
__dismantle_del_panel(RCore * core,RPanel * p,int pi)1718 static void __dismantle_del_panel(RCore *core, RPanel *p, int pi) {
1719 RPanels *panels = core->panels;
1720 if (panels->n_panels <= 1) {
1721 return;
1722 }
1723 __dismantle_panel (panels, p);
1724 __del_panel (core, pi);
1725 }
1726
__toggle_help(RCore * core)1727 static void __toggle_help(RCore *core) {
1728 RPanels *ps = core->panels;
1729 int i;
1730 for (i = 0; i < ps->n_panels; i++) {
1731 RPanel *p = __get_panel (ps, i);
1732 if (r_str_endswith (p->model->cmd, "Help")) {
1733 __dismantle_del_panel (core, p, i);
1734 if (ps->mode == PANEL_MODE_MENU) {
1735 __set_mode (core, PANEL_MODE_DEFAULT);
1736 }
1737 return;
1738 }
1739 }
1740 __add_help_panel (core);
1741 if (ps->mode == PANEL_MODE_MENU) {
1742 __set_mode (core, PANEL_MODE_DEFAULT);
1743 }
1744 __update_help (core, ps);
1745 }
1746
__reset_snow(RPanels * panels)1747 static void __reset_snow(RPanels *panels) {
1748 RPanel *cur = __get_cur_panel (panels);
1749 r_list_free (panels->snows);
1750 panels->snows = NULL;
1751 cur->view->refresh = true;
1752 }
1753
__toggle_zoom_mode(RCore * core)1754 static void __toggle_zoom_mode(RCore *core) {
1755 RPanels *panels = core->panels;
1756 RPanel *cur = __get_cur_panel (panels);
1757 if (panels->mode != PANEL_MODE_ZOOM) {
1758 panels->prevMode = panels->mode;
1759 __set_mode (core, PANEL_MODE_ZOOM);
1760 __save_panel_pos (cur);
1761 __maximize_panel_size (panels);
1762 } else {
1763 __set_mode (core, panels->prevMode);
1764 panels->prevMode = PANEL_MODE_DEFAULT;
1765 __restore_panel_pos (cur);
1766 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
1767 __reset_snow (panels);
1768 }
1769 }
1770 }
1771
__set_root_state(RCore * core,RPanelsRootState state)1772 static void __set_root_state(RCore *core, RPanelsRootState state) {
1773 core->panels_root->root_state = state;
1774 }
1775
__handle_tab_next(RCore * core)1776 static void __handle_tab_next(RCore *core) {
1777 if (core->panels_root->n_panels > 1) {
1778 core->panels_root->cur_panels++;
1779 core->panels_root->cur_panels %= core->panels_root->n_panels;
1780 __set_root_state (core, ROTATE);
1781 }
1782 }
1783
__handle_print_rotate(RCore * core)1784 static void __handle_print_rotate(RCore *core) {
1785 if (r_config_get_i (core->config, "asm.pseudo")) {
1786 r_config_toggle (core->config, "asm.pseudo");
1787 r_config_toggle (core->config, "asm.esil");
1788 } else if (r_config_get_i (core->config, "asm.esil")) {
1789 r_config_toggle (core->config, "asm.esil");
1790 } else {
1791 r_config_toggle (core->config, "asm.pseudo");
1792 }
1793 }
1794
__handle_tab_prev(RCore * core)1795 static void __handle_tab_prev(RCore *core) {
1796 if (core->panels_root->n_panels > 1) {
1797 core->panels_root->cur_panels--;
1798 if (core->panels_root->cur_panels < 0) {
1799 core->panels_root->cur_panels = core->panels_root->n_panels - 1;
1800 }
1801 __set_root_state (core, ROTATE);
1802 }
1803 }
1804
__handle_tab_name(RCore * core)1805 static void __handle_tab_name(RCore *core) {
1806 core->panels->name = __show_status_input (core, "tab name: ");
1807 }
1808
__handle_tab_new(RCore * core)1809 static void __handle_tab_new(RCore *core) {
1810 if (core->panels_root->n_panels >= PANEL_NUM_LIMIT) {
1811 return;
1812 }
1813 __init_new_panels_root (core);
1814 }
1815
__init_sdb(RCore * core)1816 static void __init_sdb(RCore *core) {
1817 Sdb *db = core->panels->db;
1818 sdb_set (db, "Symbols", "isq", 0);
1819 sdb_set (db, "Stack" , "px 256@r:SP", 0);
1820 sdb_set (db, "Locals", "afvd", 0);
1821 sdb_set (db, "Registers", "dr", 0);
1822 sdb_set (db, "RegisterRefs", "drr", 0);
1823 sdb_set (db, "Disassembly", "pd", 0);
1824 sdb_set (db, "Disassemble Summary", "pdsf", 0);
1825 sdb_set (db, "Decompiler", "pdc", 0);
1826 sdb_set (db, "Decompiler With Offsets", "pdco", 0);
1827 sdb_set (db, "Graph", "agf", 0);
1828 sdb_set (db, "Tiny Graph", "agft", 0);
1829 sdb_set (db, "Info", "i", 0);
1830 sdb_set (db, "Database", "k ***", 0);
1831 sdb_set (db, "Console", "$console", 0);
1832 sdb_set (db, "Hexdump", "xc $r*16", 0);
1833 sdb_set (db, "Xrefs", "ax", 0);
1834 sdb_set (db, "Xrefs Here", "ax.", 0);
1835 sdb_set (db, "Functions", "afl", 0);
1836 sdb_set (db, "Function Calls", "aflm", 0);
1837 sdb_set (db, "Comments", "CC", 0);
1838 sdb_set (db, "Entropy", "p=e 100", 0);
1839 sdb_set (db, "Entropy Fire", "p==e 100", 0);
1840 sdb_set (db, "DRX", "drx", 0);
1841 sdb_set (db, "Sections", "iSq", 0);
1842 sdb_set (db, "Segments", "iSSq", 0);
1843 sdb_set (db, PANEL_TITLE_STRINGS_DATA, "izq", 0);
1844 sdb_set (db, PANEL_TITLE_STRINGS_BIN, "izzq", 0);
1845 sdb_set (db, "Maps", "dm", 0);
1846 sdb_set (db, "Modules", "dmm", 0);
1847 sdb_set (db, "Backtrace", "dbt", 0);
1848 sdb_set (db, "Breakpoints", "db", 0);
1849 sdb_set (db, "Imports", "iiq", 0);
1850 sdb_set (db, "Clipboard", "yx", 0);
1851 sdb_set (db, "New", "o", 0);
1852 sdb_set (db, "Var READ address", "afvR", 0);
1853 sdb_set (db, "Var WRITE address", "afvW", 0);
1854 sdb_set (db, "Summary", "pdsf", 0);
1855 sdb_set (db, "Classes", "icq", 0);
1856 sdb_set (db, "Methods", "ic", 0);
1857 sdb_set (db, "Relocs", "ir", 0);
1858 sdb_set (db, "Headers", "iH", 0);
1859 sdb_set (db, "File Hashes", "it", 0);
1860 }
1861
__free_panel_model(RPanel * panel)1862 static void __free_panel_model(RPanel *panel) {
1863 if (!panel) {
1864 return;
1865 }
1866 free (panel->model->title);
1867 free (panel->model->cmd);
1868 free (panel->model->cmdStrCache);
1869 free (panel->model->readOnly);
1870 free (panel->model);
1871 }
1872
__replace_cmd(RCore * core,const char * title,const char * cmd)1873 static void __replace_cmd(RCore *core, const char *title, const char *cmd) {
1874 RPanels *panels = core->panels;
1875 RPanel *cur = __get_cur_panel (panels);
1876 __free_panel_model (cur);
1877 cur->model = R_NEW0 (RPanelModel);
1878 cur->model->title = r_str_dup (cur->model->title, title);
1879 cur->model->cmd = r_str_dup (cur->model->cmd, cmd);
1880 __set_cmd_str_cache (core, cur, NULL);
1881 __set_panel_addr (core, cur, core->offset);
1882 cur->model->type = PANEL_TYPE_DEFAULT;
1883 __set_dcb (core, cur);
1884 __set_pcb (cur);
1885 __set_rcb (panels, cur);
1886 __cache_white_list (core, cur);
1887 __set_refresh_all (core, false, true);
1888 }
1889
__create_panel(RCore * core,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title,const char * cmd)1890 static void __create_panel(RCore *core, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char* title, const char *cmd) {
1891 if (!__check_panel_num (core)) {
1892 return;
1893 }
1894 if (!panel) {
1895 return;
1896 }
1897 switch (dir) {
1898 case PANEL_LAYOUT_VERTICAL:
1899 __split_panel_vertical (core, panel, title, cmd);
1900 break;
1901 case PANEL_LAYOUT_HORIZONTAL:
1902 __split_panel_horizontal (core, panel, title, cmd);
1903 break;
1904 case PANEL_LAYOUT_NONE:
1905 __replace_cmd (core, title, cmd);
1906 break;
1907 }
1908 }
1909
__create_panel_db(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)1910 static void __create_panel_db(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
1911 RCore *core = (RCore *)user;
1912 char *cmd = sdb_get (core->panels->db, title, 0);
1913 if (!cmd) {
1914 return;
1915 }
1916 __create_panel (core, panel, dir, title, cmd);
1917 }
1918
__create_panel_input(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)1919 static void __create_panel_input(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
1920 RCore *core = (RCore *)user;
1921 char *cmd = __show_status_input (core, "Command: ");
1922 if (cmd) {
1923 __create_panel (core, panel, dir, cmd, cmd);
1924 }
1925 }
1926
__replace_current_panel_input(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)1927 static void __replace_current_panel_input(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
1928 RCore *core = (RCore *)user;
1929 char *cmd = __show_status_input (core, "New command: ");
1930 if (R_STR_ISNOTEMPTY (cmd)) {
1931 __replace_cmd (core, cmd, cmd);
1932 }
1933 free (cmd);
1934 }
1935
__search_strings(RCore * core,bool whole)1936 static char *__search_strings(RCore *core, bool whole) {
1937 const char *title = whole ? PANEL_TITLE_STRINGS_BIN : PANEL_TITLE_STRINGS_DATA;
1938 const char *str = __show_status_input (core, "Search Strings: ");
1939 char *db_val = __search_db (core, title);
1940 char *ret = r_str_newf ("%s~%s", db_val, str);
1941 free (db_val);
1942 return ret;
1943 }
1944
__search_strings_data_create(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)1945 static void __search_strings_data_create(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
1946 RCore *core = (RCore *)user;
1947 __create_panel (core, panel, dir, title, __search_strings (core, false));
1948 }
1949
__search_strings_bin_create(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)1950 static void __search_strings_bin_create(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
1951 RCore *core = (RCore *)user;
1952 __create_panel (core, panel, dir, title, __search_strings (core, true));
1953 }
1954
__get_panels(RPanelsRoot * panels_root,int i)1955 static RPanels *__get_panels(RPanelsRoot *panels_root, int i) {
1956 if (!panels_root || (i >= PANEL_NUM_LIMIT)) {
1957 return NULL;
1958 }
1959 return panels_root->panels[i];
1960 }
1961
__update_disassembly_or_open(RCore * core)1962 static void __update_disassembly_or_open (RCore *core) {
1963 RPanels *panels = core->panels;
1964 int i;
1965 bool create_new = true;
1966 for (i = 0; i < panels->n_panels; i++) {
1967 RPanel *p = __get_panel (panels, i);
1968 if (__check_panel_type (p, PANEL_CMD_DISASSEMBLY)) {
1969 __set_panel_addr (core, p, core->offset);
1970 create_new = false;
1971 }
1972 }
1973 if (create_new) {
1974 RPanel *panel = __get_panel (panels, 0);
1975 int x0 = panel->view->pos.x;
1976 int y0 = panel->view->pos.y;
1977 int w0 = panel->view->pos.w;
1978 int h0 = panel->view->pos.h;
1979 int threshold_w = x0 + panel->view->pos.w;
1980 int x1 = x0 + w0 / 2 - 1;
1981 int w1 = threshold_w - x1;
1982
1983 __insert_panel (core, 0, PANEL_TITLE_DISASSEMBLY, PANEL_CMD_DISASSEMBLY);
1984 RPanel *p0 = __get_panel (panels, 0);
1985 __set_geometry (&p0->view->pos, x0, y0, w0 / 2, h0);
1986
1987 RPanel *p1 = __get_panel (panels, 1);
1988 __set_geometry (&p1->view->pos, x1, y0, w1, h0);
1989
1990 __set_cursor (core, false);
1991 __set_curnode (core, 0);
1992 }
1993 }
1994
__continue_cb(void * user)1995 static int __continue_cb(void *user) {
1996 RCore *core = (RCore *)user;
1997 r_core_cmd (core, "dc", 0);
1998 r_cons_flush ();
1999 return 0;
2000 }
2001
__continue_modal_cb(void * user,R_UNUSED RPanel * panel,R_UNUSED const RPanelLayout dir,R_UNUSED R_NULLABLE const char * title)2002 static void __continue_modal_cb(void *user, R_UNUSED RPanel *panel, R_UNUSED const RPanelLayout dir, R_UNUSED R_NULLABLE const char *title) {
2003 __continue_cb (user);
2004 __update_disassembly_or_open ((RCore *)user);
2005 }
2006
__panel_single_step_in(RCore * core)2007 static void __panel_single_step_in(RCore *core) {
2008 if (r_config_get_i (core->config, "cfg.debug")) {
2009 r_core_cmd (core, "ds", 0);
2010 r_core_cmd (core, ".dr*", 0);
2011 } else {
2012 r_core_cmd (core, "aes", 0);
2013 r_core_cmd (core, ".ar*", 0);
2014 }
2015 }
2016
__step_cb(void * user)2017 static int __step_cb(void *user) {
2018 RCore *core = (RCore *)user;
2019 __panel_single_step_in (core);
2020 __update_disassembly_or_open (core);
2021 return 0;
2022 }
2023
__panel_single_step_over(RCore * core)2024 static void __panel_single_step_over(RCore *core) {
2025 bool io_cache = r_config_get_i (core->config, "io.cache");
2026 r_config_set_b (core->config, "io.cache", false);
2027 if (r_config_get_i (core->config, "cfg.debug")) {
2028 r_core_cmd (core, "dso", 0);
2029 r_core_cmd (core, ".dr*", 0);
2030 } else {
2031 r_core_cmd (core, "aeso", 0);
2032 r_core_cmd (core, ".ar*", 0);
2033 }
2034 r_config_set_b (core->config, "io.cache", io_cache);
2035 }
2036
__step_over_cb(void * user)2037 static int __step_over_cb(void *user) {
2038 RCore *core = (RCore *)user;
2039 __panel_single_step_over (core);
2040 __update_disassembly_or_open (core);
2041 return 0;
2042 }
2043
__step_modal_cb(void * user,R_UNUSED RPanel * panel,R_UNUSED const RPanelLayout dir,R_UNUSED R_NULLABLE const char * title)2044 static void __step_modal_cb(void *user, R_UNUSED RPanel *panel, R_UNUSED const RPanelLayout dir, R_UNUSED R_NULLABLE const char *title) {
2045 __step_cb (user);
2046 }
2047
__panel_prompt(const char * prompt,char * buf,int len)2048 static void __panel_prompt(const char *prompt, char *buf, int len) {
2049 r_line_set_prompt (prompt);
2050 *buf = 0;
2051 r_cons_fgets (buf, len, 0, NULL);
2052 }
2053
__break_points_cb(void * user)2054 static int __break_points_cb(void *user) {
2055 RCore *core = (RCore *)user;
2056 char buf[128];
2057 const char *prompt = "addr: ";
2058
2059 core->cons->line->prompt_type = R_LINE_PROMPT_OFFSET;
2060 r_line_set_hist_callback (core->cons->line,
2061 &r_line_hist_offset_up,
2062 &r_line_hist_offset_down);
2063 __panel_prompt (prompt, buf, sizeof (buf));
2064 r_line_set_hist_callback (core->cons->line, &r_line_hist_cmd_up, &r_line_hist_cmd_down);
2065 core->cons->line->prompt_type = R_LINE_PROMPT_DEFAULT;
2066
2067 ut64 addr = r_num_math (core->num, buf);
2068 r_core_cmdf (core, "dbs 0x%08"PFMT64x, addr);
2069 return 0;
2070 }
2071
__put_breakpoints_cb(void * user,R_UNUSED RPanel * panel,R_UNUSED const RPanelLayout dir,R_UNUSED R_NULLABLE const char * title)2072 static void __put_breakpoints_cb(void *user, R_UNUSED RPanel *panel, R_UNUSED const RPanelLayout dir, R_UNUSED R_NULLABLE const char *title) {
2073 __break_points_cb (user);
2074 }
2075
__step_over_modal_cb(void * user,R_UNUSED RPanel * panel,R_UNUSED const RPanelLayout dir,R_UNUSED R_NULLABLE const char * title)2076 static void __step_over_modal_cb(void *user, R_UNUSED RPanel *panel, R_UNUSED const RPanelLayout dir, R_UNUSED R_NULLABLE const char *title) {
2077 __step_over_cb (user);
2078 }
2079
__show_all_decompiler_cb(void * user)2080 static int __show_all_decompiler_cb(void *user) {
2081 RCore *core = (RCore *)user;
2082 RAnalFunction *func = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
2083 if (!func) {
2084 return 0;
2085 }
2086 RPanelsRoot *root = core->panels_root;
2087 const char *pdc_now = r_config_get (core->config, "cmd.pdc");
2088 char *opts = r_core_cmd_str (core, "e cmd.pdc=?");
2089 RList *optl = r_str_split_list (opts, "\n", 0);
2090 RListIter *iter;
2091 char *opt;
2092 int i = 0;
2093 __handle_tab_new (core);
2094 RPanels *panels = __get_panels (root, root->n_panels - 1);
2095 r_list_foreach (optl, iter, opt) {
2096 if (R_STR_ISEMPTY (opt)) {
2097 continue;
2098 }
2099 r_config_set (core->config, "cmd.pdc", opt);
2100 RPanel *panel = __get_panel (panels, i++);
2101 panels->n_panels = i;
2102 panel->model->title = r_str_new (opt);
2103 __set_read_only (core, panel, r_core_cmd_str (core, opt));
2104 }
2105 __layout_equal_hor (panels);
2106 r_list_free (optl);
2107 free (opts);
2108 r_config_set (core->config, "cmd.pdc", pdc_now);
2109 root->cur_panels = root->n_panels - 1;
2110 __set_root_state (core, ROTATE);
2111 return 0;
2112 }
2113
__delegate_show_all_decompiler_cb(void * user,RPanel * panel,const RPanelLayout dir,R_NULLABLE const char * title)2114 static void __delegate_show_all_decompiler_cb(void *user, RPanel *panel, const RPanelLayout dir, R_NULLABLE const char *title) {
2115 (void)__show_all_decompiler_cb ((RCore *)user);
2116 }
2117
__init_modal_db(RCore * core)2118 static void __init_modal_db(RCore *core) {
2119 Sdb *db = core->panels->modal_db;
2120 SdbKv *kv;
2121 SdbListIter *sdb_iter;
2122 SdbList *sdb_list = sdb_foreach_list (core->panels->db, true);
2123 ls_foreach (sdb_list, sdb_iter, kv) {
2124 const char *key = sdbkv_key (kv);
2125 sdb_ptr_set (db, r_str_new (key), &__create_panel_db, 0);
2126 }
2127 sdb_ptr_set (db, "Search strings in data sections", &__search_strings_data_create, 0);
2128 sdb_ptr_set (db, "Search strings in the whole bin", &__search_strings_bin_create, 0);
2129 sdb_ptr_set (db, "Create New", &__create_panel_input, 0);
2130 sdb_ptr_set (db, "Change Command of Current Panel", &__replace_current_panel_input, 0);
2131 sdb_ptr_set (db, PANEL_TITLE_ALL_DECOMPILER, &__delegate_show_all_decompiler_cb, 0);
2132 if (r_config_get_i (core->config, "cfg.debug")) {
2133 sdb_ptr_set (db, "Put Breakpoints", &__put_breakpoints_cb, 0);
2134 sdb_ptr_set (db, "Continue", &__continue_modal_cb, 0);
2135 sdb_ptr_set (db, "Step", &__step_modal_cb, 0);
2136 sdb_ptr_set (db, "Step Over", &__step_over_modal_cb, 0);
2137 }
2138 }
2139
__renew_filter(RPanel * panel,int n)2140 static void __renew_filter(RPanel *panel, int n) {
2141 panel->model->n_filter = 0;
2142 char **filter = calloc (sizeof (char *), n);
2143 if (!filter) {
2144 panel->model->filter = NULL;
2145 return;
2146 }
2147 panel->model->filter = filter;
2148 }
2149
__reset_filter(RCore * core,RPanel * panel)2150 static void __reset_filter(RCore *core, RPanel *panel) {
2151 free (panel->model->filter);
2152 panel->model->filter = NULL;
2153 __renew_filter (panel, PANEL_NUM_LIMIT);
2154 __set_cmd_str_cache (core, panel, NULL);
2155 panel->view->refresh = true;
2156 __reset_scroll_pos (panel);
2157 }
2158
__rotate_panel_cmds(RCore * core,const char ** cmds,const int cmdslen,const char * prefix,bool rev)2159 static void __rotate_panel_cmds(RCore *core, const char **cmds, const int cmdslen, const char *prefix, bool rev) {
2160 if (!cmdslen) {
2161 return;
2162 }
2163 RPanel *p = __get_cur_panel (core->panels);
2164 __reset_filter (core, p);
2165 if (rev) {
2166 if (!p->model->rotate) {
2167 p->model->rotate = cmdslen - 1;
2168 } else {
2169 p->model->rotate--;
2170 }
2171 } else {
2172 p->model->rotate++;
2173 }
2174 char tmp[64], *between;
2175 int i = p->model->rotate % cmdslen;
2176 snprintf (tmp, sizeof (tmp), "%s%s", prefix, cmds[i]);
2177 between = r_str_between (p->model->cmd, prefix, " ");
2178 if (between) {
2179 char replace[64];
2180 snprintf (replace, sizeof (replace), "%s%s", prefix, between);
2181 p->model->cmd = r_str_replace (p->model->cmd, replace, tmp, 1);
2182 } else {
2183 p->model->cmd = r_str_dup (p->model->cmd, tmp);
2184 }
2185 __set_cmd_str_cache (core, p, NULL);
2186 p->view->refresh = true;
2187 }
2188
__rotate_entropy_v_cb(void * user,bool rev)2189 static void __rotate_entropy_v_cb(void *user, bool rev) {
2190 RCore *core = (RCore *)user;
2191 __rotate_panel_cmds (core, entropy_rotate, COUNT (entropy_rotate), "p=", rev);
2192 }
2193
__rotate_entropy_h_cb(void * user,bool rev)2194 static void __rotate_entropy_h_cb(void *user, bool rev) {
2195 RCore *core = (RCore *)user;
2196 __rotate_panel_cmds (core, entropy_rotate, COUNT (entropy_rotate), "p==", rev);
2197 }
2198
__rotate_asmemu(RCore * core,RPanel * p)2199 static void __rotate_asmemu(RCore *core, RPanel *p) {
2200 const bool isEmuStr = r_config_get_i (core->config, "emu.str");
2201 const bool isEmu = r_config_get_i (core->config, "asm.emu");
2202 if (isEmu) {
2203 if (isEmuStr) {
2204 r_config_set (core->config, "emu.str", "false");
2205 } else {
2206 r_config_set (core->config, "asm.emu", "false");
2207 }
2208 } else {
2209 r_config_set (core->config, "emu.str", "true");
2210 }
2211 p->view->refresh = true;
2212 }
2213
__rotate_hexdump_cb(void * user,bool rev)2214 static void __rotate_hexdump_cb(void *user, bool rev) {
2215 RCore *core = (RCore *)user;
2216 RPanel *p = __get_cur_panel (core->panels);
2217
2218 if (rev) {
2219 p->model->rotate--;
2220 } else {
2221 p->model->rotate++;
2222 }
2223 r_core_visual_applyHexMode (core, p->model->rotate);
2224 __rotate_asmemu (core, p);
2225 }
2226
__rotate_register_cb(void * user,bool rev)2227 static void __rotate_register_cb(void *user, bool rev) {
2228 RCore *core = (RCore *)user;
2229 __rotate_panel_cmds (core, register_rotate, COUNT (register_rotate), "dr", rev);
2230 }
2231
__rotate_function_cb(void * user,bool rev)2232 static void __rotate_function_cb(void *user, bool rev) {
2233 RCore *core = (RCore *)user;
2234 __rotate_panel_cmds (core, function_rotate, COUNT (function_rotate), "af", rev);
2235 }
2236
__rotate_disasm_cb(void * user,bool rev)2237 static void __rotate_disasm_cb(void *user, bool rev) {
2238 RCore *core = (RCore *)user;
2239 RPanel *p = __get_cur_panel (core->panels);
2240
2241 //TODO: need to come up with a better solution but okay for now
2242 if (!strcmp (p->model->cmd, PANEL_CMD_DECOMPILER) ||
2243 !strcmp (p->model->cmd, PANEL_CMD_DECOMPILER_O)) {
2244 return;
2245 }
2246
2247 if (rev) {
2248 if (!p->model->rotate) {
2249 p->model->rotate = 4;
2250 } else {
2251 p->model->rotate--;
2252 }
2253 } else {
2254 p->model->rotate++;
2255 }
2256 r_core_visual_applyDisMode (core, p->model->rotate);
2257 __rotate_asmemu (core, p);
2258 }
2259
__init_rotate_db(RCore * core)2260 static void __init_rotate_db(RCore *core) {
2261 Sdb *db = core->panels->rotate_db;
2262 sdb_ptr_set (db, "pd", &__rotate_disasm_cb, 0);
2263 sdb_ptr_set (db, "p==", &__rotate_entropy_h_cb, 0);
2264 sdb_ptr_set (db, "p=", &__rotate_entropy_v_cb, 0);
2265 sdb_ptr_set (db, "px", &__rotate_hexdump_cb, 0);
2266 sdb_ptr_set (db, "dr", &__rotate_register_cb, 0);
2267 sdb_ptr_set (db, "af", &__rotate_function_cb, 0);
2268 sdb_ptr_set (db, PANEL_CMD_HEXDUMP, &__rotate_hexdump_cb, 0);
2269 }
2270
__init_all_dbs(RCore * core)2271 static void __init_all_dbs(RCore *core) {
2272 __init_sdb (core);
2273 __init_modal_db (core);
2274 __init_rotate_db (core);
2275 }
2276
__create_new_canvas(RCore * core,int w,int h)2277 static RConsCanvas *__create_new_canvas(RCore *core, int w, int h) {
2278 RConsCanvas *can = r_cons_canvas_new (w, h);
2279 if (!can) {
2280 eprintf ("Cannot create RCons.canvas context\n");
2281 return false;
2282 }
2283 r_cons_canvas_fill (can, 0, 0, w, h, ' ');
2284 can->linemode = r_config_get_i (core->config, "graph.linemode");
2285 can->color = r_config_get_i (core->config, "scr.color");
2286 return can;
2287 }
2288
__free_menu_item(RPanelsMenuItem * item)2289 static void __free_menu_item(RPanelsMenuItem *item) {
2290 if (!item) {
2291 return;
2292 }
2293 size_t i;
2294 free (item->name);
2295 free (item->p->model);
2296 free (item->p->view);
2297 free (item->p);
2298 for (i = 0; i < item->n_sub; i++) {
2299 __free_menu_item (item->sub[i]);
2300 }
2301 free (item->sub);
2302 free (item);
2303 }
2304
__mht_free_kv(HtPPKv * kv)2305 static void __mht_free_kv(HtPPKv *kv) {
2306 free (kv->key);
2307 __free_menu_item ((RPanelsMenuItem *)kv->value);
2308 }
2309
__init(RCore * core,RPanels * panels,int w,int h)2310 static bool __init(RCore *core, RPanels *panels, int w, int h) {
2311 panels->panel = NULL;
2312 panels->n_panels = 0;
2313 panels->columnWidth = 80;
2314 if (r_config_get_i (core->config, "cfg.debug")) {
2315 panels->layout = PANEL_LAYOUT_DEFAULT_DYNAMIC;
2316 } else {
2317 panels->layout = PANEL_LAYOUT_DEFAULT_STATIC;
2318 }
2319 panels->autoUpdate = false;
2320 panels->mouse_on_edge_x = false;
2321 panels->mouse_on_edge_y = false;
2322 panels->mouse_orig_x = 0;
2323 panels->mouse_orig_y = 0;
2324 panels->can = __create_new_canvas (core, w, h);
2325 panels->db = sdb_new0 ();
2326 panels->rotate_db = sdb_new0 ();
2327 panels->modal_db = sdb_new0 ();
2328 panels->mht = ht_pp_new (NULL, (HtPPKvFreeFunc)__mht_free_kv, (HtPPCalcSizeV)strlen);
2329 panels->fun = PANEL_FUN_NOFUN;
2330 panels->prevMode = PANEL_MODE_DEFAULT;
2331 panels->name = NULL;
2332
2333 if (w < 140) {
2334 panels->columnWidth = w / 3;
2335 }
2336 return true;
2337 }
2338
__panels_new(RCore * core)2339 static RPanels *__panels_new(RCore *core) {
2340 RPanels *panels = R_NEW0 (RPanels);
2341 if (!panels) {
2342 return NULL;
2343 }
2344 int h, w = r_cons_get_size (&h);
2345 firstRun = true;
2346 if (!__init (core, panels, w, h)) {
2347 free (panels);
2348 return NULL;
2349 }
2350 return panels;
2351 }
2352
__handle_tab_new_with_cur_panel(RCore * core)2353 static void __handle_tab_new_with_cur_panel (RCore *core) {
2354 RPanels *panels = core->panels;
2355 if (panels->n_panels <= 1) {
2356 return;
2357 }
2358
2359 RPanelsRoot *root = core->panels_root;
2360 if (root->n_panels + 1 >= PANEL_NUM_LIMIT) {
2361 return;
2362 }
2363
2364 RPanel *cur = __get_cur_panel (panels);
2365
2366 RPanels *new_panels = __panels_new (core);
2367 if (!new_panels) {
2368 return;
2369 }
2370 root->panels[root->n_panels] = new_panels;
2371
2372 RPanels *prev = core->panels;
2373 core->panels = new_panels;
2374
2375 if (!__init_panels_menu (core) || !__init_panels (core, new_panels)) {
2376 core->panels = prev;
2377 return;
2378 }
2379 __set_mode (core, PANEL_MODE_DEFAULT);
2380 __init_all_dbs (core);
2381
2382 RPanel *new_panel = __get_panel (new_panels, 0);
2383 __init_panel_param (core, new_panel, cur->model->title, cur->model->cmd);
2384 new_panel->model->cache = cur->model->cache;
2385 new_panel->model->funcName = r_str_new (cur->model->funcName);
2386 __set_cmd_str_cache (core, new_panel, r_str_new (cur->model->cmdStrCache));
2387 __maximize_panel_size (new_panels);
2388
2389 core->panels = prev;
2390 __dismantle_del_panel (core, cur, panels->curnode);
2391
2392 root->cur_panels = root->n_panels;
2393 root->n_panels++;
2394 __set_root_state (core, ROTATE);
2395 }
2396
__handle_tab_key(RCore * core,bool shift)2397 static void __handle_tab_key(RCore *core, bool shift) {
2398 __set_cursor (core, false);
2399 RPanels *panels = core->panels;
2400 RPanel *cur = __get_cur_panel (panels);
2401 r_cons_switchbuf (false);
2402 cur->view->refresh = true;
2403 if (!shift) {
2404 if (panels->mode == PANEL_MODE_MENU) {
2405 __set_curnode (core, 0);
2406 __set_mode (core, PANEL_MODE_DEFAULT);
2407 } else if (panels->mode == PANEL_MODE_ZOOM) {
2408 __set_curnode (core, ++panels->curnode);
2409 } else {
2410 __set_curnode (core, ++panels->curnode);
2411 }
2412 } else {
2413 if (panels->mode == PANEL_MODE_MENU) {
2414 __set_curnode (core, panels->n_panels - 1);
2415 __set_mode (core, PANEL_MODE_DEFAULT);
2416 } else if (panels->mode == PANEL_MODE_ZOOM) {
2417 __set_curnode (core, --panels->curnode);
2418 } else {
2419 __set_curnode (core, --panels->curnode);
2420 }
2421 }
2422 cur = __get_cur_panel (panels);
2423 cur->view->refresh = true;
2424 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
2425 __reset_snow (panels);
2426 }
2427 }
2428
__handle_zoom_mode(RCore * core,const int key)2429 static bool __handle_zoom_mode(RCore *core, const int key) {
2430 RPanels *panels = core->panels;
2431 r_cons_switchbuf (false);
2432 switch (key) {
2433 case 'Q':
2434 case 'q':
2435 case 0x0d:
2436 __toggle_zoom_mode (core);
2437 break;
2438 case 'c':
2439 case 'C':
2440 case ';':
2441 case ' ':
2442 case '_':
2443 case '/':
2444 case '"':
2445 case 'A':
2446 case 'r':
2447 case '0':
2448 case '1':
2449 case '2':
2450 case '3':
2451 case '4':
2452 case '5':
2453 case '6':
2454 case '7':
2455 case '8':
2456 case '9':
2457 case 'u':
2458 case 'U':
2459 case 'b':
2460 case 'd':
2461 case 'n':
2462 case 'N':
2463 case 'g':
2464 case 'h':
2465 case 'j':
2466 case 'k':
2467 case 'J':
2468 case 'K':
2469 case 'l':
2470 case '.':
2471 case 'R':
2472 case 'p':
2473 case 'P':
2474 case 's':
2475 case 'S':
2476 case 't':
2477 case 'T':
2478 case 'x':
2479 case 'X':
2480 case ':':
2481 case '[':
2482 case ']':
2483 return false;
2484 case 9:
2485 __restore_panel_pos (panels->panel[panels->curnode]);
2486 __handle_tab_key (core, false);
2487 __save_panel_pos (panels->panel[panels->curnode]);
2488 __maximize_panel_size (panels);
2489 break;
2490 case 'Z':
2491 __restore_panel_pos (panels->panel[panels->curnode]);
2492 __handle_tab_key (core, true);
2493 __save_panel_pos (panels->panel[panels->curnode]);
2494 __maximize_panel_size (panels);
2495 break;
2496 case '?':
2497 __toggle_zoom_mode (core);
2498 __toggle_help (core);
2499 __toggle_zoom_mode (core);
2500 break;
2501 }
2502 return true;
2503 }
2504
__set_refresh_by_type(RCore * core,const char * cmd,bool clearCache)2505 static void __set_refresh_by_type(RCore *core, const char *cmd, bool clearCache) {
2506 RPanels *panels = core->panels;
2507 int i;
2508 for (i = 0; i < panels->n_panels; i++) {
2509 RPanel *p = __get_panel (panels, i);
2510 if (!__check_panel_type (p, cmd)) {
2511 continue;
2512 }
2513 p->view->refresh = true;
2514 if (clearCache) {
2515 __set_cmd_str_cache (core, p, NULL);
2516 }
2517 }
2518 }
2519
filter_arg(char * a)2520 static char *filter_arg(char *a) {
2521 r_name_filter_print (a);
2522 char *r = r_str_escape (a);
2523 free (a);
2524 return r;
2525 }
2526
__handleComment(RCore * core)2527 static void __handleComment(RCore *core) {
2528 RPanel *p = __get_cur_panel (core->panels);
2529 if (!__check_panel_type (p, PANEL_CMD_DISASSEMBLY)) {
2530 return;
2531 }
2532 char buf[4095];
2533 char *cmd = NULL;
2534 r_line_set_prompt ("[Comment]> ");
2535 if (r_cons_fgets (buf, sizeof (buf), 0, NULL) > 0) {
2536 ut64 addr, orig;
2537 addr = orig = core->offset;
2538 if (core->print->cur_enabled) {
2539 addr += core->print->cur;
2540 r_core_seek (core, addr, false);
2541 r_core_cmdf (core, "s 0x%"PFMT64x, addr);
2542 }
2543 if (!strcmp (buf, "-")) {
2544 cmd = strdup ("CC-");
2545 } else {
2546 char *arg = filter_arg (strdup (buf));
2547 switch (buf[0]) {
2548 case '-':
2549 cmd = r_str_newf ("\"CC-%s\"", arg);
2550 break;
2551 case '!':
2552 strcpy (buf, "\"CC!");
2553 break;
2554 default:
2555 cmd = r_str_newf ("\"CC %s\"", arg);
2556 break;
2557 }
2558 free (arg);
2559 }
2560 if (cmd) {
2561 r_core_cmd (core, cmd, 1);
2562 }
2563 if (core->print->cur_enabled) {
2564 r_core_seek (core, orig, true);
2565 }
2566 free (cmd);
2567 }
2568 __set_refresh_by_type (core, p->model->cmd, true);
2569 }
2570
__move_to_direction(RCore * core,Direction direction)2571 static bool __move_to_direction(RCore *core, Direction direction) {
2572 RPanels *panels = core->panels;
2573 RPanel *cur = __get_cur_panel (panels);
2574 int cur_x0 = cur->view->pos.x, cur_x1 = cur->view->pos.x + cur->view->pos.w - 1, cur_y0 = cur->view->pos.y, cur_y1 = cur->view->pos.y + cur->view->pos.h - 1;
2575 int temp_x0, temp_x1, temp_y0, temp_y1;
2576 int i;
2577 for (i = 0; i < panels->n_panels; i++) {
2578 RPanel *p = __get_panel (panels, i);
2579 temp_x0 = p->view->pos.x;
2580 temp_x1 = p->view->pos.x + p->view->pos.w - 1;
2581 temp_y0 = p->view->pos.y;
2582 temp_y1 = p->view->pos.y + p->view->pos.h - 1;
2583 switch (direction) {
2584 case LEFT:
2585 if (temp_x1 == cur_x0) {
2586 if (temp_y1 <= cur_y0 || cur_y1 <= temp_y0) {
2587 continue;
2588 }
2589 __set_curnode (core, i);
2590 return true;
2591 }
2592 break;
2593 case RIGHT:
2594 if (temp_x0 == cur_x1) {
2595 if (temp_y1 <= cur_y0 || cur_y1 <= temp_y0) {
2596 continue;
2597 }
2598 __set_curnode (core, i);
2599 return true;
2600 }
2601 break;
2602 case UP:
2603 if (temp_y1 == cur_y0) {
2604 if (temp_x1 <= cur_x0 || cur_x1 <= temp_x0) {
2605 continue;
2606 }
2607 __set_curnode (core, i);
2608 return true;
2609 }
2610 break;
2611 case DOWN:
2612 if (temp_y0 == cur_y1) {
2613 if (temp_x1 <= cur_x0 || cur_x1 <= temp_x0) {
2614 continue;
2615 }
2616 __set_curnode (core, i);
2617 return true;
2618 }
2619 break;
2620 default:
2621 break;
2622 }
2623 }
2624 return false;
2625 }
2626
__direction_default_cb(void * user,int direction)2627 static void __direction_default_cb(void *user, int direction) {
2628 RCore *core = (RCore *)user;
2629 RPanel *cur = __get_cur_panel (core->panels);
2630 cur->view->refresh = true;
2631 switch ((Direction)direction) {
2632 case LEFT:
2633 if (cur->view->sx > 0) {
2634 cur->view->sx--;
2635 }
2636 break;
2637 case RIGHT:
2638 cur->view->sx++;
2639 break;
2640 case UP:
2641 if (cur->view->sy > 0) {
2642 cur->view->sy--;
2643 }
2644 break;
2645 case DOWN:
2646 cur->view->sy++;
2647 break;
2648 }
2649 }
2650
__direction_disassembly_cb(void * user,int direction)2651 static void __direction_disassembly_cb(void *user, int direction) {
2652 RCore *core = (RCore *)user;
2653 RPanels *panels = core->panels;
2654 RPanel *cur = __get_cur_panel (panels);
2655 int cols = core->print->cols;
2656 cur->view->refresh = true;
2657 switch ((Direction)direction) {
2658 case LEFT:
2659 if (core->print->cur_enabled) {
2660 __cursor_left (core);
2661 r_core_block_read (core);
2662 __set_panel_addr (core, cur, core->offset);
2663 } else if (panels->mode == PANEL_MODE_ZOOM) {
2664 cur->model->addr--;
2665 } else if (cur->view->sx > 0) {
2666 cur->view->sx--;
2667 }
2668 break;
2669 case RIGHT:
2670 if (core->print->cur_enabled) {
2671 __cursor_right (core);
2672 r_core_block_read (core);
2673 __set_panel_addr (core, cur, core->offset);
2674 } else if (panels->mode == PANEL_MODE_ZOOM) {
2675 cur->model->addr++;
2676 } else {
2677 cur->view->sx++;
2678 }
2679 break;
2680 case UP:
2681 core->offset = cur->model->addr;
2682 if (core->print->cur_enabled) {
2683 __cursor_up (core);
2684 r_core_block_read (core);
2685 __set_panel_addr (core, cur, core->offset);
2686 } else {
2687 r_core_visual_disasm_up (core, &cols);
2688 r_core_seek_delta (core, -cols);
2689 __set_panel_addr (core, cur, core->offset);
2690 }
2691 break;
2692 case DOWN:
2693 core->offset = cur->model->addr;
2694 if (core->print->cur_enabled) {
2695 __cursor_down (core);
2696 r_core_block_read (core);
2697 __set_panel_addr (core, cur, core->offset);
2698 } else {
2699 RAsmOp op;
2700 r_core_visual_disasm_down (core, &op, &cols);
2701 r_core_seek (core, core->offset + cols, true);
2702 __set_panel_addr (core, cur, core->offset);
2703 }
2704 break;
2705 }
2706 }
2707
__direction_graph_cb(void * user,int direction)2708 static void __direction_graph_cb(void *user, int direction) {
2709 RCore *core = (RCore *)user;
2710 RPanels *panels = core->panels;
2711 RPanel *cur = __get_cur_panel (panels);
2712 cur->view->refresh = true;
2713 const int speed = r_config_get_i (core->config, "graph.scroll") * 2;
2714 switch ((Direction)direction) {
2715 case LEFT:
2716 if (cur->view->sx > 0) {
2717 cur->view->sx -= speed;
2718 }
2719 break;
2720 case RIGHT:
2721 cur->view->sx += speed;
2722 break;
2723 case UP:
2724 if (cur->view->sy > 0) {
2725 cur->view->sy -= speed;
2726 }
2727 break;
2728 case DOWN:
2729 cur->view->sy += speed;
2730 break;
2731 }
2732 }
2733
__direction_register_cb(void * user,int direction)2734 static void __direction_register_cb(void *user, int direction) {
2735 RCore *core = (RCore *)user;
2736 RPanels *panels = core->panels;
2737 RPanel *cur = __get_cur_panel (panels);
2738 int cols = core->dbg->regcols;
2739 cols = cols > 0 ? cols : 3;
2740 cur->view->refresh = true;
2741 switch ((Direction)direction) {
2742 case LEFT:
2743 if (core->print->cur_enabled) {
2744 __cursor_left (core);
2745 } else if (cur->view->sx > 0) {
2746 cur->view->sx--;
2747 cur->view->refresh = true;
2748 }
2749 break;
2750 case RIGHT:
2751 if (core->print->cur_enabled) {
2752 __cursor_right (core);
2753 } else {
2754 cur->view->sx++;
2755 cur->view->refresh = true;
2756 }
2757 break;
2758 case UP:
2759 if (core->print->cur_enabled) {
2760 int tmp = core->print->cur;
2761 tmp -= cols;
2762 if (tmp >= 0) {
2763 core->print->cur = tmp;
2764 }
2765 }
2766 break;
2767 case DOWN:
2768 if (core->print->cur_enabled) {
2769 core->print->cur += cols;
2770 }
2771 break;
2772 }
2773 }
2774
__direction_stack_cb(void * user,int direction)2775 static void __direction_stack_cb(void *user, int direction) {
2776 RCore *core = (RCore *)user;
2777 RPanels *panels = core->panels;
2778 RPanel *cur = __get_cur_panel (panels);
2779 int cols = r_config_get_i (core->config, "hex.cols");
2780 if (cols < 1) {
2781 cols = 16;
2782 }
2783 cur->view->refresh = true;
2784 switch ((Direction)direction) {
2785 case LEFT:
2786 if (core->print->cur_enabled) {
2787 __cursor_left (core);
2788 } else if (cur->view->sx > 0) {
2789 cur->view->sx--;
2790 cur->view->refresh = true;
2791 }
2792 break;
2793 case RIGHT:
2794 if (core->print->cur_enabled) {
2795 __cursor_right (core);
2796 } else {
2797 cur->view->sx++;
2798 cur->view->refresh = true;
2799 }
2800 break;
2801 case UP:
2802 r_config_set_i (core->config, "stack.delta",
2803 r_config_get_i (core->config, "stack.delta") + cols);
2804 cur->model->addr -= cols;
2805 break;
2806 case DOWN:
2807 r_config_set_i (core->config, "stack.delta",
2808 r_config_get_i (core->config, "stack.delta") - cols);
2809 cur->model->addr += cols;
2810 break;
2811 }
2812 }
2813
__direction_hexdump_cb(void * user,int direction)2814 static void __direction_hexdump_cb(void *user, int direction) {
2815 RCore *core = (RCore *)user;
2816 RPanels *panels = core->panels;
2817 RPanel *cur = __get_cur_panel (panels);
2818 int cols = r_config_get_i (core->config, "hex.cols");
2819 if (cols < 1) {
2820 cols = 16;
2821 }
2822 cur->view->refresh = true;
2823 switch ((Direction)direction) {
2824 case LEFT:
2825 if (!core->print->cur) {
2826 cur->model->addr -= cols;
2827 core->print->cur += cols - 1;
2828 } else if (core->print->cur_enabled) {
2829 __cursor_left (core);
2830 } else {
2831 cur->model->addr--;
2832 }
2833 break;
2834 case RIGHT:
2835 if (core->print->cur / cols + 1 > cur->view->pos.h - 5
2836 && core->print->cur % cols == cols - 1) {
2837 cur->model->addr += cols;
2838 core->print->cur -= cols - 1;
2839 } else if (core->print->cur_enabled) {
2840 __cursor_right (core);
2841 } else {
2842 cur->model->addr++;
2843 }
2844 break;
2845 case UP:
2846 if (!cur->model->cache) {
2847 if (core->print->cur_enabled) {
2848 if (!(core->print->cur / cols)) {
2849 cur->model->addr -= cols;
2850 } else {
2851 core->print->cur -= cols;
2852 }
2853 } else {
2854 if (cur->model->addr <= cols) {
2855 __set_panel_addr (core, cur, 0);
2856 } else {
2857 cur->model->addr -= cols;
2858 }
2859 }
2860 } else if (cur->view->sy > 0) {
2861 cur->view->sy--;
2862 }
2863 break;
2864 case DOWN:
2865 if (!cur->model->cache) {
2866 if (core->print->cur_enabled) {
2867 if (core->print->cur / cols + 1 > cur->view->pos.h - 5) {
2868 cur->model->addr += cols;
2869 } else {
2870 core->print->cur += cols;
2871 }
2872 } else {
2873 cur->model->addr += cols;
2874 }
2875 } else {
2876 cur->view->sy++;
2877 }
2878 break;
2879 }
2880 }
2881
__direction_panels_cursor_cb(void * user,int direction)2882 static void __direction_panels_cursor_cb(void *user, int direction) {
2883 RCore *core = (RCore *)user;
2884 RPanels *panels = core->panels;
2885 RPanel *cur = __get_cur_panel (panels);
2886 cur->view->refresh = true;
2887 const int THRESHOLD = cur->view->pos.h / 3;
2888 int sub;
2889 switch ((Direction)direction) {
2890 case LEFT:
2891 if (core->print->cur_enabled) {
2892 break;
2893 }
2894 if (cur->view->sx > 0) {
2895 cur->view->sx -= r_config_get_i (core->config, "graph.scroll");
2896 }
2897 break;
2898 case RIGHT:
2899 if (core->print->cur_enabled) {
2900 break;
2901 }
2902 cur->view->sx += r_config_get_i (core->config, "graph.scroll");
2903 break;
2904 case UP:
2905 if (core->print->cur_enabled) {
2906 if (cur->view->curpos > 0) {
2907 cur->view->curpos--;
2908 }
2909 if (cur->view->sy > 0) {
2910 sub = cur->view->curpos - cur->view->sy;
2911 if (sub < 0) {
2912 cur->view->sy--;
2913 }
2914 }
2915 } else {
2916 if (cur->view->sy > 0) {
2917 cur->view->curpos -= 1;
2918 cur->view->sy -= 1;
2919 }
2920 }
2921 break;
2922 case DOWN:
2923 core->offset = cur->model->addr;
2924 if (core->print->cur_enabled) {
2925 cur->view->curpos++;
2926 sub = cur->view->curpos - cur->view->sy;
2927 if (sub > THRESHOLD) {
2928 cur->view->sy++;
2929 }
2930 } else {
2931 cur->view->curpos += 1;
2932 cur->view->sy += 1;
2933 }
2934 break;
2935 }
2936 }
2937
__toggle_window_mode(RCore * core)2938 static void __toggle_window_mode(RCore *core) {
2939 RPanels *panels = core->panels;
2940 if (panels->mode != PANEL_MODE_WINDOW) {
2941 panels->prevMode = panels->mode;
2942 __set_mode (core, PANEL_MODE_WINDOW);
2943 } else {
2944 __set_mode (core, panels->prevMode);
2945 panels->prevMode = PANEL_MODE_DEFAULT;
2946 }
2947 }
2948
__resize_panel_left(RPanels * panels)2949 static void __resize_panel_left(RPanels *panels) {
2950 RPanel *cur = __get_cur_panel (panels);
2951 int i, cx0, cx1, cy0, cy1, tx0, tx1, ty0, ty1, cur1 = 0, cur2 = 0, cur3 = 0, cur4 = 0;
2952 cx0 = cur->view->pos.x;
2953 cx1 = cur->view->pos.x + cur->view->pos.w - 1;
2954 cy0 = cur->view->pos.y;
2955 cy1 = cur->view->pos.y + cur->view->pos.h - 1;
2956 RPanel **targets1 = malloc (sizeof (RPanel *) * panels->n_panels);
2957 RPanel **targets2 = malloc (sizeof (RPanel *) * panels->n_panels);
2958 RPanel **targets3 = malloc (sizeof (RPanel *) * panels->n_panels);
2959 RPanel **targets4 = malloc (sizeof (RPanel *) * panels->n_panels);
2960 if (!targets1 || !targets2 || !targets3 || !targets4) {
2961 goto beach;
2962 }
2963 for (i = 0; i < panels->n_panels; i++) {
2964 if (i == panels->curnode) {
2965 continue;
2966 }
2967 RPanel *p = __get_panel (panels, i);
2968 tx0 = p->view->pos.x;
2969 tx1 = p->view->pos.x + p->view->pos.w - 1;
2970 ty0 = p->view->pos.y;
2971 ty1 = p->view->pos.y + p->view->pos.h - 1;
2972 if (ty0 == cy0 && ty1 == cy1 && tx1 == cx0 && tx1 - PANEL_CONFIG_RESIZE_W > tx0) {
2973 p->view->pos.w -= PANEL_CONFIG_RESIZE_W;
2974 cur->view->pos.x -= PANEL_CONFIG_RESIZE_W;
2975 cur->view->pos.w += PANEL_CONFIG_RESIZE_W;
2976 p->view->refresh = true;
2977 cur->view->refresh = true;
2978 goto beach;
2979 }
2980 bool y_included = (ty1 >= cy0 && cy1 >= ty1) || (ty0 >= cy0 && cy1 >= ty0);
2981 if (tx1 == cx0 && y_included) {
2982 if (tx1 - PANEL_CONFIG_RESIZE_W > tx0) {
2983 targets1[cur1++] = p;
2984 }
2985 }
2986 if (tx0 == cx1 && y_included) {
2987 if (tx0 - PANEL_CONFIG_RESIZE_W > cx0) {
2988 targets3[cur3++] = p;
2989 }
2990 }
2991 if (tx0 == cx0) {
2992 if (tx0 - PANEL_CONFIG_RESIZE_W > 0) {
2993 targets2[cur2++] = p;
2994 }
2995 }
2996 if (tx1 == cx1) {
2997 if (tx1 + PANEL_CONFIG_RESIZE_W < panels->can->w) {
2998 targets4[cur4++] = p;
2999 }
3000 }
3001 }
3002 if (cur1 > 0) {
3003 for (i = 0; i < cur1; i++) {
3004 targets1[i]->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3005 targets1[i]->view->refresh = true;
3006 }
3007 for (i = 0; i < cur2; i++) {
3008 targets2[i]->view->pos.x -= PANEL_CONFIG_RESIZE_W;
3009 targets2[i]->view->pos.w += PANEL_CONFIG_RESIZE_W;
3010 targets2[i]->view->refresh = true;
3011 }
3012 cur->view->pos.x -= PANEL_CONFIG_RESIZE_W;
3013 cur->view->pos.w += PANEL_CONFIG_RESIZE_W;
3014 cur->view->refresh = true;
3015 } else if (cur3 > 0) {
3016 for (i = 0; i < cur3; i++) {
3017 targets3[i]->view->pos.w += PANEL_CONFIG_RESIZE_W;
3018 targets3[i]->view->pos.x -= PANEL_CONFIG_RESIZE_W;
3019 targets3[i]->view->refresh = true;
3020 }
3021 for (i = 0; i < cur4; i++) {
3022 targets4[i]->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3023 targets4[i]->view->refresh = true;
3024 }
3025 cur->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3026 cur->view->refresh = true;
3027 }
3028 beach:
3029 free (targets1);
3030 free (targets2);
3031 free (targets3);
3032 free (targets4);
3033 }
3034
__resize_panel_right(RPanels * panels)3035 static void __resize_panel_right(RPanels *panels) {
3036 RPanel *cur = __get_cur_panel (panels);
3037 int i, tx0, tx1, ty0, ty1, cur1 = 0, cur2 = 0, cur3 = 0, cur4 = 0;
3038 int cx0 = cur->view->pos.x;
3039 int cx1 = cur->view->pos.x + cur->view->pos.w - 1;
3040 int cy0 = cur->view->pos.y;
3041 int cy1 = cur->view->pos.y + cur->view->pos.h - 1;
3042 RPanel **targets1 = malloc (sizeof (RPanel *) * panels->n_panels);
3043 RPanel **targets2 = malloc (sizeof (RPanel *) * panels->n_panels);
3044 RPanel **targets3 = malloc (sizeof (RPanel *) * panels->n_panels);
3045 RPanel **targets4 = malloc (sizeof (RPanel *) * panels->n_panels);
3046 if (!targets1 || !targets2 || !targets3 || !targets4) {
3047 goto beach;
3048 }
3049 for (i = 0; i < panels->n_panels; i++) {
3050 if (i == panels->curnode) {
3051 continue;
3052 }
3053 RPanel *p = __get_panel (panels, i);
3054 tx0 = p->view->pos.x;
3055 tx1 = p->view->pos.x + p->view->pos.w - 1;
3056 ty0 = p->view->pos.y;
3057 ty1 = p->view->pos.y + p->view->pos.h - 1;
3058 if (ty0 == cy0 && ty1 == cy1 && tx0 == cx1 && tx0 + PANEL_CONFIG_RESIZE_W < tx1) {
3059 p->view->pos.x += PANEL_CONFIG_RESIZE_W;
3060 p->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3061 cur->view->pos.w += PANEL_CONFIG_RESIZE_W;
3062 p->view->refresh = true;
3063 cur->view->refresh = true;
3064 goto beach;
3065 }
3066 bool y_included = (ty1 >= cy0 && cy1 >= ty1) || (ty0 >= cy0 && cy1 >= ty0);
3067 if (tx1 == cx0 && y_included) {
3068 if (tx1 + PANEL_CONFIG_RESIZE_W < cx1) {
3069 targets1[cur1++] = p;
3070 }
3071 }
3072 if (tx0 == cx1 && y_included) {
3073 if (tx0 + PANEL_CONFIG_RESIZE_W < tx1) {
3074 targets3[cur3++] = p;
3075 }
3076 }
3077 if (tx0 == cx0) {
3078 if (tx0 + PANEL_CONFIG_RESIZE_W < tx1) {
3079 targets2[cur2++] = p;
3080 }
3081 }
3082 if (tx1 == cx1) {
3083 if (tx1 + PANEL_CONFIG_RESIZE_W < panels->can->w) {
3084 targets4[cur4++] = p;
3085 }
3086 }
3087 }
3088 if (cur3 > 0) {
3089 for (i = 0; i < cur3; i++) {
3090 targets3[i]->view->pos.x += PANEL_CONFIG_RESIZE_W;
3091 targets3[i]->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3092 targets3[i]->view->refresh = true;
3093 }
3094 for (i = 0; i < cur4; i++) {
3095 targets4[i]->view->pos.w += PANEL_CONFIG_RESIZE_W;
3096 targets4[i]->view->refresh = true;
3097 }
3098 cur->view->pos.w += PANEL_CONFIG_RESIZE_W;
3099 cur->view->refresh = true;
3100 } else if (cur1 > 0) {
3101 for (i = 0; i < cur1; i++) {
3102 targets1[i]->view->pos.w += PANEL_CONFIG_RESIZE_W;
3103 targets1[i]->view->refresh = true;
3104 }
3105 for (i = 0; i < cur2; i++) {
3106 targets2[i]->view->pos.x += PANEL_CONFIG_RESIZE_W;
3107 targets2[i]->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3108 targets2[i]->view->refresh = true;
3109 }
3110 cur->view->pos.x += PANEL_CONFIG_RESIZE_W;
3111 cur->view->pos.w -= PANEL_CONFIG_RESIZE_W;
3112 cur->view->refresh = true;
3113 }
3114 beach:
3115 free (targets1);
3116 free (targets2);
3117 free (targets3);
3118 free (targets4);
3119 }
3120
__resize_panel_up(RPanels * panels)3121 static void __resize_panel_up(RPanels *panels) {
3122 RPanel *cur = __get_cur_panel (panels);
3123 int i, tx0, tx1, ty0, ty1, cur1 = 0, cur2 = 0, cur3 = 0, cur4 = 0;
3124 int cx0 = cur->view->pos.x;
3125 int cx1 = cur->view->pos.x + cur->view->pos.w - 1;
3126 int cy0 = cur->view->pos.y;
3127 int cy1 = cur->view->pos.y + cur->view->pos.h - 1;
3128 RPanel **targets1 = malloc (sizeof (RPanel *) * panels->n_panels);
3129 RPanel **targets2 = malloc (sizeof (RPanel *) * panels->n_panels);
3130 RPanel **targets3 = malloc (sizeof (RPanel *) * panels->n_panels);
3131 RPanel **targets4 = malloc (sizeof (RPanel *) * panels->n_panels);
3132 if (!targets1 || !targets2 || !targets3 || !targets4) {
3133 goto beach;
3134 }
3135 for (i = 0; i < panels->n_panels; i++) {
3136 if (i == panels->curnode) {
3137 continue;
3138 }
3139 RPanel *p = __get_panel (panels, i);
3140 tx0 = p->view->pos.x;
3141 tx1 = p->view->pos.x + p->view->pos.w - 1;
3142 ty0 = p->view->pos.y;
3143 ty1 = p->view->pos.y + p->view->pos.h - 1;
3144 if (tx0 == cx0 && tx1 == cx1 && ty1 == cy0 && ty1 - PANEL_CONFIG_RESIZE_H > ty0) {
3145 p->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3146 cur->view->pos.y -= PANEL_CONFIG_RESIZE_H;
3147 cur->view->pos.h += PANEL_CONFIG_RESIZE_H;
3148 p->view->refresh = true;
3149 cur->view->refresh = true;
3150 goto beach;
3151 }
3152 bool x_included = (tx1 >= cx0 && cx1 >= tx1) || (tx0 >= cx0 && cx1 >= tx0);
3153 if (ty1 == cy0 && x_included) {
3154 if (ty1 - PANEL_CONFIG_RESIZE_H > ty0) {
3155 targets1[cur1++] = p;
3156 }
3157 }
3158 if (ty0 == cy1 && x_included) {
3159 if (ty0 - PANEL_CONFIG_RESIZE_H > cy0) {
3160 targets3[cur3++] = p;
3161 }
3162 }
3163 if (ty0 == cy0) {
3164 if (ty0 - PANEL_CONFIG_RESIZE_H > 0) {
3165 targets2[cur2++] = p;
3166 }
3167 }
3168 if (ty1 == cy1) {
3169 if (ty1 - PANEL_CONFIG_RESIZE_H > ty0) {
3170 targets4[cur4++] = p;
3171 }
3172 }
3173 }
3174 if (cur1 > 0) {
3175 for (i = 0; i < cur1; i++) {
3176 targets1[i]->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3177 targets1[i]->view->refresh = true;
3178 }
3179 for (i = 0; i < cur2; i++) {
3180 targets2[i]->view->pos.y -= PANEL_CONFIG_RESIZE_H;
3181 targets2[i]->view->pos.h += PANEL_CONFIG_RESIZE_H;
3182 targets2[i]->view->refresh = true;
3183 }
3184 cur->view->pos.y -= PANEL_CONFIG_RESIZE_H;
3185 cur->view->pos.h += PANEL_CONFIG_RESIZE_H;
3186 cur->view->refresh = true;
3187 } else if (cur3 > 0) {
3188 for (i = 0; i < cur3; i++) {
3189 targets3[i]->view->pos.h += PANEL_CONFIG_RESIZE_H;
3190 targets3[i]->view->pos.y -= PANEL_CONFIG_RESIZE_H;
3191 targets3[i]->view->refresh = true;
3192 }
3193 for (i = 0; i < cur4; i++) {
3194 targets4[i]->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3195 targets4[i]->view->refresh = true;
3196 }
3197 cur->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3198 cur->view->refresh = true;
3199 }
3200 beach:
3201 free (targets1);
3202 free (targets2);
3203 free (targets3);
3204 free (targets4);
3205 }
__resize_panel_down(RPanels * panels)3206 static void __resize_panel_down(RPanels *panels) {
3207 RPanel *cur = __get_cur_panel (panels);
3208 int i, tx0, tx1, ty0, ty1, cur1 = 0, cur2 = 0, cur3 = 0, cur4 = 0;
3209 int cx0 = cur->view->pos.x;
3210 int cx1 = cur->view->pos.x + cur->view->pos.w - 1;
3211 int cy0 = cur->view->pos.y;
3212 int cy1 = cur->view->pos.y + cur->view->pos.h - 1;
3213 RPanel **targets1 = malloc (sizeof (RPanel *) * panels->n_panels);
3214 RPanel **targets2 = malloc (sizeof (RPanel *) * panels->n_panels);
3215 RPanel **targets3 = malloc (sizeof (RPanel *) * panels->n_panels);
3216 RPanel **targets4 = malloc (sizeof (RPanel *) * panels->n_panels);
3217 if (!targets1 || !targets2 || !targets3 || !targets4) {
3218 goto beach;
3219 }
3220 for (i = 0; i < panels->n_panels; i++) {
3221 if (i == panels->curnode) {
3222 continue;
3223 }
3224 RPanel *p = __get_panel (panels, i);
3225 tx0 = p->view->pos.x;
3226 tx1 = p->view->pos.x + p->view->pos.w - 1;
3227 ty0 = p->view->pos.y;
3228 ty1 = p->view->pos.y + p->view->pos.h - 1;
3229 if (tx0 == cx0 && tx1 == cx1 && ty0 == cy1 && ty0 + PANEL_CONFIG_RESIZE_H < ty1) {
3230 p->view->pos.y += PANEL_CONFIG_RESIZE_H;
3231 p->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3232 cur->view->pos.h += PANEL_CONFIG_RESIZE_H;
3233 p->view->refresh = true;
3234 cur->view->refresh = true;
3235 goto beach;
3236 }
3237 bool x_included = (tx1 >= cx0 && cx1 >= tx1) || (tx0 >= cx0 && cx1 >= tx0);
3238 if (ty1 == cy0 && x_included) {
3239 if (ty1 + PANEL_CONFIG_RESIZE_H < cy1) {
3240 targets1[cur1++] = p;
3241 }
3242 }
3243 if (ty0 == cy1 && x_included) {
3244 if (ty0 + PANEL_CONFIG_RESIZE_H < ty1) {
3245 targets3[cur3++] = p;
3246 }
3247 }
3248 if (ty0 == cy0) {
3249 if (ty0 + PANEL_CONFIG_RESIZE_H < ty1) {
3250 targets2[cur2++] = p;
3251 }
3252 }
3253 if (ty1 == cy1) {
3254 if (ty1 + PANEL_CONFIG_RESIZE_H < panels->can->h) {
3255 targets4[cur4++] = p;
3256 }
3257 }
3258 }
3259 if (cur3 > 0) {
3260 for (i = 0; i < cur3; i++) {
3261 targets3[i]->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3262 targets3[i]->view->pos.y += PANEL_CONFIG_RESIZE_H;
3263 targets3[i]->view->refresh = true;
3264 }
3265 for (i = 0; i < cur4; i++) {
3266 targets4[i]->view->pos.h += PANEL_CONFIG_RESIZE_H;
3267 targets4[i]->view->refresh = true;
3268 }
3269 cur->view->pos.h += PANEL_CONFIG_RESIZE_H;
3270 cur->view->refresh = true;
3271 } else if (cur1 > 0) {
3272 for (i = 0; i < cur1; i++) {
3273 targets1[i]->view->pos.h += PANEL_CONFIG_RESIZE_H;
3274 targets1[i]->view->refresh = true;
3275 }
3276 for (i = 0; i < cur2; i++) {
3277 targets2[i]->view->pos.y += PANEL_CONFIG_RESIZE_H;
3278 targets2[i]->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3279 targets2[i]->view->refresh = true;
3280 }
3281 cur->view->pos.y += PANEL_CONFIG_RESIZE_H;
3282 cur->view->pos.h -= PANEL_CONFIG_RESIZE_H;
3283 cur->view->refresh = true;
3284 }
3285 beach:
3286 free (targets1);
3287 free (targets2);
3288 free (targets3);
3289 free (targets4);
3290 }
3291
__handle_window_mode(RCore * core,const int key)3292 static bool __handle_window_mode(RCore *core, const int key) {
3293 RPanels *panels = core->panels;
3294 RPanel *cur = __get_cur_panel (panels);
3295 r_cons_switchbuf (false);
3296 switch (key) {
3297 case 'Q':
3298 case 'q':
3299 case 'w':
3300 __toggle_window_mode (core);
3301 break;
3302 case 0x0d:
3303 __toggle_zoom_mode (core);
3304 break;
3305 case 9: // tab
3306 __handle_tab_key (core, false);
3307 break;
3308 case 'Z': // shift-tab
3309 __handle_tab_key (core, true);
3310 break;
3311 case 'e':
3312 {
3313 char *cmd = __show_status_input (core, "New command: ");
3314 if (R_STR_ISNOTEMPTY (cmd)) {
3315 __replace_cmd (core, cmd, cmd);
3316 }
3317 free (cmd);
3318 }
3319 break;
3320 case 'h':
3321 if (r_config_get_i (core->config, "scr.cursor")) {
3322 core->cons->cpos.x--;
3323 } else {
3324 (void)__move_to_direction (core, LEFT);
3325 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
3326 __reset_snow (panels);
3327 }
3328 }
3329 break;
3330 case 'j':
3331 if (r_config_get_i (core->config, "scr.cursor")) {
3332 core->cons->cpos.y++;
3333 } else {
3334 (void)__move_to_direction (core, DOWN);
3335 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
3336 __reset_snow (panels);
3337 }
3338 }
3339 break;
3340 case 'k':
3341 if (r_config_get_i (core->config, "scr.cursor")) {
3342 core->cons->cpos.y--;
3343 } else {
3344 (void)__move_to_direction (core, UP);
3345 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
3346 __reset_snow (panels);
3347 }
3348 }
3349 break;
3350 case 'l':
3351 if (r_config_get_i (core->config, "scr.cursor")) {
3352 core->cons->cpos.x++;
3353 } else {
3354 (void)__move_to_direction (core, RIGHT);
3355 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
3356 __reset_snow (panels);
3357 }
3358 }
3359 break;
3360 case 'H':
3361 if (r_config_get_i (core->config, "scr.cursor")) {
3362 core->cons->cpos.x += 5;
3363 } else {
3364 r_cons_switchbuf (false);
3365 __resize_panel_left (panels);
3366 }
3367 break;
3368 case 'L':
3369 if (r_config_get_i (core->config, "scr.cursor")) {
3370 core->cons->cpos.x += 5;
3371 } else {
3372 r_cons_switchbuf (false);
3373 __resize_panel_right (panels);
3374 }
3375 break;
3376 case 'J':
3377 if (r_config_get_i (core->config, "scr.cursor")) {
3378 core->cons->cpos.y += 5;
3379 } else {
3380 r_cons_switchbuf (false);
3381 __resize_panel_down (panels);
3382 }
3383 break;
3384 case 'K':
3385 if (r_config_get_i (core->config, "scr.cursor")) {
3386 core->cons->cpos.y -= 5;
3387 } else {
3388 r_cons_switchbuf (false);
3389 __resize_panel_up (panels);
3390 }
3391 break;
3392 case 'n':
3393 __create_panel_input (core, cur, PANEL_LAYOUT_VERTICAL, NULL);
3394 break;
3395 case 'N':
3396 __create_panel_input (core, cur, PANEL_LAYOUT_HORIZONTAL, NULL);
3397 break;
3398 case 'X':
3399 __dismantle_del_panel (core, cur, panels->curnode);
3400 break;
3401 case '"':
3402 case ':':
3403 case ';':
3404 case '/':
3405 case 'd':
3406 case 'b':
3407 case 'p':
3408 case 'P':
3409 case 't':
3410 case 'T':
3411 case '?':
3412 case '|':
3413 case '-':
3414 return false;
3415 }
3416 return true;
3417 }
3418
__jmp_to_cursor_addr(RCore * core,RPanel * panel)3419 static void __jmp_to_cursor_addr(RCore *core, RPanel *panel) {
3420 ut64 addr = __parse_string_on_cursor (core, panel, panel->view->curpos);
3421 if (addr == UT64_MAX) {
3422 return;
3423 }
3424 core->offset = addr;
3425 __update_disassembly_or_open (core);
3426 }
3427
__set_breakpoints_on_cursor(RCore * core,RPanel * panel)3428 static void __set_breakpoints_on_cursor(RCore *core, RPanel *panel) {
3429 if (!r_config_get_i (core->config, "cfg.debug")) {
3430 return;
3431 }
3432 if (__check_panel_type (panel, PANEL_CMD_DISASSEMBLY)) {
3433 r_core_cmdf (core, "dbs 0x%08"PFMT64x, core->offset + core->print->cur);
3434 panel->view->refresh = true;
3435 }
3436 }
3437
__insert_value(RCore * core)3438 static void __insert_value(RCore *core) {
3439 if (!r_config_get_i (core->config, "io.cache")) {
3440 if (__show_status_yesno (core, 1, "Insert is not available because io.cache is off. Turn on now?(Y/n)")) {
3441 r_config_set_b (core->config, "io.cache", true);
3442 (void)__show_status (core, "io.cache is on and insert is available now.");
3443 } else {
3444 (void)__show_status (core, "You can always turn on io.cache in Menu->Edit->io.cache");
3445 return;
3446 }
3447 }
3448 RPanels *panels = core->panels;
3449 RPanel *cur = __get_cur_panel (panels);
3450 char buf[128];
3451 if (__check_panel_type (cur, PANEL_CMD_STACK)) {
3452 const char *prompt = "insert hex: ";
3453 __panel_prompt (prompt, buf, sizeof (buf));
3454 r_core_cmdf (core, "wx %s @ 0x%08" PFMT64x, buf, cur->model->addr);
3455 cur->view->refresh = true;
3456 } else if (__check_panel_type (cur, PANEL_CMD_REGISTERS)) {
3457 const char *creg = core->dbg->creg;
3458 if (creg) {
3459 const char *prompt = "new-reg-value> ";
3460 __panel_prompt (prompt, buf, sizeof (buf));
3461 r_core_cmdf (core, "dr %s = %s", creg, buf);
3462 cur->view->refresh = true;
3463 }
3464 } else if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
3465 const char *prompt = "insert hex: ";
3466 __panel_prompt (prompt, buf, sizeof (buf));
3467 r_core_cmdf (core, "wx %s @ 0x%08" PFMT64x, buf, core->offset + core->print->cur);
3468 cur->view->refresh = true;
3469 } else if (__check_panel_type (cur, PANEL_CMD_HEXDUMP)) {
3470 const char *prompt = "insert hex: ";
3471 __panel_prompt (prompt, buf, sizeof (buf));
3472 r_core_cmdf (core, "wx %s @ 0x%08" PFMT64x, buf, cur->model->addr + core->print->cur);
3473 cur->view->refresh = true;
3474 }
3475 }
3476
__cursor_del_breakpoints(RCore * core,RPanel * panel)3477 static void __cursor_del_breakpoints(RCore *core, RPanel *panel) {
3478 RListIter *iter;
3479 RBreakpointItem *b;
3480 int i = 0;
3481 r_list_foreach (core->dbg->bp->bps, iter, b) {
3482 if (panel->view->curpos == i++) {
3483 r_bp_del (core->dbg->bp, b->addr);
3484 }
3485 }
3486 }
3487
__set_addr_by_type(RCore * core,const char * cmd,ut64 addr)3488 static void __set_addr_by_type(RCore *core, const char *cmd, ut64 addr) {
3489 RPanels *panels = core->panels;
3490 int i;
3491 for (i = 0; i < panels->n_panels; i++) {
3492 RPanel *p = __get_panel (panels, i);
3493 if (!__check_panel_type (p, cmd)) {
3494 continue;
3495 }
3496 __set_panel_addr (core, p, addr);
3497 }
3498 }
3499
__handle_refs(RCore * core,RPanel * panel,ut64 tmp)3500 static void __handle_refs(RCore *core, RPanel *panel, ut64 tmp) {
3501 if (tmp != UT64_MAX) {
3502 core->offset = tmp;
3503 }
3504 int key = __show_status(core, "xrefs:x refs:X ");
3505 switch (key) {
3506 case 'x':
3507 (void)r_core_visual_refs (core, true, false);
3508 break;
3509 case 'X':
3510 (void)r_core_visual_refs (core, false, false);
3511 break;
3512 default:
3513 break;
3514 }
3515 if (__check_panel_type (panel, PANEL_CMD_DISASSEMBLY)) {
3516 __set_panel_addr (core, panel, core->offset);
3517 } else {
3518 __set_addr_by_type (core, PANEL_CMD_DISASSEMBLY, core->offset);
3519 }
3520 }
3521
__handle_cursor_mode(RCore * core,const int key)3522 static bool __handle_cursor_mode(RCore *core, const int key) {
3523 RPanel *cur = __get_cur_panel (core->panels);
3524 RPrint *print = core->print;
3525 char *db_val;
3526 switch (key) {
3527 case ':':
3528 case ';':
3529 case 'd':
3530 case 'h':
3531 case 'j':
3532 case 'k':
3533 case 'J':
3534 case 'K':
3535 case 'l':
3536 case 'm':
3537 case 'Z':
3538 case '"':
3539 case 9:
3540 return false;
3541 case 'g':
3542 cur->view->curpos = 0;
3543 __reset_scroll_pos (cur);
3544 cur->view->refresh = true;
3545 break;
3546 case ']':
3547 if (__check_panel_type (cur, PANEL_CMD_HEXDUMP)) {
3548 const int cols = r_config_get_i (core->config, "hex.cols");
3549 r_config_set_i (core->config, "hex.cols", cols + 1);
3550 } else {
3551 const int cmtcol = r_config_get_i (core->config, "asm.cmt.col");
3552 r_config_set_i (core->config, "asm.cmt.col", cmtcol + 2);
3553 }
3554 cur->view->refresh = true;
3555 break;
3556 case '[':
3557 if (__check_panel_type (cur, PANEL_CMD_HEXDUMP)) {
3558 const int cols = r_config_get_i (core->config, "hex.cols");
3559 r_config_set_i (core->config, "hex.cols", cols - 1);
3560 } else {
3561 int cmtcol = r_config_get_i (core->config, "asm.cmt.col");
3562 if (cmtcol > 2) {
3563 r_config_set_i (core->config, "asm.cmt.col", cmtcol - 2);
3564 }
3565 }
3566 cur->view->refresh = true;
3567 break;
3568 case 'Q':
3569 case 'q':
3570 case 'c':
3571 __set_cursor (core, !print->cur_enabled);
3572 cur->view->refresh = true;
3573 break;
3574 case 'w':
3575 __toggle_window_mode (core);
3576 __set_cursor (core, false);
3577 cur->view->refresh = true;
3578 break;
3579 case 'i':
3580 __insert_value (core);
3581 break;
3582 case '*':
3583 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
3584 r_core_cmdf (core, "dr PC=0x%08"PFMT64x, core->offset + print->cur);
3585 __set_panel_addr (core, cur, core->offset + print->cur);
3586 }
3587 break;
3588 case '-':
3589 db_val = __search_db (core, "Breakpoints");
3590 if (__check_panel_type (cur, db_val)) {
3591 __cursor_del_breakpoints(core, cur);
3592 free (db_val);
3593 break;
3594 }
3595 free (db_val);
3596 return false;
3597 case 'x':
3598 __handle_refs (core, cur, __parse_string_on_cursor (core, cur, cur->view->curpos));
3599 break;
3600 case 0x0d:
3601 __jmp_to_cursor_addr (core, cur);
3602 break;
3603 case 'b':
3604 __set_breakpoints_on_cursor (core, cur);
3605 break;
3606 case 'H':
3607 cur->view->curpos = cur->view->sy;
3608 cur->view->refresh = true;
3609 break;
3610 }
3611 return true;
3612 }
3613
__drag_and_resize(RCore * core)3614 static bool __drag_and_resize(RCore *core) {
3615 RPanels *panels = core->panels;
3616 if (panels->mouse_on_edge_x || panels->mouse_on_edge_y) {
3617 int x, y;
3618 if (r_cons_get_click (&x, &y)) {
3619 if (panels->mouse_on_edge_x) {
3620 __update_edge_x (core, x - panels->mouse_orig_x);
3621 }
3622 if (panels->mouse_on_edge_y) {
3623 __update_edge_y (core, y - panels->mouse_orig_y);
3624 }
3625 }
3626 panels->mouse_on_edge_x = false;
3627 panels->mouse_on_edge_y = false;
3628 return true;
3629 }
3630 return false;
3631 }
3632
__get_word_from_canvas(RCore * core,RPanels * panels,int x,int y)3633 static char *__get_word_from_canvas(RCore *core, RPanels *panels, int x, int y) {
3634 RStrBuf rsb;
3635 r_strbuf_init (&rsb);
3636 char *cs = r_cons_canvas_to_string (panels->can);
3637 r_strbuf_setf (&rsb, " %s", cs);
3638 char *R = r_str_ansi_crop (r_strbuf_get (&rsb), 0, y - 1, x + 1024, y);
3639 r_str_ansi_filter (R, NULL, NULL, -1);
3640 char *r = r_str_ansi_crop (r_strbuf_get (&rsb), x - 1, y - 1, x + 1024, y);
3641 r_str_ansi_filter (r, NULL, NULL, -1);
3642 char *pos = strstr (R, r);
3643 if (!pos) {
3644 pos = R;
3645 }
3646 #define TOkENs ":=*+-/()[,] "
3647 const char *sp = r_str_rsep (R, pos, TOkENs);
3648 if (sp) {
3649 sp++;
3650 } else {
3651 sp = pos;
3652 }
3653 char *sp2 = (char *)r_str_sep (sp, TOkENs);
3654 if (sp2) {
3655 *sp2 = 0;
3656 }
3657 char *res = strdup (sp);
3658 free (r);
3659 free (R);
3660 free (cs);
3661 r_strbuf_fini (&rsb);
3662 return res;
3663 }
3664
__get_word_from_canvas_for_menu(RCore * core,RPanels * panels,int x,int y)3665 static char *__get_word_from_canvas_for_menu(RCore *core, RPanels *panels, int x, int y) {
3666 char *cs = r_cons_canvas_to_string (panels->can);
3667 char *R = r_str_ansi_crop (cs, 0, y - 1, x + 1024, y);
3668 r_str_ansi_filter (R, NULL, NULL, -1);
3669 char *r = r_str_ansi_crop (cs, x - 1, y - 1, x + 1024, y);
3670 r_str_ansi_filter (r, NULL, NULL, -1);
3671 char *pos = strstr (R, r);
3672 char *tmp = pos;
3673 const char *padding = " ";
3674 if (!pos) {
3675 pos = R;
3676 }
3677 int i = 0;
3678 while (pos > R && strncmp (padding, pos, strlen (padding))) {
3679 pos--;
3680 i++;
3681 }
3682 while (R_STR_ISNOTEMPTY (tmp) && strncmp (padding, tmp, strlen (padding))) {
3683 tmp++;
3684 i++;
3685 }
3686 char *ret = r_str_newlen (pos += strlen (padding), i - strlen (padding));
3687 if (!ret) {
3688 ret = strdup (pos);
3689 }
3690 free (r);
3691 free (R);
3692 free (cs);
3693 return ret;
3694 }
3695
__handle_tab_nth(RCore * core,int ch)3696 static void __handle_tab_nth(RCore *core, int ch) {
3697 ch -= '0' + 1;
3698 if (ch < 0) {
3699 return;
3700 }
3701 if (ch != core->panels_root->cur_panels && ch < core->panels_root->n_panels) {
3702 core->panels_root->cur_panels = ch;
3703 __set_root_state (core, ROTATE);
3704 }
3705 }
3706
__clear_panels_menuRec(RPanelsMenuItem * pmi)3707 static void __clear_panels_menuRec(RPanelsMenuItem *pmi) {
3708 size_t i = 0;
3709 for (i = 0; i < pmi->n_sub; i++) {
3710 RPanelsMenuItem *sub = pmi->sub[i];
3711 if (sub) {
3712 sub->selectedIndex = 0;
3713 __clear_panels_menuRec (sub);
3714 }
3715 }
3716 }
3717
__clear_panels_menu(RCore * core)3718 static void __clear_panels_menu(RCore *core) {
3719 RPanels *p = core->panels;
3720 RPanelsMenu *pm = p->panels_menu;
3721 __clear_panels_menuRec (pm->root);
3722 pm->root->selectedIndex = 0;
3723 pm->history[0] = pm->root;
3724 pm->depth = 1;
3725 pm->n_refresh = 0;
3726 }
3727
__handle_mouse_on_top(RCore * core,int x,int y)3728 static bool __handle_mouse_on_top(RCore *core, int x, int y) {
3729 RPanels *panels = core->panels;
3730 char *word = __get_word_from_canvas (core, panels, x, y);
3731 int i;
3732 for (i = 0; i < COUNT (menus); i++) {
3733 if (!strcmp (word, menus[i])) {
3734 __set_mode (core, PANEL_MODE_MENU);
3735 __clear_panels_menu (core);
3736 RPanelsMenu *menu = panels->panels_menu;
3737 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
3738 parent->selectedIndex = i;
3739 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
3740 (void)(child->cb (core));
3741 free (word);
3742 return true;
3743 }
3744 }
3745 if (!strcmp (word, "Tab")) {
3746 __handle_tab_new (core);
3747 free (word);
3748 return true;
3749 }
3750 if (word[0] == '[' && word[1] && word[2] == ']') {
3751 return true;
3752 }
3753 if (atoi (word)) {
3754 __handle_tab_nth (core, word[0]);
3755 return true;
3756 }
3757 return false;
3758 }
3759
__del_menu(RCore * core)3760 static void __del_menu(RCore *core) {
3761 RPanels *panels = core->panels;
3762 RPanelsMenu *menu = panels->panels_menu;
3763 int i;
3764 menu->depth--;
3765 for (i = 1; i < menu->depth; i++) {
3766 menu->history[i]->p->view->refresh = true;
3767 menu->refreshPanels[i - 1] = menu->history[i]->p;
3768 }
3769 menu->n_refresh = menu->depth - 1;
3770 }
3771
__draw_menu(RCore * core,RPanelsMenuItem * item)3772 static RStrBuf *__draw_menu(RCore *core, RPanelsMenuItem *item) {
3773 RStrBuf *buf = r_strbuf_new (NULL);
3774 if (!buf) {
3775 return NULL;
3776 }
3777 size_t i;
3778 for (i = 0; i < item->n_sub; i++) {
3779 if (i == item->selectedIndex) {
3780 r_strbuf_appendf (buf, "%s> %s"Color_RESET,
3781 core->cons->context->pal.graph_box2, item->sub[i]->name);
3782 } else {
3783 r_strbuf_appendf (buf, " %s", item->sub[i]->name);
3784 }
3785 r_strbuf_append (buf, " \n");
3786 }
3787 return buf;
3788 }
3789
__update_menu_contents(RCore * core,RPanelsMenu * menu,RPanelsMenuItem * parent)3790 static void __update_menu_contents(RCore *core, RPanelsMenu *menu, RPanelsMenuItem *parent) {
3791 RPanel *p = parent->p;
3792 RStrBuf *buf = __draw_menu (core, parent);
3793 if (!buf) {
3794 return;
3795 }
3796 free (p->model->title);
3797 p->model->title = r_strbuf_drain (buf);
3798 int new_w = r_str_bounds (p->model->title, &p->view->pos.h);
3799 p->view->pos.w = new_w;
3800 p->view->pos.h += 4;
3801 p->model->type = PANEL_TYPE_MENU;
3802 p->view->refresh = true;
3803 menu->refreshPanels[menu->n_refresh - 1] = p;
3804 }
3805
__handle_mouse_on_menu(RCore * core,int x,int y)3806 static void __handle_mouse_on_menu(RCore *core, int x, int y) {
3807 RPanels *panels = core->panels;
3808 char *word = __get_word_from_canvas_for_menu (core, panels, x, y);
3809 RPanelsMenu *menu = panels->panels_menu;
3810 int i, d = menu->depth - 1;
3811 while (d) {
3812 RPanelsMenuItem *parent = menu->history[d--];
3813 for (i = 0; i < parent->n_sub; i++) {
3814 if (!strcmp (word, parent->sub[i]->name)) {
3815 parent->selectedIndex = i;
3816 (void)(parent->sub[parent->selectedIndex]->cb (core));
3817 __update_menu_contents (core, menu, parent);
3818 free (word);
3819 return;
3820 }
3821 }
3822 __del_menu (core);
3823 }
3824 __clear_panels_menu (core);
3825 __set_mode (core, PANEL_MODE_DEFAULT);
3826 __get_cur_panel (panels)->view->refresh = true;
3827 free (word);
3828 }
3829
__toggle_cache(RCore * core,RPanel * p)3830 static void __toggle_cache(RCore *core, RPanel *p) {
3831 p->model->cache = !p->model->cache;
3832 __set_cmd_str_cache (core, p, NULL);
3833 p->view->refresh = true;
3834 }
3835
__draw_modal(RCore * core,RModal * modal,int range_end,int start,const char * name)3836 static bool __draw_modal(RCore *core, RModal *modal, int range_end, int start, const char *name) {
3837 if (start < modal->offset) {
3838 return true;
3839 }
3840 if (start >= range_end) {
3841 return false;
3842 }
3843 if (start == modal->idx) {
3844 r_strbuf_appendf (modal->data, "> %s%s"Color_RESET, core->cons->context->pal.graph_box2, name);
3845 } else {
3846 r_strbuf_appendf (modal->data, " %s", name);
3847 }
3848 r_strbuf_append (modal->data, " \n");
3849 return true;
3850 }
3851
__update_modal(RCore * core,Sdb * menu_db,RModal * modal)3852 static void __update_modal(RCore *core, Sdb *menu_db, RModal *modal) {
3853 RPanels *panels = core->panels;
3854 RConsCanvas *can = panels->can;
3855 modal->data = r_strbuf_new (NULL);
3856 int count = sdb_count (menu_db);
3857 if (modal->idx >= count) {
3858 modal->idx = 0;
3859 modal->offset = 0;
3860 } else if (modal->idx >= modal->offset + modal->pos.h) {
3861 if (modal->offset + modal->pos.h >= count) {
3862 modal->offset = 0;
3863 modal->idx = 0;
3864 } else {
3865 modal->offset += 1;
3866 }
3867 } else if (modal->idx < 0) {
3868 modal->offset = R_MAX (count - modal->pos.h, 0);
3869 modal->idx = count - 1;
3870 } else if (modal->idx < modal->offset) {
3871 modal->offset -= 1;
3872 }
3873 SdbList *l = sdb_foreach_list (menu_db, true);
3874 SdbKv *kv;
3875 SdbListIter *iter;
3876 int i = 0;
3877 int max_h = R_MIN (modal->offset + modal->pos.h, count);
3878 ls_foreach (l, iter, kv) {
3879 if (__draw_modal (core, modal, max_h, i, sdbkv_key (kv))) {
3880 i++;
3881 }
3882 }
3883 r_cons_gotoxy (0, 0);
3884 r_cons_canvas_fill (can, modal->pos.x, modal->pos.y, modal->pos.w + 2, modal->pos.h + 2, ' ');
3885 (void)r_cons_canvas_gotoxy (can, modal->pos.x + 2, modal->pos.y + 1);
3886 r_cons_canvas_write (can, r_strbuf_get (modal->data));
3887 r_strbuf_free (modal->data);
3888
3889 r_cons_canvas_box (can, modal->pos.x, modal->pos.y, modal->pos.w + 2, modal->pos.h + 2, core->cons->context->pal.graph_box2);
3890
3891 r_cons_canvas_print (can);
3892 r_cons_flush ();
3893 show_cursor (core);
3894 }
3895
__exec_modal(RCore * core,RPanel * panel,RModal * modal,Sdb * menu_db,RPanelLayout dir)3896 static void __exec_modal(RCore *core, RPanel *panel, RModal *modal, Sdb *menu_db, RPanelLayout dir) {
3897 SdbList *l = sdb_foreach_list (menu_db, true);
3898 SdbKv *kv;
3899 SdbListIter *iter;
3900 int i = 0;
3901 ls_foreach (l, iter, kv) {
3902 if (i++ == modal->idx) {
3903 RPanelAlmightyCallback cb = sdb_ptr_get (menu_db, sdbkv_key (kv), 0);
3904 cb (core, panel, dir, sdbkv_key (kv));
3905 break;
3906 }
3907 }
3908 }
3909
__delete_modal(RCore * core,RModal * modal,Sdb * menu_db)3910 static void __delete_modal(RCore *core, RModal *modal, Sdb *menu_db) {
3911 SdbList *l = sdb_foreach_list (menu_db, true);
3912 SdbKv *kv;
3913 SdbListIter *iter;
3914 int i = 0;
3915 ls_foreach (l, iter, kv) {
3916 if (i++ == modal->idx) {
3917 sdb_remove (menu_db, sdbkv_key (kv), 0);
3918 }
3919 }
3920 }
3921
__init_modal(void)3922 static RModal *__init_modal(void) {
3923 RModal *modal = R_NEW0 (RModal);
3924 if (modal) {
3925 __set_pos (&modal->pos, 0, 0);
3926 modal->idx = 0;
3927 modal->offset = 0;
3928 }
3929 return modal;
3930 }
3931
__free_modal(RModal ** modal)3932 static void __free_modal(RModal **modal) {
3933 free (*modal);
3934 *modal = NULL;
3935 }
3936
__create_modal(RCore * core,RPanel * panel,Sdb * menu_db)3937 static void __create_modal(RCore *core, RPanel *panel, Sdb *menu_db) {
3938 __set_cursor (core, false);
3939 const int w = 40;
3940 const int h = 20;
3941 const int x = (core->panels->can->w - w) / 2;
3942 const int y = (core->panels->can->h - h) / 2;
3943 RModal *modal = __init_modal ();
3944 __set_geometry (&modal->pos, x, y, w, h);
3945 int okey, key, cx, cy;
3946 char *word = NULL;
3947 __update_modal (core, menu_db, modal);
3948 while (modal) {
3949 okey = r_cons_readchar ();
3950 key = r_cons_arrow_to_hjkl (okey);
3951 word = NULL;
3952 if (key == INT8_MAX - 1) {
3953 if (r_cons_get_click (&cx, &cy)) {
3954 if ((cx < x || x + w < cx) || ((cy < y || y + h < cy))) {
3955 key = 'q';
3956 } else {
3957 word = __get_word_from_canvas_for_menu (core, core->panels, cx, cy);
3958 if (word) {
3959 void *cb = sdb_ptr_get (menu_db, word, 0);
3960 if (cb) {
3961 ((RPanelAlmightyCallback)cb) (core, panel, PANEL_LAYOUT_NONE, word);
3962 __free_modal (&modal);
3963 free (word);
3964 break;
3965 }
3966 free (word);
3967 }
3968 }
3969 }
3970 }
3971 switch (key) {
3972 case 'e':
3973 {
3974 __free_modal (&modal);
3975 char *cmd = __show_status_input (core, "New command: ");
3976 if (R_STR_ISNOTEMPTY (cmd)) {
3977 __replace_cmd (core, cmd, cmd);
3978 }
3979 free (cmd);
3980 }
3981 break;
3982 case 'j':
3983 modal->idx++;
3984 __update_modal (core, menu_db, modal);
3985 break;
3986 case 'k':
3987 modal->idx--;
3988 __update_modal (core, menu_db, modal);
3989 break;
3990 case 'v':
3991 __exec_modal (core, panel, modal, menu_db, PANEL_LAYOUT_VERTICAL);
3992 __free_modal (&modal);
3993 break;
3994 case 'h':
3995 __exec_modal (core, panel, modal, menu_db, PANEL_LAYOUT_HORIZONTAL);
3996 __free_modal (&modal);
3997 break;
3998 case 0x0d:
3999 __exec_modal (core, panel, modal, menu_db, PANEL_LAYOUT_NONE);
4000 __free_modal (&modal);
4001 break;
4002 case '-':
4003 __delete_modal (core, modal, menu_db);
4004 __update_modal (core, menu_db, modal);
4005 break;
4006 case 'q':
4007 case '"':
4008 __free_modal (&modal);
4009 break;
4010 }
4011 }
4012 }
4013
__handle_mouse_on_X(RCore * core,int x,int y)4014 static bool __handle_mouse_on_X(RCore *core, int x, int y) {
4015 RPanels *panels = core->panels;
4016 const int idx = __get_panel_idx_in_pos (core, x, y);
4017 char *word = __get_word_from_canvas (core, panels, x, y);
4018 if (idx == -1) {
4019 return false;
4020 }
4021 RPanel *ppos = __get_panel(panels, idx);
4022 const int TITLE_Y = ppos->view->pos.y + 2;
4023 if (y == TITLE_Y && strcmp (word, " X ")) {
4024 int fx = ppos->view->pos.x;
4025 int fX = fx + ppos->view->pos.w;
4026 __set_curnode (core, idx);
4027 __set_refresh_all (core, true, true);
4028 if (x > (fX - 13) && x < fX) {
4029 __toggle_cache (core, __get_cur_panel (panels));
4030 } else if (x > fx && x < (fx + 5)) {
4031 __dismantle_del_panel (core, ppos, idx);
4032 } else {
4033 __create_modal (core, __get_panel (panels, 0), panels->modal_db);
4034 __set_mode (core, PANEL_MODE_DEFAULT);
4035 }
4036 free (word);
4037 return true;
4038 }
4039 free (word);
4040 return false;
4041 }
4042
__seek_all(RCore * core,ut64 addr)4043 static void __seek_all(RCore *core, ut64 addr) {
4044 RPanels *panels = core->panels;
4045 int i;
4046 for (i = 0; i < panels->n_panels; i++) {
4047 RPanel *panel = __get_panel (panels, i);
4048 panel->model->addr = addr;
4049 }
4050 }
4051
__handle_mouse_on_panel(RCore * core,RPanel * panel,int x,int y,int * key)4052 static bool __handle_mouse_on_panel(RCore *core, RPanel *panel, int x, int y, int *key) {
4053 RPanels *panels = core->panels;
4054 int h;
4055 (void)r_cons_get_size (&h);
4056 const int idx = __get_panel_idx_in_pos (core, x, y);
4057 char *word = __get_word_from_canvas (core, panels, x, y);
4058 if (idx == -1) {
4059 return false;
4060 }
4061 __set_curnode (core, idx);
4062 __set_refresh_all (core, true, true);
4063 RPanel *ppos = __get_panel(panels, idx);
4064 if (word) {
4065 const ut64 addr = r_num_math (core->num, word);
4066 if (__check_panel_type (panel, PANEL_CMD_FUNCTION) &&
4067 __check_if_addr (word, strlen (word))) {
4068 r_core_seek (core, addr, true);
4069 __set_addr_by_type (core, PANEL_CMD_DISASSEMBLY, addr);
4070 }
4071 r_flag_set (core->flags, "panel.addr", addr, 1);
4072 r_config_set (core->config, "scr.highlight", word);
4073 {
4074 ut64 addr = r_num_math (core->num, word);
4075 if (addr > 0) {
4076 // TODO implement proper panel offset sync
4077 // __set_panel_addr (core, cur, addr);
4078 __seek_all (core, addr);
4079 }
4080 }
4081 free (word);
4082 }
4083 if (x >= ppos->view->pos.x && x < ppos->view->pos.x + 4) {
4084 *key = 'c';
4085 return false;
4086 }
4087 return true;
4088 }
4089
__handle_mouse(RCore * core,RPanel * panel,int * key)4090 static bool __handle_mouse(RCore *core, RPanel *panel, int *key) {
4091 RPanels *panels = core->panels;
4092 if (__drag_and_resize (core)) {
4093 return true;
4094 }
4095 if (key && !*key) {
4096 int x, y;
4097 if (!r_cons_get_click (&x, &y)) {
4098 return false;
4099 }
4100 if (y == MENU_Y && __handle_mouse_on_top (core, x, y)) {
4101 return true;
4102 }
4103 if (panels->mode == PANEL_MODE_MENU) {
4104 __handle_mouse_on_menu (core, x, y);
4105 return true;
4106 }
4107 if (__handle_mouse_on_X (core, x, y)) {
4108 return true;
4109 }
4110 if (__check_if_mouse_x_illegal (core, x) || __check_if_mouse_y_illegal (core, y)) {
4111 panels->mouse_on_edge_x = false;
4112 panels->mouse_on_edge_y = false;
4113 return true;
4114 }
4115 panels->mouse_on_edge_x = __check_if_mouse_x_on_edge (core, x, y);
4116 panels->mouse_on_edge_y = __check_if_mouse_y_on_edge (core, x, y);
4117 if (panels->mouse_on_edge_x || panels->mouse_on_edge_y) {
4118 return true;
4119 }
4120 if (__handle_mouse_on_panel (core, panel, x, y, key)) {
4121 return true;
4122 }
4123 int h, w = r_cons_get_size (&h);
4124 if (y == h) {
4125 RPanel *p = __get_cur_panel (panels);
4126 __split_panel_horizontal (core, p, p->model->title, p->model->cmd);
4127 } else if (x == w) {
4128 RPanel *p = __get_cur_panel (panels);
4129 __split_panel_vertical (core, p, p->model->title, p->model->cmd);
4130 }
4131 }
4132 if (key && *key == INT8_MAX) {
4133 *key = '"';
4134 return false;
4135 }
4136 return false;
4137 }
4138
__add_visual_mark(RCore * core)4139 static void __add_visual_mark(RCore *core) {
4140 char *msg = r_str_newf (R_CONS_CLEAR_LINE"Set shortcut key for 0x%"PFMT64x": ", core->offset);
4141 int ch = __show_status (core, msg);
4142 free (msg);
4143 r_core_visual_mark (core, ch);
4144 }
4145
__handle_visual_mark(RCore * core)4146 static void __handle_visual_mark(RCore *core) {
4147 RPanel *cur = __get_cur_panel (core->panels);
4148 if (!__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
4149 return;
4150 }
4151 int act = __show_status (core, "Visual Mark s:set -:remove \':use: ");
4152 switch (act) {
4153 case 's':
4154 __add_visual_mark (core);
4155 break;
4156 case '-':
4157 r_cons_gotoxy (0, 0);
4158 if (r_core_visual_mark_dump (core)) {
4159 r_cons_printf (R_CONS_CLEAR_LINE"Remove a shortcut key from the list\n");
4160 r_cons_flush ();
4161 int ch = r_cons_readchar ();
4162 r_core_visual_mark_del (core, ch);
4163 }
4164 break;
4165 case '\'':
4166 r_cons_gotoxy (0, 0);
4167 if (r_core_visual_mark_dump (core)) {
4168 r_cons_flush ();
4169 int ch = r_cons_readchar ();
4170 r_core_visual_mark_seek (core, ch);
4171 __set_panel_addr (core, cur, core->offset);
4172 }
4173 }
4174 }
4175
__move_panel_to_left(RCore * core,RPanel * panel,int src)4176 static void __move_panel_to_left(RCore *core, RPanel *panel, int src) {
4177 RPanels *panels = core->panels;
4178 __shrink_panels_backward (core, src);
4179 panels->panel[0] = panel;
4180 int h, w = r_cons_get_size (&h);
4181 int p_w = w - panels->columnWidth;
4182 p_w /= 2;
4183 int new_w = w - p_w;
4184 __set_geometry (&panel->view->pos, 0, 1, p_w + 1, h - 1);
4185 int i = 1;
4186 for (; i < panels->n_panels; i++) {
4187 RPanel *tmp = __get_panel (panels, i);
4188 int t_x = ((double)tmp->view->pos.x / (double)w) * (double)new_w + p_w;
4189 int t_w = ((double)tmp->view->pos.w / (double)w) * (double)new_w + 1;
4190 __set_geometry (&tmp->view->pos, t_x, tmp->view->pos.y, t_w, tmp->view->pos.h);
4191 }
4192 __fix_layout (core);
4193 __set_curnode (core, 0);
4194 }
4195
__move_panel_to_right(RCore * core,RPanel * panel,int src)4196 static void __move_panel_to_right(RCore *core, RPanel *panel, int src) {
4197 RPanels *panels = core->panels;
4198 __shrink_panels_forward (core, src);
4199 panels->panel[panels->n_panels - 1] = panel;
4200 int h, w = r_cons_get_size (&h);
4201 int p_w = w - panels->columnWidth;
4202 p_w /= 2;
4203 int p_x = w - p_w;
4204 __set_geometry (&panel->view->pos, p_x - 1, 1, p_w + 1, h - 1);
4205 int new_w = w - p_w;
4206 int i = 0;
4207 for (; i < panels->n_panels - 1; i++) {
4208 RPanel *tmp = __get_panel (panels, i);
4209 int t_x = ((double)tmp->view->pos.x / (double)w) * (double)new_w;
4210 int t_w = ((double)tmp->view->pos.w / (double)w) * (double)new_w + 1;
4211 __set_geometry (&tmp->view->pos, t_x, tmp->view->pos.y, t_w, tmp->view->pos.h);
4212 }
4213 __fix_layout (core);
4214 __set_curnode (core, panels->n_panels - 1);
4215 }
4216
__move_panel_to_up(RCore * core,RPanel * panel,int src)4217 static void __move_panel_to_up(RCore *core, RPanel *panel, int src) {
4218 RPanels *panels = core->panels;
4219 __shrink_panels_backward (core, src);
4220 panels->panel[0] = panel;
4221 int h, w = r_cons_get_size (&h);
4222 int p_h = h / 2;
4223 int new_h = h - p_h;
4224 __set_geometry (&panel->view->pos, 0, 1, w, p_h - 1);
4225 int i = 1;
4226 for (; i < panels->n_panels; i++) {
4227 RPanel *tmp = __get_panel (panels, i);
4228 int t_y = ((double)tmp->view->pos.y / (double)h) * (double)new_h + p_h;
4229 int t_h = ((double)tmp->view->pos.h / (double)h) * (double)new_h + 1;
4230 __set_geometry (&tmp->view->pos, tmp->view->pos.x, t_y, tmp->view->pos.w, t_h);
4231 }
4232 __fix_layout (core);
4233 __set_curnode (core, 0);
4234 }
4235
__move_panel_to_down(RCore * core,RPanel * panel,int src)4236 static void __move_panel_to_down(RCore *core, RPanel *panel, int src) {
4237 RPanels *panels = core->panels;
4238 __shrink_panels_forward (core, src);
4239 panels->panel[panels->n_panels - 1] = panel;
4240 int h, w = r_cons_get_size (&h);
4241 int p_h = h / 2;
4242 int new_h = h - p_h;
4243 __set_geometry (&panel->view->pos, 0, new_h, w, p_h);
4244 size_t i = 0;
4245 for (; i < panels->n_panels - 1; i++) {
4246 RPanel *tmp = __get_panel (panels, i);
4247 const size_t t_y = (tmp->view->pos.y * new_h / h) + 1;
4248 const size_t t_h = (tmp->view->edge & (1 << PANEL_EDGE_BOTTOM)) ? new_h - t_y : (tmp->view->pos.h * new_h / h) ;
4249 __set_geometry (&tmp->view->pos, tmp->view->pos.x, t_y, tmp->view->pos.w, t_h);
4250 }
4251 __fix_layout (core);
4252 __set_curnode (core, panels->n_panels - 1);
4253 }
4254
__move_panel_to_dir(RCore * core,RPanel * panel,int src)4255 static void __move_panel_to_dir(RCore *core, RPanel *panel, int src) {
4256 RPanels *panels = core->panels;
4257 __dismantle_panel (panels, panel);
4258 int key = __show_status (core, "Move the current panel to direction (h/j/k/l): ");
4259 key = r_cons_arrow_to_hjkl (key);
4260 __set_refresh_all (core, false, true);
4261 switch (key) {
4262 case 'h':
4263 __move_panel_to_left (core, panel, src);
4264 break;
4265 case 'l':
4266 __move_panel_to_right (core, panel, src);
4267 break;
4268 case 'k':
4269 __move_panel_to_up (core, panel, src);
4270 break;
4271 case 'j':
4272 __move_panel_to_down (core, panel, src);
4273 break;
4274 default:
4275 break;
4276 }
4277 }
4278
__set_dcb(RCore * core,RPanel * p)4279 static void __set_dcb(RCore *core, RPanel *p) {
4280 if (__is_abnormal_cursor_type (core, p)) {
4281 p->model->cache = true;
4282 p->model->directionCb = __direction_panels_cursor_cb;
4283 return;
4284 }
4285 if ((p->model->cache && p->model->cmdStrCache) || p->model->readOnly) {
4286 p->model->directionCb = __direction_default_cb;
4287 return;
4288 }
4289 if (!p->model->cmd) {
4290 return;
4291 }
4292 if (__check_panel_type (p, PANEL_CMD_GRAPH)) {
4293 p->model->directionCb = __direction_graph_cb;
4294 return;
4295 }
4296 if (__check_panel_type (p, PANEL_CMD_STACK)) {
4297 p->model->directionCb = __direction_stack_cb;
4298 } else if (__check_panel_type (p, PANEL_CMD_DISASSEMBLY)) {
4299 p->model->directionCb = __direction_disassembly_cb;
4300 } else if (__check_panel_type (p, PANEL_CMD_REGISTERS)) {
4301 p->model->directionCb = __direction_register_cb;
4302 } else if (__check_panel_type (p, PANEL_CMD_HEXDUMP)) {
4303 p->model->directionCb = __direction_hexdump_cb;
4304 } else {
4305 p->model->directionCb = __direction_default_cb;
4306 }
4307 }
4308
__swap_panels(RPanels * panels,int p0,int p1)4309 static void __swap_panels(RPanels *panels, int p0, int p1) {
4310 RPanel *panel0 = __get_panel (panels, p0);
4311 RPanel *panel1 = __get_panel (panels, p1);
4312 RPanelModel *tmp = panel0->model;
4313
4314 panel0->model = panel1->model;
4315 panel1->model = tmp;
4316 }
4317
__check_func(RCore * core)4318 static bool __check_func(RCore *core) {
4319 RAnalFunction *fun = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
4320 if (!fun) {
4321 r_cons_message ("Not in a function. Type 'df' to define it here");
4322 return false;
4323 }
4324 if (r_list_empty (fun->bbs)) {
4325 r_cons_message ("No basic blocks in this function. You may want to use 'afb+'.");
4326 return false;
4327 }
4328 return true;
4329 }
4330
__call_visual_graph(RCore * core)4331 static void __call_visual_graph(RCore *core) {
4332 if (__check_func (core)) {
4333 RPanels *panels = core->panels;
4334
4335 r_cons_canvas_free (panels->can);
4336 panels->can = NULL;
4337
4338 int ocolor = r_config_get_i (core->config, "scr.color");
4339
4340 r_core_visual_graph (core, NULL, NULL, true);
4341 r_config_set_i (core->config, "scr.color", ocolor);
4342
4343 int h, w = r_cons_get_size (&h);
4344 panels->can = __create_new_canvas (core, w, h);
4345 }
4346 }
4347
__check_func_diff(RCore * core,RPanel * p)4348 static bool __check_func_diff(RCore *core, RPanel *p) {
4349 RAnalFunction *func = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
4350 if (!func) {
4351 if (R_STR_ISEMPTY (p->model->funcName)) {
4352 return false;
4353 }
4354 p->model->funcName = NULL;
4355 return true;
4356 }
4357 if (!p->model->funcName || strcmp (p->model->funcName, func->name)) {
4358 p->model->funcName = r_str_dup (p->model->funcName, func->name);
4359 return true;
4360 }
4361 return false;
4362 }
4363
__print_default_cb(void * user,void * p)4364 static void __print_default_cb(void *user, void *p) {
4365 RCore *core = (RCore *)user;
4366 RPanel *panel = (RPanel *)p;
4367 bool update = core->panels->autoUpdate && __check_func_diff (core, panel);
4368 char *cmdstr = __find_cmd_str_cache (core, panel);
4369 if (update || !cmdstr) {
4370 cmdstr = __handle_cmd_str_cache (core, panel, false);
4371 if (panel->model->cache && panel->model->cmdStrCache) {
4372 __reset_scroll_pos (panel);
4373 }
4374 }
4375 __update_panel_contents (core, panel, cmdstr);
4376 }
4377
__print_decompiler_cb(void * user,void * p)4378 static void __print_decompiler_cb(void *user, void *p) {
4379 //TODO: Refactoring
4380 //TODO: Also, __check_func_diff should use addr not name
4381 RCore *core = (RCore *)user;
4382 RPanel *panel = (RPanel *)p;
4383 bool update = core->panels->autoUpdate && __check_func_diff (core, panel);
4384 char *cmdstr = NULL;
4385 if (!update) {
4386 cmdstr = __find_cmd_str_cache (core, panel);
4387 if (cmdstr) {
4388 __update_pdc_contents (core, panel, cmdstr);
4389 }
4390 return;
4391 }
4392 RAnalFunction *func = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
4393 if (func && core->panels_root->cur_pdc_cache) {
4394 cmdstr = r_str_new ((char *)sdb_ptr_get (core->panels_root->cur_pdc_cache,
4395 r_num_as_string (NULL, func->addr, false), 0));
4396 if (cmdstr) {
4397 __set_cmd_str_cache (core, panel, cmdstr);
4398 __reset_scroll_pos (panel);
4399 __update_pdc_contents (core, panel, cmdstr);
4400 return;
4401 }
4402 }
4403 cmdstr = __handle_cmd_str_cache (core, panel, false);
4404 if (cmdstr) {
4405 __reset_scroll_pos (panel);
4406 __set_decompiler_cache (core, cmdstr);
4407 __update_pdc_contents (core, panel, cmdstr);
4408 }
4409 }
4410
__print_disasmsummary_cb(void * user,void * p)4411 static void __print_disasmsummary_cb (void *user, void *p) {
4412 RCore *core = (RCore *)user;
4413 RPanel *panel = (RPanel *)p;
4414 bool update = core->panels->autoUpdate && __check_func_diff (core, panel);
4415 char *cmdstr = __find_cmd_str_cache (core, panel);
4416 if (update || !cmdstr) {
4417 cmdstr = __handle_cmd_str_cache (core, panel, true);
4418 if (panel->model->cache && panel->model->cmdStrCache) {
4419 __reset_scroll_pos (panel);
4420 }
4421 }
4422 __update_panel_contents (core, panel, cmdstr);
4423 }
4424
__print_disassembly_cb(void * user,void * p)4425 static void __print_disassembly_cb(void *user, void *p) {
4426 RCore *core = (RCore *)user;
4427 RPanel *panel = (RPanel *)p;
4428 core->print->screen_bounds = 1LL;
4429 char *cmdstr = __find_cmd_str_cache (core, panel);
4430 if (cmdstr) {
4431 __update_panel_contents (core, panel, cmdstr);
4432 return;
4433 }
4434 char *ocmd = panel->model->cmd;
4435 panel->model->cmd = r_str_newf ("%s %d", panel->model->cmd, panel->view->pos.h - 3);
4436 ut64 o_offset = core->offset;
4437 core->offset = panel->model->addr;
4438 r_core_seek (core, panel->model->addr, true);
4439 if (r_config_get_i (core->config, "cfg.debug")) {
4440 r_core_cmd (core, ".dr*", 0);
4441 }
4442 cmdstr = __handle_cmd_str_cache (core, panel, false);
4443 core->offset = o_offset;
4444 free (panel->model->cmd);
4445 panel->model->cmd = ocmd;
4446 __update_panel_contents (core, panel, cmdstr);
4447 }
4448
__do_panels_refresh(RCore * core)4449 static void __do_panels_refresh(RCore *core) {
4450 if (core->panels) {
4451 __panel_all_clear (core->panels);
4452 __panels_layout_refresh (core);
4453 }
4454 }
4455
__do_panels_resize(RCore * core)4456 static void __do_panels_resize(RCore *core) {
4457 RPanels *panels = core->panels;
4458 int i;
4459 int h, w = r_cons_get_size (&h);
4460 for (i = 0; i < panels->n_panels; i++) {
4461 RPanel *panel = __get_panel (panels, i);
4462 if ((panel->view->edge & (1 << PANEL_EDGE_BOTTOM))
4463 && (panel->view->pos.y + panel->view->pos.h < h)) {
4464 panel->view->pos.h = h - panel->view->pos.y;
4465 }
4466 if ((panel->view->edge & (1 << PANEL_EDGE_RIGHT))
4467 && (panel->view->pos.x + panel->view->pos.w < w)) {
4468 panel->view->pos.w = w - panel->view->pos.x;
4469 }
4470 }
4471 __do_panels_refresh (core);
4472 }
4473
__do_panels_refreshOneShot(RCore * core)4474 static void __do_panels_refreshOneShot(RCore *core) {
4475 r_core_task_enqueue_oneshot (&core->tasks, (RCoreTaskOneShot) __do_panels_resize, core);
4476 }
4477
__print_graph_cb(void * user,void * p)4478 static void __print_graph_cb(void *user, void *p) {
4479 RCore *core = (RCore *)user;
4480 RPanel *panel = (RPanel *)p;
4481 bool update = core->panels->autoUpdate && __check_func_diff (core, panel);
4482 char *cmdstr = __find_cmd_str_cache (core, panel);
4483 if (update || !cmdstr) {
4484 cmdstr = __handle_cmd_str_cache (core, panel, false);
4485 }
4486 core->cons->event_resize = NULL;
4487 core->cons->event_data = core;
4488 core->cons->event_resize = (RConsEvent) __do_panels_refreshOneShot;
4489 __update_panel_contents (core, panel, cmdstr);
4490 }
4491
__print_stack_cb(void * user,void * p)4492 static void __print_stack_cb(void *user, void *p) {
4493 RCore *core = (RCore *)user;
4494 RPanel *panel = (RPanel *)p;
4495 const int delta = r_config_get_i (core->config, "stack.delta");
4496 const int bits = r_config_get_i (core->config, "asm.bits");
4497 const char sign = (delta < 0)? '+': '-';
4498 const int absdelta = R_ABS (delta);
4499 char *cmd = r_str_newf ("%s%s ", PANEL_CMD_STACK, bits == 32 ? "w" : "q");
4500 int n = r_str_split (panel->model->cmd, ' ');
4501 int i;
4502 for (i = 0; i < n; i++) {
4503 const char *s = r_str_word_get0 (panel->model->cmd, i);
4504 if (!i) {
4505 continue;
4506 }
4507 cmd = r_str_append (cmd, s);
4508 }
4509 panel->model->cmd = cmd;
4510 const char *cmdstr = r_core_cmd_str (core, r_str_newf ("%s%c%d", cmd, sign, absdelta));
4511 __update_panel_contents (core, panel, cmdstr);
4512 }
4513
__print_hexdump_cb(void * user,void * p)4514 static void __print_hexdump_cb(void *user, void *p) {
4515 RCore *core = (RCore *)user;
4516 RPanel *panel = (RPanel *)p;
4517 char *cmdstr = __find_cmd_str_cache (core, panel);
4518 if (!cmdstr) {
4519 ut64 o_offset = core->offset;
4520 if (!panel->model->cache) {
4521 core->offset = panel->model->addr;
4522 r_core_seek (core, core->offset, true);
4523 r_core_block_read (core);
4524 }
4525 char *base = hexdump_rotate[R_ABS(panel->model->rotate) % COUNT (hexdump_rotate)];
4526 char *cmd = r_str_newf ("%s ", base);
4527 int n = r_str_split (panel->model->cmd, ' ');
4528 int i;
4529 for (i = 0; i < n; i++) {
4530 const char *s = r_str_word_get0 (panel->model->cmd, i);
4531 if (!i) {
4532 continue;
4533 }
4534 cmd = r_str_append (cmd, s);
4535 }
4536 panel->model->cmd = cmd;
4537 cmdstr = __handle_cmd_str_cache (core, panel, false);
4538 core->offset = o_offset;
4539 }
4540 __update_panel_contents (core, panel, cmdstr);
4541 }
4542
__hudstuff(RCore * core)4543 static void __hudstuff(RCore *core) {
4544 RPanels *panels = core->panels;
4545 RPanel *cur = __get_cur_panel (panels);
4546 r_core_visual_hudstuff (core);
4547
4548 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
4549 __set_panel_addr (core, cur, core->offset);
4550 } else {
4551 int i;
4552 for (i = 0; i < panels->n_panels; i++) {
4553 RPanel *panel = __get_panel (panels, i);
4554 if (__check_panel_type (panel, PANEL_CMD_DISASSEMBLY)) {
4555 __set_panel_addr (core, panel, core->offset);
4556 break;
4557 }
4558 }
4559 }
4560 }
4561
__print_snow(RPanels * panels)4562 static void __print_snow(RPanels *panels) {
4563 if (!panels->snows) {
4564 panels->snows = r_list_newf (free);
4565 }
4566 RPanel *cur = __get_cur_panel (panels);
4567 int i, amount = r_num_rand (4);
4568 if (amount > 0) {
4569 for (i = 0; i < amount; i++) {
4570 RPanelsSnow *snow = R_NEW (RPanelsSnow);
4571 snow->x = r_num_rand (cur->view->pos.w) + cur->view->pos.x;
4572 snow->y = cur->view->pos.y;
4573 r_list_append (panels->snows, snow);
4574 }
4575 }
4576 RListIter *iter, *iter2;
4577 RPanelsSnow *snow;
4578 r_list_foreach_safe (panels->snows, iter, iter2, snow) {
4579 int pos = r_num_rand (3) - 1;
4580 snow->x += pos;
4581 snow->y++;
4582 if (snow->x >= cur->view->pos.w + cur->view->pos.x || snow->x <= cur->view->pos.x + 1) {
4583 r_list_delete (panels->snows, iter);
4584 continue;
4585 }
4586 if (snow->y >= cur->view->pos.h + cur->view->pos.y - 1) {
4587 r_list_delete (panels->snows, iter);
4588 continue;
4589 }
4590 if (r_cons_canvas_gotoxy (panels->can, snow->x, snow->y)) {
4591 if (panels->fun == PANEL_FUN_SAKURA) {
4592 r_cons_canvas_write (panels->can, Color_BMAGENTA","Color_RESET);
4593 } else {
4594 r_cons_canvas_write (panels->can, "*");
4595 }
4596 }
4597 }
4598 }
4599
__set_pcb(RPanel * p)4600 static void __set_pcb(RPanel *p) {
4601 if (!p->model->cmd) {
4602 return;
4603 }
4604 if (__check_panel_type (p, PANEL_CMD_DISASSEMBLY)) {
4605 p->model->print_cb = __print_disassembly_cb;
4606 return;
4607 }
4608 if (__check_panel_type (p, PANEL_CMD_STACK)) {
4609 p->model->print_cb = __print_stack_cb;
4610 return;
4611 }
4612 if (__check_panel_type (p, PANEL_CMD_HEXDUMP)) {
4613 p->model->print_cb = __print_hexdump_cb;
4614 return;
4615 }
4616 if (__check_panel_type (p, PANEL_CMD_DECOMPILER)) {
4617 p->model->print_cb = __print_decompiler_cb;
4618 return;
4619 }
4620 if (__check_panel_type (p, PANEL_CMD_GRAPH)) {
4621 p->model->print_cb = __print_graph_cb;
4622 return;
4623 }
4624 if (__check_panel_type (p, PANEL_CMD_TINYGRAPH)) {
4625 p->model->print_cb = __print_graph_cb;
4626 return;
4627 }
4628 if (__check_panel_type (p, PANEL_CMD_DISASMSUMMARY)) {
4629 p->model->print_cb = __print_disasmsummary_cb;
4630 return;
4631 }
4632 p->model->print_cb = __print_default_cb;
4633 }
4634
__file_history_up(RLine * line)4635 static int __file_history_up(RLine *line) {
4636 RCore *core = line->user;
4637 RList *files = r_id_storage_list (core->io->files);
4638 int num_files = r_list_length (files);
4639 if (line->file_hist_index >= num_files || line->file_hist_index < 0) {
4640 return false;
4641 }
4642 line->file_hist_index++;
4643 RIODesc *desc = r_list_get_n (files, num_files - line->file_hist_index);
4644 if (desc) {
4645 strncpy (line->buffer.data, desc->name, R_LINE_BUFSIZE - 1);
4646 line->buffer.index = line->buffer.length = strlen (line->buffer.data);
4647 }
4648 r_list_free (files);
4649 return true;
4650 }
4651
__file_history_down(RLine * line)4652 static int __file_history_down(RLine *line) {
4653 RCore *core = line->user;
4654 RList *files = r_id_storage_list (core->io->files);
4655 int num_files = r_list_length (files);
4656 if (line->file_hist_index <= 0 || line->file_hist_index > num_files) {
4657 return false;
4658 }
4659 line->file_hist_index--;
4660 if (line->file_hist_index <= 0) {
4661 line->buffer.data[0] = '\0';
4662 line->buffer.index = line->buffer.length = 0;
4663 return false;
4664 }
4665 RIODesc *desc = r_list_get_n (files, num_files - line->file_hist_index);
4666 if (desc) {
4667 strncpy (line->buffer.data, desc->name, R_LINE_BUFSIZE - 1);
4668 line->buffer.index = line->buffer.length = strlen (line->buffer.data);
4669 }
4670 r_list_free (files);
4671 return true;
4672 }
4673
4674
__open_file_cb(void * user)4675 static int __open_file_cb(void *user) {
4676 RCore *core = (RCore *)user;
4677 core->cons->line->prompt_type = R_LINE_PROMPT_FILE;
4678 r_line_set_hist_callback (core->cons->line, &__file_history_up, &__file_history_down);
4679 __add_cmdf_panel (core, "open file: ", "o %s");
4680 core->cons->line->prompt_type = R_LINE_PROMPT_DEFAULT;
4681 r_line_set_hist_callback (core->cons->line, &r_line_hist_cmd_up, &r_line_hist_cmd_down);
4682 return 0;
4683 }
4684
__rw_cb(void * user)4685 static int __rw_cb(void *user) {
4686 RCore *core = (RCore *)user;
4687 r_core_cmd (core, "oo+", 0);
4688 return 0;
4689 }
4690
__debugger_cb(void * user)4691 static int __debugger_cb(void *user) {
4692 RCore *core = (RCore *)user;
4693 r_core_cmd (core, "oo", 0);
4694 return 0;
4695 }
4696
__settings_decompiler_cb(void * user)4697 static int __settings_decompiler_cb(void *user) {
4698 RCore *core = (RCore *)user;
4699 RPanelsRoot *root = core->panels_root;
4700 RPanelsMenu *menu = core->panels->panels_menu;
4701 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
4702 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
4703 const char *pdc_next = child->name;
4704 const char *pdc_now = r_config_get (core->config, "cmd.pdc");
4705 if (!strcmp (pdc_next, pdc_now)) {
4706 return 0;
4707 }
4708 root->cur_pdc_cache = sdb_ptr_get (root->pdc_caches, pdc_next, 0);
4709 if (!root->cur_pdc_cache) {
4710 Sdb *sdb = sdb_new0 ();
4711 if (sdb) {
4712 sdb_ptr_set (root->pdc_caches, pdc_next, sdb, 0);
4713 root->cur_pdc_cache = sdb;
4714 }
4715 }
4716 r_config_set (core->config, "cmd.pdc", pdc_next);
4717 int j = 0;
4718 for (j = 0; j < core->panels->n_panels; j++) {
4719 RPanel *panel = __get_panel (core->panels, j);
4720 if (!strncmp (panel->model->cmd, "pdc", 3)) {
4721 char *cmdstr = r_core_cmd_strf (core, "pdc@0x%08"PFMT64x, panel->model->addr);
4722 __update_panel_contents (core, panel, cmdstr);
4723 __reset_scroll_pos (panel);
4724 free (cmdstr);
4725 }
4726 }
4727 __set_refresh_all (core, true, false);
4728 __set_mode (core, PANEL_MODE_DEFAULT);
4729 return 0;
4730 }
4731
__create_default_panels(RCore * core)4732 static void __create_default_panels(RCore *core) {
4733 RPanels *panels = core->panels;
4734 panels->n_panels = 0;
4735 __set_curnode (core, 0);
4736 const char **panels_list = panels_static;
4737 if (panels->layout == PANEL_LAYOUT_DEFAULT_DYNAMIC) {
4738 panels_list = panels_dynamic;
4739 }
4740
4741 int i = 0;
4742 while (panels_list[i]) {
4743 RPanel *p = __get_panel (panels, panels->n_panels);
4744 if (!p) {
4745 return;
4746 }
4747 const char *s = panels_list[i++];
4748 char *db_val = __search_db (core, s);
4749 __init_panel_param (core, p, s, db_val);
4750 free (db_val);
4751 }
4752 }
4753
__load_layout_saved_cb(void * user)4754 static int __load_layout_saved_cb(void *user) {
4755 RCore *core = (RCore *)user;
4756 RPanelsMenu *menu = core->panels->panels_menu;
4757 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
4758 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
4759 if (!r_core_panels_load (core, child->name)) {
4760 __create_default_panels (core);
4761 __panels_layout (core->panels);
4762 }
4763 __set_curnode (core, 0);
4764 core->panels->panels_menu->depth = 1;
4765 __set_mode (core, PANEL_MODE_DEFAULT);
4766 return 0;
4767 }
4768
__load_layout_default_cb(void * user)4769 static int __load_layout_default_cb(void *user) {
4770 RCore *core = (RCore *)user;
4771 __init_panels (core, core->panels);
4772 __create_default_panels (core);
4773 __panels_layout (core->panels);
4774 core->panels->panels_menu->depth = 1;
4775 __set_mode (core, PANEL_MODE_DEFAULT);
4776 return 0;
4777 }
4778
__close_file_cb(void * user)4779 static int __close_file_cb(void *user) {
4780 RCore *core = (RCore *)user;
4781 r_core_cmd0 (core, "o-*");
4782 return 0;
4783 }
4784
__save_layout_cb(void * user)4785 static int __save_layout_cb(void *user) {
4786 RCore *core = (RCore *)user;
4787 r_core_panels_save (core, NULL);
4788 __set_mode (core, PANEL_MODE_DEFAULT);
4789 __clear_panels_menu (core);
4790 __get_cur_panel (core->panels)->view->refresh = true;
4791 return 0;
4792 }
4793
__update_menu(RCore * core,const char * parent,R_NULLABLE RPanelMenuUpdateCallback cb)4794 static void __update_menu(RCore *core, const char *parent, R_NULLABLE RPanelMenuUpdateCallback cb) {
4795 RPanels *panels = core->panels;
4796 void *addr = ht_pp_find (panels->mht, parent, NULL);
4797 RPanelsMenuItem *p_item = (RPanelsMenuItem *)addr;
4798 int i;
4799 for (i = 0; i < p_item->n_sub; i++) {
4800 RPanelsMenuItem *sub = p_item->sub[i];
4801 ht_pp_delete (core->panels->mht, sdb_fmt ("%s.%s", parent, sub->name));
4802 }
4803 p_item->sub = NULL;
4804 p_item->n_sub = 0;
4805 if (cb) {
4806 cb (core, parent);
4807 }
4808 RPanelsMenu *menu = panels->panels_menu;
4809 __update_menu_contents (core, menu, p_item);
4810 }
4811
__get_panels_config_dir_path(void)4812 static char *__get_panels_config_dir_path(void) {
4813 return r_str_home (R_JOIN_2_PATHS (R2_HOME_DATADIR, ".r2panels"));
4814 }
4815
__add_menu(RCore * core,const char * parent,const char * name,RPanelsMenuCallback cb)4816 static void __add_menu(RCore *core, const char *parent, const char *name, RPanelsMenuCallback cb) {
4817 RPanels *panels = core->panels;
4818 RPanelsMenuItem *p_item, *item = R_NEW0 (RPanelsMenuItem);
4819 if (!item) {
4820 return;
4821 }
4822 if (parent) {
4823 void *addr = ht_pp_find (panels->mht, parent, NULL);
4824 p_item = (RPanelsMenuItem *)addr;
4825 ht_pp_insert (panels->mht, sdb_fmt ("%s.%s", parent, name), item);
4826 } else {
4827 p_item = panels->panels_menu->root;
4828 ht_pp_insert (panels->mht, sdb_fmt ("%s", name), item);
4829 }
4830 item->n_sub = 0;
4831 item->selectedIndex = 0;
4832 item->name = name ? r_str_new (name) : NULL;
4833 item->sub = NULL;
4834 item->cb = cb;
4835 item->p = R_NEW0 (RPanel);
4836 if (item->p) {
4837 item->p->model = R_NEW0 (RPanelModel);
4838 item->p->view = R_NEW0 (RPanelView);
4839 if (item->p->model && item->p->view) {
4840 p_item->n_sub++;
4841 RPanelsMenuItem **sub = realloc (p_item->sub, sizeof (RPanelsMenuItem *) * p_item->n_sub);
4842 if (sub) {
4843 p_item->sub = sub;
4844 p_item->sub[p_item->n_sub - 1] = item;
4845 item = NULL;
4846 }
4847 }
4848 }
4849 __free_menu_item (item);
4850 }
4851
__init_menu_saved_layout(void * _core,const char * parent)4852 static void __init_menu_saved_layout (void *_core, const char *parent) {
4853 char *dir_path = __get_panels_config_dir_path ();
4854 RList *dir = r_sys_dir (dir_path);
4855 if (!dir) {
4856 free (dir_path);
4857 return;
4858 }
4859 RCore *core = (RCore *)_core;
4860 RListIter *it;
4861 char *entry;
4862 r_list_foreach (dir, it, entry) {
4863 if (strcmp (entry, ".") && strcmp (entry, "..")) {
4864 __add_menu (core, parent, entry, __load_layout_saved_cb);
4865 }
4866 }
4867 r_list_free (dir);
4868 free (dir_path);
4869 }
4870
__clear_layout_cb(void * user)4871 static int __clear_layout_cb(void *user) {
4872 RCore *core = (RCore *)user;
4873 if (!__show_status_yesno (core, 0, "Clear all the saved layouts?(y/n): ")) {
4874 return 0;
4875 }
4876 char *dir_path = __get_panels_config_dir_path ();
4877 RList *dir = r_sys_dir ((const char *)dir_path);
4878 if (!dir) {
4879 free (dir_path);
4880 return 0;
4881 }
4882 RListIter *it;
4883 char *entry;
4884 r_list_foreach (dir, it, entry) {
4885 char *tmp = r_str_newf ("%s%s%s", dir_path, R_SYS_DIR, entry);
4886 r_file_rm (tmp);
4887 free (tmp);
4888 }
4889 r_file_rm (dir_path);
4890 r_list_free (dir);
4891 free (dir_path);
4892
4893 __update_menu (core, "File.Load Layout.Saved", __init_menu_saved_layout);
4894 return 0;
4895 }
4896
__copy_cb(void * user)4897 static int __copy_cb(void *user) {
4898 RCore *core = (RCore *)user;
4899 __add_cmdf_panel (core, "How many bytes? ", "\"y %s\"");
4900 return 0;
4901 }
4902
__paste_cb(void * user)4903 static int __paste_cb(void *user) {
4904 RCore *core = (RCore *)user;
4905 r_core_cmd0 (core, "yy");
4906 return 0;
4907 }
4908
__write_str_cb(void * user)4909 static int __write_str_cb(void *user) {
4910 RCore *core = (RCore *)user;
4911 __add_cmdf_panel (core, "insert string: ", "\"w %s\"");
4912 return 0;
4913 }
4914
__write_hex_cb(void * user)4915 static int __write_hex_cb(void *user) {
4916 RCore *core = (RCore *)user;
4917 __add_cmdf_panel (core, "insert hexpairs: ", "\"wx %s\"");
4918 return 0;
4919 }
4920
__assemble_cb(void * user)4921 static int __assemble_cb(void *user) {
4922 RCore *core = (RCore *)user;
4923 r_core_visual_asm (core, core->offset);
4924 return 0;
4925 }
4926
__fill_cb(void * user)4927 static int __fill_cb(void *user) {
4928 RCore *core = (RCore *)user;
4929 __add_cmdf_panel (core, "Fill with: ", "wow %s");
4930 return 0;
4931 }
4932
__settings_colors_cb(void * user)4933 static int __settings_colors_cb(void *user) {
4934 RCore *core = (RCore *)user;
4935 RPanelsMenu *menu = core->panels->panels_menu;
4936 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
4937 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
4938 r_str_ansi_filter (child->name, NULL, NULL, -1);
4939 r_core_cmdf (core, "eco %s", child->name);
4940 int i;
4941 for (i = 1; i < menu->depth; i++) {
4942 RPanel *p = menu->history[i]->p;
4943 p->view->refresh = true;
4944 menu->refreshPanels[i - 1] = p;
4945 }
4946 __update_menu(core, "Settings.Colors", __init_menu_color_settings_layout);
4947 return 0;
4948 }
4949
__config_value_cb(void * user)4950 static int __config_value_cb(void *user) {
4951 RCore *core = (RCore *)user;
4952 RPanelsMenu *menu = core->panels->panels_menu;
4953 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
4954 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
4955 RStrBuf *tmp = r_strbuf_new (child->name);
4956 (void)r_str_split (r_strbuf_get(tmp), ':');
4957 const char *v = __show_status_input (core, "New value: ");
4958 r_config_set (core->config, r_strbuf_get (tmp), v);
4959 r_strbuf_free (tmp);
4960 free (parent->p->model->title);
4961 parent->p->model->title = r_strbuf_drain (__draw_menu (core, parent));
4962 size_t i;
4963 for (i = 1; i < menu->depth; i++) {
4964 RPanel *p = menu->history[i]->p;
4965 p->view->refresh = true;
4966 menu->refreshPanels[i - 1] = p;
4967 }
4968 if (!strcmp (parent->name, "asm")) {
4969 __update_menu (core, "Settings.Disassembly.asm", __init_menu_disasm_asm_settings_layout);
4970 }
4971 if (!strcmp (parent->name, "Screen")) {
4972 __update_menu (core, "Settings.Screen", __init_menu_screen_settings_layout);
4973 }
4974 return 0;
4975 }
4976
__config_toggle_cb(void * user)4977 static int __config_toggle_cb(void *user) {
4978 RCore *core = (RCore *)user;
4979 RPanelsMenu *menu = core->panels->panels_menu;
4980 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
4981 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
4982 RStrBuf *tmp = r_strbuf_new (child->name);
4983 (void)r_str_split (r_strbuf_get (tmp), ':');
4984 r_config_toggle (core->config, r_strbuf_get (tmp));
4985 r_strbuf_free (tmp);
4986 free (parent->p->model->title);
4987 parent->p->model->title = r_strbuf_drain (__draw_menu (core, parent));
4988 size_t i;
4989 for (i = 1; i < menu->depth; i++) {
4990 RPanel *p = menu->history[i]->p;
4991 p->view->refresh = true;
4992 menu->refreshPanels[i - 1] = p;
4993 }
4994 if (!strcmp (parent->name, "asm")) {
4995 __update_menu (core, "Settings.Disassembly.asm", __init_menu_disasm_asm_settings_layout);
4996 }
4997 if (!strcmp (parent->name, "Screen")) {
4998 __update_menu (core, "Settings.Screen", __init_menu_screen_settings_layout);
4999 }
5000 return 0;
5001 }
5002
__init_menu_screen_settings_layout(void * _core,const char * parent)5003 static void __init_menu_screen_settings_layout(void *_core, const char *parent) {
5004 RCore *core = (RCore *)_core;
5005 RStrBuf *rsb = r_strbuf_new (NULL);
5006 int i = 0;
5007 while (menus_settings_screen[i]) {
5008 const char *menu = menus_settings_screen[i];
5009 r_strbuf_set (rsb, menu);
5010 r_strbuf_append (rsb, ": ");
5011 r_strbuf_append (rsb, r_config_get (core->config, menu));
5012 if (!strcmp (menus_settings_screen[i], "scr.color")) {
5013 __add_menu (core, parent, r_strbuf_get (rsb), __config_value_cb);
5014 } else {
5015 __add_menu (core, parent, r_strbuf_get (rsb), __config_toggle_cb);
5016 }
5017 i++;
5018 }
5019 r_strbuf_free (rsb);
5020 }
5021
__calculator_cb(void * user)5022 static int __calculator_cb(void *user) {
5023 RCore *core = (RCore *)user;
5024 for (;;) {
5025 char *s = __show_status_input (core, "> ");
5026 if (!s || !*s) {
5027 free (s);
5028 break;
5029 }
5030 r_core_cmdf (core, "? %s", s);
5031 r_cons_flush ();
5032 free (s);
5033 }
5034 return 0;
5035 }
5036
__r2_shell_cb(void * user)5037 static int __r2_shell_cb(void *user) {
5038 RCore *core = (RCore *)user;
5039 core->vmode = false;
5040 r_core_visual_prompt_input (core);
5041 core->vmode = true;
5042 return 0;
5043 }
5044
__system_shell_cb(void * user)5045 static int __system_shell_cb(void *user) {
5046 r_cons_set_raw (0);
5047 r_cons_flush ();
5048 r_sys_cmd ("$SHELL");
5049 return 0;
5050 }
5051
__string_whole_bin_cb(void * user)5052 static int __string_whole_bin_cb(void *user) {
5053 RCore *core = (RCore *)user;
5054 __add_cmdf_panel (core, "search strings in the whole binary: ", "izzq~%s");
5055 return 0;
5056 }
5057
__string_data_sec_cb(void * user)5058 static int __string_data_sec_cb(void *user) {
5059 RCore *core = (RCore *)user;
5060 __add_cmdf_panel (core, "search string in data sections: ", "izq~%s");
5061 return 0;
5062 }
5063
__rop_cb(void * user)5064 static int __rop_cb(void *user) {
5065 RCore *core = (RCore *)user;
5066 __add_cmdf_panel (core, "rop grep: ", "\"/R %s\"");
5067 return 0;
5068 }
5069
__code_cb(void * user)5070 static int __code_cb(void *user) {
5071 RCore *core = (RCore *)user;
5072 __add_cmdf_panel (core, "search code: ", "\"/c %s\"");
5073 return 0;
5074 }
5075
__hexpairs_cb(void * user)5076 static int __hexpairs_cb(void *user) {
5077 RCore *core = (RCore *)user;
5078 __add_cmdf_panel (core, "search hexpairs: ", "\"/x %s\"");
5079 return 0;
5080 }
5081
__esil_init(RCore * core)5082 static void __esil_init(RCore *core) {
5083 r_core_cmd (core, "aeim", 0);
5084 r_core_cmd (core, "aeip", 0);
5085 }
5086
__esil_step_to(RCore * core,ut64 end)5087 static void __esil_step_to(RCore *core, ut64 end) {
5088 r_core_cmdf (core, "aesu 0x%08"PFMT64x, end);
5089 }
5090
5091
__esil_init_cb(void * user)5092 static int __esil_init_cb(void *user) {
5093 RCore *core = (RCore *)user;
5094 __esil_init (core);
5095 return 0;
5096 }
5097
__esil_step_to_cb(void * user)5098 static int __esil_step_to_cb(void *user) {
5099 RCore *core = (RCore *)user;
5100 char *end = __show_status_input (core, "target addr: ");
5101 __esil_step_to (core, r_num_math (core->num, end));
5102 return 0;
5103 }
5104
__esil_step_range_cb(void * user)5105 static int __esil_step_range_cb(void *user) {
5106 RStrBuf *rsb = r_strbuf_new (NULL);
5107 RCore *core = (RCore *)user;
5108 r_strbuf_append (rsb, "start addr: ");
5109 char *s = __show_status_input (core, r_strbuf_get (rsb));
5110 r_strbuf_append (rsb, s);
5111 r_strbuf_append (rsb, " end addr: ");
5112 char *d = __show_status_input (core, r_strbuf_get (rsb));
5113 r_strbuf_free (rsb);
5114 ut64 s_a = r_num_math (core->num, s);
5115 ut64 d_a = r_num_math (core->num, d);
5116 if (s_a >= d_a) {
5117 return 0;
5118 }
5119 ut64 tmp = core->offset;
5120 core->offset = s_a;
5121 __esil_init (core);
5122 __esil_step_to (core, d_a);
5123 core->offset = tmp;
5124 return 0;
5125 }
5126
__io_cache_on_cb(void * user)5127 static int __io_cache_on_cb(void *user) {
5128 RCore *core = (RCore *)user;
5129 r_config_set_b (core->config, "io.cache", true);
5130 (void)__show_status (core, "io.cache is on");
5131 __set_mode (core, PANEL_MODE_DEFAULT);
5132 return 0;
5133 }
5134
__io_cache_off_cb(void * user)5135 static int __io_cache_off_cb(void *user) {
5136 RCore *core = (RCore *)user;
5137 r_config_set_b (core->config, "io.cache", false);
5138 (void)__show_status (core, "io.cache is off");
5139 __set_mode (core, PANEL_MODE_DEFAULT);
5140 return 0;
5141 }
5142
__reload_cb(void * user)5143 static int __reload_cb(void *user) {
5144 RCore *core = (RCore *)user;
5145 r_core_file_reopen_debug (core, "");
5146 __update_disassembly_or_open (core);
5147 return 0;
5148 }
5149
__function_cb(void * user)5150 static int __function_cb(void *user) {
5151 RCore *core = (RCore *)user;
5152 r_core_cmdf (core, "af");
5153 return 0;
5154 }
5155
__symbols_cb(void * user)5156 static int __symbols_cb(void *user) {
5157 RCore *core = (RCore *)user;
5158 r_core_cmdf (core, "aa");
5159 return 0;
5160 }
5161
__program_cb(void * user)5162 static int __program_cb(void *user) {
5163 RCore *core = (RCore *)user;
5164 r_core_cmdf (core, "aaa");
5165 return 0;
5166 }
5167
__basic_blocks_cb(void * user)5168 static int __basic_blocks_cb(void *user) {
5169 RCore *core = (RCore *)user;
5170 r_core_cmdf (core, "aab");
5171 return 0;
5172 }
5173
__calls_cb(void * user)5174 static int __calls_cb(void *user) {
5175 RCore *core = (RCore *)user;
5176 r_core_cmdf (core, "aac");
5177 return 0;
5178 }
5179
__watch_points_cb(void * user)5180 static int __watch_points_cb(void *user) {
5181 RCore *core = (RCore *)user;
5182 char addrBuf[128], rw[128];
5183 const char *addrPrompt = "addr: ", *rwPrompt = "<r/w/rw>: ";
5184 __panel_prompt (addrPrompt, addrBuf, sizeof (addrBuf));
5185 __panel_prompt (rwPrompt, rw, sizeof (rw));
5186 ut64 addr = r_num_math (core->num, addrBuf);
5187 r_core_cmdf (core, "dbw 0x%08"PFMT64x" %s", addr, rw);
5188 return 0;
5189 }
5190
__references_cb(void * user)5191 static int __references_cb(void *user) {
5192 RCore *core = (RCore *)user;
5193 r_core_cmdf (core, "aar");
5194 return 0;
5195 }
5196
__fortune_cb(void * user)5197 static int __fortune_cb(void *user) {
5198 RCore *core = (RCore *)user;
5199 char *s = r_core_cmd_str (core, "fo");
5200 r_cons_message (s);
5201 free (s);
5202 return 0;
5203 }
5204
__game_cb(void * user)5205 static int __game_cb(void *user) {
5206 RCore *core = (RCore *)user;
5207 r_cons_2048 (core->panels->can->color);
5208 return 0;
5209 }
5210
__help_cb(void * user)5211 static int __help_cb(void *user) {
5212 RCore *core = (RCore *)user;
5213 __toggle_help (core);
5214 return 0;
5215 }
5216
__license_cb(void * user)5217 static int __license_cb(void *user) {
5218 r_cons_message ("Copyright 2006-2020 - pancake - LGPL");
5219 return 0;
5220 }
5221
__version_cb(void * user)5222 static int __version_cb(void *user) {
5223 RCore *core = (RCore *)user;
5224 char *s = r_core_cmd_str (core, "?V");
5225 r_cons_message (s);
5226 free (s);
5227 return 0;
5228 }
5229
__writeValueCb(void * user)5230 static int __writeValueCb(void *user) {
5231 RCore *core = (RCore *)user;
5232 char *res = __show_status_input (core, "insert number: ");
5233 if (res) {
5234 r_core_cmdf (core, "\"wv %s\"", res);
5235 free (res);
5236 }
5237 return 0;
5238 }
5239
__quit_cb(void * user)5240 static int __quit_cb(void *user) {
5241 __set_root_state ((RCore *)user, QUIT);
5242 return 0;
5243 }
5244
__open_menu_cb(void * user)5245 static int __open_menu_cb (void *user) {
5246 RCore* core = (RCore *)user;
5247 RPanelsMenu *menu = core->panels->panels_menu;
5248 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
5249 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
5250 if (menu->depth < 2) {
5251 __set_pos (&child->p->view->pos, menu->root->selectedIndex * 6, 1);
5252 } else {
5253 RPanelsMenuItem *p = menu->history[menu->depth - 2];
5254 RPanelsMenuItem *parent2 = p->sub[p->selectedIndex];
5255 __set_pos (&child->p->view->pos, parent2->p->view->pos.x + parent2->p->view->pos.w - 1,
5256 menu->depth == 2 ? parent2->p->view->pos.y + parent2->selectedIndex : parent2->p->view->pos.y);
5257 }
5258 RStrBuf *buf = __draw_menu (core, child);
5259 if (!buf) {
5260 return 0;
5261 }
5262 free (child->p->model->title);
5263 child->p->model->title = r_strbuf_drain (buf);
5264 child->p->view->pos.w = r_str_bounds (child->p->model->title, &child->p->view->pos.h);
5265 child->p->view->pos.h += 4;
5266 child->p->model->type = PANEL_TYPE_MENU;
5267 child->p->view->refresh = true;
5268 menu->refreshPanels[menu->n_refresh++] = child->p;
5269 menu->history[menu->depth++] = child;
5270 return 0;
5271 }
5272
cmpstr(const void * _a,const void * _b)5273 static int cmpstr(const void *_a, const void *_b) {
5274 char *a = (char *)_a, *b = (char *)_b;
5275 return strcmp (a, b);
5276 }
5277
__sorted_list(RCore * core,const char * menu[],int count)5278 static RList *__sorted_list(RCore *core, const char *menu[], int count) {
5279 RList *list = r_list_newf (NULL);
5280 int i;
5281 for (i = 0; i < count; i++) {
5282 if (menu[i]) {
5283 (void)r_list_append (list, (void *)menu[i]);
5284 }
5285 }
5286 r_list_sort (list, cmpstr);
5287 return list;
5288 }
5289
__init_menu_color_settings_layout(void * _core,const char * parent)5290 static void __init_menu_color_settings_layout (void *_core, const char *parent) {
5291 RCore *core = (RCore *)_core;
5292 const char *color = core->cons->context->pal.graph_box2;
5293 char *now = r_core_cmd_str (core, "eco.");
5294 r_str_split (now, '\n');
5295 parent = "Settings.Colors";
5296 RList *list = __sorted_list (core, (const char **)menus_Colors, COUNT (menus_Colors));
5297 char *pos;
5298 RListIter* iter;
5299 RStrBuf *buf = r_strbuf_new (NULL);
5300 r_list_foreach (list, iter, pos) {
5301 if (pos && !strcmp (now, pos)) {
5302 r_strbuf_setf (buf, "%s%s", color, pos);
5303 __add_menu (core, parent, r_strbuf_get (buf), __settings_colors_cb);
5304 continue;
5305 }
5306 __add_menu (core, parent, pos, __settings_colors_cb);
5307 }
5308 free (now);
5309 r_list_free (list);
5310 r_strbuf_free (buf);
5311 }
5312
__init_menu_disasm_settings_layout(void * _core,const char * parent)5313 static void __init_menu_disasm_settings_layout (void *_core, const char *parent) {
5314 RCore *core = (RCore *)_core;
5315 int i = 0;
5316 RList *list = __sorted_list (core, menus_settings_disassembly, COUNT (menus_settings_disassembly));
5317 char *pos;
5318 RListIter* iter;
5319 RStrBuf *rsb = r_strbuf_new (NULL);
5320 r_list_foreach (list, iter, pos) {
5321 if (!strcmp (pos, "asm")) {
5322 __add_menu (core, parent, pos, __open_menu_cb);
5323 __init_menu_disasm_asm_settings_layout (core, "Settings.Disassembly.asm");
5324 } else {
5325 r_strbuf_set (rsb, pos);
5326 r_strbuf_append (rsb, ": ");
5327 r_strbuf_append (rsb, r_config_get (core->config, pos));
5328 __add_menu (core, parent, r_strbuf_get (rsb), __config_toggle_cb);
5329 }
5330 i++;
5331 }
5332 r_list_free (list);
5333 r_strbuf_free (rsb);
5334 }
5335
__init_menu_disasm_asm_settings_layout(void * _core,const char * parent)5336 static void __init_menu_disasm_asm_settings_layout(void *_core, const char *parent) {
5337 RCore *core = (RCore *)_core;
5338 RList *list = __sorted_list (core, menus_settings_disassembly_asm, COUNT (menus_settings_disassembly_asm));
5339 char *pos;
5340 RListIter* iter;
5341 RStrBuf *rsb = r_strbuf_new (NULL);
5342 r_list_foreach (list, iter, pos) {
5343 r_strbuf_set (rsb, pos);
5344 r_strbuf_append (rsb, ": ");
5345 r_strbuf_append (rsb, r_config_get (core->config, pos));
5346 if (!strcmp (pos, "asm.var.summary") ||
5347 !strcmp (pos, "asm.arch") ||
5348 !strcmp (pos, "asm.bits") ||
5349 !strcmp (pos, "asm.cpu")) {
5350 __add_menu (core, parent, r_strbuf_get (rsb), __config_value_cb);
5351 } else {
5352 __add_menu (core, parent, r_strbuf_get (rsb), __config_toggle_cb);
5353 }
5354 }
5355 r_list_free (list);
5356 r_strbuf_free (rsb);
5357 }
5358
__load_config_menu(RCore * core)5359 static void __load_config_menu(RCore *core) {
5360 RList *themes_list = r_core_list_themes (core);
5361 RListIter *th_iter;
5362 char *th;
5363 int i = 0;
5364 r_list_foreach (themes_list, th_iter, th) {
5365 menus_Colors[i++] = th;
5366 }
5367 }
5368
__init_panels_menu(RCore * core)5369 static bool __init_panels_menu(RCore *core) {
5370 RPanels *panels = core->panels;
5371 RPanelsMenu *panels_menu = R_NEW0 (RPanelsMenu);
5372 if (!panels_menu) {
5373 return false;
5374 }
5375 RPanelsMenuItem *root = R_NEW0 (RPanelsMenuItem);
5376 if (!root) {
5377 R_FREE (panels_menu);
5378 return false;
5379 }
5380 panels->panels_menu = panels_menu;
5381 panels_menu->root = root;
5382 root->n_sub = 0;
5383 root->name = NULL;
5384 root->sub = NULL;
5385
5386 __load_config_menu (core);
5387
5388 int i = 0;
5389 while (menus[i]) {
5390 __add_menu (core, NULL, menus[i], __open_menu_cb);
5391 i++;
5392 }
5393 char *parent = "File";
5394 i = 0;
5395 while (menus_File[i]) {
5396 if (!strcmp (menus_File[i], "Open")) {
5397 __add_menu (core, parent, menus_File[i], __open_file_cb);
5398 } else if (!strcmp (menus_File[i], "ReOpen")) {
5399 __add_menu (core, parent, menus_File[i], __open_menu_cb);
5400 } else if (!strcmp (menus_File[i], "Close")) {
5401 __add_menu (core, parent, menus_File[i], __close_file_cb);
5402 } else if (!strcmp (menus_File[i], "Save Layout")) {
5403 __add_menu (core, parent, menus_File[i], __save_layout_cb);
5404 } else if (!strcmp (menus_File[i], "Load Layout")) {
5405 __add_menu (core, parent, menus_File[i], __open_menu_cb);
5406 } else if (!strcmp (menus_File[i], "Clear Saved Layouts")) {
5407 __add_menu (core, parent, menus_File[i], __clear_layout_cb);
5408 } else if (!strcmp (menus_File[i], "Quit")) {
5409 __add_menu (core, parent, menus_File[i], __quit_cb);
5410 } else {
5411 __add_menu (core, parent, menus_File[i], __add_cmd_panel);
5412 }
5413 i++;
5414 }
5415
5416 parent = "Settings";
5417 i = 0;
5418 while (menus_Settings[i]) {
5419 __add_menu (core, parent, menus_Settings[i++], __open_menu_cb);
5420 }
5421
5422 parent = "Edit";
5423 i = 0;
5424 while (menus_Edit[i]) {
5425 if (!strcmp (menus_Edit[i], "Copy")) {
5426 __add_menu (core, parent, menus_Edit[i], __copy_cb);
5427 } else if (!strcmp (menus_Edit[i], "Paste")) {
5428 __add_menu (core, parent, menus_Edit[i], __paste_cb);
5429 } else if (!strcmp (menus_Edit[i], "Write String")) {
5430 __add_menu (core, parent, menus_Edit[i], __write_str_cb);
5431 } else if (!strcmp (menus_Edit[i], "Write Hex")) {
5432 __add_menu (core, parent, menus_Edit[i], __write_hex_cb);
5433 } else if (!strcmp (menus_Edit[i], "Write Value")) {
5434 __add_menu (core, parent, menus_Edit[i], __writeValueCb);
5435 } else if (!strcmp (menus_Edit[i], "Assemble")) {
5436 __add_menu (core, parent, menus_Edit[i], __assemble_cb);
5437 } else if (!strcmp (menus_Edit[i], "Fill")) {
5438 __add_menu (core, parent, menus_Edit[i], __fill_cb);
5439 } else if (!strcmp (menus_Edit[i], "io.cache")) {
5440 __add_menu (core, parent, menus_Edit[i], __open_menu_cb);
5441 } else {
5442 __add_menu (core, parent, menus_Edit[i], __add_cmd_panel);
5443 }
5444 i++;
5445 }
5446
5447 {
5448 parent = "View";
5449 i = 0;
5450 RList *list = __sorted_list (core, menus_View, COUNT (menus_View));
5451 char *pos;
5452 RListIter* iter;
5453 r_list_foreach (list, iter, pos) {
5454 if (!strcmp (pos, PANEL_TITLE_ALL_DECOMPILER)) {
5455 __add_menu (core, parent, pos, __show_all_decompiler_cb);
5456 } else {
5457 __add_menu (core, parent, pos, __add_cmd_panel);
5458 }
5459 }
5460 }
5461
5462 parent = "Tools";
5463 i = 0;
5464 while (menus_Tools[i]) {
5465 if (!strcmp (menus_Tools[i], "Calculator")) {
5466 __add_menu (core, parent, menus_Tools[i], __calculator_cb);
5467 } else if (!strcmp (menus_Tools[i], "R2 Shell")) {
5468 __add_menu (core, parent, menus_Tools[i], __r2_shell_cb);
5469 } else if (!strcmp (menus_Tools[i], "System Shell")) {
5470 __add_menu (core, parent, menus_Tools[i], __system_shell_cb);
5471 }
5472 i++;
5473 }
5474
5475 parent = "Search";
5476 i = 0;
5477 while (menus_Search[i]) {
5478 if (!strcmp (menus_Search[i], "String (Whole Bin)")) {
5479 __add_menu (core, parent, menus_Search[i], __string_whole_bin_cb);
5480 } else if (!strcmp (menus_Search[i], "String (Data Sections)")) {
5481 __add_menu (core, parent, menus_Search[i], __string_data_sec_cb);
5482 } else if (!strcmp (menus_Search[i], "ROP")) {
5483 __add_menu (core, parent, menus_Search[i], __rop_cb);
5484 } else if (!strcmp (menus_Search[i], "Code")) {
5485 __add_menu (core, parent, menus_Search[i], __code_cb);
5486 } else if (!strcmp (menus_Search[i], "Hexpairs")) {
5487 __add_menu (core, parent, menus_Search[i], __hexpairs_cb);
5488 }
5489 i++;
5490 }
5491
5492 parent = "Emulate";
5493 i = 0;
5494 while (menus_Emulate[i]) {
5495 if (!strcmp (menus_Emulate[i], "Step From")) {
5496 __add_menu (core, parent, menus_Emulate[i], __esil_init_cb);
5497 } else if (!strcmp (menus_Emulate[i], "Step To")) {
5498 __add_menu (core, parent, menus_Emulate[i], __esil_step_to_cb);
5499 } else if (!strcmp (menus_Emulate[i], "Step Range")) {
5500 __add_menu (core, parent, menus_Emulate[i], __esil_step_range_cb);
5501 }
5502 i++;
5503 }
5504
5505 {
5506 parent = "Debug";
5507 i = 0;
5508 RList *list = __sorted_list (core, menus_Debug, COUNT (menus_Debug));
5509 char *pos;
5510 RListIter* iter;
5511 r_list_foreach (list, iter, pos) {
5512 if (!strcmp (pos, "Breakpoints")) {
5513 __add_menu (core, parent, pos, __break_points_cb);
5514 } else if (!strcmp (pos, "Watchpoints")) {
5515 __add_menu (core, parent, pos, __watch_points_cb);
5516 } else if (!strcmp (pos, "Continue")) {
5517 __add_menu (core, parent, pos, __continue_cb);
5518 } else if (!strcmp (pos, "Step")) {
5519 __add_menu (core, parent, pos, __step_cb);
5520 } else if (!strcmp (pos, "Step Over")) {
5521 __add_menu (core, parent, pos, __step_over_cb);
5522 } else if (!strcmp (pos, "Reload")) {
5523 __add_menu (core, parent, pos, __reload_cb);
5524 } else {
5525 __add_menu (core, parent, pos, __add_cmd_panel);
5526 }
5527 }
5528 }
5529
5530 parent = "Analyze";
5531 i = 0;
5532 while (menus_Analyze[i]) {
5533 if (!strcmp (menus_Analyze[i], "Function")) {
5534 __add_menu (core, parent, menus_Analyze[i], __function_cb);
5535 } else if (!strcmp (menus_Analyze[i], "Symbols")) {
5536 __add_menu (core, parent, menus_Analyze[i], __symbols_cb);
5537 } else if (!strcmp (menus_Analyze[i], "Program")) {
5538 __add_menu (core, parent, menus_Analyze[i], __program_cb);
5539 } else if (!strcmp (menus_Analyze[i], "BasicBlocks")) {
5540 __add_menu (core, parent, menus_Analyze[i], __basic_blocks_cb);
5541 } else if (!strcmp (menus_Analyze[i], "Calls")) {
5542 __add_menu (core, parent, menus_Analyze[i], __calls_cb);
5543 } else if (!strcmp (menus_Analyze[i], "References")) {
5544 __add_menu (core, parent, menus_Analyze[i], __references_cb);
5545 }
5546 i++;
5547 }
5548 parent = "Help";
5549 i = 0;
5550 while (menus_Help[i]) {
5551 if (!strcmp (menus_Help[i], "License")) {
5552 __add_menu (core, parent, menus_Help[i], __license_cb);
5553 } else if (!strcmp (menus_Help[i], "Version")) {
5554 __add_menu (core, parent, menus_Help[i], __version_cb);
5555 } else if (!strcmp (menus_Help[i], "Fortune")) {
5556 __add_menu (core, parent, menus_Help[i], __fortune_cb);
5557 } else if (!strcmp (menus_Help[i], "2048")) {
5558 __add_menu (core, parent, menus_Help[i], __game_cb);
5559 } else {
5560 __add_menu (core, parent, menus_Help[i], __help_cb);
5561 }
5562 i++;
5563 }
5564
5565 parent = "File.ReOpen";
5566 i = 0;
5567 while (menus_ReOpen[i]) {
5568 if (!strcmp (menus_ReOpen[i], "In RW")) {
5569 __add_menu (core, parent, menus_ReOpen[i], __rw_cb);
5570 } else if (!strcmp (menus_ReOpen[i], "In Debugger")) {
5571 __add_menu (core, parent, menus_ReOpen[i], __debugger_cb);
5572 }
5573 i++;
5574 }
5575
5576 parent = "File.Load Layout";
5577 i = 0;
5578 while (menus_loadLayout[i]) {
5579 if (!strcmp (menus_loadLayout[i], "Saved")) {
5580 __add_menu (core, parent, menus_loadLayout[i], __open_menu_cb);
5581 } else if (!strcmp (menus_loadLayout[i], "Default")) {
5582 __add_menu (core, parent, menus_loadLayout[i], __load_layout_default_cb);
5583 }
5584 i++;
5585 }
5586
5587 __init_menu_saved_layout (core, "File.Load Layout.Saved");
5588
5589 __init_menu_color_settings_layout (core, "Settings.Colors");
5590
5591 {
5592 parent = "Settings.Decompiler";
5593 char *opts = r_core_cmd_str (core, "e cmd.pdc=?");
5594 RList *optl = r_str_split_list (opts, "\n", 0);
5595 RListIter *iter;
5596 char *opt;
5597 r_list_foreach (optl, iter, opt) {
5598 __add_menu (core, parent, strdup (opt), __settings_decompiler_cb);
5599 }
5600 r_list_free (optl);
5601 free (opts);
5602 }
5603
5604 __init_menu_disasm_settings_layout (core, "Settings.Disassembly");
5605 __init_menu_screen_settings_layout (core, "Settings.Screen");
5606
5607 parent = "Edit.io.cache";
5608 i = 0;
5609 while (menus_iocache[i]) {
5610 if (!strcmp (menus_iocache[i], "On")) {
5611 __add_menu (core, parent, menus_iocache[i], __io_cache_on_cb);
5612 } else if (!strcmp (menus_iocache[i], "Off")) {
5613 __add_menu (core, parent, menus_iocache[i], __io_cache_off_cb);
5614 }
5615 i++;
5616 }
5617
5618 panels_menu->history = calloc (8, sizeof (RPanelsMenuItem *));
5619 __clear_panels_menu (core);
5620 panels_menu->refreshPanels = calloc (8, sizeof (RPanel *));
5621 return true;
5622 }
5623
__init_panels(RCore * core,RPanels * panels)5624 static bool __init_panels(RCore *core, RPanels *panels) {
5625 panels->panel = calloc (sizeof (RPanel *), PANEL_NUM_LIMIT);
5626 if (!panels->panel) {
5627 return false;
5628 }
5629 int i;
5630 for (i = 0; i < PANEL_NUM_LIMIT; i++) {
5631 panels->panel[i] = R_NEW0 (RPanel);
5632 panels->panel[i]->model = R_NEW0 (RPanelModel);
5633 __renew_filter (panels->panel[i], PANEL_NUM_LIMIT);
5634 panels->panel[i]->view = R_NEW0 (RPanelView);
5635 if (!panels->panel[i]->model || !panels->panel[i]->view) {
5636 return false;
5637 }
5638 }
5639 return true;
5640 }
5641
__refresh_core_offset(RCore * core)5642 static void __refresh_core_offset (RCore *core) {
5643 RPanels *panels = core->panels;
5644 RPanel *cur = __get_cur_panel (panels);
5645 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
5646 core->offset = cur->model->addr;
5647 }
5648 }
5649
demo_begin(RCore * core,RConsCanvas * can)5650 static void demo_begin(RCore *core, RConsCanvas *can) {
5651 char *s = r_cons_canvas_to_string (can);
5652 if (s) {
5653 // TODO drop utf8!!
5654 r_str_ansi_filter (s, NULL, NULL, -1);
5655 int i, h, w = r_cons_get_size (&h);
5656 for (i = 0; i < 40; i+= (1 + (i/30))) {
5657 int H = i * ((double)h / 40);
5658 char *r = r_str_scale (s, w, H);
5659 r_cons_clear00 ();
5660 r_cons_gotoxy (0, (h / 2) - (H / 2));
5661 r_cons_strcat (r);
5662 r_cons_flush ();
5663 free (r);
5664 r_sys_usleep (3000);
5665 }
5666 free (s);
5667 }
5668 }
5669
demo_end(RCore * core,RConsCanvas * can)5670 static void demo_end(RCore *core, RConsCanvas *can) {
5671 bool utf8 = r_config_get_i (core->config, "scr.utf8");
5672 r_config_set_b (core->config, "scr.utf8", false);
5673 RPanel *cur = __get_cur_panel (core->panels);
5674 cur->view->refresh = true;
5675 firstRun= false;
5676 __panels_refresh (core);
5677 firstRun= true;
5678 r_config_set_b (core->config, "scr.utf8", utf8);
5679 char *s = r_cons_canvas_to_string (can);
5680 if (s) {
5681 // TODO drop utf8!!
5682 r_str_ansi_filter (s, NULL, NULL, -1);
5683 int i, h, w = r_cons_get_size (&h);
5684 for (i = h; i > 0; i--) {
5685 int H = i;
5686 char *r = r_str_scale (s, w, H);
5687 r_cons_clear00 ();
5688 r_cons_gotoxy (0, (h / 2) - (H / 2)); // center
5689 //r_cons_gotoxy (0, h-H); // bottom
5690 r_cons_strcat (r);
5691 r_cons_flush ();
5692 free (r);
5693 r_sys_usleep (3000);
5694 }
5695 r_sys_usleep (100000);
5696 free (s);
5697 }
5698 }
5699
__default_panel_print(RCore * core,RPanel * panel)5700 static void __default_panel_print(RCore *core, RPanel *panel) {
5701 bool o_cur = core->print->cur_enabled;
5702 core->print->cur_enabled = o_cur & (__get_cur_panel (core->panels) == panel);
5703 if (panel->model->readOnly) {
5704 __update_help_contents (core, panel);
5705 __update_help_title (core, panel);
5706 } else if (panel->model->cmd) {
5707 panel->model->print_cb (core, panel);
5708 __update_panel_title (core, panel);
5709 }
5710 core->print->cur_enabled = o_cur;
5711 }
5712
__panel_print(RCore * core,RConsCanvas * can,RPanel * panel,int color)5713 static void __panel_print(RCore *core, RConsCanvas *can, RPanel *panel, int color) {
5714 if (!can || !panel|| !panel->view->refresh) {
5715 return;
5716 }
5717 if (can->w <= panel->view->pos.x || can->h <= panel->view->pos.y) {
5718 return;
5719 }
5720 panel->view->refresh = panel->model->type == PANEL_TYPE_MENU;
5721 r_cons_canvas_fill (can, panel->view->pos.x, panel->view->pos.y, panel->view->pos.w, panel->view->pos.h, ' ');
5722 if (panel->model->type == PANEL_TYPE_MENU) {
5723 __menu_panel_print (can, panel, panel->view->sx, panel->view->sy, panel->view->pos.w, panel->view->pos.h);
5724 } else {
5725 __default_panel_print (core, panel);
5726 }
5727 int w, h;
5728 w = R_MIN (panel->view->pos.w, can->w - panel->view->pos.x);
5729 h = R_MIN (panel->view->pos.h, can->h - panel->view->pos.y);
5730 if (color) {
5731 r_cons_canvas_box (can, panel->view->pos.x, panel->view->pos.y, w, h, core->cons->context->pal.graph_box2);
5732 } else {
5733 r_cons_canvas_box (can, panel->view->pos.x, panel->view->pos.y, w, h, core->cons->context->pal.graph_box);
5734 }
5735 }
5736
__panels_refresh(RCore * core)5737 static void __panels_refresh(RCore *core) {
5738 RPanels *panels = core->panels;
5739 if (!panels) {
5740 return;
5741 }
5742 RConsCanvas *can = panels->can;
5743 if (!can) {
5744 return;
5745 }
5746 r_cons_gotoxy (0, 0);
5747 int i, h, w = r_cons_get_size (&h);
5748 if (!r_cons_canvas_resize (can, w, h)) {
5749 return;
5750 }
5751 RStrBuf *title = r_strbuf_new (" ");
5752 bool utf8 = r_config_get_i (core->config, "scr.utf8");
5753 if (firstRun) {
5754 r_config_set_b (core->config, "scr.utf8", false);
5755 }
5756
5757 __refresh_core_offset (core);
5758 __set_refresh_all (core, false, false);
5759
5760 //TODO use getPanel
5761 for (i = 0; i < panels->n_panels; i++) {
5762 if (i != panels->curnode) {
5763 __panel_print (core, can, __get_panel (panels, i), 0);
5764 }
5765 }
5766 if (panels->mode == PANEL_MODE_MENU) {
5767 __panel_print (core, can, __get_cur_panel (panels), 0);
5768 } else {
5769 __panel_print (core, can, __get_cur_panel (panels), 1);
5770 }
5771 for (i = 0; i < panels->panels_menu->n_refresh; i++) {
5772 __panel_print (core, can, panels->panels_menu->refreshPanels[i], 1);
5773 }
5774 (void) r_cons_canvas_gotoxy (can, -can->sx, -can->sy);
5775 r_cons_canvas_fill (can, -can->sx, -can->sy, w, 1, ' ');
5776 const char *color = core->cons->context->pal.graph_box2;
5777 if (panels->mode == PANEL_MODE_ZOOM) {
5778 r_strbuf_appendf (title, "%s Zoom Mode | Press Enter or q to quit"Color_RESET, color);
5779 } else if (panels->mode == PANEL_MODE_WINDOW) {
5780 r_strbuf_appendf (title, "%s Window Mode | hjkl: move around the panels | q: quit the mode | Enter: Zoom mode"Color_RESET, color);
5781 } else {
5782 RPanelsMenuItem *parent = panels->panels_menu->root;
5783 for (i = 0; i < parent->n_sub; i++) {
5784 RPanelsMenuItem *item = parent->sub[i];
5785 if (panels->mode == PANEL_MODE_MENU && i == parent->selectedIndex) {
5786 r_strbuf_appendf (title, "%s[%s]"Color_RESET, color, item->name);
5787 } else {
5788 r_strbuf_appendf (title, " %s ", item->name);
5789 }
5790 }
5791 }
5792 if (panels->mode == PANEL_MODE_MENU) {
5793 r_cons_canvas_write (can, Color_YELLOW);
5794 r_cons_canvas_write (can, r_strbuf_get (title));
5795 r_cons_canvas_write (can, Color_RESET);
5796 } else {
5797 r_cons_canvas_write (can, Color_RESET);
5798 r_cons_canvas_write (can, r_strbuf_get (title));
5799 }
5800 r_strbuf_setf (title, "[0x%08"PFMT64x "]", core->offset);
5801 i = -can->sx + w - r_strbuf_length (title);
5802 (void) r_cons_canvas_gotoxy (can, i, -can->sy);
5803 r_cons_canvas_write (can, r_strbuf_get (title));
5804
5805 int tab_pos = i;
5806 for (i = core->panels_root->n_panels; i > 0; i--) {
5807 RPanels *panels = core->panels_root->panels[i - 1];
5808 char *name = NULL;
5809 if (panels) {
5810 name = panels->name;
5811 }
5812 if (i - 1 == core->panels_root->cur_panels) {
5813 if (!name) {
5814 r_strbuf_setf (title, "%s[%d] "Color_RESET, color, i);
5815 } else {
5816 r_strbuf_setf (title, "%s[%s] "Color_RESET, color, name);
5817 }
5818 tab_pos -= r_str_ansi_len (r_strbuf_get (title));
5819 } else {
5820 if (!name) {
5821 r_strbuf_setf (title, "%d ", i);
5822 } else {
5823 r_strbuf_setf (title, "%s ", name);
5824 }
5825 tab_pos -= r_strbuf_length (title);
5826 }
5827 (void) r_cons_canvas_gotoxy (can, tab_pos, -can->sy);
5828 r_cons_canvas_write (can, r_strbuf_get (title));
5829 }
5830 r_strbuf_set (title, "Tab ");
5831 tab_pos -= r_strbuf_length (title);
5832 (void) r_cons_canvas_gotoxy (can, tab_pos, -can->sy);
5833 r_cons_canvas_write (can, r_strbuf_get (title));
5834 r_strbuf_free (title);
5835
5836 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
5837 __print_snow (panels);
5838 }
5839
5840 if (firstRun) {
5841 if (core->panels_root->n_panels < 2) {
5842 if (r_config_get_i (core->config, "scr.demo")) {
5843 demo_begin (core, can);
5844 }
5845 }
5846 firstRun = false;
5847 r_config_set_b (core->config, "scr.utf8", utf8);
5848 RPanel *cur = __get_cur_panel (core->panels);
5849 cur->view->refresh = true;
5850 __panels_refresh (core);
5851 return;
5852 }
5853 r_cons_canvas_print (can);
5854 if (core->scr_gadgets) {
5855 r_core_cmd0 (core, "pg");
5856 }
5857 show_cursor (core);
5858 r_cons_flush ();
5859 if (r_cons_singleton ()->fps) {
5860 r_cons_print_fps (40);
5861 }
5862 }
5863
__panel_breakpoint(RCore * core)5864 static void __panel_breakpoint(RCore *core) {
5865 RPanel *cur = __get_cur_panel (core->panels);
5866 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
5867 r_core_cmd (core, "dbs $$", 0);
5868 cur->view->refresh = true;
5869 }
5870 }
5871
__panel_continue(RCore * core)5872 static void __panel_continue(RCore *core) {
5873 r_core_cmd (core, "dc", 0);
5874 }
5875
__handle_menu(RCore * core,const int key)5876 static void __handle_menu(RCore *core, const int key) {
5877 RPanels *panels = core->panels;
5878 RPanelsMenu *menu = panels->panels_menu;
5879 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
5880 RPanelsMenuItem *child = parent->sub[parent->selectedIndex];
5881 r_cons_switchbuf (false);
5882 switch (key) {
5883 case 'h':
5884 if (menu->depth <= 2) {
5885 menu->n_refresh = 0;
5886 if (menu->root->selectedIndex > 0) {
5887 menu->root->selectedIndex--;
5888 } else {
5889 menu->root->selectedIndex = menu->root->n_sub - 1;
5890 }
5891 if (menu->depth == 2) {
5892 menu->depth = 1;
5893 (void)(menu->root->sub[menu->root->selectedIndex]->cb (core));
5894 }
5895 } else {
5896 __del_menu (core);
5897 }
5898 break;
5899 case 'j':
5900 if (r_config_get_i (core->config, "scr.cursor")) {
5901 core->cons->cpos.y++;
5902 } else {
5903 if (menu->depth == 1) {
5904 (void)(child->cb (core));
5905 } else {
5906 parent->selectedIndex = R_MIN (parent->n_sub - 1, parent->selectedIndex + 1);
5907 __update_menu_contents (core, menu, parent);
5908 }
5909 }
5910 break;
5911 case 'k':
5912 if (r_config_get_i (core->config, "scr.cursor")) {
5913 core->cons->cpos.y--;
5914 } else {
5915 if (menu->depth < 2) {
5916 break;
5917 }
5918 RPanelsMenuItem *parent = menu->history[menu->depth - 1];
5919 if (parent->selectedIndex > 0) {
5920 parent->selectedIndex--;
5921 __update_menu_contents (core, menu, parent);
5922 }
5923 }
5924 break;
5925 case 'l':
5926 {
5927 if (menu->depth == 1) {
5928 menu->root->selectedIndex++;
5929 menu->root->selectedIndex %= menu->root->n_sub;
5930 break;
5931 }
5932 if (parent->sub[parent->selectedIndex]->sub) {
5933 (void)(parent->sub[parent->selectedIndex]->cb (core));
5934 } else {
5935 menu->n_refresh = 0;
5936 menu->root->selectedIndex++;
5937 menu->root->selectedIndex %= menu->root->n_sub;
5938 menu->depth = 1;
5939 (void)(menu->root->sub[menu->root->selectedIndex]->cb (core));
5940 }
5941 }
5942 break;
5943 case 'm':
5944 case 'q':
5945 case 'Q':
5946 case -1:
5947 if (panels->panels_menu->depth > 1) {
5948 __del_menu (core);
5949 } else {
5950 menu->n_refresh = 0;
5951 __set_mode (core, PANEL_MODE_DEFAULT);
5952 __get_cur_panel (panels)->view->refresh = true;
5953 }
5954 break;
5955 case '$':
5956 r_core_cmd0 (core, "dr PC=$$");
5957 break;
5958 case ' ':
5959 case '\r':
5960 case '\n':
5961 (void)(child->cb (core));
5962 break;
5963 case 9:
5964 menu->n_refresh = 0;
5965 __handle_tab_key (core, false);
5966 break;
5967 case 'Z':
5968 menu->n_refresh = 0;
5969 __handle_tab_key (core, true);
5970 break;
5971 case ':':
5972 menu->n_refresh = 0;
5973 __handlePrompt (core, panels);
5974 break;
5975 case '?':
5976 menu->n_refresh = 0;
5977 __toggle_help (core);
5978 break;
5979 case '"':
5980 menu->n_refresh = 0;
5981 __create_modal (core, __get_panel (panels, 0), panels->modal_db);
5982 __set_mode (core, PANEL_MODE_DEFAULT);
5983 break;
5984 }
5985 }
5986
__handle_console(RCore * core,RPanel * panel,const int key)5987 static bool __handle_console(RCore *core, RPanel *panel, const int key) {
5988 if (!__check_panel_type (panel, PANEL_CMD_CONSOLE)) {
5989 return false;
5990 }
5991 r_cons_switchbuf (false);
5992 switch (key) {
5993 case 'i':
5994 {
5995 char cmd[128] = {0};
5996 char *prompt = r_str_newf ("[0x%08"PFMT64x"]) ", core->offset);
5997 __panel_prompt (prompt, cmd, sizeof (cmd));
5998 if (*cmd) {
5999 if (!strcmp (cmd, "clear")) {
6000 r_core_cmd0 (core, ":>$console");
6001 } else {
6002 r_core_cmdf (core, "?e %s %s>>$console", prompt, cmd);
6003 r_core_cmdf (core, "%s >>$console", cmd);
6004 }
6005 }
6006 panel->view->refresh = true;
6007 }
6008 return true;
6009 case 'l':
6010 r_core_cmd0 (core, ":>$console");
6011 panel->view->refresh = true;
6012 return true;
6013 default:
6014 // add more things later
6015 break;
6016 }
6017 return false;
6018 }
6019
__create_panels_config_path(const char * file)6020 static char *__create_panels_config_path(const char *file) {
6021 char *dir_path = __get_panels_config_dir_path ();
6022 r_sys_mkdirp (dir_path);
6023 char *file_path = r_str_newf (R_JOIN_2_PATHS ("%s", "%s"), dir_path, file);
6024 R_FREE (dir_path);
6025 return file_path;
6026 }
6027
__get_panels_config_file_from_dir(const char * file)6028 static char *__get_panels_config_file_from_dir(const char *file) {
6029 char *dir_path = __get_panels_config_dir_path ();
6030 RList *dir = r_sys_dir (dir_path);
6031 if (!dir_path || !dir) {
6032 free (dir_path);
6033 return NULL;
6034 }
6035 char *tmp = NULL;
6036 RListIter *it;
6037 char *entry;
6038 r_list_foreach (dir, it, entry) {
6039 if (!strcmp (entry, file)) {
6040 tmp = entry;
6041 break;
6042 }
6043 }
6044 if (!tmp) {
6045 r_list_free (dir);
6046 free (dir_path);
6047 return NULL;
6048 }
6049 char *ret = r_str_newf (R_JOIN_2_PATHS ("%s", "%s"), dir_path, tmp);
6050 r_list_free (dir);
6051 free (dir_path);
6052 return ret;
6053 }
6054
r_core_panels_save(RCore * core,const char * oname)6055 R_API void r_core_panels_save(RCore *core, const char *oname) {
6056 int i;
6057 if (!core->panels) {
6058 return;
6059 }
6060 const char *name = oname;
6061 if (R_STR_ISEMPTY (name)) {
6062 name = __show_status_input (core, "Name for the layout: ");
6063 if (R_STR_ISEMPTY (name)) {
6064 (void)__show_status (core, "Name can't be empty!");
6065 return;
6066 }
6067 }
6068 char *config_path = __create_panels_config_path (name);
6069 RPanels *panels = core->panels;
6070 PJ *pj = pj_new ();
6071 for (i = 0; i < panels->n_panels; i++) {
6072 RPanel *panel = __get_panel (panels, i);
6073 pj_o (pj);
6074 pj_ks (pj, "Title", panel->model->title);
6075 pj_ks (pj, "Cmd", panel->model->cmd);
6076 pj_kn (pj, "x", panel->view->pos.x);
6077 pj_kn (pj, "y", panel->view->pos.y);
6078 pj_kn (pj, "w", panel->view->pos.w);
6079 pj_kn (pj, "h", panel->view->pos.h);
6080 pj_end (pj);
6081 }
6082 FILE *fd = r_sandbox_fopen (config_path, "w");
6083 if (fd) {
6084 char *pjs = pj_drain (pj);
6085 fprintf (fd, "%s\n", pjs);
6086 free (pjs);
6087 fclose (fd);
6088 __update_menu (core, "File.Load Layout.Saved", __init_menu_saved_layout);
6089 (void)__show_status (core, "Panels layout saved!");
6090 }
6091 free (config_path);
6092 }
6093
__parse_panels_config(const char * cfg,int len)6094 static char *__parse_panels_config(const char *cfg, int len) {
6095 if (R_STR_ISEMPTY (cfg) || len < 2) {
6096 return NULL;
6097 }
6098 char *tmp = r_str_newlen (cfg, len + 1);
6099 int i = 0;
6100 for (; i < len; i++) {
6101 if (tmp[i] == '}') {
6102 if (i + 1 < len) {
6103 if (tmp[i + 1] == ',') {
6104 tmp[i + 1] = '\n';
6105 }
6106 continue;
6107 }
6108 tmp[i + 1] = '\n';
6109 }
6110 }
6111 return tmp;
6112 }
6113
r_core_panels_load(RCore * core,const char * _name)6114 R_API bool r_core_panels_load(RCore *core, const char *_name) {
6115 if (!core->panels) {
6116 return false;
6117 }
6118 char *config_path = __get_panels_config_file_from_dir (_name);
6119 if (!config_path) {
6120 char *tmp = r_str_newf ("No saved layout found for the name: %s", _name);
6121 (void)__show_status (core, tmp);
6122 free (tmp);
6123 return false;
6124 }
6125 char *panels_config = r_file_slurp (config_path, NULL);
6126 free (config_path);
6127 if (!panels_config) {
6128 char *tmp = r_str_newf ("Layout is empty: %s", _name);
6129 (void)__show_status (core, tmp);
6130 free (tmp);
6131 return false;
6132 }
6133 RPanels *panels = core->panels;
6134 __panel_all_clear (panels);
6135 panels->n_panels = 0;
6136 __set_curnode (core, 0);
6137 char *title, *cmd, *x, *y, *w, *h, *p_cfg = panels_config, *tmp_cfg;
6138 int i, tmp_count;
6139 tmp_cfg = __parse_panels_config (p_cfg, strlen (p_cfg));
6140 tmp_count = r_str_split (tmp_cfg, '\n');
6141 for (i = 0; i < tmp_count; i++) {
6142 if (R_STR_ISEMPTY (tmp_cfg)) {
6143 break;
6144 }
6145 title = sdb_json_get_str (tmp_cfg, "Title");
6146 cmd = sdb_json_get_str (tmp_cfg, "Cmd");
6147 (void)r_str_arg_unescape (cmd);
6148 x = sdb_json_get_str (tmp_cfg, "x");
6149 y = sdb_json_get_str (tmp_cfg, "y");
6150 w = sdb_json_get_str (tmp_cfg, "w");
6151 h = sdb_json_get_str (tmp_cfg, "h");
6152 RPanel *p = __get_panel (panels, panels->n_panels);
6153 __set_geometry (&p->view->pos, atoi (x), atoi (y), atoi (w),atoi (h));
6154 __init_panel_param (core, p, title, cmd);
6155 // TODO: fix code duplication with __update_help
6156 if (r_str_endswith (cmd, "Help")) {
6157 p->model->title = r_str_dup (p->model->title, "Help");
6158 p->model->cmd = r_str_dup (p->model->cmd, "Help");
6159 RStrBuf *rsb = r_strbuf_new (NULL);
6160 r_core_visual_append_help (rsb, "Panels Mode", help_msg_panels);
6161 if (!rsb) {
6162 return false;
6163 }
6164 __set_read_only (core, p, r_strbuf_drain (rsb));
6165 }
6166 tmp_cfg += strlen (tmp_cfg) + 1;
6167 }
6168 free (panels_config);
6169 if (!panels->n_panels) {
6170 free (tmp_cfg);
6171 return false;
6172 }
6173 __set_refresh_all (core, true, false);
6174 return true;
6175 }
6176
__rotate_panels(RCore * core,bool rev)6177 static void __rotate_panels(RCore *core, bool rev) {
6178 RPanels *panels = core->panels;
6179 RPanel *first = __get_panel (panels, 0);
6180 RPanel *last = __get_panel (panels, panels->n_panels - 1);
6181 int i;
6182 RPanelModel *tmp_model;
6183 if (!rev) {
6184 tmp_model = first->model;
6185 for (i = 0; i < panels->n_panels - 1; i++) {
6186 RPanel *p0 = __get_panel (panels, i);
6187 RPanel *p1 = __get_panel (panels, i + 1);
6188 p0->model = p1->model;
6189 }
6190 last->model = tmp_model;
6191 } else {
6192 tmp_model = last->model;
6193 for (i = panels->n_panels - 1; i > 0; i--) {
6194 RPanel *p0 = __get_panel (panels, i);
6195 RPanel *p1 = __get_panel (panels, i - 1);
6196 p0->model = p1->model;
6197 }
6198 first->model = tmp_model;
6199 }
6200 __set_refresh_all (core, false, true);
6201 }
6202
__undo_seek(RCore * core)6203 static void __undo_seek(RCore *core) {
6204 RPanel *cur = __get_cur_panel (core->panels);
6205 if (!__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6206 return;
6207 }
6208 RIOUndos *undo = r_io_sundo (core->io, core->offset);
6209 if (undo) {
6210 r_core_visual_seek_animation (core, undo->off);
6211 __set_panel_addr (core, cur, core->offset);
6212 }
6213 }
6214
__set_filter(RCore * core,RPanel * panel)6215 static void __set_filter(RCore *core, RPanel *panel) {
6216 if (!panel->model->filter) {
6217 return;
6218 }
6219 char *input = __show_status_input (core, "filter word: ");
6220 if (input) {
6221 panel->model->filter[panel->model->n_filter++] = input;
6222 __set_cmd_str_cache (core, panel, NULL);
6223 panel->view->refresh = true;
6224 }
6225 __reset_scroll_pos (panel);
6226 }
6227
__redo_seek(RCore * core)6228 static void __redo_seek(RCore *core) {
6229 RPanel *cur = __get_cur_panel (core->panels);
6230 if (!__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6231 return;
6232 }
6233 RIOUndos *undo = r_io_sundo_redo (core->io);
6234 if (undo) {
6235 r_core_visual_seek_animation (core, undo->off);
6236 __set_panel_addr (core, cur, core->offset);
6237 }
6238 }
6239
__handle_tab(RCore * core)6240 static void __handle_tab(RCore *core) {
6241 r_cons_gotoxy (0, 0);
6242 if (core->panels_root->n_panels <= 1) {
6243 r_cons_printf (R_CONS_CLEAR_LINE"%s[Tab] t:new T:new with current panel -:del =:name"Color_RESET, core->cons->context->pal.graph_box2);
6244 } else {
6245 const int min = 1;
6246 const int max = core->panels_root->n_panels;
6247 r_cons_printf (R_CONS_CLEAR_LINE"%s[Tab] [%d..%d]:select; p:prev; n:next; t:new T:new with current panel -:del =:name"Color_RESET,
6248 core->cons->context->pal.graph_box2, min, max);
6249 }
6250 r_cons_flush ();
6251 int ch = r_cons_readchar ();
6252
6253 if (isdigit (ch)) {
6254 __handle_tab_nth (core, ch);
6255 return;
6256 }
6257
6258 switch (ch) {
6259 case 'n':
6260 __handle_tab_next (core);
6261 return;
6262 case 'p':
6263 __handle_tab_prev (core);
6264 return;
6265 case '-':
6266 __set_root_state (core, DEL);
6267 return;
6268 case '=':
6269 __handle_tab_name (core);
6270 return;
6271 case 't':
6272 __handle_tab_new (core);
6273 return;
6274 case 'T':
6275 __handle_tab_new_with_cur_panel (core);
6276 return;
6277 }
6278 }
6279
6280 // copypasta from visual
prevOpcode(RCore * core)6281 static void prevOpcode(RCore *core) {
6282 RPrint *p = core->print;
6283 ut64 addr, oaddr = core->offset + core->print->cur;
6284 if (r_core_prevop_addr (core, oaddr, 1, &addr)) {
6285 const int delta = oaddr - addr;
6286 p->cur -= delta;
6287 } else {
6288 p->cur -= 4;
6289 }
6290 }
6291
nextOpcode(RCore * core)6292 static void nextOpcode(RCore *core) {
6293 RAnalOp *aop = r_core_anal_op (core, core->offset + core->print->cur, R_ANAL_OP_MASK_BASIC);
6294 RPrint *p = core->print;
6295 if (aop) {
6296 p->cur += aop->size;
6297 r_anal_op_free (aop);
6298 } else {
6299 p->cur += 4;
6300 }
6301 }
6302
__panels_process(RCore * core,RPanels * panels)6303 static void __panels_process(RCore *core, RPanels *panels) {
6304 if (!panels) {
6305 return;
6306 }
6307 int i, okey, key;
6308 RPanelsRoot *panels_root = core->panels_root;
6309 RPanels *prev;
6310 prev = core->panels;
6311 core->panels = panels;
6312 panels->autoUpdate = true;
6313 int h, w = r_cons_get_size (&h);
6314 panels->can = __create_new_canvas (core, w, h);
6315 __set_refresh_all (core, false, true);
6316
6317 r_cons_switchbuf (false);
6318
6319 int originCursor = core->print->cur;
6320 core->print->cur = 0;
6321 core->print->cur_enabled = false;
6322 core->print->col = 0;
6323
6324 bool originVmode = core->vmode;
6325 core->vmode = true;
6326 {
6327 const char *layout = r_config_get (core->config, "scr.layout");
6328 if (R_STR_ISNOTEMPTY (layout)) {
6329 r_core_panels_load (core, layout);
6330 }
6331 }
6332
6333 bool o_interactive = r_cons_is_interactive ();
6334 r_cons_set_interactive (true);
6335 r_core_visual_showcursor (core, false);
6336
6337 r_cons_enable_mouse (false);
6338 repeat:
6339 r_cons_enable_mouse (r_config_get_i (core->config, "scr.wheel"));
6340 core->panels = panels;
6341 core->cons->event_resize = NULL; // avoid running old event with new data
6342 core->cons->event_data = core;
6343 core->cons->event_resize = (RConsEvent) __do_panels_refreshOneShot;
6344 __panels_layout_refresh (core);
6345 RPanel *cur = __get_cur_panel (panels);
6346 if (panels->fun == PANEL_FUN_SNOW || panels->fun == PANEL_FUN_SAKURA) {
6347 if (panels->mode == PANEL_MODE_MENU) {
6348 panels->fun = PANEL_FUN_NOFUN;
6349 __reset_snow (panels);
6350 goto repeat;
6351 }
6352 okey = r_cons_readchar_timeout (300);
6353 if (okey == -1) {
6354 cur->view->refresh = true;
6355 goto repeat;
6356 }
6357 } else {
6358 okey = r_cons_readchar ();
6359 }
6360
6361 key = r_cons_arrow_to_hjkl (okey);
6362 virtualmouse:
6363 if (__handle_mouse (core, cur, &key)) {
6364 if (panels_root->root_state != DEFAULT) {
6365 goto exit;
6366 }
6367 goto repeat;
6368 }
6369
6370 r_cons_switchbuf (true);
6371
6372 if (panels->mode == PANEL_MODE_MENU) {
6373 __handle_menu (core, key);
6374 if (__check_root_state (core, QUIT) ||
6375 __check_root_state (core, ROTATE)) {
6376 goto exit;
6377 }
6378 goto repeat;
6379 }
6380
6381 if (core->print->cur_enabled) {
6382 if (__handle_cursor_mode (core, key)) {
6383 goto repeat;
6384 }
6385 }
6386
6387 if (panels->mode == PANEL_MODE_ZOOM) {
6388 if (__handle_zoom_mode (core, key)) {
6389 goto repeat;
6390 }
6391 }
6392
6393 if (panels->mode == PANEL_MODE_WINDOW) {
6394 if (__handle_window_mode (core, key)) {
6395 goto repeat;
6396 }
6397 }
6398
6399 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY) && '0' < key && key <= '9') {
6400 ut8 ch = key;
6401 r_core_visual_jump (core, ch);
6402 __set_panel_addr (core, cur, core->offset);
6403 goto repeat;
6404 }
6405
6406 const char *cmd;
6407 RConsCanvas *can = panels->can;
6408 if (__handle_console (core, cur, key)) {
6409 goto repeat;
6410 }
6411 switch (key) {
6412 case 'u':
6413 __undo_seek (core);
6414 break;
6415 case 'U':
6416 __redo_seek (core);
6417 break;
6418 case 'p':
6419 __rotate_panels (core, false);
6420 break;
6421 case 'P':
6422 __rotate_panels (core, true);
6423 break;
6424 case '.':
6425 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6426 ut64 addr = r_debug_reg_get (core->dbg, "PC");
6427 if (addr && addr != UT64_MAX) {
6428 r_core_seek (core, addr, true);
6429 } else {
6430 addr = r_num_get (core->num, "entry0");
6431 if (addr && addr != UT64_MAX) {
6432 r_core_seek (core, addr, true);
6433 }
6434 }
6435 __set_panel_addr (core, cur, core->offset);
6436 }
6437 break;
6438 case '?':
6439 __toggle_help (core);
6440 break;
6441 case 'b':
6442 r_core_visual_browse (core, NULL);
6443 break;
6444 case ';':
6445 __handleComment (core);
6446 break;
6447 case '$':
6448 if (core->print->cur_enabled) {
6449 r_core_cmdf (core, "dr PC=$$+%d", core->print->cur);
6450 } else {
6451 r_core_cmd0 (core, "dr PC=$$");
6452 }
6453 break;
6454 case 's':
6455 __panel_single_step_in (core);
6456 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6457 __set_panel_addr (core, cur, core->offset);
6458 }
6459 break;
6460 case 'S':
6461 __panel_single_step_over (core);
6462 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6463 __set_panel_addr (core, cur, core->offset);
6464 }
6465 break;
6466 case ' ':
6467 if (r_config_get_i (core->config, "graph.web")) {
6468 r_core_cmd0 (core, "agv $$");
6469 } else {
6470 __call_visual_graph (core);
6471 }
6472 break;
6473 case ':':
6474 r_core_visual_prompt_input (core);
6475 __set_panel_addr (core, cur, core->offset);
6476 break;
6477 case 'c':
6478 __activate_cursor (core);
6479 break;
6480 case 'C':
6481 {
6482 int color = r_config_get_i (core->config, "scr.color");
6483 if (++color > 2) {
6484 color = 0;
6485 }
6486 r_config_set_i (core->config, "scr.color", color);
6487 can->color = color;
6488 __set_refresh_all (core, true, false);
6489 }
6490 break;
6491 case 'r':
6492 if (r_config_get_i (core->config, "asm.hint.call")) {
6493 r_config_toggle (core->config, "asm.hint.call");
6494 r_config_set_b (core->config, "asm.hint.jmp", true);
6495 } else if (r_config_get_i (core->config, "asm.hint.jmp")) {
6496 r_config_toggle (core->config, "asm.hint.jmp");
6497 r_config_set_b (core->config, "asm.hint.emu", true);
6498 } else if (r_config_get_i (core->config, "asm.hint.emu")) {
6499 r_config_toggle (core->config, "asm.hint.emu");
6500 r_config_set_b (core->config, "asm.hint.lea", true);
6501 } else if (r_config_get_i (core->config, "asm.hint.lea")) {
6502 r_config_toggle (core->config, "asm.hint.lea");
6503 r_config_set_b (core->config, "asm.hint.call", true);
6504 } else {
6505 r_config_set_b (core->config, "asm.hint.call", true);
6506 }
6507 break;
6508 case 'R':
6509 if (r_config_get_i (core->config, "scr.randpal")) {
6510 r_core_cmd0 (core, "ecr");
6511 } else {
6512 r_core_cmd0 (core, "ecn");
6513 }
6514 __do_panels_refresh (core);
6515 break;
6516 case 'a':
6517 panels->autoUpdate = __show_status_yesno (core, 1, "Auto update On? (Y/n)");
6518 break;
6519 case 'A':
6520 {
6521 const int ocur = core->print->cur_enabled;
6522 r_core_visual_asm (core, core->offset);
6523 core->print->cur_enabled = ocur;
6524 }
6525 break;
6526 case 'd':
6527 r_core_visual_define (core, "", 0);
6528 break;
6529 case 'D':
6530 __replace_cmd (core, PANEL_TITLE_DISASSEMBLY, PANEL_CMD_DISASSEMBLY);
6531 break;
6532 case 'j':
6533 if (r_config_get_i (core->config, "scr.cursor")) {
6534 core->cons->cpos.y++;
6535 } else {
6536 if (core->print->cur_enabled) {
6537 nextOpcode (core);
6538 } else {
6539 r_cons_switchbuf (false);
6540 if (cur->model->directionCb) {
6541 cur->model->directionCb (core, (int)DOWN);
6542 }
6543 }
6544 }
6545 break;
6546 case 'k':
6547 if (r_config_get_i (core->config, "scr.cursor")) {
6548 core->cons->cpos.y--;
6549 } else {
6550 if (core->print->cur_enabled) {
6551 prevOpcode (core);
6552 } else {
6553 r_cons_switchbuf (false);
6554 if (cur->model->directionCb) {
6555 cur->model->directionCb (core, (int)UP);
6556 }
6557 }
6558 }
6559 break;
6560 case 'K':
6561 if (r_config_get_i (core->config, "scr.cursor")) {
6562 core->cons->cpos.y -= 5;
6563 } else {
6564 if (core->print->cur_enabled) {
6565 size_t i;
6566 for (i = 0; i < 4; i++) {
6567 prevOpcode (core);
6568 }
6569 } else {
6570 r_cons_switchbuf (false);
6571 if (cur->model->directionCb) {
6572 for (i = 0; i < __get_cur_panel (panels)->view->pos.h / 2 - 6; i++) {
6573 cur->model->directionCb (core, (int)UP);
6574 }
6575 }
6576 }
6577 }
6578 break;
6579 case 'J':
6580 if (r_config_get_i (core->config, "scr.cursor")) {
6581 core->cons->cpos.y += 5;
6582 } else {
6583 if (core->print->cur_enabled) {
6584 size_t i;
6585 for (i = 0; i < 4; i++) {
6586 nextOpcode (core);
6587 }
6588 } else {
6589 r_cons_switchbuf (false);
6590 if (cur->model->directionCb) {
6591 for (i = 0; i < __get_cur_panel (panels)->view->pos.h / 2 - 6; i++) {
6592 cur->model->directionCb (core, (int)DOWN);
6593 }
6594 }
6595 }
6596 }
6597 break;
6598 case 'H':
6599 if (r_config_get_i (core->config, "scr.cursor")) {
6600 core->cons->cpos.x -= 5;
6601 } else {
6602 r_cons_switchbuf (false);
6603 if (cur->model->directionCb) {
6604 for (i = 0; i < __get_cur_panel (panels)->view->pos.w / 3; i++) {
6605 cur->model->directionCb (core, (int)LEFT);
6606 }
6607 }
6608 }
6609 break;
6610 case 'L':
6611 if (r_config_get_i (core->config, "scr.cursor")) {
6612 core->cons->cpos.x += 5;
6613 } else {
6614 r_cons_switchbuf (false);
6615 if (cur->model->directionCb) {
6616 for (i = 0; i < __get_cur_panel (panels)->view->pos.w / 3; i++) {
6617 cur->model->directionCb (core, (int)RIGHT);
6618 }
6619 }
6620 }
6621 break;
6622 case 'f':
6623 __set_filter (core, cur);
6624 break;
6625 case 'F':
6626 __reset_filter (core, cur);
6627 break;
6628 case '_':
6629 __hudstuff (core);
6630 break;
6631 case '\\':
6632 r_core_visual_hud (core);
6633 break;
6634 case '"':
6635 r_cons_switchbuf (false);
6636 __create_modal (core, cur, panels->modal_db);
6637 if (__check_root_state (core, ROTATE)) {
6638 goto exit;
6639 }
6640 // all panels containing decompiler data should be cached
6641 cur->model->cache = strstr (cur->model->title, "Decomp") != NULL;
6642 break;
6643 case 'O':
6644 __handle_print_rotate (core);
6645 break;
6646 case 'n':
6647 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6648 r_core_seek_next (core, r_config_get (core->config, "scr.nkey"));
6649 __set_panel_addr (core, cur, core->offset);
6650 }
6651 break;
6652 case 'N':
6653 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6654 r_core_seek_previous (core, r_config_get (core->config, "scr.nkey"));
6655 __set_panel_addr (core, cur, core->offset);
6656 }
6657 break;
6658 case 'x':
6659 __handle_refs (core, cur, UT64_MAX);
6660 break;
6661 case 'X':
6662 #if 0
6663 // already accessible via xX
6664 r_core_visual_refs (core, false, true);
6665 cur->model->addr = core->offset;
6666 set_refresh_all (panels, false);
6667 #endif
6668 __dismantle_del_panel (core, cur, panels->curnode);
6669 break;
6670 case 9: // TAB
6671 __handle_tab_key (core, false);
6672 break;
6673 case 'Z': // SHIFT-TAB
6674 __handle_tab_key (core, true);
6675 break;
6676 case 'M':
6677 __handle_visual_mark (core);
6678 break;
6679 case 'e':
6680 {
6681 char *cmd = __show_status_input (core, "New command: ");
6682 if (R_STR_ISNOTEMPTY (cmd)) {
6683 __replace_cmd (core, cmd, cmd);
6684 }
6685 free (cmd);
6686 }
6687 break;
6688 case 'm':
6689 __set_mode (core, PANEL_MODE_MENU);
6690 __clear_panels_menu (core);
6691 __get_cur_panel (panels)->view->refresh = true;
6692 break;
6693 case 'g':
6694 r_core_visual_showcursor (core, true);
6695 r_core_visual_offset (core);
6696 r_core_visual_showcursor (core, false);
6697 __set_panel_addr (core, cur, core->offset);
6698 break;
6699 case 'G':
6700 {
6701 const char *hl = r_config_get (core->config, "scr.highlight");
6702 if (hl) {
6703 ut64 addr = r_num_math (core->num, hl);
6704 __set_panel_addr (core, cur, addr);
6705 // r_io_sundo_push (core->io, addr, false); // doesnt seems to work
6706 }
6707 }
6708 break;
6709 case 'h':
6710 if (r_config_get_i (core->config, "scr.cursor")) {
6711 core->cons->cpos.x--;
6712 } else {
6713 if (core->print->cur_enabled) {
6714 core->print->cur--;
6715 } else {
6716 r_cons_switchbuf (false);
6717 if (cur->model->directionCb) {
6718 cur->model->directionCb (core, (int)LEFT);
6719 }
6720 }
6721 }
6722 break;
6723 case 'l':
6724 if (r_config_get_i (core->config, "scr.cursor")) {
6725 core->cons->cpos.x++;
6726 } else {
6727 if (core->print->cur_enabled) {
6728 core->print->cur++;
6729 } else {
6730 r_cons_switchbuf (false);
6731 if (cur->model->directionCb) {
6732 cur->model->directionCb (core, (int)RIGHT);
6733 }
6734 }
6735 }
6736 break;
6737 case 'V':
6738 if (r_config_get_i (core->config, "graph.web")) {
6739 r_core_cmd0 (core, "agv $$");
6740 } else {
6741 __call_visual_graph (core);
6742 }
6743 break;
6744 case ']':
6745 if (__check_panel_type (cur, PANEL_CMD_HEXDUMP)) {
6746 r_config_set_i (core->config, "hex.cols", r_config_get_i (core->config, "hex.cols") + 1);
6747 } else {
6748 int cmtcol = r_config_get_i (core->config, "asm.cmt.col");
6749 r_config_set_i (core->config, "asm.cmt.col", cmtcol + 2);
6750 }
6751 cur->view->refresh = true;
6752 break;
6753 case '[':
6754 if (__check_panel_type (cur, PANEL_CMD_HEXDUMP)) {
6755 r_config_set_i (core->config, "hex.cols", r_config_get_i (core->config, "hex.cols") - 1);
6756 } else {
6757 int cmtcol = r_config_get_i (core->config, "asm.cmt.col");
6758 if (cmtcol > 2) {
6759 r_config_set_i (core->config, "asm.cmt.col", cmtcol - 2);
6760 }
6761 }
6762 cur->view->refresh = true;
6763 break;
6764 case '/':
6765 r_core_cmd0 (core, "?i highlight;e scr.highlight=`yp`");
6766 break;
6767 case 'z':
6768 if (panels->curnode > 0) {
6769 __swap_panels (panels, 0, panels->curnode);
6770 __set_curnode (core, 0);
6771 }
6772 break;
6773 case 'i':
6774 if (cur->model->rotateCb) {
6775 cur->model->rotateCb (core, false);
6776 cur->view->refresh = true;
6777 }
6778 break;
6779 case 'I':
6780 if (cur->model->rotateCb) {
6781 cur->model->rotateCb (core, true);
6782 cur->view->refresh = true;
6783 }
6784 break;
6785 case 't':
6786 __handle_tab (core);
6787 if (panels_root->root_state != DEFAULT) {
6788 goto exit;
6789 }
6790 break;
6791 case 'T':
6792 if (panels_root->n_panels > 1) {
6793 __set_root_state (core, DEL);
6794 goto exit;
6795 }
6796 break;
6797 case 'w':
6798 __toggle_window_mode (core);
6799 break;
6800 case 'W':
6801 __move_panel_to_dir (core, cur, panels->curnode);
6802 break;
6803 case 0x0d: // "\\n"
6804 if (r_config_get_i (core->config, "scr.cursor")) {
6805 key = 0;
6806 r_cons_set_click (core->cons->cpos.x, core->cons->cpos.y);
6807 goto virtualmouse;
6808 } else {
6809 __toggle_zoom_mode (core);
6810 }
6811 break;
6812 case '|':
6813 {
6814 RPanel *p = __get_cur_panel (panels);
6815 __split_panel_vertical (core, p, p->model->title, p->model->cmd);
6816 break;
6817 }
6818 case '-':
6819 {
6820 RPanel *p = __get_cur_panel (panels);
6821 __split_panel_horizontal (core, p, p->model->title, p->model->cmd);
6822 break;
6823 }
6824 case '*':
6825 if (__check_func (core)) {
6826 r_cons_canvas_free (can);
6827 panels->can = NULL;
6828
6829 __replace_cmd (core, PANEL_TITLE_DECOMPILER, PANEL_CMD_DECOMPILER);
6830
6831 int h, w = r_cons_get_size (&h);
6832 panels->can = __create_new_canvas (core, w, h);
6833 }
6834 break;
6835 case '(':
6836 if (panels->fun != PANEL_FUN_SNOW && panels->fun != PANEL_FUN_SAKURA) {
6837 //TODO: Refactoring the FUN if bored af
6838 //panels->fun = PANEL_FUN_SNOW;
6839 panels->fun = PANEL_FUN_SAKURA;
6840 } else {
6841 panels->fun = PANEL_FUN_NOFUN;
6842 __reset_snow (panels);
6843 }
6844 break;
6845 case ')':
6846 __rotate_asmemu (core, __get_cur_panel (panels));
6847 break;
6848 case '&':
6849 __toggle_cache (core, __get_cur_panel (panels));
6850 break;
6851 case R_CONS_KEY_F1:
6852 cmd = r_config_get (core->config, "key.f1");
6853 if (cmd && *cmd) {
6854 (void)r_core_cmd0 (core, cmd);
6855 }
6856 break;
6857 case R_CONS_KEY_F2:
6858 cmd = r_config_get (core->config, "key.f2");
6859 if (cmd && *cmd) {
6860 (void)r_core_cmd0 (core, cmd);
6861 } else {
6862 __panel_breakpoint (core);
6863 }
6864 break;
6865 case R_CONS_KEY_F3:
6866 cmd = r_config_get (core->config, "key.f3");
6867 if (cmd && *cmd) {
6868 (void)r_core_cmd0 (core, cmd);
6869 }
6870 break;
6871 case R_CONS_KEY_F4:
6872 cmd = r_config_get (core->config, "key.f4");
6873 if (cmd && *cmd) {
6874 (void)r_core_cmd0 (core, cmd);
6875 }
6876 break;
6877 case R_CONS_KEY_F5:
6878 cmd = r_config_get (core->config, "key.f5");
6879 if (cmd && *cmd) {
6880 (void)r_core_cmd0 (core, cmd);
6881 }
6882 break;
6883 case R_CONS_KEY_F6:
6884 cmd = r_config_get (core->config, "key.f6");
6885 if (cmd && *cmd) {
6886 (void)r_core_cmd0 (core, cmd);
6887 }
6888 break;
6889 case R_CONS_KEY_F7:
6890 cmd = r_config_get (core->config, "key.f7");
6891 if (cmd && *cmd) {
6892 (void)r_core_cmd0 (core, cmd);
6893 } else {
6894 __panel_single_step_in (core);
6895 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6896 __set_panel_addr (core, cur, core->offset);
6897 }
6898 }
6899 break;
6900 case R_CONS_KEY_F8:
6901 cmd = r_config_get (core->config, "key.f8");
6902 if (cmd && *cmd) {
6903 (void)r_core_cmd0 (core, cmd);
6904 } else {
6905 __panel_single_step_over (core);
6906 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6907 __set_panel_addr (core, cur, core->offset);
6908 }
6909 }
6910 break;
6911 case R_CONS_KEY_F9:
6912 cmd = r_config_get (core->config, "key.f9");
6913 if (cmd && *cmd) {
6914 (void)r_core_cmd0 (core, cmd);
6915 } else {
6916 if (__check_panel_type (cur, PANEL_CMD_DISASSEMBLY)) {
6917 __panel_continue (core);
6918 __set_panel_addr (core, cur, core->offset);
6919 }
6920 }
6921 break;
6922 case R_CONS_KEY_F10:
6923 cmd = r_config_get (core->config, "key.f10");
6924 if (cmd && *cmd) {
6925 (void)r_core_cmd0 (core, cmd);
6926 }
6927 break;
6928 case R_CONS_KEY_F11:
6929 cmd = r_config_get (core->config, "key.f11");
6930 if (cmd && *cmd) {
6931 (void)r_core_cmd0 (core, cmd);
6932 }
6933 break;
6934 case R_CONS_KEY_F12:
6935 cmd = r_config_get (core->config, "key.f12");
6936 if (cmd && *cmd) {
6937 (void)r_core_cmd0 (core, cmd);
6938 }
6939 break;
6940 case 'Q':
6941 __set_root_state (core, QUIT);
6942 goto exit;
6943 case '!':
6944 fromVisual = true;
6945 case 'q':
6946 case -1: // EOF
6947 __set_root_state (core, DEL);
6948 if (core->panels_root->n_panels < 2) {
6949 if (r_config_get_i (core->config, "scr.demo")) {
6950 demo_end (core, can);
6951 }
6952 }
6953 goto exit;
6954 #if 0
6955 case 27: // ESC
6956 if (r_cons_readchar () == 91) {
6957 if (r_cons_readchar () == 90) {}
6958 }
6959 break;
6960 #endif
6961 default:
6962 // eprintf ("Key %d\n", key);
6963 // sleep (1);
6964 break;
6965 }
6966 goto repeat;
6967 exit:
6968 if (!originVmode) {
6969 r_core_visual_showcursor (core, true);
6970 }
6971 core->cons->event_resize = NULL;
6972 core->cons->event_data = NULL;
6973 core->print->cur = originCursor;
6974 core->print->cur_enabled = false;
6975 core->print->col = 0;
6976 core->vmode = originVmode;
6977 core->panels = prev;
6978 r_cons_set_interactive (o_interactive);
6979 }
6980
__del_panels(RCore * core)6981 static void __del_panels(RCore *core) {
6982 RPanelsRoot *panels_root = core->panels_root;
6983 if (panels_root->n_panels <= 1) {
6984 core->panels_root->root_state = QUIT;
6985 return;
6986 }
6987 int i;
6988 for (i = panels_root->cur_panels; i < panels_root->n_panels - 1; i++) {
6989 panels_root->panels[i] = panels_root->panels[i + 1];
6990 }
6991 panels_root->n_panels--;
6992 if (panels_root->cur_panels >= panels_root->n_panels) {
6993 panels_root->cur_panels = panels_root->n_panels - 1;
6994 }
6995 }
6996
r_core_panels_root(RCore * core,RPanelsRoot * panels_root)6997 R_API bool r_core_panels_root(RCore *core, RPanelsRoot *panels_root) {
6998 fromVisual = core->vmode;
6999 if (!panels_root) {
7000 panels_root = R_NEW0 (RPanelsRoot);
7001 if (!panels_root) {
7002 return false;
7003 }
7004 core->panels_root = panels_root;
7005 panels_root->panels = calloc (sizeof (RPanels *), PANEL_NUM_LIMIT);
7006 panels_root->n_panels = 0;
7007 panels_root->cur_panels = 0;
7008 panels_root->pdc_caches = sdb_new0 ();
7009 panels_root->cur_pdc_cache = NULL;
7010 __set_root_state (core, DEFAULT);
7011 __init_new_panels_root (core);
7012 } else {
7013 if (!panels_root->n_panels) {
7014 panels_root->n_panels = 0;
7015 panels_root->cur_panels = 0;
7016 __init_new_panels_root (core);
7017 }
7018 const char *pdc_now = r_config_get (core->config, "cmd.pdc");
7019 if (sdb_exists (panels_root->pdc_caches, pdc_now)) {
7020 panels_root->cur_pdc_cache = sdb_ptr_get (panels_root->pdc_caches, r_str_new (pdc_now), 0);
7021 } else {
7022 Sdb *sdb = sdb_new0();
7023 sdb_ptr_set (panels_root->pdc_caches, r_str_new (pdc_now), sdb, 0);
7024 panels_root->cur_pdc_cache = sdb;
7025 }
7026 }
7027 const char *layout = r_config_get (core->config, "scr.layout");
7028 if (!R_STR_ISEMPTY (layout)) {
7029 r_core_cmdf (core, "v %s", layout);
7030 }
7031 RPanels *panels = panels_root->panels[panels_root->cur_panels];
7032 if (panels) {
7033 size_t i = 0;
7034 for (; i < panels->n_panels; i++) {
7035 RPanel *cur = __get_panel (panels, i);
7036 if (cur) {
7037 cur->model->addr = core->offset;
7038 }
7039 }
7040 }
7041 while (panels_root->n_panels) {
7042 __set_root_state (core, DEFAULT);
7043 __panels_process (core, panels_root->panels[panels_root->cur_panels]);
7044 if (__check_root_state (core, DEL)) {
7045 __del_panels (core);
7046 }
7047 if (__check_root_state (core, QUIT)) {
7048 break;
7049 }
7050 }
7051 if (fromVisual) {
7052 r_core_cmdf (core, "V");
7053 } else {
7054 r_cons_enable_mouse (false);
7055 }
7056 return true;
7057 }
7058
__init_new_panels_root(RCore * core)7059 static void __init_new_panels_root(RCore *core) {
7060 RPanelsRoot *panels_root = core->panels_root;
7061 RPanels *panels = __panels_new (core);
7062 if (!panels) {
7063 return;
7064 }
7065 RPanels *prev = core->panels;
7066 core->panels = panels;
7067 panels_root->panels[panels_root->n_panels++] = panels;
7068 if (!__init_panels_menu (core)) {
7069 core->panels = prev;
7070 return;
7071 }
7072 if (!__init_panels (core, panels)) {
7073 core->panels = prev;
7074 return;
7075 }
7076 __init_all_dbs (core);
7077 __set_mode (core, PANEL_MODE_DEFAULT);
7078 __create_default_panels (core);
7079 __panels_layout (panels);
7080 core->panels = prev;
7081 }
7082