first commit
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Dávid Ali
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
49
README.md
Normal file
49
README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# chexed
|
||||
|
||||
A simple terminal-based hex editor. It is written in C and uses the ncurses library.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need a Linux system and the ncurses library.
|
||||
|
||||
Install it on Debian/Ubuntu with this command:
|
||||
```bash
|
||||
sudo apt install libncurses-dev
|
||||
```
|
||||
|
||||
## Compilation
|
||||
|
||||
Use `gcc` to compile the source code. Run this command:
|
||||
|
||||
```bash
|
||||
gcc chexed.c -o chexed -lncurses
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program with a file path:
|
||||
|
||||
```bash
|
||||
./chexed your_file.bin
|
||||
```
|
||||
|
||||
### Controls
|
||||
|
||||
* **Arrow Keys**: navigate through the file.
|
||||
* **Page Up / Page Down**: scroll quickly.
|
||||
* **0-9, A-F**: input hex values.
|
||||
* **+ / -**: increment or decrement the byte value by 1.
|
||||
* **Ctrl+S**: save changes to the file.
|
||||
* **Ctrl+Q**: quit the program.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
The program loads the entire file into RAM. Do not open files larger than your available memory.
|
||||
|
||||
The file size is fixed: you cannot insert or delete bytes.
|
||||
|
||||
Editing works in a specific way: typing a new digit shifts the current value 4 bits to the left.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
217
chexed.c
Normal file
217
chexed.c
Normal file
@@ -0,0 +1,217 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user