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 if (r->cols == 80)
125 text_start += ngroups - 1;
126 else if (r->cols > 80)
127 text_start += ngroups;
128
129 mcview_display_clean (view);
130
131
132
133 from = view->dpy_start;
134 #ifdef HAVE_CHARSET
135 if (view->utf8)
136 {
137 if (from >= view->bytes_per_line)
138 {
139 row--;
140 from -= view->bytes_per_line;
141 }
142 if (view->bytes_per_line == 4 && from >= view->bytes_per_line)
143 {
144 row--;
145 from -= view->bytes_per_line;
146 }
147 }
148 #endif
149 while (curr != NULL && (curr->offset < from))
150 curr = curr->next;
151
152 for (; mcview_get_byte (view, from, NULL) && row < r->lines; row++)
153 {
154 int col = 0;
155 int bytes;
156
157
158 if (row >= 0)
159 {
160 int i;
161
162 g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from);
163 widget_gotoyx (view, r->y + row, r->x);
164 tty_setcolor (VIEW_BOLD_COLOR);
165 for (i = 0; col < r->cols && 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 ch = '.';
223 else
224 {
225 gchar *next_ch;
226
227 next_ch = g_utf8_next_char (utf8buf);
228 cont_bytes = next_ch - utf8buf - 1;
229 if (g_unichar_iswide (ch))
230 cjk_right = TRUE;
231 }
232
233 utf8_changed = (first_changed >= 0 && first_changed <= cont_bytes);
234 curr = corr;
235 }
236 }
237 #endif
238
239
240
241 if (row < 0)
242 {
243 if (curr != NULL && from == curr->offset)
244 curr = curr->next;
245 continue;
246 }
247
248 if (!mcview_get_byte (view, from, &c))
249 break;
250
251
252 if (from == view->hex_cursor && !view->hexview_in_text)
253 {
254 view->cursor_row = row;
255 view->cursor_col = col;
256 }
257
258
259 boldflag_byte = mcview_hex_calculate_boldflag (view, from, curr, FALSE);
260 boldflag_char = mcview_hex_calculate_boldflag (view, from, curr, utf8_changed);
261
262
263 if (curr != NULL && from == curr->offset)
264 {
265 c = curr->value;
266 curr = curr->next;
267 }
268
269
270 tty_setcolor (boldflag_byte == MARK_NORMAL ? VIEW_NORMAL_COLOR :
271 boldflag_byte == MARK_SELECTED ? VIEW_BOLD_COLOR :
272 boldflag_byte == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
273
274 view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR);
275
276
277 widget_gotoyx (view, r->y + row, r->x + col);
278 if (col < r->cols)
279 {
280 tty_print_char (hex_char[c / 16]);
281 col++;
282 }
283 if (col < r->cols)
284 {
285 tty_print_char (hex_char[c % 16]);
286 col++;
287 }
288
289
290 tty_setcolor (VIEW_NORMAL_COLOR);
291 if (bytes != view->bytes_per_line - 1)
292 {
293 if (col < r->cols)
294 {
295 tty_print_char (' ');
296 col++;
297 }
298
299
300 if (bytes % 4 == 3)
301 {
302 if (view->data_area.cols >= 80 && col < r->cols)
303 {
304 tty_print_one_vline (TRUE);
305 col++;
306 }
307 if (col < r->cols)
308 {
309 tty_print_char (' ');
310 col++;
311 }
312 }
313 }
314
315
316
317 tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR :
318 boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR :
319 boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
320
321 view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR);
322
323
324 #ifdef HAVE_CHARSET
325 if (mc_global.utf8_display)
326 {
327 if (!view->utf8)
328 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
329 if (!g_unichar_isprint (c))
330 c = '.';
331 }
332 else if (view->utf8)
333 ch = convert_from_utf_to_current_c (ch, view->converter);
334 else
335 #endif
336 {
337 #ifdef HAVE_CHARSET
338 c = convert_to_display_c (c);
339 #endif
340
341 if (!is_printable (c))
342 c = '.';
343 }
344
345
346 if (text_start + bytes < r->cols)
347 {
348 widget_gotoyx (view, r->y + row, r->x + text_start + bytes);
349 #ifdef HAVE_CHARSET
350 if (view->utf8)
351 tty_print_anychar (ch);
352 else
353 #endif
354 tty_print_char (c);
355 }
356
357
358 if (from == view->hex_cursor && view->hexview_in_text)
359 {
360 view->cursor_row = row;
361 view->cursor_col = text_start + bytes;
362 }
363 }
364 }
365
366
367 tty_setcolor (VIEW_NORMAL_COLOR);
368
369 mcview_place_cursor (view);
370 view->dpy_end = from;
371 }
372
373
374
375 gboolean
376 mcview_hexedit_save_changes (WView *view)
377 {
378 int answer = 0;
379
380 if (view->change_list == NULL)
381 return TRUE;
382
383 while (answer == 0)
384 {
385 int fp;
386 char *text;
387 struct hexedit_change_node *curr, *next;
388
389 g_assert (view->filename_vpath != NULL);
390
391 fp = mc_open (view->filename_vpath, O_WRONLY);
392 if (fp != -1)
393 {
394 for (curr = view->change_list; curr != NULL; curr = next)
395 {
396 next = curr->next;
397
398 if (mc_lseek (fp, curr->offset, SEEK_SET) == -1
399 || mc_write (fp, &(curr->value), 1) != 1)
400 goto save_error;
401
402
403 view->change_list = next;
404 view->dirty++;
405 mcview_set_byte (view, curr->offset, curr->value);
406 g_free (curr);
407 }
408
409 view->change_list = NULL;
410
411 if (view->locked)
412 view->locked = unlock_file (view->filename_vpath);
413
414 if (mc_close (fp) == -1)
415 message (D_ERROR, _("Save file"),
416 _("Error while closing the file:\n%s\n"
417 "Data may have been written or not"), unix_error_string (errno));
418
419 view->dirty++;
420 return TRUE;
421 }
422
423 save_error:
424 text = g_strdup_printf (_("Cannot save file:\n%s"), unix_error_string (errno));
425 (void) mc_close (fp);
426
427 answer = query_dialog (_("Save file"), text, D_ERROR, 2, _("&Retry"), _("&Cancel"));
428 g_free (text);
429 }
430
431 return FALSE;
432 }
433
434
435
436 void
437 mcview_toggle_hexedit_mode (WView *view)
438 {
439 view->hexedit_mode = !view->hexedit_mode;
440 view->dpy_bbar_dirty = TRUE;
441 view->dirty++;
442 }
443
444
445
446 void
447 mcview_hexedit_free_change_list (WView *view)
448 {
449 struct hexedit_change_node *curr, *next;
450
451 for (curr = view->change_list; curr != NULL; curr = next)
452 {
453 next = curr->next;
454 g_free (curr);
455 }
456 view->change_list = NULL;
457
458 if (view->locked)
459 view->locked = unlock_file (view->filename_vpath);
460
461 view->dirty++;
462 }
463
464
465
466 void
467 mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node)
468 {
469
470
471
472 struct hexedit_change_node **chnode = head;
473
474 while (*chnode != NULL && (*chnode)->offset < node->offset)
475 chnode = &((*chnode)->next);
476
477 node->next = *chnode;
478 *chnode = node;
479 }
480
481