Files
chexed/chexed.c
2026-01-19 16:30:00 +01:00

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;
}