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
);
333 case CK_ViewToggleHexEditMode
:
334 /* Toggle between hexview and hexedit mode */
335 mcview_toggle_hexedit_mode (view
);
337 case CK_ViewToggleHexMode
:
338 /* Toggle between hex view and text view */
339 mcview_toggle_hex_mode (view
);
345 if (mcview_dialog_goto (view
, &addr
))
348 mcview_moveto_offset (view
, addr
);
351 message (D_ERROR
, _("Warning"), _("Invalid value"));
357 case CK_ViewHexEditSave
:
358 mcview_hexedit_save_changes (view
);
361 mcview_search (view
);
363 case CK_ViewToggleMagicMode
:
364 mcview_toggle_magic_mode (view
);
366 case CK_ViewToggleNroffMode
:
367 mcview_toggle_nroff_mode (view
);
370 case CK_ViewToggleHexNavMode
:
371 view
->hexview_in_text
= !view
->hexview_in_text
;
374 case CK_ViewMoveToBol
:
375 mcview_moveto_bol (view
);
377 case CK_ViewMoveToEol
:
378 mcview_moveto_eol (view
);
380 case CK_ViewMoveLeft
:
381 mcview_move_left (view
, 1);
383 case CK_ViewMoveRight
:
384 mcview_move_right (view
, 1);
386 /* Continue search */
387 case CK_ViewContinueSearch
:
388 mcview_continue_search_cmd (view
);
390 case CK_ViewToggleRuler
:
391 mcview_display_toggle_ruler (view
);
394 mcview_move_up (view
, 1);
396 case CK_ViewMoveDown
:
397 mcview_move_down (view
, 1);
399 case CK_ViewMoveHalfPgUp
:
400 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
402 case CK_ViewMoveHalfPgDn
:
403 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
405 case CK_ViewMovePgUp
:
406 mcview_move_up (view
, view
->data_area
.height
);
408 case CK_ViewMovePgDn
:
409 mcview_move_down (view
, view
->data_area
.height
);
411 case CK_ShowCommandLine
:
415 // Unlike Ctrl-O, run a new shell if the subshell is not running
420 case CK_ViewGotoBookmark
:
421 view
->marks
[view
->marker
] = view
->dpy_start
;
423 case CK_ViewNewBookmark
:
424 view
->dpy_start
= view
->marks
[view
->marker
];
427 case CK_SelectCodepage
:
428 mcview_select_encoding (view
);
431 case CK_ViewNextFile
:
432 case CK_ViewPrevFile
:
433 /* Use to indicate parent that we want to see the next/previous file */
434 /* Does not work in panel mode */
435 if (!mcview_is_in_panel (view
))
436 view
->move_dir
= (command
== CK_ViewNextFile
) ? 1 : -1;
439 if (mcview_ok_to_quit (view
))
440 view
->want_to_quit
= TRUE
;
443 res
= MSG_NOT_HANDLED
;
450 mcview_handle_key (mcview_t
* view
, int key
)
452 unsigned long command
;
454 key
= convert_from_input_c (key
);
458 if (view
->hexedit_mode
&& (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
461 command
= lookup_keymap_command (view
->hex_map
, key
);
462 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
466 command
= lookup_keymap_command (view
->plain_map
, key
);
467 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
470 if (mcview_check_left_right_keys (view
, key
) == MSG_HANDLED
)
473 if (check_movement_keys (key
, view
->data_area
.height
+ 1, view
,
474 mcview_cmk_move_up
, mcview_cmk_move_down
,
475 mcview_cmk_moveto_top
, mcview_cmk_moveto_bottom
) == MSG_HANDLED
)
478 #ifdef MC_ENABLE_DEBUGGING_CODE
480 { /* mnemonic: "test" */
481 mcview_ccache_dump (view
);
485 if (key
>= '0' && key
<= '9')
486 view
->marker
= key
- '0';
489 return MSG_NOT_HANDLED
;
493 /* --------------------------------------------------------------------------------------------- */
496 mcview_adjust_size (Dlg_head
* h
)
501 /* Look up the viewer and the buttonbar, we assume only two widgets here */
502 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
503 b
= find_buttonbar (h
);
505 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
506 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
508 mcview_compute_areas (view
);
509 mcview_update_bytes_per_line (view
);
513 /* --------------------------------------------------------------------------------------------- */
515 /*** public functions ****************************************************************************/
517 /* --------------------------------------------------------------------------------------------- */
520 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
522 mcview_t
*view
= (mcview_t
*) w
;
524 Dlg_head
*h
= view
->widget
.parent
;
526 mcview_compute_areas (view
);
527 mcview_update_bytes_per_line (view
);
532 if (mcview_is_in_panel (view
))
533 add_hook (&select_file_hook
, mcview_hook
, view
);
535 view
->dpy_bbar_dirty
= TRUE
;
539 mcview_display (view
);
544 mcview_place_cursor (view
);
548 i
= mcview_handle_key (view
, parm
);
549 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
552 mcview_update (view
);
556 i
= mcview_execute_cmd (view
, parm
);
557 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
560 mcview_update (view
);
564 view
->dpy_bbar_dirty
= TRUE
;
565 mcview_update (view
);
570 if (mcview_is_in_panel (view
))
571 delete_hook (&select_file_hook
, mcview_hook
);
575 return default_proc (msg
, parm
);
579 /* --------------------------------------------------------------------------------------------- */
582 mcview_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
584 mcview_t
*view
= data
;
589 mcview_adjust_size (h
);
593 /* command from buttonbar */
594 return send_message ((Widget
*) view
, WIDGET_COMMAND
, parm
);
597 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
601 /* --------------------------------------------------------------------------------------------- */