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 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,
41 #include <sys/types.h>
43 #include "lib/global.h"
44 #include "lib/vfs/vfs.h"
45 #include "lib/strutil.h"
46 #include "lib/util.h" /* save_file_position() */
47 #include "lib/lock.h" /* unlock_file() */
48 #include "lib/widget.h"
49 #include "lib/charsets.h"
52 #include "src/selcodepage.h"
57 /*** global variables ****************************************************************************/
59 #define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
60 const off_t INVALID_OFFSET
= (off_t
) - 1;
61 const off_t OFFSETTYPE_MAX
= ((off_t
) 1 << (OFF_T_BITWIDTH
- 1)) - 1;
63 /*** file scope macro definitions ****************************************************************/
65 /*** file scope type declarations ****************************************************************/
67 /*** file scope variables ************************************************************************/
69 /*** file scope functions ************************************************************************/
70 /* --------------------------------------------------------------------------------------------- */
72 /* --------------------------------------------------------------------------------------------- */
73 /*** public functions ****************************************************************************/
74 /* --------------------------------------------------------------------------------------------- */
77 mcview_toggle_magic_mode (mcview_t
* view
)
79 char *filename
, *command
;
81 if (view
->datasource
== DS_STDIN_PIPE
) /* stdin can't be "re-opened" */
82 return; /* and we can't do magic toggle without reopen, yet */
84 mcview_altered_magic_flag
= 1;
85 view
->magic_mode
= !view
->magic_mode
;
86 filename
= g_strdup (view
->filename
);
87 command
= g_strdup (view
->command
);
91 mcview_load (view
, command
, filename
, 0);
94 view
->dpy_bbar_dirty
= TRUE
;
98 /* --------------------------------------------------------------------------------------------- */
101 mcview_toggle_wrap_mode (mcview_t
* view
)
103 if (view
->text_wrap_mode
)
104 view
->dpy_start
= mcview_bol (view
, view
->dpy_start
, 0);
105 view
->text_wrap_mode
= !view
->text_wrap_mode
;
106 view
->dpy_bbar_dirty
= TRUE
;
110 /* --------------------------------------------------------------------------------------------- */
113 mcview_toggle_nroff_mode (mcview_t
* view
)
115 view
->text_nroff_mode
= !view
->text_nroff_mode
;
116 mcview_altered_nroff_flag
= 1;
117 view
->dpy_bbar_dirty
= TRUE
;
121 /* --------------------------------------------------------------------------------------------- */
124 mcview_toggle_hex_mode (mcview_t
* view
)
126 view
->hex_mode
= !view
->hex_mode
;
130 view
->hex_cursor
= view
->dpy_start
;
131 view
->dpy_start
= mcview_offset_rounddown (view
->dpy_start
, view
->bytes_per_line
);
132 widget_want_cursor (view
->widget
, 1);
136 view
->dpy_start
= mcview_bol (view
, view
->hex_cursor
, 0);
137 view
->hex_cursor
= view
->dpy_start
;
138 widget_want_cursor (view
->widget
, 0);
140 mcview_altered_hex_mode
= 1;
141 view
->dpy_bbar_dirty
= TRUE
;
145 /* --------------------------------------------------------------------------------------------- */
148 mcview_ok_to_quit (mcview_t
* view
)
152 if (view
->change_list
== NULL
)
155 if (!mc_global
.widget
.midnight_shutdown
)
158 r
= query_dialog (_("Quit"),
159 _("File was modified. Save with exit?"), D_NORMAL
, 3,
160 _("&Yes"), _("&No"), _("&Cancel quit"));
164 r
= query_dialog (_("Quit"),
165 _("Midnight Commander is being shut down.\nSave modified file?"),
166 D_NORMAL
, 2, _("&Yes"), _("&No"));
175 return mcview_hexedit_save_changes (view
) || mc_global
.widget
.midnight_shutdown
;
177 mcview_hexedit_free_change_list (view
);
184 /* --------------------------------------------------------------------------------------------- */
187 mcview_init (mcview_t
* view
)
191 view
->filename
= NULL
;
192 view
->workdir
= NULL
;
193 view
->command
= NULL
;
194 view
->search_nroff_seq
= NULL
;
196 mcview_set_datasource_none (view
);
198 view
->growbuf_in_use
= FALSE
;
199 /* leave the other growbuf fields uninitialized */
201 view
->hexedit_lownibble
= FALSE
;
202 view
->locked
= FALSE
;
203 view
->coord_cache
= NULL
;
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
;
213 /* {status,ruler,data}_area are left uninitialized */
216 view
->dpy_bbar_dirty
= TRUE
;
217 view
->bytes_per_line
= 1;
219 view
->search_start
= 0;
220 view
->search_end
= 0;
223 for (i
= 0; i
< sizeof (view
->marks
) / sizeof (view
->marks
[0]); i
++)
227 view
->update_steps
= 0;
228 view
->update_activate
= 0;
230 view
->saved_bookmarks
= NULL
;
233 /* --------------------------------------------------------------------------------------------- */
236 mcview_done (mcview_t
* view
)
238 /* Save current file position */
239 if (mcview_remember_file_position
&& view
->filename
!= NULL
)
243 vpath
= vfs_path_from_str (view
->filename
);
244 canon_fname
= vfs_path_to_str (vpath
);
245 save_file_position (canon_fname
, -1, 0,
246 view
->hex_mode
? view
->hex_cursor
: view
->dpy_start
,
247 view
->saved_bookmarks
);
248 view
->saved_bookmarks
= NULL
;
249 g_free (canon_fname
);
250 vfs_path_free (vpath
);
253 /* Write back the global viewer mode */
254 mcview_default_hex_mode
= view
->hex_mode
;
255 mcview_default_nroff_flag
= view
->text_nroff_mode
;
256 mcview_default_magic_flag
= view
->magic_mode
;
257 mcview_global_wrap_mode
= view
->text_wrap_mode
;
259 /* Free memory used by the viewer */
261 /* view->widget needs no destructor */
263 g_free (view
->filename
);
264 view
->filename
= NULL
;
265 g_free (view
->workdir
);
266 view
->workdir
= NULL
;
267 g_free (view
->command
);
268 view
->command
= NULL
;
270 mcview_close_datasource (view
);
271 /* the growing buffer is freed with the datasource */
273 coord_cache_free (view
->coord_cache
), view
->coord_cache
= NULL
;
275 if (view
->converter
== INVALID_CONV
)
276 view
->converter
= str_cnv_from_term
;
278 if (view
->converter
!= str_cnv_from_term
)
280 str_close_conv (view
->converter
);
281 view
->converter
= str_cnv_from_term
;
284 mc_search_free (view
->search
);
286 g_free (view
->last_search_string
);
287 view
->last_search_string
= NULL
;
288 mcview_nroff_seq_free (&view
->search_nroff_seq
);
289 mcview_hexedit_free_change_list (view
);
292 /* --------------------------------------------------------------------------------------------- */
295 mcview_set_codeset (mcview_t
* view
)
298 const char *cp_id
= NULL
;
302 get_codepage_id (mc_global
.source_codepage
>=
303 0 ? mc_global
.source_codepage
: mc_global
.display_codepage
);
307 conv
= str_crt_conv_from (cp_id
);
308 if (conv
!= INVALID_CONV
)
310 if (view
->converter
!= str_cnv_from_term
)
311 str_close_conv (view
->converter
);
312 view
->converter
= conv
;
314 view
->utf8
= (gboolean
) str_isutf8 (cp_id
);
321 /* --------------------------------------------------------------------------------------------- */
324 mcview_select_encoding (mcview_t
* view
)
327 if (do_select_codepage ())
328 mcview_set_codeset (view
);
334 /* --------------------------------------------------------------------------------------------- */
337 mcview_show_error (mcview_t
* view
, const char *msg
)
339 mcview_close_datasource (view
);
340 if (mcview_is_in_panel (view
))
342 mcview_set_datasource_string (view
, msg
);
346 message (D_ERROR
, MSG_ERROR
, "%s", msg
);
350 /* --------------------------------------------------------------------------------------------- */
351 /** returns index of the first char in the line
352 * it is constant for all line characters
356 mcview_bol (mcview_t
* view
, off_t current
, off_t limit
)
360 filesize
= mcview_get_filesize (view
);
363 if (current
> filesize
)
365 if (!mcview_get_byte (view
, current
, &c
))
369 if (!mcview_get_byte (view
, current
- 1, &c
))
374 while (current
> 0 && current
>= limit
)
376 if (!mcview_get_byte (view
, current
- 1, &c
))
378 if (c
== '\r' || c
== '\n')
385 /* --------------------------------------------------------------------------------------------- */
386 /** returns index of last char on line + width EOL
387 * mcview_eol of the current line == mcview_bol next line
391 mcview_eol (mcview_t
* view
, off_t current
, off_t limit
)
395 filesize
= mcview_get_filesize (view
);
398 if (current
>= filesize
)
400 while (current
< filesize
&& current
< limit
)
402 if (!mcview_get_byte (view
, current
, &c
))
409 else if (prev_ch
== '\r')
419 /* --------------------------------------------------------------------------------------------- */
422 mcview_get_title (const Dlg_head
* h
, size_t len
)
424 const mcview_t
*view
= (const mcview_t
*) find_widget_type (h
, mcview_callback
);
425 const char *modified
= view
->hexedit_mode
&& (view
->change_list
!= NULL
) ? "(*) " : " ";
426 const char *file_label
;
430 file_label
= view
->filename
!= NULL
? view
->filename
:
431 view
->command
!= NULL
? view
->command
: "";
432 file_label
= str_term_trim (file_label
, len
- str_term_width1 (_("View: ")));
434 return g_strconcat (_("View: "), modified
, file_label
, (char *) NULL
);
437 /* --------------------------------------------------------------------------------------------- */
440 mcview_lock_file (mcview_t
* view
)
445 fullpath
= mc_build_filename (view
->workdir
, view
->filename
, (char *) NULL
);
446 ret
= lock_file (fullpath
);
452 /* --------------------------------------------------------------------------------------------- */
455 mcview_unlock_file (mcview_t
* view
)
460 fullpath
= mc_build_filename (view
->workdir
, view
->filename
, (char *) NULL
);
461 ret
= unlock_file (fullpath
);
467 /* --------------------------------------------------------------------------------------------- */