1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

regedit: Import hex editor.

This was tested separately editing files. It needs to be
connected to regedit's value editor.

Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
This commit is contained in:
C. Davis 2012-08-06 19:06:15 -07:00 committed by Michael Adam
parent bdc40f909f
commit 3c14ab13b1
3 changed files with 458 additions and 1 deletions

View File

@ -0,0 +1,406 @@
#include "includes.h"
#include "regedit_hexedit.h"
static int max_rows(WINDOW *win)
{
int maxy, maxx;
getmaxyx(win, maxy, maxx);
return maxy - 1;
}
static int hexedit_free(struct hexedit *buf)
{
if (buf->status_line) {
delwin(buf->status_line);
}
if (buf->win) {
delwin(buf->win);
}
return 0;
}
struct hexedit *hexedit_new(TALLOC_CTX *ctx, WINDOW *parent, int nlines,
int y, int x, size_t sz)
{
struct hexedit *buf;
buf = talloc_zero(ctx, struct hexedit);
if (buf == NULL) {
return NULL;
}
talloc_set_destructor(buf, hexedit_free);
buf->data = talloc_zero_array(buf, uint8_t, sz);
if (buf->data == NULL) {
goto fail;
}
buf->len = sz;
buf->alloc_size = sz;
buf->win = derwin(parent, nlines, LINE_WIDTH, y, x);
if (buf->win == NULL) {
goto fail;
}
buf->cursor_x = HEX_COL1;
buf->status_line = derwin(buf->win, 1, LINE_WIDTH, max_rows(buf->win), 0);
if (buf->status_line == NULL) {
goto fail;
}
wattron(buf->status_line, A_REVERSE | A_STANDOUT);
return buf;
fail:
talloc_free(buf);
return NULL;
}
static size_t bytes_per_screen(WINDOW *win)
{
return max_rows(win) * BYTES_PER_LINE;
}
void hexedit_set_cursor(struct hexedit *buf)
{
werase(buf->status_line);
wprintw(buf->status_line, "Len:%lu Off:%lu Val:0x%X", buf->len,
buf->cursor_offset, buf->data[buf->cursor_offset]);
wrefresh(buf->status_line);
wmove(buf->win, buf->cursor_y, buf->cursor_x);
}
void hexedit_refresh(struct hexedit *buf)
{
size_t end;
size_t lineno;
size_t off;
werase(buf->win);
end = buf->offset + bytes_per_screen(buf->win);
if (end > buf->len) {
end = buf->len;
}
for (off = buf->offset, lineno = 0; off < end; off += BYTES_PER_LINE, ++lineno) {
uint8_t *line = buf->data + off;
size_t i, endline;
wmove(buf->win, lineno, 0);
wprintw(buf->win, "%08X ", off);
endline = BYTES_PER_LINE;
if (off + BYTES_PER_LINE > buf->len) {
endline = buf->len - off;
}
for (i = 0; i < endline; ++i) {
wprintw(buf->win, "%02X", line[i]);
if (i + 1 < endline) {
if (i == 3) {
wprintw(buf->win, " ");
} else {
wprintw(buf->win, " ");
}
}
}
wmove(buf->win, lineno, ASCII_COL);
for (i = 0; i < endline; ++i) {
if (isprint(line[i])) {
waddch(buf->win, line[i]);
} else {
waddch(buf->win, '.');
}
}
}
}
static void calc_cursor_offset(struct hexedit *buf)
{
buf->cursor_offset = buf->offset + buf->cursor_y * BYTES_PER_LINE + buf->cursor_line_offset;
}
static int offset_to_hex_col(size_t pos)
{
switch (pos) {
case 0:
return HEX_COL1;
case 1:
return HEX_COL1 + 3;
case 2:
return HEX_COL1 + 6;
case 3:
return HEX_COL1 + 9;
case 4:
return HEX_COL2;
case 5:
return HEX_COL2 + 3;
case 6:
return HEX_COL2 + 6;
case 7:
return HEX_COL2 + 9;
}
return -1;
}
static bool scroll_down(struct hexedit *buf)
{
if (buf->offset + bytes_per_screen(buf->win) >= buf->len) {
return false;
}
buf->offset += BYTES_PER_LINE;
return true;
}
static bool scroll_up(struct hexedit *buf)
{
if (buf->offset == 0) {
return false;
}
buf->offset -= BYTES_PER_LINE;
return true;
}
static void cursor_down(struct hexedit *buf)
{
if (buf->cursor_y + 1 == max_rows(buf->win)) {
if (scroll_down(buf)) {
hexedit_refresh(buf);
}
} else {
if (buf->cursor_offset + BYTES_PER_LINE >= buf->len) {
return;
}
buf->cursor_y++;
}
calc_cursor_offset(buf);
}
static void cursor_up(struct hexedit *buf)
{
if (buf->cursor_y == 0) {
if (scroll_up(buf)) {
hexedit_refresh(buf);
}
} else {
buf->cursor_y--;
}
calc_cursor_offset(buf);
}
static bool is_over_gap(struct hexedit *buf)
{
int col;
if (buf->cursor_x < ASCII_COL) {
if (buf->cursor_x >= HEX_COL2) {
col = buf->cursor_x - HEX_COL2;
} else {
col = buf->cursor_x - HEX_COL1;
}
switch (col) {
case 2:
case 5:
case 8:
return true;
}
}
return false;
}
static void cursor_left(struct hexedit *buf)
{
if (buf->cursor_x == HEX_COL1) {
return;
}
if (buf->cursor_x == HEX_COL2) {
buf->cursor_x = HEX_COL1_END - 1;
buf->cursor_line_offset = 3;
buf->nibble = 1;
} else if (buf->cursor_x == ASCII_COL) {
size_t off = buf->offset + buf->cursor_y * BYTES_PER_LINE;
if (off + 7 >= buf->len) {
size_t lastpos = buf->len - off - 1;
buf->cursor_x = offset_to_hex_col(lastpos) + 1;
buf->cursor_line_offset = lastpos;
} else {
buf->cursor_x = HEX_COL2_END - 1;
buf->cursor_line_offset = 7;
}
buf->nibble = 1;
} else {
if (buf->cursor_x > ASCII_COL || buf->nibble == 0) {
buf->cursor_line_offset--;
}
buf->cursor_x--;
buf->nibble = !buf->nibble;
}
if (is_over_gap(buf)) {
buf->cursor_x--;
}
calc_cursor_offset(buf);
}
static void cursor_right(struct hexedit *buf)
{
int new_x = buf->cursor_x + 1;
if (new_x == ASCII_COL_END) {
return;
}
if ((buf->cursor_x >= ASCII_COL || buf->nibble == 1) &&
buf->cursor_offset + 1 == buf->len) {
if (buf->cursor_x < ASCII_COL) {
new_x = ASCII_COL;
buf->cursor_line_offset = 0;
buf->nibble = 0;
} else {
return;
}
}
if (new_x == HEX_COL1_END) {
new_x = HEX_COL2;
buf->cursor_line_offset = 4;
buf->nibble = 0;
} else if (new_x == HEX_COL2_END) {
new_x = ASCII_COL;
buf->cursor_line_offset = 0;
buf->nibble = 0;
} else {
if (buf->cursor_x >= ASCII_COL || buf->nibble == 1) {
buf->cursor_line_offset++;
}
buf->nibble = !buf->nibble;
}
buf->cursor_x = new_x;
if (is_over_gap(buf)) {
buf->cursor_x++;
}
calc_cursor_offset(buf);
}
static void do_edit(struct hexedit *buf, int c)
{
uint8_t *byte;
byte = buf->data + buf->cursor_offset;
if (buf->cursor_x >= ASCII_COL) {
*byte = (uint8_t)c;
mvwprintw(buf->win, buf->cursor_y,
offset_to_hex_col(buf->cursor_line_offset), "%X", c);
if (!isprint(c)) {
c = '.';
}
mvwaddch(buf->win, buf->cursor_y, ASCII_COL + buf->cursor_line_offset, c);
cursor_right(buf);
} else {
if (!isxdigit(c)) {
return;
}
c = toupper(c);
waddch(buf->win, c);
if (isdigit(c)) {
c = c - '0';
} else {
c = c - 'A' + 10;
}
if (buf->nibble == 0) {
*byte = (*byte & 0x0f) | c << 4;
} else {
*byte = (*byte & 0xf0) | c;
}
c = *byte;
if (!isprint(c)) {
c = '.';
}
mvwaddch(buf->win, buf->cursor_y, ASCII_COL + buf->cursor_line_offset, c);
if (buf->cursor_x + 1 != HEX_COL2_END) {
cursor_right(buf);
}
}
}
void hexedit_driver(struct hexedit *buf, int c)
{
switch (c) {
case HE_CURSOR_UP:
cursor_up(buf);
break;
case HE_CURSOR_DOWN:
cursor_down(buf);
break;
case HE_CURSOR_LEFT:
cursor_left(buf);
break;
case HE_CURSOR_RIGHT:
cursor_right(buf);
break;
case HE_CURSOR_PGUP:
break;
case HE_CURSOR_PGDN:
break;
default:
do_edit(buf, c & 0xff);
break;
}
}
WERROR hexedit_resize_buffer(struct hexedit *buf, size_t newsz)
{
/* reset the cursor if it'll be out of bounds
after the resize */
if (buf->cursor_offset >= newsz) {
buf->cursor_y = 0;
buf->cursor_x = HEX_COL1;
buf->offset = 0;
buf->cursor_offset = 0;
buf->cursor_line_offset = 0;
buf->nibble = 0;
}
if (newsz > buf->len) {
if (newsz > buf->alloc_size) {
uint8_t *d;
d = talloc_realloc(buf, buf->data, uint8_t, newsz);
if (d == NULL) {
return WERR_NOMEM;
}
buf->data = d;
buf->alloc_size = newsz;
}
memset(buf->data + buf->len, '\0', newsz - buf->len);
buf->len = newsz;
} else {
buf->len = newsz;
}
return WERR_OK;
}

View File

@ -0,0 +1,50 @@
#ifndef _HEXEDIT_H_
#define _HEXEDIT_H_
#include <ncurses.h>
enum {
HE_CURSOR_UP = 0x1000,
HE_CURSOR_DOWN = 0x1100,
HE_CURSOR_LEFT = 0x1200,
HE_CURSOR_RIGHT = 0x1300,
HE_CURSOR_PGUP = 0x1400,
HE_CURSOR_PGDN = 0x1500
};
/*
offset hex1 hex2 ascii
00000000 FF FF FF FF FF FF FF FF ........
*/
#define LINE_WIDTH 44
#define HEX_COL1 10
#define HEX_COL1_END 21
#define HEX_COL2 23
#define HEX_COL2_END 34
#define ASCII_COL 36
#define ASCII_COL_END LINE_WIDTH
#define BYTES_PER_LINE 8
struct hexedit {
size_t offset;
size_t len;
size_t alloc_size;
int cursor_y;
int cursor_x;
size_t cursor_offset;
size_t cursor_line_offset;
int nibble;
uint8_t *data;
WINDOW *win;
WINDOW *status_line;
};
struct hexedit *hexedit_new(TALLOC_CTX *ctx, WINDOW *parent, int nlines,
int y, int x, size_t sz);
void hexedit_set_cursor(struct hexedit *buf);
void hexedit_refresh(struct hexedit *buf);
void hexedit_driver(struct hexedit *buf, int c);
WERROR hexedit_resize_buffer(struct hexedit *buf, size_t newsz);
#endif

View File

@ -1644,7 +1644,8 @@ bld.SAMBA3_PYTHON('pylibsmb',
bld.SAMBA3_BINARY('regedit',
source="""utils/regedit.c utils/regedit_samba3.c
utils/regedit_wrap.c utils/regedit_treeview.c
utils/regedit_valuelist.c utils/regedit_dialog.c""",
utils/regedit_valuelist.c utils/regedit_dialog.c
utils/regedit_hexedit.c""",
deps='ncurses menu panel form registry param popt_samba3 smbregistry',
enabled=bld.env.build_regedit,
vars=locals())