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 "../src/global.h"
53 #include "../src/panel.h"
54 #include "../src/layout.h"
55 #include "../src/wtools.h"
56 #include "../src/history.h"
57 #include "../src/charsets.h"
58 #include "../src/tty/tty.h"
59 #include "../src/tty/key.h"
60 #include "../src/cmd.h"
61 #include "../src/execute.h"
62 #include "../src/help.h"
66 /*** global variables ****************************************************************************/
68 /*** file scope macro definitions ****************************************************************/
70 /*** file scope type declarations ****************************************************************/
72 /*** file scope variables ************************************************************************/
74 /*** file scope functions ************************************************************************/
76 /* --------------------------------------------------------------------------------------------- */
79 mcview_continue_search_cmd (mcview_t
* view
)
81 if (view
->last_search_string
!= NULL
) {
82 mcview_do_search (view
);
84 /* if not... then ask for an expression */
85 mcview_search_cmd (view
);
89 /* --------------------------------------------------------------------------------------------- */
91 mcview_handle_editkey (mcview_t
* view
, int key
)
93 struct hexedit_change_node
*node
;
96 /* Has there been a change at this position? */
97 node
= view
->change_list
;
98 while (node
&& (node
->offset
!= view
->hex_cursor
))
101 if (!view
->hexview_in_text
) {
103 unsigned int hexvalue
= 0;
105 if (key
>= '0' && key
<= '9')
106 hexvalue
= 0 + (key
- '0');
107 else if (key
>= 'A' && key
<= 'F')
108 hexvalue
= 10 + (key
- 'A');
109 else if (key
>= 'a' && key
<= 'f')
110 hexvalue
= 10 + (key
- 'a');
112 return MSG_NOT_HANDLED
;
115 byte_val
= node
->value
;
117 mcview_get_byte (view
, view
->hex_cursor
, &byte_val
);
119 if (view
->hexedit_lownibble
) {
120 byte_val
= (byte_val
& 0xf0) | (hexvalue
);
122 byte_val
= (byte_val
& 0x0f) | (hexvalue
<< 4);
126 if (key
< 256 && ((key
== '\n') || is_printable (key
)))
129 return MSG_NOT_HANDLED
;
132 node
= g_new (struct hexedit_change_node
, 1);
133 node
->offset
= view
->hex_cursor
;
134 node
->value
= byte_val
;
135 mcview_enqueue_change (&view
->change_list
, node
);
137 node
->value
= byte_val
;
140 mcview_update (view
);
141 mcview_move_right (view
, 1);
145 /* --------------------------------------------------------------------------------------------- */
147 /* Check for left and right arrows, possibly with modifiers */
149 mcview_check_left_right_keys (mcview_t
* view
, int c
)
152 mcview_move_left (view
, 1);
156 if (c
== KEY_RIGHT
) {
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
)) {
166 if (view
->dpy_text_column
>= 10)
167 view
->dpy_text_column
-= 10;
169 view
->dpy_text_column
= 0;
174 if (c
== (KEY_M_CTRL
| KEY_RIGHT
)) {
175 if (view
->dpy_text_column
<= OFFSETTYPE_MAX
- 10)
176 view
->dpy_text_column
+= 10;
178 view
->dpy_text_column
= OFFSETTYPE_MAX
;
183 return MSG_NOT_HANDLED
;
186 /* --------------------------------------------------------------------------------------------- */
189 mcview_cmk_move_up (void *w
, int n
)
191 mcview_move_up ((mcview_t
*) w
, n
);
194 /* --------------------------------------------------------------------------------------------- */
197 mcview_cmk_move_down (void *w
, int n
)
199 mcview_move_down ((mcview_t
*) w
, n
);
202 /* --------------------------------------------------------------------------------------------- */
205 mcview_cmk_moveto_top (void *w
, int n
)
208 mcview_moveto_top ((mcview_t
*) w
);
211 /* --------------------------------------------------------------------------------------------- */
214 mcview_cmk_moveto_bottom (void *w
, int n
)
217 mcview_moveto_bottom ((mcview_t
*) w
);
220 /* --------------------------------------------------------------------------------------------- */
223 mcview_hook (void *v
)
225 mcview_t
*view
= (mcview_t
*) v
;
228 /* If the user is busy typing, wait until he finishes to update the
231 if (!hook_present (idle_hook
, mcview_hook
))
232 add_hook (&idle_hook
, mcview_hook
, v
);
236 delete_hook (&idle_hook
, mcview_hook
);
238 if (get_current_type () == view_listing
)
239 panel
= current_panel
;
240 else if (get_other_type () == view_listing
)
245 mcview_load (view
, 0, panel
->dir
.list
[panel
->selected
].fname
, 0);
246 mcview_display (view
);
249 /* --------------------------------------------------------------------------------------------- */
253 mcview_handle_key (mcview_t
* view
, int c
)
255 c
= convert_from_input_c (c
);
257 if (view
->hex_mode
) {
260 view
->hexview_in_text
= !view
->hexview_in_text
;
265 mcview_moveto_bol (view
);
270 mcview_move_left (view
, 1);
274 mcview_moveto_eol (view
);
278 mcview_move_right (view
, 1);
282 if (view
->hexedit_mode
&& mcview_handle_editkey (view
, c
) == MSG_HANDLED
)
286 if (mcview_check_left_right_keys (view
, c
))
289 if (check_movement_keys (c
, view
->data_area
.height
+ 1, view
,
290 mcview_cmk_move_up
, mcview_cmk_move_down
,
291 mcview_cmk_moveto_top
, mcview_cmk_moveto_bottom
))
298 view
->search_type
= MC_SEARCH_T_REGEX
;
299 mcview_search_cmd (view
);
302 /* Continue search */
307 mcview_continue_search_cmd (view
);
312 mcview_toggle_ruler_cmd (view
);
316 mcview_move_left (view
, 1);
322 mcview_move_down (view
, 1);
326 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
330 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
335 mcview_move_up (view
, 1);
339 mcview_move_right (view
, 1);
344 mcview_move_down (view
, view
->data_area
.height
);
351 /* Unlike Ctrl-O, run a new shell if the subshell is not running. */
357 mcview_move_up (view
, view
->data_area
.height
);
361 mcview_move_up (view
, 2);
365 mcview_move_down (view
, 2);
369 view
->marks
[view
->marker
] = view
->dpy_start
;
373 view
->dpy_start
= view
->marks
[view
->marker
];
377 /* Use to indicate parent that we want to see the next/previous file */
378 /* Does not work in panel mode */
381 if (!mcview_is_in_panel (view
))
382 view
->move_dir
= c
== XCTRL ('f') ? 1 : -1;
387 if (mcview_ok_to_quit (view
))
388 view
->want_to_quit
= TRUE
;
392 mcview_select_encoding (view
);
394 mcview_update (view
);
397 #ifdef MC_ENABLE_DEBUGGING_CODE
398 case 't': /* mnemonic: "test" */
399 mcview_ccache_dump (view
);
403 if (c
>= '0' && c
<= '9')
404 view
->marker
= c
- '0';
407 return MSG_NOT_HANDLED
;
410 /* --------------------------------------------------------------------------------------------- */
412 /*** public functions ****************************************************************************/
414 /* --------------------------------------------------------------------------------------------- */
417 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
419 mcview_t
*view
= (mcview_t
*) w
;
421 Dlg_head
*h
= view
->widget
.parent
;
423 mcview_compute_areas (view
);
424 mcview_update_bytes_per_line (view
);
428 if (mcview_is_in_panel (view
))
429 add_hook (&select_file_hook
, mcview_hook
, view
);
431 view
->dpy_bbar_dirty
= TRUE
;
435 mcview_display (view
);
440 mcview_place_cursor (view
);
444 i
= mcview_handle_key ((mcview_t
*) view
, parm
);
445 if (view
->want_to_quit
&& !mcview_is_in_panel (view
))
448 mcview_update (view
);
453 view
->dpy_bbar_dirty
= TRUE
;
454 mcview_update (view
);
459 if (mcview_is_in_panel (view
))
460 delete_hook (&select_file_hook
, mcview_hook
);
464 return default_proc (msg
, parm
);
468 /* --------------------------------------------------------------------------------------------- */
471 mcview_dialog_callback (Dlg_head
* h
, dlg_msg_t msg
, int parm
)
475 mcview_adjust_size (h
);
479 return default_dlg_callback (h
, msg
, parm
);
483 /* --------------------------------------------------------------------------------------------- */
486 mcview_help_cmd (void)
488 interactive_display (NULL
, "[Internal File Viewer]");
491 /* --------------------------------------------------------------------------------------------- */
494 mcview_quit_cmd (mcview_t
* view
)
496 if (mcview_ok_to_quit (view
))
497 dlg_stop (view
->widget
.parent
);
500 /* --------------------------------------------------------------------------------------------- */
502 /* Toggle between hex view and text view */
504 mcview_toggle_hex_mode_cmd (mcview_t
* view
)
506 mcview_toggle_hex_mode (view
);
507 mcview_update (view
);
510 /* --------------------------------------------------------------------------------------------- */
513 mcview_moveto_line_cmd (mcview_t
* view
)
515 char *answer
, *answer_end
, prompt
[BUF_SMALL
];
518 mcview_offset_to_coord (view
, &line
, &col
, view
->dpy_start
);
520 g_snprintf (prompt
, sizeof (prompt
),
521 _(" The current line number is %lld.\n"
522 " Enter the new line number:"), (line
+ 1));
523 answer
= input_dialog (_(" Goto line "), prompt
, MC_HISTORY_VIEW_GOTO_LINE
, "");
524 if (answer
!= NULL
&& answer
[0] != '\0') {
526 line
= strtoul (answer
, &answer_end
, 10);
527 if (*answer_end
== '\0' && errno
== 0 && line
>= 1)
528 mcview_moveto (view
, line
- 1, 0);
532 mcview_update (view
);
535 /* --------------------------------------------------------------------------------------------- */
538 mcview_moveto_addr_cmd (mcview_t
* view
)
540 char *line
, *error
, prompt
[BUF_SMALL
], prompt_format
[BUF_SMALL
];
543 g_snprintf (prompt_format
, sizeof (prompt_format
),
544 _(" The current address is %s.\n"
545 " Enter the new address:"), "0x%08" OFFSETTYPE_PRIX
"");
546 g_snprintf (prompt
, sizeof (prompt
), prompt_format
, view
->hex_cursor
);
547 line
= input_dialog (_(" Goto Address "), prompt
, MC_HISTORY_VIEW_GOTO_ADDR
, "");
550 addr
= strtoul (line
, &error
, 0);
551 if ((*error
== '\0') && mcview_get_byte (view
, addr
, NULL
) == TRUE
) {
552 mcview_moveto_offset (view
, addr
);
554 message (D_ERROR
, _("Warning"), _(" Invalid address "));
560 mcview_update (view
);
563 /* --------------------------------------------------------------------------------------------- */
565 /* Toggle between hexview and hexedit mode */
567 mcview_toggle_hexedit_mode_cmd (mcview_t
* view
)
569 mcview_toggle_hexedit_mode (view
);
570 mcview_update (view
);
573 /* --------------------------------------------------------------------------------------------- */
576 mcview_hexedit_save_changes_cmd (mcview_t
* view
)
578 (void) mcview_hexedit_save_changes (view
);
581 /* --------------------------------------------------------------------------------------------- */
583 /* Toggle between wrapped and unwrapped view */
585 mcview_toggle_wrap_mode_cmd (mcview_t
* view
)
587 mcview_toggle_wrap_mode (view
);
588 mcview_update (view
);
591 /* --------------------------------------------------------------------------------------------- */
595 mcview_search_cmd (mcview_t
* view
)
597 if (mcview_dialog_search (view
))
598 mcview_do_search (view
);
601 /* --------------------------------------------------------------------------------------------- */
604 mcview_toggle_magic_mode_cmd (mcview_t
* view
)
606 mcview_toggle_magic_mode (view
);
607 mcview_update (view
);
610 /* --------------------------------------------------------------------------------------------- */
613 mcview_toggle_nroff_mode_cmd (mcview_t
* view
)
615 mcview_toggle_nroff_mode (view
);
616 mcview_update (view
);
619 /* --------------------------------------------------------------------------------------------- */
622 mcview_toggle_ruler_cmd (mcview_t
* view
)
624 mcview_display_toggle_ruler (view
);
627 /* --------------------------------------------------------------------------------------------- */