diff --git a/libr/core/panels.c b/libr/core/panels.c index a02a3bf744..34ff3bc815 100644 --- a/libr/core/panels.c +++ b/libr/core/panels.c @@ -9,29 +9,11 @@ #define PANEL_TITLE_SYMBOLS "Symbols" #define PANEL_TITLE_STACK "Stack" -#define PANEL_TITLE_LOCALS "Locals" #define PANEL_TITLE_STACKREFS "StackRefs" #define PANEL_TITLE_REGISTERS "Registers" #define PANEL_TITLE_REGISTERREFS "RegisterRefs" #define PANEL_TITLE_DISASSEMBLY "Disassembly" #define PANEL_TITLE_PSEUDO "Pseudo" -#define PANEL_TITLE_NEWFILES "New files" -#define PANEL_TITLE_INFO "Info" -#define PANEL_TITLE_DATABASE "Database" -#define PANEL_TITLE_HEXDUMP "Hexdump" -#define PANEL_TITLE_FUNCTIONS "Functions" -#define PANEL_TITLE_COMMENTS "Comments" -#define PANEL_TITLE_ENTROPY "Entropy" -#define PANEL_TITLE_DRX "DRX" -#define PANEL_TITLE_SECTIONS "Sections" -#define PANEL_TITLE_STRINGS "Strings" -#define PANEL_TITLE_MAPS "Maps" -#define PANEL_TITLE_MODULES "Modules" -#define PANEL_TITLE_BACKTRACE "Backtrace" -#define PANEL_TITLE_BREAKPOINTS "Breakpoints" -#define PANEL_TITLE_IMPORTS "Imports" -#define PANEL_TITLE_CLIPBOARD "Clipboard" -#define PANEL_TITLE_FCNINFO "FcnInfo" #define PANEL_TITLE_GRAPH "Graph" #define PANEL_CMD_SYMBOLS "isq" @@ -43,23 +25,8 @@ #define PANEL_CMD_DISASSEMBLY "pd $r" #define PANEL_CMD_PSEUDO "pdc" #define PANEL_CMD_GRAPH "agf" -#define PANEL_CMD_INFO "i" -#define PANEL_CMD_DATABASE "k ***" -#define PANEL_CMD_HEXDUMP "px 512" -#define PANEL_CMD_FUNCTIONS "afl" -#define PANEL_CMD_COMMENTS "CC" -#define PANEL_CMD_ENTROPY "p=e" -#define PANEL_CMD_DRX "drx" -#define PANEL_CMD_SECTIONS "iSq" -#define PANEL_CMD_STRINGS "izq" -#define PANEL_CMD_MAPS "dm" -#define PANEL_CMD_MODULES "dmm" -#define PANEL_CMD_BACKTRACE "dbt" -#define PANEL_CMD_BREAKPOINTS "db" -#define PANEL_CMD_IMPORTS "iiq" -#define PANEL_CMD_CLIPBOARD "yx" -#define PANEL_CMD_FCNINFO "afi" +#define PANEL_CONFIG_MENU_MAX 64 #define PANEL_CONFIG_PAGE 10 #define PANEL_CONFIG_SIDEPANEL_W 60 #define PANEL_CONFIG_RESIZE_W 4 @@ -76,71 +43,74 @@ static const char *menus[] = { "File", "Edit", "View", "Tools", "Search", "Debug", "Analyze", "Help", NULL }; -static const int menuNum = ((int)sizeof (menus) / (int)sizeof (const char*)) - 1; +static const int menuNum = ((int)sizeof (menus) / (int)sizeof (const char *)) - 1; static const char *menus_File[] = { "New", "Open", "ReOpen", "Close", "Sections", "Strings", "Symbols", "Imports", "Info", "Database", "Save Layout", "Load Layout", "Quit", NULL }; +static const int fileNum = ((int)sizeof (menus_File) / (int)sizeof (const char *)) - 1; static const char *menus_ReOpen[] = { "In RW", "In Debugger", NULL }; +static const int reopenNum = ((int)sizeof (menus_ReOpen) / (int)sizeof (const char *)) - 1; static const char *menus_Edit[] = { "Copy", "Paste", "Clipboard", "Write String", "Write Hex", "Write Value", "Assemble", "Fill", "io.cache", NULL }; +static const int editNum = ((int)sizeof (menus_Edit) / (int)sizeof (const char *)) - 1; static const char *menus_View[] = { "Hexdump", "Disassembly", "Graph", "FcnInfo", "Functions", "Comments", "Entropy", "Colors", "Stack", "StackRefs", "Pseudo", NULL }; +static const int viewNum = ((int)sizeof (menus_View) / (int)sizeof (const char *)) - 1; static const char *menus_Tools[] = { - "Assembler", "Calculator", "R2 Shell", "System Shell", + "Calculator", "R2 Shell", "System Shell", NULL }; +static const int toolsNum = ((int)sizeof (menus_Tools) / (int)sizeof (const char *)) - 1; static const char *menus_Search[] = { "String", "ROP", "Code", "Hexpairs", NULL }; +static const int searchNum = ((int)sizeof (menus_Search) / (int)sizeof (const char *)) - 1; static const char *menus_Debug[] = { "Registers", "RegisterRefs", "DRX", "Breakpoints", - "Watchpoints", "Maps", "Modules", - "Backtrace", "Locals", - "Continue", "Cont until.", - "Step", "Step Over", - "Reload", + "Maps", "Modules", "Backtrace", "Locals", "Continue", + "Step", "Step Over", "Reload", NULL }; +static const int debugNum = ((int)sizeof (menus_Debug) / (int)sizeof (const char *)) - 1; static const char *menus_Analyze[] = { "Function", "Symbols", "Program", "BasicBlocks", "Calls", "References", NULL }; +static const int analyzeNum = ((int)sizeof (menus_Analyze) / (int)sizeof (const char *)) - 1; static const char *menus_Help[] = { - "Fortune", "Commands", "2048", "License", ".", "About", + "Fortune", "Commands", "2048", "License", "About", NULL }; +static const int helpNum = ((int)sizeof (menus_Help) / (int)sizeof (const char *)) - 1; -static void layoutMenu(RPanel *panel); -static void layoutSubMenu(RPanels *panels, int w); static void layoutDefault(RPanels *panels); static void layoutBalance(RPanels *panels); -static void layoutSidePanel(RCore *core, const char *title, const char *cmd); +static int layoutSidePanel(void *user); static void changePanelNum(RPanels *panels, int now, int after); static void splitPanelVertical(RCore *core); static void splitPanelHorizontal(RCore *core); static void panelPrint(RCore *core, RConsCanvas *can, RPanel *panel, int color); static void panelAllClear(RPanels *panels); static void addPanelFrame(RCore* core, RPanels* panels, const char *title, const char *cmd); -static RPanel createMenuPanel(int x, int y, char *title); static bool checkFunc(RCore *core); static void activateCursor(RCore *core); static void cursorLeft(RCore *core); @@ -165,9 +135,53 @@ static void resizePanelRight(RPanels *panels); static void resizePanelUp(RPanels *panels); static void resizePanelDown(RPanels *panels); static void handleTabKey(RCore *core, bool shift); +static int openMenuCb(void *user); +static int openFileCb(void *user); +static int rwCb(void *user); +static int debuggerCb(void *user); +static int closeFileCb(void *user); +static int copyCb(void *user); +static int pasteCb(void *user); +static int writeStrCb(void *user); +static int writeHexCb(void *user); +static int assembleCb(void *user); +static int fillCb(void *user); +static int iocacheCb(void *user); +static int colorsCb(void *user); +static int calculatorCb(void *user); +static int r2shellCb(void *user); +static int systemShellCb(void *user); +static int stringCb(void *user); +static int ropCb(void *user); +static int codeCb(void *user); +static int hexpairsCb(void *user); +static int continueCb(void *user); +static int stepCb(void *user); +static int stepoverCb(void *user); +static int reloadCb(void *user); +static int functionCb(void *user); +static int symbolsCb(void *user); +static int programCb(void *user); +static int basicblocksCb(void *user); +static int callsCb(void *user); +static int referencesCb(void *user); +static int fortuneCb(void *user); +static int commandsCb(void *user); +static int gameCb(void *user); +static int licenseCb(void *user); +static int aboutCb(void *user); +static int quitCb(void *user); +static void addMenu(RPanelsMenuItem *parent, const char *name, RPanelsMenuCallback cb); +static int file_history_up(RLine *line); +static int file_history_down(RLine *line); static char *getPanelsConfigPath(); static bool init(RCore *core, RPanels *panels, int w, int h); +static void initSdb(RPanels *panels); +static bool initPanelsMenu(RPanels *panels); static bool initPanels(RCore *core, RPanels *panels); +static RStrBuf *drawMenu(RPanelsMenuItem *item); +static void positionNewMenu(RPanelsMenu *menu, RPanelsMenuItem *parent, RPanelsMenuItem *child); +static void moveMenuCursor(RPanelsMenu *menu, RPanelsMenuItem *parent); static void freeSinglePanel(RPanel *panel); static void freeAllPanels(RPanels *panels); static void panelBreakpoint(RCore *core); @@ -183,8 +197,6 @@ static void savePanelsLayout(RPanels* panels); static void loadPanelsLayout(RCore *core); static void replaceCmd(RPanels* panels, char *title, char *cmd); static void handleMenu(RCore *core, const int key, int *exit); -static void onMenu(RCore *core, const char *menu, int *exit); -static void changeMenu(RPanels *panels, const char **dstMenu); static void switchMode(RPanels *panels); static void maximizePanelSize(RPanels *panels); static void insertValue(RCore *core); @@ -314,61 +326,6 @@ static void panelAllClear(RPanels *panels) { r_cons_flush (); } -static void layoutMenu(RPanel *panel) { - panel->pos.w = r_str_bounds (panel->title, &panel->pos.h); - panel->pos.h += 4; -} - -static void layoutSubMenu(RPanels *panels, int w) { - int i, j; - RPanel panel; - int x = panels->menuIndexStack[0] * 6; - int y = 1; - const char **currentMenu; - int currentMenuIndex; - for (i = 0; i < panels->menuStackDepth; i++) { - if (i == 0) { - continue; - } - currentMenu = panels->menuStack[i]; - currentMenuIndex = panels->menuIndexStack[i]; - RStrBuf *tit = r_strbuf_new (NULL); - if (!tit) { - return; - } - for (j = 0; currentMenu[j]; j++) { - if (currentMenuIndex == j) { - r_strbuf_append (tit, "> "); - } else { - r_strbuf_append (tit, " "); - } - r_strbuf_append (tit, currentMenu[j]); - r_strbuf_append (tit, " \n"); - } - panel = createMenuPanel (x, y, r_strbuf_drain (tit)); - layoutMenu (&panel); - panels->menuPanel[i] = panel; - x += panel.pos.w - 1; - y = panels->menuIndexStack[i] + 2; - } - RStrBuf *tit = r_strbuf_new (NULL); - if (!tit) { - return; - } - for (i = 0; panels->currentMenu[i]; i++) { - if (panels->currentMenuIndex == i) { - r_strbuf_append (tit, "> "); - } else { - r_strbuf_append (tit, " "); - } - r_strbuf_append (tit, panels->currentMenu[i]); - r_strbuf_append (tit, " \n"); - } - panel = createMenuPanel (x, y, r_strbuf_drain (tit)); - layoutMenu (&panel); - panels->menuPanel[panels->menuStackDepth] = panel; -} - R_API void r_core_panels_layout (RPanels *panels) { panels->can->sx = 0; panels->can->sy = 0; @@ -445,14 +402,19 @@ static void layoutBalance(RPanels *panels) { } } -static void layoutSidePanel(RCore *core, const char *title, const char *cmd) { +static int layoutSidePanel(void *user) { + RCore *core = (RCore *)user; RPanels *panels = core->panels; RPanel *panel = panels->panel; - int h; - r_cons_get_size (&h); - int i; + RPanelsMenu *menu = core->panels->panelsMenu; + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + RPanelsMenuItem *child = parent->sub[parent->selectedIndex]; + const char *cmd = sdb_get (panels->db, child->name, 0); + if (!cmd) { + return 0; + } + int i, h; (void)r_cons_get_size (&h); - for (i = 0; i < panels->n_panels; i++) { RPanel *p = &panel[i]; if (p->pos.x == 0) { @@ -462,8 +424,7 @@ static void layoutSidePanel(RCore *core, const char *title, const char *cmd) { } } } - - addPanelFrame (core, panels, title, cmd); + addPanelFrame (core, panels, child->name, cmd); changePanelNum (panels, panels->n_panels - 1, 0); panel[0].pos.x = 0; panel[0].pos.y = 1; @@ -471,6 +432,7 @@ static void layoutSidePanel(RCore *core, const char *title, const char *cmd) { panel[0].pos.h = h - 1; panels->curnode = 0; setRefreshAll (panels); + return 0; } static void splitPanelVertical(RCore *core) { @@ -687,21 +649,17 @@ static void handleUpKey(RCore *core) { r_cons_switchbuf (false); if (panels->curnode == panels->menu_pos) { - if (panels->menuStackDepth == 0) { + RPanelsMenu *menu = panels->panelsMenu; + if (menu->depth < 2) { return; - } else if (panels->menuStackDepth == 1) { - if (!panels->currentMenuIndex) { - panels->menuStackDepth = 0; - panels->currentMenuIndex = panels->menuIndexStack[0]; - panels->currentMenu = panels->menuStack[0]; - setRefreshAll (panels); - } else { - panels->currentMenuIndex--; - } - } else { - if (panels->currentMenuIndex) { - panels->currentMenuIndex--; - } + } + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + if (parent->selectedIndex > 0) { + parent->selectedIndex--; + moveMenuCursor (menu, parent); + } else if (menu->depth == 2) { + menu->depth--; + setRefreshAll (panels); } } else { panels->panel[panels->curnode].refresh = true; @@ -750,13 +708,14 @@ static void handleDownKey(RCore *core) { RPanels *panels = core->panels; r_cons_switchbuf (false); if (panels->curnode == panels->menu_pos) { - if (!panels->menuStackDepth) { - int exit = 0; - onMenu (core, panels->currentMenu[panels->currentMenuIndex], &exit); + RPanelsMenu *menu = panels->panelsMenu; + if (menu->depth == 1) { + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + parent->sub[parent->selectedIndex]->cb(core); } else { - if (panels->currentMenu[panels->currentMenuIndex + 1]) { - panels->currentMenuIndex++; - } + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + parent->selectedIndex = R_MIN (parent->n_sub - 1, parent->selectedIndex + 1); + moveMenuCursor (menu, parent); } } else { panels->panel[panels->curnode].refresh = true; @@ -799,21 +758,18 @@ static void handleLeftKey(RCore *core) { RPanels *panels = core->panels; r_cons_switchbuf (false); if (panels->curnode == panels->menu_pos) { - if (!panels->menuStackDepth) { - if (panels->currentMenuIndex) { - panels->currentMenuIndex--; - } else { - panels->currentMenuIndex = menuNum - 1; - } - } else if (panels->menuStackDepth > 0) { - panels->menuStackDepth = 0; - panels->currentMenu = panels->menuStack[0]; - if (panels->menuIndexStack[0]) { - panels->currentMenuIndex = panels->menuIndexStack[0] - 1; + RPanelsMenu *menu = panels->panelsMenu; + if (menu->depth <= 2) { + if (menu->root->selectedIndex > 0) { + menu->root->selectedIndex--; } else { - panels->currentMenuIndex = menuNum - 1; + menu->root->selectedIndex = menu->root->n_sub - 1; + } + if (menu->depth == 2) { + menu->depth = 1; + setRefreshAll (panels); + menu->root->sub[menu->root->selectedIndex]->cb (core); } - setRefreshAll (panels); } } else if (!strcmp (panels->panel[panels->curnode].cmd, PANEL_CMD_GRAPH)) { if (panels->panel[panels->curnode].sx > 0) { @@ -838,15 +794,21 @@ static void handleRightKey(RCore *core) { RPanels *panels = core->panels; r_cons_switchbuf (false); if (panels->curnode == panels->menu_pos) { - if (!panels->menuStackDepth) { - panels->currentMenuIndex++; - panels->currentMenuIndex %= menuNum; - } else if (panels->menuStackDepth > 0) { - panels->menuStackDepth = 0; - panels->currentMenu = panels->menuStack[0]; - panels->currentMenuIndex = panels->menuIndexStack[0] + 1; - panels->currentMenuIndex %= menuNum; + RPanelsMenu *menu = panels->panelsMenu; + if (menu->depth == 1) { + menu->root->selectedIndex++; + menu->root->selectedIndex %= menu->root->n_sub; + return; + } + RPanelsMenuItem *child = menu->history[menu->depth - 1]; + if (child->sub[child->selectedIndex]->sub) { + child->sub[child->selectedIndex]->cb (core); + } else { + menu->root->selectedIndex++; + menu->root->selectedIndex %= menu->root->n_sub; + menu->depth = 1; setRefreshAll (panels); + menu->root->sub[menu->root->selectedIndex]->cb (core); } } else if (!strcmp (panels->panel[panels->curnode].cmd, PANEL_CMD_GRAPH)) { panels->panel[panels->curnode].sx += r_config_get_i (core->config, "graph.scroll"); @@ -1568,14 +1530,505 @@ static void addPanelFrame(RCore *core, RPanels* panels, const char *title, const panels->n_panels++; } -static RPanel createMenuPanel(int x, int y, char *title) { - RPanel panel = {{0}}; - panel.pos.x = x; - panel.pos.y = y; - panel.title = title; - panel.refresh = true; - panel.type = PANEL_TYPE_MENU; - return panel; +static int openFileCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + core->cons->line->file_prompt = true; + r_line_set_hist_callback (core->cons->line, &file_history_up, &file_history_down); + char *res = r_cons_input ("open file: "); + if (res) { + if (*res) { + r_core_cmdf (core, "o %s", res); + } + free (res); + } + core->cons->line->file_prompt = false; + r_line_set_hist_callback (core->cons->line, &cmd_history_up, &cmd_history_down); + r_cons_enable_mouse (true); + return 0; +} + +static int rwCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "oo+", 0); + return 0; +} + +static int debuggerCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "oo", 0); + return 0; +} + +static int closeFileCb (void *user) { + RCore *core = (RCore *)user; + r_core_cmd0 (core, "o-*"); + return 0; +} + +static int copyCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("How many bytes? "); + if (res) { + r_core_cmdf (core, "\"y %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int pasteCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd0 (core, "yy"); + return 0; +} + +static int writeStrCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("insert string: "); + if (res) { + r_core_cmdf (core, "\"w %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int writeHexCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("insert hexpairs: "); + if (res) { + r_core_cmdf (core, "\"wx %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int assembleCb(void *user) { + RCore *core = (RCore *)user; + r_core_visual_asm (core, core->offset); + return 0; +} + +static int fillCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *s = r_cons_input ("Fill with: "); + r_core_cmdf (core, "wow %s", s); + free (s); + r_cons_enable_mouse (true); + return 0; +} + +static int iocacheCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd0 (core, "e!io.cache"); + return 0; +} + +static int colorsCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd0 (core, "e!scr.color"); + return 0; +} + +static int calculatorCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + for (;;) { + char *s = r_cons_input ("> "); + if (!s || !*s) { + free (s); + break; + } + r_core_cmdf (core, "? %s", s); + r_cons_flush (); + free (s); + } + r_cons_enable_mouse (true); + return 0; +} + +static int r2shellCb(void *user) { + RCore *core = (RCore *)user; + core->vmode = false; + r_core_visual_prompt_input (core); + core->vmode = true; + return 0; +} + +static int systemShellCb(void *user) { + r_cons_set_raw (0); + r_cons_flush (); + r_sys_cmd ("$SHELL"); + return 0; +} + +static int stringCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("search string: "); + if (res) { + r_core_cmdf (core, "\"/ %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int ropCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("rop grep: "); + if (res) { + r_core_cmdf (core, "\"/R %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int codeCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("search code: "); + if (res) { + r_core_cmdf (core, "\"/c %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int hexpairsCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("search hexpairs: "); + if (res) { + r_core_cmdf (core, "\"/x %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int continueCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "dc", 0); + r_cons_flush (); + return 0; +} + +static int stepCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "ds", 0); + r_cons_flush (); + return 0; +} + +static int stepoverCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "dso", 0); + r_cons_flush (); + return 0; +} + +static int reloadCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd (core, "ood", 0); + r_cons_flush (); + return 0; +} + +static int functionCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "af"); + return 0; +} + +static int symbolsCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "aa"); + return 0; +} + +static int programCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "aaa"); + return 0; +} + +static int basicblocksCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "aab"); + return 0; +} + +static int callsCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "aac"); + return 0; +} + +static int referencesCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmdf (core, "aar"); + return 0; +} + +static int fortuneCb(void *user) { + RCore *core = (RCore *)user; + char *s = r_core_cmd_str (core, "fo"); + r_cons_message (s); + free (s); + return 0; +} + +static int commandsCb(void *user) { + RCore *core = (RCore *)user; + r_core_cmd0 (core, "?;?@?;?$?;???"); + r_cons_any_key (NULL); + return 0; +} + +static int gameCb(void *user) { + RCore *core = (RCore *)user; + r_cons_2048 (core->panels->can->color); + return 0; +} + +static int licenseCb(void *user) { + r_cons_message ("Copyright 2006-2016 - pancake - LGPL"); + return 0; +} + +static int aboutCb(void *user) { + RCore *core = (RCore *)user; + char *s = r_core_cmd_str (core, "?V"); + r_cons_message (s); + free (s); + return 0; +} + +static int writeValueCb(void *user) { + RCore *core = (RCore *)user; + r_cons_enable_mouse (false); + char *res = r_cons_input ("insert number: "); + if (res) { + r_core_cmdf (core, "\"wv %s\"", res); + free (res); + } + r_cons_enable_mouse (true); + return 0; +} + +static int quitCb(void *user) { + return 0; +} + +static int openMenuCb (void *user) { + RCore* core = (RCore *)user; + RPanelsMenu *menu = core->panels->panelsMenu; + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + RPanelsMenuItem *child = parent->sub[parent->selectedIndex]; + positionNewMenu (menu, parent, child); + menu->history[menu->depth++] = child; + return 0; +} + +static void addMenu(RPanelsMenuItem *parent, const char *name, RPanelsMenuCallback cb) { + RPanelsMenuItem *item = R_NEW0 (RPanelsMenuItem); + item->n_sub = 0; + item->selectedIndex = 0; + item->name = name ? strdup (name) : NULL; + item->sub = NULL; + item->cb = cb; + item->p = R_NEW0 (RPanel); + item->selfIndex = parent->n_sub; + parent->n_sub++; + parent->sub = realloc (parent->sub, sizeof (RPanelsMenuItem *) * parent->n_sub); + parent->sub[parent->n_sub - 1] = item; +} + +static RStrBuf *drawMenu(RPanelsMenuItem *item) { + RStrBuf *buf = r_strbuf_new (NULL); + if (!buf) { + return NULL; + } + int i; + for (i = 0; i < item->n_sub; i++) { + if (i == item->selectedIndex) { + r_strbuf_append (buf, "> "); + } else { + r_strbuf_append (buf, " "); + } + r_strbuf_append (buf, item->sub[i]->name); + r_strbuf_append (buf, " \n"); + } + return buf; +} + +static void positionNewMenu(RPanelsMenu *menu, RPanelsMenuItem *parent, RPanelsMenuItem *child) { + child->p->pos.x = menu->depth <= 2 ? child->selfIndex * 6 : parent->p->pos.x + parent->p->pos.w - 1; + child->p->pos.y = menu->depth <= 2 ? 1 : parent->selectedIndex + 2; + RStrBuf *buf = drawMenu (child); + if (!buf) { + return; + } + child->p->title = r_strbuf_drain (buf); + child->p->pos.w = r_str_bounds (child->p->title, &child->p->pos.h); + child->p->pos.h += 4; + child->p->type = PANEL_TYPE_MENU; + child->p->refresh = true; + menu->refreshPanels[menu->n_refresh++] = child->p; +} + +static void moveMenuCursor(RPanelsMenu *menu, RPanelsMenuItem *parent) { + RStrBuf *buf = drawMenu (parent); + if (!buf) { + return; + } + parent->p->title = r_strbuf_drain (buf); + parent->p->pos.w = r_str_bounds (parent->p->title, &parent->p->pos.h); + parent->p->pos.h += 4; + parent->p->type = PANEL_TYPE_MENU; + parent->p->refresh = true; + menu->refreshPanels[menu->n_refresh++] = parent->p; +} + +static bool initPanelsMenu(RPanels *panels) { + RPanelsMenu *panelsMenu = R_NEW0 (RPanelsMenu); + RPanelsMenuItem *root = R_NEW0 (RPanelsMenuItem); + root->n_sub = 0; + root->selectedIndex = 0; + root->name = NULL; + root->sub = NULL; + int i; + for (i = 0; i < menuNum; i++) { + addMenu (root, menus[i], openMenuCb); + } + for (i = 0; i < fileNum; i++) { + if (!strcmp (menus_File[i], "Open")) { + addMenu (root->sub[0], menus_File[i], openFileCb); + } else if (!strcmp (menus_File[i], "ReOpen")) { + addMenu (root->sub[0], menus_File[i], openMenuCb); + } else if (!strcmp (menus_File[i], "Close")) { + addMenu (root->sub[0], menus_File[i], closeFileCb); + } else if (!strcmp (menus_File[i], "Quit")) { + addMenu (root->sub[0], menus_File[i], quitCb); + } else { + addMenu (root->sub[0], menus_File[i], layoutSidePanel); + } + } + for (i = 0; i < editNum; i++) { + if (!strcmp (menus_Edit[i], "Copy")) { + addMenu (root->sub[1], menus_Edit[i], copyCb); + } else if (!strcmp (menus_Edit[i], "Paste")) { + addMenu (root->sub[1], menus_Edit[i], pasteCb); + } else if (!strcmp (menus_Edit[i], "Write String")) { + addMenu (root->sub[1], menus_Edit[i], writeStrCb); + } else if (!strcmp (menus_Edit[i], "Write Hex")) { + addMenu (root->sub[1], menus_Edit[i], writeHexCb); + } else if (!strcmp (menus_Edit[i], "Write Value")) { + addMenu (root->sub[1], menus_Edit[i], writeValueCb); + } else if (!strcmp (menus_Edit[i], "Assemble")) { + addMenu (root->sub[1], menus_Edit[i], assembleCb); + } else if (!strcmp (menus_Edit[i], "Fill")) { + addMenu (root->sub[1], menus_Edit[i], fillCb); + } else if (!strcmp (menus_Edit[i], "io.cache")) { + addMenu (root->sub[1], menus_Edit[i], iocacheCb); + } else { + addMenu (root->sub[1], menus_Edit[i], layoutSidePanel); + } + } + for (i = 0; i < viewNum; i++) { + if (!strcmp (menus_View[i], "Colors")) { + addMenu (root->sub[2], menus_View[i], colorsCb); + } else { + addMenu (root->sub[2], menus_View[i], layoutSidePanel); + } + } + for (i = 0; i < toolsNum; i++) { + if (!strcmp (menus_Tools[i], "Calculator")) { + addMenu (root->sub[3], menus_Tools[i], calculatorCb); + } else if (!strcmp (menus_Tools[i], "R2 Shell")) { + addMenu (root->sub[3], menus_Tools[i], r2shellCb); + } else if (!strcmp (menus_Tools[i], "System Shell")) { + addMenu (root->sub[3], menus_Tools[i], systemShellCb); + } + } + for (i = 0; i < searchNum; i++) { + if (!strcmp (menus_Search[i], "String")) { + addMenu (root->sub[4], menus_Search[i], stringCb); + } else if (!strcmp (menus_Search[i], "ROP")) { + addMenu (root->sub[4], menus_Search[i], ropCb); + } else if (!strcmp (menus_Search[i], "Code")) { + addMenu (root->sub[4], menus_Search[i], codeCb); + } else if (!strcmp (menus_Search[i], "Hexpairs")) { + addMenu (root->sub[4], menus_Search[i], hexpairsCb); + } + } + for (i = 0; i < debugNum; i++) { + if (!strcmp (menus_Debug[i], "Continue")) { + addMenu (root->sub[5], menus_Debug[i], continueCb); + } else if (!strcmp (menus_Debug[i], "Step")) { + addMenu (root->sub[5], menus_Debug[i], stepCb); + } else if (!strcmp (menus_Debug[i], "Step Over")) { + addMenu (root->sub[5], menus_Debug[i], stepoverCb); + } else if (!strcmp (menus_Debug[i], "Reload")) { + addMenu (root->sub[5], menus_Debug[i], reloadCb); + } else { + addMenu (root->sub[5], menus_Debug[i], layoutSidePanel); + } + } + for (i = 0; i < analyzeNum; i++) { + if (!strcmp (menus_Analyze[i], "Function")) { + addMenu (root->sub[6], menus_Analyze[i], functionCb); + } else if (!strcmp (menus_Analyze[i], "Symbols")) { + addMenu (root->sub[6], menus_Analyze[i], symbolsCb); + } else if (!strcmp (menus_Analyze[i], "Program")) { + addMenu (root->sub[6], menus_Analyze[i], programCb); + } else if (!strcmp (menus_Analyze[i], "BasicBlocks")) { + addMenu (root->sub[6], menus_Analyze[i], basicblocksCb); + } else if (!strcmp (menus_Analyze[i], "Calls")) { + addMenu (root->sub[6], menus_Analyze[i], callsCb); + } else if (!strcmp (menus_Analyze[i], "References")) { + addMenu (root->sub[6], menus_Analyze[i], referencesCb); + } + } + for (i = 0; i < helpNum; i++) { + if (!strcmp (menus_Help[i], "Fortune")) { + addMenu (root->sub[7], menus_Help[i], fortuneCb); + } else if (!strcmp (menus_Help[i], "Commands")) { + addMenu (root->sub[7], menus_Help[i], commandsCb); + } else if (!strcmp (menus_Help[i], "2048")) { + addMenu (root->sub[7], menus_Help[i], gameCb); + } else if (!strcmp (menus_Help[i], "License")) { + addMenu (root->sub[7], menus_Help[i], licenseCb); + } else if (!strcmp (menus_Help[i], "About")) { + addMenu (root->sub[7], menus_Help[i], aboutCb); + } + } + for (i = 0; i < reopenNum; i++) { + if (!strcmp (menus_ReOpen[i], "In RW")) { + addMenu (root->sub[0]->sub[2], menus_ReOpen[i], rwCb); + } else if (!strcmp (menus_ReOpen[i], "In Debugger")) { + addMenu (root->sub[0]->sub[2], menus_ReOpen[i], debuggerCb); + } + } + root->selectedIndex = 0; + panelsMenu->root = root; + panelsMenu->history = calloc (8, sizeof (RPanelsMenuItem *)); + panelsMenu->history[0] = root; + panelsMenu->depth = 1; + panelsMenu->n_refresh = 0; + panelsMenu->refreshPanels = calloc (8, sizeof (RPanel *)); + panels->panelsMenu = panelsMenu; + return true; } static bool initPanels(RCore *core, RPanels *panels) { @@ -1607,11 +2060,6 @@ static void freeAllPanels(RPanels *panels) { free (panels->panel); } -// damn singletons.. there should be only one screen and therefor -// only one visual instance of the graph view. refactoring this -// into a struct makes the code to reference pointers unnecesarily -// we can look for a non-global solution here in the future if -// necessary R_API void r_core_panels_refresh(RCore *core) { RPanels *panels = core->panels; if (!panels) { @@ -1625,11 +2073,6 @@ R_API void r_core_panels_refresh(RCore *core) { if (!can) { return; } - if (panels->curnode > panels->menu_pos) { - panels->menuStackDepth = 0; - panels->currentMenu = NULL; - panels->currentMenuIndex = 0; - } char title[1024]; char str[1024]; int i, h, w = r_cons_get_size (&h); @@ -1649,12 +2092,10 @@ R_API void r_core_panels_refresh(RCore *core) { if (panels->curnode > panels->menu_pos) { panelPrint (core, can, &panel[panels->curnode], 1); } - if (panels->curnode == panels->menu_pos && panels->menuStackDepth > 0) { - layoutSubMenu (panels, w); - for (i = 0; i <= panels->menuStackDepth; i++) { - panelPrint (core, can, &panels->menuPanel[i], 1); - } + for (i = 0; i < panels->panelsMenu->n_refresh; i++) { + panelPrint (core, can, panels->panelsMenu->refreshPanels[i], 1); } + panels->panelsMenu->n_refresh = 0; (void) r_cons_canvas_gotoxy (can, -can->sx, -can->sy); r_cons_canvas_fill (can, -can->sx, -can->sy, panel->pos.w, 1, ' '); title[0] = 0; @@ -1666,23 +2107,17 @@ R_API void r_core_panels_refresh(RCore *core) { snprintf (str, sizeof (title) - 1, "%s Zoom Mode: Press Enter or q to quit"Color_RESET, color); strcat (title, str); } else { - for (i = 0; menus[i]; i++) { + RPanelsMenuItem *parent = panels->panelsMenu->root; + for (i = 0; i < parent->n_sub; i++) { + RPanelsMenuItem *item = parent->sub[i]; if (panels->curnode == panels->menu_pos) { - if (panels->menuStackDepth > 0) { - if (i == panels->menuIndexStack[0]) { - snprintf (str, sizeof (title) - 1, "%s[%s]"Color_RESET, color, menus[i]); - } else { - snprintf (str, sizeof (title) - 1, "%s %s "Color_RESET, color, menus[i]); - } + if (i == parent->selectedIndex) { + snprintf (str, sizeof (title) - 1, "%s[%s]"Color_RESET, color, item->name); } else { - if (i == panels->currentMenuIndex) { - snprintf (str, sizeof (title) - 1, "%s[%s]"Color_RESET, color, menus[i]); - } else { - snprintf (str, sizeof (title) - 1, "%s %s "Color_RESET, color, menus[i]); - } + snprintf (str, sizeof (title) - 1, "%s %s "Color_RESET, color, item->name); } } else { - snprintf (str, sizeof (title) - 1, "%s %s "Color_RESET, color, menus[i]); + snprintf (str, sizeof (title) - 1, "%s %s "Color_RESET, color, item->name); } strcat (title, str); } @@ -1783,29 +2218,54 @@ static void panelPrompt(const char *prompt, char *buf, int len) { r_cons_fgets (buf, len, 0, NULL); } +static void initSdb(RPanels *panels) { + sdb_set (panels->db, "Symbols", "isq", 0); + sdb_set (panels->db, "Stack" , "px 256@r:SP", 0); + sdb_set (panels->db, "Locals", "afvd", 0); + sdb_set (panels->db, "StackRefs", "pxr 256@r:SP", 0); + sdb_set (panels->db, "Registers", "dr=", 0); + sdb_set (panels->db, "RegisterRefs", "drr", 0); + sdb_set (panels->db, "Disassembly", "pd $r", 0); + sdb_set (panels->db, "Pseudo", "pdc", 0); + sdb_set (panels->db, "Graph", "agf", 0); + sdb_set (panels->db, "Info", "i", 0); + sdb_set (panels->db, "Database", "k ***", 0); + sdb_set (panels->db, "Hexdump", "px 512", 0); + sdb_set (panels->db, "Functions", "afl", 0); + sdb_set (panels->db, "Comments", "CC", 0); + sdb_set (panels->db, "Entropy", "p=e", 0); + sdb_set (panels->db, "DRX", "drx", 0); + sdb_set (panels->db, "Sections", "iSq", 0); + sdb_set (panels->db, "Strings", "izq", 0); + sdb_set (panels->db, "Maps", "dm", 0); + sdb_set (panels->db, "Modules", "dmm", 0); + sdb_set (panels->db, "Backtrace", "dbt", 0); + sdb_set (panels->db, "Breakpoints", "db", 0); + sdb_set (panels->db, "Imports", "iiq", 0); + sdb_set (panels->db, "Clipboard", "yx", 0); + sdb_set (panels->db, "FcnInfo", "afi", 0); + sdb_set (panels->db, "New", "o", 0); +} + static bool init (RCore *core, RPanels *panels, int w, int h) { panels->panel = NULL; panels->n_panels = 0; panels->columnWidth = 80; panels->layout = 0; panels->menu_pos = -1; - panels->menuStack = calloc (sizeof (char **), PANEL_MENU_LIMIT); - panels->menuIndexStack = calloc (sizeof (int), PANEL_MENU_LIMIT); - panels->menuStackDepth = 0; - panels->currentMenu = NULL; - panels->currentMenuIndex = 0; - panels->menuPanel = calloc (sizeof (RPanel), PANEL_MENU_LIMIT); - panels->callgraph = 0; panels->isResizing = false; panels->isZoom = false; panels->can = createNewCanvas (core, w, h); + panels->db = sdb_new0 (); + initSdb (panels); + if (w < 140) { panels->columnWidth = w / 3; } return true; } -R_API int file_history_up(RLine *line) { +static int file_history_up(RLine *line) { RCore *core = line->user; RList *files = r_id_storage_list (core->io->files); int num_files = r_list_length (files); @@ -1820,7 +2280,7 @@ R_API int file_history_up(RLine *line) { return true; } -R_API int file_history_down(RLine *line) { +static int file_history_down(RLine *line) { RCore *core = line->user; RList *files = r_id_storage_list (core->io->files); int num_files = r_list_length (files); @@ -1842,6 +2302,9 @@ R_API int file_history_down(RLine *line) { static void handleMenu(RCore *core, const int key, int *exit) { RPanels *panels = core->panels; + RPanelsMenu *menu = panels->panelsMenu; + RPanelsMenuItem *parent = menu->history[menu->depth - 1]; + RPanelsMenuItem *child = parent->sub[parent->selectedIndex]; switch (key) { case 'h': handleLeftKey (core); @@ -1857,19 +2320,12 @@ static void handleMenu(RCore *core, const int key, int *exit) { break; case 'q': case -1: - if (panels->menuStackDepth == 0) { - *exit = 1; - return; - } - panels->menuStackDepth--; - panels->currentMenu = panels->menuStack[panels->menuStackDepth]; - panels->currentMenuIndex = panels->menuIndexStack[panels->menuStackDepth]; - setRefreshAll (core->panels); - break; + *exit = 1; + return; case ' ': case '\r': case '\n': - onMenu (core, panels->currentMenu[panels->currentMenuIndex], exit); + child->cb (core); break; case 9: handleTabKey (core, false); @@ -1879,280 +2335,6 @@ static void handleMenu(RCore *core, const int key, int *exit) { } } -static void onMenu(RCore *core, const char *menu, int *exit) { - RPanels *panels = core->panels; - if (!strcmp (menu, "File")) { - changeMenu (panels, menus_File); - return; - } - if (!strcmp (menu, "Edit")) { - changeMenu (panels, menus_Edit); - return; - } - if (!strcmp (menu, "View")) { - changeMenu (panels, menus_View); - return; - } - if (!strcmp (menu, "Tools")) { - changeMenu (panels, menus_Tools); - return; - } - if (!strcmp (menu, "Search")) { - changeMenu (panels, menus_Search); - return; - } - if (!strcmp (menu, "Debug")) { - changeMenu (panels, menus_Debug); - return; - } - if (!strcmp (menu, "Analyze")) { - changeMenu (panels, menus_Analyze); - return; - } - if (!strcmp (menu, "Help")) { - changeMenu (panels, menus_Help); - return; - } - if (!strcmp (menu, "ReOpen")) { - panels->menuStack[panels->menuStackDepth] = panels->currentMenu; - panels->menuIndexStack[panels->menuStackDepth] = panels->currentMenuIndex; - panels->menuStackDepth++; - panels->currentMenu = menus_ReOpen; - panels->currentMenuIndex = 0; - return; - } - if (!strcmp (menu, "New")) { - addPanelFrame (core, panels, PANEL_TITLE_NEWFILES, "o"); - } else if (!strcmp (menu, "Open")) { - r_cons_enable_mouse (false); - core->cons->line->file_prompt = true; - r_line_set_hist_callback (core->cons->line, &file_history_up, &file_history_down); - char *res = r_cons_input ("open file: "); - if (res) { - if (*res) { - r_core_cmdf (core, "o %s", res); - } - free (res); - } - core->cons->line->file_prompt = false; - r_line_set_hist_callback (core->cons->line, &cmd_history_up, &cmd_history_down); - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "RegisterRefs")) { - layoutSidePanel (core, PANEL_TITLE_REGISTERREFS, PANEL_CMD_REGISTERREFS); - } else if (!strcmp (menu, "Registers")) { - layoutSidePanel (core, PANEL_TITLE_REGISTERS, PANEL_CMD_REGISTERS); - } else if (!strcmp (menu, "Info")) { - layoutSidePanel (core, PANEL_TITLE_INFO, PANEL_CMD_INFO); - } else if (!strcmp (menu, "Database")) { - layoutSidePanel (core, PANEL_TITLE_DATABASE, PANEL_CMD_DATABASE); - } else if (!strcmp (menu, "Save Layout")) { - savePanelsLayout (panels); - } else if (!strcmp (menu, "Load Layout")) { - loadPanelsLayout (core); - } else if (!strcmp (menu, "About")) { - char *s = r_core_cmd_str (core, "?V"); - r_cons_message (s); - free (s); - } else if (!strcmp (menu, "Hexdump")) { - layoutSidePanel (core, PANEL_TITLE_HEXDUMP, PANEL_CMD_HEXDUMP); - } else if (!strcmp (menu, "Disassembly")) { - layoutSidePanel (core, PANEL_TITLE_DISASSEMBLY, PANEL_CMD_DISASSEMBLY); - } else if (!strcmp (menu, "Functions")) { - layoutSidePanel (core, PANEL_TITLE_FUNCTIONS, PANEL_CMD_FUNCTIONS); - } else if (!strcmp (menu, "Comments")) { - layoutSidePanel (core, PANEL_TITLE_COMMENTS, PANEL_CMD_COMMENTS); - } else if (!strcmp (menu, "Entropy")) { - layoutSidePanel (core, PANEL_TITLE_ENTROPY, PANEL_CMD_ENTROPY); - } else if (!strcmp (menu, "Pseudo")) { - layoutSidePanel (core, PANEL_TITLE_PSEUDO, PANEL_CMD_PSEUDO); - } else if (!strcmp (menu, "Symbols")) { - r_core_cmdf (core, "aa"); - } else if (!strcmp (menu, "BasicBlocks")) { - r_core_cmdf (core, "aab"); - } else if (!strcmp (menu, "Function")) { - r_core_cmdf (core, "af"); - } else if (!strcmp (menu, "DRX")) { - layoutSidePanel (core, PANEL_TITLE_DRX, PANEL_CMD_DRX); - } else if (!strcmp (menu, "Program")) { - r_core_cmdf (core, "aaa"); - } else if (!strcmp (menu, "Calls")) { - r_core_cmdf (core, "aac"); - } else if (!strcmp (menu, "ROP")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("rop grep: "); - if (res) { - r_core_cmdf (core, "\"/R %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "String")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("search string: "); - if (res) { - r_core_cmdf (core, "\"/ %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Hexpairs")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("search hexpairs: "); - if (res) { - r_core_cmdf (core, "\"/x %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Code")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("search code: "); - if (res) { - r_core_cmdf (core, "\"/c %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Copy")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("How many bytes? "); - if (res) { - r_core_cmdf (core, "\"y %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Write String")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("insert string: "); - if (res) { - r_core_cmdf (core, "\"w %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Write Value")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("insert number: "); - if (res) { - r_core_cmdf (core, "\"wv %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Write Hex")) { - r_cons_enable_mouse (false); - char *res = r_cons_input ("insert hexpairs: "); - if (res) { - r_core_cmdf (core, "\"wx %s\"", res); - free (res); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Calculator")) { - r_cons_enable_mouse (false); - for (;;) { - char *s = r_cons_input ("> "); - if (!s || !*s) { - free (s); - break; - } - r_core_cmdf (core, "? %s", s); - r_cons_flush (); - free (s); - } - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "Assemble")) { - r_core_visual_asm (core, core->offset); - } else if (!strcmp (menu, "Sections")) { - layoutSidePanel (core, PANEL_TITLE_SECTIONS, PANEL_CMD_SECTIONS); - } else if (!strcmp (menu, "Close")) { - r_core_cmd0 (core, "o-*"); - } else if (!strcmp (menu, "Strings")) { - layoutSidePanel (core, PANEL_TITLE_STRINGS, PANEL_CMD_STRINGS); - } else if (!strcmp (menu, "Maps")) { - layoutSidePanel (core, PANEL_TITLE_MAPS, PANEL_CMD_MAPS); - } else if (!strcmp (menu, "Modules")) { - layoutSidePanel (core, PANEL_TITLE_MODULES, PANEL_CMD_MODULES); - } else if (!strcmp (menu, "Backtrace")) { - layoutSidePanel (core, PANEL_TITLE_BACKTRACE, PANEL_CMD_BACKTRACE); - } else if (!strcmp (menu, "Locals")) { - layoutSidePanel (core, PANEL_TITLE_LOCALS, PANEL_CMD_LOCALS); - } else if (!strcmp (menu, "Step")) { - r_core_cmd (core, "ds", 0); - r_cons_flush (); - } else if (!strcmp (menu, "In RW")) { - r_core_cmd (core, "oo+", 0); - r_cons_flush (); - } else if (!strcmp (menu, "In Debugger")) { - r_core_cmd (core, "oo", 0); - r_cons_flush (); - } else if (!strcmp (menu, "Reload")) { - r_core_cmd (core, "ood", 0); - r_cons_flush (); - } else if (!strcmp (menu, "Step Over")) { - r_core_cmd (core, "dso", 0); - r_cons_flush (); - } else if (!strcmp (menu, "StackRefs")) { - layoutSidePanel (core, PANEL_TITLE_STACKREFS, PANEL_CMD_STACKREFS); - } else if (!strcmp (menu, "Stack")) { - layoutSidePanel (core, PANEL_TITLE_STACK, PANEL_CMD_STACK); - } else if (!strcmp (menu, "Continue")) { - r_core_cmd (core, "dc", 0); - r_cons_flush (); - } else if (!strcmp (menu, "Breakpoints")) { - layoutSidePanel (core, PANEL_TITLE_BREAKPOINTS, PANEL_CMD_BREAKPOINTS); - } else if (!strcmp (menu, "Symbols")) { - layoutSidePanel (core, PANEL_TITLE_SYMBOLS, PANEL_CMD_SYMBOLS); - } else if (!strcmp (menu, "Imports")) { - layoutSidePanel (core, PANEL_TITLE_IMPORTS, PANEL_CMD_IMPORTS); - } else if (!strcmp (menu, "Paste")) { - r_core_cmd0 (core, "yy"); - } else if (!strcmp (menu, "Clipboard")) { - layoutSidePanel (core, PANEL_TITLE_CLIPBOARD, PANEL_CMD_CLIPBOARD); - } else if (!strcmp (menu, "io.cache")) { - r_core_cmd0 (core, "e!io.cache"); - } else if (!strcmp (menu, "Fill")) { - r_cons_enable_mouse (false); - char *s = r_cons_input ("Fill with: "); - r_core_cmdf (core, "wow %s", s); - free (s); - r_cons_enable_mouse (true); - } else if (!strcmp (menu, "References")) { - r_core_cmdf (core, "aar"); - } else if (!strcmp (menu, "FcnInfo")) { - layoutSidePanel (core, PANEL_TITLE_FCNINFO, PANEL_CMD_FCNINFO); - } else if (!strcmp (menu, "Graph")) { - r_core_visual_graph (core, NULL, NULL, true); - // addPanelFrame ("Graph", "agf"); - } else if (!strcmp (menu, "System Shell")) { - r_cons_set_raw (0); - r_cons_flush (); - r_sys_cmd ("$SHELL"); - } else if (!strcmp (menu, "R2 Shell")) { - core->vmode = false; - r_core_visual_prompt_input (core); - core->vmode = true; - } else if (!strcmp (menu, "2048")) { - r_cons_2048 (panels->can->color); - } else if (!strcmp (menu, "License")) { - r_cons_message ("Copyright 2006-2016 - pancake - LGPL"); - } else if (!strcmp (menu, "Fortune")) { - char *s = r_core_cmd_str (core, "fo"); - r_cons_message (s); - free (s); - } else if (!strcmp (menu, "Commands")) { - r_core_cmd0 (core, "?;?@?;?$?;???"); - r_cons_any_key (NULL); - } else if (!strcmp (menu, "Colors")) { - r_core_cmd0 (core, "e!scr.color"); - } else if (!strcmp (menu, "Quit")) { - *exit = 1; - return; - } - doPanelsRefresh (core); -} - -static void changeMenu(RPanels *panels, const char **dstMenu) { - panels->menuStack[panels->menuStackDepth] = panels->currentMenu; - panels->menuIndexStack[panels->menuStackDepth] = panels->currentMenuIndex; - panels->menuStackDepth++; - panels->currentMenu = dstMenu; - panels->currentMenuIndex = 0; -} - static void handleTabKey(RCore *core, bool shift) { RPanels *panels = core->panels; r_cons_switchbuf (false); @@ -2171,12 +2353,7 @@ static void handleTabKey(RCore *core, bool shift) { panels->curnode = panels->n_panels - 1; } } - if (panels->curnode == panels->menu_pos) { - panels->currentMenu = menus; - panels->currentMenuIndex = 0; - } else { - panels->panel[panels->curnode].refresh = true; - } + panels->panel[panels->curnode].refresh = true; } static void savePanelPos(RPanel* panel) { @@ -2344,9 +2521,8 @@ R_API void r_core_panels_free(RPanels *panels) { r_cons_switchbuf (true); if (panels) { freeAllPanels (panels); - if (panels->can) { - r_cons_canvas_free (panels->can); - } + r_cons_canvas_free (panels->can); + sdb_free (panels->db); free (panels); } } @@ -2362,6 +2538,10 @@ R_API int r_core_visual_panels(RCore *core, RPanels *panels) { } } + if (!initPanelsMenu (panels)) { + return false; + } + if (!initPanels (core, panels)) { r_core_panels_free (panels); return false; @@ -2632,8 +2812,6 @@ repeat: break; case 'm': panels->curnode = panels->menu_pos; - panels->currentMenu = menus; - panels->currentMenuIndex = 0; break; case 'H': r_cons_switchbuf (false); diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index fec85f179d..eea3cb161d 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -999,6 +999,23 @@ R_API void r_agraph_foreach_edge(RAGraph *g, RAEdgeCallback cb, void *user); R_API void r_agraph_set_curnode(RAGraph *g, RANode *node); #endif +typedef int (*RPanelsMenuCallback)(void *user); +typedef struct r_panels_menu_item { + int n_sub, selectedIndex, selfIndex; + const char *name; + struct r_panels_menu_item **sub; + RPanelsMenuCallback cb; + RPanel *p; +} RPanelsMenuItem; + +typedef struct r_panels_menu_t { + RPanelsMenuItem *root; + RPanelsMenuItem **history; + int depth; + int n_refresh; + RPanel **refreshPanels; +} RPanelsMenu; + typedef struct r_panels_t { RConsCanvas *can; RPanel *panel; @@ -1006,16 +1023,11 @@ typedef struct r_panels_t { int columnWidth; int layout; int menu_pos; - int callgraph; int curnode; bool isResizing; bool isZoom; - const char ***menuStack; - int *menuIndexStack; - int menuStackDepth; - const char **currentMenu; - int currentMenuIndex; - RPanel *menuPanel; + RPanelsMenu *panelsMenu; + Sdb *db; } RPanels; #ifdef __cplusplus