/* radare - LGPL - Copyright 2009-2014 - pancake */ #include #include #define I r_cons_singleton() #if 0 //__UNIX__ #include static int is_fd_ready(int fd) { fd_set rfds; struct timeval tv; if (fd==-1) return 0; FD_ZERO (&rfds); FD_SET (fd, &rfds); tv.tv_sec = 0; tv.tv_usec = 1; if (select (1, &rfds, NULL, NULL, &tv) == -1) return 0; return 1; return !FD_ISSET (0, &rfds); } #endif R_API int r_cons_controlz(int ch) { #if __UNIX__ if (ch == 0x1a) { r_cons_set_raw (0); r_cons_show_cursor (1); r_sys_stop (); return 0; } #endif return ch; } 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 (); 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; } // XXX no control for max length here?!?! R_API int r_cons_fgets(char *buf, int len, int argc, const char **argv) { #define RETURN(x) { ret=x; goto beach; } RCons *cons = r_cons_singleton (); int ret = 0, color = cons->pal.input && *cons->pal.input; #if 0 int mouse = r_cons_enable_mouse (R_FALSE); r_cons_enable_mouse (R_FALSE); r_cons_flush (); #endif if (cons->user_fgets) { RETURN (cons->user_fgets (buf, len)); } *buf = '\0'; fflush (cons->fdin); if (color) { const char *p = cons->pal.input; int len = p? strlen (p): 0; if (len>0) fwrite (p, len, 1, stdout); fflush (stdout); } if (fgets (buf, len, cons->fdin) == NULL) { if (color) { printf (Color_RESET); fflush (stdout); } RETURN (-1); } if (feof (cons->fdin)) { if (color) printf (Color_RESET); RETURN (-2); } buf[strlen (buf)-1] = '\0'; if (color) printf (Color_RESET); ret = strlen (buf); beach: //r_cons_enable_mouse (mouse); return ret; } R_API int r_cons_any_key(const char *msg) { if (msg && *msg) { r_cons_printf ("\n-- %s --\n", msg); } else { r_cons_strcat ("\n--press any key--\n"); } r_cons_flush (); return r_cons_readchar (); //r_cons_strcat ("\x1b[2J\x1b[0;0H"); // wtf? } #if __WINDOWS__ && !__CYGWIN__ static int readchar_win() { int ch=0; BOOL ret; BOOL bCtrl=FALSE; DWORD mode, out; HANDLE h; INPUT_RECORD irInBuf[128]; int dir; int i; do_it_again: h = GetStdHandle (STD_INPUT_HANDLE); GetConsoleMode (h, &mode); SetConsoleMode (h, 0 | ENABLE_MOUSE_INPUT); // RAW ret= ReadConsoleInput(h,irInBuf,128,&out); if (ret) { for (i = 0; i < out; i++) { if (irInBuf[i].EventType==MOUSE_EVENT) { switch(irInBuf[i].Event.MouseEvent.dwEventFlags) { case MOUSE_WHEELED: if (irInBuf[i].Event.MouseEvent.dwButtonState & 0xFF000000) ch='j'; else ch='k'; break; } } if (irInBuf[i].EventType==KEY_EVENT) { if (irInBuf[i].Event.KeyEvent.bKeyDown) { ch=irInBuf[i].Event.KeyEvent.uChar.AsciiChar; bCtrl=irInBuf[i].Event.KeyEvent.dwControlKeyState & 8; if (irInBuf[i].Event.KeyEvent.uChar.AsciiChar==0) { ch=0; switch(irInBuf[i].Event.KeyEvent.wVirtualKeyCode) { case VK_DOWN: // key down if (bCtrl) ch='J'; else ch='j'; break; case VK_RIGHT: // key right if (bCtrl) ch='L'; else ch='l'; break; case VK_UP: // key up if (bCtrl) ch='K'; else ch='k'; break; case VK_LEFT: // key left if (bCtrl) ch='H'; else ch='h'; break; case VK_PRIOR: // key home if (bCtrl) ch='K'; else ch='K'; break; case VK_NEXT: // key end if (bCtrl) ch='J'; else ch='J'; break; case VK_F1: if (bCtrl) ch=R_CONS_KEY_F1; else ch=R_CONS_KEY_F1; break; case VK_F2: if (bCtrl) ch=R_CONS_KEY_F2; else ch=R_CONS_KEY_F2; break; case VK_F3: if (bCtrl) ch=R_CONS_KEY_F3; else ch=R_CONS_KEY_F3; break; case VK_F4: if (bCtrl) ch=R_CONS_KEY_F4; else ch=R_CONS_KEY_F4; break; case VK_F5: if (bCtrl) ch=0xcf5; else ch=R_CONS_KEY_F5; break; case VK_F6: if (bCtrl) ch=R_CONS_KEY_F6; else ch=R_CONS_KEY_F6; break; case VK_F7: if (bCtrl) ch=R_CONS_KEY_F7; else ch=R_CONS_KEY_F7; break; case VK_F8: if (bCtrl) ch=R_CONS_KEY_F8; else ch=R_CONS_KEY_F8; break; case VK_F9: if (bCtrl) ch=R_CONS_KEY_F9; else ch=R_CONS_KEY_F9; break; case VK_F10: if (bCtrl) ch=R_CONS_KEY_F10; else ch=R_CONS_KEY_F10; break; case VK_F11: if (bCtrl) ch=R_CONS_KEY_F11; else ch=R_CONS_KEY_F11; break; case VK_F12: if (bCtrl) ch=R_CONS_KEY_F12; else ch=R_CONS_KEY_F12; break; default: ch=0; break; } } } } } } FlushConsoleInputBuffer(h); SetConsoleMode (h, mode); if (ch==0) goto do_it_again; /*r_cons_gotoxy (1, 2); r_cons_printf ("\n"); r_cons_printf ("| buf = %x |\n", ch); r_cons_printf ("\n"); r_cons_flush (); r_sys_sleep (1);*/ return ch; } #endif R_API int r_cons_readchar() { char buf[2]; buf[0] = -1; #if __WINDOWS__ && !__CYGWIN__ //&& !MINGW32 #if 1 // if something goes wrong set this to 0. skuater..... return readchar_win(); #endif BOOL ret; DWORD out; DWORD mode; HANDLE h = GetStdHandle (STD_INPUT_HANDLE); GetConsoleMode (h, &mode); SetConsoleMode (h, 0); // RAW ignore: ret = ReadConsole (h, buf, 1, &out, NULL); FlushConsoleInputBuffer(h); if (!ret) return -1; SetConsoleMode (h, mode); #else r_cons_set_raw (1); if (read (0, buf, 1)==-1) return -1; r_cons_set_raw (0); #endif return r_cons_controlz (buf[0]); } R_API int r_cons_yesno(int def, const char *fmt, ...) { va_list ap; int key = def; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); fflush (stderr); r_cons_set_raw (1); (void)read (0, &key, 1); write (2, "\n", 1); if (key == 'Y') key = 'y'; r_cons_set_raw (0); if (key=='\n' || key=='\r') key = def; return key=='y'; }