This source file includes following definitions.
- mcview_remove_ext_script
- mcview_continue_search_cmd
- mcview_hook
- mcview_handle_editkey
- mcview_load_next_prev_init
- mcview_scan_for_file
- mcview_load_next_prev
- mcview_load_file_from_history
- mcview_help
- mcview_execute_cmd
- mcview_lookup_key
- mcview_handle_key
- mcview_resize
- mcview_ok_to_quit
- mcview_callback
- mcview_dialog_callback
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
37
38
39
40
41
42
43
44
45 #include <config.h>
46
47 #include <stdlib.h>
48
49 #include "lib/global.h"
50
51 #include "lib/tty/tty.h"
52 #include "lib/tty/key.h"
53 #include "lib/lock.h"
54 #include "lib/file-entry.h"
55 #include "lib/widget.h"
56 #include "lib/charsets.h"
57 #include "lib/event.h"
58 #include "lib/mcconfig.h"
59
60 #include "src/filemanager/layout.h"
61 #include "src/filemanager/filemanager.h"
62 #include "src/filemanager/ext.h"
63
64 #include "src/history.h"
65 #include "src/file_history.h"
66 #include "src/execute.h"
67 #include "src/keymap.h"
68
69 #include "internal.h"
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 static void
86 mcview_remove_ext_script (WView *view)
87 {
88 if (view->ext_script != NULL)
89 {
90 mc_unlink (view->ext_script);
91 vfs_path_free (view->ext_script, TRUE);
92 view->ext_script = NULL;
93 }
94 }
95
96
97
98 static void
99 mcview_continue_search_cmd (WView *view)
100 {
101 if (view->last_search_string != NULL)
102 mcview_search (view, FALSE);
103 else
104 {
105
106 char *s;
107
108 s = mc_config_history_get_recent_item (MC_HISTORY_SHARED_SEARCH);
109 if (s != NULL)
110 {
111 view->last_search_string = s;
112
113 if (mcview_search_init (view))
114 {
115 mcview_search (view, FALSE);
116 return;
117 }
118
119
120 MC_PTR_FREE (view->last_search_string);
121 }
122
123
124 mcview_search (view, TRUE);
125 }
126 }
127
128
129
130 static void
131 mcview_hook (void *v)
132 {
133 WView *view = (WView *) v;
134 WPanel *panel;
135 const file_entry_t *fe;
136
137
138
139 if (!is_idle ())
140 {
141 if (!hook_present (idle_hook, mcview_hook))
142 add_hook (&idle_hook, mcview_hook, v);
143 return;
144 }
145
146 delete_hook (&idle_hook, mcview_hook);
147
148 if (get_current_type () == view_listing)
149 panel = current_panel;
150 else if (get_other_type () == view_listing)
151 panel = other_panel;
152 else
153 return;
154
155 fe = panel_current_entry (panel);
156 if (fe == NULL)
157 return;
158
159 mcview_done (view);
160 mcview_init (view);
161 mcview_load (view, 0, fe->fname->str, 0, 0, 0);
162 mcview_display (view);
163 }
164
165
166
167 static cb_ret_t
168 mcview_handle_editkey (WView *view, int key)
169 {
170 struct hexedit_change_node *node;
171 int byte_val = -1;
172
173
174 node = view->change_list;
175 while ((node != NULL) && (node->offset != view->hex_cursor))
176 node = node->next;
177
178 if (!view->hexview_in_text)
179 {
180
181 unsigned int hexvalue = 0;
182
183 if (key >= '0' && key <= '9')
184 hexvalue = 0 + (key - '0');
185 else if (key >= 'A' && key <= 'F')
186 hexvalue = 10 + (key - 'A');
187 else if (key >= 'a' && key <= 'f')
188 hexvalue = 10 + (key - 'a');
189 else
190 return MSG_NOT_HANDLED;
191
192 if (node != NULL)
193 byte_val = node->value;
194 else
195 mcview_get_byte (view, view->hex_cursor, &byte_val);
196
197 if (view->hexedit_lownibble)
198 byte_val = (byte_val & 0xf0) | (hexvalue);
199 else
200 byte_val = (byte_val & 0x0f) | (hexvalue << 4);
201 }
202 else
203 {
204
205 if (key < 256 && key != '\t')
206 byte_val = key;
207 else
208 return MSG_NOT_HANDLED;
209 }
210
211 if ((view->filename_vpath != NULL)
212 && (*(vfs_path_get_last_path_str (view->filename_vpath)) != '\0')
213 && (view->change_list == NULL))
214 view->locked = lock_file (view->filename_vpath) != 0;
215
216 if (node == NULL)
217 {
218 node = g_new (struct hexedit_change_node, 1);
219 node->offset = view->hex_cursor;
220 node->value = byte_val;
221 mcview_enqueue_change (&view->change_list, node);
222 }
223 else
224 node->value = byte_val;
225
226 view->dirty++;
227 mcview_move_right (view, 1);
228
229 return MSG_HANDLED;
230 }
231
232
233
234 static void
235 mcview_load_next_prev_init (WView *view)
236 {
237 if (mc_global.mc_run_mode != MC_RUN_VIEWER)
238 {
239
240 view->dir = ¤t_panel->dir;
241 view->dir_idx = ¤t_panel->current;
242 }
243 else if (view->dir == NULL)
244 {
245
246
247
248
249
250 dir_sort_options_t sort_op = { FALSE, TRUE, FALSE };
251
252
253 view->dir = g_new0 (dir_list, 1);
254 view->dir_idx = g_new (int, 1);
255
256 if (dir_list_load (view->dir, view->workdir_vpath, (GCompareFunc) sort_name, &sort_op,
257 NULL))
258 {
259 const char *fname;
260 size_t fname_len;
261 int i;
262
263 fname = x_basename (vfs_path_as_str (view->filename_vpath));
264 fname_len = strlen (fname);
265
266
267 for (i = 0; i != view->dir->len; i++)
268 {
269 const file_entry_t *fe = &view->dir->list[i];
270
271 if (fname_len == fe->fname->len && strncmp (fname, fe->fname->str, fname_len) == 0)
272 break;
273 }
274
275 *view->dir_idx = i;
276 }
277 else
278 {
279 message (D_ERROR, MSG_ERROR, _ ("Cannot read directory contents"));
280 MC_PTR_FREE (view->dir);
281 MC_PTR_FREE (view->dir_idx);
282 }
283 }
284 }
285
286
287
288 static void
289 mcview_scan_for_file (WView *view, int direction)
290 {
291 int i;
292
293 for (i = *view->dir_idx + direction; i != *view->dir_idx; i += direction)
294 {
295 if (i < 0)
296 i = view->dir->len - 1;
297 if (i == view->dir->len)
298 i = 0;
299 if (!S_ISDIR (view->dir->list[i].st.st_mode))
300 break;
301 }
302
303 *view->dir_idx = i;
304 }
305
306
307
308 static void
309 mcview_load_next_prev (WView *view, int direction)
310 {
311 dir_list *dir;
312 int *dir_idx;
313 vfs_path_t *vfile;
314 vfs_path_t *ext_script = NULL;
315
316 mcview_load_next_prev_init (view);
317 mcview_scan_for_file (view, direction);
318
319
320 dir = view->dir;
321 dir_idx = view->dir_idx;
322 view->dir = NULL;
323 view->dir_idx = NULL;
324 vfile =
325 vfs_path_append_new (view->workdir_vpath, dir->list[*dir_idx].fname->str, (char *) NULL);
326 mcview_done (view);
327 mcview_remove_ext_script (view);
328 mcview_init (view);
329 if (regex_command_for (view, vfile, "View", &ext_script) == 0)
330 mcview_load (view, NULL, vfs_path_as_str (vfile), 0, 0, 0);
331 vfs_path_free (vfile, TRUE);
332 view->dir = dir;
333 view->dir_idx = dir_idx;
334 view->ext_script = ext_script;
335
336 view->dpy_bbar_dirty = FALSE;
337 view->dirty++;
338 }
339
340
341
342 static void
343 mcview_load_file_from_history (WView *view)
344 {
345 char *filename;
346 int action;
347
348 filename = show_file_history (CONST_WIDGET (view), &action);
349
350 if (filename != NULL && (action == CK_View || action == CK_Enter))
351 {
352 mcview_done (view);
353 mcview_init (view);
354
355 mcview_load (view, NULL, filename, 0, 0, 0);
356
357 view->dpy_bbar_dirty = FALSE;
358 view->dirty++;
359 }
360
361 g_free (filename);
362 }
363
364
365
366 static void
367 mcview_help (const WView *view)
368 {
369 ev_help_t event_data = { NULL, "[Internal File Viewer]" };
370
371 (void) view;
372
373 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
374 }
375
376
377
378 static cb_ret_t
379 mcview_execute_cmd (WView *view, long command)
380 {
381 int res = MSG_HANDLED;
382
383 switch (command)
384 {
385 case CK_Help:
386 mcview_help (view);
387 break;
388 case CK_HexMode:
389
390 mcview_toggle_hex_mode (view);
391 break;
392 case CK_HexEditMode:
393
394 mcview_toggle_hexedit_mode (view);
395 break;
396 case CK_ToggleNavigation:
397 view->hexview_in_text = !view->hexview_in_text;
398 view->dirty++;
399 break;
400 case CK_LeftQuick:
401 if (!view->mode_flags.hex)
402 mcview_move_left (view, 10);
403 break;
404 case CK_RightQuick:
405 if (!view->mode_flags.hex)
406 mcview_move_right (view, 10);
407 break;
408 case CK_Goto:
409 {
410 off_t addr;
411
412 if (mcview_dialog_goto (view, &addr))
413 {
414 if (addr >= 0)
415 mcview_moveto_offset (view, addr);
416 else
417 {
418 message (D_ERROR, _ ("Warning"), "%s", _ ("Invalid value"));
419 view->dirty++;
420 }
421 }
422 break;
423 }
424 case CK_Save:
425 mcview_hexedit_save_changes (view);
426 break;
427 case CK_Search:
428 mcview_search (view, TRUE);
429 break;
430 case CK_SearchContinue:
431 mcview_continue_search_cmd (view);
432 break;
433 case CK_SearchForward:
434 mcview_search_options.backwards = FALSE;
435 mcview_search (view, TRUE);
436 break;
437 case CK_SearchForwardContinue:
438 mcview_search_options.backwards = FALSE;
439 mcview_continue_search_cmd (view);
440 break;
441 case CK_SearchBackward:
442 mcview_search_options.backwards = TRUE;
443 mcview_search (view, TRUE);
444 break;
445 case CK_SearchBackwardContinue:
446 mcview_search_options.backwards = TRUE;
447 mcview_continue_search_cmd (view);
448 break;
449 case CK_SearchOppositeContinue:
450 {
451 gboolean direction;
452
453 direction = mcview_search_options.backwards;
454 mcview_search_options.backwards = !direction;
455 mcview_continue_search_cmd (view);
456 mcview_search_options.backwards = direction;
457 }
458 break;
459 case CK_WrapMode:
460
461 mcview_toggle_wrap_mode (view);
462 break;
463 case CK_MagicMode:
464 mcview_toggle_magic_mode (view);
465 break;
466 case CK_NroffMode:
467 mcview_toggle_nroff_mode (view);
468 break;
469 case CK_Home:
470 mcview_moveto_bol (view);
471 break;
472 case CK_End:
473 mcview_moveto_eol (view);
474 break;
475 case CK_Left:
476 mcview_move_left (view, 1);
477 break;
478 case CK_Right:
479 mcview_move_right (view, 1);
480 break;
481 case CK_Up:
482 mcview_move_up (view, 1);
483 break;
484 case CK_Down:
485 mcview_move_down (view, 1);
486 break;
487 case CK_HalfPageUp:
488 mcview_move_up (view, (view->data_area.lines + 1) / 2);
489 break;
490 case CK_HalfPageDown:
491 mcview_move_down (view, (view->data_area.lines + 1) / 2);
492 break;
493 case CK_PageUp:
494 mcview_move_up (view, view->data_area.lines);
495 break;
496 case CK_PageDown:
497 mcview_move_down (view, view->data_area.lines);
498 break;
499 case CK_Top:
500 mcview_moveto_top (view);
501 break;
502 case CK_Bottom:
503 mcview_moveto_bottom (view);
504 break;
505 case CK_Shell:
506 toggle_subshell ();
507 break;
508 case CK_Ruler:
509 mcview_display_toggle_ruler (view);
510 break;
511 case CK_Bookmark:
512 view->dpy_start = view->marks[view->marker];
513 view->dpy_paragraph_skip_lines = 0;
514 view->dpy_wrap_dirty = TRUE;
515 view->dirty++;
516 break;
517 case CK_BookmarkGoto:
518 view->marks[view->marker] = view->dpy_start;
519 break;
520 case CK_SelectCodepage:
521 mcview_select_encoding (view);
522 view->dirty++;
523 break;
524 case CK_FileNext:
525 case CK_FilePrev:
526
527 if (!mcview_is_in_panel (view))
528 mcview_load_next_prev (view, command == CK_FileNext ? 1 : -1);
529 break;
530 case CK_History:
531 mcview_load_file_from_history (view);
532 break;
533 case CK_Quit:
534 if (!mcview_is_in_panel (view))
535 dlg_close (DIALOG (WIDGET (view)->owner));
536 break;
537 case CK_Cancel:
538
539 break;
540 default:
541 res = MSG_NOT_HANDLED;
542 }
543 return res;
544 }
545
546
547
548 static long
549 mcview_lookup_key (WView *view, int key)
550 {
551 if (view->mode_flags.hex)
552 return keybind_lookup_keymap_command (view->hex_keymap, key);
553
554 return widget_lookup_key (WIDGET (view), key);
555 }
556
557
558
559 static cb_ret_t
560 mcview_handle_key (WView *view, int key)
561 {
562 long command;
563
564 key = convert_from_input_c (key);
565
566 if (view->hexedit_mode && view->mode_flags.hex
567 && mcview_handle_editkey (view, key) == MSG_HANDLED)
568 return MSG_HANDLED;
569
570 command = mcview_lookup_key (view, key);
571 if (command != CK_IgnoreKey && mcview_execute_cmd (view, command) == MSG_HANDLED)
572 return MSG_HANDLED;
573
574 #ifdef MC_ENABLE_DEBUGGING_CODE
575 if (key == 't')
576 {
577 mcview_ccache_dump (view);
578 return MSG_HANDLED;
579 }
580 #endif
581 if (key >= '0' && key <= '9')
582 view->marker = key - '0';
583
584
585 return MSG_NOT_HANDLED;
586 }
587
588
589
590 static inline void
591 mcview_resize (WView *view)
592 {
593 view->dpy_wrap_dirty = TRUE;
594 mcview_compute_areas (view);
595 mcview_update_bytes_per_line (view);
596 }
597
598
599
600 static gboolean
601 mcview_ok_to_quit (WView *view)
602 {
603 int r;
604
605 if (view->change_list == NULL)
606 return TRUE;
607
608 if (!mc_global.midnight_shutdown)
609 {
610 query_set_sel (2);
611 r = query_dialog (_ ("Quit"), _ ("File was modified. Save with exit?"), D_NORMAL, 3,
612 _ ("&Yes"), _ ("&No"), _ ("&Cancel"));
613 }
614 else
615 {
616 char *text;
617
618 text = g_strdup_printf (_ ("%s is being shut down.\nSave modified file?"), PACKAGE_NAME);
619 r = query_dialog (_ ("Quit"), text, D_NORMAL, 2, _ ("&Yes"), _ ("&No"));
620 g_free (text);
621
622
623 if (r == -1)
624 r = 1;
625 }
626
627 switch (r)
628 {
629 case 0:
630 return mcview_hexedit_save_changes (view) || mc_global.midnight_shutdown;
631 case 1:
632 mcview_hexedit_free_change_list (view);
633 return TRUE;
634 default:
635 return FALSE;
636 }
637 }
638
639
640
641
642
643 cb_ret_t
644 mcview_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
645 {
646 WView *view = (WView *) w;
647 cb_ret_t i;
648
649 mcview_compute_areas (view);
650 mcview_update_bytes_per_line (view);
651
652 switch (msg)
653 {
654 case MSG_INIT:
655 if (mcview_is_in_panel (view))
656 add_hook (&select_file_hook, mcview_hook, view);
657 else
658 view->dpy_bbar_dirty = TRUE;
659 return MSG_HANDLED;
660
661 case MSG_DRAW:
662 mcview_display (view);
663 return MSG_HANDLED;
664
665 case MSG_CURSOR:
666 if (view->mode_flags.hex)
667 mcview_place_cursor (view);
668 return MSG_HANDLED;
669
670 case MSG_KEY:
671 i = mcview_handle_key (view, parm);
672 mcview_update (view);
673 return i;
674
675 case MSG_ACTION:
676 i = mcview_execute_cmd (view, parm);
677 mcview_update (view);
678 return i;
679
680 case MSG_FOCUS:
681 view->dpy_bbar_dirty = TRUE;
682
683 mcview_update (view);
684 return MSG_HANDLED;
685
686 case MSG_RESIZE:
687 widget_default_callback (w, NULL, MSG_RESIZE, 0, data);
688 mcview_resize (view);
689 return MSG_HANDLED;
690
691 case MSG_DESTROY:
692 if (mcview_is_in_panel (view))
693 {
694 delete_hook (&select_file_hook, mcview_hook);
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 delete_hook (&idle_hook, mcview_hook);
716
717 if (mc_global.midnight_shutdown)
718 mcview_ok_to_quit (view);
719 }
720 mcview_done (view);
721 mcview_remove_ext_script (view);
722 return MSG_HANDLED;
723
724 default:
725 return widget_default_callback (w, sender, msg, parm, data);
726 }
727 }
728
729
730
731 cb_ret_t
732 mcview_dialog_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
733 {
734 WDialog *h = DIALOG (w);
735 WView *view;
736
737 switch (msg)
738 {
739 case MSG_ACTION:
740
741
742
743
744 return mcview_execute_cmd (NULL, parm);
745
746 case MSG_VALIDATE:
747 view = (WView *) widget_find_by_type (w, mcview_callback);
748
749 widget_set_state (w, WST_ACTIVE, TRUE);
750 if (mcview_ok_to_quit (view))
751 dlg_close (h);
752 else
753 mcview_update (view);
754 return MSG_HANDLED;
755
756 default:
757 return dlg_default_callback (w, sender, msg, parm, data);
758 }
759 }
760
761