2 #include "regedit_hexedit.h"
4 static int max_rows(WINDOW
*win
)
8 getmaxyx(win
, maxy
, maxx
);
13 static int hexedit_free(struct hexedit
*buf
)
15 if (buf
->status_line
) {
16 delwin(buf
->status_line
);
25 struct hexedit
*hexedit_new(TALLOC_CTX
*ctx
, WINDOW
*parent
, int nlines
,
26 int y
, int x
, size_t sz
)
30 buf
= talloc_zero(ctx
, struct hexedit
);
35 talloc_set_destructor(buf
, hexedit_free
);
37 buf
->data
= talloc_zero_array(buf
, uint8_t, sz
);
38 if (buf
->data
== NULL
) {
44 buf
->win
= derwin(parent
, nlines
, LINE_WIDTH
, y
, x
);
45 if (buf
->win
== NULL
) {
48 buf
->cursor_x
= HEX_COL1
;
50 buf
->status_line
= derwin(buf
->win
, 1, LINE_WIDTH
, max_rows(buf
->win
), 0);
51 if (buf
->status_line
== NULL
) {
54 wattron(buf
->status_line
, A_REVERSE
| A_STANDOUT
);
64 static size_t bytes_per_screen(WINDOW
*win
)
66 return max_rows(win
) * BYTES_PER_LINE
;
69 void hexedit_set_cursor(struct hexedit
*buf
)
71 werase(buf
->status_line
);
72 wprintw(buf
->status_line
, "Len:%lu Off:%lu Val:0x%X", buf
->len
,
73 buf
->cursor_offset
, buf
->data
[buf
->cursor_offset
]);
74 wrefresh(buf
->status_line
);
75 wmove(buf
->win
, buf
->cursor_y
, buf
->cursor_x
);
78 void hexedit_refresh(struct hexedit
*buf
)
86 end
= buf
->offset
+ bytes_per_screen(buf
->win
);
91 for (off
= buf
->offset
, lineno
= 0; off
< end
; off
+= BYTES_PER_LINE
, ++lineno
) {
92 uint8_t *line
= buf
->data
+ off
;
95 wmove(buf
->win
, lineno
, 0);
96 wprintw(buf
->win
, "%08X ", off
);
98 endline
= BYTES_PER_LINE
;
100 if (off
+ BYTES_PER_LINE
> buf
->len
) {
101 endline
= buf
->len
- off
;
104 for (i
= 0; i
< endline
; ++i
) {
105 wprintw(buf
->win
, "%02X", line
[i
]);
106 if (i
+ 1 < endline
) {
108 wprintw(buf
->win
, " ");
110 wprintw(buf
->win
, " ");
115 wmove(buf
->win
, lineno
, ASCII_COL
);
116 for (i
= 0; i
< endline
; ++i
) {
117 if (isprint(line
[i
])) {
118 waddch(buf
->win
, line
[i
]);
120 waddch(buf
->win
, '.');
126 static void calc_cursor_offset(struct hexedit
*buf
)
128 buf
->cursor_offset
= buf
->offset
+ buf
->cursor_y
* BYTES_PER_LINE
+ buf
->cursor_line_offset
;
131 static int offset_to_hex_col(size_t pos
)
156 static bool scroll_down(struct hexedit
*buf
)
158 if (buf
->offset
+ bytes_per_screen(buf
->win
) >= buf
->len
) {
162 buf
->offset
+= BYTES_PER_LINE
;
167 static bool scroll_up(struct hexedit
*buf
)
169 if (buf
->offset
== 0) {
173 buf
->offset
-= BYTES_PER_LINE
;
178 static void cursor_down(struct hexedit
*buf
)
180 if (buf
->cursor_y
+ 1 == max_rows(buf
->win
)) {
181 if (scroll_down(buf
)) {
182 hexedit_refresh(buf
);
185 if (buf
->cursor_offset
+ BYTES_PER_LINE
>= buf
->len
) {
191 calc_cursor_offset(buf
);
194 static void cursor_up(struct hexedit
*buf
)
196 if (buf
->cursor_y
== 0) {
197 if (scroll_up(buf
)) {
198 hexedit_refresh(buf
);
204 calc_cursor_offset(buf
);
207 static bool is_over_gap(struct hexedit
*buf
)
211 if (buf
->cursor_x
< ASCII_COL
) {
212 if (buf
->cursor_x
>= HEX_COL2
) {
213 col
= buf
->cursor_x
- HEX_COL2
;
215 col
= buf
->cursor_x
- HEX_COL1
;
229 static void cursor_left(struct hexedit
*buf
)
231 if (buf
->cursor_x
== HEX_COL1
) {
234 if (buf
->cursor_x
== HEX_COL2
) {
235 buf
->cursor_x
= HEX_COL1_END
- 1;
236 buf
->cursor_line_offset
= 3;
238 } else if (buf
->cursor_x
== ASCII_COL
) {
239 size_t off
= buf
->offset
+ buf
->cursor_y
* BYTES_PER_LINE
;
240 if (off
+ 7 >= buf
->len
) {
241 size_t lastpos
= buf
->len
- off
- 1;
242 buf
->cursor_x
= offset_to_hex_col(lastpos
) + 1;
243 buf
->cursor_line_offset
= lastpos
;
245 buf
->cursor_x
= HEX_COL2_END
- 1;
246 buf
->cursor_line_offset
= 7;
250 if (buf
->cursor_x
> ASCII_COL
|| buf
->nibble
== 0) {
251 buf
->cursor_line_offset
--;
254 buf
->nibble
= !buf
->nibble
;
257 if (is_over_gap(buf
)) {
261 calc_cursor_offset(buf
);
264 static void cursor_right(struct hexedit
*buf
)
266 int new_x
= buf
->cursor_x
+ 1;
268 if (new_x
== ASCII_COL_END
) {
271 if ((buf
->cursor_x
>= ASCII_COL
|| buf
->nibble
== 1) &&
272 buf
->cursor_offset
+ 1 == buf
->len
) {
273 if (buf
->cursor_x
< ASCII_COL
) {
275 buf
->cursor_line_offset
= 0;
281 if (new_x
== HEX_COL1_END
) {
283 buf
->cursor_line_offset
= 4;
285 } else if (new_x
== HEX_COL2_END
) {
287 buf
->cursor_line_offset
= 0;
290 if (buf
->cursor_x
>= ASCII_COL
|| buf
->nibble
== 1) {
291 buf
->cursor_line_offset
++;
293 buf
->nibble
= !buf
->nibble
;
296 buf
->cursor_x
= new_x
;
298 if (is_over_gap(buf
)) {
302 calc_cursor_offset(buf
);
305 static void do_edit(struct hexedit
*buf
, int c
)
309 byte
= buf
->data
+ buf
->cursor_offset
;
311 if (buf
->cursor_x
>= ASCII_COL
) {
314 mvwprintw(buf
->win
, buf
->cursor_y
,
315 offset_to_hex_col(buf
->cursor_line_offset
), "%X", c
);
319 mvwaddch(buf
->win
, buf
->cursor_y
, ASCII_COL
+ buf
->cursor_line_offset
, c
);
333 if (buf
->nibble
== 0) {
334 *byte
= (*byte
& 0x0f) | c
<< 4;
336 *byte
= (*byte
& 0xf0) | c
;
343 mvwaddch(buf
->win
, buf
->cursor_y
, ASCII_COL
+ buf
->cursor_line_offset
, c
);
345 if (buf
->cursor_x
+ 1 != HEX_COL2_END
) {
351 void hexedit_driver(struct hexedit
*buf
, int c
)
363 case HE_CURSOR_RIGHT
:
371 do_edit(buf
, c
& 0xff);
376 WERROR
hexedit_resize_buffer(struct hexedit
*buf
, size_t newsz
)
378 /* reset the cursor if it'll be out of bounds
380 if (buf
->cursor_offset
>= newsz
) {
382 buf
->cursor_x
= HEX_COL1
;
384 buf
->cursor_offset
= 0;
385 buf
->cursor_line_offset
= 0;
389 if (newsz
> buf
->len
) {
390 if (newsz
> buf
->alloc_size
) {
392 d
= talloc_realloc(buf
, buf
->data
, uint8_t, newsz
);
397 buf
->alloc_size
= newsz
;
399 memset(buf
->data
+ buf
->len
, '\0', newsz
- buf
->len
);