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
)
97 mcview_do_search (view
);
101 /* find last search string in history */
103 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
104 if (history
!= NULL
&& history
->data
!= NULL
)
106 view
->last_search_string
= (gchar
*) g_strdup (history
->data
);
107 history
= g_list_first (history
);
108 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
109 g_list_free (history
);
111 view
->search
= mc_search_new (view
->last_search_string
, -1);
112 view
->search_nroff_seq
= mcview_nroff_seq_new (view
);
116 /* if not... then ask for an expression */
117 g_free (view
->last_search_string
);
118 view
->last_search_string
= NULL
;
119 mcview_search (view
);
123 view
->search
->search_type
= mcview_search_options
.type
;
124 view
->search
->is_all_charsets
= mcview_search_options
.all_codepages
;
125 view
->search
->is_case_sentitive
= mcview_search_options
.case_sens
;
126 view
->search
->whole_words
= mcview_search_options
.whole_words
;
127 view
->search
->search_fn
= mcview_search_cmd_callback
;
128 view
->search
->update_fn
= mcview_search_update_cmd_callback
;
130 mcview_do_search (view
);
135 /* if not... then ask for an expression */
136 g_free (view
->last_search_string
);
137 view
->last_search_string
= NULL
;
138 mcview_search (view
);
143 /* --------------------------------------------------------------------------------------------- */
145 /* Check for left and right arrows, possibly with modifiers */
147 mcview_check_left_right_keys (mcview_t
* view
, int c
)
151 mcview_move_left (view
, 1);
157 mcview_move_right (view
, 1);
161 /* Ctrl with arrows moves by 10 postions in the unwrap mode */
162 if (view
->hex_mode
|| view
->text_wrap_mode
)
163 return MSG_NOT_HANDLED
;
165 if (c
== (KEY_M_CTRL
| KEY_LEFT
))
167 if (view
->dpy_text_column
>= 10)
168 view
->dpy_text_column
-= 10;
170 view
->dpy_text_column
= 0;
175 if (c
== (KEY_M_CTRL
| KEY_RIGHT
))
177 if (view
->dpy_text_column
<= OFFSETTYPE_MAX
- 10)
178 view
->dpy_text_column
+= 10;
180 view
->dpy_text_column
= OFFSETTYPE_MAX
;
185 return MSG_NOT_HANDLED
;
188 /* --------------------------------------------------------------------------------------------- */
191 mcview_cmk_move_up (void *w
, int n
)
193 mcview_move_up ((mcview_t
*) w
, n
);
196 /* --------------------------------------------------------------------------------------------- */
199 mcview_cmk_move_down (void *w
, int n
)
201 mcview_move_down ((mcview_t
*) w
, n
);
204 /* --------------------------------------------------------------------------------------------- */
207 mcview_cmk_moveto_top (void *w
, int n
)
210 mcview_moveto_top ((mcview_t
*) w
);
213 /* --------------------------------------------------------------------------------------------- */
216 mcview_cmk_moveto_bottom (void *w
, int n
)
219 mcview_moveto_bottom ((mcview_t
*) w
);
222 /* --------------------------------------------------------------------------------------------- */
225 mcview_hook (void *v
)
227 mcview_t
*view
= (mcview_t
*) v
;
230 /* If the user is busy typing, wait until he finishes to update the
234 if (!hook_present (idle_hook
, mcview_hook
))
235 add_hook (&idle_hook
, mcview_hook
, v
);
239 delete_hook (&idle_hook
, mcview_hook
);
241 if (get_current_type () == view_listing
)
242 panel
= current_panel
;
243 else if (get_other_type () == view_listing
)
248 mcview_load (view
, 0, panel
->dir
.list
[panel
->selected
].fname
, 0);
249 mcview_display (view
);
252 /* --------------------------------------------------------------------------------------------- */
255 mcview_handle_editkey (mcview_t
* view
, int key
)
257 struct hexedit_change_node
*node
;
259 /* Has there been a change at this position? */
260 node
= view
->change_list
;
261 while (node
&& (node
->offset
!= view
->hex_cursor
))
264 if (!view
->hexview_in_text
)
267 unsigned int hexvalue
= 0;
268 if (key
>= '0' && key
<= '9')
270 hexvalue
= 0 + (key
- '0');
272 else if (key
>= 'A' && key
<= 'F')
273 hexvalue
= 10 + (key
- 'A');
274 else if (key
>= 'a' && key
<= 'f')
275 hexvalue
= 10 + (key
- 'a');
277 return MSG_NOT_HANDLED
;
280 byte_val
= node
->value
;
282 mcview_get_byte (view
, view
->hex_cursor
, &byte_val
);
284 if (view
->hexedit_lownibble
)
286 byte_val
= (byte_val
& 0xf0) | (hexvalue
);
290 byte_val
= (byte_val
& 0x0f) | (hexvalue
<< 4);
296 if (key
< 256 && ((key
== '\n') || is_printable (key
)))
299 return MSG_NOT_HANDLED
;
303 node
= g_new (struct hexedit_change_node
, 1);
304 node
->offset
= view
->hex_cursor
;
305 node
->value
= byte_val
;
306 mcview_enqueue_change (&view
->change_list
, node
);
310 node
->value
= byte_val
;
313 mcview_move_right (view
, 1);
317 /* --------------------------------------------------------------------------------------------- */
320 mcview_execute_cmd (mcview_t
* view
, unsigned long command
)
322 int res
= MSG_HANDLED
;
327 interactive_display (NULL
, "[Internal File Viewer]");
329 case CK_ViewToggleWrapMode
:
330 /* Toggle between wrapped and unwrapped view */
331 mcview_toggle_wrap_mode (view
);
334 case CK_ViewToggleHexEditMode
:
335 /* Toggle between hexview and hexedit mode */
336 mcview_toggle_hexedit_mode (view
);
339 case CK_ViewToggleHexMode
:
340 /* Toggle between hex view and text view */
341 mcview_toggle_hex_mode (view
);
348 if (mcview_dialog_goto (view
, &addr
))
351 mcview_moveto_offset (view
, addr
);
354 message (D_ERROR
, _("Warning"), _("Invalid value"));
360 case CK_ViewHexEditSave
:
361 mcview_hexedit_save_changes (view
);
364 mcview_search (view
);
366 case CK_ViewToggleMagicMode
:
367 mcview_toggle_magic_mode (view
);
370 case CK_ViewToggleNroffMode
:
371 mcview_toggle_nroff_mode (view
);
374 case CK_ViewToggleHexNavMode
:
375 view
->hexview_in_text
= !view
->hexview_in_text
;
378 case CK_ViewMoveToBol
:
379 mcview_moveto_bol (view
);
381 case CK_ViewMoveToEol
:
382 mcview_moveto_eol (view
);
384 case CK_ViewMoveLeft
:
385 mcview_move_left (view
, 1);
387 case CK_ViewMoveRight
:
388 mcview_move_right (view
, 1);
390 /* Continue search */
391 case CK_ViewContinueSearch
:
392 mcview_continue_search_cmd (view
);
394 case CK_ViewToggleRuler
:
395 mcview_display_toggle_ruler (view
);
398 mcview_move_up (view
, 1);
400 case CK_ViewMoveDown
:
401 mcview_move_down (view
, 1);
403 case CK_ViewMoveHalfPgUp
:
404 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
406 case CK_ViewMoveHalfPgDn
:
407 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
409 case CK_ViewMovePgUp
:
410 mcview_move_up (view
, view
->data_area
.height
);
412 case CK_ViewMovePgDn
:
413 mcview_move_down (view
, view
->data_area
.height
);
415 case CK_ShowCommandLine
:
419 // Unlike Ctrl-O, run a new shell if the subshell is not running
424 case CK_ViewGotoBookmark
:
425 view
->marks
[view
->marker
] = view
->dpy_start
;
427 case CK_ViewNewBookmark
:
428 view
->dpy_start
= view
->marks
[view
->marker
];
431 case CK_SelectCodepage
:
432 mcview_select_encoding (view
);
435 case CK_ViewNextFile
:
436 case CK_ViewPrevFile
:
437 /* Use to indicate parent that we want to see the next/previous file */
438 /* Does not work in panel mode */
439 if (!mcview_is_in_panel (view
))
440 view
->move_dir
= (command
== CK_ViewNextFile
) ? 1 : -1;
443 if (mcview_ok_to_quit (view
))
444 view
->want_to_quit
= TRUE
;
447 res
= MSG_NOT_HANDLED
;
454 mcview_handle_key (mcview_t
* view
, int key
)
456 unsigned long command
;
458 key
= convert_from_input_c (key
);
462 if (view
->hexedit_mode
&& (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
465 command
= lookup_keymap_command (view
->hex_map
, key
);
466 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
470 command
= lookup_keymap_command (view
->plain_map
, key
);
471 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
474 if (mcview_check_left_right_keys (view
, key
))
477 if (check_movement_keys (key
, view
->data_area
.height
+ 1, view
,
478 mcview_cmk_move_up
, mcview_cmk_move_down
,
479 mcview_cmk_moveto_top
, mcview_cmk_moveto_bottom
))
482 #ifdef MC_ENABLE_DEBUGGING_CODE
484 { /* mnemonic: "test" */
485 mcview_ccache_dump (view
);
489 if (key
>= '0' && key
<= '9')
490 view
->marker
= key
- '0';
493 return MSG_NOT_HANDLED
;
497 /* --------------------------------------------------------------------------------------------- */
500 mcview_adjust_size (Dlg_head
* h
)
505 /* Look up the viewer and the buttonbar, we assume only two widgets here */
506 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
507 b
= find_buttonbar (h
);
509 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
510 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
512 mcview_compute_areas (view
);
513 mcview_update_bytes_per_line (view
);
517 /* --------------------------------------------------------------------------------------------- */
519 /*** public functions ****************************************************************************/
521 /* --------------------------------------------------------------------------------------------- */
524 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
526 mcview_t
*view
= (mcview_t
*) w
;
528 Dlg_head
*h
= view
->widget
.parent
;
530 mcview_compute_areas (view
);
531 mcview_update_bytes_per_line (view
);
536 if (mcview_is_in_panel (view
))
537 add_hook (&select_file_hook
, mcview_hook
, view
);
539 view
->dpy_bbar_dirty
= TRUE
;
543 mcview_display (view
);
548 mcview_place_cursor (view
);
552 i
= mcview_handle_key (view
, parm
);
553 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
556 mcview_update (view
);
560 i
= mcview_execute_cmd (view
, parm
);
561 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
564 mcview_update (view
);
568 view
->dpy_bbar_dirty
= TRUE
;
569 mcview_update (view
);
574 if (mcview_is_in_panel (view
))
575 delete_hook (&select_file_hook
, mcview_hook
);
579 return default_proc (msg
, parm
);
583 /* --------------------------------------------------------------------------------------------- */
586 mcview_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
588 mcview_t
*view
= data
;
593 mcview_adjust_size (h
);
597 /* command from buttonbar */
598 return send_message ((Widget
*) view
, WIDGET_COMMAND
, parm
);
601 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
605 /* --------------------------------------------------------------------------------------------- */