hexedit: restore screen on exit

function                                             old     new   delta
hexedit_main                                         998    1082     +84
restore_term                                           -      29     +29
remap                                                168     173      +5
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 118/0)             Total: 118 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-09-14 09:42:40 +02:00
parent d72e804e6d
commit 363fb5ec40
2 changed files with 53 additions and 28 deletions

View File

@ -15,19 +15,28 @@
#include "libbb.h" #include "libbb.h"
#define ESC "\033" #define ESC "\033"
#define HOME ESC"[H" #define HOME ESC"[H"
#define CLEAR ESC"[H"ESC"[J" #define CLEAR ESC"[H"ESC"[J"
#define SET_ALT_SCR ESC"[?1049h"
#define POP_ALT_SCR ESC"[?1049l"
#undef CTRL
#define CTRL(c) ((c) & (uint8_t)~0x60)
struct globals { struct globals {
smallint half; smallint half;
smallint in_read_key;
int fd; int fd;
unsigned height; unsigned height;
unsigned row;
uint8_t *addr; uint8_t *addr;
uint8_t *current_byte; uint8_t *current_byte;
uint8_t *eof_byte; uint8_t *eof_byte;
off_t size; off_t size;
off_t offset; off_t offset;
/* needs to be zero-inited, thus keeping it in G: */
char read_key_buffer[KEYCODE_BUFFER_SIZE];
struct termios orig_termios; struct termios orig_termios;
}; };
#define G (*ptr_to_globals) #define G (*ptr_to_globals)
@ -41,6 +50,24 @@ struct globals {
/* "12ef5670 (xx )*16 _1_3_5_7_9abcdef\n"NUL */ /* "12ef5670 (xx )*16 _1_3_5_7_9abcdef\n"NUL */
#define LINEBUF_SIZE (8 + 1 + 3*16 + 16 + 1 + 1 /*paranoia:*/ + 13) #define LINEBUF_SIZE (8 + 1 + 3*16 + 16 + 1 + 1 /*paranoia:*/ + 13)
static void restore_term(void)
{
tcsetattr_stdin_TCSANOW(&G.orig_termios);
printf(POP_ALT_SCR);
fflush_all();
}
static void sig_catcher(int sig)
{
if (!G.in_read_key) {
/* now it's not safe to do I/O, just inform the main loop */
bb_got_signal = sig;
return;
}
restore_term();
kill_myself_with_sig(sig);
}
static int format_line(char *hex, uint8_t *data, off_t offset) static int format_line(char *hex, uint8_t *data, off_t offset)
{ {
int ofs_pos; int ofs_pos;
@ -141,9 +168,10 @@ static void remap(unsigned cur_pos)
G.fd, G.fd,
G.offset G.offset
); );
if (G.addr == MAP_FAILED) if (G.addr == MAP_FAILED) {
//TODO: restore termios? restore_term();
bb_perror_msg_and_die("mmap"); bb_perror_msg_and_die("mmap");
}
G.current_byte = G.addr + cur_pos; G.current_byte = G.addr + cur_pos;
@ -201,12 +229,6 @@ static void move_mapping_lower(void)
remap(pos); remap(pos);
} }
static void sig_catcher(int sig)
{
tcsetattr_stdin_TCSANOW(&G.orig_termios);
kill_myself_with_sig(sig);
}
//usage:#define hexedit_trivial_usage //usage:#define hexedit_trivial_usage
//usage: "FILE" //usage: "FILE"
//usage:#define hexedit_full_usage "\n\n" //usage:#define hexedit_full_usage "\n\n"
@ -214,8 +236,6 @@ static void sig_catcher(int sig)
int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int hexedit_main(int argc UNUSED_PARAM, char **argv) int hexedit_main(int argc UNUSED_PARAM, char **argv)
{ {
unsigned row = 0;
INIT_G(); INIT_G();
get_terminal_width_height(-1, NULL, &G.height); get_terminal_width_height(-1, NULL, &G.height);
@ -237,7 +257,7 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
remap(0); remap(0);
printf(CLEAR); printf(SET_ALT_SCR);
redraw(); redraw();
printf(ESC"[1;10H"); /* position on 1st hex byte in first line */ printf(ESC"[1;10H"); /* position on 1st hex byte in first line */
@ -245,21 +265,22 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
//Backspace: undo //Backspace: undo
//Enter: goto specified position //Enter: goto specified position
//Ctrl-L: redraw //Ctrl-L: redraw
//Ctrl-X: save and exit (maybe also Q?)
//Ctrl-Z: suspend //Ctrl-Z: suspend
//'/', Ctrl-S: search //'/', Ctrl-S: search
//TODO: go to end-of-screen on exit (for this, sighandler should interrupt read_key())
//TODO: detect window resize //TODO: detect window resize
//TODO: read-only mode if open(O_RDWR) fails? hide cursor in this case?
for (;;) { for (;;) {
char read_key_buffer[KEYCODE_BUFFER_SIZE];
unsigned cnt; unsigned cnt;
int32_t key; int32_t key = key; // for compiler
uint8_t byte; uint8_t byte;
fflush_all(); fflush_all();
key = read_key(STDIN_FILENO, read_key_buffer, -1); G.in_read_key = 1;
if (!bb_got_signal)
key = read_key(STDIN_FILENO, G.read_key_buffer, -1);
G.in_read_key = 0;
if (bb_got_signal)
key = CTRL('X');
cnt = 1; cnt = 1;
switch (key) { switch (key) {
@ -329,9 +350,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
} }
down: down:
putchar('\n'); /* down one line, possibly scroll screen */ putchar('\n'); /* down one line, possibly scroll screen */
row++; G.row++;
if (row >= G.height) { if (G.row >= G.height) {
row--; G.row--;
redraw_cur_line(); redraw_cur_line();
} }
if (--cnt) if (--cnt)
@ -371,8 +392,8 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
} }
G.current_byte -= 16; G.current_byte -= 16;
up: up:
if (row != 0) { if (G.row != 0) {
row--; G.row--;
printf(ESC"[A"); /* up (won't scroll) */ printf(ESC"[A"); /* up (won't scroll) */
} else { } else {
//printf(ESC"[T"); /* scroll up */ - not implemented on Linux VT! //printf(ESC"[T"); /* scroll up */ - not implemented on Linux VT!
@ -382,8 +403,12 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
if (--cnt) if (--cnt)
goto k_up; goto k_up;
break; break;
} case CTRL('X'):
} restore_term();
return EXIT_SUCCESS;
} /* switch */
} /* for (;;) */
/* not reached */
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1103,7 +1103,7 @@ static int64_t getch_nowait(void)
goto again; goto again;
} }
/* EOF/error (ssh session got killed etc) */ /* EOF/error (ssh session got killed etc) */
less_exit(0); less_exit(EXIT_SUCCESS);
} }
set_tty_cooked(); set_tty_cooked();
return key64; return key64;