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"
61 #include "src/panel.h"
62 #include "src/layout.h"
63 #include "src/history.h"
65 #include "src/execute.h"
67 #include "src/keybind-defaults.h"
68 #include "src/main.h" /* midnight_shutdown */
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
;
252 interactive_display (NULL
, "[Internal File Viewer]");
254 case CK_ViewToggleWrapMode
:
255 /* Toggle between wrapped and unwrapped view */
256 mcview_toggle_wrap_mode (view
);
258 case CK_ViewToggleHexEditMode
:
259 /* Toggle between hexview and hexedit mode */
260 mcview_toggle_hexedit_mode (view
);
262 case CK_ViewToggleHexMode
:
263 /* Toggle between hex view and text view */
264 mcview_toggle_hex_mode (view
);
270 if (mcview_dialog_goto (view
, &addr
))
273 mcview_moveto_offset (view
, addr
);
276 message (D_ERROR
, _("Warning"), _("Invalid value"));
282 case CK_ViewHexEditSave
:
283 mcview_hexedit_save_changes (view
);
286 mcview_search (view
);
288 case CK_ViewToggleMagicMode
:
289 mcview_toggle_magic_mode (view
);
291 case CK_ViewToggleNroffMode
:
292 mcview_toggle_nroff_mode (view
);
294 case CK_ViewToggleHexNavMode
:
295 view
->hexview_in_text
= !view
->hexview_in_text
;
298 case CK_ViewMoveToBol
:
299 mcview_moveto_bol (view
);
301 case CK_ViewMoveToEol
:
302 mcview_moveto_eol (view
);
304 case CK_ViewMoveLeft
:
305 mcview_move_left (view
, 1);
307 case CK_ViewMoveRight
:
308 mcview_move_right (view
, 1);
310 case CK_ViewMoveLeft10
:
312 mcview_move_left (view
, 10);
314 case CK_ViewMoveRight10
:
316 mcview_move_right (view
, 10);
318 case CK_ViewContinueSearch
:
319 mcview_continue_search_cmd (view
);
321 case CK_ViewToggleRuler
:
322 mcview_display_toggle_ruler (view
);
325 mcview_move_up (view
, 1);
327 case CK_ViewMoveDown
:
328 mcview_move_down (view
, 1);
330 case CK_ViewMoveHalfPgUp
:
331 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
333 case CK_ViewMoveHalfPgDn
:
334 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
336 case CK_ViewMovePgUp
:
337 mcview_move_up (view
, view
->data_area
.height
);
339 case CK_ViewMovePgDn
:
340 mcview_move_down (view
, view
->data_area
.height
);
343 mcview_moveto_top (view
);
345 case CK_ViewMoveBottom
:
346 mcview_moveto_bottom (view
);
348 case CK_ShowCommandLine
:
352 // Unlike Ctrl-O, run a new shell if the subshell is not running
357 case CK_ViewGotoBookmark
:
358 view
->marks
[view
->marker
] = view
->dpy_start
;
360 case CK_ViewNewBookmark
:
361 view
->dpy_start
= view
->marks
[view
->marker
];
364 case CK_SelectCodepage
:
365 mcview_select_encoding (view
);
368 case CK_ViewNextFile
:
369 case CK_ViewPrevFile
:
370 /* Use to indicate parent that we want to see the next/previous file */
371 /* Does not work in panel mode */
372 if (!mcview_is_in_panel (view
))
373 view
->move_dir
= (command
== CK_ViewNextFile
) ? 1 : -1;
376 if (!mcview_is_in_panel (view
))
377 dlg_stop (view
->widget
.owner
);
380 res
= MSG_NOT_HANDLED
;
385 /* --------------------------------------------------------------------------------------------- */
388 mcview_handle_key (mcview_t
* view
, int key
)
390 unsigned long command
;
392 key
= convert_from_input_c (key
);
396 if (view
->hexedit_mode
&& (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
399 command
= keybind_lookup_keymap_command (view
->hex_map
, key
);
400 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
404 command
= keybind_lookup_keymap_command (view
->plain_map
, key
);
405 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
408 #ifdef MC_ENABLE_DEBUGGING_CODE
410 { /* mnemonic: "test" */
411 mcview_ccache_dump (view
);
415 if (key
>= '0' && key
<= '9')
416 view
->marker
= key
- '0';
419 return MSG_NOT_HANDLED
;
423 /* --------------------------------------------------------------------------------------------- */
426 mcview_adjust_size (Dlg_head
* h
)
431 /* Look up the viewer and the buttonbar, we assume only two widgets here */
432 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
433 b
= find_buttonbar (h
);
435 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
436 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
438 mcview_compute_areas (view
);
439 mcview_update_bytes_per_line (view
);
443 /* --------------------------------------------------------------------------------------------- */
444 /*** public functions ****************************************************************************/
445 /* --------------------------------------------------------------------------------------------- */
448 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
450 mcview_t
*view
= (mcview_t
*) w
;
453 mcview_compute_areas (view
);
454 mcview_update_bytes_per_line (view
);
459 if (mcview_is_in_panel (view
))
460 add_hook (&select_file_hook
, mcview_hook
, view
);
462 view
->dpy_bbar_dirty
= TRUE
;
466 mcview_display (view
);
471 mcview_place_cursor (view
);
475 i
= mcview_handle_key (view
, parm
);
476 mcview_update (view
);
480 i
= mcview_execute_cmd (view
, parm
);
481 mcview_update (view
);
485 view
->dpy_bbar_dirty
= TRUE
;
486 mcview_update (view
);
490 if (mcview_is_in_panel (view
))
492 delete_hook (&select_file_hook
, mcview_hook
);
494 if (midnight_shutdown
)
495 mcview_ok_to_quit (view
);
501 return default_proc (msg
, parm
);
505 /* --------------------------------------------------------------------------------------------- */
508 mcview_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
515 mcview_adjust_size (h
);
519 /* command from buttonbar */
520 view
= (mcview_t
*) data
;
521 return send_message ((Widget
*) view
, WIDGET_COMMAND
, parm
);
524 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
525 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
526 if (mcview_ok_to_quit (view
))
527 h
->state
= DLG_CLOSED
;
529 mcview_update (view
);
533 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
537 /* --------------------------------------------------------------------------------------------- */