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/filemanager/layout.h"
62 #include "src/filemanager/cmd.h"
63 #include "src/filemanager/midnight.h" /* current_panel */
65 #include "src/history.h"
66 #include "src/execute.h"
68 #include "src/keybind-defaults.h"
69 #include "src/main.h" /* midnight_shutdown */
74 /*** global variables ****************************************************************************/
76 /*** file scope macro definitions ****************************************************************/
78 /*** file scope type declarations ****************************************************************/
80 /*** file scope variables ************************************************************************/
82 /*** file scope functions ************************************************************************/
83 /* --------------------------------------------------------------------------------------------- */
87 mcview_search (mcview_t
* view
)
89 if (mcview_dialog_search (view
))
90 mcview_do_search (view
);
93 /* --------------------------------------------------------------------------------------------- */
96 mcview_continue_search_cmd (mcview_t
* view
)
98 if (view
->last_search_string
!= NULL
)
100 mcview_do_search (view
);
104 /* find last search string in history */
106 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
107 if (history
!= NULL
&& history
->data
!= NULL
)
109 view
->last_search_string
= (gchar
*) g_strdup (history
->data
);
110 history
= g_list_first (history
);
111 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
112 g_list_free (history
);
114 view
->search
= mc_search_new (view
->last_search_string
, -1);
115 view
->search_nroff_seq
= mcview_nroff_seq_new (view
);
119 /* if not... then ask for an expression */
120 g_free (view
->last_search_string
);
121 view
->last_search_string
= NULL
;
122 mcview_search (view
);
126 view
->search
->search_type
= mcview_search_options
.type
;
127 view
->search
->is_all_charsets
= mcview_search_options
.all_codepages
;
128 view
->search
->is_case_sensitive
= mcview_search_options
.case_sens
;
129 view
->search
->whole_words
= mcview_search_options
.whole_words
;
130 view
->search
->search_fn
= mcview_search_cmd_callback
;
131 view
->search
->update_fn
= mcview_search_update_cmd_callback
;
133 mcview_do_search (view
);
138 /* if not... then ask for an expression */
139 g_free (view
->last_search_string
);
140 view
->last_search_string
= NULL
;
141 mcview_search (view
);
146 /* --------------------------------------------------------------------------------------------- */
149 mcview_hook (void *v
)
151 mcview_t
*view
= (mcview_t
*) v
;
154 /* If the user is busy typing, wait until he finishes to update the
158 if (!hook_present (idle_hook
, mcview_hook
))
159 add_hook (&idle_hook
, mcview_hook
, v
);
163 delete_hook (&idle_hook
, mcview_hook
);
165 if (get_current_type () == view_listing
)
166 panel
= current_panel
;
167 else if (get_other_type () == view_listing
)
174 mcview_load (view
, 0, panel
->dir
.list
[panel
->selected
].fname
, 0);
175 mcview_display (view
);
178 /* --------------------------------------------------------------------------------------------- */
181 mcview_handle_editkey (mcview_t
* view
, int key
)
183 struct hexedit_change_node
*node
;
186 /* Has there been a change at this position? */
187 node
= view
->change_list
;
188 while ((node
!= NULL
) && (node
->offset
!= view
->hex_cursor
))
191 if (!view
->hexview_in_text
)
194 unsigned int hexvalue
= 0;
196 if (key
>= '0' && key
<= '9')
197 hexvalue
= 0 + (key
- '0');
198 else if (key
>= 'A' && key
<= 'F')
199 hexvalue
= 10 + (key
- 'A');
200 else if (key
>= 'a' && key
<= 'f')
201 hexvalue
= 10 + (key
- 'a');
203 return MSG_NOT_HANDLED
;
206 byte_val
= node
->value
;
208 mcview_get_byte (view
, view
->hex_cursor
, &byte_val
);
210 if (view
->hexedit_lownibble
)
211 byte_val
= (byte_val
& 0xf0) | (hexvalue
);
213 byte_val
= (byte_val
& 0x0f) | (hexvalue
<< 4);
218 if (key
< 256 && ((key
== '\n') || is_printable (key
)))
221 return MSG_NOT_HANDLED
;
224 if ((view
->filename
!= NULL
) && (view
->filename
[0] != '\0') && (view
->change_list
== NULL
))
225 view
->locked
= mcview_lock_file (view
);
229 node
= g_new (struct hexedit_change_node
, 1);
230 node
->offset
= view
->hex_cursor
;
231 node
->value
= byte_val
;
232 mcview_enqueue_change (&view
->change_list
, node
);
235 node
->value
= byte_val
;
238 mcview_move_right (view
, 1);
243 /* --------------------------------------------------------------------------------------------- */
246 mcview_execute_cmd (mcview_t
* view
, unsigned long command
)
248 int res
= MSG_HANDLED
;
253 interactive_display (NULL
, "[Internal File Viewer]");
255 case CK_ViewToggleWrapMode
:
256 /* Toggle between wrapped and unwrapped view */
257 mcview_toggle_wrap_mode (view
);
259 case CK_ViewToggleHexEditMode
:
260 /* Toggle between hexview and hexedit mode */
261 mcview_toggle_hexedit_mode (view
);
263 case CK_ViewToggleHexMode
:
264 /* Toggle between hex view and text view */
265 mcview_toggle_hex_mode (view
);
271 if (mcview_dialog_goto (view
, &addr
))
274 mcview_moveto_offset (view
, addr
);
277 message (D_ERROR
, _("Warning"), _("Invalid value"));
283 case CK_ViewHexEditSave
:
284 mcview_hexedit_save_changes (view
);
287 mcview_search (view
);
289 case CK_ViewToggleMagicMode
:
290 mcview_toggle_magic_mode (view
);
292 case CK_ViewToggleNroffMode
:
293 mcview_toggle_nroff_mode (view
);
295 case CK_ViewToggleHexNavMode
:
296 view
->hexview_in_text
= !view
->hexview_in_text
;
299 case CK_ViewMoveToBol
:
300 mcview_moveto_bol (view
);
302 case CK_ViewMoveToEol
:
303 mcview_moveto_eol (view
);
305 case CK_ViewMoveLeft
:
306 mcview_move_left (view
, 1);
308 case CK_ViewMoveRight
:
309 mcview_move_right (view
, 1);
311 case CK_ViewMoveLeft10
:
313 mcview_move_left (view
, 10);
315 case CK_ViewMoveRight10
:
317 mcview_move_right (view
, 10);
319 case CK_ViewContinueSearch
:
320 mcview_continue_search_cmd (view
);
322 case CK_ViewToggleRuler
:
323 mcview_display_toggle_ruler (view
);
326 mcview_move_up (view
, 1);
328 case CK_ViewMoveDown
:
329 mcview_move_down (view
, 1);
331 case CK_ViewMoveHalfPgUp
:
332 mcview_move_up (view
, (view
->data_area
.height
+ 1) / 2);
334 case CK_ViewMoveHalfPgDn
:
335 mcview_move_down (view
, (view
->data_area
.height
+ 1) / 2);
337 case CK_ViewMovePgUp
:
338 mcview_move_up (view
, view
->data_area
.height
);
340 case CK_ViewMovePgDn
:
341 mcview_move_down (view
, view
->data_area
.height
);
344 mcview_moveto_top (view
);
346 case CK_ViewMoveBottom
:
347 mcview_moveto_bottom (view
);
349 case CK_ShowCommandLine
:
353 // Unlike Ctrl-O, run a new shell if the subshell is not running
358 case CK_ViewGotoBookmark
:
359 view
->marks
[view
->marker
] = view
->dpy_start
;
361 case CK_ViewNewBookmark
:
362 view
->dpy_start
= view
->marks
[view
->marker
];
365 case CK_SelectCodepage
:
366 mcview_select_encoding (view
);
369 case CK_ViewNextFile
:
370 case CK_ViewPrevFile
:
371 /* Use to indicate parent that we want to see the next/previous file */
372 /* Does not work in panel mode */
373 if (!mcview_is_in_panel (view
))
374 view
->move_dir
= (command
== CK_ViewNextFile
) ? 1 : -1;
377 if (!mcview_is_in_panel (view
))
378 dlg_stop (view
->widget
.owner
);
381 res
= MSG_NOT_HANDLED
;
386 /* --------------------------------------------------------------------------------------------- */
389 mcview_handle_key (mcview_t
* view
, int key
)
391 unsigned long command
;
393 key
= convert_from_input_c (key
);
397 if (view
->hexedit_mode
&& (mcview_handle_editkey (view
, key
) == MSG_HANDLED
))
400 command
= keybind_lookup_keymap_command (view
->hex_map
, key
);
401 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
405 command
= keybind_lookup_keymap_command (view
->plain_map
, key
);
406 if ((command
!= CK_Ignore_Key
) && (mcview_execute_cmd (view
, command
) == MSG_HANDLED
))
409 #ifdef MC_ENABLE_DEBUGGING_CODE
411 { /* mnemonic: "test" */
412 mcview_ccache_dump (view
);
416 if (key
>= '0' && key
<= '9')
417 view
->marker
= key
- '0';
420 return MSG_NOT_HANDLED
;
424 /* --------------------------------------------------------------------------------------------- */
427 mcview_adjust_size (Dlg_head
* h
)
432 /* Look up the viewer and the buttonbar, we assume only two widgets here */
433 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
434 b
= find_buttonbar (h
);
436 widget_set_size (&view
->widget
, 0, 0, LINES
- 1, COLS
);
437 widget_set_size (&b
->widget
, LINES
- 1, 0, 1, COLS
);
439 mcview_compute_areas (view
);
440 mcview_update_bytes_per_line (view
);
444 /* --------------------------------------------------------------------------------------------- */
445 /*** public functions ****************************************************************************/
446 /* --------------------------------------------------------------------------------------------- */
449 mcview_callback (Widget
* w
, widget_msg_t msg
, int parm
)
451 mcview_t
*view
= (mcview_t
*) w
;
454 mcview_compute_areas (view
);
455 mcview_update_bytes_per_line (view
);
460 if (mcview_is_in_panel (view
))
461 add_hook (&select_file_hook
, mcview_hook
, view
);
463 view
->dpy_bbar_dirty
= TRUE
;
467 mcview_display (view
);
472 mcview_place_cursor (view
);
476 i
= mcview_handle_key (view
, parm
);
477 mcview_update (view
);
481 i
= mcview_execute_cmd (view
, parm
);
482 mcview_update (view
);
486 view
->dpy_bbar_dirty
= TRUE
;
487 mcview_update (view
);
491 if (mcview_is_in_panel (view
))
493 delete_hook (&select_file_hook
, mcview_hook
);
495 if (midnight_shutdown
)
496 mcview_ok_to_quit (view
);
502 return default_proc (msg
, parm
);
506 /* --------------------------------------------------------------------------------------------- */
509 mcview_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
516 mcview_adjust_size (h
);
520 /* command from buttonbar */
521 view
= (mcview_t
*) data
;
522 return send_message ((Widget
*) view
, WIDGET_COMMAND
, parm
);
525 view
= (mcview_t
*) find_widget_type (h
, mcview_callback
);
526 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
527 if (mcview_ok_to_quit (view
))
528 h
->state
= DLG_CLOSED
;
530 mcview_update (view
);
534 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
538 /* --------------------------------------------------------------------------------------------- */