2 Internal file viewer for the Midnight Commander
3 Callback function for some actions (hotkeys, menu)
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
39 The functions in this section can be bound to hotkeys. They are all
40 of the same type (taking a pointer to mcview_t as parameter and
41 returning void). TODO: In the not-too-distant future, these commands
42 will become fully configurable, like they already are in the
43 internal editor. By convention, all the function names end in
52 #include "lib/global.h"
54 #include "lib/tty/tty.h"
55 #include "lib/tty/key.h" /* is_idle() */
56 #include "lib/lock.h" /* lock_file() */
58 #include "lib/widget.h"
59 #include "lib/charsets.h"
60 #include "lib/event.h" /* mc_event_raise() */
62 #include "src/filemanager/layout.h"
63 #include "src/filemanager/cmd.h"
64 #include "src/filemanager/midnight.h" /* current_panel */
66 #include "src/history.h"
67 #include "src/execute.h"
68 #include "src/keybind-defaults.h"
73 /*** global variables ****************************************************************************/
75 /*** file scope macro definitions ****************************************************************/
77 /*** file scope type declarations ****************************************************************/
79 /*** file scope variables ************************************************************************/
81 /*** file scope functions ************************************************************************/
82 /* --------------------------------------------------------------------------------------------- */
86 mcview_search (mcview_t
* view
)
88 if (mcview_dialog_search (view
))
89 mcview_do_search (view
);
92 /* --------------------------------------------------------------------------------------------- */
95 mcview_continue_search_cmd (mcview_t
* view
)
97 if (view
->last_search_string
!= NULL
)
99 mcview_do_search (view
);
103 /* find last search string in history */
105 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
106 if (history
!= NULL
&& history
->data
!= NULL
)
108 view
->last_search_string
= (gchar
*) g_strdup (history
->data
);
109 history
= g_list_first (history
);
110 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
111 g_list_free (history
);
113 view
->search
= mc_search_new (view
->last_search_string
, -1);
114 view
->search_nroff_seq
= mcview_nroff_seq_new (view
);
118 /* if not... then ask for an expression */
119 g_free (view
->last_search_string
);
120 view
->last_search_string
= NULL
;
121 mcview_search (view
);
125 view
->search
->search_type
= mcview_search_options
.type
;
126 view
->search
->is_all_charsets
= mcview_search_options
.all_codepages
;
127 view
->search
->is_case_sensitive
= mcview_search_options
.case_sens
;
128 view
->search
->whole_words
= mcview_search_options
.whole_words
;
129 view
->search
->search_fn
= mcview_search_cmd_callback
;
130 view
->search
->update_fn
= mcview_search_update_cmd_callback
;
132 mcview_do_search (view
);
137 /* if not... then ask for an expression */
138 g_free (view
->last_search_string
);
139 view
->last_search_string
= NULL
;
140 mcview_search (view
);
145 /* --------------------------------------------------------------------------------------------- */
148 mcview_hook (void *v
)
150 mcview_t
*view
= (mcview_t
*) v
;
153 /* If the user is busy typing, wait until he finishes to update the
157 if (!hook_present (idle_hook
, mcview_hook
))
158 add_hook (&idle_hook
, mcview_hook
, v
);
162 delete_hook (&idle_hook
, mcview_hook
);
164 if (get_current_type () == view_listing
)
165 panel
= current_panel
;
166 else if (get_other_type () == view_listing
)
173 mcview_load (view
, 0, panel
->dir
.list
[panel
->selected
].fname
, 0);
174 mcview_display (view
);
177 /* --------------------------------------------------------------------------------------------- */
180 mcview_handle_editkey (mcview_t
* view
, int key
)
182 struct hexedit_change_node
*node
;
185 /* Has there been a change at this position? */
186 node
= view
->change_list
;
187 while ((node
!= NULL
) && (node
->offset
!= view
->hex_cursor
))
190 if (!view
->hexview_in_text
)
193 unsigned int hexvalue
= 0;
195 if (key
>= '0' && key
<= '9')
196 hexvalue
= 0 + (key
- '0');
197 else if (key
>= 'A' && key
<= 'F')
198 hexvalue
= 10 + (key
- 'A');
199 else if (key
>= 'a' && key
<= 'f')
200 hexvalue
= 10 + (key
- 'a');
202 return MSG_NOT_HANDLED
;
205 byte_val
= node
->value
;
207 mcview_get_byte (view
, view
->hex_cursor
, &byte_val
);
209 if (view
->hexedit_lownibble
)
210 byte_val
= (byte_val
& 0xf0) | (hexvalue
);
212 byte_val
= (byte_val
& 0x0f) | (hexvalue
<< 4);
217 if (key
< 256 && ((key
== '\n') || is_printable (key
)))
220 return MSG_NOT_HANDLED
;
223 if ((view
->filename
!= NULL
) && (view
->filename
[0] != '\0') && (view
->change_list
== NULL
))
224 view
->locked
= mcview_lock_file (view
);
228 node
= g_new (struct hexedit_change_node
, 1);
229 node
->offset
= view
->hex_cursor
;
230 node
->value
= byte_val
;
231 mcview_enqueue_change (&view
->change_list
, node
);
234 node
->value
= byte_val
;
237 mcview_move_right (view
, 1);
242 /* --------------------------------------------------------------------------------------------- */
245 mcview_execute_cmd (mcview_t
* view
, unsigned long command
)
247 int res
= MSG_HANDLED
;
253 ev_help_t event_data
= { NULL
, "[Internal File Viewer]" };
254 mc_event_raise (MCEVENT_GROUP_CORE
, "help", &event_data
);
258 /* Toggle between wrapped and unwrapped view */
259 mcview_toggle_wrap_mode (view
);
262 /* Toggle between hexview and hexedit mode */
263 mcview_toggle_hexedit_mode (view
);
266 /* Toggle between hex view and text view */
267 mcview_toggle_hex_mode (view
);
273 if (mcview_dialog_goto (view
, &addr
))
276 mcview_moveto_offset (view
, addr
);
279 message (D_ERROR
, _("Warning"), _("Invalid value"));
286 mcview_hexedit_save_changes (view
);
289 mcview_search (view
);
292 mcview_toggle_magic_mode (view
);
295 mcview_toggle_nroff_mode (view
);
297 case CK_ToggleNavigation
:
298 view
->hexview_in_text
= !view
->hexview_in_text
;
302 mcview_moveto_bol (view
);
305 mcview_moveto_eol (view
);
308 mcview_move_left (view
, 1);
311 mcview_move_right (view
, 1);
315 mcview_move_left (view
, 10);
319 mcview_move_right (view
, 10);
321 case CK_SearchContinue
:
322 mcview_continue_search_cmd (view
);
325 mcview_display_toggle_ruler (view
);
328 mcview_move_up (view
, 1);
331 mcview_move_down (view
, 1);
334 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
336 case CK_HalfPageDown
:
337 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
340 mcview_move_up (view
, view
->data_area
.height
);
343 mcview_move_down (view
, view
->data_area
.height
);
346 mcview_moveto_top (view
);
349 mcview_moveto_bottom (view
);
354 case CK_BookmarkGoto
:
355 view
->marks
[view
->marker
] = view
->dpy_start
;
358 view
->dpy_start
= view
->marks
[view
->marker
];
362 case CK_SelectCodepage
:
363 mcview_select_encoding (view
);
369 /* Use to indicate parent that we want to see the next/previous file */
370 /* Does not work in panel mode */
371 if (!mcview_is_in_panel (view
))
372 view
->move_dir
= (command
== CK_FileNext
) ? 1 : -1;
375 if (!mcview_is_in_panel (view
))
376 dlg_stop (view
->widget
.owner
);
379 /* don't close viewer due to SIGINT */
382 res
= MSG_NOT_HANDLED
;
387 /* --------------------------------------------------------------------------------------------- */
390 mcview_handle_key (mcview_t
* view
, int key
)
392 unsigned long command
;
394 key
= convert_from_input_c (key
);
398 if (view
->hexedit_mode
&& (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
401 command
= keybind_lookup_keymap_command (viewer_hex_map
, key
);
402 if ((command
!= CK_IgnoreKey
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
406 command
= keybind_lookup_keymap_command (viewer_map
, key
);
407 if ((command
!= CK_IgnoreKey
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
410 #ifdef MC_ENABLE_DEBUGGING_CODE
412 { /* mnemonic: "test" */
413 mcview_ccache_dump (view
);
417 if (key
>= '0' && key
<= '9')
418 view
->marker
= key
- '0';
421 return MSG_NOT_HANDLED
;
425 /* --------------------------------------------------------------------------------------------- */
428 mcview_adjust_size (Dlg_head
* h
)
433 /* Look up the viewer and the buttonbar, we assume only two widgets here */
434 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
435 b
= find_buttonbar (h
);
437 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
438 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
440 mcview_compute_areas (view
);
441 mcview_update_bytes_per_line (view
);
445 /* --------------------------------------------------------------------------------------------- */
446 /*** public functions ****************************************************************************/
447 /* --------------------------------------------------------------------------------------------- */
450 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
452 mcview_t
*view
= (mcview_t
*) w
;
455 mcview_compute_areas (view
);
456 mcview_update_bytes_per_line (view
);
461 if (mcview_is_in_panel (view
))
462 add_hook (&select_file_hook
, mcview_hook
, view
);
464 view
->dpy_bbar_dirty
= TRUE
;
468 mcview_display (view
);
473 mcview_place_cursor (view
);
477 i
= mcview_handle_key (view
, parm
);
478 mcview_update (view
);
482 i
= mcview_execute_cmd (view
, parm
);
483 mcview_update (view
);
487 view
->dpy_bbar_dirty
= TRUE
;
488 mcview_update (view
);
492 if (mcview_is_in_panel (view
))
494 delete_hook (&select_file_hook
, mcview_hook
);
496 if (mc_global
.widget
.midnight_shutdown
)
497 mcview_ok_to_quit (view
);
503 return default_proc (msg
, parm
);
507 /* --------------------------------------------------------------------------------------------- */
510 mcview_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
517 mcview_adjust_size (h
);
523 return mcview_execute_cmd (NULL
, parm
);
524 /* message from buttonbar */
525 if (sender
== (Widget
*) find_buttonbar (h
))
528 return send_message ((Widget
*) data
, WIDGET_COMMAND
, parm
);
530 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
531 return mcview_execute_cmd (view
, parm
);
533 return MSG_NOT_HANDLED
;
536 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
537 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
538 if (mcview_ok_to_quit (view
))
539 h
->state
= DLG_CLOSED
;
541 mcview_update (view
);
545 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
549 /* --------------------------------------------------------------------------------------------- */