diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-15 14:00:41 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-15 14:00:41 +0200 |
commit | f3fa86525850620d31e48a742a25fd4965b1dba2 (patch) | |
tree | 0febe63460aef1e01456e2e4d56b33bdcccfdab0 /miscutils | |
parent | 9a4100cf53f75356854ce752374babf8135c3f42 (diff) | |
download | busybox-f3fa86525850620d31e48a742a25fd4965b1dba2.tar.gz |
hexedit: fixes to "goto address" code
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/hexedit.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 7e74e1f24..8334181c7 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -31,6 +31,7 @@ struct globals { int fd; unsigned height; unsigned row; + unsigned pagesize; uint8_t *baseaddr; uint8_t *current_byte; uint8_t *eof_byte; @@ -45,8 +46,17 @@ struct globals { SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) -/* Hopefully there aren't arches with PAGE_SIZE > 64k */ -#define G_mapsize (64*1024) +//TODO: move to libbb +#if defined(__x86_64__) || defined(i386) +# define G_pagesize 4096 +# define INIT_PAGESIZE() ((void)0) +#else +# define G_pagesize (G.pagesize) +# define INIT_PAGESIZE() ((void)(G.pagesize = getpagesize())) +#endif + +/* hopefully there aren't arches with PAGE_SIZE > 64k */ +#define G_mapsize (64*1024) /* "12ef5670 (xx )*16 _1_3_5_7_9abcdef\n"NUL */ #define LINEBUF_SIZE (8 + 1 + 3*16 + 16 + 1 + 1 /*paranoia:*/ + 13) @@ -86,7 +96,7 @@ static int format_line(char *hex, uint8_t *data, off_t offset) #endif hex += ofs_pos; - text = hex + 16*3; + text = hex + 16 * 3; end1 = data + 15; if ((G.size - offset) > 0) { end = end1; @@ -114,28 +124,36 @@ static int format_line(char *hex, uint8_t *data, off_t offset) return ofs_pos; } -static void redraw(void) +static void redraw(unsigned cursor) { uint8_t *data; off_t offset; unsigned i, pos; printf(HOME CLEAR); - data = G.baseaddr; - offset = G.offset; + + /* if cursor is past end of screen, how many lines to move down? */ + i = (cursor / 16) - G.height + 1; + if ((int)i < 0) + i = 0; + + data = G.baseaddr + i * 16; + offset = G.offset + i * 16; + cursor -= i * 16; pos = i = 0; while (i < G.height) { char buf[LINEBUF_SIZE]; pos = format_line(buf, data, offset); printf( - "\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */ + "\r\n%s" + (!i) * 2, /* print \r\n only on 2nd line and later */ buf ); data += 16; offset += 16; i++; } - printf(ESC"[1;%uH", pos + 1); /* position on 1st hex byte in first line */ + + printf(ESC"[%u;%uH", 1 + cursor / 16, 1 + pos + (cursor & 0xf) * 3); } static void redraw_cur_line(void) @@ -195,7 +213,7 @@ static int move_mapping_further(void) if ((G.size - G.offset) < G_mapsize) return 0; /* can't move mapping even further, it's at the end already */ - pagesize = getpagesize(); /* constant on most arches */ + pagesize = G_pagesize; /* constant on most arches */ pos = G.current_byte - G.baseaddr; if (pos >= pagesize) { /* move offset up until current position is in 1st page */ @@ -219,7 +237,7 @@ static int move_mapping_lower(void) if (G.offset == 0) return 0; /* we are at 0 already */ - pagesize = getpagesize(); /* constant on most arches */ + pagesize = G_pagesize; /* constant on most arches */ pos = G.current_byte - G.baseaddr; /* move offset down until current position is in last page */ @@ -243,6 +261,7 @@ int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int hexedit_main(int argc UNUSED_PARAM, char **argv) { INIT_G(); + INIT_PAGESIZE(); get_terminal_width_height(-1, NULL, &G.height); if (1) { @@ -263,7 +282,7 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) bb_signals(BB_FATAL_SIGS, sig_catcher); remap(0); - redraw(); + redraw(0); //TODO: //Home/End: start/end of line; '<'/'>': start/end of file //Backspace: undo @@ -411,26 +430,27 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) { 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) { + 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; + pgmask = G_pagesize - 1; cnt = t & pgmask; t = t & ~(off_t)pgmask; if (t < 0) cnt = t = 0; + if (t != 0 && cnt < 0x1ff) { + /* very close to end of page, possibly to EOF */ + /* move one page lower */ + t -= G_pagesize; + cnt += G_pagesize; + } G.offset = t; - remap(cnt & 0xf); - redraw(); - if (cnt & 0xf) - printf(ESC"[%uC", (cnt & 0xf) * 3); /* cursor right 3*i */ - cnt >>= 4; - if (cnt) - goto k_down; + remap(cnt); + redraw(cnt); break; } /* EOF/error on input: fall through to exiting */ |