1
1
mc/src/viewer/lib.c
Andrew Borodin 2cc2f34912 MCView: reimplemented messages and commands handling.
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2010-06-22 21:16:19 +04:00

399 строки
11 KiB
C

/*
Internal file viewer for the Midnight Commander
Common finctions (used from some other mcviewer functions)
Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
Written by: 1994, 1995, 1998 Miguel de Icaza
1994, 1995 Janne Kukonlehto
1995 Jakub Jelinek
1996 Joseph M. Hinkle
1997 Norbert Warmuth
1998 Pavel Machek
2004 Roland Illig <roland.illig@gmx.de>
2005 Roland Illig <roland.illig@gmx.de>
2009 Slava Zanko <slavazanko@google.com>
2009 Andrew Borodin <aborodin@vmail.ru>
2009 Ilia Maslakov <il.smind@gmail.com>
This file is part of the Midnight Commander.
The Midnight Commander is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Midnight Commander is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#include <config.h>
#include <limits.h>
#include <sys/types.h>
#include "lib/global.h"
#include "lib/vfs/mc-vfs/vfs.h"
#include "lib/strutil.h"
#include "src/wtools.h"
#include "src/main.h"
#include "src/charsets.h"
#include "src/selcodepage.h"
#include "internal.h"
#include "mcviewer.h"
/*** global variables ****************************************************************************/
#define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
const off_t INVALID_OFFSET = (off_t) - 1;
const off_t OFFSETTYPE_MAX = ((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1;
/*** file scope macro definitions ****************************************************************/
/*** file scope type declarations ****************************************************************/
/*** file scope variables ************************************************************************/
/*** file scope functions ************************************************************************/
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
void
mcview_toggle_magic_mode (mcview_t * view)
{
char *filename, *command;
mcview_altered_magic_flag = 1;
view->magic_mode = !view->magic_mode;
filename = g_strdup (view->filename);
command = g_strdup (view->command);
mcview_done (view);
mcview_init (view);
mcview_load (view, command, filename, 0);
g_free (filename);
g_free (command);
view->dpy_bbar_dirty = TRUE;
view->dirty++;
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_toggle_wrap_mode (mcview_t * view)
{
if (view->text_wrap_mode)
view->dpy_start = mcview_bol (view, view->dpy_start);
view->text_wrap_mode = !view->text_wrap_mode;
view->dpy_bbar_dirty = TRUE;
view->dirty++;
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_toggle_nroff_mode (mcview_t * view)
{
view->text_nroff_mode = !view->text_nroff_mode;
mcview_altered_nroff_flag = 1;
view->dpy_bbar_dirty = TRUE;
view->dirty++;
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_toggle_hex_mode (mcview_t * view)
{
view->hex_mode = !view->hex_mode;
if (view->hex_mode)
{
view->hex_cursor = view->dpy_start;
view->dpy_start = mcview_offset_rounddown (view->dpy_start, view->bytes_per_line);
widget_want_cursor (view->widget, 1);
}
else
{
view->dpy_start = view->hex_cursor;
mcview_moveto_bol (view);
widget_want_cursor (view->widget, 0);
}
mcview_altered_hex_mode = 1;
view->dpy_bbar_dirty = TRUE;
view->dirty++;
}
/* --------------------------------------------------------------------------------------------- */
gboolean
mcview_ok_to_quit (mcview_t * view)
{
int r;
if (view->change_list == NULL)
return TRUE;
r = query_dialog (_("Quit"),
_("File was modified, Save with exit?"), D_NORMAL, 3,
_("&Cancel quit"), _("&Yes"), _("&No"));
switch (r)
{
case 1:
return mcview_hexedit_save_changes (view);
case 2:
mcview_hexedit_free_change_list (view);
return TRUE;
default:
return FALSE;
}
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_init (mcview_t * view)
{
size_t i;
view->filename = NULL;
view->command = NULL;
view->search_nroff_seq = NULL;
mcview_set_datasource_none (view);
view->growbuf_in_use = FALSE;
/* leave the other growbuf fields uninitialized */
view->hexedit_lownibble = FALSE;
view->coord_cache = NULL;
view->dpy_start = 0;
view->dpy_text_column = 0;
view->dpy_end = 0;
view->hex_cursor = 0;
view->cursor_col = 0;
view->cursor_row = 0;
view->change_list = NULL;
/* {status,ruler,data}_area are left uninitialized */
view->dirty = 0;
view->dpy_bbar_dirty = TRUE;
view->bytes_per_line = 1;
view->search_start = 0;
view->search_end = 0;
view->marker = 0;
for (i = 0; i < sizeof (view->marks) / sizeof (view->marks[0]); i++)
view->marks[i] = 0;
view->move_dir = 0;
view->update_steps = 0;
view->update_activate = 0;
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_done (mcview_t * view)
{
/* Save current file position */
if (mcview_remember_file_position && view->filename != NULL)
{
char *canon_fname;
canon_fname = vfs_canon (view->filename);
save_file_position (canon_fname, -1, 0, view->dpy_start);
g_free (canon_fname);
}
/* Write back the global viewer mode */
mcview_default_hex_mode = view->hex_mode;
mcview_default_nroff_flag = view->text_nroff_mode;
mcview_default_magic_flag = view->magic_mode;
mcview_global_wrap_mode = view->text_wrap_mode;
/* Free memory used by the viewer */
/* view->widget needs no destructor */
g_free (view->filename);
view->filename = NULL;
g_free (view->command);
view->command = NULL;
mcview_close_datasource (view);
/* the growing buffer is freed with the datasource */
coord_cache_free (view->coord_cache), view->coord_cache = NULL;
if (view->converter == INVALID_CONV)
view->converter = str_cnv_from_term;
if (view->converter != str_cnv_from_term)
{
str_close_conv (view->converter);
view->converter = str_cnv_from_term;
}
mc_search_free (view->search);
view->search = NULL;
g_free (view->last_search_string);
view->last_search_string = NULL;
mcview_nroff_seq_free (&view->search_nroff_seq);
mcview_hexedit_free_change_list (view);
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_set_codeset (mcview_t * view)
{
#ifdef HAVE_CHARSET
const char *cp_id = NULL;
view->utf8 = TRUE;
cp_id = get_codepage_id (source_codepage >= 0 ? source_codepage : display_codepage);
if (cp_id != NULL)
{
GIConv conv;
conv = str_crt_conv_from (cp_id);
if (conv != INVALID_CONV)
{
if (view->converter != str_cnv_from_term)
str_close_conv (view->converter);
view->converter = conv;
}
view->utf8 = (gboolean) str_isutf8 (cp_id);
}
#else
(void) view;
#endif
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_select_encoding (mcview_t * view)
{
#ifdef HAVE_CHARSET
if (do_select_codepage ())
{
mcview_set_codeset (view);
}
#else
(void) view;
#endif
}
/* --------------------------------------------------------------------------------------------- */
void
mcview_show_error (mcview_t * view, const char *msg)
{
mcview_close_datasource (view);
if (mcview_is_in_panel (view))
{
mcview_set_datasource_string (view, msg);
}
else
{
message (D_ERROR, MSG_ERROR, "%s", msg);
}
}
/* --------------------------------------------------------------------------------------------- */
/* returns index of the first char in the line */
/* it is constant for all line characters */
off_t
mcview_bol (mcview_t * view, off_t current)
{
int c;
off_t filesize;
filesize = mcview_get_filesize (view);
if (current <= 0)
return 0;
if (current > filesize)
return filesize;
if (!mcview_get_byte (view, current, &c))
return current;
if (c == '\n')
{
if (!mcview_get_byte (view, current - 1, &c))
return current;
if (c == '\r')
current--;
}
while (current > 0)
{
if (!mcview_get_byte (view, current - 1, &c))
break;
if (c == '\r' || c == '\n')
break;
current--;
}
return current;
}
/* returns index of last char on line + width EOL */
/* mcview_eol of the current line == mcview_bol next line */
off_t
mcview_eol (mcview_t * view, off_t current)
{
int c, prev_ch = 0;
off_t filesize;
filesize = mcview_get_filesize (view);
if (current < 0)
return 0;
if (current >= filesize)
return filesize;
while (current < filesize)
{
if (!mcview_get_byte (view, current, &c))
break;
if (c == '\n')
{
current++;
break;
}
else if (prev_ch == '\r')
{
break;
}
current++;
prev_ch = c;
}
return current;
}
char *
mcview_get_title (const Dlg_head *h, size_t len)
{
const mcview_t *view = (const mcview_t *) find_widget_type (h, mcview_callback);
const char *modified = view->hexedit_mode && (view->change_list != NULL) ? "(*) " : " ";
const char *file_label;
len -= 4;
file_label = view->filename != NULL ? view->filename :
view->command != NULL ? view->command : "";
file_label = str_term_trim (file_label, len - str_term_width1 (_("View: ")));
return g_strconcat (_("View: "), modified, file_label, (char *) NULL);
}