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