[git commit] hexedit: restore screen on exit

Denys Vlasenko vda.linux at googlemail.com
Thu Sep 14 07:42:40 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=363fb5ec4091120003b3f204996e7ff0aa354e58
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 miscutils/hexedit.c | 79 +++++++++++++++++++++++++++++++++++------------------
 miscutils/less.c    |  2 +-
 2 files changed, 53 insertions(+), 28 deletions(-)

diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c
index e8bc73b..b8627e8 100644
--- a/miscutils/hexedit.c
+++ b/miscutils/hexedit.c
@@ -15,19 +15,28 @@
 
 #include "libbb.h"
 
-#define ESC	"\033"
-#define HOME	ESC"[H"
-#define CLEAR	ESC"[H"ESC"[J"
+#define ESC		"\033"
+#define HOME		ESC"[H"
+#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 {
 	smallint half;
+	smallint in_read_key;
 	int fd;
 	unsigned height;
+	unsigned row;
 	uint8_t *addr;
 	uint8_t *current_byte;
 	uint8_t *eof_byte;
 	off_t size;
 	off_t offset;
+	/* needs to be zero-inited, thus keeping it in G: */
+	char read_key_buffer[KEYCODE_BUFFER_SIZE];
 	struct termios orig_termios;
 };
 #define G (*ptr_to_globals)
@@ -41,6 +50,24 @@ struct globals {
 /* "12ef5670 (xx )*16 _1_3_5_7_9abcdef\n"NUL */
 #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)
 {
 	int ofs_pos;
@@ -141,9 +168,10 @@ static void remap(unsigned cur_pos)
 		G.fd,
 		G.offset
 	);
-	if (G.addr == MAP_FAILED)
-//TODO: restore termios?
+	if (G.addr == MAP_FAILED) {
+		restore_term();
 		bb_perror_msg_and_die("mmap");
+	}
 
 	G.current_byte = G.addr + cur_pos;
 
@@ -201,12 +229,6 @@ static void move_mapping_lower(void)
 	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:	"FILE"
 //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 UNUSED_PARAM, char **argv)
 {
-	unsigned row = 0;
-
 	INIT_G();
 
 	get_terminal_width_height(-1, NULL, &G.height);
@@ -237,7 +257,7 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 
 	remap(0);
 
-	printf(CLEAR);
+	printf(SET_ALT_SCR);
 	redraw();
 	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
 	//Enter: goto specified position
 	//Ctrl-L: redraw
-	//Ctrl-X: save and exit (maybe also Q?)
 	//Ctrl-Z: suspend
 	//'/', Ctrl-S: search
-//TODO: go to end-of-screen on exit (for this, sighandler should interrupt read_key())
 //TODO: detect window resize
-//TODO: read-only mode if open(O_RDWR) fails? hide cursor in this case?
 
 	for (;;) {
-		char read_key_buffer[KEYCODE_BUFFER_SIZE];
 		unsigned cnt;
-		int32_t key;
+		int32_t key = key; // for compiler
 		uint8_t byte;
 
 		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;
 		switch (key) {
@@ -329,9 +350,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 			}
  down:
 			putchar('\n'); /* down one line, possibly scroll screen */
-			row++;
-			if (row >= G.height) {
-				row--;
+			G.row++;
+			if (G.row >= G.height) {
+				G.row--;
 				redraw_cur_line();
 			}
 			if (--cnt)
@@ -371,8 +392,8 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 			}
 			G.current_byte -= 16;
  up:
-			if (row != 0) {
-				row--;
+			if (G.row != 0) {
+				G.row--;
 				printf(ESC"[A"); /* up (won't scroll) */
 			} else {
 				//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)
 				goto k_up;
 			break;
-		}
-	}
+		case CTRL('X'):
+			restore_term();
+			return EXIT_SUCCESS;
+		} /* switch */
+	} /* for (;;) */
 
+	/* not reached */
 	return EXIT_SUCCESS;
 }
diff --git a/miscutils/less.c b/miscutils/less.c
index 241f7f8..f869a9e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -1103,7 +1103,7 @@ static int64_t getch_nowait(void)
 			goto again;
 		}
 		/* EOF/error (ssh session got killed etc) */
-		less_exit(0);
+		less_exit(EXIT_SUCCESS);
 	}
 	set_tty_cooked();
 	return key64;


More information about the busybox-cvs mailing list