2 Internal file viewer for the Midnight Commander
3 Common finctions (used from some other mcviewer functions)
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009, 2011
7 The Free Software Foundation, Inc.
10 Miguel de Icaza, 1994, 1995, 1998
11 Janne Kukonlehto, 1994, 1995
13 Joseph M. Hinkle, 1996
16 Roland Illig <roland.illig@gmx.de>, 2004, 2005
17 Slava Zanko <slavazanko@google.com>, 2009
18 Andrew Borodin <aborodin@vmail.ru>, 2009
19 Ilia Maslakov <il.smind@gmail.com>, 2009
21 This file is part of the Midnight Commander.
23 The Midnight Commander is free software: you can redistribute it
24 and/or modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation, either version 3 of the License,
26 or (at your option) any later version.
28 The Midnight Commander is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program. If not, see <http://www.gnu.org/licenses/>.
40 #include <sys/types.h>
42 #include "lib/global.h"
43 #include "lib/vfs/vfs.h"
44 #include "lib/strutil.h"
45 #include "lib/util.h" /* save_file_position() */
46 #include "lib/widget.h"
48 #include "lib/charsets.h"
53 #include "src/selcodepage.h"
59 /*** global variables ****************************************************************************/
61 #define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
62 const off_t INVALID_OFFSET
= (off_t
) - 1;
63 const off_t OFFSETTYPE_MAX
= ((off_t
) 1 << (OFF_T_BITWIDTH
- 1)) - 1;
65 /*** file scope macro definitions ****************************************************************/
67 /*** file scope type declarations ****************************************************************/
69 /*** file scope variables ************************************************************************/
71 /*** file scope functions ************************************************************************/
72 /* --------------------------------------------------------------------------------------------- */
74 /* --------------------------------------------------------------------------------------------- */
75 /*** public functions ****************************************************************************/
76 /* --------------------------------------------------------------------------------------------- */
79 mcview_toggle_magic_mode (mcview_t
* view
)
81 char *filename
, *command
;
83 int *dir_count
, *dir_idx
;
85 mcview_altered_magic_flag
= 1;
86 view
->magic_mode
= !view
->magic_mode
;
89 filename
= vfs_path_to_str (view
->filename_vpath
);
90 command
= g_strdup (view
->command
);
92 dir_count
= view
->dir_count
;
93 dir_idx
= view
->dir_idx
;
95 view
->dir_count
= NULL
;
99 mcview_load (view
, command
, filename
, 0);
101 view
->dir_count
= dir_count
;
102 view
->dir_idx
= dir_idx
;
106 view
->dpy_bbar_dirty
= TRUE
;
110 /* --------------------------------------------------------------------------------------------- */
113 mcview_toggle_wrap_mode (mcview_t
* view
)
115 if (view
->text_wrap_mode
)
116 view
->dpy_start
= mcview_bol (view
, view
->dpy_start
, 0);
117 view
->text_wrap_mode
= !view
->text_wrap_mode
;
118 view
->dpy_bbar_dirty
= TRUE
;
122 /* --------------------------------------------------------------------------------------------- */
125 mcview_toggle_nroff_mode (mcview_t
* view
)
127 view
->text_nroff_mode
= !view
->text_nroff_mode
;
128 mcview_altered_nroff_flag
= 1;
129 view
->dpy_bbar_dirty
= TRUE
;
133 /* --------------------------------------------------------------------------------------------- */
136 mcview_toggle_hex_mode (mcview_t
* view
)
138 view
->hex_mode
= !view
->hex_mode
;
142 view
->hex_cursor
= view
->dpy_start
;
143 view
->dpy_start
= mcview_offset_rounddown (view
->dpy_start
, view
->bytes_per_line
);
144 widget_want_cursor (view
->widget
, 1);
148 view
->dpy_start
= mcview_bol (view
, view
->hex_cursor
, 0);
149 view
->hex_cursor
= view
->dpy_start
;
150 widget_want_cursor (view
->widget
, 0);
152 mcview_altered_hex_mode
= 1;
153 view
->dpy_bbar_dirty
= TRUE
;
157 /* --------------------------------------------------------------------------------------------- */
160 mcview_ok_to_quit (mcview_t
* view
)
164 if (view
->change_list
== NULL
)
167 if (!mc_global
.midnight_shutdown
)
170 r
= query_dialog (_("Quit"),
171 _("File was modified. Save with exit?"), D_NORMAL
, 3,
172 _("&Yes"), _("&No"), _("&Cancel quit"));
176 r
= query_dialog (_("Quit"),
177 _("Midnight Commander is being shut down.\nSave modified file?"),
178 D_NORMAL
, 2, _("&Yes"), _("&No"));
187 return mcview_hexedit_save_changes (view
) || mc_global
.midnight_shutdown
;
189 mcview_hexedit_free_change_list (view
);
196 /* --------------------------------------------------------------------------------------------- */
199 mcview_init (mcview_t
* view
)
203 view
->filename_vpath
= NULL
;
204 view
->workdir_vpath
= NULL
;
205 view
->command
= NULL
;
206 view
->search_nroff_seq
= NULL
;
208 mcview_set_datasource_none (view
);
210 view
->growbuf_in_use
= FALSE
;
211 /* leave the other growbuf fields uninitialized */
213 view
->hexedit_lownibble
= FALSE
;
214 view
->locked
= FALSE
;
215 view
->coord_cache
= NULL
;
218 view
->dpy_text_column
= 0;
220 view
->hex_cursor
= 0;
221 view
->cursor_col
= 0;
222 view
->cursor_row
= 0;
223 view
->change_list
= NULL
;
225 /* {status,ruler,data}_area are left uninitialized */
228 view
->dpy_bbar_dirty
= TRUE
;
229 view
->bytes_per_line
= 1;
231 view
->search_start
= 0;
232 view
->search_end
= 0;
235 for (i
= 0; i
< sizeof (view
->marks
) / sizeof (view
->marks
[0]); i
++)
238 view
->update_steps
= 0;
239 view
->update_activate
= 0;
241 view
->saved_bookmarks
= NULL
;
244 /* --------------------------------------------------------------------------------------------- */
247 mcview_done (mcview_t
* view
)
249 /* Save current file position */
250 if (mcview_remember_file_position
&& view
->filename_vpath
!= NULL
)
252 save_file_position (view
->filename_vpath
, -1, 0,
253 view
->hex_mode
? view
->hex_cursor
: view
->dpy_start
,
254 view
->saved_bookmarks
);
255 view
->saved_bookmarks
= NULL
;
258 /* Write back the global viewer mode */
259 mcview_default_hex_mode
= view
->hex_mode
;
260 mcview_default_nroff_flag
= view
->text_nroff_mode
;
261 mcview_default_magic_flag
= view
->magic_mode
;
262 mcview_global_wrap_mode
= view
->text_wrap_mode
;
264 /* Free memory used by the viewer */
266 /* view->widget needs no destructor */
268 vfs_path_free (view
->filename_vpath
);
269 view
->filename_vpath
= NULL
;
270 vfs_path_free (view
->workdir_vpath
);
271 view
->workdir_vpath
= NULL
;
272 g_free (view
->command
);
273 view
->command
= NULL
;
275 mcview_close_datasource (view
);
276 /* the growing buffer is freed with the datasource */
278 coord_cache_free (view
->coord_cache
), view
->coord_cache
= NULL
;
280 if (view
->converter
== INVALID_CONV
)
281 view
->converter
= str_cnv_from_term
;
283 if (view
->converter
!= str_cnv_from_term
)
285 str_close_conv (view
->converter
);
286 view
->converter
= str_cnv_from_term
;
289 mc_search_free (view
->search
);
291 g_free (view
->last_search_string
);
292 view
->last_search_string
= NULL
;
293 mcview_nroff_seq_free (&view
->search_nroff_seq
);
294 mcview_hexedit_free_change_list (view
);
296 if (mc_global
.mc_run_mode
== MC_RUN_VIEWER
&& view
->dir
!= NULL
)
298 /* mcviewer is the owner of file list */
299 clean_dir (view
->dir
, *view
->dir_count
);
300 g_free (view
->dir
->list
);
301 g_free (view
->dir_count
);
302 g_free (view
->dir_idx
);
309 /* --------------------------------------------------------------------------------------------- */
312 mcview_set_codeset (mcview_t
* view
)
315 const char *cp_id
= NULL
;
319 get_codepage_id (mc_global
.source_codepage
>=
320 0 ? mc_global
.source_codepage
: mc_global
.display_codepage
);
324 conv
= str_crt_conv_from (cp_id
);
325 if (conv
!= INVALID_CONV
)
327 if (view
->converter
!= str_cnv_from_term
)
328 str_close_conv (view
->converter
);
329 view
->converter
= conv
;
331 view
->utf8
= (gboolean
) str_isutf8 (cp_id
);
338 /* --------------------------------------------------------------------------------------------- */
342 mcview_select_encoding (mcview_t
* view
)
344 if (do_select_codepage ())
345 mcview_set_codeset (view
);
349 /* --------------------------------------------------------------------------------------------- */
352 mcview_show_error (mcview_t
* view
, const char *msg
)
354 mcview_close_datasource (view
);
355 if (mcview_is_in_panel (view
))
357 mcview_set_datasource_string (view
, msg
);
361 message (D_ERROR
, MSG_ERROR
, "%s", msg
);
365 /* --------------------------------------------------------------------------------------------- */
366 /** returns index of the first char in the line
367 * it is constant for all line characters
371 mcview_bol (mcview_t
* view
, off_t current
, off_t limit
)
375 filesize
= mcview_get_filesize (view
);
378 if (current
> filesize
)
380 if (!mcview_get_byte (view
, current
, &c
))
384 if (!mcview_get_byte (view
, current
- 1, &c
))
389 while (current
> 0 && current
>= limit
)
391 if (!mcview_get_byte (view
, current
- 1, &c
))
393 if (c
== '\r' || c
== '\n')
400 /* --------------------------------------------------------------------------------------------- */
401 /** returns index of last char on line + width EOL
402 * mcview_eol of the current line == mcview_bol next line
406 mcview_eol (mcview_t
* view
, off_t current
, off_t limit
)
410 filesize
= mcview_get_filesize (view
);
413 if (current
>= filesize
)
415 while (current
< filesize
&& current
< limit
)
417 if (!mcview_get_byte (view
, current
, &c
))
424 else if (prev_ch
== '\r')
434 /* --------------------------------------------------------------------------------------------- */
437 mcview_get_title (const Dlg_head
* h
, size_t len
)
439 const mcview_t
*view
= (const mcview_t
*) find_widget_type (h
, mcview_callback
);
440 const char *modified
= view
->hexedit_mode
&& (view
->change_list
!= NULL
) ? "(*) " : " ";
441 const char *file_label
;
445 view_filename
= view
->filename_vpath
!= NULL
? vfs_path_to_str (view
->filename_vpath
) : NULL
;
449 file_label
= view_filename
!= NULL
? view_filename
: view
->command
!= NULL
? view
->command
: "";
450 file_label
= str_term_trim (file_label
, len
- str_term_width1 (_("View: ")));
452 ret_str
= g_strconcat (_("View: "), modified
, file_label
, (char *) NULL
);
453 g_free (view_filename
);
457 /* --------------------------------------------------------------------------------------------- */