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