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