/* hexedit.c - Hexadecimal file editor * * Copyright 2015 Rob Landley * * No standard USE_HEXEDIT(NEWTOY(hexedit, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) config HEXEDIT bool "hexedit" default n help usage: hexedit FILENAME Hexadecimal file editor. */ #define FOR_hexedit #include "toys.h" GLOBALS( char *data; long long len, base; int numlen; unsigned height; ) static void sigttyreset(int i) { set_terminal(1, 0, 0); // how do I re-raise the signal so it dies with right signal info for wait()? _exit(127); } static void esc(char *s) { printf("\033[%s", s); } static void jump(x, y) { char s[32]; sprintf(s, "%d;%dH", y+1, x+1); esc(s); } static void draw_line(long long yy) { int x; yy = (TT.base+yy)*16; if (yySIZE_MAX) TT.len = SIZE_MAX; // count file length hex digits, rounded up to multiple of 4 for (pos = TT.len, TT.numlen = 0; pos; pos >>= 4, TT.numlen++); TT.numlen += (4-TT.numlen)&3; TT.data = mmap(0, TT.len, PROT_READ, MAP_SHARED, fd, 0); draw_page(); y = x = 0; for (;;) { pos = 16*(TT.base+y)+x; if (pos>=TT.len) { pos = TT.len-1; x = (TT.len-1)%15; } esc("7m"); highlight(TT.data[pos], x, y); fflush(0); key = scan_key(toybuf, keys, 1); if (key==-1 || key==4 || key==27) break; esc("0m"); highlight(TT.data[pos], x, y); //jump(73,0); //printf("%d[%c]", key, (key > 255) ? 'X' : key); if (key==KEY_UP) { if (--y<0) { if (TT.base) { TT.base--; esc("1T"); jump(0, 0); draw_line(0); } y = 0; } } else if (key==KEY_DOWN) { if (y == TT.height-1 && pos+32=TT.height) y--; } else if (key==KEY_RIGHT) { if (x<15 && pos+1=TT.len) TT.base=(TT.len-1)/16; draw_page(); } else if (key==KEY_HOME) { TT.base = 0; draw_page(); } else if (key==KEY_END) { TT.base=(TT.len-1)/16; draw_page(); } } munmap(TT.data, TT.len); close(fd); set_terminal(1, 0, 0); esc("?25h"); esc("0m"); jump(0, 999); xputc('\n'); // DEBUG: dump unknown escape sequence for (;;) { key = scan_key(toybuf, keys, 0); if (key >= 0) printf("%d(%c) ", key, key); else { printf("%d\n", key); break; } } xputc('\n'); }