R_API void r_cons_less_str(const char *str) { int lines_count; int w, h, ch, to, ui = 1, from = 0; char *p = strdup (str); int *lines = splitlines (p, &lines_count); r_cons_set_raw (R_TRUE); r_cons_show_cursor (R_FALSE); r_cons_reset (); h = 0; while (ui) { w = r_cons_get_size (&h); to = R_MIN (lines_count, from+h); if (from+3>lines_count) from = lines_count-3; printpage (p, lines, from, to); ch = r_cons_readchar (); ch = r_cons_arrow_to_hjkl (ch); switch (ch) { case ' ': from += h; break; case 'g': from = 0; break; case 'G': from = lines_count-1-h; break; case 'q': ui = 0; break; case '\r': case '\n': case 'j': from++; break; case 'J': from+=h; break; case 'k': if (from>0) from--; break; case 'K': from = (from>=h)? from-h: 0; break; } } free (lines); r_cons_set_raw (R_FALSE); r_cons_show_cursor (R_TRUE); }
R_API int r_cons_any_key(const char *msg) { if (msg && *msg) { r_cons_printf ("\n-- %s --\n", msg); } else { r_cons_print ("\n--press any key--\n"); } r_cons_flush (); return r_cons_readchar (); //r_cons_strcat ("\x1b[2J\x1b[0;0H"); // wtf? }
R_API int r_cons_readchar_timeout(ut32 usec) { #if __UNIX__ struct timeval tv; fd_set fdset, errset; FD_ZERO (&fdset); FD_ZERO (&errset); FD_SET (0, &fdset); tv.tv_sec = 0; // usec / 1000; tv.tv_usec = 1000 * usec; r_cons_set_raw (1); if (select (1, &fdset, NULL, &errset, &tv) == 1) { return r_cons_readchar (); } r_cons_set_raw (0); // timeout return -1; #else return readchar_win (usec); #endif }
R_API void r_cons_2048() { int ch; r_cons_set_raw (1); twok_init (); twok_add (); twok_add (); while (twok_fin()) { r_cons_clear00(); r_cons_printf ("[r2048] score: %d moves: %d\n", score, moves); r_cons_flush (); twok_print(); ch = r_cons_readchar (); ch = r_cons_arrow_to_hjkl (ch); switch(ch){ case 'h': twok_move(1,1); break; case 'j': twok_move(0,0); break; case 'k': twok_move(0,1); break; case 'l': twok_move(1,0); break; } if (ch<1||ch =='q') break; } r_cons_clear00(); r_cons_printf ("[r2048] score: %d\n", score ); r_cons_flush (); twok_print(); r_cons_printf ("\n [r2048.score] %d\n", score ); do { ch = r_cons_any_key ("Press 'q' to quit."); } while (ch != 'q' && ch >= 1); r_cons_set_raw (0); }
R_API char *r_cons_password(const char *msg) { int i = 0; char buf[256] = {0}; printf ("\r%s", msg); fflush (stdout); r_cons_set_raw (1); #if __UNIX__ RCons *a = r_cons_singleton (); a->term_raw.c_lflag &= ~(ECHO | ECHONL); // // required to make therm/iterm show the key // // cannot read when enabled in this way // a->term_raw.c_lflag |= ICANON; tcsetattr (0, TCSADRAIN, &a->term_raw); signal (SIGTSTP, SIG_IGN); #endif while (i < sizeof (buf) - 1) { int ch = r_cons_readchar (); if (ch == 127) { // backspace if (i < 1) { break; } i--; continue; } if (ch == '\r' || ch == '\n') { break; } buf[i++] = ch; } buf[i] = 0; r_cons_set_raw (0); printf ("\n"); #if __UNIX__ signal (SIGTSTP, SIG_DFL); #endif return strdup (buf); }
static int parseMouseEvent() { int ch = r_cons_readchar (); /* Skip the x/y coordinates */ #if USE_CLICK int x = r_cons_readchar() - 33; int y = r_cons_readchar() - 33; #else (void) r_cons_readchar (); (void) r_cons_readchar (); #endif #if USE_CLICK if (ch == 35) { /* handle click */ #define CLICK_DEBUG 1 #if CLICK_DEBUG r_cons_gotoxy (0, 0); r_cons_printf ("Click at %d %d\n", x, y); r_cons_flush (); #endif RCons *cons = r_cons_singleton (); if (cons->onclick) { cons->onclick (cons->data, x, y); } r_cons_enable_mouse (false); (void)r_cons_readchar (); return 0; } #endif if (ch != 0x20 && ch >= 64 + 32) { /* Grab wheel events only */ I->mouse_event = 1; return "kj"[(ch - (64 + 32))&1]; } // temporary disable the mouse wheel to allow select r_cons_enable_mouse (false); (void)r_cons_readchar (); return 0; }
R_API int r_cons_arrow_to_hjkl(int ch) { #if __WINDOWS_ && !__CYGWIN__ return ch; #endif I->mouse_event = 0; /* emacs */ switch ((ut8)ch) { case 0xc3: r_cons_readchar(); ch='K'; break; // emacs repag (alt + v) case 0x16: ch='J'; break; // emacs avpag (ctrl + v) case 0x10: ch='k'; break; // emacs up (ctrl + p) case 0x0e: ch='j'; break; // emacs down (ctrl + n) case 0x06: ch='l'; break; // emacs right (ctrl + f) case 0x02: ch='h'; break; // emacs left (ctrl + b) } if (ch != 0x1b) { return ch; } ch = r_cons_readchar (); if (!ch) { return 0; } switch (ch) { case 0x1b: ch = 'q'; // XXX: must be 0x1b (R_CONS_KEY_ESC) break; case 0x4f: // function keys from f1 to f4 ch = r_cons_readchar (); #if defined(__HAIKU__) /* Haiku don use the '[' char for funcion keys */ if (ch > 'O') {/* only in f1..f12 funcion keys */ ch = 0xf1 + (ch&0xf); break; } case '[': // 0x5b function keys (2) /* Haiku need ESC + [ for PageUp and PageDown */ if (ch < 'A' || ch == '[') { ch = r_cons_readchar (); } #else ch = 0xf1 + (ch & 0xf); break; case '[': // function keys (2) ch = r_cons_readchar (); #endif switch (ch) { case '[': ch = r_cons_readchar (); switch (ch) { case '2': ch = R_CONS_KEY_F11; break; case 'A': ch = R_CONS_KEY_F1; break; case 'B': ch = R_CONS_KEY_F2; break; case 'C': ch = R_CONS_KEY_F3; break; case 'D': ch = R_CONS_KEY_F4; break; } break; case '2': ch = r_cons_readchar (); switch (ch) { case 0x7e: ch = R_CONS_KEY_F12; break; default: r_cons_readchar (); switch (ch) { case '0': ch = R_CONS_KEY_F9; break; case '1': ch = R_CONS_KEY_F10; break; case '3': ch = R_CONS_KEY_F11; break; } break; } break; case '1': ch = r_cons_readchar (); switch (ch) { case ':': // arrow+shift ch = r_cons_readchar (); ch = r_cons_readchar (); switch (ch) { case 'A': ch = 'K'; break; case 'B': ch = 'J'; break; case 'C': ch = 'L'; break; case 'D': ch = 'H'; break; } break; /* case '1': ch = R_CONS_KEY_F1; break; case '2': ch = R_CONS_KEY_F2; break; case '3': ch = R_CONS_KEY_F3; break; case '4': ch = R_CONS_KEY_F4; break; */ case '5': r_cons_readchar (); ch = 0xf5; break; case '6': r_cons_readchar (); ch = 0xf7; break; case '7': r_cons_readchar (); ch = 0xf6; break; case '8': r_cons_readchar (); ch = 0xf7; break; case '9': r_cons_readchar (); ch = 0xf8; break; } // F9-F12 not yet supported!! break; case '5': ch = 'K'; r_cons_readchar(); break; // repag case '6': ch = 'J'; r_cons_readchar(); break; // avpag /* arrow keys */ case 'A': ch = 'k'; break; // up case 'B': ch = 'j'; break; // down case 'C': ch = 'l'; break; // right case 'D': ch = 'h'; break; // left case 'M': ch = parseMouseEvent(); break; } break; } return ch; }
R_API int r_cons_less_str(const char *str, const char *exitkeys) { static int in_help = false; static const char *r_cons_less_help = \ " u/space - page up/down\n" " jk - line down/up\n" " gG - begin/end buffer\n" " / - search in buffer\n" " _ - enter the hud mode\n" " n/p - next/prev search result\n" " q - quit\n" " ? - show this help\n" "\n"; int lines_count = 0; RRegex *rx = NULL; int w, h, ch, to, ui = 1, from = 0, i; const char *sreg; RList **mla; if (!str || !*str) { return 0; } // rcons kills str after flushing the buffer, so we must keep a copy char *ostr = strdup (str); if (!ostr) { return 0; } char *p = strdup (str); if (!p) { free (ostr); return 0; } int *lines = pager_splitlines (p, &lines_count); if (lines_count < 1) { mla = NULL; } else { mla = calloc (lines_count, sizeof (RList *)); if (!mla) { free (p); free (ostr); free (lines); return 0; } } for (i = 0; i < lines_count; i++) { mla[i] = r_list_new (); } r_cons_set_raw (true); r_cons_show_cursor (false); r_cons_reset (); h = 0; while (ui) { w = r_cons_get_size (&h); to = R_MIN (lines_count, from + h); if (from + 3 > lines_count) { from = lines_count - 3; } if (from < 0) { from = 0; } pager_printpage (p, lines, mla, from, to, w); ch = r_cons_readchar (); if (exitkeys && strchr (exitkeys, ch)) { for (i = 0; i < lines_count; i++) { r_list_free (mla[i]); } free (p); free (mla); free (ostr); free (lines); return ch; } ch = r_cons_arrow_to_hjkl (ch); switch (ch) { case '_': r_cons_hud_string (ostr); break; case '?': if (!in_help) { in_help = true; r_cons_less_str (r_cons_less_help, NULL); in_help = false; } break; case 'u': from -= h; if (from < 0) { from = 0; } break; case ' ': from += h; break; case 'g': from = 0; break; case 'G': from = lines_count-h; break; case -1: // EOF case '\x03': // ^C case 'q': ui = 0; break; case '\r': case '\n': case 'j': from++; break; case 'J': from+=h; break; case 'k': if (from > 0) { from--; } break; case 'K': from = (from>=h)? from-h: 0; break; case '/': /* search */ r_cons_reset_colors (); r_line_set_prompt ("/"); sreg = r_line_readline (); from = R_MIN (lines_count - 1, from); /* repeat last search if empty string is provided */ if (sreg[0]) { /* prepare for a new search */ if (rx) { r_regex_free (rx); } rx = r_regex_new (sreg, ""); } else { /* we got an empty string */ from = pager_next_match (from, mla, lines_count); break; } if (!rx) { break; } /* find all occurences */ if (pager_all_matches (p, rx, mla, lines, lines_count)) { from = pager_next_match (from, mla, lines_count); } break; case 'n': /* next match */ /* search already performed */ if (rx) { from = pager_next_match (from, mla, lines_count); } break; case 'N': case 'p': /* previous match */ if (rx) { from = pager_prev_match (from, mla); } break; } } for (i = 0; i < lines_count; i++) { r_list_free (mla[i]); } free (mla); r_regex_free (rx); free (lines); free (p); r_cons_reset_colors (); r_cons_set_raw (false); r_cons_show_cursor (true); free (ostr); return 0; }
R_API void r_cons_less_str(const char *str) { int lines_count; RRegex *rx = NULL; int w, h, ch, to, ui = 1, from = 0, i; const char *sreg; if(str == NULL || str[0] == '\0') return; char *p = strdup (str); int *lines = splitlines (p, &lines_count); RRegexMatch **ms = malloc(lines_count * sizeof(void *)); for(i = 0; i < lines_count; i++) ms[i] = calloc(NMATCHES, sizeof(RRegexMatch)); r_cons_set_raw (R_TRUE); r_cons_show_cursor (R_FALSE); r_cons_reset (); w = h = 0; while (ui) { w = r_cons_get_size (&h); to = R_MIN (lines_count, from+h); if (from+3>lines_count) from = lines_count-3; if (from<0) from = 0; printpage (p, lines, ms, from, to, w); ch = r_cons_readchar (); ch = r_cons_arrow_to_hjkl (ch); switch (ch) { case ' ': from += h; break; case 'g': from = 0; break; case 'G': from = lines_count-1-h; break; case -1: // EOF case 'q': ui = 0; break; case '\r': case '\n': case 'j': from++; break; case 'J': from+=h; break; case 'k': if (from>0) from--; break; case 'K': from = (from>=h)? from-h: 0; break; case '/': /* search */ r_cons_reset_colors(); r_line_set_prompt("/"); sreg = r_line_readline(); from = R_MIN(lines_count - 1, from); /* repeat last search if empty string is provided */ if(sreg[0]){ /* prepare for a new search */ if(rx) r_regex_free(rx); rx = r_regex_new(sreg, ""); } else { /* we got an empty string */ from = next_match(from, ms, lines_count); break; } if(!rx) break; /* find all occurences */ if(all_matches(p, rx, ms, lines, lines_count)) from = next_match(from, ms, lines_count); break; case 'n': /* next match */ /* search already performed */ if(rx) from = next_match(from, ms, lines_count); break; case 'p': /* previous match */ if(rx) from = prev_match(from, ms); break; } } for(i = 0; i < lines_count; i++) free(ms[i]); free(ms); if(rx) r_regex_free(rx); free (lines); free (p); r_cons_reset_colors(); r_cons_set_raw (R_FALSE); r_cons_show_cursor (R_TRUE); }
R_API int r_cons_arrow_to_hjkl(int ch) { I->mouse_event = 0; /* emacs */ switch ((ut8)ch) { case 0xc3: r_cons_readchar(); ch='K'; break; // emacs repag (alt + v) case 0x16: ch='J'; break; // emacs avpag (ctrl + v) case 0x10: ch='k'; break; // emacs up (ctrl + p) case 0x0e: ch='j'; break; // emacs down (ctrl + n) case 0x06: ch='l'; break; // emacs right (ctrl + f) case 0x02: ch='h'; break; // emacs left (ctrl + b) } if (ch != 0x1b) return ch; ch = r_cons_readchar (); if (!ch) return 0; switch (ch) { case 0x1b: ch = 'q'; // XXX: must be 0x1b (R_CONS_KEY_ESC) break; case 0x4f: // function keys from f1 to f4 ch = r_cons_readchar (); ch = 0xf1 + (ch&0xf); break; case '[': // function keys (2) ch = r_cons_readchar (); switch (ch) { case '[': ch = r_cons_readchar (); switch (ch) { case '2': ch = R_CONS_KEY_F11; break; case 'A': ch = R_CONS_KEY_F1; break; case 'B': ch = R_CONS_KEY_F2; break; case 'C': ch = R_CONS_KEY_F3; break; case 'D': ch = R_CONS_KEY_F4; break; } break; case '2': ch = r_cons_readchar (); switch (ch) { case 0x7e: ch = R_CONS_KEY_F12; break; default: r_cons_readchar (); switch (ch) { case '0': ch = R_CONS_KEY_F9; break; case '1': ch = R_CONS_KEY_F10; break; case '3': ch = R_CONS_KEY_F11; break; } break; } break; case '1': ch = r_cons_readchar (); switch (ch) { case ':': // arrow+shift ch = r_cons_readchar (); ch = r_cons_readchar (); switch (ch) { case 'A': ch = 'K'; break; case 'B': ch = 'J'; break; case 'C': ch = 'L'; break; case 'D': ch = 'H'; break; } break; /* case '1': ch = R_CONS_KEY_F1; break; case '2': ch = R_CONS_KEY_F2; break; case '3': ch = R_CONS_KEY_F3; break; case '4': ch = R_CONS_KEY_F4; break; */ case '5': r_cons_readchar (); ch = 0xf5; break; case '6': r_cons_readchar (); ch = 0xf7; break; case '7': r_cons_readchar (); ch = 0xf6; break; case '8': r_cons_readchar (); ch = 0xf7; break; case '9': r_cons_readchar (); ch = 0xf8; break; } // F9-F12 not yet supported!! break; case '5': ch='K'; break; // repag case '6': ch='J'; break; // avpag case 'A': ch='k'; break; // up case 'B': ch='j'; break; // down case 'C': ch='l'; break; // right case 'D': ch='h'; break; // left case 'M': // Mouse events ch = r_cons_readchar (); /* Skip the x/y coordinates */ (void)r_cons_readchar(); (void)r_cons_readchar(); if (ch==0x20) { // click r_cons_enable_mouse (R_FALSE); ch = 0; //r_cons_enable_mouse (R_TRUE); } else if (ch >= 64 + 32) { /* Grab wheel events only */ I->mouse_event = 1; ch = "kj"[(ch - (64 + 32))&1]; } else { // temporary disable the mouse wheel to allow select r_cons_enable_mouse (R_FALSE); (void)r_cons_readchar (); ch = 0; } } break; } return ch; }
// Display a list of entries in the hud, filtered and emphasized based // on the user input. R_API char *r_cons_hud(RList *list, const char *prompt, const bool usecolor) { const int buf_size = 128; int ch, nch, first_line, current_entry_n, j, i = 0; char *p, *x, user_input[buf_size], mask[buf_size]; int last_color_change, top_entry_n = 0; char *selected_entry = NULL; char tmp, last_mask = 0; void *current_entry; RListIter *iter; user_input[0] = 0; r_cons_clear (); // Repeat until the user exits the hud for (;;) { first_line = 1; r_cons_gotoxy (0, 0); current_entry_n = 0; selected_entry = NULL; if (prompt && *prompt) r_cons_printf (">> %s\n", prompt); r_cons_printf ("> %s|\n", user_input); // Iterate over each entry in the list r_list_foreach (list, iter, current_entry) { memset (mask, 0, buf_size); if (!user_input[0] || strmatch (current_entry, user_input, mask, buf_size)) { // if the user scrolled down the list, do not print the first entries if (!top_entry_n || current_entry_n >= top_entry_n) { // remove everything after a tab (in ??, it contains the commands) x = strchr (current_entry, '\t'); if (x) *x = 0; p = strdup (current_entry); // if the filter is empty, print the entry and move on if (!user_input[0]) { r_cons_printf (" %c %s\n", first_line? '-': ' ', current_entry); } else { // otherwise we need to emphasize the matching part if (usecolor) { last_color_change = 0; last_mask = 0; r_cons_printf (" %c ", first_line? '-': ' '); // Instead of printing one char at the time // (which would be slow), we group substrings of the same color for (j = 0; p[j]; j++) { if (mask[j] != last_mask) { tmp = p[j]; p[j] = 0; if (mask[j]) { r_cons_printf (Color_RESET"%s", p + last_color_change); } else { r_cons_printf (Color_GREEN"%s", p + last_color_change); } p[j] = tmp; last_color_change = j; last_mask = mask[j]; } } if (last_mask) { r_cons_printf (Color_GREEN"%s\n"Color_RESET, p + last_color_change); } else { r_cons_printf (Color_RESET"%s\n", p + last_color_change); } } else { // Otherwise we print the matching characters uppercase for (j = 0; p[j]; j++) { if (mask[j]) p[j] = toupper ((unsigned char)p[j]); } r_cons_printf (" %c %s\n", first_line? '-': ' ', p); } } // Clean up and restore the tab character (if any) free (p); if (x) *x = '\t'; if (first_line) selected_entry = current_entry; first_line = 0; } current_entry_n++; } } r_cons_visual_flush (); ch = r_cons_readchar (); nch = r_cons_arrow_to_hjkl (ch); if (nch == 'j' && ch != 'j') { if (top_entry_n + 1 < current_entry_n) top_entry_n++; } else if (nch == 'k' && ch != 'k') { if (top_entry_n >= 0) top_entry_n--; } else switch (ch) { case 9: // \t if (top_entry_n + 1 < current_entry_n) top_entry_n++; else top_entry_n = 0; break; case 10: // \n case 13: // \r top_entry_n = 0; // if (!*buf) // return NULL; if (current_entry_n >= 1) { //eprintf ("%s\n", buf); //i = buf[0] = 0; return strdup (selected_entry); } // no match! break; case 23: // ^w top_entry_n = 0; i = user_input[0] = 0; break; case 0x1b: // ESC return NULL; case 8: // bs case 127: // bs top_entry_n = 0; if (i < 1) return NULL; user_input[--i] = 0; break; default: if (IS_PRINTABLE (ch)) { if (i >= buf_size) { break; } top_entry_n = 0; if (i + 1 >= buf_size) { // too many break; } user_input[i++] = ch; user_input[i] = 0; } break; } }
R_API int r_cons_arrow_to_hjkl(int ch) { if (ch==0x1b) { #if 0 //__UNIX__ if (!is_fd_ready (0)) return 0; #endif ch = r_cons_readchar (); if (!ch) return 0; switch (ch) { case 0x1b: ch = 'q'; // XXX: must be 0x1b (R_CONS_KEY_ESC) break; case 0x4f: // function keys from f1 to f4 ch = r_cons_readchar (); ch = 0xf1 + (ch&0xf); break; case 0: case '[': // function keys (2) ch = r_cons_readchar (); switch (ch) { case '[': ch = r_cons_readchar (); switch (ch) { case '2': ch = R_CONS_KEY_F11; break; case 'A': ch = R_CONS_KEY_F1; break; case 'B': ch = R_CONS_KEY_F2; break; case 'C': ch = R_CONS_KEY_F3; break; case 'D': ch = R_CONS_KEY_F4; break; } break; case '2': ch = r_cons_readchar (); switch (ch) { case 0x7e: ch = R_CONS_KEY_F12; break; default: r_cons_readchar (); switch (ch) { case '0': ch = R_CONS_KEY_F9; break; case '1': ch = R_CONS_KEY_F10; break; case '3': ch = R_CONS_KEY_F11; break; } break; } break; case '1': ch = r_cons_readchar (); switch (ch) { case ':': // arrow+shift ch = r_cons_readchar (); ch = r_cons_readchar (); switch (ch) { case 'A': ch = 'K'; break; case 'B': ch = 'J'; break; case 'C': ch = 'L'; break; case 'D': ch = 'H'; break; } break; /* case '1': ch = R_CONS_KEY_F1; break; case '2': ch = R_CONS_KEY_F2; break; case '3': ch = R_CONS_KEY_F3; break; case '4': ch = R_CONS_KEY_F4; break; */ case '5': r_cons_readchar (); ch = 0xf5; break; case '6': r_cons_readchar (); ch = 0xf7; break; case '7': r_cons_readchar (); ch = 0xf6; break; case '8': r_cons_readchar (); ch = 0xf7; break; case '9': r_cons_readchar (); ch = 0xf8; break; } // F9-F12 not yet supported!! break; case '5': ch='K'; break; // repag case '6': ch='J'; break; // avpag case 'A': ch='k'; break; // up case 'B': ch='j'; break; // down case 'C': ch='l'; break; // right case 'D': ch='h'; break; // left case 'M': // Mouse events ch = r_cons_readchar (); /* Skip the x/y coordinates */ (void)r_cons_readchar(); (void)r_cons_readchar(); if (ch==0x20) { // click r_cons_enable_mouse (R_FALSE); ch = 0; //r_cons_enable_mouse (R_TRUE); } else if (ch >= 64 + 32) { /* Grab wheel events only */ ch = "kj"[(ch - (64 + 32))&1]; } else { // temporary disable the mouse wheel to allow select r_cons_enable_mouse (R_FALSE); (void)r_cons_readchar (); ch = 0; } } break; } } return ch; }
R_API void r_cons_any_key() { r_cons_strcat ("\n--press any key--\n"); r_cons_flush (); r_cons_readchar (); //r_cons_strcat ("\x1b[2J\x1b[0;0H"); // wtf? }
R_API int r_cons_arrow_to_hjkl(int ch) { if (ch==0x1b) { #if 0 //__UNIX__ if (!is_fd_ready (0)) return 0; #endif ch = r_cons_readchar (); if (!ch) return 0; switch (ch) { case 0x1b: ch = 'q'; // XXX: must be 0x1b (R_CONS_KEY_ESC) break; case 0x4f: // function keys from f1 to f4 ch = r_cons_readchar (); ch = 0xf1 + (ch&0xf); break; case 0: case '[': // function keys (2) ch = r_cons_readchar (); switch (ch) { case '[': switch (ch) { case '2': ch = R_CONS_KEY_F11; break; case 'A': ch = R_CONS_KEY_F1; break; case 'B': ch = R_CONS_KEY_F2; break; case 'C': ch = R_CONS_KEY_F3; break; case 'D': ch = R_CONS_KEY_F4; break; } break; case '2': ch = r_cons_readchar (); switch (ch) { case 0x7e: ch = R_CONS_KEY_F12; break; default: r_cons_readchar (); switch (ch) { case '0': ch = R_CONS_KEY_F9; break; case '1': ch = R_CONS_KEY_F10; break; case '3': ch = R_CONS_KEY_F11; break; } break; } break; case '1': ch = r_cons_readchar (); switch (ch) { case ':': // arrow+shift ch = r_cons_readchar (); ch = r_cons_readchar (); switch (ch) { case 'A': ch = 'K'; break; case 'B': ch = 'J'; break; case 'C': ch = 'L'; break; case 'D': ch = 'H'; break; } break; /* case '1': ch = R_CONS_KEY_F1; break; case '2': ch = R_CONS_KEY_F2; break; case '3': ch = R_CONS_KEY_F3; break; case '4': ch = R_CONS_KEY_F4; break; */ case '5': r_cons_readchar (); ch = 0xf5; break; case '6': r_cons_readchar (); ch = 0xf7; break; case '7': r_cons_readchar (); ch = 0xf6; break; case '8': r_cons_readchar (); ch = 0xf7; break; case '9': r_cons_readchar (); ch = 0xf8; break; } // F9-F12 not yet supported!! break; case '5': ch='K'; break; // repag case '6': ch='J'; break; // avpag case 'A': ch='k'; break; // up case 'B': ch='j'; break; // down case 'C': ch='l'; break; // right case 'D': ch='h'; break; // left } break; } } return ch; }
R_API char *r_cons_hud(RList *list, const char *prompt) { int ch, nch, first, n, j, i = 0; int choose = 0; char *p, buf[128]; RListIter *iter; char *match = NULL; void *pos; buf[0] = 0; r_cons_clear (); for (;;) { first = 1; r_cons_gotoxy (0, 0); n = 0; match = NULL; if (prompt && *prompt) r_cons_printf (">> %s\n", prompt); r_cons_printf ("> %s|\n", buf); r_list_foreach (list, iter, pos) { if (!buf[0] || strmatch (pos, buf)) { char *x = strchr (pos, '\t'); // remove \t.* if (!choose || n>=choose) { if (x) *x = 0; p = strdup (pos); for (j=0; p[j]; j++) { if (strchr (buf, p[j])) p[j] = toupper ((unsigned char)p[j]); } r_cons_printf (" %c %s\n", first?'-':' ', p); free (p); if (x) *x = '\t'; if (first) match = pos; first = 0; } n++; } } r_cons_visual_flush (); ch = r_cons_readchar (); nch = r_cons_arrow_to_hjkl (ch); if (nch == 'j' && ch != 'j') { if (choose+1 < n) choose++; } else if (nch == 'k' && ch != 'k') { if (choose>=0) choose--; } else switch (ch) { case 9: // \t if (choose+1 < n) choose++; else choose = 0; break; case 10: // \n case 13: // \r choose = 0; // if (!*buf) // return NULL; if (n >= 1) { //eprintf ("%s\n", buf); //i = buf[0] = 0; return strdup (match); } // no match! break; case 23: // ^w choose = 0; i = buf[0] = 0; break; case 0x1b: // ESC return NULL; case 8: // bs case 127: // bs choose = 0; if (i<1) return NULL; buf[--i] = 0; break; default: if (IS_PRINTABLE (ch)) { choose = 0; buf[i++] = ch; buf[i] = 0; } break; } } return NULL; }
r_cons_any_key (); r_cons_clear00 (); } else { r_list_foreach (xrefs, iter, refi) { fun = r_anal_fcn_find (core->anal, refi->addr, R_ANAL_FCN_TYPE_NULL); r_cons_printf (" [%i] 0x%08"PFMT64x" %s XREF 0x%08"PFMT64x" (%s) \n", count, refi->at, refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)": refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr, fun?fun->name:"unk"); if (++count > 9) break; } } } else xrefs = NULL; r_cons_flush (); ch = r_cons_readchar (); if (ch >= '0' && ch <= '9') { refi = r_list_get_n (xrefs, ch-0x30); if (refi) r_core_cmdf (core, "s 0x%"PFMT64x, refi->addr); } r_list_free (xrefs); } break; case 'X': { int count = 0; RAnalRef *refi; RListIter *iter; RAnalFunction *fun;
R_API int r_core_visual_panels(RCore *core) { #define OS_INIT() ostack.size = 0; ostack.panels[0] = 0; #define OS_PUSH(x) if (ostack.size<LIMIT) {ostack.panels[++ostack.size]=x;} #define OS_POP() ((ostack.size>0)? ostack.panels[--ostack.size]:0) int okey, key, wheel; int w, h; int asm_comments = 0; int asm_bytes = 0; n_panels = 0; panels = NULL; callgraph = 0; _core = core; OS_INIT(); w = r_cons_get_size (&h); can = r_cons_canvas_new (w, h); can->linemode = 1; can->color = r_config_get_i (core->config, "scr.color"); // disable colors in disasm because canvas doesnt supports ansi text yet r_config_set_i (core->config, "scr.color", 0); //can->color = 0; if (!can) { eprintf ("Cannot create RCons.canvas context\n"); return R_FALSE; } n_panels = bbPanels (core, &panels); if (!panels) { r_config_set_i (core->config, "scr.color", can->color); free (can); return R_FALSE; } reloadPanels (core); asm_comments = r_config_get_i (core->config, "asm.comments"); r_config_set_i (core->config, "asm.comments", 0); asm_bytes = r_config_get_i (core->config, "asm.bytes"); r_config_set_i (core->config, "asm.bytes", 0); repeat: core->cons->event_data = core; core->cons->event_resize = \ (RConsEvent)r_core_panels_refresh; w = r_cons_get_size (&h); Layout_run (panels); r_core_panels_refresh (core); wheel = r_config_get_i (core->config, "scr.wheel"); if (wheel) r_cons_enable_mouse (R_TRUE); // r_core_graph_inputhandle() okey = r_cons_readchar (); key = r_cons_arrow_to_hjkl (okey); switch (key) { case ' ': case '\n': if (menu_y) { const char *action = menus_sub[menu_x][menu_y-1]; eprintf ("ACTION %s\n", action); if (strstr (action, "New")) { int i; // add new panel for testing for (i=0; panels[i].text; i++) { // find last panel } panels[i].text = strdup ("Test"); panels[i].cmd = r_str_newf ("pxW $r-2"); panels[i].addr = core->offset; panels[i].type = PANEL_TYPE_FRAME; i++; n_panels++; panels[i].text = NULL; } if (strstr (action, "Quit")) { goto beach; } } break; case '?': r_cons_clear00 (); r_cons_printf ("Visual Ascii Art Panels:\n" " ! run r2048 game\n" " . - center graph to the current node\n" " : - run r2 command in prompt\n" " hl - toggle scr.color\n" " HL - move vertical column split\n" " JK - select prev/next panels\n" " jk - scroll/select menu\n" " q - quit, back to visual mode\n" ); r_cons_flush (); r_cons_any_key (NULL); break; case ':': core->vmode = R_FALSE; r_core_visual_prompt_input (core); core->vmode = R_TRUE; break; case 'C': can->color = !!!can->color; //WTF //r_config_swap (core->config, "scr.color"); // refresh graph // reloadPanels (core); break; case '!': r_cons_2048 (); break; case 'j': if (panels[curnode].type == PANEL_TYPE_FLOAT) { if (menus_sub[menu_x][menu_y]) menu_y ++; } break; case 'k': if (panels[curnode].type == PANEL_TYPE_FLOAT) { menu_y --; if (menu_y<0) menu_y = 0; } break; case 'J': curnode++; if (!panels[curnode].text) { curnode--; } break; case 'K': curnode--; if (curnode<0) curnode = 0; break; case 'H': COLW += 4; break; case 'L': COLW -= 4; if (COLW<0) COLW=0; break; case 'h': if (menu_x) { menu_x --; menu_y = menu_y?1:0; } break; case 'l': if (menus[menu_x + 1]) { menu_x ++; menu_y = menu_y?1:0; } break; case 'q': case -1: // EOF goto beach; case 27: // ESC if (r_cons_readchar () == 91) { if (r_cons_readchar () == 90) { } } break; default: //eprintf ("Key %d\n", key); //sleep (1); break; } goto repeat; beach: free (panels); r_config_set_i (core->config, "scr.color", can->color); free (can); r_config_set_i (core->config, "asm.comments", asm_comments); r_config_set_i (core->config, "asm.bytes", asm_bytes); return R_TRUE; }