diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-14 10:51:12 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-14 10:51:12 +0200 |
commit | d54f58d487bfa5d6646d9a728d503351691081bf (patch) | |
tree | 7e8b76263c6a70e3b26defc49677bce5227e3784 | |
parent | 363fb5ec4091120003b3f204996e7ff0aa354e58 (diff) | |
download | busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.tar.gz busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.tar.bz2 busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.zip |
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.c | 79 | ||||
-rw-r--r-- | miscutils/less.c | 4 |
2 files changed, 56 insertions, 27 deletions
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index b8627e826..eaf4ba57b 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c | |||
@@ -17,7 +17,8 @@ | |||
17 | 17 | ||
18 | #define ESC "\033" | 18 | #define ESC "\033" |
19 | #define HOME ESC"[H" | 19 | #define HOME ESC"[H" |
20 | #define CLEAR ESC"[H"ESC"[J" | 20 | #define CLEAR ESC"[J" |
21 | #define CLEAR_TILL_EOL ESC"[K" | ||
21 | #define SET_ALT_SCR ESC"[?1049h" | 22 | #define SET_ALT_SCR ESC"[?1049h" |
22 | #define POP_ALT_SCR ESC"[?1049l" | 23 | #define POP_ALT_SCR ESC"[?1049l" |
23 | 24 | ||
@@ -30,7 +31,7 @@ struct globals { | |||
30 | int fd; | 31 | int fd; |
31 | unsigned height; | 32 | unsigned height; |
32 | unsigned row; | 33 | unsigned row; |
33 | uint8_t *addr; | 34 | uint8_t *baseaddr; |
34 | uint8_t *current_byte; | 35 | uint8_t *current_byte; |
35 | uint8_t *eof_byte; | 36 | uint8_t *eof_byte; |
36 | off_t size; | 37 | off_t size; |
@@ -117,14 +118,15 @@ static void redraw(void) | |||
117 | { | 118 | { |
118 | uint8_t *data; | 119 | uint8_t *data; |
119 | off_t offset; | 120 | off_t offset; |
120 | unsigned i; | 121 | unsigned i, pos; |
121 | 122 | ||
122 | data = G.addr; | 123 | printf(HOME CLEAR); |
123 | offset = 0; | 124 | data = G.baseaddr; |
124 | i = 0; | 125 | offset = G.offset; |
126 | pos = i = 0; | ||
125 | while (i < G.height) { | 127 | while (i < G.height) { |
126 | char buf[LINEBUF_SIZE]; | 128 | char buf[LINEBUF_SIZE]; |
127 | format_line(buf, data, offset); | 129 | pos = format_line(buf, data, offset); |
128 | printf( | 130 | printf( |
129 | "\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */ | 131 | "\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */ |
130 | buf | 132 | buf |
@@ -133,6 +135,7 @@ static void redraw(void) | |||
133 | offset += 16; | 135 | offset += 16; |
134 | i++; | 136 | i++; |
135 | } | 137 | } |
138 | printf(ESC"[1;%uH", pos + 1); /* position on 1st hex byte in first line */ | ||
136 | } | 139 | } |
137 | 140 | ||
138 | static void redraw_cur_line(void) | 141 | static void redraw_cur_line(void) |
@@ -144,7 +147,7 @@ static void redraw_cur_line(void) | |||
144 | 147 | ||
145 | column = (0xf & (uintptr_t)G.current_byte); | 148 | column = (0xf & (uintptr_t)G.current_byte); |
146 | data = G.current_byte - column; | 149 | data = G.current_byte - column; |
147 | offset = G.offset + (data - G.addr); | 150 | offset = G.offset + (data - G.baseaddr); |
148 | 151 | ||
149 | column = column*3 + G.half; | 152 | column = column*3 + G.half; |
150 | column += format_line(buf, data, offset); | 153 | column += format_line(buf, data, offset); |
@@ -158,28 +161,28 @@ static void redraw_cur_line(void) | |||
158 | 161 | ||
159 | static void remap(unsigned cur_pos) | 162 | static void remap(unsigned cur_pos) |
160 | { | 163 | { |
161 | if (G.addr) | 164 | if (G.baseaddr) |
162 | munmap(G.addr, G_mapsize); | 165 | munmap(G.baseaddr, G_mapsize); |
163 | 166 | ||
164 | G.addr = mmap(NULL, | 167 | G.baseaddr = mmap(NULL, |
165 | G_mapsize, | 168 | G_mapsize, |
166 | PROT_READ | PROT_WRITE, | 169 | PROT_READ | PROT_WRITE, |
167 | MAP_SHARED, | 170 | MAP_SHARED, |
168 | G.fd, | 171 | G.fd, |
169 | G.offset | 172 | G.offset |
170 | ); | 173 | ); |
171 | if (G.addr == MAP_FAILED) { | 174 | if (G.baseaddr == MAP_FAILED) { |
172 | restore_term(); | 175 | restore_term(); |
173 | bb_perror_msg_and_die("mmap"); | 176 | bb_perror_msg_and_die("mmap"); |
174 | } | 177 | } |
175 | 178 | ||
176 | G.current_byte = G.addr + cur_pos; | 179 | G.current_byte = G.baseaddr + cur_pos; |
177 | 180 | ||
178 | G.eof_byte = G.addr + G_mapsize; | 181 | G.eof_byte = G.baseaddr + G_mapsize; |
179 | if ((G.size - G.offset) < G_mapsize) { | 182 | if ((G.size - G.offset) < G_mapsize) { |
180 | /* mapping covers tail of the file */ | 183 | /* mapping covers tail of the file */ |
181 | /* we do have a mapped byte which is past eof */ | 184 | /* we do have a mapped byte which is past eof */ |
182 | G.eof_byte = G.addr + (G.size - G.offset); | 185 | G.eof_byte = G.baseaddr + (G.size - G.offset); |
183 | } | 186 | } |
184 | } | 187 | } |
185 | static void move_mapping_further(void) | 188 | static void move_mapping_further(void) |
@@ -191,7 +194,7 @@ static void move_mapping_further(void) | |||
191 | return; /* can't move mapping even further, it's at the end already */ | 194 | return; /* can't move mapping even further, it's at the end already */ |
192 | 195 | ||
193 | pagesize = getpagesize(); /* constant on most arches */ | 196 | pagesize = getpagesize(); /* constant on most arches */ |
194 | pos = G.current_byte - G.addr; | 197 | pos = G.current_byte - G.baseaddr; |
195 | if (pos >= pagesize) { | 198 | if (pos >= pagesize) { |
196 | /* move offset up until current position is in 1st page */ | 199 | /* move offset up until current position is in 1st page */ |
197 | do { | 200 | do { |
@@ -214,7 +217,7 @@ static void move_mapping_lower(void) | |||
214 | return; /* we are at 0 already */ | 217 | return; /* we are at 0 already */ |
215 | 218 | ||
216 | pagesize = getpagesize(); /* constant on most arches */ | 219 | pagesize = getpagesize(); /* constant on most arches */ |
217 | pos = G.current_byte - G.addr; | 220 | pos = G.current_byte - G.baseaddr; |
218 | 221 | ||
219 | /* move offset down until current position is in last page */ | 222 | /* move offset down until current position is in last page */ |
220 | pos += pagesize; | 223 | pos += pagesize; |
@@ -252,18 +255,15 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
252 | G.size = xlseek(G.fd, 0, SEEK_END); | 255 | G.size = xlseek(G.fd, 0, SEEK_END); |
253 | 256 | ||
254 | /* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */ | 257 | /* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */ |
258 | printf(SET_ALT_SCR); | ||
255 | set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL); | 259 | set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL); |
256 | bb_signals(BB_FATAL_SIGS, sig_catcher); | 260 | bb_signals(BB_FATAL_SIGS, sig_catcher); |
257 | 261 | ||
258 | remap(0); | 262 | remap(0); |
259 | |||
260 | printf(SET_ALT_SCR); | ||
261 | redraw(); | 263 | redraw(); |
262 | printf(ESC"[1;10H"); /* position on 1st hex byte in first line */ | ||
263 | 264 | ||
264 | //TODO: //Home/End: start/end of line; '<'/'>': start/end of file | 265 | //TODO: //Home/End: start/end of line; '<'/'>': start/end of file |
265 | //Backspace: undo | 266 | //Backspace: undo |
266 | //Enter: goto specified position | ||
267 | //Ctrl-L: redraw | 267 | //Ctrl-L: redraw |
268 | //Ctrl-Z: suspend | 268 | //Ctrl-Z: suspend |
269 | //'/', Ctrl-S: search | 269 | //'/', Ctrl-S: search |
@@ -367,9 +367,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
367 | } | 367 | } |
368 | if ((0xf & (uintptr_t)G.current_byte) == 0) { | 368 | if ((0xf & (uintptr_t)G.current_byte) == 0) { |
369 | /* leftmost pos, wrap to prev line */ | 369 | /* leftmost pos, wrap to prev line */ |
370 | if (G.current_byte == G.addr) { | 370 | if (G.current_byte == G.baseaddr) { |
371 | move_mapping_lower(); | 371 | move_mapping_lower(); |
372 | if (G.current_byte == G.addr) | 372 | if (G.current_byte == G.baseaddr) |
373 | break; /* first line, don't do anything */ | 373 | break; /* first line, don't do anything */ |
374 | } | 374 | } |
375 | G.half = 1; | 375 | G.half = 1; |
@@ -385,9 +385,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
385 | cnt = G.height; | 385 | cnt = G.height; |
386 | case KEYCODE_UP: | 386 | case KEYCODE_UP: |
387 | k_up: | 387 | k_up: |
388 | if ((G.current_byte - G.addr) < 16) { | 388 | if ((G.current_byte - G.baseaddr) < 16) { |
389 | move_mapping_lower(); | 389 | move_mapping_lower(); |
390 | if ((G.current_byte - G.addr) < 16) | 390 | if ((G.current_byte - G.baseaddr) < 16) |
391 | break; | 391 | break; |
392 | } | 392 | } |
393 | G.current_byte -= 16; | 393 | G.current_byte -= 16; |
@@ -403,6 +403,35 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
403 | if (--cnt) | 403 | if (--cnt) |
404 | goto k_up; | 404 | goto k_up; |
405 | break; | 405 | break; |
406 | |||
407 | case '\n': | ||
408 | case '\r': | ||
409 | /* [Enter]: goto specified position */ | ||
410 | { | ||
411 | char buf[sizeof(G.offset)*3 + 4]; | ||
412 | printf(ESC"[999;1H" CLEAR_TILL_EOL); /* go to last line */ | ||
413 | if (read_line_input(NULL, "Go to (dec,0Xhex,0oct): ", buf, sizeof(buf)) >= 0) { | ||
414 | off_t t; | ||
415 | unsigned pgmask; | ||
416 | |||
417 | t = bb_strtoull(buf, NULL, 0); | ||
418 | if (t >= G.size) | ||
419 | t = G.size - 1; | ||
420 | pgmask = getpagesize() - 1; | ||
421 | cnt = t & pgmask; | ||
422 | t = t & ~(off_t)pgmask; | ||
423 | if (t < 0) | ||
424 | cnt = t = 0; | ||
425 | G.offset = t; | ||
426 | remap(0); | ||
427 | redraw(); | ||
428 | cnt /= 16; | ||
429 | if (cnt) | ||
430 | goto k_down; | ||
431 | break; | ||
432 | } | ||
433 | /* EOF/error on input: fall through to exiting */ | ||
434 | } | ||
406 | case CTRL('X'): | 435 | case CTRL('X'): |
407 | restore_term(); | 436 | restore_term(); |
408 | return EXIT_SUCCESS; | 437 | return EXIT_SUCCESS; |
diff --git a/miscutils/less.c b/miscutils/less.c index f869a9e82..d524b6c87 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -281,9 +281,9 @@ static void set_tty_cooked(void) | |||
281 | 281 | ||
282 | /* Move the cursor to a position (x,y), where (0,0) is the | 282 | /* Move the cursor to a position (x,y), where (0,0) is the |
283 | top-left corner of the console */ | 283 | top-left corner of the console */ |
284 | static void move_cursor(int line, int row) | 284 | static void move_cursor(int line, int col) |
285 | { | 285 | { |
286 | printf(ESC"[%u;%uH", line, row); | 286 | printf(ESC"[%u;%uH", line, col); |
287 | } | 287 | } |
288 | 288 | ||
289 | static void clear_line(void) | 289 | static void clear_line(void) |