2016-05-15 23:54:47 +02:00
|
|
|
/* radare2 - LGPL - Copyright 2008-2016 - pancake */
|
2009-02-05 22:08:46 +01:00
|
|
|
|
|
|
|
#include <r_cons.h>
|
2014-05-17 02:37:29 +02:00
|
|
|
#include <r_print.h>
|
2016-01-16 08:43:54 -05:00
|
|
|
#include <limits.h>
|
2009-02-05 22:08:46 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2010-02-18 16:36:55 +01:00
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
2009-02-05 22:08:46 +01:00
|
|
|
|
2016-06-29 12:33:31 +02:00
|
|
|
#define COUNT_LINES 1
|
|
|
|
|
2013-09-03 22:45:43 +02:00
|
|
|
R_LIB_VERSION (r_cons);
|
2013-06-14 02:51:33 +02:00
|
|
|
|
2010-02-21 20:21:36 +01:00
|
|
|
static RCons r_cons_instance;
|
2010-01-30 14:02:53 +01:00
|
|
|
#define I r_cons_instance
|
2009-02-17 00:09:40 +01:00
|
|
|
|
2016-10-18 23:15:51 +02:00
|
|
|
//this structure goes into cons_stack when r_cons_push/pop
|
|
|
|
typedef struct {
|
|
|
|
char *buf;
|
2016-12-22 00:13:16 +03:00
|
|
|
int buf_len;
|
2016-10-18 23:15:51 +02:00
|
|
|
int buf_size;
|
2016-11-02 22:59:32 +01:00
|
|
|
RConsGrep *grep;
|
2016-10-18 23:15:51 +02:00
|
|
|
} RConsStack;
|
|
|
|
|
2016-11-20 19:20:14 +01:00
|
|
|
typedef struct {
|
|
|
|
bool breaked;
|
|
|
|
void *data;
|
2016-12-22 00:13:16 +03:00
|
|
|
RConsEvent event_interrupt;
|
2016-11-20 19:20:14 +01:00
|
|
|
} RConsBreakStack;
|
|
|
|
|
|
|
|
static void break_stack_free(void *ptr) {
|
|
|
|
RConsBreakStack *b = (RConsBreakStack*)ptr;
|
|
|
|
free (b);
|
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
|
|
|
|
static void cons_stack_free(void *ptr) {
|
|
|
|
RConsStack *s = (RConsStack *)ptr;
|
|
|
|
free (s->buf);
|
2016-11-02 22:59:32 +01:00
|
|
|
free (s->grep);
|
2016-10-18 23:15:51 +02:00
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
static void break_signal(int sig) {
|
2015-09-14 02:08:31 +02:00
|
|
|
I.breaked = true;
|
2014-05-14 23:24:46 +02:00
|
|
|
r_print_set_interrupted (I.breaked);
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.event_interrupt) {
|
2011-01-23 13:12:16 +01:00
|
|
|
I.event_interrupt (I.data);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2009-02-17 00:09:40 +01:00
|
|
|
}
|
|
|
|
|
2016-10-18 23:15:51 +02:00
|
|
|
static inline void r_cons_write(const char *buf, int len) {
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2015-11-01 05:10:49 +01:00
|
|
|
if (I.ansicon) {
|
2016-06-29 12:33:31 +02:00
|
|
|
(void) write (I.fdout, buf, len);
|
2015-06-11 12:12:22 +02:00
|
|
|
} else {
|
2015-11-01 05:10:49 +01:00
|
|
|
if (I.fdout == 1) {
|
|
|
|
r_cons_w32_print ((const ut8*)buf, len, 0);
|
|
|
|
} else {
|
2016-06-29 12:33:31 +02:00
|
|
|
(void) write (I.fdout, buf, len);
|
2015-11-01 05:10:49 +01:00
|
|
|
}
|
2015-06-11 12:12:22 +02:00
|
|
|
}
|
2010-06-25 01:44:15 +02:00
|
|
|
#else
|
2016-06-29 12:33:31 +02:00
|
|
|
(void) write (I.fdout, buf, len);
|
2010-06-25 01:44:15 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-08-31 17:06:59 +02:00
|
|
|
R_API char *r_cons_color_random_string(int bg) {
|
|
|
|
int r, g, b;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.truecolor > 0) {
|
2015-08-31 17:06:59 +02:00
|
|
|
char out[32];
|
|
|
|
r = r_num_rand (0xff);
|
|
|
|
g = r_num_rand (0xff);
|
|
|
|
b = r_num_rand (0xff);
|
|
|
|
r_cons_rgb_str (out, r, g, b, bg);
|
|
|
|
return strdup (out);
|
|
|
|
}
|
|
|
|
// random ansi
|
2016-06-29 12:33:31 +02:00
|
|
|
const char *color = "white";
|
2015-08-31 17:06:59 +02:00
|
|
|
r = r_num_rand (8);
|
|
|
|
switch (r) {
|
2016-07-01 00:56:35 -04:00
|
|
|
case 0: color = "red"; break;
|
|
|
|
case 1: color = "white"; break;
|
|
|
|
case 2: color = "green"; break;
|
|
|
|
case 3: color = "magenta"; break;
|
|
|
|
case 4: color = "yellow"; break;
|
|
|
|
case 5: color = "cyan"; break;
|
|
|
|
case 6: color = "blue"; break;
|
|
|
|
case 7: color = "gray"; break;
|
2015-08-31 17:06:59 +02:00
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
return strdup (color);
|
2015-08-31 17:06:59 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 23:48:18 +02:00
|
|
|
R_API char *r_cons_color_random(int bg) {
|
|
|
|
int r, g, b;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.truecolor > 0) {
|
2013-10-14 23:48:18 +02:00
|
|
|
char out[32];
|
2013-10-15 03:56:01 +02:00
|
|
|
r = r_num_rand (0xff);
|
|
|
|
g = r_num_rand (0xff);
|
|
|
|
b = r_num_rand (0xff);
|
2013-10-14 23:48:18 +02:00
|
|
|
r_cons_rgb_str (out, r, g, b, bg);
|
|
|
|
return strdup (out);
|
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
const char *color = Color_RESET;
|
2013-10-14 23:48:18 +02:00
|
|
|
// random ansi
|
|
|
|
r = r_num_rand (16);
|
|
|
|
switch (r) {
|
2016-07-01 00:56:35 -04:00
|
|
|
case 0: color = Color_RED; break;
|
|
|
|
case 1: color = Color_BRED; break;
|
|
|
|
case 2: color = Color_WHITE; break;
|
|
|
|
case 3: color = Color_BWHITE; break;
|
|
|
|
case 4: color = Color_GREEN; break;
|
|
|
|
case 5: color = Color_BGREEN; break;
|
|
|
|
case 6: color = Color_MAGENTA; break;
|
|
|
|
case 7: color = Color_BMAGENTA; break;
|
|
|
|
case 8: color = Color_YELLOW; break;
|
|
|
|
case 9: color = Color_BYELLOW; break;
|
|
|
|
case 10: color = Color_CYAN; break;
|
|
|
|
case 11: color = Color_BCYAN; break;
|
|
|
|
case 12: color = Color_BLUE; break;
|
|
|
|
case 13: color = Color_BBLUE; break;
|
|
|
|
case 14: color = Color_GRAY; break;
|
|
|
|
case 15: color = Color_BGRAY; break;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
|
|
|
return strdup (color);
|
2013-10-14 23:48:18 +02:00
|
|
|
}
|
|
|
|
|
2013-01-22 05:06:12 +01:00
|
|
|
R_API void r_cons_color (int fg, int r, int g, int b) {
|
|
|
|
int k;
|
|
|
|
r = R_DIM (r, 0, 255);
|
|
|
|
g = R_DIM (g, 0, 255);
|
|
|
|
b = R_DIM (b, 0, 255);
|
|
|
|
if (r == g && g == b) { // b&w
|
|
|
|
k = 232 + (int)(((r+g+b)/3)/10.3);
|
|
|
|
} else {
|
2016-06-29 12:33:31 +02:00
|
|
|
r = (int)(r / 42.6);
|
|
|
|
g = (int)(g / 42.6);
|
|
|
|
b = (int)(b / 42.6);
|
|
|
|
k = 16 + (r * 36) + (g * 6) + b;
|
2013-01-22 05:06:12 +01:00
|
|
|
}
|
|
|
|
r_cons_printf ("\x1b[%d;5;%dm", fg? 48: 38, k);
|
|
|
|
}
|
|
|
|
|
2016-06-26 00:16:37 -04:00
|
|
|
R_API void r_cons_println(const char* str) {
|
|
|
|
r_cons_print (str);
|
2016-09-14 00:22:43 +02:00
|
|
|
r_cons_newline ();
|
2016-06-26 00:16:37 -04:00
|
|
|
}
|
|
|
|
|
2016-12-24 18:12:04 +01:00
|
|
|
R_API void r_cons_strcat_justify(const char *str, int j, char c) {
|
2011-05-21 14:27:46 +02:00
|
|
|
int i, o, len;
|
2016-06-29 12:33:31 +02:00
|
|
|
for (o = i = len = 0; str[i]; i++, len++) {
|
2011-05-21 14:27:46 +02:00
|
|
|
if (str[i]=='\n') {
|
|
|
|
r_cons_memset (' ', j);
|
2011-09-12 03:26:32 +02:00
|
|
|
if (c) {
|
|
|
|
r_cons_memset (c, 1);
|
|
|
|
r_cons_memset (' ', 1);
|
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
r_cons_memcat (str + o, len);
|
|
|
|
if (str[o + len] == '\n') {
|
2011-05-21 14:27:46 +02:00
|
|
|
r_cons_newline ();
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
|
|
|
o = i + 1;
|
2011-05-21 14:27:46 +02:00
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
if (len > 1) {
|
2016-12-17 10:42:15 +01:00
|
|
|
r_cons_memcat (str + o, len);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2011-05-21 14:27:46 +02:00
|
|
|
}
|
|
|
|
|
2010-02-18 16:36:55 +01:00
|
|
|
R_API RCons *r_cons_singleton () {
|
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
|
2016-11-20 19:20:14 +01:00
|
|
|
R_API void r_cons_break_clear() {
|
2015-09-14 02:08:31 +02:00
|
|
|
I.breaked = false;
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_break_push(RConsBreak cb, void *user) {
|
|
|
|
if (I.break_stack) {
|
|
|
|
//if we don't have any element in the stack start the signal
|
|
|
|
RConsBreakStack *b = R_NEW0 (RConsBreakStack);
|
|
|
|
if (!b) return;
|
|
|
|
if (r_stack_is_empty (I.break_stack)) {
|
|
|
|
#if __UNIX__ || __CYGWIN__
|
|
|
|
signal (SIGINT, break_signal);
|
|
|
|
#endif
|
|
|
|
I.breaked = false;
|
|
|
|
}
|
|
|
|
//save the actual state
|
|
|
|
b->event_interrupt = I.event_interrupt;
|
|
|
|
b->data = I.data;
|
|
|
|
r_stack_push (I.break_stack, b);
|
|
|
|
//configure break
|
|
|
|
I.event_interrupt = cb;
|
|
|
|
I.data = user;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_break_pop() {
|
|
|
|
//restore old state
|
|
|
|
if (I.break_stack) {
|
2016-12-22 00:13:16 +03:00
|
|
|
RConsBreakStack *b = NULL;
|
2016-11-20 19:20:14 +01:00
|
|
|
r_print_set_interrupted (I.breaked);
|
|
|
|
b = r_stack_pop (I.break_stack);
|
|
|
|
if (b) {
|
|
|
|
I.event_interrupt = b->event_interrupt;
|
|
|
|
I.data = b->data;
|
|
|
|
break_stack_free (b);
|
|
|
|
} else {
|
|
|
|
//there is not more elements in the stack
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2016-11-20 19:20:14 +01:00
|
|
|
signal (SIGINT, SIG_IGN);
|
2009-02-17 00:09:40 +01:00
|
|
|
#endif
|
2016-12-22 00:13:16 +03:00
|
|
|
I.breaked = false;
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
}
|
2009-02-17 00:09:40 +01:00
|
|
|
}
|
|
|
|
|
2015-09-25 18:38:07 +02:00
|
|
|
R_API bool r_cons_is_breaked() {
|
2016-12-12 23:57:04 +01:00
|
|
|
if (I.timeout) {
|
|
|
|
if (r_sys_now () > I.timeout) {
|
|
|
|
I.breaked = true;
|
|
|
|
eprintf ("\nTimeout!\n");
|
|
|
|
I.timeout = 0;
|
|
|
|
}
|
|
|
|
}
|
2015-07-21 06:06:00 +02:00
|
|
|
return I.breaked;
|
|
|
|
}
|
|
|
|
|
2016-12-12 23:57:04 +01:00
|
|
|
R_API void r_cons_break_timeout(int timeout) {
|
|
|
|
if (!timeout && I.timeout) {
|
|
|
|
I.timeout = 0;
|
|
|
|
} else {
|
|
|
|
if (timeout) {
|
|
|
|
I.timeout = r_sys_now () + (timeout * 1000000);
|
|
|
|
} else {
|
|
|
|
I.timeout = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_break_end() {
|
2015-09-14 02:08:31 +02:00
|
|
|
I.breaked = false;
|
2016-12-12 23:57:04 +01:00
|
|
|
I.timeout = 0;
|
2014-05-14 23:24:46 +02:00
|
|
|
r_print_set_interrupted (I.breaked);
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2010-01-30 14:02:53 +01:00
|
|
|
signal (SIGINT, SIG_IGN);
|
2009-02-17 00:09:40 +01:00
|
|
|
#endif
|
2016-11-20 19:20:14 +01:00
|
|
|
if (!r_stack_is_empty (I.break_stack)) {
|
|
|
|
//free all the stack
|
|
|
|
r_stack_free (I.break_stack);
|
|
|
|
//create another one
|
|
|
|
I.break_stack = r_stack_newf (6, break_stack_free);
|
|
|
|
I.data = NULL;
|
|
|
|
I.event_interrupt = NULL;
|
|
|
|
}
|
2009-02-17 00:09:40 +01:00
|
|
|
}
|
|
|
|
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2010-06-27 22:14:06 +02:00
|
|
|
static HANDLE h;
|
|
|
|
static BOOL __w32_control(DWORD type) {
|
2010-10-28 14:17:40 +02:00
|
|
|
if (type == CTRL_C_EVENT) {
|
2010-06-27 22:14:06 +02:00
|
|
|
break_signal (2); // SIGINT
|
2015-05-05 18:08:01 +02:00
|
|
|
eprintf("{ctrl+c} pressed.\n");
|
2015-09-14 02:08:31 +02:00
|
|
|
return true;
|
2010-10-28 14:17:40 +02:00
|
|
|
}
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2010-06-27 22:14:06 +02:00
|
|
|
}
|
2015-01-26 19:55:12 +03:00
|
|
|
#elif __UNIX__ || __CYGWIN__
|
2011-01-23 13:12:16 +01:00
|
|
|
static void resize (int sig) {
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.event_resize) {
|
2013-04-01 05:28:34 +02:00
|
|
|
I.event_resize (I.event_data);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2011-01-23 13:12:16 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-06-29 12:33:31 +02:00
|
|
|
R_API bool r_cons_enable_mouse(const bool enable) {
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2016-06-29 12:33:31 +02:00
|
|
|
const char *code = enable
|
|
|
|
? "\x1b[?1001s" "\x1b[?1000h"
|
|
|
|
: "\x1b[?1001r" "\x1b[?1000l";
|
|
|
|
bool enabled = I.mouse;
|
|
|
|
I.mouse = enable;
|
|
|
|
write (2, code, 16);
|
2014-03-02 00:31:35 +01:00
|
|
|
return enabled;
|
|
|
|
#else
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2014-03-02 00:31:35 +01:00
|
|
|
#endif
|
2014-02-27 10:39:31 +00:00
|
|
|
}
|
|
|
|
|
2016-06-29 12:33:31 +02:00
|
|
|
static void r_cons_pal_null() {
|
2015-04-10 11:22:45 +02:00
|
|
|
int i;
|
|
|
|
RCons *cons = r_cons_singleton ();
|
2016-06-29 12:33:31 +02:00
|
|
|
for (i = 0; i < R_CONS_PALETTE_LIST_SIZE; i++){
|
2016-12-22 00:13:16 +03:00
|
|
|
cons->pal.list[i] = NULL;
|
2015-04-10 11:22:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 23:15:51 +02:00
|
|
|
R_API RCons *r_cons_new() {
|
2015-01-21 18:06:06 +01:00
|
|
|
I.refcnt++;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.refcnt != 1) {
|
2015-01-21 18:06:06 +01:00
|
|
|
return &I;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2013-08-28 03:06:10 +02:00
|
|
|
I.line = r_line_new ();
|
2014-09-27 04:05:27 +02:00
|
|
|
I.highlight = NULL;
|
2011-01-23 13:12:16 +01:00
|
|
|
I.event_interrupt = NULL;
|
2015-01-14 23:31:29 +01:00
|
|
|
I.is_wine = -1;
|
2014-02-24 16:10:12 +01:00
|
|
|
I.fps = 0;
|
2017-02-20 02:31:49 +01:00
|
|
|
I.use_color = false;
|
2015-09-14 02:08:31 +02:00
|
|
|
I.blankline = true;
|
2013-12-09 05:23:06 +01:00
|
|
|
I.teefile = NULL;
|
2014-01-09 00:29:00 +01:00
|
|
|
I.fix_columns = 0;
|
|
|
|
I.fix_rows = 0;
|
2015-02-11 00:13:04 +01:00
|
|
|
I.mouse_event = 0;
|
2014-01-09 00:29:00 +01:00
|
|
|
I.force_rows = 0;
|
|
|
|
I.force_columns = 0;
|
2011-01-23 13:12:16 +01:00
|
|
|
I.event_resize = NULL;
|
|
|
|
I.data = NULL;
|
2013-04-01 05:28:34 +02:00
|
|
|
I.event_data = NULL;
|
2015-09-14 02:08:31 +02:00
|
|
|
I.is_interactive = true;
|
|
|
|
I.noflush = false;
|
2016-10-26 23:04:55 +02:00
|
|
|
I.linesleep = 0;
|
2010-01-30 14:02:53 +01:00
|
|
|
I.fdin = stdin;
|
|
|
|
I.fdout = 1;
|
2015-09-14 02:08:31 +02:00
|
|
|
I.breaked = false;
|
2013-08-28 03:06:10 +02:00
|
|
|
//I.lines = 0;
|
2010-01-30 14:02:53 +01:00
|
|
|
I.buffer = NULL;
|
|
|
|
I.buffer_sz = 0;
|
|
|
|
I.buffer_len = 0;
|
2016-10-26 23:04:55 +02:00
|
|
|
r_cons_get_size (&I.pagesize);
|
2011-06-26 23:49:11 +02:00
|
|
|
I.num = NULL;
|
2014-01-08 23:44:05 +01:00
|
|
|
I.null = 0;
|
2015-11-01 05:10:49 +01:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2015-12-08 14:59:30 +01:00
|
|
|
I.ansicon = r_sys_getenv ("ANSICON");
|
2015-11-01 05:10:49 +01:00
|
|
|
#endif
|
2012-11-12 17:06:28 +01:00
|
|
|
#if EMSCRIPTEN
|
|
|
|
/* do nothing here :? */
|
2015-01-26 19:55:12 +03:00
|
|
|
#elif __UNIX__ || __CYGWIN__
|
2010-01-30 14:02:53 +01:00
|
|
|
tcgetattr (0, &I.term_buf);
|
2010-02-28 14:49:26 +01:00
|
|
|
memcpy (&I.term_raw, &I.term_buf, sizeof (I.term_raw));
|
2010-01-30 14:02:53 +01:00
|
|
|
I.term_raw.c_iflag &= ~(BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
|
|
|
I.term_raw.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
|
|
|
I.term_raw.c_cflag &= ~(CSIZE|PARENB);
|
|
|
|
I.term_raw.c_cflag |= CS8;
|
|
|
|
I.term_raw.c_cc[VMIN] = 1; // Solaris stuff hehe
|
2011-01-23 13:12:16 +01:00
|
|
|
signal (SIGWINCH, resize);
|
2010-01-30 14:02:53 +01:00
|
|
|
#elif __WINDOWS__
|
2010-06-27 22:14:06 +02:00
|
|
|
h = GetStdHandle (STD_INPUT_HANDLE);
|
2010-10-28 14:17:40 +02:00
|
|
|
GetConsoleMode (h, (PDWORD) &I.term_buf);
|
2010-01-30 14:02:53 +01:00
|
|
|
I.term_raw = 0;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (!SetConsoleCtrlHandler ((PHANDLER_ROUTINE)__w32_control, TRUE)) {
|
2010-03-05 01:49:12 +01:00
|
|
|
eprintf ("r_cons: Cannot set control console handler\n");
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
#endif
|
2012-02-05 02:39:04 +01:00
|
|
|
I.pager = NULL; /* no pager by default */
|
2013-07-17 19:34:27 +02:00
|
|
|
I.truecolor = 0;
|
2014-03-02 00:31:35 +01:00
|
|
|
I.mouse = 0;
|
2016-10-18 23:15:51 +02:00
|
|
|
I.cons_stack = r_stack_newf (6, cons_stack_free);
|
2016-11-20 19:20:14 +01:00
|
|
|
I.break_stack = r_stack_newf (6, break_stack_free);
|
2015-04-10 11:22:45 +02:00
|
|
|
r_cons_pal_null ();
|
2013-05-22 04:22:49 +02:00
|
|
|
r_cons_pal_init (NULL);
|
|
|
|
r_cons_rgb_init ();
|
2010-01-30 14:02:53 +01:00
|
|
|
r_cons_reset ();
|
2010-05-20 17:40:58 +02:00
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
|
2016-10-18 23:15:51 +02:00
|
|
|
R_API RCons *r_cons_free() {
|
2015-01-21 18:06:06 +01:00
|
|
|
I.refcnt--;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.refcnt != 0) {
|
2015-01-21 18:06:06 +01:00
|
|
|
return NULL;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2015-04-10 11:22:45 +02:00
|
|
|
r_cons_pal_free ();
|
2013-08-28 03:06:10 +02:00
|
|
|
if (I.line) {
|
2015-01-13 02:01:44 +01:00
|
|
|
r_line_free ();
|
2013-08-28 03:06:10 +02:00
|
|
|
I.line = NULL;
|
|
|
|
}
|
2011-10-09 21:54:14 +02:00
|
|
|
if (I.buffer) {
|
2010-12-26 23:38:53 +01:00
|
|
|
free (I.buffer);
|
2011-10-09 21:54:14 +02:00
|
|
|
I.buffer = NULL;
|
|
|
|
}
|
2016-12-17 10:42:15 +01:00
|
|
|
R_FREE (I.break_word);
|
2016-12-22 00:13:16 +03:00
|
|
|
r_stack_free (I.cons_stack);
|
2016-11-20 19:20:14 +01:00
|
|
|
r_stack_free (I.break_stack);
|
2010-05-20 17:40:58 +02:00
|
|
|
return NULL;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2016-06-29 12:33:31 +02:00
|
|
|
#define MOAR (4096 * 8)
|
2016-10-19 02:09:14 +02:00
|
|
|
static bool palloc(int moar) {
|
2016-01-16 08:43:54 -05:00
|
|
|
void *temp;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (moar <= 0) {
|
2016-10-19 02:09:14 +02:00
|
|
|
return false;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2016-09-19 13:44:47 +01:00
|
|
|
if (!I.buffer) {
|
2016-01-16 08:43:54 -05:00
|
|
|
int new_sz;
|
2016-06-29 12:33:31 +02:00
|
|
|
if ((INT_MAX - MOAR) < moar) {
|
2016-10-19 02:09:14 +02:00
|
|
|
return false;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2016-05-15 23:54:47 +02:00
|
|
|
new_sz = moar + MOAR;
|
2016-06-29 12:33:31 +02:00
|
|
|
temp = calloc (1, new_sz);
|
|
|
|
if (temp) {
|
|
|
|
I.buffer_sz = new_sz;
|
|
|
|
I.buffer = temp;
|
|
|
|
I.buffer[0] = '\0';
|
|
|
|
}
|
2016-10-19 02:09:14 +02:00
|
|
|
} else if (moar + I.buffer_len > I.buffer_sz) {
|
2014-08-30 01:11:04 +02:00
|
|
|
char *new_buffer;
|
|
|
|
int old_buffer_sz = I.buffer_sz;
|
2016-06-29 12:33:31 +02:00
|
|
|
if ((INT_MAX - MOAR - moar) < I.buffer_sz) {
|
2016-10-19 02:09:14 +02:00
|
|
|
return false;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2016-10-19 02:09:14 +02:00
|
|
|
I.buffer_sz += moar + MOAR;
|
2016-01-16 08:43:54 -05:00
|
|
|
new_buffer = realloc (I.buffer, I.buffer_sz);
|
2016-06-29 12:33:31 +02:00
|
|
|
if (new_buffer) {
|
2014-08-30 01:11:04 +02:00
|
|
|
I.buffer = new_buffer;
|
2016-06-29 12:33:31 +02:00
|
|
|
} else {
|
|
|
|
I.buffer_sz = old_buffer_sz;
|
2016-10-19 02:09:14 +02:00
|
|
|
return false;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
2016-10-19 02:09:14 +02:00
|
|
|
return true;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API int r_cons_eof() {
|
2010-01-30 14:02:53 +01:00
|
|
|
return feof (I.fdin);
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_gotoxy(int x, int y) {
|
2011-12-05 15:21:13 +01:00
|
|
|
r_cons_printf ("\x1b[%d;%dH", y, x);
|
2009-04-03 11:11:17 +00:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
|
2012-11-14 03:25:32 +01:00
|
|
|
R_API void r_cons_print_clear() {
|
2016-06-29 12:33:31 +02:00
|
|
|
r_cons_strcat ("\x1b[0;0H\x1b[0m");
|
2012-11-14 03:25:32 +01:00
|
|
|
}
|
|
|
|
|
2013-07-17 03:51:53 +02:00
|
|
|
R_API void r_cons_fill_line() {
|
|
|
|
char *p, white[1024];
|
2016-06-29 12:33:31 +02:00
|
|
|
int cols = I.columns - 1;
|
|
|
|
if (cols < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p = (cols >= sizeof (white))
|
|
|
|
? malloc (cols + 1): white;
|
|
|
|
if (p) {
|
|
|
|
memset (p, ' ', cols);
|
|
|
|
p[cols] = 0;
|
|
|
|
r_cons_strcat (p);
|
|
|
|
if (white != p) {
|
|
|
|
free (p);
|
|
|
|
}
|
|
|
|
}
|
2013-07-17 03:51:53 +02:00
|
|
|
}
|
|
|
|
|
2014-03-08 02:56:04 +01:00
|
|
|
R_API void r_cons_clear_line(int std_err) {
|
2011-11-29 03:46:46 +01:00
|
|
|
#if __WINDOWS__
|
2015-11-01 05:10:49 +01:00
|
|
|
if (I.ansicon) {
|
|
|
|
fprintf (std_err? stderr: stdout,"\x1b[0K\r");
|
|
|
|
} else {
|
|
|
|
char white[1024];
|
|
|
|
memset (&white, ' ', sizeof (white));
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.columns < sizeof (white)) {
|
|
|
|
white[I.columns - 1] = 0;
|
|
|
|
} else {
|
|
|
|
white[sizeof (white) - 1] = 0; // HACK
|
|
|
|
}
|
2015-11-01 05:10:49 +01:00
|
|
|
fprintf (std_err? stderr: stdout, "\r%s\r", white);
|
|
|
|
}
|
2011-11-29 03:46:46 +01:00
|
|
|
#else
|
2014-03-08 02:56:04 +01:00
|
|
|
fprintf (std_err? stderr: stdout,"\x1b[0K\r");
|
2011-11-29 03:46:46 +01:00
|
|
|
#endif
|
2014-03-08 02:56:04 +01:00
|
|
|
fflush (std_err? stderr: stdout);
|
2011-11-19 02:49:11 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_clear00() {
|
2010-01-30 14:02:53 +01:00
|
|
|
r_cons_clear ();
|
|
|
|
r_cons_gotoxy (0, 0);
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2013-04-01 04:42:14 +02:00
|
|
|
R_API void r_cons_reset_colors() {
|
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_clear() {
|
2010-02-28 23:57:55 +01:00
|
|
|
r_cons_strcat (Color_RESET"\x1b[2J");
|
2010-01-30 14:02:53 +01:00
|
|
|
I.lines = 0;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_reset() {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.buffer) {
|
2010-01-30 14:02:53 +01:00
|
|
|
I.buffer[0] = '\0';
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
I.buffer_len = 0;
|
|
|
|
I.lines = 0;
|
|
|
|
I.lastline = I.buffer;
|
|
|
|
I.grep.strings[0][0] = '\0';
|
|
|
|
I.grep.nstrings = 0; // XXX
|
|
|
|
I.grep.line = -1;
|
2016-10-25 12:03:55 +02:00
|
|
|
I.grep.sort = -1;
|
2016-10-25 12:39:36 +02:00
|
|
|
I.grep.sort_invert = false;
|
2010-01-30 14:02:53 +01:00
|
|
|
I.grep.str = NULL;
|
2015-09-23 23:00:14 +02:00
|
|
|
memset (I.grep.tokens, 0, R_CONS_GREP_TOKENS);
|
|
|
|
I.grep.tokens_used = 0;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API const char *r_cons_get_buffer() {
|
2016-11-18 12:59:27 +01:00
|
|
|
//check len otherwise it will return trash
|
|
|
|
return I.buffer_len? I.buffer : NULL;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-08-17 01:27:24 +02:00
|
|
|
R_API void r_cons_filter() {
|
2017-02-20 02:31:49 +01:00
|
|
|
/* grep */
|
2016-10-19 16:18:04 +02:00
|
|
|
if (I.grep.nstrings > 0 || I.grep.tokens_used || I.grep.less || I.grep.json) {
|
2010-08-17 01:27:24 +02:00
|
|
|
r_cons_grepbuf (I.buffer, I.buffer_len);
|
2016-10-18 01:49:32 +02:00
|
|
|
}
|
2010-08-17 01:27:24 +02:00
|
|
|
/* html */
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
2015-03-31 00:44:14 +02:00
|
|
|
R_API void r_cons_push() {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.cons_stack) {
|
|
|
|
RConsStack *data = R_NEW0 (RConsStack);
|
|
|
|
data->buf = malloc (I.buffer_len);
|
|
|
|
if (!data->buf) {
|
|
|
|
free (data);
|
2016-10-18 01:49:32 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
memcpy (data->buf, I.buffer, I.buffer_len);
|
|
|
|
data->buf_len = I.buffer_len;
|
|
|
|
data->buf_size = I.buffer_sz;
|
2016-11-02 22:59:32 +01:00
|
|
|
data->grep = R_NEW0 (RConsGrep);
|
|
|
|
if (data->grep) {
|
|
|
|
memcpy (data->grep, &I.grep, sizeof (RConsGrep));
|
|
|
|
if (I.grep.str) {
|
|
|
|
data->grep->str = strdup (I.grep.str);
|
|
|
|
}
|
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
r_stack_push (I.cons_stack, data);
|
2015-03-31 00:44:14 +02:00
|
|
|
I.buffer_len = 0;
|
2016-11-17 23:41:49 +01:00
|
|
|
if (I.buffer) {
|
|
|
|
memset (I.buffer, 0, I.buffer_sz);
|
|
|
|
}
|
2015-03-31 00:44:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_pop() {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.cons_stack) {
|
|
|
|
RConsStack *data = (RConsStack *)r_stack_pop (I.cons_stack);
|
2016-10-19 02:09:14 +02:00
|
|
|
char *tmp;
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!data) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!data->buf) {
|
|
|
|
free (data);
|
|
|
|
return;
|
2016-12-22 00:13:16 +03:00
|
|
|
}
|
2016-10-19 02:09:14 +02:00
|
|
|
tmp = malloc (data->buf_size);
|
|
|
|
if (!tmp) {
|
|
|
|
cons_stack_free ((void *)data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
free (I.buffer);
|
|
|
|
I.buffer = tmp;
|
2016-10-18 23:15:51 +02:00
|
|
|
memcpy (I.buffer, data->buf, data->buf_len);
|
|
|
|
I.buffer_len = data->buf_len;
|
|
|
|
I.buffer_sz = data->buf_size;
|
2016-11-02 22:59:32 +01:00
|
|
|
if (data->grep) {
|
|
|
|
memcpy (&I.grep, data->grep, sizeof (RConsGrep));
|
|
|
|
if (data->grep->str) {
|
|
|
|
free (I.grep.str);
|
|
|
|
I.grep.str = data->grep->str;
|
|
|
|
}
|
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
cons_stack_free ((void *)data);
|
2015-03-31 00:44:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_flush() {
|
|
|
|
const char *tee = I.teefile;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.noflush) {
|
2009-02-05 22:08:46 +01:00
|
|
|
return;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2014-01-08 23:44:05 +01:00
|
|
|
if (I.null) {
|
|
|
|
r_cons_reset ();
|
|
|
|
return;
|
|
|
|
}
|
2010-08-17 01:27:24 +02:00
|
|
|
r_cons_filter ();
|
2016-09-18 13:28:26 +02:00
|
|
|
if (I.is_interactive && I.fdout == 1) {
|
2012-02-05 02:39:04 +01:00
|
|
|
/* Use a pager if the output doesn't fit on the terminal window. */
|
2015-01-17 01:21:43 +01:00
|
|
|
if (I.pager && *I.pager && I.buffer_len > 0
|
2012-02-05 02:39:04 +01:00
|
|
|
&& r_str_char_count (I.buffer, '\n') >= I.rows) {
|
|
|
|
I.buffer[I.buffer_len-1] = 0;
|
2013-11-09 03:25:43 +01:00
|
|
|
r_sys_cmd_str_full (I.pager, I.buffer, NULL, NULL, NULL);
|
2012-02-05 02:39:04 +01:00
|
|
|
r_cons_reset ();
|
|
|
|
|
|
|
|
} else if (I.buffer_len > CONS_MAX_USER) {
|
2015-04-09 19:54:59 +02:00
|
|
|
#if COUNT_LINES
|
|
|
|
int i, lines = 0;
|
2016-10-18 23:15:51 +02:00
|
|
|
for (i = 0; I.buffer[i]; i++) {
|
2016-12-12 20:21:20 +01:00
|
|
|
if (I.buffer[i] == '\n') {
|
2015-04-09 19:54:59 +02:00
|
|
|
lines ++;
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2015-04-09 19:54:59 +02:00
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
if (lines > 0 && !r_cons_yesno ('n',"Do you want to print %d lines? (y/N)", lines)) {
|
2015-04-09 19:54:59 +02:00
|
|
|
r_cons_reset ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2014-05-14 03:53:22 +02:00
|
|
|
char buf[64];
|
|
|
|
char *buflen = r_num_units (buf, I.buffer_len);
|
2015-07-07 00:21:51 +02:00
|
|
|
if (buflen && !r_cons_yesno ('n',"Do you want to print %s chars? (y/N)", buflen)) {
|
2010-01-30 14:02:53 +01:00
|
|
|
r_cons_reset ();
|
2009-02-27 00:18:19 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-04-09 19:54:59 +02:00
|
|
|
#endif
|
2014-11-10 05:39:17 +01:00
|
|
|
// fix | more | less problem
|
|
|
|
r_cons_set_raw (1);
|
2009-02-27 00:18:19 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-11 12:12:22 +02:00
|
|
|
if (tee && *tee) {
|
2012-10-20 00:31:18 +02:00
|
|
|
FILE *d = r_sandbox_fopen (tee, "a+");
|
2016-10-18 23:15:51 +02:00
|
|
|
if (d) {
|
2016-10-19 16:18:04 +02:00
|
|
|
if (I.buffer_len != fwrite (I.buffer, 1, I.buffer_len, d)) {
|
2011-02-28 00:03:26 +01:00
|
|
|
eprintf ("r_cons_flush: fwrite: error (%s)\n", tee);
|
2016-10-19 16:18:04 +02:00
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
fclose (d);
|
2016-10-18 23:15:51 +02:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot write on '%s'\n", tee);
|
|
|
|
}
|
2010-01-26 01:28:33 +01:00
|
|
|
}
|
2014-09-27 03:48:54 +02:00
|
|
|
r_cons_highlight (I.highlight);
|
2011-02-28 00:03:26 +01:00
|
|
|
// is_html must be a filter, not a write endpoint
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.is_html) {
|
|
|
|
r_cons_html_print (I.buffer);
|
|
|
|
} else {
|
2016-11-16 03:02:50 +01:00
|
|
|
if (I.is_interactive && !r_sandbox_enable (false)) {
|
|
|
|
if (I.linesleep > 0 && I.linesleep < 1000) {
|
|
|
|
int i = 0;
|
|
|
|
int pagesize = R_MAX (1, I.pagesize);
|
|
|
|
char *ptr = I.buffer;
|
|
|
|
char *nl = strchr (ptr, '\n');
|
|
|
|
int len = I.buffer_len;
|
|
|
|
I.buffer[I.buffer_len] = 0;
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-11-16 03:02:50 +01:00
|
|
|
while (nl && !r_cons_is_breaked ()) {
|
|
|
|
r_cons_write (ptr, nl - ptr + 1);
|
|
|
|
if (!(i % pagesize)) {
|
|
|
|
r_sys_usleep (I.linesleep * 1000);
|
|
|
|
}
|
|
|
|
ptr = nl + 1;
|
|
|
|
nl = strchr (ptr, '\n');
|
|
|
|
i++;
|
2016-10-26 23:04:55 +02:00
|
|
|
}
|
2016-11-16 03:02:50 +01:00
|
|
|
r_cons_write (ptr, I.buffer + len - ptr);
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2016-11-16 03:02:50 +01:00
|
|
|
} else {
|
|
|
|
r_cons_write (I.buffer, I.buffer_len);
|
2016-10-26 23:04:55 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_cons_write (I.buffer, I.buffer_len);
|
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2015-06-04 01:30:33 +02:00
|
|
|
|
2010-01-30 14:02:53 +01:00
|
|
|
r_cons_reset ();
|
2015-09-29 00:42:31 +02:00
|
|
|
if (I.newline) {
|
|
|
|
eprintf ("\n");
|
|
|
|
I.newline = false;
|
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_visual_flush() {
|
2016-06-29 12:33:31 +02:00
|
|
|
if (I.noflush) {
|
2010-02-28 14:49:26 +01:00
|
|
|
return;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2014-09-27 03:48:54 +02:00
|
|
|
r_cons_highlight (I.highlight);
|
2014-01-08 23:44:05 +01:00
|
|
|
if (!I.null) {
|
2010-02-28 14:49:26 +01:00
|
|
|
/* TODO: this ifdef must go in the function body */
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2015-11-01 05:10:49 +01:00
|
|
|
if (I.ansicon) {
|
|
|
|
r_cons_visual_write (I.buffer);
|
|
|
|
} else {
|
|
|
|
r_cons_w32_print ((const ut8*)I.buffer, I.buffer_len, 1);
|
|
|
|
}
|
2010-02-28 14:49:26 +01:00
|
|
|
#else
|
2014-01-08 23:44:05 +01:00
|
|
|
r_cons_visual_write (I.buffer);
|
2010-02-28 14:49:26 +01:00
|
|
|
#endif
|
2014-01-08 23:44:05 +01:00
|
|
|
}
|
2010-02-28 14:49:26 +01:00
|
|
|
r_cons_reset ();
|
2014-02-24 16:10:12 +01:00
|
|
|
if (I.fps) {
|
2016-06-29 12:33:31 +02:00
|
|
|
int fps = 0, w = r_cons_get_size (NULL);
|
2014-02-24 16:10:12 +01:00
|
|
|
static ut64 prev = 0LL; //r_sys_now ();
|
|
|
|
fps = 0;
|
|
|
|
if (prev) {
|
|
|
|
ut64 now = r_sys_now ();
|
|
|
|
ut64 diff = now-prev;
|
|
|
|
fps = (diff<1000000)? (1000000/diff): 0;
|
|
|
|
prev = now;
|
2016-10-18 23:15:51 +02:00
|
|
|
} else {
|
|
|
|
prev = r_sys_now ();
|
|
|
|
}
|
2014-02-24 16:10:12 +01:00
|
|
|
eprintf ("\x1b[0;%dH[%d FPS] \n", w-10, fps);
|
|
|
|
}
|
2010-02-28 14:49:26 +01:00
|
|
|
}
|
|
|
|
|
2015-12-08 14:59:30 +01:00
|
|
|
static int real_strlen(const char *ptr, int len) {
|
|
|
|
int utf8len = r_str_len_utf8 (ptr);
|
|
|
|
int ansilen = r_str_ansi_len (ptr);
|
2016-06-29 12:33:31 +02:00
|
|
|
int diff = len - utf8len;
|
|
|
|
if (diff) {
|
|
|
|
diff--;
|
|
|
|
}
|
2015-12-08 14:59:30 +01:00
|
|
|
return ansilen - diff;
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_visual_write (char *buffer) {
|
2013-07-17 03:51:53 +02:00
|
|
|
char white[1024];
|
2011-03-24 22:47:06 +01:00
|
|
|
int cols = I.columns;
|
2015-07-13 23:04:34 +02:00
|
|
|
int alen, plen, lines = I.rows;
|
2011-04-06 09:29:25 +02:00
|
|
|
const char *endptr;
|
2015-07-13 23:04:34 +02:00
|
|
|
char *nl, *ptr = buffer, *pptr;
|
2011-04-29 10:38:01 +02:00
|
|
|
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.null) {
|
|
|
|
return;
|
|
|
|
}
|
2011-11-25 09:40:28 +01:00
|
|
|
memset (&white, ' ', sizeof (white));
|
2011-05-21 15:45:43 +02:00
|
|
|
while ((nl = strchr (ptr, '\n'))) {
|
2011-04-29 10:38:01 +02:00
|
|
|
int len = ((int)(size_t)(nl-ptr))+1;
|
2011-03-25 14:54:30 +01:00
|
|
|
|
2011-03-24 22:47:06 +01:00
|
|
|
*nl = 0;
|
2015-12-08 14:59:30 +01:00
|
|
|
alen = real_strlen (ptr, len);
|
2011-03-24 22:47:06 +01:00
|
|
|
*nl = '\n';
|
2015-07-13 23:04:34 +02:00
|
|
|
pptr = ptr > buffer ? ptr - 1 : ptr;
|
|
|
|
plen = ptr > buffer ? len : len - 1;
|
2011-03-25 14:54:30 +01:00
|
|
|
|
2015-07-13 23:04:34 +02:00
|
|
|
if (alen > cols) {
|
2016-01-10 23:46:33 +01:00
|
|
|
int olen = len;
|
2011-03-25 14:54:30 +01:00
|
|
|
endptr = r_str_ansi_chrn (ptr, cols);
|
|
|
|
endptr++;
|
2016-01-10 23:46:33 +01:00
|
|
|
len = endptr - ptr;
|
2015-07-13 23:04:34 +02:00
|
|
|
plen = ptr > buffer ? len : len - 1;
|
2016-01-10 23:46:33 +01:00
|
|
|
if (lines > 0) {
|
2015-07-13 23:04:34 +02:00
|
|
|
r_cons_write (pptr, plen);
|
2016-01-10 23:46:33 +01:00
|
|
|
if (len != olen) {
|
2016-01-11 23:47:49 +01:00
|
|
|
r_cons_write (Color_RESET, strlen (Color_RESET));
|
2016-01-10 23:46:33 +01:00
|
|
|
}
|
|
|
|
}
|
2011-05-21 15:45:43 +02:00
|
|
|
} else {
|
2015-07-13 23:04:34 +02:00
|
|
|
if (lines > 0) {
|
|
|
|
int w = cols - alen;
|
|
|
|
r_cons_write (pptr, plen);
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.blankline && w > 0) {
|
|
|
|
if (w > sizeof (white) - 1) {
|
2016-01-10 23:46:33 +01:00
|
|
|
w = sizeof (white) - 1;
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2011-11-25 00:22:44 +01:00
|
|
|
r_cons_write (white, w);
|
2011-11-25 09:40:28 +01:00
|
|
|
}
|
2011-11-25 00:22:44 +01:00
|
|
|
}
|
2011-12-02 02:13:49 +01:00
|
|
|
// TRICK to empty columns.. maybe buggy in w32
|
|
|
|
if (r_mem_mem ((const ut8*)ptr, len, (const ut8*)"\x1b[0;0H", 6)) {
|
|
|
|
lines = I.rows;
|
2015-07-13 23:04:34 +02:00
|
|
|
r_cons_write (pptr, plen);
|
2011-12-02 02:13:49 +01:00
|
|
|
}
|
2011-05-21 15:45:43 +02:00
|
|
|
}
|
2011-12-02 02:13:49 +01:00
|
|
|
lines--; // do not use last line
|
2016-06-29 12:33:31 +02:00
|
|
|
ptr = nl + 1;
|
2010-02-28 14:49:26 +01:00
|
|
|
}
|
2011-12-05 00:29:24 +01:00
|
|
|
/* fill the rest of screen */
|
2016-06-29 12:33:31 +02:00
|
|
|
if (lines > 0) {
|
|
|
|
if (cols > sizeof (white)) {
|
2011-12-05 00:29:24 +01:00
|
|
|
cols = sizeof (white);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
|
|
|
while (--lines >= 0) {
|
2011-12-05 00:29:24 +01:00
|
|
|
r_cons_write (white, cols);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2011-12-05 00:29:24 +01:00
|
|
|
}
|
2010-02-28 14:49:26 +01:00
|
|
|
}
|
|
|
|
|
2016-12-24 18:12:04 +01:00
|
|
|
R_API void r_cons_printf_list(const char *format, va_list ap) {
|
2012-02-05 00:33:34 +01:00
|
|
|
size_t size, written;
|
2016-12-29 19:20:33 +01:00
|
|
|
va_list ap2;
|
2009-02-05 22:08:46 +01:00
|
|
|
|
2016-12-29 19:20:33 +01:00
|
|
|
va_copy (ap2, ap);
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.null || !format) {
|
2016-12-31 17:22:59 +01:00
|
|
|
va_end (ap2);
|
2016-10-18 23:15:51 +02:00
|
|
|
return;
|
|
|
|
}
|
2010-01-26 01:28:33 +01:00
|
|
|
if (strchr (format, '%')) {
|
2015-08-31 17:06:59 +02:00
|
|
|
palloc (MOAR + strlen (format) * 20);
|
2016-12-29 19:20:33 +01:00
|
|
|
club:
|
2015-08-31 17:06:59 +02:00
|
|
|
size = I.buffer_sz - I.buffer_len - 1; /* remaining space in I.buffer */
|
2016-11-17 23:41:49 +01:00
|
|
|
written = vsnprintf (I.buffer + I.buffer_len, size, format, ap);
|
2016-11-02 22:59:32 +01:00
|
|
|
if (written >= size) { /* not all bytes were written */
|
2012-02-05 00:33:34 +01:00
|
|
|
palloc (written);
|
2016-12-29 19:20:33 +01:00
|
|
|
va_copy (ap, ap2);
|
|
|
|
va_copy (ap2, ap);
|
|
|
|
written = vsnprintf (I.buffer + I.buffer_len, written, format, ap2);
|
|
|
|
if (written >= size) {
|
|
|
|
palloc (written);
|
|
|
|
goto club;
|
|
|
|
}
|
|
|
|
va_end (ap2);
|
2012-02-05 00:33:34 +01:00
|
|
|
}
|
|
|
|
I.buffer_len += written;
|
2016-06-25 03:09:30 +02:00
|
|
|
} else {
|
|
|
|
r_cons_strcat (format);
|
|
|
|
}
|
2016-12-29 19:20:33 +01:00
|
|
|
va_end (ap2);
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2016-12-24 18:12:04 +01:00
|
|
|
R_API void r_cons_printf(const char *format, ...) {
|
|
|
|
va_list ap;
|
|
|
|
va_start (ap, format);
|
|
|
|
r_cons_printf_list (format, ap);
|
|
|
|
va_end (ap);
|
|
|
|
}
|
|
|
|
|
2011-09-12 03:01:07 +02:00
|
|
|
R_API int r_cons_get_column() {
|
|
|
|
char *line = strrchr (I.buffer, '\n');
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!line) {
|
|
|
|
line = I.buffer;
|
|
|
|
}
|
2011-09-12 03:01:07 +02:00
|
|
|
I.buffer[I.buffer_len] = 0;
|
|
|
|
return r_str_ansi_len (line);
|
|
|
|
}
|
|
|
|
|
2009-03-21 22:59:35 +00:00
|
|
|
/* final entrypoint for adding stuff in the buffer screen */
|
2017-01-29 23:05:02 +01:00
|
|
|
R_API int r_cons_memcat(const char *str, int len) {
|
2016-06-29 12:33:31 +02:00
|
|
|
if (len < 0 || (I.buffer_len + len) < 0) {
|
2017-01-29 23:05:02 +01:00
|
|
|
return -1;
|
2015-03-04 01:27:22 +01:00
|
|
|
}
|
2014-10-30 22:58:51 +01:00
|
|
|
if (I.echo) {
|
|
|
|
write (2, str, len);
|
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
if (str && len > 0 && !I.null) {
|
2016-10-19 02:09:14 +02:00
|
|
|
if (palloc (len + 1)) {
|
|
|
|
memcpy (I.buffer + I.buffer_len, str, len);
|
|
|
|
I.buffer_len += len;
|
|
|
|
I.buffer[I.buffer_len] = 0;
|
|
|
|
}
|
2011-02-23 02:10:28 +01:00
|
|
|
}
|
2016-09-20 00:11:59 +02:00
|
|
|
if (I.flush) {
|
|
|
|
r_cons_flush ();
|
|
|
|
}
|
2016-12-22 00:13:16 +03:00
|
|
|
if (I.break_word && str) {
|
2016-12-17 10:42:15 +01:00
|
|
|
if (r_mem_mem ((const ut8*)str, len, (const ut8*)I.break_word, I.break_word_len)) {
|
|
|
|
I.breaked = true;
|
|
|
|
}
|
|
|
|
}
|
2017-01-29 23:05:02 +01:00
|
|
|
return len;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2011-05-21 14:27:46 +02:00
|
|
|
R_API void r_cons_memset(char ch, int len) {
|
2016-06-29 12:33:31 +02:00
|
|
|
if (!I.null && len > 0) {
|
|
|
|
palloc (len + 1);
|
2017-01-24 11:36:02 +01:00
|
|
|
memset (I.buffer + I.buffer_len, ch, len);
|
2011-05-21 14:27:46 +02:00
|
|
|
I.buffer_len += len;
|
2017-01-24 11:36:02 +01:00
|
|
|
I.buffer[I.buffer_len] = 0;
|
2011-05-21 14:27:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_strcat(const char *str) {
|
2013-07-17 03:51:53 +02:00
|
|
|
int len;
|
2016-06-29 12:33:31 +02:00
|
|
|
if (!str || I.null) {
|
|
|
|
return;
|
|
|
|
}
|
2013-07-17 03:51:53 +02:00
|
|
|
len = strlen (str);
|
2016-06-29 12:33:31 +02:00
|
|
|
if (len > 0) {
|
2010-01-30 14:02:53 +01:00
|
|
|
r_cons_memcat (str, len);
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_newline() {
|
2016-06-29 12:33:31 +02:00
|
|
|
if (!I.null) {
|
2014-01-08 23:44:05 +01:00
|
|
|
r_cons_strcat ("\n");
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2017-03-10 12:38:41 +01:00
|
|
|
// This place is wrong to manage the color reset, can interfire with r2pipe output sending resetchars
|
|
|
|
// and break json output appending extra chars.
|
|
|
|
// this code now is managed into output.c:118 at function r_cons_w32_print
|
|
|
|
// now the console color is reset with each \n (same stuff do it here but in correct place ... i think)
|
|
|
|
//#if __WINDOWS__
|
|
|
|
//r_cons_reset_colors();
|
|
|
|
//#endif
|
2012-09-05 03:25:03 +02:00
|
|
|
//if (I.is_html) r_cons_strcat ("<br />\n");
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2014-09-22 13:45:36 +02:00
|
|
|
/* return the aproximated x,y of cursor before flushing */
|
|
|
|
R_API int r_cons_get_cursor(int *rows) {
|
|
|
|
int i, col = 0;
|
|
|
|
int row = 0;
|
|
|
|
// TODO: we need to handle GOTOXY and CLRSCR ansi escape code too
|
2016-06-29 12:33:31 +02:00
|
|
|
for (i = 0; i < I.buffer_len; i++) {
|
2014-09-22 13:45:36 +02:00
|
|
|
// ignore ansi chars, copypasta from r_str_ansi_len
|
|
|
|
if (I.buffer[i] == 0x1b) {
|
|
|
|
char ch2 = I.buffer[i+1];
|
|
|
|
char *str = I.buffer;
|
|
|
|
if (ch2 == '\\') {
|
|
|
|
i++;
|
|
|
|
} else if (ch2 == ']') {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!strncmp (str + 2 + 5, "rgb:", 4))
|
2014-09-22 13:45:36 +02:00
|
|
|
i += 18;
|
|
|
|
} else if (ch2 == '[') {
|
2016-10-18 23:15:51 +02:00
|
|
|
for (++i; str[i] && str[i] != 'J' && str[i] != 'm' && str[i] != 'H'; i++);
|
2014-09-22 13:45:36 +02:00
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
} else if (I.buffer[i] == '\n') {
|
2014-09-22 13:45:36 +02:00
|
|
|
row++;
|
|
|
|
col = 0;
|
2016-06-29 12:33:31 +02:00
|
|
|
} else {
|
|
|
|
col++;
|
|
|
|
}
|
2014-09-22 13:45:36 +02:00
|
|
|
}
|
2016-06-29 12:33:31 +02:00
|
|
|
if (rows) {
|
2014-09-22 13:45:36 +02:00
|
|
|
*rows = row;
|
2016-06-29 12:33:31 +02:00
|
|
|
}
|
2014-09-22 13:45:36 +02:00
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
2016-06-02 12:45:11 +02:00
|
|
|
R_API bool r_cons_isatty() {
|
|
|
|
#if __UNIX__ || __CYGWIN__
|
|
|
|
struct winsize win = { 0 };
|
|
|
|
const char *tty;
|
|
|
|
struct stat sb;
|
|
|
|
|
2016-09-01 12:06:22 +02:00
|
|
|
if (!isatty (1)) {
|
2016-06-02 12:45:11 +02:00
|
|
|
return false;
|
2016-09-01 12:06:22 +02:00
|
|
|
}
|
|
|
|
if (ioctl (1, TIOCGWINSZ, &win)) {
|
2016-06-02 12:45:11 +02:00
|
|
|
return false;
|
2016-09-01 12:06:22 +02:00
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!win.ws_col || !win.ws_row) {
|
2016-06-02 12:45:11 +02:00
|
|
|
return false;
|
2016-09-01 12:06:22 +02:00
|
|
|
}
|
2016-06-02 12:45:11 +02:00
|
|
|
tty = ttyname (1);
|
2016-09-01 12:06:22 +02:00
|
|
|
if (!tty) {
|
2016-06-02 12:45:11 +02:00
|
|
|
return false;
|
2016-09-01 12:06:22 +02:00
|
|
|
}
|
|
|
|
if (stat (tty, &sb) || !S_ISCHR (sb.st_mode)) {
|
2016-06-02 12:45:11 +02:00
|
|
|
return false;
|
2016-09-01 12:06:22 +02:00
|
|
|
}
|
2016-06-02 12:45:11 +02:00
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
/* non-UNIX do not have ttys */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-24 03:17:43 +02:00
|
|
|
// XXX: if this function returns <0 in rows or cols expect MAYHEM
|
2010-01-30 14:02:53 +01:00
|
|
|
R_API int r_cons_get_size(int *rows) {
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2015-11-01 05:10:49 +01:00
|
|
|
char buffer[1024];
|
2015-01-12 16:05:33 +01:00
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
|
2015-11-01 05:10:49 +01:00
|
|
|
I.columns = (csbi.srWindow.Right - csbi.srWindow.Left) - 1;
|
2015-01-12 16:31:12 +01:00
|
|
|
I.rows = csbi.srWindow.Bottom - csbi.srWindow.Top; // last row empty
|
2015-01-12 16:05:33 +01:00
|
|
|
#elif EMSCRIPTEN
|
2013-09-07 01:35:11 +02:00
|
|
|
I.columns = 80;
|
|
|
|
I.rows = 23;
|
2015-01-26 20:01:48 +03:00
|
|
|
#elif __UNIX__ || __CYGWIN__
|
2015-09-01 22:10:28 +02:00
|
|
|
struct winsize win = { 0 };
|
2016-10-18 23:15:51 +02:00
|
|
|
if (isatty (0) && !ioctl (0, TIOCGWINSZ, &win)) {
|
|
|
|
if ((!win.ws_col) || (!win.ws_row)) {
|
2016-06-02 12:45:11 +02:00
|
|
|
const char *tty = ttyname (1);
|
2016-09-01 17:12:06 +02:00
|
|
|
int fd = open (tty? tty: "/dev/tty", O_RDONLY);
|
2013-11-23 01:49:21 +01:00
|
|
|
if (fd != -1) {
|
2015-09-01 22:10:28 +02:00
|
|
|
int ret = ioctl (fd, TIOCGWINSZ, &win);
|
2016-10-18 23:15:51 +02:00
|
|
|
if (ret || !win.ws_col || !win.ws_row) {
|
2015-09-01 22:10:28 +02:00
|
|
|
win.ws_col = 80;
|
|
|
|
win.ws_row = 23;
|
2013-11-23 01:49:21 +01:00
|
|
|
}
|
|
|
|
close (fd);
|
|
|
|
}
|
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
I.columns = win.ws_col;
|
2015-06-04 01:30:33 +02:00
|
|
|
I.rows = win.ws_row;
|
2011-01-23 13:12:16 +01:00
|
|
|
} else {
|
|
|
|
I.columns = 80;
|
|
|
|
I.rows = 23;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
#else
|
2011-12-02 14:32:04 +01:00
|
|
|
char *str = r_sys_getenv ("COLUMNS");
|
2016-06-29 12:33:31 +02:00
|
|
|
if (str) {
|
2010-01-30 14:02:53 +01:00
|
|
|
I.columns = atoi (str);
|
2011-01-23 17:48:31 +01:00
|
|
|
I.rows = 23; // XXX. windows must get console size
|
2011-08-28 00:01:03 +02:00
|
|
|
free (str);
|
2011-01-23 17:48:31 +01:00
|
|
|
} else {
|
|
|
|
I.columns = 80;
|
|
|
|
I.rows = 23;
|
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
#endif
|
2014-09-24 03:17:43 +02:00
|
|
|
#if SIMULATE_ADB_SHELL
|
|
|
|
I.rows = 0;
|
|
|
|
I.columns = 0;
|
|
|
|
#endif
|
|
|
|
#if SIMULATE_MAYHEM
|
|
|
|
// expect tons of crashes
|
|
|
|
I.rows = -1;
|
|
|
|
I.columns = -1;
|
|
|
|
#endif
|
2016-06-02 12:45:11 +02:00
|
|
|
if (I.rows < 0) {
|
2014-09-24 03:17:43 +02:00
|
|
|
I.rows = 0;
|
2016-06-02 12:45:11 +02:00
|
|
|
}
|
|
|
|
if (I.columns < 0) {
|
2014-09-24 03:17:43 +02:00
|
|
|
I.columns = 0;
|
2016-06-02 12:45:11 +02:00
|
|
|
}
|
2016-10-18 23:15:51 +02:00
|
|
|
if (I.force_columns) {
|
|
|
|
I.columns = I.force_columns;
|
|
|
|
}
|
|
|
|
if (I.force_rows) {
|
|
|
|
I.rows = I.force_rows;
|
|
|
|
}
|
|
|
|
if (I.fix_columns) {
|
|
|
|
I.columns += I.fix_columns;
|
|
|
|
}
|
|
|
|
if (I.fix_rows) {
|
|
|
|
I.rows += I.fix_rows;
|
|
|
|
}
|
|
|
|
if (rows) {
|
2014-09-24 03:17:43 +02:00
|
|
|
*rows = I.rows;
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2014-09-14 01:07:15 +02:00
|
|
|
I.rows = R_MAX (0, I.rows);
|
|
|
|
return R_MAX (0, I.columns);
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2011-12-02 01:58:34 +01:00
|
|
|
R_API void r_cons_show_cursor (int cursor) {
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
2011-12-02 01:58:34 +01:00
|
|
|
// TODO
|
|
|
|
#else
|
2016-09-01 17:12:06 +02:00
|
|
|
if (cursor) {
|
|
|
|
write (1, "\x1b[?25h", 6);
|
|
|
|
} else {
|
|
|
|
write (1, "\x1b[?25l", 6);
|
|
|
|
}
|
2011-12-02 01:58:34 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-02-05 22:08:46 +01:00
|
|
|
/**
|
|
|
|
* void r_cons_set_raw( [0,1] )
|
|
|
|
*
|
|
|
|
* Change canonicality of the terminal
|
|
|
|
*
|
|
|
|
* For optimization reasons, there's no initialization flag, so you need to
|
|
|
|
* ensure that the make the first call to r_cons_set_raw() with '1' and
|
|
|
|
* the next calls ^=1, so: 1, 0, 1, 0, 1, ...
|
|
|
|
*
|
|
|
|
* If you doesn't use this order you'll probably loss your terminal properties.
|
|
|
|
*
|
|
|
|
*/
|
2012-02-01 02:22:43 +01:00
|
|
|
static int oldraw = -1;
|
2010-02-28 14:49:26 +01:00
|
|
|
R_API void r_cons_set_raw(int is_raw) {
|
2016-09-01 17:12:06 +02:00
|
|
|
if (oldraw != -1) {
|
|
|
|
if (is_raw == oldraw) {
|
2012-02-01 02:22:43 +01:00
|
|
|
return;
|
2016-09-01 17:12:06 +02:00
|
|
|
}
|
|
|
|
}
|
2012-11-12 17:06:28 +01:00
|
|
|
#if EMSCRIPTEN
|
|
|
|
/* do nothing here */
|
2015-01-26 19:55:12 +03:00
|
|
|
#elif __UNIX__ || __CYGWIN__
|
2015-04-09 16:43:20 +02:00
|
|
|
// enforce echo off
|
|
|
|
I.term_raw.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
2016-09-01 17:12:06 +02:00
|
|
|
if (is_raw) {
|
|
|
|
tcsetattr (0, TCSANOW, &I.term_raw);
|
|
|
|
} else {
|
|
|
|
tcsetattr (0, TCSANOW, &I.term_buf);
|
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
#elif __WINDOWS__
|
2016-09-01 17:12:06 +02:00
|
|
|
if (is_raw) {
|
|
|
|
SetConsoleMode (h, (DWORD)I.term_raw);
|
|
|
|
} else {
|
|
|
|
SetConsoleMode (h, (DWORD)I.term_buf);
|
|
|
|
}
|
2010-02-28 14:49:26 +01:00
|
|
|
#else
|
|
|
|
#warning No raw console supported for this platform
|
2009-02-05 22:08:46 +01:00
|
|
|
#endif
|
2010-01-30 14:02:53 +01:00
|
|
|
fflush (stdout);
|
2012-02-01 02:22:43 +01:00
|
|
|
oldraw = is_raw;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
2011-05-11 16:48:20 +02:00
|
|
|
|
|
|
|
R_API void r_cons_invert(int set, int color) {
|
2013-01-22 05:06:12 +01:00
|
|
|
r_cons_strcat (R_CONS_INVERT (set, color));
|
2011-05-11 16:48:20 +02:00
|
|
|
}
|
2011-05-16 01:47:01 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Enable/Disable scrolling in terminal:
|
|
|
|
FMI: cd libr/cons/t ; make ti ; ./ti
|
|
|
|
smcup: disable terminal scrolling (fullscreen mode)
|
|
|
|
rmcup: enable terminal scrolling (normal mode)
|
|
|
|
*/
|
|
|
|
R_API void r_cons_set_cup(int enable) {
|
2015-01-26 19:55:12 +03:00
|
|
|
#if __UNIX__ || __CYGWIN__
|
2011-05-16 01:47:01 +02:00
|
|
|
if (enable) {
|
2014-09-04 22:57:10 +02:00
|
|
|
const char *code =
|
|
|
|
"\x1b[?1049h" // xterm
|
|
|
|
"\x1b" "7\x1b[?47h"; // xterm-color
|
|
|
|
write (2, code, strlen (code));
|
2011-05-16 01:47:01 +02:00
|
|
|
} else {
|
2014-09-04 22:57:10 +02:00
|
|
|
const char *code =
|
|
|
|
"\x1b[?1049l" // xterm
|
|
|
|
"\x1b[?47l""\x1b""8"; // xterm-color
|
|
|
|
write (2, code, strlen (code));
|
2011-05-16 01:47:01 +02:00
|
|
|
}
|
|
|
|
fflush (stdout);
|
2015-11-01 05:10:49 +01:00
|
|
|
#elif __WINDOWS__ && !__CYGWIN__
|
|
|
|
if (I.ansicon) {
|
|
|
|
if (enable) {
|
|
|
|
const char *code =
|
|
|
|
"\x1b[?1049h" // xterm
|
|
|
|
"\x1b" "7\x1b[?47h"; // xterm-color
|
|
|
|
write (2, code, strlen (code));
|
|
|
|
} else {
|
|
|
|
const char *code =
|
|
|
|
"\x1b[?1049l" // xterm
|
|
|
|
"\x1b[?47l""\x1b""8"; // xterm-color
|
|
|
|
write (2, code, strlen (code));
|
|
|
|
}
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
2011-05-16 01:47:01 +02:00
|
|
|
#endif
|
2015-11-01 05:10:49 +01:00
|
|
|
/* not supported ? */
|
2011-05-16 01:47:01 +02:00
|
|
|
}
|
2011-05-21 14:27:46 +02:00
|
|
|
|
|
|
|
R_API void r_cons_column(int c) {
|
2011-12-05 15:35:37 +01:00
|
|
|
char *b = malloc (I.buffer_len+1);
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!b) {
|
|
|
|
return;
|
|
|
|
}
|
2011-05-21 14:27:46 +02:00
|
|
|
memcpy (b, I.buffer, I.buffer_len);
|
2011-07-02 05:55:09 +02:00
|
|
|
b[I.buffer_len] = 0;
|
2011-05-21 14:27:46 +02:00
|
|
|
r_cons_reset ();
|
|
|
|
// align current buffer N chars right
|
2011-05-21 15:45:43 +02:00
|
|
|
r_cons_strcat_justify (b, c, 0);
|
2011-05-21 14:27:46 +02:00
|
|
|
r_cons_gotoxy (0, 0);
|
2013-01-25 02:03:57 +01:00
|
|
|
free(b);
|
2011-05-21 14:27:46 +02:00
|
|
|
}
|
2012-02-05 01:25:40 +01:00
|
|
|
|
|
|
|
static int lasti = 0; /* last interactive mode */
|
|
|
|
|
|
|
|
R_API void r_cons_set_interactive(int x) {
|
|
|
|
lasti = r_cons_singleton ()->is_interactive;
|
|
|
|
r_cons_singleton ()->is_interactive = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_set_last_interactive() {
|
|
|
|
r_cons_singleton ()->is_interactive = lasti;
|
|
|
|
}
|
2014-02-24 00:38:53 +01:00
|
|
|
|
|
|
|
R_API void r_cons_set_title(const char *str) {
|
|
|
|
r_cons_printf ("\x1b]0;%s\007", str);
|
|
|
|
}
|
2014-08-17 01:41:53 +02:00
|
|
|
|
|
|
|
R_API void r_cons_zero() {
|
2016-09-01 17:12:06 +02:00
|
|
|
if (I.line) {
|
|
|
|
I.line->zerosep = true;
|
|
|
|
}
|
2014-08-17 17:23:26 +02:00
|
|
|
write (1, "", 1);
|
2014-08-17 01:41:53 +02:00
|
|
|
}
|
2014-09-27 03:48:54 +02:00
|
|
|
|
|
|
|
R_API void r_cons_highlight (const char *word) {
|
2015-05-27 18:24:35 +03:00
|
|
|
int l, *cpos;
|
2016-09-01 17:12:06 +02:00
|
|
|
char *rword, *res, *clean;
|
|
|
|
char *inv[2] = {
|
|
|
|
R_CONS_INVERT (true, true),
|
|
|
|
R_CONS_INVERT (false, true)
|
|
|
|
};
|
|
|
|
int linv[2] = {
|
|
|
|
strlen (inv[0]),
|
|
|
|
strlen (inv[1])
|
|
|
|
};
|
2015-05-27 18:24:35 +03:00
|
|
|
|
2015-06-01 22:17:41 +03:00
|
|
|
if (word && *word && I.buffer) {
|
2015-05-21 13:58:27 +03:00
|
|
|
int word_len = strlen (word);
|
2015-05-27 18:24:35 +03:00
|
|
|
char *orig;
|
|
|
|
clean = I.buffer;
|
|
|
|
l = r_str_ansi_filter (clean, &orig, &cpos, 0);
|
|
|
|
I.buffer = orig;
|
2014-09-28 03:53:59 +02:00
|
|
|
if (I.highlight) {
|
|
|
|
if (strcmp (word, I.highlight)) {
|
|
|
|
free (I.highlight);
|
|
|
|
I.highlight = strdup (word);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
I.highlight = strdup (word);
|
|
|
|
}
|
2015-05-21 13:58:27 +03:00
|
|
|
rword = malloc (word_len + linv[0] + linv[1] + 1);
|
2016-05-24 09:01:35 +03:00
|
|
|
if (!rword) {
|
|
|
|
free (cpos);
|
|
|
|
return;
|
|
|
|
}
|
2015-05-21 13:58:27 +03:00
|
|
|
strcpy (rword, inv[0]);
|
|
|
|
strcpy (rword + linv[0], word);
|
|
|
|
strcpy (rword + linv[0] + word_len, inv[1]);
|
2015-05-27 18:24:35 +03:00
|
|
|
res = r_str_replace_thunked (I.buffer, clean, cpos,
|
|
|
|
l, word, rword, 1);
|
2014-09-27 03:48:54 +02:00
|
|
|
if (res) {
|
|
|
|
I.buffer = res;
|
2014-09-27 03:51:04 +02:00
|
|
|
I.buffer_len = I.buffer_sz = strlen (res);
|
2014-09-27 03:48:54 +02:00
|
|
|
}
|
2015-01-16 00:56:54 +01:00
|
|
|
free (rword);
|
2015-05-27 18:24:35 +03:00
|
|
|
free (clean);
|
|
|
|
free (cpos);
|
|
|
|
/* don't free orig - it's assigned
|
|
|
|
* to I.buffer and possibly realloc'd */
|
2014-09-27 03:48:54 +02:00
|
|
|
} else {
|
2014-09-28 03:53:59 +02:00
|
|
|
free (I.highlight);
|
2014-09-27 03:48:54 +02:00
|
|
|
I.highlight = NULL;
|
|
|
|
}
|
|
|
|
}
|
2014-11-13 03:36:48 +01:00
|
|
|
|
2017-01-23 22:42:27 +01:00
|
|
|
R_API char *r_cons_lastline (int *len) {
|
|
|
|
char *b = I.buffer + I.buffer_len;
|
|
|
|
while (b > I.buffer) {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (*b == '\n') {
|
2014-11-13 03:36:48 +01:00
|
|
|
b++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
b--;
|
|
|
|
}
|
2017-01-23 22:42:27 +01:00
|
|
|
if (len) {
|
|
|
|
int delta = b - I.buffer;
|
|
|
|
*len = I.buffer_len - delta;
|
|
|
|
}
|
2014-11-13 03:36:48 +01:00
|
|
|
return b;
|
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
|
|
|
|
/* swap color from foreground to background, returned value must be freed */
|
|
|
|
R_API char *r_cons_swap_ground(const char *col) {
|
|
|
|
if (!strncmp (col, "\x1b[48;5;", 7)) {
|
|
|
|
/* rgb background */
|
|
|
|
return r_str_newf ("\x1b[38;5;%s", col+7);
|
|
|
|
} else if (!strncmp (col, "\x1b[38;5;", 7)) {
|
|
|
|
/* rgb foreground */
|
|
|
|
return r_str_newf ("\x1b[48;5;%s", col+7);
|
|
|
|
} else if (!strncmp (col, "\x1b[4", 3)) {
|
|
|
|
/* is background */
|
|
|
|
return r_str_newf ("\x1b[3%s", col+3);
|
|
|
|
} else if (!strncmp (col, "\x1b[3", 3)) {
|
|
|
|
/* is foreground */
|
|
|
|
return r_str_newf ("\x1b[4%s", col+3);
|
|
|
|
}
|
|
|
|
return strdup (col);
|
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
|
|
|
|
R_API bool r_cons_drop (int n) {
|
|
|
|
if (n > I.buffer_len) {
|
|
|
|
I.buffer_len = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
I.buffer_len -= n;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_chop () {
|
2016-10-18 23:15:51 +02:00
|
|
|
while (I.buffer_len > 0) {
|
2016-10-21 01:24:40 +02:00
|
|
|
char ch = I.buffer[I.buffer_len - 1];
|
2016-10-18 23:15:51 +02:00
|
|
|
if (ch != '\n' && !IS_WHITESPACE (ch)) {
|
2015-10-30 03:07:22 +01:00
|
|
|
break;
|
2016-10-18 23:15:51 +02:00
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
I.buffer_len--;
|
|
|
|
}
|
|
|
|
}
|
2016-05-10 22:15:24 +02:00
|
|
|
|
|
|
|
R_API void r_cons_bind(RConsBind *bind) {
|
2016-10-18 23:15:51 +02:00
|
|
|
if (!bind) {
|
|
|
|
return;
|
|
|
|
}
|
2016-05-10 22:15:24 +02:00
|
|
|
bind->get_size = r_cons_get_size;
|
|
|
|
bind->get_cursor = r_cons_get_cursor;
|
|
|
|
}
|
2016-10-21 01:24:40 +02:00
|
|
|
|
|
|
|
R_API const char* r_cons_get_rune(const ut8 ch) {
|
|
|
|
if (ch >= RUNECODE_MIN && ch < RUNECODE_MAX) {
|
|
|
|
switch (ch) {
|
|
|
|
case RUNECODE_LINE_HORIZ: return RUNE_LINE_HORIZ;
|
|
|
|
case RUNECODE_LINE_VERT: return RUNE_LINE_VERT;
|
|
|
|
case RUNECODE_LINE_CROSS: return RUNE_LINE_CROSS;
|
|
|
|
case RUNECODE_CORNER_TL: return RUNE_CORNER_TL;
|
|
|
|
case RUNECODE_CORNER_TR: return RUNE_CORNER_TR;
|
|
|
|
case RUNECODE_CORNER_BR: return RUNE_CORNER_BR;
|
|
|
|
case RUNECODE_CORNER_BL: return RUNE_CORNER_BL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-12-17 10:42:15 +01:00
|
|
|
R_API void r_cons_breakword(const char *s) {
|
|
|
|
free (I.break_word);
|
|
|
|
if (s) {
|
|
|
|
I.break_word = strdup (s);
|
|
|
|
I.break_word_len = strlen (s);
|
|
|
|
} else {
|
|
|
|
I.break_word = NULL;
|
|
|
|
I.break_word_len = 0;
|
|
|
|
}
|
|
|
|
}
|