217 lines
4.7 KiB
C
217 lines
4.7 KiB
C
#include <ncurses.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#define ROW_SIZE 16
|
|
#define CTRL_KEY(k) ((k) & 0x1f)
|
|
|
|
unsigned char* buffer;
|
|
long file_size;
|
|
char* filename;
|
|
int cursor_pos = 0;
|
|
int scroll_offset = 0;
|
|
|
|
void load_file(const char* fname) {
|
|
FILE* f = fopen(fname, "rb");
|
|
if (!f) {
|
|
perror("Nie można otworzyć pliku");
|
|
exit(1);
|
|
}
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
file_size = ftell(f);
|
|
rewind(f);
|
|
|
|
buffer = malloc(file_size);
|
|
fread(buffer, 1, file_size, f);
|
|
fclose(f);
|
|
}
|
|
|
|
void save_file() {
|
|
FILE* f = fopen(filename, "wb");
|
|
if (f) {
|
|
fwrite(buffer, 1, file_size, f);
|
|
fclose(f);
|
|
}
|
|
}
|
|
void draw_interface() {
|
|
clear();
|
|
int max_y, max_x;
|
|
getmaxyx(stdscr, max_y, max_x);
|
|
|
|
attron(COLOR_PAIR(1));
|
|
mvprintw(0, 0, "HEXED: %s (ROZMIAR: %ld bajtow)", filename, file_size);
|
|
mvprintw(
|
|
1, 0,
|
|
"^S: Zapisz | ^Q: Wyjscie | Strzalki: Nawigacja | +/-: Zmien wartosc");
|
|
mvhline(2, 0, ACS_HLINE, max_x);
|
|
attroff(COLOR_PAIR(1));
|
|
|
|
int rows_to_draw = max_y - 4;
|
|
|
|
for (int i = 0; i < rows_to_draw; i++) {
|
|
int offset = scroll_offset + (i * ROW_SIZE);
|
|
if (offset >= file_size) break;
|
|
|
|
attron(COLOR_PAIR(1));
|
|
mvprintw(3 + i, 0, "%08X: ", offset);
|
|
attroff(COLOR_PAIR(1));
|
|
|
|
for (int j = 0; j < ROW_SIZE; j++) {
|
|
if (offset + j < file_size) {
|
|
unsigned char val = buffer[offset + j];
|
|
int color_pair = (val == 0x00) ? 3 : 2;
|
|
|
|
if (offset + j == cursor_pos) {
|
|
attron(COLOR_PAIR(4));
|
|
printw("%02X ", val);
|
|
attroff(COLOR_PAIR(4));
|
|
} else {
|
|
attron(COLOR_PAIR(color_pair));
|
|
printw("%02X ", val);
|
|
attroff(COLOR_PAIR(color_pair));
|
|
}
|
|
} else {
|
|
printw(" ");
|
|
}
|
|
}
|
|
|
|
printw("| ");
|
|
|
|
for (int j = 0; j < ROW_SIZE; j++) {
|
|
if (offset + j < file_size) {
|
|
unsigned char c = buffer[offset + j];
|
|
char ch = (isprint(c)) ? c : '.';
|
|
int color_pair = (c == 0x00) ? 3 : 2;
|
|
|
|
if (offset + j == cursor_pos) {
|
|
attron(COLOR_PAIR(4));
|
|
printw("%c", ch);
|
|
attroff(COLOR_PAIR(4));
|
|
} else {
|
|
attron(COLOR_PAIR(color_pair));
|
|
printw("%c", ch);
|
|
attroff(COLOR_PAIR(color_pair));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
refresh();
|
|
}
|
|
void update_byte(int ch) {
|
|
int val = -1;
|
|
if (ch >= '0' && ch <= '9') val = ch - '0';
|
|
if (ch >= 'a' && ch <= 'f') val = ch - 'a' + 10;
|
|
if (ch >= 'A' && ch <= 'F') val = ch - 'A' + 10;
|
|
|
|
if (val != -1) {
|
|
buffer[cursor_pos] = (buffer[cursor_pos] << 4) | val;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc < 2) {
|
|
printf("Uzycie: %s <plik>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
filename = argv[1];
|
|
load_file(filename);
|
|
|
|
initscr();
|
|
start_color();
|
|
use_default_colors();
|
|
|
|
init_pair(1, COLOR_CYAN, -1);
|
|
init_pair(2, COLOR_WHITE, -1);
|
|
init_pair(3, COLOR_BLUE, -1);
|
|
init_pair(4, COLOR_BLACK, COLOR_WHITE);
|
|
|
|
raw();
|
|
noecho();
|
|
keypad(stdscr, TRUE);
|
|
curs_set(0);
|
|
|
|
int ch;
|
|
|
|
int max_y, max_x;
|
|
draw_interface();
|
|
int running = 1;
|
|
while (running) {
|
|
ch = getch();
|
|
|
|
getmaxyx(stdscr, max_y, max_x);
|
|
|
|
switch (ch) {
|
|
case CTRL_KEY('q'):
|
|
running = 0;
|
|
break;
|
|
case KEY_UP:
|
|
if (cursor_pos >= ROW_SIZE) cursor_pos -= ROW_SIZE;
|
|
break;
|
|
case KEY_DOWN:
|
|
if (cursor_pos + ROW_SIZE < file_size) cursor_pos += ROW_SIZE;
|
|
break;
|
|
case KEY_LEFT:
|
|
if (cursor_pos > 0) cursor_pos--;
|
|
break;
|
|
case KEY_RIGHT:
|
|
if (cursor_pos < file_size - 1) cursor_pos++;
|
|
break;
|
|
case '+':
|
|
buffer[cursor_pos]++;
|
|
break;
|
|
case '-':
|
|
buffer[cursor_pos]--;
|
|
break;
|
|
case CTRL_KEY('s'):
|
|
save_file();
|
|
mvprintw(max_y - 1, 0, "ZAPISANO!");
|
|
break;
|
|
case KEY_NPAGE: {
|
|
int rows = max_y - 4;
|
|
int jump = rows * ROW_SIZE;
|
|
|
|
if (cursor_pos + jump < file_size) {
|
|
cursor_pos += jump;
|
|
} else {
|
|
cursor_pos = file_size - 1;
|
|
}
|
|
} break;
|
|
|
|
case KEY_PPAGE: {
|
|
int rows = max_y - 4;
|
|
int jump = rows * ROW_SIZE;
|
|
|
|
if (cursor_pos - jump >= 0) {
|
|
cursor_pos -= jump;
|
|
} else {
|
|
cursor_pos = 0;
|
|
}
|
|
} break;
|
|
default:
|
|
update_byte(ch);
|
|
break;
|
|
}
|
|
|
|
int rows_on_screen = max_y - 4;
|
|
int cursor_row_start = (cursor_pos / ROW_SIZE) * ROW_SIZE;
|
|
|
|
if (cursor_pos < scroll_offset) {
|
|
scroll_offset = cursor_row_start;
|
|
}
|
|
|
|
else if (cursor_pos >= scroll_offset + (rows_on_screen * ROW_SIZE)) {
|
|
scroll_offset = cursor_row_start - ((rows_on_screen - 1) * ROW_SIZE);
|
|
|
|
if (scroll_offset < 0) scroll_offset = 0;
|
|
}
|
|
|
|
draw_interface();
|
|
}
|
|
|
|
endwin();
|
|
free(buffer);
|
|
return 0;
|
|
} |