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
91 : MARK_NORMAL;
92 }
93
94
95
96
97
98 void
99 mcview_display_hex (WView *view)
100 {
101 const WRect *r = &view->data_area;
102 int ngroups = view->bytes_per_line / 4;
103
104
105
106
107
108
109 int text_start;
110
111 int row = 0;
112 off_t from;
113 mark_t boldflag_byte = MARK_NORMAL;
114 mark_t boldflag_char = MARK_NORMAL;
115 struct hexedit_change_node *curr = view->change_list;
116 #ifdef HAVE_CHARSET
117 int cont_bytes = 0;
118 gboolean cjk_right = FALSE;
119 #endif
120 gboolean utf8_changed = FALSE;
121
122 char hex_buff[10];
123
124 text_start = 8 + 13 * ngroups;
125 if (r->cols == 80)
126 text_start += ngroups - 1;
127 else if (r->cols > 80)
128 text_start += ngroups;
129
130 mcview_display_clean (view);
131
132
133
134 from = view->dpy_start;
135 #ifdef HAVE_CHARSET
136 if (view->utf8)
137 {
138 if (from >= view->bytes_per_line)
139 {
140 row--;
141 from -= view->bytes_per_line;
142 }
143 if (view->bytes_per_line == 4 && from >= view->bytes_per_line)
144 {
145 row--;
146 from -= view->bytes_per_line;
147 }
148 }
149 #endif
150 while (curr != NULL && (curr->offset < from))
151 curr = curr->next;
152
153 for (; mcview_get_byte (view, from, NULL) && row < r->lines; row++)
154 {
155 int col = 0;
156 int bytes;
157
158
159 if (row >= 0)
160 {
161 int i;
162
163 g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from);
164 widget_gotoyx (view, r->y + row, r->x);
165 tty_setcolor (VIEW_BOLD_COLOR);
166 for (i = 0; col < r->cols && hex_buff[i] != '\0'; col++, i++)
167 tty_print_char (hex_buff[i]);
168 tty_setcolor (VIEW_NORMAL_COLOR);
169 }
170
171 for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++)
172 {
173 int c;
174 #ifdef HAVE_CHARSET
175 int ch = 0;
176
177 if (view->utf8)
178 {
179 struct hexedit_change_node *corr = curr;
180
181 if (cont_bytes != 0)
182 {
183
184 cont_bytes--;
185 ch = ' ';
186 if (cjk_right)
187 {
188
189 cjk_right = FALSE;
190 ch = -1;
191 }
192 }
193 else
194 {
195 int j;
196 gchar utf8buf[UTF8_CHAR_LEN + 1];
197 int res;
198 int first_changed = -1;
199
200 for (j = 0; j < UTF8_CHAR_LEN; j++)
201 {
202 if (mcview_get_byte (view, from + j, &res))
203 utf8buf[j] = res;
204 else
205 {
206 utf8buf[j] = '\0';
207 break;
208 }
209 if (curr != NULL && from + j == curr->offset)
210 {
211 utf8buf[j] = curr->value;
212 if (first_changed == -1)
213 first_changed = j;
214 }
215 if (curr != NULL && from + j >= curr->offset)
216 curr = curr->next;
217 }
218 utf8buf[UTF8_CHAR_LEN] = '\0';
219
220
221 ch = g_utf8_get_char_validated (utf8buf, -1);
222 if (ch == -1 || ch == -2)
223 ch = '.';
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
276 view->hexview_in_text ? VIEW_SELECTED_COLOR
277 : VIEW_UNDERLINED_COLOR);
278
279
280 widget_gotoyx (view, r->y + row, r->x + col);
281 if (col < r->cols)
282 {
283 tty_print_char (hex_char[c / 16]);
284 col++;
285 }
286 if (col < r->cols)
287 {
288 tty_print_char (hex_char[c % 16]);
289 col++;
290 }
291
292
293 tty_setcolor (VIEW_NORMAL_COLOR);
294 if (bytes != view->bytes_per_line - 1)
295 {
296 if (col < r->cols)
297 {
298 tty_print_char (' ');
299 col++;
300 }
301
302
303 if (bytes % 4 == 3)
304 {
305 if (view->data_area.cols >= 80 && col < r->cols)
306 {
307 tty_print_one_vline (TRUE);
308 col++;
309 }
310 if (col < r->cols)
311 {
312 tty_print_char (' ');
313 col++;
314 }
315 }
316 }
317
318
319
320 tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR
321 : boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR
322 : boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR
323 :
324
325 view->hexview_in_text ? VIEW_SELECTED_COLOR
326 : MARKED_SELECTED_COLOR);
327
328 #ifdef HAVE_CHARSET
329 if (mc_global.utf8_display)
330 {
331 if (!view->utf8)
332 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
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 < r->cols)
351 {
352 widget_gotoyx (view, r->y + row, r->x + 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) != 0;
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"),
422 unix_error_string (errno));
423
424 view->dirty++;
425 return TRUE;
426 }
427
428 save_error:
429 text = g_strdup_printf (_ ("Cannot save file:\n%s"), unix_error_string (errno));
430 (void) mc_close (fp);
431
432 answer = query_dialog (_ ("Save file"), text, D_ERROR, 2, _ ("&Retry"), _ ("&Cancel"));
433 g_free (text);
434 }
435
436 return FALSE;
437 }
438
439
440
441 void
442 mcview_toggle_hexedit_mode (WView *view)
443 {
444 view->hexedit_mode = !view->hexedit_mode;
445 view->dpy_bbar_dirty = TRUE;
446 view->dirty++;
447 }
448
449
450
451 void
452 mcview_hexedit_free_change_list (WView *view)
453 {
454 struct hexedit_change_node *curr, *next;
455
456 for (curr = view->change_list; curr != NULL; curr = next)
457 {
458 next = curr->next;
459 g_free (curr);
460 }
461 view->change_list = NULL;
462
463 if (view->locked)
464 view->locked = unlock_file (view->filename_vpath) != 0;
465
466 view->dirty++;
467 }
468
469
470
471 void
472 mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node)
473 {
474
475
476
477 struct hexedit_change_node **chnode = head;
478
479 while (*chnode != NULL && (*chnode)->offset < node->offset)
480 chnode = &((*chnode)->next);
481
482 node->next = *chnode;
483 *chnode = node;
484 }
485
486