summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2017-09-14 10:51:12 +0200
committerDenys Vlasenko2017-09-14 10:51:12 +0200
commitd54f58d487bfa5d6646d9a728d503351691081bf (patch)
tree7e8b76263c6a70e3b26defc49677bce5227e3784
parent363fb5ec4091120003b3f204996e7ff0aa354e58 (diff)
downloadbusybox-d54f58d487bfa5d6646d9a728d503351691081bf.zip
busybox-d54f58d487bfa5d6646d9a728d503351691081bf.tar.gz
hexedit: implement "[enter] goto offset" key
This is a must if you need to edit sector 123456789999 on your /dev/disk. text data bss dec hex filename 922745 481 6832 930058 e310a busybox_old 923023 481 6832 930336 e3220 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/hexedit.c79
-rw-r--r--miscutils/less.c4
2 files changed, 56 insertions, 27 deletions
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c
index b8627e8..eaf4ba5 100644
--- a/miscutils/hexedit.c
+++ b/miscutils/hexedit.c
@@ -17,7 +17,8 @@
#define ESC "\033"
#define HOME ESC"[H"
-#define CLEAR ESC"[H"ESC"[J"
+#define CLEAR ESC"[J"
+#define CLEAR_TILL_EOL ESC"[K"
#define SET_ALT_SCR ESC"[?1049h"
#define POP_ALT_SCR ESC"[?1049l"
@@ -30,7 +31,7 @@ struct globals {
int fd;
unsigned height;
unsigned row;
- uint8_t *addr;
+ uint8_t *baseaddr;
uint8_t *current_byte;
uint8_t *eof_byte;
off_t size;
@@ -117,14 +118,15 @@ static void redraw(void)
{
uint8_t *data;
off_t offset;
- unsigned i;
+ unsigned i, pos;
- data = G.addr;
- offset = 0;
- i = 0;
+ printf(HOME CLEAR);
+ data = G.baseaddr;
+ offset = G.offset;
+ pos = i = 0;
while (i < G.height) {
char buf[LINEBUF_SIZE];
- format_line(buf, data, offset);
+ pos = format_line(buf, data, offset);
printf(
"\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */
buf
@@ -133,6 +135,7 @@ static void redraw(void)
offset += 16;
i++;
}
+ printf(ESC"[1;%uH", pos + 1); /* position on 1st hex byte in first line */
}
static void redraw_cur_line(void)
@@ -144,7 +147,7 @@ static void redraw_cur_line(void)
column = (0xf & (uintptr_t)G.current_byte);
data = G.current_byte - column;
- offset = G.offset + (data - G.addr);
+ offset = G.offset + (data - G.baseaddr);
column = column*3 + G.half;
column += format_line(buf, data, offset);
@@ -158,28 +161,28 @@ static void redraw_cur_line(void)
static void remap(unsigned cur_pos)
{
- if (G.addr)
- munmap(G.addr, G_mapsize);
+ if (G.baseaddr)
+ munmap(G.baseaddr, G_mapsize);
- G.addr = mmap(NULL,
+ G.baseaddr = mmap(NULL,
G_mapsize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
G.fd,
G.offset
);
- if (G.addr == MAP_FAILED) {
+ if (G.baseaddr == MAP_FAILED) {
restore_term();
bb_perror_msg_and_die("mmap");
}
- G.current_byte = G.addr + cur_pos;
+ G.current_byte = G.baseaddr + cur_pos;
- G.eof_byte = G.addr + G_mapsize;
+ G.eof_byte = G.baseaddr + G_mapsize;
if ((G.size - G.offset) < G_mapsize) {
/* mapping covers tail of the file */
/* we do have a mapped byte which is past eof */
- G.eof_byte = G.addr + (G.size - G.offset);
+ G.eof_byte = G.baseaddr + (G.size - G.offset);
}
}
static void move_mapping_further(void)
@@ -191,7 +194,7 @@ static void move_mapping_further(void)
return; /* can't move mapping even further, it's at the end already */
pagesize = getpagesize(); /* constant on most arches */
- pos = G.current_byte - G.addr;
+ pos = G.current_byte - G.baseaddr;
if (pos >= pagesize) {
/* move offset up until current position is in 1st page */
do {
@@ -214,7 +217,7 @@ static void move_mapping_lower(void)
return; /* we are at 0 already */
pagesize = getpagesize(); /* constant on most arches */
- pos = G.current_byte - G.addr;
+ pos = G.current_byte - G.baseaddr;
/* move offset down until current position is in last page */
pos += pagesize;
@@ -252,18 +255,15 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
G.size = xlseek(G.fd, 0, SEEK_END);
/* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */
+ printf(SET_ALT_SCR);
set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL);
bb_signals(BB_FATAL_SIGS, sig_catcher);
remap(0);
-
- printf(SET_ALT_SCR);
redraw();
- printf(ESC"[1;10H"); /* position on 1st hex byte in first line */
//TODO: //Home/End: start/end of line; '<'/'>': start/end of file
//Backspace: undo
- //Enter: goto specified position
//Ctrl-L: redraw
//Ctrl-Z: suspend
//'/', Ctrl-S: search
@@ -367,9 +367,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
}
if ((0xf & (uintptr_t)G.current_byte) == 0) {
/* leftmost pos, wrap to prev line */
- if (G.current_byte == G.addr) {
+ if (G.current_byte == G.baseaddr) {
move_mapping_lower();
- if (G.current_byte == G.addr)
+ if (G.current_byte == G.baseaddr)
break; /* first line, don't do anything */
}
G.half = 1;
@@ -385,9 +385,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
cnt = G.height;
case KEYCODE_UP:
k_up:
- if ((G.current_byte - G.addr) < 16) {
+ if ((G.current_byte - G.baseaddr) < 16) {
move_mapping_lower();
- if ((G.current_byte - G.addr) < 16)
+ if ((G.current_byte - G.baseaddr) < 16)
break;
}
G.current_byte -= 16;
@@ -403,6 +403,35 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
if (--cnt)
goto k_up;
break;
+
+ case '\n':
+ case '\r':
+ /* [Enter]: goto specified position */
+ {
+ char buf[sizeof(G.offset)*3 + 4];
+ printf(ESC"[999;1H" CLEAR_TILL_EOL); /* go to last line */
+ if (read_line_input(NULL, "Go to (dec,0Xhex,0oct): ", buf, sizeof(buf)) >= 0) {
+ off_t t;
+ unsigned pgmask;
+
+ t = bb_strtoull(buf, NULL, 0);
+ if (t >= G.size)
+ t = G.size - 1;
+ pgmask = getpagesize() - 1;
+ cnt = t & pgmask;
+ t = t & ~(off_t)pgmask;
+ if (t < 0)
+ cnt = t = 0;
+ G.offset = t;
+ remap(0);
+ redraw();
+ cnt /= 16;
+ if (cnt)
+ goto k_down;
+ break;
+ }
+ /* EOF/error on input: fall through to exiting */
+ }
case CTRL('X'):
restore_term();
return EXIT_SUCCESS;
diff --git a/miscutils/less.c b/miscutils/less.c
index f869a9e..d524b6c 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -281,9 +281,9 @@ static void set_tty_cooked(void)
/* Move the cursor to a position (x,y), where (0,0) is the
top-left corner of the console */
-static void move_cursor(int line, int row)
+static void move_cursor(int line, int col)
{
- printf(ESC"[%u;%uH", line, row);
+ printf(ESC"[%u;%uH", line, col);
}
static void clear_line(void)