This source file includes following definitions.
- mcview_hex_calculate_boldflag
- mcview_display_hex
- mcview_hexedit_save_changes
- mcview_toggle_hexedit_mode
- mcview_hexedit_free_change_list
- mcview_enqueue_change
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <config.h>
37
38 #include <errno.h>
39 #include <inttypes.h>
40
41 #include "lib/global.h"
42 #include "lib/tty/tty.h"
43 #include "lib/skin.h"
44 #include "lib/vfs/vfs.h"
45 #include "lib/lock.h"
46 #include "lib/util.h"
47 #include "lib/widget.h"
48 #ifdef HAVE_CHARSET
49 #include "lib/charsets.h"
50 #endif
51
52 #include "internal.h"
53
54
55
56
57
58
59
60 typedef enum
61 {
62 MARK_NORMAL,
63 MARK_SELECTED,
64 MARK_CURSOR,
65 MARK_CHANGED
66 } mark_t;
67
68
69
70 static const char hex_char[] = "0123456789ABCDEF";
71
72
73
74
75
76
77
78
79
80
81
82
83 static mark_t
84 mcview_hex_calculate_boldflag (WView * view, off_t from, struct hexedit_change_node *curr,
85 gboolean force_changed)
86 {
87 return (from == view->hex_cursor) ? MARK_CURSOR
88 : ((curr != NULL && from == curr->offset) || force_changed) ? MARK_CHANGED
89 : (view->search_start <= from && from < view->search_end) ? MARK_SELECTED : MARK_NORMAL;
90 }
91
92
93
94
95
96 void
97 mcview_display_hex (WView * view)
98 {
99 const screen_dimen top = view->data_area.top;
100 const screen_dimen left = view->data_area.left;
101 const screen_dimen height = view->data_area.height;
102 const screen_dimen width = view->data_area.width;
103 const int ngroups = view->bytes_per_line / 4;
104
105
106
107
108
109
110 const screen_dimen text_start = 8 + 13 * ngroups +
111 ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1));
112
113 int row;
114 off_t from;
115 mark_t boldflag_byte = MARK_NORMAL;
116 mark_t boldflag_char = MARK_NORMAL;
117 struct hexedit_change_node *curr = view->change_list;
118 #ifdef HAVE_CHARSET
119 int cont_bytes = 0;
120 gboolean cjk_right = FALSE;
121 #endif
122 gboolean utf8_changed = FALSE;
123
124 char hex_buff[10];
125
126 mcview_display_clean (view);
127
128
129
130 from = view->dpy_start;
131 row = 0;
132 #ifdef HAVE_CHARSET
133 if (view->utf8)
134 {
135 if (from >= view->bytes_per_line)
136 {
137 row--;
138 from -= view->bytes_per_line;
139 }
140 if (view->bytes_per_line == 4 && from >= view->bytes_per_line)
141 {
142 row--;
143 from -= view->bytes_per_line;
144 }
145 }
146 #endif
147 while (curr && (curr->offset < from))
148 {
149 curr = curr->next;
150 }
151
152 for (; mcview_get_byte (view, from, NULL) && row < (int) height; row++)
153 {
154 screen_dimen col = 0;
155 int bytes;
156
157
158 if (row >= 0)
159 {
160 size_t i;
161
162 g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from);
163 widget_gotoyx (view, top + row, left);
164 tty_setcolor (VIEW_BOLD_COLOR);
165 for (i = 0; col < width && hex_buff[i] != '\0'; col++, i++)
166 tty_print_char (hex_buff[i]);
167 tty_setcolor (VIEW_NORMAL_COLOR);
168 }
169
170 for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++)
171 {
172 int c;
173 #ifdef HAVE_CHARSET
174 int ch = 0;
175
176 if (view->utf8)
177 {
178 struct hexedit_change_node *corr = curr;
179
180 if (cont_bytes != 0)
181 {
182
183 cont_bytes--;
184 ch = ' ';
185 if (cjk_right)
186 {
187
188 cjk_right = FALSE;
189 ch = -1;
190 }
191 }
192 else
193 {
194 int j;
195 gchar utf8buf[UTF8_CHAR_LEN + 1];
196 int res;
197 int first_changed = -1;
198
199 for (j = 0; j < UTF8_CHAR_LEN; j++)
200 {
201 if (mcview_get_byte (view, from + j, &res))
202 utf8buf[j] = res;
203 else
204 {
205 utf8buf[j] = '\0';
206 break;
207 }
208 if (curr != NULL && from + j == curr->offset)
209 {
210 utf8buf[j] = curr->value;
211 if (first_changed == -1)
212 first_changed = j;
213 }
214 if (curr != NULL && from + j >= curr->offset)
215 curr = curr->next;
216 }
217 utf8buf[UTF8_CHAR_LEN] = '\0';
218
219
220 ch = g_utf8_get_char_validated (utf8buf, -1);
221 if (ch == -1 || ch == -2)
222 {
223 ch = '.';
224 }
225 else
226 {
227 gchar *next_ch;
228
229 next_ch = g_utf8_next_char (utf8buf);
230 cont_bytes = next_ch - utf8buf - 1;
231 if (g_unichar_iswide (ch))
232 cjk_right = TRUE;
233 }
234
235 utf8_changed = (first_changed >= 0 && first_changed <= cont_bytes);
236 curr = corr;
237 }
238 }
239 #endif
240
241
242
243 if (row < 0)
244 {
245 if (curr != NULL && from == curr->offset)
246 curr = curr->next;
247 continue;
248 }
249
250 if (!mcview_get_byte (view, from, &c))
251 break;
252
253
254 if (from == view->hex_cursor && !view->hexview_in_text)
255 {
256 view->cursor_row = row;
257 view->cursor_col = col;
258 }
259
260
261 boldflag_byte = mcview_hex_calculate_boldflag (view, from, curr, FALSE);
262 boldflag_char = mcview_hex_calculate_boldflag (view, from, curr, utf8_changed);
263
264
265 if (curr != NULL && from == curr->offset)
266 {
267 c = curr->value;
268 curr = curr->next;
269 }
270
271
272 tty_setcolor (boldflag_byte == MARK_NORMAL ? VIEW_NORMAL_COLOR :
273 boldflag_byte == MARK_SELECTED ? VIEW_BOLD_COLOR :
274 boldflag_byte == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
275
276 view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR);
277
278
279 widget_gotoyx (view, top + row, left + col);
280 if (col < width)
281 {
282 tty_print_char (hex_char[c / 16]);
283 col += 1;
284 }
285 if (col < width)
286 {
287 tty_print_char (hex_char[c % 16]);
288 col += 1;
289 }
290
291
292 tty_setcolor (VIEW_NORMAL_COLOR);
293 if (bytes != view->bytes_per_line - 1)
294 {
295 if (col < width)
296 {
297 tty_print_char (' ');
298 col += 1;
299 }
300
301
302 if (bytes % 4 == 3)
303 {
304 if (view->data_area.width >= 80 && col < width)
305 {
306 tty_print_one_vline (TRUE);
307 col += 1;
308 }
309 if (col < width)
310 {
311 tty_print_char (' ');
312 col += 1;
313 }
314 }
315 }
316
317
318
319 tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR :
320 boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR :
321 boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
322
323 view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR);
324
325
326 #ifdef HAVE_CHARSET
327 if (mc_global.utf8_display)
328 {
329 if (!view->utf8)
330 {
331 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
332 }
333 if (!g_unichar_isprint (c))
334 c = '.';
335 }
336 else if (view->utf8)
337 ch = convert_from_utf_to_current_c (ch, view->converter);
338 else
339 #endif
340 {
341 #ifdef HAVE_CHARSET
342 c = convert_to_display_c (c);
343 #endif
344
345 if (!is_printable (c))
346 c = '.';
347 }
348
349
350 if (text_start + bytes < width)
351 {
352 widget_gotoyx (view, top + row, left + text_start + bytes);
353 #ifdef HAVE_CHARSET
354 if (view->utf8)
355 tty_print_anychar (ch);
356 else
357 #endif
358 tty_print_char (c);
359 }
360
361
362 if (from == view->hex_cursor && view->hexview_in_text)
363 {
364 view->cursor_row = row;
365 view->cursor_col = text_start + bytes;
366 }
367 }
368 }
369
370
371 tty_setcolor (VIEW_NORMAL_COLOR);
372
373 mcview_place_cursor (view);
374 view->dpy_end = from;
375 }
376
377
378
379 gboolean
380 mcview_hexedit_save_changes (WView * view)
381 {
382 int answer = 0;
383
384 if (view->change_list == NULL)
385 return TRUE;
386
387 while (answer == 0)
388 {
389 int fp;
390 char *text;
391 struct hexedit_change_node *curr, *next;
392
393 g_assert (view->filename_vpath != NULL);
394
395 fp = mc_open (view->filename_vpath, O_WRONLY);
396 if (fp != -1)
397 {
398 for (curr = view->change_list; curr != NULL; curr = next)
399 {
400 next = curr->next;
401
402 if (mc_lseek (fp, curr->offset, SEEK_SET) == -1
403 || mc_write (fp, &(curr->value), 1) != 1)
404 goto save_error;
405
406
407 view->change_list = next;
408 view->dirty++;
409 mcview_set_byte (view, curr->offset, curr->value);
410 g_free (curr);
411 }
412
413 view->change_list = NULL;
414
415 if (view->locked)
416 view->locked = unlock_file (view->filename_vpath);
417
418 if (mc_close (fp) == -1)
419 message (D_ERROR, _("Save file"),
420 _("Error while closing the file:\n%s\n"
421 "Data may have been written or not"), unix_error_string (errno));
422
423 view->dirty++;
424 return TRUE;
425 }
426
427 save_error:
428 text = g_strdup_printf (_("Cannot save file:\n%s"), unix_error_string (errno));
429 (void) mc_close (fp);
430
431 answer = query_dialog (_("Save file"), text, D_ERROR, 2, _("&Retry"), _("&Cancel"));
432 g_free (text);
433 }
434
435 return FALSE;
436 }
437
438
439
440 void
441 mcview_toggle_hexedit_mode (WView * view)
442 {
443 view->hexedit_mode = !view->hexedit_mode;
444 view->dpy_bbar_dirty = TRUE;
445 view->dirty++;
446 }
447
448
449
450 void
451 mcview_hexedit_free_change_list (WView * view)
452 {
453 struct hexedit_change_node *curr, *next;
454
455 for (curr = view->change_list; curr != NULL; curr = next)
456 {
457 next = curr->next;
458 g_free (curr);
459 }
460 view->change_list = NULL;
461
462 if (view->locked)
463 view->locked = unlock_file (view->filename_vpath);
464
465 view->dirty++;
466 }
467
468
469
470 void
471 mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node)
472 {
473
474
475
476 struct hexedit_change_node **chnode = head;
477
478 while (*chnode != NULL && (*chnode)->offset < node->offset)
479 chnode = &((*chnode)->next);
480
481 node->next = *chnode;
482 *chnode = node;
483 }
484
485