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"
57 #include "src/dialog.h" /* cb_ret_t */
58 #include "src/panel.h"
59 #include "src/layout.h"
60 #include "src/wtools.h"
61 #include "src/history.h"
62 #include "src/charsets.h"
64 #include "src/execute.h"
66 #include "src/keybind.h"
67 #include "src/cmddef.h" /* CK_ cmd name const */
72 /*** global variables ****************************************************************************/
74 /*** file scope macro definitions ****************************************************************/
76 /*** file scope type declarations ****************************************************************/
78 /*** file scope variables ************************************************************************/
80 /*** file scope functions ************************************************************************/
84 mcview_search (mcview_t
*view
)
86 if (mcview_dialog_search (view
))
87 mcview_do_search (view
);
90 /* --------------------------------------------------------------------------------------------- */
93 mcview_continue_search_cmd (mcview_t
* view
)
95 if (view
->last_search_string
!= NULL
) {
96 mcview_do_search (view
);
98 /* find last search string in history */
100 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
101 if (history
!= NULL
&& history
->data
!= NULL
) {
102 view
->last_search_string
= (gchar
*) g_strdup(history
->data
);
103 history
= g_list_first (history
);
104 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
105 g_list_free (history
);
107 view
->search
= mc_search_new (view
->last_search_string
, -1);
108 view
->search_nroff_seq
= mcview_nroff_seq_new (view
);
111 /* if not... then ask for an expression */
112 g_free(view
->last_search_string
);
113 view
->last_search_string
= NULL
;
114 mcview_search (view
);
116 view
->search
->search_type
= mcview_search_options
.type
;
117 view
->search
->is_all_charsets
= mcview_search_options
.all_codepages
;
118 view
->search
->is_case_sentitive
= mcview_search_options
.case_sens
;
119 view
->search
->whole_words
= mcview_search_options
.whole_words
;
120 view
->search
->search_fn
= mcview_search_cmd_callback
;
121 view
->search
->update_fn
= mcview_search_update_cmd_callback
;
123 mcview_do_search (view
);
126 /* if not... then ask for an expression */
127 g_free(view
->last_search_string
);
128 view
->last_search_string
= NULL
;
129 mcview_search (view
);
134 /* --------------------------------------------------------------------------------------------- */
136 /* Check for left and right arrows, possibly with modifiers */
138 mcview_check_left_right_keys (mcview_t
* view
, int c
)
141 mcview_move_left (view
, 1);
145 if (c
== KEY_RIGHT
) {
146 mcview_move_right (view
, 1);
150 /* Ctrl with arrows moves by 10 postions in the unwrap mode */
151 if (view
->hex_mode
|| view
->text_wrap_mode
)
152 return MSG_NOT_HANDLED
;
154 if (c
== (KEY_M_CTRL
| KEY_LEFT
)) {
155 if (view
->dpy_text_column
>= 10)
156 view
->dpy_text_column
-= 10;
158 view
->dpy_text_column
= 0;
163 if (c
== (KEY_M_CTRL
| KEY_RIGHT
)) {
164 if (view
->dpy_text_column
<= OFFSETTYPE_MAX
- 10)
165 view
->dpy_text_column
+= 10;
167 view
->dpy_text_column
= OFFSETTYPE_MAX
;
172 return MSG_NOT_HANDLED
;
175 /* --------------------------------------------------------------------------------------------- */
178 mcview_cmk_move_up (void *w
, int n
)
180 mcview_move_up ((mcview_t
*) w
, n
);
183 /* --------------------------------------------------------------------------------------------- */
186 mcview_cmk_move_down (void *w
, int n
)
188 mcview_move_down ((mcview_t
*) w
, n
);
191 /* --------------------------------------------------------------------------------------------- */
194 mcview_cmk_moveto_top (void *w
, int n
)
197 mcview_moveto_top ((mcview_t
*) w
);
200 /* --------------------------------------------------------------------------------------------- */
203 mcview_cmk_moveto_bottom (void *w
, int n
)
206 mcview_moveto_bottom ((mcview_t
*) w
);
209 /* --------------------------------------------------------------------------------------------- */
212 mcview_hook (void *v
)
214 mcview_t
*view
= (mcview_t
*) v
;
217 /* If the user is busy typing, wait until he finishes to update the
220 if (!hook_present (idle_hook
, mcview_hook
))
221 add_hook (&idle_hook
, mcview_hook
, v
);
225 delete_hook (&idle_hook
, mcview_hook
);
227 if (get_current_type () == view_listing
)
228 panel
= current_panel
;
229 else if (get_other_type () == view_listing
)
234 mcview_load (view
, 0, panel
->dir
.list
[panel
->selected
].fname
, 0);
235 mcview_display (view
);
238 /* --------------------------------------------------------------------------------------------- */
241 mcview_handle_editkey (mcview_t
* view
, int key
)
243 struct hexedit_change_node
*node
;
245 /* Has there been a change at this position? */
246 node
= view
->change_list
;
247 while (node
&& (node
->offset
!= view
->hex_cursor
))
250 if (!view
->hexview_in_text
) {
252 unsigned int hexvalue
= 0;
253 if (key
>= '0' && key
<= '9') {
254 hexvalue
= 0 + (key
- '0');
255 } else if (key
>= 'A' && key
<= 'F')
256 hexvalue
= 10 + (key
- 'A');
257 else if (key
>= 'a' && key
<= 'f')
258 hexvalue
= 10 + (key
- 'a');
260 return MSG_NOT_HANDLED
;
263 byte_val
= node
->value
;
265 mcview_get_byte (view
, view
->hex_cursor
, &byte_val
);
267 if (view
->hexedit_lownibble
) {
268 byte_val
= (byte_val
& 0xf0) | (hexvalue
);
270 byte_val
= (byte_val
& 0x0f) | (hexvalue
<< 4);
274 if (key
< 256 && ((key
== '\n') || is_printable (key
)))
277 return MSG_NOT_HANDLED
;
280 node
= g_new (struct hexedit_change_node
, 1);
281 node
->offset
= view
->hex_cursor
;
282 node
->value
= byte_val
;
283 mcview_enqueue_change (&view
->change_list
, node
);
285 node
->value
= byte_val
;
288 mcview_move_right (view
, 1);
292 /* --------------------------------------------------------------------------------------------- */
295 mcview_execute_cmd (mcview_t
*view
, unsigned long command
)
297 int res
= MSG_HANDLED
;
301 interactive_display (NULL
, "[Internal File Viewer]");
303 case CK_ViewToggleWrapMode
:
304 /* Toggle between wrapped and unwrapped view */
305 mcview_toggle_wrap_mode (view
);
308 case CK_ViewToggleHexEditMode
:
309 /* Toggle between hexview and hexedit mode */
310 mcview_toggle_hexedit_mode (view
);
313 case CK_ViewToggleHexMode
:
314 /* Toggle between hex view and text view */
315 mcview_toggle_hex_mode (view
);
322 if (mcview_dialog_goto (view
, &addr
)) {
324 mcview_moveto_offset (view
, addr
);
326 message (D_ERROR
, _("Warning"), _("Invalid value"));
332 case CK_ViewHexEditSave
:
333 mcview_hexedit_save_changes (view
);
336 mcview_search (view
);
338 case CK_ViewToggleMagicMode
:
339 mcview_toggle_magic_mode (view
);
342 case CK_ViewToggleNroffMode
:
343 mcview_toggle_nroff_mode (view
);
346 case CK_ViewToggleHexNavMode
:
347 view
->hexview_in_text
= !view
->hexview_in_text
;
350 case CK_ViewMoveToBol
:
351 mcview_moveto_bol (view
);
353 case CK_ViewMoveToEol
:
354 mcview_moveto_eol (view
);
356 case CK_ViewMoveLeft
:
357 mcview_move_left (view
, 1);
359 case CK_ViewMoveRight
:
360 mcview_move_right (view
, 1);
362 /* Continue search */
363 case CK_ViewContinueSearch
:
364 mcview_continue_search_cmd (view
);
366 case CK_ViewToggleRuler
:
367 mcview_display_toggle_ruler (view
);
370 mcview_move_up (view
, 1);
372 case CK_ViewMoveDown
:
373 mcview_move_down (view
, 1);
375 case CK_ViewMoveHalfPgUp
:
376 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
378 case CK_ViewMoveHalfPgDn
:
379 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
381 case CK_ViewMovePgUp
:
382 mcview_move_up (view
, view
->data_area
.height
);
384 case CK_ViewMovePgDn
:
385 mcview_move_down (view
, view
->data_area
.height
);
387 case CK_ShowCommandLine
:
391 // Unlike Ctrl-O, run a new shell if the subshell is not running
396 case CK_ViewGotoBookmark
:
397 view
->marks
[view
->marker
] = view
->dpy_start
;
399 case CK_ViewNewBookmark
:
400 view
->dpy_start
= view
->marks
[view
->marker
];
403 case CK_SelectCodepage
:
404 mcview_select_encoding (view
);
407 case CK_ViewNextFile
:
408 case CK_ViewPrevFile
:
409 /* Use to indicate parent that we want to see the next/previous file */
410 /* Does not work in panel mode */
411 if (!mcview_is_in_panel (view
))
412 view
->move_dir
= (command
== CK_ViewNextFile
) ? 1 : -1;
415 if (mcview_ok_to_quit (view
))
416 view
->want_to_quit
= TRUE
;
419 res
= MSG_NOT_HANDLED
;
426 mcview_handle_key (mcview_t
* view
, int key
)
428 unsigned long command
;
430 key
= convert_from_input_c (key
);
432 if (view
->hex_mode
) {
433 if (view
->hexedit_mode
434 && (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
437 command
= lookup_keymap_command (view
->hex_map
, key
);
438 if ((command
!= CK_Ignore_Key
)
439 && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
443 command
= lookup_keymap_command (view
->plain_map
, key
);
444 if ((command
!= CK_Ignore_Key
)
445 && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
448 if (mcview_check_left_right_keys (view
, key
))
451 if (check_movement_keys (key
, view
->data_area
.height
+ 1, view
,
452 mcview_cmk_move_up
, mcview_cmk_move_down
,
453 mcview_cmk_moveto_top
, mcview_cmk_moveto_bottom
))
456 #ifdef MC_ENABLE_DEBUGGING_CODE
457 if (c
== 't') { /* mnemonic: "test" */
458 mcview_ccache_dump (view
);
462 if (key
>= '0' && key
<= '9')
463 view
->marker
= key
- '0';
466 return MSG_NOT_HANDLED
;
470 /* --------------------------------------------------------------------------------------------- */
473 mcview_adjust_size (Dlg_head
*h
)
478 /* Look up the viewer and the buttonbar, we assume only two widgets here */
479 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
480 b
= find_buttonbar (h
);
482 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
483 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
485 mcview_compute_areas (view
);
486 mcview_update_bytes_per_line (view
);
490 /* --------------------------------------------------------------------------------------------- */
492 /*** public functions ****************************************************************************/
494 /* --------------------------------------------------------------------------------------------- */
497 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
499 mcview_t
*view
= (mcview_t
*) w
;
501 Dlg_head
*h
= view
->widget
.parent
;
503 mcview_compute_areas (view
);
504 mcview_update_bytes_per_line (view
);
508 if (mcview_is_in_panel (view
))
509 add_hook (&select_file_hook
, mcview_hook
, view
);
511 view
->dpy_bbar_dirty
= TRUE
;
515 mcview_display (view
);
520 mcview_place_cursor (view
);
524 i
= mcview_handle_key (view
, parm
);
525 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
528 mcview_update (view
);
532 i
= mcview_execute_cmd (view
, parm
);
533 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
536 mcview_update (view
);
540 view
->dpy_bbar_dirty
= TRUE
;
541 mcview_update (view
);
546 if (mcview_is_in_panel (view
))
547 delete_hook (&select_file_hook
, mcview_hook
);
551 return default_proc (msg
, parm
);
555 /* --------------------------------------------------------------------------------------------- */
558 mcview_dialog_callback (Dlg_head
*h
, Widget
*sender
,
559 dlg_msg_t msg
, int parm
, void *data
)
561 mcview_t
*view
= data
;
565 mcview_adjust_size (h
);
569 /* command from buttonbar */
570 return send_message ((Widget
*) view
, WIDGET_COMMAND
, parm
);
573 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
577 /* --------------------------------------------------------------------------------------------- */