2 Internal file viewer for the Midnight Commander
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,
42 #include "../src/global.h"
44 #include "../src/tty/tty.h"
46 #include "../src/strutil.h"
47 #include "../src/main.h"
48 #include "../src/charsets.h"
49 #include "../src/main-widgets.h" /* the_menubar */
50 #include "../src/menu.h" /* menubar_visible */
55 /*** global variables ****************************************************************************/
57 int mcview_default_hex_mode
= 0;
58 int mcview_default_nroff_flag
= 0;
59 int mcview_global_wrap_mode
= 1;
60 int mcview_default_magic_flag
= 1;
62 int mcview_altered_hex_mode
= 0;
63 int mcview_altered_magic_flag
= 0;
64 int mcview_altered_nroff_flag
= 0;
66 int mcview_remember_file_position
= FALSE
;
68 /* Maxlimit for skipping updates */
69 int mcview_max_dirt_limit
= 10;
71 /* Scrolling is done in pages or line increments */
72 int mcview_mouse_move_pages
= 1;
75 /*** file scope macro definitions ****************************************************************/
77 /*** file scope type declarations ****************************************************************/
79 /*** file scope variables ************************************************************************/
82 /*** file scope functions ************************************************************************/
84 /* --------------------------------------------------------------------------------------------- */
88 mcview_event (mcview_t
*view
, Gpm_Event
*event
, int *result
)
94 /* rest of the upper frame, the menu is invisible - call menu */
95 if (mcview_is_in_panel (view
) && (event
->type
& GPM_DOWN
)
96 && event
->y
== 1 && !menubar_visible
) {
97 event
->x
+= view
->widget
.x
;
98 *result
= the_menubar
->widget
.mouse (event
, the_menubar
);
99 return 0; /* don't draw viewer over menu */
102 /* We are not interested in the release events */
103 if (!(event
->type
& (GPM_DOWN
| GPM_DRAG
)))
107 if ((event
->buttons
& GPM_B_UP
) && (event
->type
& GPM_DOWN
)) {
108 mcview_move_up (view
, 2);
111 if ((event
->buttons
& GPM_B_DOWN
) && (event
->type
& GPM_DOWN
)) {
112 mcview_move_down (view
, 2);
119 /* Scrolling left and right */
120 if (!view
->text_wrap_mode
) {
121 if (x
< view
->data_area
.width
* 1 / 4) {
122 mcview_move_left (view
, 1);
124 } else if (x
< view
->data_area
.width
* 3 / 4) {
125 /* ignore the click */
127 mcview_move_right (view
, 1);
132 /* Scrolling up and down */
133 if (y
< view
->data_area
.top
+ view
->data_area
.height
* 1 / 3) {
134 if (mcview_mouse_move_pages
)
135 mcview_move_up (view
, view
->data_area
.height
/ 2);
137 mcview_move_up (view
, 1);
139 } else if (y
< view
->data_area
.top
+ view
->data_area
.height
* 2 / 3) {
140 /* ignore the click */
142 if (mcview_mouse_move_pages
)
143 mcview_move_down (view
, view
->data_area
.height
/ 2);
145 mcview_move_down (view
, 1);
152 *result
= MOU_REPEAT
;
156 /* --------------------------------------------------------------------------------------------- */
160 mcview_real_event (Gpm_Event
* event
, void *x
)
162 mcview_t
*view
= (mcview_t
*) x
;
165 if (mcview_event (view
, event
, &result
))
166 mcview_update (view
);
170 /* --------------------------------------------------------------------------------------------- */
172 /*** public functions ****************************************************************************/
174 /* --------------------------------------------------------------------------------------------- */
177 mcview_new (int y
, int x
, int cols
, int lines
, int is_panel
)
179 mcview_t
*view
= g_new0 (mcview_t
, 1);
182 init_widget (&view
->widget
, y
, x
, lines
, cols
, mcview_callback
, mcview_real_event
);
184 view
->filename
= NULL
;
185 view
->command
= NULL
;
186 view
->search_nroff_seq
= NULL
;
188 mcview_set_datasource_none (view
);
190 view
->growbuf_in_use
= FALSE
;
191 /* leave the other growbuf fields uninitialized */
193 view
->hex_mode
= FALSE
;
194 view
->hexedit_mode
= FALSE
;
195 view
->hexview_in_text
= FALSE
;
196 view
->text_nroff_mode
= FALSE
;
197 view
->text_wrap_mode
= FALSE
;
198 view
->magic_mode
= FALSE
;
201 view
->hexedit_lownibble
= FALSE
;
202 view
->coord_cache
= NULL
;
204 view
->dpy_frame_size
= is_panel
? 1 : 0;
206 view
->dpy_text_column
= 0;
208 view
->hex_cursor
= 0;
209 view
->cursor_col
= 0;
210 view
->cursor_row
= 0;
211 view
->change_list
= NULL
;
212 view
->converter
= str_cnv_from_term
;
214 mcview_set_codeset (view
);
216 /* {status,ruler,data}_area are left uninitialized */
219 view
->dpy_bbar_dirty
= TRUE
;
220 view
->bytes_per_line
= 1;
222 view
->search_start
= 0;
223 view
->search_end
= 0;
225 view
->want_to_quit
= FALSE
;
227 for (i
= 0; i
< sizeof (view
->marks
) / sizeof (view
->marks
[0]); i
++)
231 view
->update_steps
= 0;
232 view
->update_activate
= 0;
234 if (mcview_default_hex_mode
)
235 mcview_toggle_hex_mode (view
);
236 if (mcview_default_nroff_flag
)
237 mcview_toggle_nroff_mode (view
);
238 if (mcview_global_wrap_mode
)
239 mcview_toggle_wrap_mode (view
);
240 if (mcview_default_magic_flag
)
241 mcview_toggle_magic_mode (view
);
246 /* --------------------------------------------------------------------------------------------- */
250 mcview_viewer (const char *command
, const char *file
, int *move_dir_p
, int start_line
)
257 /* Create dialog and widgets, put them on the dialog */
259 create_dlg (0, 0, LINES
, COLS
, NULL
, mcview_dialog_callback
,
260 "[Internal File Viewer]", NULL
, DLG_WANT_TAB
);
262 mcview_t
= mcview_new (0, 0, COLS
, LINES
- 1, 0);
264 bar
= buttonbar_new (1);
266 add_widget (view_dlg
, bar
);
267 add_widget (view_dlg
, mcview_t
);
269 succeeded
= mcview_load (mcview_t
, command
, file
, start_line
);
273 *move_dir_p
= mcview_t
->move_dir
;
278 destroy_dlg (view_dlg
);
283 /* {{{ Miscellaneous functions }}} */
285 /* --------------------------------------------------------------------------------------------- */
288 mcview_load (mcview_t
* view
, const char *command
, const char *file
, int start_line
)
292 char tmp
[BUF_MEDIUM
];
296 gboolean retval
= FALSE
;
298 assert (view
->bytes_per_line
!= 0);
301 /* Set up the state */
302 mcview_set_datasource_none (view
);
303 view
->filename
= g_strdup (file
);
306 /* Clear the markers */
308 for (i
= 0; i
< 10; i
++)
311 if (!mcview_is_in_panel (view
)) {
312 view
->dpy_text_column
= 0;
315 if (command
&& (view
->magic_mode
|| file
== NULL
|| file
[0] == '\0')) {
316 retval
= mcview_load_command_output (view
, command
);
317 } else if (file
!= NULL
&& file
[0] != '\0') {
319 if ((fd
= mc_open (file
, O_RDONLY
| O_NONBLOCK
)) == -1) {
320 g_snprintf (tmp
, sizeof (tmp
), _(" Cannot open \"%s\"\n %s "),
321 file
, unix_error_string (errno
));
322 mcview_show_error (view
, tmp
);
323 g_free (view
->filename
);
324 view
->filename
= NULL
;
328 /* Make sure we are working with a regular file */
329 if (mc_fstat (fd
, &st
) == -1) {
331 g_snprintf (tmp
, sizeof (tmp
), _(" Cannot stat \"%s\"\n %s "),
332 file
, unix_error_string (errno
));
333 mcview_show_error (view
, tmp
);
334 g_free (view
->filename
);
335 view
->filename
= NULL
;
339 if (!S_ISREG (st
.st_mode
)) {
341 mcview_show_error (view
, _(" Cannot view: not a regular file "));
342 g_free (view
->filename
);
343 view
->filename
= NULL
;
347 if (st
.st_size
== 0 || mc_lseek (fd
, 0, SEEK_SET
) == -1) {
348 /* Must be one of those nice files that grow (/proc) */
349 mcview_set_datasource_vfs_pipe (view
, fd
);
351 type
= get_compression_type (fd
, file
);
353 if (view
->magic_mode
&& (type
!= COMPRESSION_NONE
)) {
354 g_free (view
->filename
);
355 view
->filename
= g_strconcat (file
, decompress_extension (type
), (char *) NULL
);
357 mcview_set_datasource_file (view
, fd
, &st
);
363 view
->command
= g_strdup (command
);
365 view
->search_start
= 0;
366 view
->search_end
= 0;
367 view
->dpy_text_column
= 0;
369 mcview_compute_areas (view
);
370 assert (view
->bytes_per_line
!= 0);
371 if (mcview_remember_file_position
&& view
->filename
!= NULL
&& start_line
== 0) {
374 canon_fname
= vfs_canon (view
->filename
);
375 load_file_position (canon_fname
, &line
, &col
);
376 g_free (canon_fname
);
377 mcview_moveto (view
, mcview_offset_doz (line
, 1), col
);
378 } else if (start_line
> 0) {
379 mcview_moveto (view
, start_line
- 1, 0);
382 view
->hexedit_lownibble
= FALSE
;
383 view
->hexview_in_text
= FALSE
;
384 view
->change_list
= NULL
;
388 /* --------------------------------------------------------------------------------------------- */