mirror of https://github.com/MidnightCommander/mc
Merge branch 'DEV_mcview2'
* DEV_mcview2: (27 commits) Implemented interruptable long-distance movements. fix: <no translation> behaviour Change prototype of mcview_get_byte() function (and al related functions) fix: uninitialized variables fix: header paths Added missed includes. Fixed OFFSETTYPE_MAX calculation. Cleanup of code. Indentation. Ticket #1530 * add 'Whole words' option into the viewer 'Search' dialog Added functions for work with nroff'ed text. Added search across nroff'ed text Fixies with search in HEX mode view: Search in plain text (not nroff'ed) now worked. Cleanup of code. Reidentation. Ticket #1431 (Missing translation in view.c ButtonBar?) Avoid warning 'format not a string literal and no format arguments'. Fixed memory leak after geting list of search types. Move search dialog from actions_cmd.c into dialogs.c Changes for correctly work after rebase to master (master with HACK_tty). fix: draw nroff text Move inline functions from internal.h into new file inlines.h ...
This commit is contained in:
commit
5257a79847
|
@ -562,6 +562,7 @@ src/Makefile
|
|||
src/mcconfig/Makefile
|
||||
src/search/Makefile
|
||||
src/tty/Makefile
|
||||
src/viewer/Makefile
|
||||
|
||||
edit/Makefile
|
||||
syntax/Makefile
|
||||
|
|
|
@ -111,7 +111,7 @@ editcmd_dialog_replace_show (WEdit * edit, const char *search_default, const cha
|
|||
&tall_codepages, 0, NULL, NULL, NULL},
|
||||
#endif
|
||||
|
||||
{quick_checkbox, 33, REPLACE_DLG_WIDTH, 10, REPLACE_DLG_HEIGHT, N_("Whole &words"), 0, 0,
|
||||
{quick_checkbox, 33, REPLACE_DLG_WIDTH, 10, REPLACE_DLG_HEIGHT, N_("&Whole words"), 0, 0,
|
||||
&twhole_words, 0, NULL, NULL, NULL},
|
||||
|
||||
|
||||
|
@ -206,7 +206,7 @@ editcmd_dialog_search_show (WEdit * edit, char **search_text)
|
|||
&tall_codepages, 0, NULL, NULL, NULL},
|
||||
#endif
|
||||
|
||||
{quick_checkbox, 33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("Whole &words"), 0, 0,
|
||||
{quick_checkbox, 33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("&Whole words"), 0, 0,
|
||||
&twhole_words, 0, NULL, NULL, NULL},
|
||||
|
||||
{quick_checkbox, 33, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT, N_("In se&lection"), 0, 0,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = mcconfig search tty
|
||||
SUBDIRS = mcconfig search tty viewer
|
||||
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) $(PCRE_CFLAGS)
|
||||
|
||||
|
@ -42,9 +42,10 @@ endif
|
|||
MCCONFIGLIB = mcconfig/libmcconfig.la
|
||||
SEARCHLIB = search/libsearch.la
|
||||
TTYLIB = tty/libmctty.la
|
||||
VIEWERLIB = viewer/libmcviewer.la
|
||||
|
||||
mc_LDADD = $(EDITLIB) $(VFSLIB) \
|
||||
$(MCCONFIGLIB) $(SEARCHLIB) $(TTYLIB) \
|
||||
$(MCCONFIGLIB) $(SEARCHLIB) $(TTYLIB) $(VIEWERLIB) \
|
||||
$(INTLLIBS) $(MCLIBS) $(SLANGLIB) $(LIBICONV) $(GLIB_LIBS)
|
||||
|
||||
CHARSET_SRC = charsets.c charsets.h selcodepage.c selcodepage.h
|
||||
|
@ -66,7 +67,7 @@ SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \
|
|||
screen.c setup.c setup.h \
|
||||
subshell.c subshell.h textconf.c textconf.h \
|
||||
tree.c tree.h treestore.c treestore.h timefmt.h user.c \
|
||||
user.h util.c util.h utilunix.c view.c view.h vfsdummy.h \
|
||||
user.h util.c util.h utilunix.c vfsdummy.h \
|
||||
widget.c widget.h wtools.c wtools.h unixcompat.h \
|
||||
ecs.h ecs.c \
|
||||
strutil.h strutil.c strutilascii.c strutil8bit.c strutilutf8.c \
|
||||
|
|
38
src/cmd.c
38
src/cmd.c
|
@ -64,7 +64,6 @@
|
|||
#include "subshell.h" /* use_subshell */
|
||||
#include "cons.saver.h" /* console_flag */
|
||||
#include "dialog.h" /* Widget */
|
||||
#include "view.h" /* mc_internal_viewer() */
|
||||
#include "wtools.h" /* message() */
|
||||
#include "widget.h" /* push_history() */
|
||||
#include "main.h" /* change_panel() */
|
||||
|
@ -80,6 +79,7 @@
|
|||
#include "history.h"
|
||||
#include "strutil.h"
|
||||
#include "dir.h"
|
||||
#include "../src/viewer/mcviewer.h"
|
||||
|
||||
#ifndef MAP_FILE
|
||||
# define MAP_FILE 0
|
||||
|
@ -123,25 +123,25 @@ view_file_at_line (const char *filename, int plain_view, int internal,
|
|||
int changed_nroff_flag = 0;
|
||||
int changed_magic_flag = 0;
|
||||
|
||||
altered_hex_mode = 0;
|
||||
altered_nroff_flag = 0;
|
||||
altered_magic_flag = 0;
|
||||
if (default_hex_mode)
|
||||
mcview_altered_hex_mode = 0;
|
||||
mcview_altered_nroff_flag = 0;
|
||||
mcview_altered_magic_flag = 0;
|
||||
if (mcview_default_hex_mode)
|
||||
changed_hex_mode = 1;
|
||||
if (default_nroff_flag)
|
||||
if (mcview_default_nroff_flag)
|
||||
changed_nroff_flag = 1;
|
||||
if (default_magic_flag)
|
||||
if (mcview_default_magic_flag)
|
||||
changed_magic_flag = 1;
|
||||
default_hex_mode = 0;
|
||||
default_nroff_flag = 0;
|
||||
default_magic_flag = 0;
|
||||
mc_internal_viewer (NULL, filename, &move_dir, start_line);
|
||||
if (changed_hex_mode && !altered_hex_mode)
|
||||
default_hex_mode = 1;
|
||||
if (changed_nroff_flag && !altered_nroff_flag)
|
||||
default_nroff_flag = 1;
|
||||
if (changed_magic_flag && !altered_magic_flag)
|
||||
default_magic_flag = 1;
|
||||
mcview_default_hex_mode = 0;
|
||||
mcview_default_nroff_flag = 0;
|
||||
mcview_default_magic_flag = 0;
|
||||
mcview_viewer (NULL, filename, &move_dir, start_line);
|
||||
if (changed_hex_mode && !mcview_altered_hex_mode)
|
||||
mcview_default_hex_mode = 1;
|
||||
if (changed_nroff_flag && !mcview_altered_nroff_flag)
|
||||
mcview_default_nroff_flag = 1;
|
||||
if (changed_magic_flag && !mcview_altered_magic_flag)
|
||||
mcview_default_magic_flag = 1;
|
||||
repaint_screen ();
|
||||
return move_dir;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ view_file_at_line (const char *filename, int plain_view, int internal,
|
|||
strcpy (view_entry, "View");
|
||||
|
||||
if (regex_command (filename, view_entry, &move_dir) == 0) {
|
||||
mc_internal_viewer (NULL, filename, &move_dir, start_line);
|
||||
mcview_viewer (NULL, filename, &move_dir, start_line);
|
||||
repaint_screen ();
|
||||
}
|
||||
} else {
|
||||
|
@ -288,7 +288,7 @@ filtered_view_cmd (void)
|
|||
if (!command)
|
||||
return;
|
||||
|
||||
mc_internal_viewer (command, "", NULL, 0);
|
||||
mcview_viewer (command, "", NULL, 0);
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
|
|
26
src/ext.c
26
src/ext.c
|
@ -38,12 +38,12 @@
|
|||
#include "main.h"
|
||||
#include "wtools.h"
|
||||
#include "ext.h"
|
||||
#include "view.h"
|
||||
#include "execute.h"
|
||||
#include "history.h"
|
||||
#include "cons.saver.h"
|
||||
#include "layout.h"
|
||||
#include "../src/search/search.h"
|
||||
#include "../src/viewer/mcviewer.h"
|
||||
|
||||
/* If set, we execute the file command to check the file type */
|
||||
int use_file_to_check_type = 1;
|
||||
|
@ -76,8 +76,8 @@ exec_extension (const char *filename, const char *data, int *move_dir,
|
|||
int parameter_found = 0;
|
||||
char prompt[80];
|
||||
int run_view = 0;
|
||||
int def_hex_mode = default_hex_mode, changed_hex_mode = 0;
|
||||
int def_nroff_flag = default_nroff_flag, changed_nroff_flag = 0;
|
||||
int def_hex_mode = mcview_default_hex_mode, changed_hex_mode = 0;
|
||||
int def_nroff_flag = mcview_default_nroff_flag, changed_nroff_flag = 0;
|
||||
int written_nonspace = 0;
|
||||
int is_cd = 0;
|
||||
char buffer[1024];
|
||||
|
@ -234,26 +234,26 @@ exec_extension (const char *filename, const char *data, int *move_dir,
|
|||
}
|
||||
|
||||
if (run_view) {
|
||||
altered_hex_mode = 0;
|
||||
altered_nroff_flag = 0;
|
||||
if (def_hex_mode != default_hex_mode)
|
||||
mcview_altered_hex_mode = 0;
|
||||
mcview_altered_nroff_flag = 0;
|
||||
if (def_hex_mode != mcview_default_hex_mode)
|
||||
changed_hex_mode = 1;
|
||||
if (def_nroff_flag != default_nroff_flag)
|
||||
if (def_nroff_flag != mcview_default_nroff_flag)
|
||||
changed_nroff_flag = 1;
|
||||
|
||||
/* If we've written whitespace only, then just load filename
|
||||
* into view
|
||||
*/
|
||||
if (written_nonspace) {
|
||||
mc_internal_viewer (cmd, filename, move_dir, start_line);
|
||||
mcview_viewer (cmd, filename, move_dir, start_line);
|
||||
unlink (file_name);
|
||||
} else {
|
||||
mc_internal_viewer (NULL, filename, move_dir, start_line);
|
||||
mcview_viewer (NULL, filename, move_dir, start_line);
|
||||
}
|
||||
if (changed_hex_mode && !altered_hex_mode)
|
||||
default_hex_mode = def_hex_mode;
|
||||
if (changed_nroff_flag && !altered_nroff_flag)
|
||||
default_nroff_flag = def_nroff_flag;
|
||||
if (changed_hex_mode && !mcview_altered_hex_mode)
|
||||
mcview_default_hex_mode = def_hex_mode;
|
||||
if (changed_nroff_flag && !mcview_altered_nroff_flag)
|
||||
mcview_default_nroff_flag = def_nroff_flag;
|
||||
repaint_screen ();
|
||||
} else if (is_cd) {
|
||||
char *q;
|
||||
|
|
|
@ -287,7 +287,7 @@ find_parameters (char **start_dir, char **pattern, char **content)
|
|||
const char *content_case_label = N_("Case sens&itive");
|
||||
const char *content_regexp_label = N_("Re&gular expression");
|
||||
const char *content_first_hit_label = N_("Fir&st hit");
|
||||
const char *content_whole_words_label = N_("Whole &words");
|
||||
const char *content_whole_words_label = N_("&Whole words");
|
||||
const char *content_all_charsets_label = N_("All cha&rsets");
|
||||
|
||||
const char *buts[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
|
||||
|
|
|
@ -72,7 +72,8 @@
|
|||
#include "cons.saver.h"
|
||||
#include "layout.h"
|
||||
#include "info.h" /* The Info widget */
|
||||
#include "view.h" /* The view widget */
|
||||
#include "../src/viewer/mcviewer.h" /* The view widget */
|
||||
|
||||
#include "setup.h" /* For save_setup() */
|
||||
#include "../vfs/vfs.h" /* For vfs_translate_url() */
|
||||
|
||||
|
@ -927,7 +928,7 @@ set_display_type (int num, int type)
|
|||
break;
|
||||
|
||||
case view_quick:
|
||||
new_widget = (Widget *) view_new (0, 0, 0, 0, 1);
|
||||
new_widget = (Widget *) mcview_new (0, 0, 0, 0, 1);
|
||||
the_other_panel = (WPanel *) panels [the_other].widget;
|
||||
if (the_other_panel)
|
||||
file_name =
|
||||
|
@ -935,7 +936,7 @@ set_display_type (int num, int type)
|
|||
else
|
||||
file_name = "";
|
||||
|
||||
view_load ((WView *) new_widget, 0, file_name, 0);
|
||||
mcview_load ((struct mcview_struct *) new_widget, 0, file_name, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "tree.h" /* xtree_mode */
|
||||
#include "../src/mcconfig/mcconfig.h"
|
||||
#include "setup.h"
|
||||
#include "view.h" /* For the externs */
|
||||
#include "../src/viewer/mcviewer.h" /* For the externs */
|
||||
#include "hotlist.h" /* load/save/done hotlist */
|
||||
#include "panelize.h" /* load/save/done panelize */
|
||||
#include "layout.h"
|
||||
|
@ -177,16 +177,16 @@ static const struct {
|
|||
{ "use_8th_bit_as_meta", &use_8th_bit_as_meta },
|
||||
{ "confirm_view_dir", &confirm_view_dir },
|
||||
{ "mouse_move_pages", &mouse_move_pages },
|
||||
{ "mouse_move_pages_viewer", &mouse_move_pages_viewer },
|
||||
{ "mouse_move_pages_viewer", &mcview_mouse_move_pages },
|
||||
{ "mouse_close_dialog", &mouse_close_dialog},
|
||||
{ "fast_refresh", &fast_refresh },
|
||||
{ "navigate_with_arrows", &navigate_with_arrows },
|
||||
{ "drop_menus", &drop_menus },
|
||||
{ "wrap_mode", &global_wrap_mode},
|
||||
{ "wrap_mode", &mcview_global_wrap_mode},
|
||||
{ "old_esc_mode", &old_esc_mode },
|
||||
{ "cd_symlinks", &cd_symlinks },
|
||||
{ "show_all_if_ambiguous", &show_all_if_ambiguous },
|
||||
{ "max_dirt_limit", &max_dirt_limit },
|
||||
{ "max_dirt_limit", &mcview_max_dirt_limit },
|
||||
{ "torben_fj_mode", &torben_fj_mode },
|
||||
{ "use_file_to_guess_type", &use_file_to_check_type },
|
||||
{ "alternate_plus_minus", &alternate_plus_minus },
|
||||
|
|
12
src/user.c
12
src/user.c
|
@ -48,7 +48,7 @@
|
|||
#include "dialog.h"
|
||||
#include "widget.h"
|
||||
#include "wtools.h"
|
||||
#include "view.h" /* for default_* externs */
|
||||
#include "../src/viewer/mcviewer.h" /* for default_* externs */
|
||||
|
||||
#define MAX_ENTRIES 16
|
||||
#define MAX_ENTRY_LEN 60
|
||||
|
@ -90,16 +90,16 @@ int check_format_view (const char *p)
|
|||
if (*q == '{'){
|
||||
for (q++;*q && *q != '}';q++) {
|
||||
if (!strncmp (q, "ascii", 5)) {
|
||||
default_hex_mode = 0;
|
||||
mcview_default_hex_mode = 0;
|
||||
q += 4;
|
||||
} else if (!strncmp (q, "hex", 3)) {
|
||||
default_hex_mode = 1;
|
||||
mcview_default_hex_mode = 1;
|
||||
q += 2;
|
||||
} else if (!strncmp (q, "nroff", 5)) {
|
||||
default_nroff_flag = 1;
|
||||
mcview_default_nroff_flag = 1;
|
||||
q += 4;
|
||||
} else if (!strncmp (q, "unform", 6)) {
|
||||
default_nroff_flag = 0;
|
||||
mcview_default_nroff_flag = 0;
|
||||
q += 5;
|
||||
}
|
||||
}
|
||||
|
@ -694,7 +694,7 @@ execute_menu_command (WEdit *edit_widget, const char *commands)
|
|||
chmod (file_name, S_IRWXU);
|
||||
if (run_view) {
|
||||
run_view = 0;
|
||||
mc_internal_viewer (file_name, NULL, &run_view, 0);
|
||||
mcview_viewer (file_name, NULL, &run_view, 0);
|
||||
} else {
|
||||
/* execute the command indirectly to allow execution even
|
||||
* on no-exec filesystems. */
|
||||
|
|
3990
src/view.c
3990
src/view.c
File diff suppressed because it is too large
Load Diff
41
src/view.h
41
src/view.h
|
@ -1,41 +0,0 @@
|
|||
|
||||
/** \file view.h
|
||||
* \brief Header: internal file viewer
|
||||
*/
|
||||
|
||||
#ifndef MC_VIEW_H
|
||||
#define MC_VIEW_H
|
||||
|
||||
typedef struct WView WView; /* Can be cast to Widget */
|
||||
|
||||
/* Creates a new WView object with the given properties. Caveat: the
|
||||
* origin is in y-x order, while the extent is in x-y order. */
|
||||
extern WView *view_new (int y, int x, int cols, int lines, int is_panel);
|
||||
|
||||
/* If {command} is not NULL, loads the output of the shell command
|
||||
* {command} and ignores {file}. If {command} is NULL, loads the
|
||||
* {file}. If the {file} is also NULL, loads nothing. If {start_line}
|
||||
* is positive, the output is shown starting in that line. */
|
||||
extern int view_load (WView *view, const char *command, const char *file,
|
||||
int start_line);
|
||||
|
||||
/* Shows {file} or the output of {command} in the internal viewer,
|
||||
* starting in line {start_line}. {ret_move_direction} may be NULL or
|
||||
* point to a variable that will receive the direction in which the user
|
||||
* wants to move (-1 = previous file, 1 = next file, 0 = do nothing).
|
||||
*/
|
||||
extern int mc_internal_viewer (const char *command, const char *file,
|
||||
int *ret_move_direction, int start_line);
|
||||
|
||||
extern int mouse_move_pages_viewer;
|
||||
extern int max_dirt_limit;
|
||||
extern int global_wrap_mode;
|
||||
extern int default_hex_mode;
|
||||
extern int default_magic_flag;
|
||||
extern int default_nroff_flag;
|
||||
extern int altered_hex_mode;
|
||||
extern int altered_magic_flag;
|
||||
extern int altered_nroff_flag;
|
||||
extern int mcview_remember_file_position;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
noinst_LTLIBRARIES = libmcviewer.la
|
||||
|
||||
libmcviewer_la_SOURCES = \
|
||||
actions_cmd.c \
|
||||
coord_cache.c \
|
||||
datasource.c \
|
||||
dialogs.c \
|
||||
display.c \
|
||||
growbuf.c \
|
||||
hex.c \
|
||||
inlines.h \
|
||||
internal.h \
|
||||
lib.c \
|
||||
mcviewer.c \
|
||||
mcviewer.h \
|
||||
move.c \
|
||||
nroff.c \
|
||||
plain.c \
|
||||
search.c
|
||||
|
||||
libmcviewer_la_CFLAGS=-I../ -I$(top_srcdir)/src \
|
||||
$(GLIB_CFLAGS) \
|
||||
-DDATADIR=\""$(pkgdatadir)/"\" -DLOCALEDIR=\""$(localedir)"\"
|
||||
|
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Callback function for some actions (hotkeys, menu)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The functions in this section can be bound to hotkeys. They are all
|
||||
of the same type (taking a pointer to mcview_t as parameter and
|
||||
returning void). TODO: In the not-too-distant future, these commands
|
||||
will become fully configurable, like they already are in the
|
||||
internal editor. By convention, all the function names end in
|
||||
"_cmd".
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/panel.h"
|
||||
#include "../src/layout.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "../src/history.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "../src/tty/key.h"
|
||||
#include "../src/cmd.h"
|
||||
#include "../src/execute.h"
|
||||
#include "../src/help.h"
|
||||
#include "internal.h"
|
||||
#include "mcviewer.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_continue_search_cmd (mcview_t * view)
|
||||
{
|
||||
if (view->last_search_string != NULL) {
|
||||
mcview_do_search (view);
|
||||
} else {
|
||||
/* if not... then ask for an expression */
|
||||
mcview_search_cmd (view);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
static cb_ret_t
|
||||
mcview_handle_editkey (mcview_t * view, int key)
|
||||
{
|
||||
struct hexedit_change_node *node;
|
||||
int byte_val;
|
||||
|
||||
/* Has there been a change at this position? */
|
||||
node = view->change_list;
|
||||
while (node && (node->offset != view->hex_cursor))
|
||||
node = node->next;
|
||||
|
||||
if (!view->hexview_in_text) {
|
||||
/* Hex editing */
|
||||
unsigned int hexvalue = 0;
|
||||
|
||||
if (key >= '0' && key <= '9')
|
||||
hexvalue = 0 + (key - '0');
|
||||
else if (key >= 'A' && key <= 'F')
|
||||
hexvalue = 10 + (key - 'A');
|
||||
else if (key >= 'a' && key <= 'f')
|
||||
hexvalue = 10 + (key - 'a');
|
||||
else
|
||||
return MSG_NOT_HANDLED;
|
||||
|
||||
if (node)
|
||||
byte_val = node->value;
|
||||
else
|
||||
mcview_get_byte (view, view->hex_cursor, &byte_val);
|
||||
|
||||
if (view->hexedit_lownibble) {
|
||||
byte_val = (byte_val & 0xf0) | (hexvalue);
|
||||
} else {
|
||||
byte_val = (byte_val & 0x0f) | (hexvalue << 4);
|
||||
}
|
||||
} else {
|
||||
/* Text editing */
|
||||
if (key < 256 && ((key == '\n') || is_printable (key)))
|
||||
byte_val = key;
|
||||
else
|
||||
return MSG_NOT_HANDLED;
|
||||
}
|
||||
if (!node) {
|
||||
node = g_new (struct hexedit_change_node, 1);
|
||||
node->offset = view->hex_cursor;
|
||||
node->value = byte_val;
|
||||
mcview_enqueue_change (&view->change_list, node);
|
||||
} else {
|
||||
node->value = byte_val;
|
||||
}
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
mcview_move_right (view, 1);
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Check for left and right arrows, possibly with modifiers */
|
||||
static cb_ret_t
|
||||
mcview_check_left_right_keys (mcview_t * view, int c)
|
||||
{
|
||||
if (c == KEY_LEFT) {
|
||||
mcview_move_left (view, 1);
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
if (c == KEY_RIGHT) {
|
||||
mcview_move_right (view, 1);
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
/* Ctrl with arrows moves by 10 postions in the unwrap mode */
|
||||
if (view->hex_mode || view->text_wrap_mode)
|
||||
return MSG_NOT_HANDLED;
|
||||
|
||||
if (c == (KEY_M_CTRL | KEY_LEFT)) {
|
||||
if (view->dpy_text_column >= 10)
|
||||
view->dpy_text_column -= 10;
|
||||
else
|
||||
view->dpy_text_column = 0;
|
||||
view->dirty++;
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
if (c == (KEY_M_CTRL | KEY_RIGHT)) {
|
||||
if (view->dpy_text_column <= OFFSETTYPE_MAX - 10)
|
||||
view->dpy_text_column += 10;
|
||||
else
|
||||
view->dpy_text_column = OFFSETTYPE_MAX;
|
||||
view->dirty++;
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
return MSG_NOT_HANDLED;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_cmk_move_up (void *w, int n)
|
||||
{
|
||||
mcview_move_up ((mcview_t *) w, n);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_cmk_move_down (void *w, int n)
|
||||
{
|
||||
mcview_move_down ((mcview_t *) w, n);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_cmk_moveto_top (void *w, int n)
|
||||
{
|
||||
(void) &n;
|
||||
mcview_moveto_top ((mcview_t *) w);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_cmk_moveto_bottom (void *w, int n)
|
||||
{
|
||||
(void) &n;
|
||||
mcview_moveto_bottom ((mcview_t *) w);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_hook (void *v)
|
||||
{
|
||||
mcview_t *view = (mcview_t *) v;
|
||||
WPanel *panel;
|
||||
|
||||
/* If the user is busy typing, wait until he finishes to update the
|
||||
screen */
|
||||
if (!is_idle ()) {
|
||||
if (!hook_present (idle_hook, mcview_hook))
|
||||
add_hook (&idle_hook, mcview_hook, v);
|
||||
return;
|
||||
}
|
||||
|
||||
delete_hook (&idle_hook, mcview_hook);
|
||||
|
||||
if (get_current_type () == view_listing)
|
||||
panel = current_panel;
|
||||
else if (get_other_type () == view_listing)
|
||||
panel = other_panel;
|
||||
else
|
||||
return;
|
||||
|
||||
mcview_load (view, 0, panel->dir.list[panel->selected].fname, 0);
|
||||
mcview_display (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Both views */
|
||||
static cb_ret_t
|
||||
mcview_handle_key (mcview_t * view, int c)
|
||||
{
|
||||
c = convert_from_input_c (c);
|
||||
|
||||
if (view->hex_mode) {
|
||||
switch (c) {
|
||||
case '\t':
|
||||
view->hexview_in_text = !view->hexview_in_text;
|
||||
view->dirty++;
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('a'):
|
||||
mcview_moveto_bol (view);
|
||||
view->dirty++;
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('b'):
|
||||
mcview_move_left (view, 1);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('e'):
|
||||
mcview_moveto_eol (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('f'):
|
||||
mcview_move_right (view, 1);
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
if (view->hexedit_mode && mcview_handle_editkey (view, c) == MSG_HANDLED)
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
if (mcview_check_left_right_keys (view, c))
|
||||
return MSG_HANDLED;
|
||||
|
||||
if (check_movement_keys (c, view->data_area.height + 1, view,
|
||||
mcview_cmk_move_up, mcview_cmk_move_down,
|
||||
mcview_cmk_moveto_top, mcview_cmk_moveto_bottom))
|
||||
return MSG_HANDLED;
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '?':
|
||||
case '/':
|
||||
view->search_type = MC_SEARCH_T_REGEX;
|
||||
mcview_search_cmd (view);
|
||||
return MSG_HANDLED;
|
||||
break;
|
||||
/* Continue search */
|
||||
case XCTRL ('r'):
|
||||
case XCTRL ('s'):
|
||||
case 'n':
|
||||
case KEY_F (17):
|
||||
mcview_continue_search_cmd (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
/* toggle ruler */
|
||||
case ALT ('r'):
|
||||
mcview_toggle_ruler_cmd (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'h':
|
||||
mcview_move_left (view, 1);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'j':
|
||||
case '\n':
|
||||
case 'e':
|
||||
mcview_move_down (view, 1);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'd':
|
||||
mcview_move_down (view, (view->data_area.height + 1) / 2);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'u':
|
||||
mcview_move_up (view, (view->data_area.height + 1) / 2);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'k':
|
||||
case 'y':
|
||||
mcview_move_up (view, 1);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'l':
|
||||
mcview_move_right (view, 1);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case ' ':
|
||||
case 'f':
|
||||
mcview_move_down (view, view->data_area.height);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('o'):
|
||||
view_other_cmd ();
|
||||
return MSG_HANDLED;
|
||||
|
||||
/* Unlike Ctrl-O, run a new shell if the subshell is not running. */
|
||||
case '!':
|
||||
exec_shell ();
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'b':
|
||||
mcview_move_up (view, view->data_area.height);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case KEY_IC:
|
||||
mcview_move_up (view, 2);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case KEY_DC:
|
||||
mcview_move_down (view, 2);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'm':
|
||||
view->marks[view->marker] = view->dpy_start;
|
||||
return MSG_HANDLED;
|
||||
|
||||
case 'r':
|
||||
view->dpy_start = view->marks[view->marker];
|
||||
view->dirty++;
|
||||
return MSG_HANDLED;
|
||||
|
||||
/* Use to indicate parent that we want to see the next/previous file */
|
||||
/* Does not work in panel mode */
|
||||
case XCTRL ('f'):
|
||||
case XCTRL ('b'):
|
||||
if (!mcview_is_in_panel (view))
|
||||
view->move_dir = c == XCTRL ('f') ? 1 : -1;
|
||||
/* FALLTHROUGH */
|
||||
case 'q':
|
||||
case XCTRL ('g'):
|
||||
case ESC_CHAR:
|
||||
if (mcview_ok_to_quit (view))
|
||||
view->want_to_quit = TRUE;
|
||||
return MSG_HANDLED;
|
||||
|
||||
case XCTRL ('t'):
|
||||
mcview_select_encoding (view);
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
#ifdef MC_ENABLE_DEBUGGING_CODE
|
||||
case 't': /* mnemonic: "test" */
|
||||
mcview_ccache_dump (view);
|
||||
return MSG_HANDLED;
|
||||
#endif
|
||||
}
|
||||
if (c >= '0' && c <= '9')
|
||||
view->marker = c - '0';
|
||||
|
||||
/* Key not used */
|
||||
return MSG_NOT_HANDLED;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
cb_ret_t
|
||||
mcview_callback (Widget * w, widget_msg_t msg, int parm)
|
||||
{
|
||||
mcview_t *view = (mcview_t *) w;
|
||||
cb_ret_t i;
|
||||
Dlg_head *h = view->widget.parent;
|
||||
|
||||
mcview_compute_areas (view);
|
||||
mcview_update_bytes_per_line (view);
|
||||
|
||||
switch (msg) {
|
||||
case WIDGET_INIT:
|
||||
if (mcview_is_in_panel (view))
|
||||
add_hook (&select_file_hook, mcview_hook, view);
|
||||
else
|
||||
view->dpy_bbar_dirty = TRUE;
|
||||
return MSG_HANDLED;
|
||||
|
||||
case WIDGET_DRAW:
|
||||
mcview_display (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case WIDGET_CURSOR:
|
||||
if (view->hex_mode)
|
||||
mcview_place_cursor (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case WIDGET_KEY:
|
||||
i = mcview_handle_key ((mcview_t *) view, parm);
|
||||
if (view->want_to_quit && !mcview_is_in_panel (view))
|
||||
dlg_stop (h);
|
||||
else {
|
||||
mcview_update (view);
|
||||
}
|
||||
return i;
|
||||
|
||||
case WIDGET_FOCUS:
|
||||
view->dpy_bbar_dirty = TRUE;
|
||||
mcview_update (view);
|
||||
return MSG_HANDLED;
|
||||
|
||||
case WIDGET_DESTROY:
|
||||
mcview_done (view);
|
||||
if (mcview_is_in_panel (view))
|
||||
delete_hook (&select_file_hook, mcview_hook);
|
||||
return MSG_HANDLED;
|
||||
|
||||
default:
|
||||
return default_proc (msg, parm);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
cb_ret_t
|
||||
mcview_dialog_callback (Dlg_head * h, dlg_msg_t msg, int parm)
|
||||
{
|
||||
switch (msg) {
|
||||
case DLG_RESIZE:
|
||||
mcview_adjust_size (h);
|
||||
return MSG_HANDLED;
|
||||
|
||||
default:
|
||||
return default_dlg_callback (h, msg, parm);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_help_cmd (void)
|
||||
{
|
||||
interactive_display (NULL, "[Internal File Viewer]");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_quit_cmd (mcview_t * view)
|
||||
{
|
||||
if (mcview_ok_to_quit (view))
|
||||
dlg_stop (view->widget.parent);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Toggle between hex view and text view */
|
||||
void
|
||||
mcview_toggle_hex_mode_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_toggle_hex_mode (view);
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_line_cmd (mcview_t * view)
|
||||
{
|
||||
char *answer, *answer_end, prompt_format[BUF_SMALL], prompt[BUF_SMALL];
|
||||
off_t line, col;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
|
||||
g_snprintf (prompt_format, sizeof (prompt_format),
|
||||
_(" The current address is %s.\n"
|
||||
" Enter the new address:"), "0x%08" OFFSETTYPE_PRIX "");
|
||||
g_snprintf (prompt, sizeof (prompt), prompt_format, view->hex_cursor);
|
||||
answer = input_dialog (_(" Goto line "), prompt, MC_HISTORY_VIEW_GOTO_LINE, "");
|
||||
if (answer != NULL && answer[0] != '\0') {
|
||||
errno = 0;
|
||||
line = strtoul (answer, &answer_end, 10);
|
||||
if (*answer_end == '\0' && errno == 0 && line >= 1)
|
||||
mcview_moveto (view, line - 1, 0);
|
||||
}
|
||||
g_free (answer);
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_addr_cmd (mcview_t * view)
|
||||
{
|
||||
char *line, *error, prompt[BUF_SMALL];
|
||||
off_t addr;
|
||||
|
||||
g_snprintf (prompt, sizeof (prompt),
|
||||
_(" The current address is 0x%lx.\n" " Enter the new address:"),
|
||||
(long unsigned int) view->hex_cursor);
|
||||
line = input_dialog (_(" Goto Address "), prompt, MC_HISTORY_VIEW_GOTO_ADDR, "");
|
||||
if (line != NULL) {
|
||||
if (*line != '\0') {
|
||||
addr = strtoul (line, &error, 0);
|
||||
if ((*error == '\0') && mcview_get_byte (view, addr, NULL) == TRUE) {
|
||||
mcview_moveto_offset (view, addr);
|
||||
} else {
|
||||
message (D_ERROR, _("Warning"), _(" Invalid address "));
|
||||
}
|
||||
}
|
||||
g_free (line);
|
||||
}
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Toggle between hexview and hexedit mode */
|
||||
void
|
||||
mcview_toggle_hexedit_mode_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_toggle_hexedit_mode (view);
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_hexedit_save_changes_cmd (mcview_t * view)
|
||||
{
|
||||
(void) mcview_hexedit_save_changes (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Toggle between wrapped and unwrapped view */
|
||||
void
|
||||
mcview_toggle_wrap_mode_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_toggle_wrap_mode (view);
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Both views */
|
||||
void
|
||||
mcview_search_cmd (mcview_t * view)
|
||||
{
|
||||
if (mcview_dialog_search (view))
|
||||
mcview_do_search (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_toggle_magic_mode_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_toggle_magic_mode (view);
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_toggle_nroff_mode_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_toggle_nroff_mode (view);
|
||||
mcview_update (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_toggle_ruler_cmd (mcview_t * view)
|
||||
{
|
||||
mcview_display_toggle_ruler (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for work with coordinate cache (ccache)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This cache provides you with a fast lookup to map file offsets into
|
||||
line/column pairs and vice versa. The interface to the mapping is
|
||||
provided by the functions mcview_coord_to_offset() and
|
||||
mcview_offset_to_coord().
|
||||
|
||||
The cache is implemented as a simple sorted array holding entries
|
||||
that map some of the offsets to their line/column pair. Entries that
|
||||
are not cached themselves are interpolated (exactly) from their
|
||||
neighbor entries. The algorithm used for determining the line/column
|
||||
for a specific offset needs to be kept synchronized with the one used
|
||||
in display().
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define VIEW_COORD_CACHE_GRANUL 1024
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_coord_cache_entry_less (const struct coord_cache_entry *a,
|
||||
const struct coord_cache_entry *b, enum ccache_type crit,
|
||||
gboolean nroff_mode)
|
||||
{
|
||||
if (crit == CCACHE_OFFSET)
|
||||
return (a->cc_offset < b->cc_offset);
|
||||
|
||||
if (a->cc_line < b->cc_line)
|
||||
return TRUE;
|
||||
|
||||
if (a->cc_line == b->cc_line) {
|
||||
if (nroff_mode) {
|
||||
return (a->cc_nroff_column < b->cc_nroff_column);
|
||||
} else {
|
||||
return (a->cc_column < b->cc_column);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef MC_ENABLE_DEBUGGING_CODE
|
||||
|
||||
void
|
||||
mcview_ccache_dump (mcview_t * view)
|
||||
{
|
||||
FILE *f;
|
||||
off_t offset, line, column, nextline_offset, filesize;
|
||||
guint i;
|
||||
const struct coord_cache_entry *cache;
|
||||
|
||||
assert (view->coord_cache != NULL);
|
||||
|
||||
filesize = mcview_get_filesize (view);
|
||||
cache = &(g_array_index (view->coord_cache, struct coord_cache_entry, 0));
|
||||
|
||||
f = fopen ("mcview-ccache.out", "w");
|
||||
if (f == NULL)
|
||||
return;
|
||||
(void) setvbuf (f, NULL, _IONBF, 0);
|
||||
|
||||
/* cache entries */
|
||||
for (i = 0; i < view->coord_cache->len; i++) {
|
||||
(void) fprintf (f,
|
||||
"entry %8u "
|
||||
"offset %8" OFFSETTYPE_PRId " "
|
||||
"line %8" OFFSETTYPE_PRId " "
|
||||
"column %8" OFFSETTYPE_PRId " "
|
||||
"nroff_column %8" OFFSETTYPE_PRId "\n",
|
||||
(unsigned int) i, cache[i].cc_offset, cache[i].cc_line,
|
||||
cache[i].cc_column, cache[i].cc_nroff_column);
|
||||
}
|
||||
(void) fprintf (f, "\n");
|
||||
|
||||
/* offset -> line/column translation */
|
||||
for (offset = 0; offset < filesize; offset++) {
|
||||
mcview_offset_to_coord (view, &line, &column, offset);
|
||||
(void) fprintf (f,
|
||||
"offset %8" OFFSETTYPE_PRId " "
|
||||
"line %8" OFFSETTYPE_PRId " "
|
||||
"column %8" OFFSETTYPE_PRId "\n", offset, line, column);
|
||||
}
|
||||
|
||||
/* line/column -> offset translation */
|
||||
for (line = 0; TRUE; line++) {
|
||||
mcview_coord_to_offset (view, &nextline_offset, line + 1, 0);
|
||||
(void) fprintf (f, "nextline_offset %8" OFFSETTYPE_PRId "\n", nextline_offset);
|
||||
|
||||
for (column = 0; TRUE; column++) {
|
||||
mcview_coord_to_offset (view, &offset, line, column);
|
||||
if (offset >= nextline_offset)
|
||||
break;
|
||||
|
||||
(void) fprintf (f,
|
||||
"line %8" OFFSETTYPE_PRId " column %8" OFFSETTYPE_PRId " offset %8"
|
||||
OFFSETTYPE_PRId "\n", line, column, offset);
|
||||
}
|
||||
|
||||
if (nextline_offset >= filesize - 1)
|
||||
break;
|
||||
}
|
||||
|
||||
(void) fclose (f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Find and return the index of the last cache entry that is
|
||||
* smaller than ''coord'', according to the criterion ''sort_by''. */
|
||||
guint
|
||||
mcview_ccache_find (mcview_t * view, const struct coord_cache_entry *cache,
|
||||
const struct coord_cache_entry *coord, enum ccache_type sort_by)
|
||||
{
|
||||
guint base, i, limit;
|
||||
|
||||
limit = view->coord_cache->len;
|
||||
assert (limit != 0);
|
||||
|
||||
base = 0;
|
||||
while (limit > 1) {
|
||||
i = base + limit / 2;
|
||||
if (mcview_coord_cache_entry_less (coord, &cache[i], sort_by, view->text_nroff_mode)) {
|
||||
/* continue the search in the lower half of the cache */
|
||||
} else {
|
||||
/* continue the search in the upper half of the cache */
|
||||
base = i;
|
||||
}
|
||||
limit = (limit + 1) / 2;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Look up the missing components of ''coord'', which are given by
|
||||
* ''lookup_what''. The function returns the smallest value that
|
||||
* matches the existing components of ''coord''.
|
||||
*/
|
||||
void
|
||||
mcview_ccache_lookup (mcview_t * view, struct coord_cache_entry *coord,
|
||||
enum ccache_type lookup_what)
|
||||
{
|
||||
guint i;
|
||||
struct coord_cache_entry *cache, current, next, entry;
|
||||
enum ccache_type sorter;
|
||||
off_t limit;
|
||||
enum {
|
||||
NROFF_START,
|
||||
NROFF_BACKSPACE,
|
||||
NROFF_CONTINUATION
|
||||
} nroff_state;
|
||||
|
||||
if (!view->coord_cache) {
|
||||
view->coord_cache = g_array_new (FALSE, FALSE, sizeof (struct coord_cache_entry));
|
||||
current.cc_offset = 0;
|
||||
current.cc_line = 0;
|
||||
current.cc_column = 0;
|
||||
current.cc_nroff_column = 0;
|
||||
g_array_append_val (view->coord_cache, current);
|
||||
}
|
||||
|
||||
sorter = (lookup_what == CCACHE_OFFSET) ? CCACHE_LINECOL : CCACHE_OFFSET;
|
||||
|
||||
tty_enable_interrupt_key ();
|
||||
|
||||
retry:
|
||||
/* find the two neighbor entries in the cache */
|
||||
cache = &(g_array_index (view->coord_cache, struct coord_cache_entry, 0));
|
||||
i = mcview_ccache_find (view, cache, coord, sorter);
|
||||
/* now i points to the lower neighbor in the cache */
|
||||
|
||||
current = cache[i];
|
||||
if (i + 1 < view->coord_cache->len)
|
||||
limit = cache[i + 1].cc_offset;
|
||||
else
|
||||
limit = current.cc_offset + VIEW_COORD_CACHE_GRANUL;
|
||||
|
||||
entry = current;
|
||||
nroff_state = NROFF_START;
|
||||
for (; current.cc_offset < limit; current = next) {
|
||||
int c, nextc;
|
||||
|
||||
if (! mcview_get_byte (view, current.cc_offset, &c))
|
||||
break;
|
||||
|
||||
if (!mcview_coord_cache_entry_less (¤t, coord, sorter, view->text_nroff_mode)) {
|
||||
if (lookup_what == CCACHE_OFFSET && view->text_nroff_mode && nroff_state != NROFF_START) {
|
||||
/* don't break here */
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide useful default values for ''next'' */
|
||||
next.cc_offset = current.cc_offset + 1;
|
||||
next.cc_line = current.cc_line;
|
||||
next.cc_column = current.cc_column + 1;
|
||||
next.cc_nroff_column = current.cc_nroff_column + 1;
|
||||
|
||||
/* and override some of them as necessary. */
|
||||
if (c == '\r') {
|
||||
mcview_get_byte_indexed (view, current.cc_offset, 1, &nextc);
|
||||
|
||||
/* Ignore '\r' if it is followed by '\r' or '\n'. If it is
|
||||
* followed by anything else, it is a Mac line ending and
|
||||
* produces a line break.
|
||||
*/
|
||||
if (nextc == '\r' || nextc == '\n') {
|
||||
next.cc_column = current.cc_column;
|
||||
next.cc_nroff_column = current.cc_nroff_column;
|
||||
} else {
|
||||
next.cc_line = current.cc_line + 1;
|
||||
next.cc_column = 0;
|
||||
next.cc_nroff_column = 0;
|
||||
}
|
||||
|
||||
} else if (nroff_state == NROFF_BACKSPACE) {
|
||||
next.cc_nroff_column = current.cc_nroff_column - 1;
|
||||
|
||||
} else if (c == '\t') {
|
||||
next.cc_column = mcview_offset_rounddown (current.cc_column, 8) + 8;
|
||||
next.cc_nroff_column = mcview_offset_rounddown (current.cc_nroff_column, 8) + 8;
|
||||
|
||||
} else if (c == '\n') {
|
||||
next.cc_line = current.cc_line + 1;
|
||||
next.cc_column = 0;
|
||||
next.cc_nroff_column = 0;
|
||||
|
||||
} else {
|
||||
/* Use all default values from above */
|
||||
}
|
||||
|
||||
switch (nroff_state) {
|
||||
case NROFF_START:
|
||||
case NROFF_CONTINUATION:
|
||||
if (mcview_is_nroff_sequence (view, current.cc_offset))
|
||||
nroff_state = NROFF_BACKSPACE;
|
||||
else
|
||||
nroff_state = NROFF_START;
|
||||
break;
|
||||
case NROFF_BACKSPACE:
|
||||
nroff_state = NROFF_CONTINUATION;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cache entries must guarantee that for each i < j,
|
||||
* line[i] <= line[j] and column[i] < column[j]. In the case of
|
||||
* nroff sequences and '\r' characters, this is not guaranteed,
|
||||
* so we cannot save them. */
|
||||
if (nroff_state == NROFF_START && c != '\r')
|
||||
entry = next;
|
||||
}
|
||||
|
||||
if (i + 1 == view->coord_cache->len && entry.cc_offset != cache[i].cc_offset) {
|
||||
g_array_append_val (view->coord_cache, entry);
|
||||
|
||||
if (!tty_got_interrupt ())
|
||||
goto retry;
|
||||
}
|
||||
|
||||
tty_disable_interrupt_key ();
|
||||
|
||||
if (lookup_what == CCACHE_OFFSET) {
|
||||
coord->cc_offset = current.cc_offset;
|
||||
} else {
|
||||
coord->cc_line = current.cc_line;
|
||||
coord->cc_column = current.cc_column;
|
||||
coord->cc_nroff_column = current.cc_nroff_column;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Functions for datasources
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The data source provides the viewer with data from either a file, a
|
||||
string or the output of a command. The mcview_get_byte() function can be
|
||||
used to get the value of a byte at a specific offset. If the offset
|
||||
is out of range, -1 is returned. The function mcview_get_byte_indexed(a,b)
|
||||
returns the byte at the offset a+b, or -1 if a+b is out of range.
|
||||
|
||||
The mcview_set_byte() function has the effect that later calls to
|
||||
mcview_get_byte() will return the specified byte for this offset. This
|
||||
function is designed only for use by the hexedit component after
|
||||
saving its changes. Inspect the source before you want to use it for
|
||||
other purposes.
|
||||
|
||||
The mcview_get_filesize() function returns the current size of the
|
||||
data source. If the growing buffer is used, this size may increase
|
||||
later on. Use the mcview_may_still_grow() function when you want to
|
||||
know if the size can change later.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_set_datasource_stdio_pipe (mcview_t * view, FILE * fp)
|
||||
{
|
||||
assert (fp != NULL);
|
||||
view->datasource = DS_STDIO_PIPE;
|
||||
view->ds_stdio_pipe = fp;
|
||||
|
||||
mcview_growbuf_init (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_set_datasource_none (mcview_t * view)
|
||||
{
|
||||
view->datasource = DS_NONE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
off_t
|
||||
mcview_get_filesize (mcview_t * view)
|
||||
{
|
||||
switch (view->datasource) {
|
||||
case DS_NONE:
|
||||
return 0;
|
||||
case DS_STDIO_PIPE:
|
||||
case DS_VFS_PIPE:
|
||||
return mcview_growbuf_filesize (view);
|
||||
case DS_FILE:
|
||||
return view->ds_file_filesize;
|
||||
case DS_STRING:
|
||||
return view->ds_string_len;
|
||||
default:
|
||||
assert (!"Unknown datasource type");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
mcview_get_ptr_file (mcview_t * view, off_t byte_index)
|
||||
{
|
||||
assert (view->datasource == DS_FILE);
|
||||
|
||||
mcview_file_load_data (view, byte_index);
|
||||
if (mcview_already_loaded (view->ds_file_offset, byte_index, view->ds_file_datalen))
|
||||
return (char *) (view->ds_file_data + (byte_index - view->ds_file_offset));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
mcview_get_ptr_string (mcview_t * view, off_t byte_index)
|
||||
{
|
||||
assert (view->datasource == DS_STRING);
|
||||
if (byte_index < view->ds_string_len)
|
||||
return (char *) (view->ds_string_data + byte_index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mcview_get_utf (mcview_t * view, off_t byte_index, int *char_width, gboolean * result)
|
||||
{
|
||||
gchar *str = NULL;
|
||||
int res = -1;
|
||||
gunichar ch;
|
||||
gchar *next_ch = NULL;
|
||||
int width = 0;
|
||||
|
||||
*result = TRUE;
|
||||
|
||||
switch (view->datasource) {
|
||||
case DS_STDIO_PIPE:
|
||||
case DS_VFS_PIPE:
|
||||
str = mcview_get_ptr_growing_buffer (view, byte_index);
|
||||
break;
|
||||
case DS_FILE:
|
||||
str = mcview_get_ptr_file (view, byte_index);
|
||||
break;
|
||||
case DS_STRING:
|
||||
str = mcview_get_ptr_string (view, byte_index);
|
||||
break;
|
||||
case DS_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (str == NULL) {
|
||||
*result = FALSE;
|
||||
width = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = g_utf8_get_char_validated (str, -1);
|
||||
|
||||
if (res < 0) {
|
||||
ch = *str;
|
||||
width = 0;
|
||||
} else {
|
||||
ch = res;
|
||||
/* Calculate UTF-8 char width */
|
||||
next_ch = g_utf8_next_char (str);
|
||||
if (next_ch) {
|
||||
width = next_ch - str;
|
||||
} else {
|
||||
ch = 0;
|
||||
width = 0;
|
||||
}
|
||||
}
|
||||
*char_width = width;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_get_byte_string (mcview_t * view, off_t byte_index, int *retval)
|
||||
{
|
||||
assert (view->datasource == DS_STRING);
|
||||
if (byte_index < view->ds_string_len) {
|
||||
if (retval)
|
||||
*retval = view->ds_string_data[byte_index];
|
||||
return TRUE;
|
||||
}
|
||||
if (retval)
|
||||
*retval = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_get_byte_none (mcview_t * view, off_t byte_index, int *retval)
|
||||
{
|
||||
assert (view->datasource == DS_NONE);
|
||||
(void) &view;
|
||||
(void) byte_index;
|
||||
if (retval)
|
||||
*retval = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_set_byte (mcview_t * view, off_t offset, byte b)
|
||||
{
|
||||
(void) &b;
|
||||
assert (offset < mcview_get_filesize (view));
|
||||
assert (view->datasource == DS_FILE);
|
||||
view->ds_file_datalen = 0; /* just force reloading */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*static inline*/
|
||||
void
|
||||
mcview_file_load_data (mcview_t * view, off_t byte_index)
|
||||
{
|
||||
off_t blockoffset;
|
||||
ssize_t res;
|
||||
size_t bytes_read;
|
||||
|
||||
assert (view->datasource == DS_FILE);
|
||||
|
||||
if (mcview_already_loaded (view->ds_file_offset, byte_index, view->ds_file_datalen))
|
||||
return;
|
||||
|
||||
if (byte_index >= view->ds_file_filesize)
|
||||
return;
|
||||
|
||||
blockoffset = mcview_offset_rounddown (byte_index, view->ds_file_datasize);
|
||||
if (mc_lseek (view->ds_file_fd, blockoffset, SEEK_SET) == -1)
|
||||
goto error;
|
||||
|
||||
bytes_read = 0;
|
||||
while (bytes_read < view->ds_file_datasize) {
|
||||
res =
|
||||
mc_read (view->ds_file_fd, view->ds_file_data + bytes_read,
|
||||
view->ds_file_datasize - bytes_read);
|
||||
if (res == -1)
|
||||
goto error;
|
||||
if (res == 0)
|
||||
break;
|
||||
bytes_read += (size_t) res;
|
||||
}
|
||||
view->ds_file_offset = blockoffset;
|
||||
if (bytes_read > view->ds_file_filesize - view->ds_file_offset) {
|
||||
/* the file has grown in the meantime -- stick to the old size */
|
||||
view->ds_file_datalen = view->ds_file_filesize - view->ds_file_offset;
|
||||
} else {
|
||||
view->ds_file_datalen = bytes_read;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
view->ds_file_datalen = 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_close_datasource (mcview_t * view)
|
||||
{
|
||||
switch (view->datasource) {
|
||||
case DS_NONE:
|
||||
break;
|
||||
case DS_STDIO_PIPE:
|
||||
if (view->ds_stdio_pipe != NULL) {
|
||||
(void) pclose (view->ds_stdio_pipe);
|
||||
mcview_display (view);
|
||||
close_error_pipe (D_NORMAL, NULL);
|
||||
view->ds_stdio_pipe = NULL;
|
||||
}
|
||||
mcview_growbuf_free (view);
|
||||
break;
|
||||
case DS_VFS_PIPE:
|
||||
if (view->ds_vfs_pipe != -1) {
|
||||
(void) mc_close (view->ds_vfs_pipe);
|
||||
view->ds_vfs_pipe = -1;
|
||||
}
|
||||
mcview_growbuf_free (view);
|
||||
break;
|
||||
case DS_FILE:
|
||||
(void) mc_close (view->ds_file_fd);
|
||||
view->ds_file_fd = -1;
|
||||
g_free (view->ds_file_data);
|
||||
view->ds_file_data = NULL;
|
||||
break;
|
||||
case DS_STRING:
|
||||
g_free (view->ds_string_data);
|
||||
view->ds_string_data = NULL;
|
||||
break;
|
||||
default:
|
||||
assert (!"Unknown datasource type");
|
||||
}
|
||||
view->datasource = DS_NONE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_set_datasource_file (mcview_t * view, int fd, const struct stat *st)
|
||||
{
|
||||
view->datasource = DS_FILE;
|
||||
view->ds_file_fd = fd;
|
||||
view->ds_file_filesize = st->st_size;
|
||||
view->ds_file_offset = 0;
|
||||
view->ds_file_data = g_malloc (4096);
|
||||
view->ds_file_datalen = 0;
|
||||
view->ds_file_datasize = 4096;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_load_command_output (mcview_t * view, const char *command)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
mcview_close_datasource (view);
|
||||
|
||||
open_error_pipe ();
|
||||
if ((fp = popen (command, "r")) == NULL) {
|
||||
/* Avoid two messages. Message from stderr has priority. */
|
||||
mcview_display (view);
|
||||
if (!close_error_pipe (mcview_is_in_panel (view) ? -1 : D_ERROR, NULL))
|
||||
mcview_show_error (view, _(" Cannot spawn child process "));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* First, check if filter produced any output */
|
||||
mcview_set_datasource_stdio_pipe (view, fp);
|
||||
if (! mcview_get_byte (view, 0, NULL)) {
|
||||
mcview_close_datasource (view);
|
||||
|
||||
/* Avoid two messages. Message from stderr has priority. */
|
||||
mcview_display (view);
|
||||
if (!close_error_pipe (mcview_is_in_panel (view) ? -1 : D_ERROR, NULL))
|
||||
mcview_show_error (view, _("Empty output from child filter"));
|
||||
return FALSE;
|
||||
} else {
|
||||
/*
|
||||
* At least something was read correctly. Close stderr and let
|
||||
* program die if it will try to write something there.
|
||||
*
|
||||
* Ideally stderr should be read asynchronously to prevent programs
|
||||
* from blocking (poll/select multiplexor).
|
||||
*/
|
||||
close_error_pipe (D_NORMAL, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_set_datasource_vfs_pipe (mcview_t * view, int fd)
|
||||
{
|
||||
assert (fd != -1);
|
||||
view->datasource = DS_VFS_PIPE;
|
||||
view->ds_vfs_pipe = fd;
|
||||
|
||||
mcview_growbuf_init (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_set_datasource_string (mcview_t * view, const char *s)
|
||||
{
|
||||
view->datasource = DS_STRING;
|
||||
view->ds_string_data = (byte *) g_strdup (s);
|
||||
view->ds_string_len = strlen (s);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for paint dialogs
|
||||
|
||||
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 "../src/global.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "internal.h"
|
||||
#include "../src/charsets.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_dialog_search (mcview_t * view)
|
||||
{
|
||||
enum {
|
||||
SEARCH_DLG_MIN_HEIGHT = 11,
|
||||
SEARCH_DLG_HEIGHT_SUPPLY = 3,
|
||||
SEARCH_DLG_WIDTH = 58
|
||||
};
|
||||
|
||||
char *defval = g_strdup (view->last_search_string != NULL ? view->last_search_string : "");
|
||||
char *exp = NULL;
|
||||
#ifdef HAVE_CHARSET
|
||||
GString *tmp;
|
||||
#endif
|
||||
|
||||
int ttype_of_search = (int) view->search_type;
|
||||
int tall_codepages = (int) view->search_all_codepages;
|
||||
int tsearch_case = (int) view->search_case;
|
||||
int twhole_words = (int) view->whole_words;
|
||||
int tsearch_backwards = (int) view->search_backwards;
|
||||
int qd_result;
|
||||
|
||||
gchar **list_of_types = mc_search_get_types_strings_array ();
|
||||
int SEARCH_DLG_HEIGHT =
|
||||
SEARCH_DLG_MIN_HEIGHT + g_strv_length (list_of_types) - SEARCH_DLG_HEIGHT_SUPPLY;
|
||||
|
||||
QuickWidget quick_widgets[] = {
|
||||
|
||||
{quick_button, 6, 10, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, N_("&Cancel"), 0,
|
||||
B_CANCEL, 0, 0, NULL, NULL, NULL},
|
||||
|
||||
{quick_button, 2, 10, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, N_("&OK"), 0, B_ENTER,
|
||||
0, 0, NULL, NULL, NULL},
|
||||
|
||||
#ifdef HAVE_CHARSET
|
||||
{quick_checkbox, SEARCH_DLG_WIDTH / 2 + 3, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT,
|
||||
N_("All charsets"), 0, 0,
|
||||
&tall_codepages, 0, NULL, NULL, NULL},
|
||||
#endif
|
||||
|
||||
{quick_checkbox, SEARCH_DLG_WIDTH / 2 + 3, SEARCH_DLG_WIDTH, 6, SEARCH_DLG_HEIGHT,
|
||||
N_("&Whole words"), 0, 0, &twhole_words, 0, NULL, NULL, NULL},
|
||||
|
||||
{quick_checkbox, SEARCH_DLG_WIDTH / 2 + 3, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT,
|
||||
N_("&Backwards"), 0, 0, &tsearch_backwards, 0, NULL, NULL, NULL},
|
||||
|
||||
{quick_checkbox, SEARCH_DLG_WIDTH / 2 + 3, SEARCH_DLG_WIDTH, 4, SEARCH_DLG_HEIGHT,
|
||||
N_("case &Sensitive"), 0, 0,
|
||||
&tsearch_case, 0, NULL, NULL, NULL},
|
||||
|
||||
{quick_radio, 3, SEARCH_DLG_WIDTH, 4, SEARCH_DLG_HEIGHT, 0, g_strv_length (list_of_types),
|
||||
ttype_of_search,
|
||||
(void *) &ttype_of_search, const_cast (char **, list_of_types), NULL, NULL, NULL},
|
||||
|
||||
|
||||
{quick_input, 3, SEARCH_DLG_WIDTH, 3, SEARCH_DLG_HEIGHT, defval, 52, 0,
|
||||
0, &exp, N_("Search"), NULL, NULL},
|
||||
|
||||
{quick_label, 2, SEARCH_DLG_WIDTH, 2, SEARCH_DLG_HEIGHT,
|
||||
N_(" Enter search string:"), 0, 0, 0, 0, 0, NULL, NULL},
|
||||
|
||||
NULL_QuickWidget
|
||||
};
|
||||
|
||||
QuickDialog Quick_input = {
|
||||
SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT, -1, 0, N_("Search"),
|
||||
"[Input Line Keys]", quick_widgets, 0
|
||||
};
|
||||
|
||||
convert_to_display (defval);
|
||||
|
||||
qd_result = quick_dialog (&Quick_input);
|
||||
g_strfreev (list_of_types);
|
||||
|
||||
if (qd_result == B_CANCEL) {
|
||||
g_free (exp);
|
||||
g_free (defval);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
view->search_backwards = tsearch_backwards;
|
||||
view->search_type = (mc_search_type_t) ttype_of_search;
|
||||
|
||||
view->search_all_codepages = (gboolean) tall_codepages;
|
||||
view->search_case = (gboolean) tsearch_case;
|
||||
view->whole_words = (gboolean) twhole_words;
|
||||
|
||||
if (exp == NULL || exp[0] == '\0') {
|
||||
g_free (exp);
|
||||
g_free (defval);
|
||||
return FALSE;
|
||||
}
|
||||
#ifdef HAVE_CHARSET
|
||||
tmp = str_convert_to_input (exp);
|
||||
|
||||
if (tmp) {
|
||||
g_free (exp);
|
||||
exp = g_string_free (tmp, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free (view->last_search_string);
|
||||
view->last_search_string = exp;
|
||||
exp = NULL;
|
||||
|
||||
if (view->search_nroff_seq)
|
||||
mcview_nroff_seq_free (&(view->search_nroff_seq));
|
||||
|
||||
if (view->search)
|
||||
mc_search_free (view->search);
|
||||
|
||||
view->search = mc_search_new (view->last_search_string, -1);
|
||||
view->search_nroff_seq = mcview_nroff_seq_new (view);
|
||||
if (!view->search) {
|
||||
g_free (exp);
|
||||
g_free (defval);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
view->search->search_type = view->search_type;
|
||||
view->search->is_all_charsets = view->search_all_codepages;
|
||||
view->search->is_case_sentitive = view->search_case;
|
||||
view->search->search_fn = mcview_search_cmd_callback;
|
||||
view->search->update_fn = mcview_search_update_cmd_callback;
|
||||
view->search->whole_words = view->whole_words;
|
||||
|
||||
g_free (exp);
|
||||
g_free (defval);
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for whow info on display
|
||||
|
||||
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 "../src/global.h"
|
||||
#include "../src/tty/color.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "../src/tty/key.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "internal.h"
|
||||
#include "mcviewer.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/* If set, show a ruler */
|
||||
static enum ruler_type {
|
||||
RULER_NONE,
|
||||
RULER_TOP,
|
||||
RULER_BOTTOM
|
||||
} ruler = RULER_NONE;
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline void
|
||||
mcview_my_define (Dlg_head * h, int idx, const char *text, void (*fn) (mcview_t *), mcview_t * view)
|
||||
{
|
||||
buttonbar_set_label_data (h, idx, text, (buttonbarfn) fn, view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Define labels and handlers for functional keys */
|
||||
static void
|
||||
mcview_labels (mcview_t * view)
|
||||
{
|
||||
const char *text;
|
||||
Dlg_head *h = view->widget.parent;
|
||||
|
||||
buttonbar_set_label (h, 1, Q_ ("ButtonBar|Help"), mcview_help_cmd);
|
||||
|
||||
mcview_my_define (h, 10, Q_ ("ButtonBar|Quit"), mcview_quit_cmd, view);
|
||||
text = view->hex_mode ? Q_ ("ButtonBar|Ascii") : Q_ ("ButtonBar|Hex");
|
||||
mcview_my_define (h, 4, text, mcview_toggle_hex_mode_cmd, view);
|
||||
text = view->hex_mode ? Q_ ("ButtonBar|Goto") : Q_ ("ButtonBar|Line");
|
||||
mcview_my_define (h, 5, text,
|
||||
view->hex_mode ? mcview_moveto_addr_cmd : mcview_moveto_line_cmd, view);
|
||||
|
||||
if (view->hex_mode) {
|
||||
if (view->hexedit_mode) {
|
||||
mcview_my_define (h, 2, Q_ ("ButtonBar|View"), mcview_toggle_hexedit_mode_cmd, view);
|
||||
} else if (view->datasource == DS_FILE) {
|
||||
mcview_my_define (h, 2, Q_ ("ButtonBar|Edit"), mcview_toggle_hexedit_mode_cmd, view);
|
||||
} else {
|
||||
buttonbar_clear_label (h, 2);
|
||||
}
|
||||
mcview_my_define (h, 6, Q_ ("ButtonBar|Save"), mcview_hexedit_save_changes_cmd, view);
|
||||
} else {
|
||||
text = view->text_wrap_mode ? Q_ ("ButtonBar|UnWrap") : Q_ ("ButtonBar|Wrap");
|
||||
mcview_my_define (h, 2, text, mcview_toggle_wrap_mode_cmd, view);
|
||||
}
|
||||
|
||||
text = view->hex_mode ? Q_ ("ButtonBar|HxSrch") : Q_ ("ButtonBar|Search");
|
||||
mcview_my_define (h, 7, text, mcview_search_cmd, view);
|
||||
text = view->magic_mode ? Q_ ("ButtonBar|Raw") : Q_ ("ButtonBar|Parse");
|
||||
mcview_my_define (h, 8, text, mcview_toggle_magic_mode_cmd, view);
|
||||
|
||||
/* don't override the key to access the main menu */
|
||||
if (!mcview_is_in_panel (view)) {
|
||||
text = view->text_nroff_mode ? Q_ ("ButtonBar|Unform") : Q_ ("ButtonBar|Format");
|
||||
mcview_my_define (h, 9, text, mcview_toggle_nroff_mode_cmd, view);
|
||||
mcview_my_define (h, 3, Q_ ("ButtonBar|Quit"), mcview_quit_cmd, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static void
|
||||
mcview_display_status (mcview_t * view)
|
||||
{
|
||||
const screen_dimen top = view->status_area.top;
|
||||
const screen_dimen left = view->status_area.left;
|
||||
const screen_dimen width = view->status_area.width;
|
||||
const screen_dimen height = view->status_area.height;
|
||||
const char *file_label, *file_name;
|
||||
screen_dimen file_label_width;
|
||||
int i;
|
||||
char *tmp;
|
||||
|
||||
if (height < 1)
|
||||
return;
|
||||
|
||||
tty_setcolor (SELECTED_COLOR);
|
||||
widget_move (view, top, left);
|
||||
tty_draw_hline (top, left, ' ', width);
|
||||
|
||||
file_label = _("File: %s");
|
||||
file_label_width = str_term_width1 (file_label) - 2;
|
||||
file_name = view->filename ? view->filename : view->command ? view->command : "";
|
||||
|
||||
if (width < file_label_width + 6)
|
||||
tty_print_string (str_fit_to_term (file_name, width, J_LEFT_FIT));
|
||||
else {
|
||||
i = (width > 22 ? 22 : width) - file_label_width;
|
||||
|
||||
tmp = g_strdup_printf (file_label, str_fit_to_term (file_name, i, J_LEFT_FIT));
|
||||
tty_print_string (tmp);
|
||||
g_free (tmp);
|
||||
if (width > 46) {
|
||||
widget_move (view, top, left + 24);
|
||||
/* FIXME: the format strings need to be changed when off_t changes */
|
||||
if (view->hex_mode)
|
||||
tty_printf (_("Offset 0x%08lx"), (unsigned long) view->hex_cursor);
|
||||
else {
|
||||
off_t line, col;
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
tty_printf (_("Line %lu Col %lu"),
|
||||
(unsigned long) line + 1,
|
||||
(unsigned long) (view->text_wrap_mode ? col : view->dpy_text_column));
|
||||
}
|
||||
}
|
||||
if (width > 62) {
|
||||
off_t filesize;
|
||||
filesize = mcview_get_filesize (view);
|
||||
widget_move (view, top, left + 43);
|
||||
if (!mcview_may_still_grow (view)) {
|
||||
tty_printf (_("%s bytes"), size_trunc (filesize));
|
||||
} else {
|
||||
tty_printf (_(">= %s bytes"), size_trunc (filesize));
|
||||
}
|
||||
}
|
||||
if (width > 26) {
|
||||
mcview_percent (view, view->hex_mode ? view->hex_cursor : view->dpy_end);
|
||||
}
|
||||
}
|
||||
tty_setcolor (SELECTED_COLOR);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_update (mcview_t * view)
|
||||
{
|
||||
static int dirt_limit = 1;
|
||||
|
||||
if (view->dpy_bbar_dirty) {
|
||||
view->dpy_bbar_dirty = FALSE;
|
||||
mcview_labels (view);
|
||||
buttonbar_redraw (view->widget.parent);
|
||||
}
|
||||
|
||||
if (view->dirty > dirt_limit) {
|
||||
/* Too many updates skipped -> force a update */
|
||||
mcview_display (view);
|
||||
view->dirty = 0;
|
||||
/* Raise the update skipping limit */
|
||||
dirt_limit++;
|
||||
if (dirt_limit > mcview_max_dirt_limit)
|
||||
dirt_limit = mcview_max_dirt_limit;
|
||||
}
|
||||
if (view->dirty) {
|
||||
if (is_idle ()) {
|
||||
/* We have time to update the screen properly */
|
||||
mcview_display (view);
|
||||
view->dirty = 0;
|
||||
if (dirt_limit > 1)
|
||||
dirt_limit--;
|
||||
} else {
|
||||
/* We are busy -> skipping full update,
|
||||
only the status line is updated */
|
||||
mcview_display_status (view);
|
||||
}
|
||||
/* Here we had a refresh, if fast scrolling does not work
|
||||
restore the refresh, although this should not happen */
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Displays as much data from view->dpy_start as fits on the screen */
|
||||
void
|
||||
mcview_display (mcview_t * view)
|
||||
{
|
||||
mcview_compute_areas (view);
|
||||
if (view->hex_mode) {
|
||||
mcview_display_hex (view);
|
||||
} else if (view->text_nroff_mode) {
|
||||
mcview_display_nroff (view);
|
||||
} else {
|
||||
mcview_display_text (view);
|
||||
}
|
||||
mcview_display_status (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_compute_areas (mcview_t * view)
|
||||
{
|
||||
struct area view_area;
|
||||
screen_dimen height, rest, y;
|
||||
|
||||
/* The viewer is surrounded by a frame of size view->dpy_frame_size.
|
||||
* Inside that frame, there are: The status line (at the top),
|
||||
* the data area and an optional ruler, which is shown above or
|
||||
* below the data area. */
|
||||
|
||||
view_area.top = view->dpy_frame_size;
|
||||
view_area.left = view->dpy_frame_size;
|
||||
view_area.height = mcview_dimen_doz (view->widget.lines, 2 * view->dpy_frame_size);
|
||||
view_area.width = mcview_dimen_doz (view->widget.cols, 2 * view->dpy_frame_size);
|
||||
|
||||
/* Most coordinates of the areas equal those of the whole viewer */
|
||||
view->status_area = view_area;
|
||||
view->ruler_area = view_area;
|
||||
view->data_area = view_area;
|
||||
|
||||
/* Compute the heights of the areas */
|
||||
rest = view_area.height;
|
||||
|
||||
height = mcview_dimen_min (rest, 1);
|
||||
view->status_area.height = height;
|
||||
rest -= height;
|
||||
|
||||
height = mcview_dimen_min (rest, (ruler == RULER_NONE || view->hex_mode) ? 0 : 2);
|
||||
view->ruler_area.height = height;
|
||||
rest -= height;
|
||||
|
||||
view->data_area.height = rest;
|
||||
|
||||
/* Compute the position of the areas */
|
||||
y = view_area.top;
|
||||
|
||||
view->status_area.top = y;
|
||||
y += view->status_area.height;
|
||||
|
||||
if (ruler == RULER_TOP) {
|
||||
view->ruler_area.top = y;
|
||||
y += view->ruler_area.height;
|
||||
}
|
||||
|
||||
view->data_area.top = y;
|
||||
y += view->data_area.height;
|
||||
|
||||
if (ruler == RULER_BOTTOM) {
|
||||
view->ruler_area.top = y;
|
||||
y += view->ruler_area.height;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_update_bytes_per_line (mcview_t * view)
|
||||
{
|
||||
const screen_dimen cols = view->data_area.width;
|
||||
int bytes;
|
||||
|
||||
if (cols < 8 + 17)
|
||||
bytes = 4;
|
||||
else
|
||||
bytes = 4 * ((cols - 8) / ((cols < 80) ? 17 : 18));
|
||||
assert (bytes != 0);
|
||||
|
||||
view->bytes_per_line = bytes;
|
||||
view->dirty = mcview_max_dirt_limit + 1; /* To force refresh */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_toggle_ruler (mcview_t * view)
|
||||
{
|
||||
static const enum ruler_type next[3] = {
|
||||
RULER_TOP,
|
||||
RULER_BOTTOM,
|
||||
RULER_NONE
|
||||
};
|
||||
|
||||
assert ((size_t) ruler < 3);
|
||||
ruler = next[(size_t) ruler];
|
||||
view->dirty++;
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_clean (mcview_t * view)
|
||||
{
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
widget_erase ((Widget *) view);
|
||||
if (view->dpy_frame_size != 0) {
|
||||
tty_draw_box (view->widget.y, view->widget.x, view->widget.lines, view->widget.cols);
|
||||
/* draw_double_box (view->widget.parent, view->widget.y,
|
||||
view->widget.x, view->widget.lines, view->widget.cols);*/
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_ruler (mcview_t * view)
|
||||
{
|
||||
static const char ruler_chars[] = "|----*----";
|
||||
const screen_dimen top = view->ruler_area.top;
|
||||
const screen_dimen left = view->ruler_area.left;
|
||||
const screen_dimen width = view->ruler_area.width;
|
||||
const screen_dimen height = view->ruler_area.height;
|
||||
const screen_dimen line_row = (ruler == RULER_TOP) ? 0 : 1;
|
||||
const screen_dimen nums_row = (ruler == RULER_TOP) ? 1 : 0;
|
||||
|
||||
char r_buff[10];
|
||||
off_t cl;
|
||||
screen_dimen c;
|
||||
|
||||
if (ruler == RULER_NONE || height < 1)
|
||||
return;
|
||||
|
||||
tty_setcolor (MARKED_COLOR);
|
||||
for (c = 0; c < width; c++) {
|
||||
cl = view->dpy_text_column + c;
|
||||
if (line_row < height) {
|
||||
widget_move (view, top + line_row, left + c);
|
||||
tty_print_char (ruler_chars[cl % 10]);
|
||||
}
|
||||
|
||||
if ((cl != 0) && (cl % 10) == 0) {
|
||||
g_snprintf (r_buff, sizeof (r_buff), "%" OFFSETTYPE_PRId, (long unsigned int) cl);
|
||||
if (nums_row < height) {
|
||||
widget_move (view, top + nums_row, left + c - 1);
|
||||
tty_print_string (r_buff);
|
||||
}
|
||||
}
|
||||
}
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_adjust_size (Dlg_head * h)
|
||||
{
|
||||
mcview_t *view;
|
||||
WButtonBar *bar;
|
||||
|
||||
/* Look up the viewer and the buttonbar, we assume only two widgets here */
|
||||
view = (mcview_t *) find_widget_type (h, mcview_callback);
|
||||
bar = find_buttonbar (h);
|
||||
widget_set_size (&view->widget, 0, 0, LINES - 1, COLS);
|
||||
widget_set_size ((Widget *) bar, LINES - 1, 0, 1, COLS);
|
||||
|
||||
mcview_compute_areas (view);
|
||||
mcview_update_bytes_per_line (view);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_percent (mcview_t * view, off_t p)
|
||||
{
|
||||
const screen_dimen top = view->status_area.top;
|
||||
const screen_dimen right = view->status_area.left + view->status_area.width;
|
||||
const screen_dimen height = view->status_area.height;
|
||||
int percent;
|
||||
off_t filesize;
|
||||
|
||||
if (height < 1 || right < 4)
|
||||
return;
|
||||
if (mcview_may_still_grow (view))
|
||||
return;
|
||||
filesize = mcview_get_filesize (view);
|
||||
|
||||
if (filesize == 0 || view->dpy_end == filesize)
|
||||
percent = 100;
|
||||
else if (p > (INT_MAX / 100))
|
||||
percent = p / (filesize / 100);
|
||||
else
|
||||
percent = p * 100 / filesize;
|
||||
|
||||
widget_move (view, top, right - 4);
|
||||
tty_printf ("%3d%%", percent);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for work with growing bufers
|
||||
|
||||
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 <errno.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "internal.h"
|
||||
|
||||
/* Block size for reading files in parts */
|
||||
#define VIEW_PAGE_SIZE ((size_t) 8192)
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_growbuf_init (mcview_t * view)
|
||||
{
|
||||
view->growbuf_in_use = TRUE;
|
||||
view->growbuf_blockptr = NULL;
|
||||
view->growbuf_blocks = 0;
|
||||
view->growbuf_lastindex = VIEW_PAGE_SIZE;
|
||||
view->growbuf_finished = FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_growbuf_free (mcview_t * view)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
for (i = 0; i < view->growbuf_blocks; i++)
|
||||
g_free (view->growbuf_blockptr[i]);
|
||||
g_free (view->growbuf_blockptr);
|
||||
view->growbuf_blockptr = NULL;
|
||||
view->growbuf_in_use = FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
off_t
|
||||
mcview_growbuf_filesize (mcview_t * view)
|
||||
{
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
if (view->growbuf_blocks == 0)
|
||||
return 0;
|
||||
else
|
||||
return ((off_t) view->growbuf_blocks - 1) * VIEW_PAGE_SIZE + view->growbuf_lastindex;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Copies the output from the pipe to the growing buffer, until either
|
||||
* the end-of-pipe is reached or the interval [0..ofs) of the growing
|
||||
* buffer is completely filled. */
|
||||
void
|
||||
mcview_growbuf_read_until (mcview_t * view, off_t ofs)
|
||||
{
|
||||
ssize_t nread;
|
||||
byte *p;
|
||||
size_t bytesfree;
|
||||
gboolean short_read;
|
||||
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
if (view->growbuf_finished)
|
||||
return;
|
||||
|
||||
short_read = FALSE;
|
||||
while (mcview_growbuf_filesize (view) < ofs || short_read) {
|
||||
if (view->growbuf_lastindex == VIEW_PAGE_SIZE) {
|
||||
/* Append a new block to the growing buffer */
|
||||
byte *newblock = g_try_malloc (VIEW_PAGE_SIZE);
|
||||
byte **newblocks = g_try_malloc (sizeof (*newblocks) * (view->growbuf_blocks + 1));
|
||||
if (!newblock || !newblocks) {
|
||||
g_free (newblock);
|
||||
g_free (newblocks);
|
||||
return;
|
||||
}
|
||||
memcpy (newblocks, view->growbuf_blockptr, sizeof (*newblocks) * view->growbuf_blocks);
|
||||
g_free (view->growbuf_blockptr);
|
||||
view->growbuf_blockptr = newblocks;
|
||||
view->growbuf_blockptr[view->growbuf_blocks++] = newblock;
|
||||
view->growbuf_lastindex = 0;
|
||||
}
|
||||
p = view->growbuf_blockptr[view->growbuf_blocks - 1] + view->growbuf_lastindex;
|
||||
bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex;
|
||||
|
||||
if (view->datasource == DS_STDIO_PIPE) {
|
||||
nread = fread (p, 1, bytesfree, view->ds_stdio_pipe);
|
||||
if (nread == 0) {
|
||||
view->growbuf_finished = TRUE;
|
||||
(void) pclose (view->ds_stdio_pipe);
|
||||
mcview_display (view);
|
||||
close_error_pipe (D_NORMAL, NULL);
|
||||
view->ds_stdio_pipe = NULL;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
assert (view->datasource == DS_VFS_PIPE);
|
||||
do {
|
||||
nread = mc_read (view->ds_vfs_pipe, p, bytesfree);
|
||||
} while (nread == -1 && errno == EINTR);
|
||||
if (nread == -1 || nread == 0) {
|
||||
view->growbuf_finished = TRUE;
|
||||
(void) mc_close (view->ds_vfs_pipe);
|
||||
view->ds_vfs_pipe = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
short_read = ((size_t) nread < bytesfree);
|
||||
view->growbuf_lastindex += nread;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_get_byte_growing_buffer (mcview_t * view, off_t byte_index, int *retval)
|
||||
{
|
||||
if (retval)
|
||||
*retval = -1;
|
||||
off_t pageno = byte_index / VIEW_PAGE_SIZE;
|
||||
off_t pageindex = byte_index % VIEW_PAGE_SIZE;
|
||||
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
if ((size_t) pageno != pageno)
|
||||
return FALSE;
|
||||
|
||||
mcview_growbuf_read_until (view, byte_index + 1);
|
||||
if (view->growbuf_blocks == 0)
|
||||
return FALSE;
|
||||
if (pageno < view->growbuf_blocks - 1) {
|
||||
if (retval)
|
||||
*retval = view->growbuf_blockptr[pageno][pageindex];
|
||||
return TRUE;
|
||||
}
|
||||
if (pageno == view->growbuf_blocks - 1 && pageindex < view->growbuf_lastindex) {
|
||||
if (retval)
|
||||
*retval = view->growbuf_blockptr[pageno][pageindex];
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
mcview_get_ptr_growing_buffer (mcview_t * view, off_t byte_index)
|
||||
{
|
||||
off_t pageno = byte_index / VIEW_PAGE_SIZE;
|
||||
off_t pageindex = byte_index % VIEW_PAGE_SIZE;
|
||||
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
if ((size_t) pageno != pageno)
|
||||
return NULL;
|
||||
|
||||
mcview_growbuf_read_until (view, byte_index + 1);
|
||||
if (view->growbuf_blocks == 0)
|
||||
return NULL;
|
||||
if (pageno < view->growbuf_blocks - 1)
|
||||
return (char *) (view->growbuf_blockptr[pageno] + pageindex);
|
||||
if (pageno == view->growbuf_blocks - 1 && pageindex < view->growbuf_lastindex)
|
||||
return (char *) (view->growbuf_blockptr[pageno] + pageindex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for hex view
|
||||
|
||||
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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "../src/tty/color.h"
|
||||
#include "../src/main.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
typedef enum {
|
||||
MARK_NORMAL,
|
||||
MARK_SELECTED,
|
||||
MARK_CURSOR,
|
||||
MARK_CHANGED
|
||||
} mark_t;
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
static const char hex_char[] = "0123456789ABCDEF";
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_hex (mcview_t * view)
|
||||
{
|
||||
const screen_dimen top = view->data_area.top;
|
||||
const screen_dimen left = view->data_area.left;
|
||||
const screen_dimen height = view->data_area.height;
|
||||
const screen_dimen width = view->data_area.width;
|
||||
const int ngroups = view->bytes_per_line / 4;
|
||||
const screen_dimen text_start = 8 + 13 * ngroups + ((width < 80) ? 0 : (ngroups - 1 + 1));
|
||||
/* 8 characters are used for the file offset, and every hex group
|
||||
* takes 13 characters. On ``big'' screens, the groups are separated
|
||||
* by an extra vertical line, and there is an extra space before the
|
||||
* text column.
|
||||
*/
|
||||
|
||||
screen_dimen row, col;
|
||||
off_t from;
|
||||
int c;
|
||||
mark_t boldflag = MARK_NORMAL;
|
||||
struct hexedit_change_node *curr = view->change_list;
|
||||
size_t i;
|
||||
int cw = 1;
|
||||
int ch = 0;
|
||||
gboolean read_res = TRUE;
|
||||
|
||||
char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */
|
||||
int bytes; /* Number of bytes already printed on the line */
|
||||
|
||||
mcview_display_clean (view);
|
||||
|
||||
/* Find the first displayable changed byte */
|
||||
from = view->dpy_start;
|
||||
while (curr && (curr->offset < from)) {
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) {
|
||||
col = 0;
|
||||
|
||||
/* Print the hex offset */
|
||||
g_snprintf (hex_buff, sizeof (hex_buff), "%08" OFFSETTYPE_PRIX " ",
|
||||
(long unsigned int) from);
|
||||
widget_move (view, top + row, left);
|
||||
tty_setcolor (MARKED_COLOR);
|
||||
for (i = 0; col < width && hex_buff[i] != '\0'; i++) {
|
||||
tty_print_char (hex_buff[i]);
|
||||
/* tty_print_char(hex_buff[i]);*/
|
||||
col += 1;
|
||||
}
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
|
||||
for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) {
|
||||
|
||||
#ifdef HAVE_CHARSET
|
||||
if (view->utf8) {
|
||||
ch = mcview_get_utf (view, from, &cw, &read_res);
|
||||
if (!read_res)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (! mcview_get_byte (view, from, &c))
|
||||
break;
|
||||
|
||||
/* Save the cursor position for mcview_place_cursor() */
|
||||
if (from == view->hex_cursor && !view->hexview_in_text) {
|
||||
view->cursor_row = row;
|
||||
view->cursor_col = col;
|
||||
}
|
||||
|
||||
/* Determine the state of the current byte */
|
||||
boldflag =
|
||||
(from == view->hex_cursor) ? MARK_CURSOR
|
||||
: (curr != NULL && from == curr->offset) ? MARK_CHANGED
|
||||
: (view->search_start <= from &&
|
||||
from < view->search_end) ? MARK_SELECTED : MARK_NORMAL;
|
||||
|
||||
/* Determine the value of the current byte */
|
||||
if (curr != NULL && from == curr->offset) {
|
||||
c = curr->value;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
/* Select the color for the hex number */
|
||||
tty_setcolor (boldflag == MARK_NORMAL ? NORMAL_COLOR :
|
||||
boldflag == MARK_SELECTED ? MARKED_COLOR :
|
||||
boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
|
||||
/* boldflag == MARK_CURSOR */
|
||||
view->hexview_in_text ? MARKED_SELECTED_COLOR : VIEW_UNDERLINED_COLOR);
|
||||
|
||||
/* Print the hex number */
|
||||
widget_move (view, top + row, left + col);
|
||||
if (col < width) {
|
||||
tty_print_char (hex_char[c / 16]);
|
||||
col += 1;
|
||||
}
|
||||
if (col < width) {
|
||||
tty_print_char (hex_char[c % 16]);
|
||||
col += 1;
|
||||
}
|
||||
|
||||
/* Print the separator */
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
if (bytes != view->bytes_per_line - 1) {
|
||||
if (col < width) {
|
||||
tty_print_char (' ');
|
||||
col += 1;
|
||||
}
|
||||
|
||||
/* After every four bytes, print a group separator */
|
||||
if (bytes % 4 == 3) {
|
||||
if (view->data_area.width >= 80 && col < width) {
|
||||
tty_print_one_vline ();
|
||||
col += 1;
|
||||
}
|
||||
if (col < width) {
|
||||
tty_print_char (' ');
|
||||
col += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the color for the character; this differs from the
|
||||
* hex color when boldflag == MARK_CURSOR */
|
||||
tty_setcolor (boldflag == MARK_NORMAL ? NORMAL_COLOR :
|
||||
boldflag == MARK_SELECTED ? MARKED_COLOR :
|
||||
boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR :
|
||||
/* boldflag == MARK_CURSOR */
|
||||
view->hexview_in_text ? VIEW_UNDERLINED_COLOR : MARKED_SELECTED_COLOR);
|
||||
|
||||
#ifdef HAVE_CHARSET
|
||||
if (utf8_display) {
|
||||
if (!view->utf8) {
|
||||
ch = convert_from_8bit_to_utf_c ((unsigned char) ch, view->converter);
|
||||
}
|
||||
if (!g_unichar_isprint (ch))
|
||||
ch = '.';
|
||||
} else {
|
||||
if (view->utf8) {
|
||||
ch = convert_from_utf_to_current_c (ch, view->converter);
|
||||
} else {
|
||||
#endif
|
||||
ch = convert_to_display_c (ch);
|
||||
#ifdef HAVE_CHARSET
|
||||
}
|
||||
}
|
||||
#endif
|
||||
c = convert_to_display_c (c);
|
||||
if (!g_ascii_isprint (c))
|
||||
c = '.';
|
||||
|
||||
/* Print corresponding character on the text side */
|
||||
if (text_start + bytes < width) {
|
||||
widget_move (view, top + row, left + text_start + bytes);
|
||||
if (!view->utf8) {
|
||||
tty_print_char (c);
|
||||
} else {
|
||||
tty_print_anychar (ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the cursor position for mcview_place_cursor() */
|
||||
if (from == view->hex_cursor && view->hexview_in_text) {
|
||||
view->cursor_row = row;
|
||||
view->cursor_col = text_start + bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Be polite to the other functions */
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
|
||||
mcview_place_cursor (view);
|
||||
view->dpy_end = from;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_hexedit_save_changes (mcview_t * view)
|
||||
{
|
||||
struct hexedit_change_node *curr, *next;
|
||||
int fp, answer;
|
||||
char *text, *error;
|
||||
|
||||
if (view->change_list == NULL)
|
||||
return TRUE;
|
||||
|
||||
retry_save:
|
||||
assert (view->filename != NULL);
|
||||
fp = mc_open (view->filename, O_WRONLY);
|
||||
if (fp == -1)
|
||||
goto save_error;
|
||||
|
||||
for (curr = view->change_list; curr != NULL; curr = next) {
|
||||
next = curr->next;
|
||||
|
||||
if (mc_lseek (fp, curr->offset, SEEK_SET) == -1 || mc_write (fp, &(curr->value), 1) != 1)
|
||||
goto save_error;
|
||||
|
||||
/* delete the saved item from the change list */
|
||||
view->change_list = next;
|
||||
view->dirty++;
|
||||
mcview_set_byte (view, curr->offset, curr->value);
|
||||
g_free (curr);
|
||||
}
|
||||
|
||||
if (mc_close (fp) == -1) {
|
||||
error = g_strdup (strerror (errno));
|
||||
message (D_ERROR, _(" Save file "),
|
||||
_(" Error while closing the file: \n %s \n"
|
||||
" Data may have been written or not. "), error);
|
||||
g_free (error);
|
||||
}
|
||||
mcview_update (view);
|
||||
return TRUE;
|
||||
|
||||
save_error:
|
||||
error = g_strdup (strerror (errno));
|
||||
text = g_strdup_printf (_(" Cannot save file: \n %s "), error);
|
||||
g_free (error);
|
||||
(void) mc_close (fp);
|
||||
|
||||
answer = query_dialog (_(" Save file "), text, D_ERROR, 2, _("&Retry"), _("&Cancel"));
|
||||
g_free (text);
|
||||
|
||||
if (answer == 0)
|
||||
goto retry_save;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_toggle_hexedit_mode (mcview_t * view)
|
||||
{
|
||||
view->hexedit_mode = !view->hexedit_mode;
|
||||
view->dpy_bbar_dirty = TRUE;
|
||||
view->dirty++;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_hexedit_free_change_list (mcview_t * view)
|
||||
{
|
||||
struct hexedit_change_node *curr, *next;
|
||||
|
||||
for (curr = view->change_list; curr != NULL; curr = next) {
|
||||
next = curr->next;
|
||||
g_free (curr);
|
||||
}
|
||||
view->change_list = NULL;
|
||||
view->dirty++;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node)
|
||||
{
|
||||
/* chnode always either points to the head of the list or
|
||||
* to one of the ->next fields in the list. The value at
|
||||
* this location will be overwritten with the new node. */
|
||||
struct hexedit_change_node **chnode = head;
|
||||
|
||||
while (*chnode != NULL && (*chnode)->offset < node->offset)
|
||||
chnode = &((*chnode)->next);
|
||||
|
||||
node->next = *chnode;
|
||||
*chnode = node;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,163 @@
|
|||
#ifndef MC_VIEWER_INLINES_H
|
||||
#define MC_VIEWER_INLINES_H
|
||||
|
||||
/*** typedefs(not structures) and defined constants ********************/
|
||||
|
||||
/*** enums *************************************************************/
|
||||
|
||||
/*** structures declarations (and typedefs of structures)***************/
|
||||
|
||||
/*** global variables defined in .c file *******************************/
|
||||
|
||||
/*** declarations of public functions **********************************/
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
static inline off_t
|
||||
mcview_offset_doz (off_t a, off_t b)
|
||||
{
|
||||
return (a >= b) ? a - b : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline off_t
|
||||
mcview_offset_rounddown (off_t a, off_t b)
|
||||
{
|
||||
assert (b != 0);
|
||||
return a - a % b;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* difference or zero */
|
||||
static inline screen_dimen
|
||||
mcview_dimen_doz (screen_dimen a, screen_dimen b)
|
||||
{
|
||||
return (a >= b) ? a - b : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline screen_dimen
|
||||
mcview_dimen_min (screen_dimen a, screen_dimen b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* {{{ Simple Primitive Functions for mcview_t }}} */
|
||||
static inline gboolean
|
||||
mcview_is_in_panel (mcview_t * view)
|
||||
{
|
||||
return (view->dpy_frame_size != 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline gboolean
|
||||
mcview_may_still_grow (mcview_t * view)
|
||||
{
|
||||
return (view->growbuf_in_use && !view->growbuf_finished);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* returns TRUE if the idx lies in the half-open interval
|
||||
* [offset; offset + size), FALSE otherwise.
|
||||
*/
|
||||
static inline gboolean
|
||||
mcview_already_loaded (off_t offset, off_t idx, size_t size)
|
||||
{
|
||||
return (offset <= idx && idx - offset < size);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline gboolean
|
||||
mcview_get_byte_file (mcview_t * view, off_t byte_index, int *retval)
|
||||
{
|
||||
assert (view->datasource == DS_FILE);
|
||||
|
||||
mcview_file_load_data (view, byte_index);
|
||||
if (mcview_already_loaded (view->ds_file_offset, byte_index, view->ds_file_datalen)) {
|
||||
if (retval)
|
||||
*retval = view->ds_file_data[byte_index - view->ds_file_offset];
|
||||
return TRUE;
|
||||
}
|
||||
if (retval)
|
||||
*retval = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline gboolean
|
||||
mcview_get_byte (mcview_t * view, off_t offset, int *retval)
|
||||
{
|
||||
switch (view->datasource) {
|
||||
case DS_STDIO_PIPE:
|
||||
case DS_VFS_PIPE:
|
||||
return mcview_get_byte_growing_buffer (view, offset, retval);
|
||||
case DS_FILE:
|
||||
return mcview_get_byte_file (view, offset, retval);
|
||||
case DS_STRING:
|
||||
return mcview_get_byte_string (view, offset, retval);
|
||||
case DS_NONE:
|
||||
return mcview_get_byte_none (view, offset, retval);
|
||||
}
|
||||
assert (!"Unknown datasource type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline gboolean
|
||||
mcview_get_byte_indexed (mcview_t * view, off_t base, off_t ofs, int *retval)
|
||||
{
|
||||
if (base <= OFFSETTYPE_MAX - ofs) {
|
||||
return mcview_get_byte (view, base + ofs, retval);
|
||||
}
|
||||
if (retval)
|
||||
*retval = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline int
|
||||
mcview_count_backspaces (mcview_t * view, off_t offset)
|
||||
{
|
||||
int backspaces = 0;
|
||||
int c;
|
||||
while (offset >= 2 * backspaces && mcview_get_byte (view, offset - 2 * backspaces, &c)
|
||||
&& c == '\b')
|
||||
backspaces++;
|
||||
return backspaces;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline gboolean
|
||||
mcview_is_nroff_sequence (mcview_t * view, off_t offset)
|
||||
{
|
||||
int c0, c1, c2;
|
||||
|
||||
/* The following commands are ordered to speed up the calculation. */
|
||||
|
||||
if (! mcview_get_byte_indexed (view, offset, 1, &c1) || c1 != '\b')
|
||||
return FALSE;
|
||||
|
||||
if (! mcview_get_byte_indexed (view, offset, 0, &c0) || !g_ascii_isprint (c0))
|
||||
return FALSE;
|
||||
|
||||
if (! mcview_get_byte_indexed (view, offset, 2, &c2) || !g_ascii_isprint (c2))
|
||||
return FALSE;
|
||||
|
||||
return (c0 == c2 || c0 == '_' || (c0 == '+' && c2 == 'o'));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,318 @@
|
|||
#ifndef MC_VIEWER_INTERNAL_H
|
||||
#define MC_VIEWER_INTERNAL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
|
||||
#include "../src/widget.h"
|
||||
#include "../src/search/search.h"
|
||||
|
||||
/*** typedefs(not structures) and defined constants ********************/
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* A width or height on the screen */
|
||||
typedef unsigned int screen_dimen;
|
||||
|
||||
#define OFFSETTYPE_PRIX "lX"
|
||||
#define OFFSETTYPE_PRId "lu"
|
||||
|
||||
extern const off_t INVALID_OFFSET;
|
||||
extern const off_t OFFSETTYPE_MAX;
|
||||
|
||||
/*** enums *************************************************************/
|
||||
|
||||
/* data sources of the view */
|
||||
enum view_ds {
|
||||
DS_NONE, /* No data available */
|
||||
DS_STDIO_PIPE, /* Data comes from a pipe using popen/pclose */
|
||||
DS_VFS_PIPE, /* Data comes from a piped-in VFS file */
|
||||
DS_FILE, /* Data comes from a VFS file */
|
||||
DS_STRING /* Data comes from a string in memory */
|
||||
};
|
||||
|
||||
|
||||
enum ccache_type {
|
||||
CCACHE_OFFSET,
|
||||
CCACHE_LINECOL
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NROFF_TYPE_NONE = 0,
|
||||
NROFF_TYPE_BOLD = 1,
|
||||
NROFF_TYPE_UNDERLINE = 2
|
||||
} nroff_type_t;
|
||||
|
||||
/*** structures declarations (and typedefs of structures)***************/
|
||||
|
||||
/* A node for building a change list on change_list */
|
||||
struct hexedit_change_node {
|
||||
struct hexedit_change_node *next;
|
||||
off_t offset;
|
||||
byte value;
|
||||
};
|
||||
|
||||
struct area {
|
||||
screen_dimen top, left;
|
||||
screen_dimen height, width;
|
||||
};
|
||||
|
||||
|
||||
/* A cache entry for mapping offsets into line/column pairs and vice versa.
|
||||
* cc_offset, cc_line, and cc_column are the 0-based values of the offset,
|
||||
* line and column of that cache entry. cc_nroff_column is the column
|
||||
* corresponding to cc_offset in nroff mode.
|
||||
*/
|
||||
struct coord_cache_entry {
|
||||
off_t cc_offset;
|
||||
off_t cc_line;
|
||||
off_t cc_column;
|
||||
off_t cc_nroff_column;
|
||||
};
|
||||
|
||||
struct mcview_nroff_struct;
|
||||
|
||||
typedef struct mcview_struct {
|
||||
Widget widget;
|
||||
|
||||
char *filename; /* Name of the file */
|
||||
char *command; /* Command used to pipe data in */
|
||||
|
||||
enum view_ds datasource; /* Where the displayed data comes from */
|
||||
|
||||
/* stdio pipe data source */
|
||||
FILE *ds_stdio_pipe; /* Output of a shell command */
|
||||
|
||||
/* vfs pipe data source */
|
||||
int ds_vfs_pipe; /* Non-seekable vfs file descriptor */
|
||||
|
||||
/* vfs file data source */
|
||||
int ds_file_fd; /* File with random access */
|
||||
off_t ds_file_filesize; /* Size of the file */
|
||||
off_t ds_file_offset; /* Offset of the currently loaded data */
|
||||
byte *ds_file_data; /* Currently loaded data */
|
||||
size_t ds_file_datalen; /* Number of valid bytes in file_data */
|
||||
size_t ds_file_datasize; /* Number of allocated bytes in file_data */
|
||||
|
||||
/* string data source */
|
||||
byte *ds_string_data; /* The characters of the string */
|
||||
size_t ds_string_len; /* The length of the string */
|
||||
|
||||
/* Growing buffers information */
|
||||
gboolean growbuf_in_use; /* Use the growing buffers? */
|
||||
byte **growbuf_blockptr; /* Pointer to the block pointers */
|
||||
size_t growbuf_blocks; /* The number of blocks in *block_ptr */
|
||||
size_t growbuf_lastindex; /* Number of bytes in the last page of the
|
||||
growing buffer */
|
||||
gboolean growbuf_finished; /* TRUE when all data has been read. */
|
||||
|
||||
/* Editor modes */
|
||||
gboolean hex_mode; /* Hexview or Hexedit */
|
||||
gboolean hexedit_mode; /* Hexedit */
|
||||
gboolean hexview_in_text; /* Is the hexview cursor in the text area? */
|
||||
gboolean text_nroff_mode; /* Nroff-style highlighting */
|
||||
gboolean text_wrap_mode; /* Wrap text lines to fit them on the screen */
|
||||
gboolean magic_mode; /* Preprocess the file using external programs */
|
||||
gboolean utf8; /* It's multibyte file codeset */
|
||||
|
||||
/* Additional editor state */
|
||||
gboolean hexedit_lownibble; /* Are we editing the last significant nibble? */
|
||||
GArray *coord_cache; /* Cache for mapping offsets to cursor positions */
|
||||
|
||||
/* Display information */
|
||||
screen_dimen dpy_frame_size; /* Size of the frame surrounding the real viewer */
|
||||
off_t dpy_start; /* Offset of the displayed data */
|
||||
off_t dpy_end; /* Offset after the displayed data */
|
||||
off_t dpy_text_column; /* Number of skipped columns in non-wrap
|
||||
* text mode */
|
||||
off_t hex_cursor; /* Hexview cursor position in file */
|
||||
screen_dimen cursor_col; /* Cursor column */
|
||||
screen_dimen cursor_row; /* Cursor row */
|
||||
struct hexedit_change_node *change_list; /* Linked list of changes */
|
||||
struct area status_area; /* Where the status line is displayed */
|
||||
struct area ruler_area; /* Where the ruler is displayed */
|
||||
struct area data_area; /* Where the data is displayed */
|
||||
|
||||
int dirty; /* Number of skipped updates */
|
||||
gboolean dpy_bbar_dirty; /* Does the button bar need to be updated? */
|
||||
|
||||
/* Mode variables */
|
||||
int bytes_per_line; /* Number of bytes per line in hex mode */
|
||||
|
||||
/* Search variables */
|
||||
off_t search_start; /* First character to start searching from */
|
||||
off_t search_end; /* Length of found string or 0 if none was found */
|
||||
|
||||
/* Pointer to the last search command */
|
||||
gboolean want_to_quit; /* Prepare for cleanup ... */
|
||||
|
||||
/* Markers */
|
||||
int marker; /* mark to use */
|
||||
off_t marks[10]; /* 10 marks: 0..9 */
|
||||
|
||||
int move_dir; /* return value from widget:
|
||||
* 0 do nothing
|
||||
* -1 view previous file
|
||||
* 1 view next file
|
||||
*/
|
||||
|
||||
off_t update_steps; /* The number of bytes between percent
|
||||
* increments */
|
||||
off_t update_activate; /* Last point where we updated the status */
|
||||
|
||||
/* converter for translation of text */
|
||||
GIConv converter;
|
||||
|
||||
/* handle of search engine */
|
||||
mc_search_t *search;
|
||||
gchar *last_search_string;
|
||||
mc_search_type_t search_type;
|
||||
gboolean search_all_codepages;
|
||||
gboolean whole_words;
|
||||
gboolean search_case;
|
||||
gboolean search_backwards;
|
||||
struct mcview_nroff_struct *search_nroff_seq;
|
||||
|
||||
int search_numNeedSkipChar;
|
||||
} mcview_t;
|
||||
|
||||
typedef struct mcview_nroff_struct {
|
||||
mcview_t *view;
|
||||
off_t index;
|
||||
int char_width;
|
||||
int current_char;
|
||||
nroff_type_t type;
|
||||
nroff_type_t prev_type;
|
||||
} mcview_nroff_t;
|
||||
|
||||
/*** global variables defined in .c file *******************************/
|
||||
|
||||
/*** declarations of public functions **********************************/
|
||||
|
||||
/* actions_cmd.c: callbacks */
|
||||
cb_ret_t mcview_callback (Widget *, widget_msg_t, int);
|
||||
cb_ret_t mcview_dialog_callback (Dlg_head *, dlg_msg_t, int);
|
||||
void mcview_help_cmd (void);
|
||||
void mcview_quit_cmd (mcview_t *);
|
||||
void mcview_toggle_hex_mode_cmd (mcview_t *);
|
||||
void mcview_moveto_line_cmd (mcview_t *);
|
||||
void mcview_moveto_addr_cmd (mcview_t *);
|
||||
void mcview_toggle_hexedit_mode_cmd (mcview_t *);
|
||||
void mcview_hexedit_save_changes_cmd (mcview_t *);
|
||||
void mcview_toggle_wrap_mode_cmd (mcview_t *);
|
||||
void mcview_search_cmd (mcview_t *);
|
||||
void mcview_toggle_magic_mode_cmd (mcview_t *);
|
||||
void mcview_toggle_nroff_mode_cmd (mcview_t *);
|
||||
void mcview_toggle_ruler_cmd (mcview_t *);
|
||||
|
||||
|
||||
/* coord_cache.c: */
|
||||
gboolean mcview_coord_cache_entry_less (const struct coord_cache_entry *,
|
||||
const struct coord_cache_entry *, enum ccache_type,
|
||||
gboolean);
|
||||
#ifdef MC_ENABLE_DEBUGGING_CODE
|
||||
void mcview_ccache_dump (mcview_t *);
|
||||
#endif
|
||||
|
||||
void
|
||||
mcview_ccache_lookup (mcview_t *, struct coord_cache_entry *, enum ccache_type);
|
||||
|
||||
|
||||
/* datasource.c: */
|
||||
void mcview_set_datasource_none (mcview_t *);
|
||||
off_t mcview_get_filesize (mcview_t *);
|
||||
char *mcview_get_ptr_file (mcview_t *, off_t);
|
||||
char *mcview_get_ptr_string (mcview_t *, off_t);
|
||||
int mcview_get_utf (mcview_t *, off_t, int *, gboolean *);
|
||||
gboolean mcview_get_byte_string (mcview_t *, off_t, int *);
|
||||
gboolean mcview_get_byte_none (mcview_t *, off_t, int *);
|
||||
void mcview_set_byte (mcview_t *, off_t, byte);
|
||||
void mcview_file_load_data (mcview_t *, off_t);
|
||||
void mcview_close_datasource (mcview_t *);
|
||||
void mcview_set_datasource_file (mcview_t *, int, const struct stat *);
|
||||
gboolean mcview_load_command_output (mcview_t *, const char *);
|
||||
void mcview_set_datasource_vfs_pipe (mcview_t *, int);
|
||||
void mcview_set_datasource_string (mcview_t *, const char *);
|
||||
|
||||
/* dialog.c: */
|
||||
gboolean mcview_dialog_search (mcview_t *);
|
||||
|
||||
/* display.c: */
|
||||
void mcview_update (mcview_t *);
|
||||
void mcview_display (mcview_t *);
|
||||
void mcview_compute_areas (mcview_t *);
|
||||
void mcview_update_bytes_per_line (mcview_t *);
|
||||
void mcview_display_toggle_ruler (mcview_t *);
|
||||
void mcview_display_clean (mcview_t *);
|
||||
void mcview_display_ruler (mcview_t *);
|
||||
void mcview_adjust_size (Dlg_head *);
|
||||
void mcview_percent (mcview_t *, off_t);
|
||||
|
||||
/* growbuf.c: */
|
||||
void mcview_growbuf_init (mcview_t *);
|
||||
void mcview_growbuf_free (mcview_t *);
|
||||
off_t mcview_growbuf_filesize (mcview_t *);
|
||||
void mcview_growbuf_read_until (mcview_t *, off_t);
|
||||
gboolean mcview_get_byte_growing_buffer (mcview_t *, off_t, int *);
|
||||
char *mcview_get_ptr_growing_buffer (mcview_t *, off_t);
|
||||
|
||||
/* hex.c: */
|
||||
void mcview_display_hex (mcview_t *);
|
||||
gboolean mcview_hexedit_save_changes (mcview_t *);
|
||||
void mcview_toggle_hexedit_mode (mcview_t *);
|
||||
void mcview_hexedit_free_change_list (mcview_t *);
|
||||
void mcview_enqueue_change (struct hexedit_change_node **, struct hexedit_change_node *);
|
||||
|
||||
/* lib.c: */
|
||||
void mcview_toggle_magic_mode (mcview_t *);
|
||||
void mcview_toggle_wrap_mode (mcview_t *);
|
||||
void mcview_toggle_nroff_mode (mcview_t *);
|
||||
void mcview_toggle_hex_mode (mcview_t *);
|
||||
gboolean mcview_ok_to_quit (mcview_t *);
|
||||
void mcview_done (mcview_t *);
|
||||
void mcview_select_encoding (mcview_t *);
|
||||
void mcview_show_error (mcview_t *, const char *);
|
||||
|
||||
/* move.c */
|
||||
void mcview_move_up (mcview_t *, off_t);
|
||||
void mcview_move_down (mcview_t *, off_t);
|
||||
void mcview_move_left (mcview_t *, off_t);
|
||||
void mcview_move_right (mcview_t *, off_t);
|
||||
void mcview_scroll_to_cursor (mcview_t *);
|
||||
void mcview_moveto_top (mcview_t *);
|
||||
void mcview_moveto_bottom (mcview_t *);
|
||||
void mcview_moveto_bol (mcview_t *);
|
||||
void mcview_moveto_eol (mcview_t *);
|
||||
void mcview_moveto_offset (mcview_t *, off_t);
|
||||
void mcview_moveto (mcview_t *, off_t, off_t);
|
||||
void mcview_coord_to_offset (mcview_t *, off_t *, off_t, off_t);
|
||||
void mcview_offset_to_coord (mcview_t *, off_t *, off_t *, off_t);
|
||||
void mcview_place_cursor (mcview_t *);
|
||||
void mcview_moveto_match (mcview_t *);
|
||||
|
||||
/* nroff.c: */
|
||||
void mcview_display_nroff (mcview_t *);
|
||||
int mcview__get_nroff_real_len (mcview_t *, off_t, off_t);
|
||||
|
||||
mcview_nroff_t *mcview_nroff_seq_new_num (mcview_t * view, off_t);
|
||||
mcview_nroff_t *mcview_nroff_seq_new (mcview_t * view);
|
||||
void mcview_nroff_seq_free (mcview_nroff_t **);
|
||||
nroff_type_t mcview_nroff_seq_info (mcview_nroff_t *);
|
||||
int mcview_nroff_seq_next (mcview_nroff_t *);
|
||||
|
||||
/* plain.c: */
|
||||
void mcview_display_text (mcview_t *);
|
||||
|
||||
/* search.c: */
|
||||
int mcview_search_cmd_callback (const void *user_data, gsize char_offset);
|
||||
int mcview_search_update_cmd_callback (const void *, gsize);
|
||||
void mcview_do_search (mcview_t *);
|
||||
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
#include "inlines.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
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 "../src/global.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "../src/strutil.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_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)
|
||||
{
|
||||
view->text_wrap_mode = !view->text_wrap_mode;
|
||||
if (view->text_wrap_mode) {
|
||||
mcview_scroll_to_cursor (view);
|
||||
} else {
|
||||
off_t line;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &(view->dpy_text_column), view->dpy_start);
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, 0);
|
||||
}
|
||||
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);
|
||||
view->widget.options |= W_WANT_CURSOR;
|
||||
} else {
|
||||
view->dpy_start = view->hex_cursor;
|
||||
mcview_moveto_bol (view);
|
||||
view->widget.options &= ~W_WANT_CURSOR;
|
||||
}
|
||||
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_done (mcview_t * view)
|
||||
{
|
||||
/* Save current file position */
|
||||
if (mcview_remember_file_position && view->filename != NULL) {
|
||||
char *canon_fname;
|
||||
off_t line, col;
|
||||
|
||||
canon_fname = vfs_canon (view->filename);
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
save_file_position (canon_fname, line + 1, col);
|
||||
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 */
|
||||
|
||||
if (view->coord_cache) {
|
||||
g_array_free (view->coord_cache, TRUE), view->coord_cache = NULL;
|
||||
}
|
||||
|
||||
mcview_hexedit_free_change_list (view);
|
||||
/* FIXME: what about view->search_exp? */
|
||||
|
||||
if (view->converter != str_cnv_from_term)
|
||||
str_close_conv (view->converter);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_select_encoding (mcview_t * view)
|
||||
{
|
||||
#ifdef HAVE_CHARSET
|
||||
const char *cp_id = NULL;
|
||||
if (do_select_codepage ()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp_id != NULL)
|
||||
view->utf8 = (gboolean) str_isutf8 (cp_id);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Interface 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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "../src/main.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "internal.h"
|
||||
#include "mcviewer.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
int mcview_default_hex_mode = 0;
|
||||
int mcview_default_nroff_flag = 0;
|
||||
int mcview_global_wrap_mode = 1;
|
||||
int mcview_default_magic_flag = 1;
|
||||
|
||||
int mcview_altered_hex_mode = 0;
|
||||
int mcview_altered_magic_flag = 0;
|
||||
int mcview_altered_nroff_flag = 0;
|
||||
|
||||
int mcview_remember_file_position = FALSE;
|
||||
|
||||
/* Maxlimit for skipping updates */
|
||||
int mcview_max_dirt_limit = 10;
|
||||
|
||||
/* Scrolling is done in pages or line increments */
|
||||
int mcview_mouse_move_pages = 1;
|
||||
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Both views */
|
||||
static int
|
||||
mcview_event (mcview_t * view, Gpm_Event * event, int *result)
|
||||
{
|
||||
screen_dimen y, x;
|
||||
|
||||
*result = MOU_NORMAL;
|
||||
|
||||
/* We are not interested in the release events */
|
||||
if (!(event->type & (GPM_DOWN | GPM_DRAG)))
|
||||
return 0;
|
||||
|
||||
/* Wheel events */
|
||||
if ((event->buttons & GPM_B_UP) && (event->type & GPM_DOWN)) {
|
||||
mcview_move_up (view, 2);
|
||||
return 1;
|
||||
}
|
||||
if ((event->buttons & GPM_B_DOWN) && (event->type & GPM_DOWN)) {
|
||||
mcview_move_down (view, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x = event->x;
|
||||
y = event->y;
|
||||
|
||||
/* Scrolling left and right */
|
||||
if (!view->text_wrap_mode) {
|
||||
if (x < view->data_area.width * 1 / 4) {
|
||||
mcview_move_left (view, 1);
|
||||
goto processed;
|
||||
} else if (x < view->data_area.width * 3 / 4) {
|
||||
/* ignore the click */
|
||||
} else {
|
||||
mcview_move_right (view, 1);
|
||||
goto processed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrolling up and down */
|
||||
if (y < view->data_area.top + view->data_area.height * 1 / 3) {
|
||||
if (mcview_mouse_move_pages)
|
||||
mcview_move_up (view, view->data_area.height / 2);
|
||||
else
|
||||
mcview_move_up (view, 1);
|
||||
goto processed;
|
||||
} else if (y < view->data_area.top + view->data_area.height * 2 / 3) {
|
||||
/* ignore the click */
|
||||
} else {
|
||||
if (mcview_mouse_move_pages)
|
||||
mcview_move_down (view, view->data_area.height / 2);
|
||||
else
|
||||
mcview_move_down (view, 1);
|
||||
goto processed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
processed:
|
||||
*result = MOU_REPEAT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Real view only */
|
||||
static int
|
||||
mcview_real_event (Gpm_Event * event, void *x)
|
||||
{
|
||||
mcview_t *view = (mcview_t *) x;
|
||||
int result;
|
||||
|
||||
if (mcview_event (view, event, &result))
|
||||
mcview_update (view);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
mcview_t *
|
||||
mcview_new (int y, int x, int cols, int lines, int is_panel)
|
||||
{
|
||||
mcview_t *view = g_new0 (mcview_t, 1);
|
||||
size_t i;
|
||||
|
||||
init_widget (&view->widget, y, x, lines, cols, mcview_callback, mcview_real_event);
|
||||
|
||||
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->hex_mode = FALSE;
|
||||
view->hexedit_mode = FALSE;
|
||||
view->hexview_in_text = FALSE;
|
||||
view->text_nroff_mode = FALSE;
|
||||
view->text_wrap_mode = FALSE;
|
||||
view->magic_mode = FALSE;
|
||||
view->utf8 = FALSE;
|
||||
|
||||
view->hexedit_lownibble = FALSE;
|
||||
view->coord_cache = NULL;
|
||||
|
||||
view->dpy_frame_size = is_panel ? 1 : 0;
|
||||
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;
|
||||
view->converter = str_cnv_from_term;
|
||||
|
||||
/* {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->want_to_quit = FALSE;
|
||||
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;
|
||||
|
||||
if (mcview_default_hex_mode)
|
||||
mcview_toggle_hex_mode (view);
|
||||
if (mcview_default_nroff_flag)
|
||||
mcview_toggle_nroff_mode (view);
|
||||
if (mcview_global_wrap_mode)
|
||||
mcview_toggle_wrap_mode (view);
|
||||
if (mcview_default_magic_flag)
|
||||
mcview_toggle_magic_mode (view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Real view only */
|
||||
int
|
||||
mcview_viewer (const char *command, const char *file, int *move_dir_p, int start_line)
|
||||
{
|
||||
gboolean succeeded;
|
||||
mcview_t *mcview_t;
|
||||
WButtonBar *bar;
|
||||
Dlg_head *view_dlg;
|
||||
|
||||
/* Create dialog and widgets, put them on the dialog */
|
||||
view_dlg =
|
||||
create_dlg (0, 0, LINES, COLS, NULL, mcview_dialog_callback,
|
||||
"[Internal File Viewer]", NULL, DLG_WANT_TAB);
|
||||
|
||||
mcview_t = mcview_new (0, 0, COLS, LINES - 1, 0);
|
||||
|
||||
bar = buttonbar_new (1);
|
||||
|
||||
add_widget (view_dlg, bar);
|
||||
add_widget (view_dlg, mcview_t);
|
||||
|
||||
succeeded = mcview_load (mcview_t, command, file, start_line);
|
||||
if (succeeded) {
|
||||
run_dlg (view_dlg);
|
||||
if (move_dir_p)
|
||||
*move_dir_p = mcview_t->move_dir;
|
||||
} else {
|
||||
if (move_dir_p)
|
||||
*move_dir_p = 0;
|
||||
}
|
||||
destroy_dlg (view_dlg);
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
/* {{{ Miscellaneous functions }}} */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_load (mcview_t * view, const char *command, const char *file, int start_line)
|
||||
{
|
||||
int i, type;
|
||||
int fd = -1;
|
||||
char tmp[BUF_MEDIUM];
|
||||
const char *enc;
|
||||
char *canon_fname;
|
||||
struct stat st;
|
||||
#ifdef HAVE_CHARSET
|
||||
const char *cp_id = NULL;
|
||||
#endif
|
||||
gboolean retval = FALSE;
|
||||
#ifdef HAVE_CHARSET
|
||||
cp_id = get_codepage_id (source_codepage);
|
||||
|
||||
if (cp_id != NULL && str_isutf8 (cp_id) != 0)
|
||||
view->utf8 = TRUE;
|
||||
else
|
||||
view->utf8 = FALSE;
|
||||
#endif
|
||||
|
||||
assert (view->bytes_per_line != 0);
|
||||
mcview_done (view);
|
||||
|
||||
/* Set up the state */
|
||||
mcview_set_datasource_none (view);
|
||||
view->filename = g_strdup (file);
|
||||
view->command = 0;
|
||||
|
||||
/* Clear the markers */
|
||||
view->marker = 0;
|
||||
for (i = 0; i < 10; i++)
|
||||
view->marks[i] = 0;
|
||||
|
||||
if (!mcview_is_in_panel (view)) {
|
||||
view->dpy_text_column = 0;
|
||||
}
|
||||
|
||||
if (command && (view->magic_mode || file == NULL || file[0] == '\0')) {
|
||||
retval = mcview_load_command_output (view, command);
|
||||
} else if (file != NULL && file[0] != '\0') {
|
||||
/* Open the file */
|
||||
if ((fd = mc_open (file, O_RDONLY | O_NONBLOCK)) == -1) {
|
||||
g_snprintf (tmp, sizeof (tmp), _(" Cannot open \"%s\"\n %s "),
|
||||
file, unix_error_string (errno));
|
||||
mcview_show_error (view, tmp);
|
||||
g_free (view->filename);
|
||||
view->filename = NULL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Make sure we are working with a regular file */
|
||||
if (mc_fstat (fd, &st) == -1) {
|
||||
mc_close (fd);
|
||||
g_snprintf (tmp, sizeof (tmp), _(" Cannot stat \"%s\"\n %s "),
|
||||
file, unix_error_string (errno));
|
||||
mcview_show_error (view, tmp);
|
||||
g_free (view->filename);
|
||||
view->filename = NULL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!S_ISREG (st.st_mode)) {
|
||||
mc_close (fd);
|
||||
mcview_show_error (view, _(" Cannot view: not a regular file "));
|
||||
g_free (view->filename);
|
||||
view->filename = NULL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (st.st_size == 0 || mc_lseek (fd, 0, SEEK_SET) == -1) {
|
||||
/* Must be one of those nice files that grow (/proc) */
|
||||
mcview_set_datasource_vfs_pipe (view, fd);
|
||||
} else {
|
||||
type = get_compression_type (fd);
|
||||
|
||||
if (view->magic_mode && (type != COMPRESSION_NONE)) {
|
||||
g_free (view->filename);
|
||||
view->filename = g_strconcat (file, decompress_extension (type), (char *) NULL);
|
||||
}
|
||||
mcview_set_datasource_file (view, fd, &st);
|
||||
}
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
finish:
|
||||
view->command = g_strdup (command);
|
||||
view->dpy_start = 0;
|
||||
view->search_start = 0;
|
||||
view->search_end = 0;
|
||||
view->dpy_text_column = 0;
|
||||
|
||||
view->converter = str_cnv_from_term;
|
||||
#ifdef HAVE_CHARSET
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (cp_id != NULL)
|
||||
view->utf8 = (gboolean) str_isutf8 (cp_id);
|
||||
#endif
|
||||
|
||||
mcview_compute_areas (view);
|
||||
assert (view->bytes_per_line != 0);
|
||||
if (mcview_remember_file_position && view->filename != NULL && start_line == 0) {
|
||||
long line, col;
|
||||
|
||||
canon_fname = vfs_canon (view->filename);
|
||||
load_file_position (canon_fname, &line, &col);
|
||||
g_free (canon_fname);
|
||||
mcview_moveto (view, mcview_offset_doz (line, 1), col);
|
||||
} else if (start_line > 0) {
|
||||
mcview_moveto (view, start_line - 1, 0);
|
||||
}
|
||||
|
||||
view->hexedit_lownibble = FALSE;
|
||||
view->hexview_in_text = FALSE;
|
||||
view->change_list = NULL;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,50 @@
|
|||
/** \file view.h
|
||||
* \brief Header: internal file viewer
|
||||
*/
|
||||
|
||||
#ifndef MC_VIEWER_H
|
||||
#define MC_VIEWER_H
|
||||
|
||||
/*** typedefs(not structures) and defined constants ********************/
|
||||
|
||||
struct mcview_struct;
|
||||
|
||||
/*** enums *************************************************************/
|
||||
|
||||
/*** structures declarations (and typedefs of structures)***************/
|
||||
|
||||
/*** global variables defined in .c file *******************************/
|
||||
|
||||
extern int mcview_default_hex_mode;
|
||||
extern int mcview_default_nroff_flag;
|
||||
extern int mcview_global_wrap_mode;
|
||||
extern int mcview_default_magic_flag;
|
||||
|
||||
extern int mcview_altered_hex_mode;
|
||||
extern int mcview_altered_magic_flag;
|
||||
extern int mcview_altered_nroff_flag;
|
||||
|
||||
extern int mcview_remember_file_position;
|
||||
extern int mcview_max_dirt_limit;
|
||||
|
||||
extern int mcview_mouse_move_pages;
|
||||
|
||||
/*** declarations of public functions **********************************/
|
||||
|
||||
|
||||
/* Creates a new mcview_t object with the given properties. Caveat: the
|
||||
* origin is in y-x order, while the extent is in x-y order. */
|
||||
extern struct mcview_struct *mcview_new (int, int, int, int, int);
|
||||
|
||||
|
||||
/* Shows {file} or the output of {command} in the internal viewer,
|
||||
* starting in line {start_line}. {ret_move_direction} may be NULL or
|
||||
* point to a variable that will receive the direction in which the user
|
||||
* wants to move (-1 = previous file, 1 = next file, 0 = do nothing).
|
||||
*/
|
||||
extern int mcview_viewer (const char *command, const char *file,
|
||||
int *ret_move_direction, int start_line);
|
||||
|
||||
extern gboolean mcview_load (struct mcview_struct *, const char *, const char *, int);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Functions for handle cursor movement
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The following variables have to do with the current position and are
|
||||
updated by the cursor movement functions.
|
||||
|
||||
In hex view and wrapped text view mode, dpy_start marks the offset of
|
||||
the top-left corner on the screen, in non-wrapping text mode it is
|
||||
the beginning of the current line. In hex mode, hex_cursor is the
|
||||
offset of the cursor. In non-wrapping text mode, dpy_text_column is
|
||||
the number of columns that are hidden on the left side on the screen.
|
||||
|
||||
In hex mode, dpy_start is updated by the view_fix_cursor_position()
|
||||
function in order to keep the other functions simple. In
|
||||
non-wrapping text mode dpy_start and dpy_text_column are normalized
|
||||
such that dpy_text_column < view_get_datacolumns().
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
static void
|
||||
mcview_movement_fixups (mcview_t * view, gboolean reset_search)
|
||||
{
|
||||
mcview_scroll_to_cursor (view);
|
||||
if (reset_search) {
|
||||
view->search_start = view->dpy_start;
|
||||
view->search_end = view->dpy_start;
|
||||
}
|
||||
view->dirty++;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_move_up (mcview_t * view, off_t lines)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
off_t bytes = lines * view->bytes_per_line;
|
||||
if (view->hex_cursor >= bytes) {
|
||||
view->hex_cursor -= bytes;
|
||||
if (view->hex_cursor < view->dpy_start)
|
||||
view->dpy_start = mcview_offset_doz (view->dpy_start, bytes);
|
||||
} else {
|
||||
view->hex_cursor %= view->bytes_per_line;
|
||||
}
|
||||
} else if (view->text_wrap_mode) {
|
||||
const screen_dimen width = view->data_area.width;
|
||||
off_t i, col, line, linestart;
|
||||
|
||||
for (i = 0; i < lines; i++) {
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
if (col >= width) {
|
||||
col -= width;
|
||||
} else if (line >= 1) {
|
||||
mcview_coord_to_offset (view, &linestart, line, 0);
|
||||
mcview_offset_to_coord (view, &line, &col, linestart - 1);
|
||||
|
||||
/* if the only thing that would be displayed were a
|
||||
* single newline character, advance to the previous
|
||||
* part of the line. */
|
||||
if (col > 0 && col % width == 0)
|
||||
col -= width;
|
||||
else
|
||||
col -= col % width;
|
||||
} else {
|
||||
/* nothing to do */
|
||||
}
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, col);
|
||||
}
|
||||
} else {
|
||||
off_t line, column;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &column, view->dpy_start);
|
||||
line = mcview_offset_doz (line, lines);
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, column);
|
||||
}
|
||||
mcview_movement_fixups (view, (lines != 1));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_move_down (mcview_t * view, off_t lines)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
off_t i, limit, last_byte;
|
||||
|
||||
last_byte = mcview_get_filesize (view);
|
||||
if (last_byte >= (off_t) view->bytes_per_line)
|
||||
limit = last_byte - view->bytes_per_line;
|
||||
else
|
||||
limit = 0;
|
||||
for (i = 0; i < lines && view->hex_cursor < limit; i++) {
|
||||
view->hex_cursor += view->bytes_per_line;
|
||||
if (lines != 1)
|
||||
view->dpy_start += view->bytes_per_line;
|
||||
}
|
||||
|
||||
} else if (view->dpy_end == mcview_get_filesize (view)) {
|
||||
/* don't move further down. There's nothing more to see. */
|
||||
|
||||
} else if (view->text_wrap_mode) {
|
||||
off_t line, col, i;
|
||||
int c;
|
||||
|
||||
for (i = 0; i < lines; i++) {
|
||||
off_t new_offset, chk_line, chk_col;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
col += view->data_area.width;
|
||||
mcview_coord_to_offset (view, &new_offset, line, col);
|
||||
|
||||
/* skip to the next line if the only thing that would be
|
||||
* displayed is the newline character. */
|
||||
mcview_offset_to_coord (view, &chk_line, &chk_col, new_offset);
|
||||
if (chk_line == line && chk_col == col && mcview_get_byte (view, new_offset, &c) == TRUE
|
||||
&& c == '\n')
|
||||
new_offset++;
|
||||
|
||||
view->dpy_start = new_offset;
|
||||
}
|
||||
|
||||
} else {
|
||||
off_t line, col;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
line += lines;
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, col);
|
||||
}
|
||||
mcview_movement_fixups (view, (lines != 1));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_move_left (mcview_t * view, off_t columns)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
assert (columns == 1);
|
||||
if (view->hexview_in_text || !view->hexedit_lownibble) {
|
||||
if (view->hex_cursor > 0)
|
||||
view->hex_cursor--;
|
||||
}
|
||||
if (!view->hexview_in_text)
|
||||
view->hexedit_lownibble = !view->hexedit_lownibble;
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
if (view->dpy_text_column >= columns)
|
||||
view->dpy_text_column -= columns;
|
||||
else
|
||||
view->dpy_text_column = 0;
|
||||
}
|
||||
mcview_movement_fixups (view, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_move_right (mcview_t * view, off_t columns)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
assert (columns == 1);
|
||||
if (view->hexview_in_text || view->hexedit_lownibble) {
|
||||
view->hex_cursor++;
|
||||
}
|
||||
if (!view->hexview_in_text)
|
||||
view->hexedit_lownibble = !view->hexedit_lownibble;
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
view->dpy_text_column += columns;
|
||||
}
|
||||
mcview_movement_fixups (view, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_scroll_to_cursor (mcview_t * view)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
const off_t bytes = view->bytes_per_line;
|
||||
const off_t displaysize = view->data_area.height * bytes;
|
||||
const off_t cursor = view->hex_cursor;
|
||||
off_t topleft = view->dpy_start;
|
||||
|
||||
if (topleft + displaysize <= cursor)
|
||||
topleft = mcview_offset_rounddown (cursor, bytes)
|
||||
- (displaysize - bytes);
|
||||
if (cursor < topleft)
|
||||
topleft = mcview_offset_rounddown (cursor, bytes);
|
||||
view->dpy_start = topleft;
|
||||
} else if (view->text_wrap_mode) {
|
||||
off_t line, col, columns;
|
||||
|
||||
columns = view->data_area.width;
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start + view->dpy_text_column);
|
||||
if (columns != 0)
|
||||
col = mcview_offset_rounddown (col, columns);
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, col);
|
||||
view->dpy_text_column = 0;
|
||||
} else {
|
||||
/* nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_top (mcview_t * view)
|
||||
{
|
||||
view->dpy_start = 0;
|
||||
view->hex_cursor = 0;
|
||||
view->dpy_text_column = 0;
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_bottom (mcview_t * view)
|
||||
{
|
||||
off_t datalines, lines_up, filesize, last_offset;
|
||||
|
||||
if (view->growbuf_in_use)
|
||||
mcview_growbuf_read_until (view, OFFSETTYPE_MAX);
|
||||
|
||||
filesize = mcview_get_filesize (view);
|
||||
last_offset = mcview_offset_doz (filesize, 1);
|
||||
datalines = view->data_area.height;
|
||||
lines_up = mcview_offset_doz (datalines, 1);
|
||||
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor = filesize;
|
||||
mcview_move_up (view, lines_up);
|
||||
view->hex_cursor = last_offset;
|
||||
} else {
|
||||
view->dpy_start = last_offset;
|
||||
mcview_moveto_bol (view);
|
||||
mcview_move_up (view, lines_up);
|
||||
}
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_bol (mcview_t * view)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
off_t line, column;
|
||||
mcview_offset_to_coord (view, &line, &column, view->dpy_start);
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, 0);
|
||||
view->dpy_text_column = 0;
|
||||
}
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_eol (mcview_t * view)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
off_t filesize, bol;
|
||||
|
||||
bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line);
|
||||
if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE) {
|
||||
view->hex_cursor = bol + view->bytes_per_line - 1;
|
||||
} else {
|
||||
filesize = mcview_get_filesize (view);
|
||||
view->hex_cursor = mcview_offset_doz (filesize, 1);
|
||||
}
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
off_t line, col;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
mcview_coord_to_offset (view, &(view->dpy_start), line, OFFSETTYPE_MAX);
|
||||
}
|
||||
mcview_movement_fixups (view, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto_offset (mcview_t * view, off_t offset)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor = offset;
|
||||
view->dpy_start = offset - offset % view->bytes_per_line;
|
||||
} else {
|
||||
view->dpy_start = offset;
|
||||
}
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_moveto (mcview_t * view, off_t line, off_t col)
|
||||
{
|
||||
off_t offset;
|
||||
|
||||
mcview_coord_to_offset (view, &offset, line, col);
|
||||
mcview_moveto_offset (view, offset);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_coord_to_offset (mcview_t * view, off_t * ret_offset, off_t line, off_t column)
|
||||
{
|
||||
struct coord_cache_entry coord;
|
||||
|
||||
coord.cc_line = line;
|
||||
coord.cc_column = column;
|
||||
coord.cc_nroff_column = column;
|
||||
mcview_ccache_lookup (view, &coord, CCACHE_OFFSET);
|
||||
*ret_offset = coord.cc_offset;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_offset_to_coord (mcview_t * view, off_t * ret_line, off_t * ret_column, off_t offset)
|
||||
{
|
||||
struct coord_cache_entry coord;
|
||||
|
||||
coord.cc_offset = offset;
|
||||
mcview_ccache_lookup (view, &coord, CCACHE_LINECOL);
|
||||
|
||||
if (ret_line)
|
||||
*ret_line = coord.cc_line;
|
||||
|
||||
if (ret_column)
|
||||
*ret_column = (view->text_nroff_mode)
|
||||
? coord.cc_nroff_column : coord.cc_column;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_place_cursor (mcview_t * view)
|
||||
{
|
||||
const screen_dimen top = view->data_area.top;
|
||||
const screen_dimen left = view->data_area.left;
|
||||
screen_dimen col;
|
||||
|
||||
col = view->cursor_col;
|
||||
if (!view->hexview_in_text && view->hexedit_lownibble)
|
||||
col++;
|
||||
widget_move (&view->widget, top + view->cursor_row, left + col);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* we have set view->search_start and view->search_end and must set
|
||||
* view->dpy_text_column and view->dpy_start
|
||||
* try to display maximum of match */
|
||||
void
|
||||
mcview_moveto_match (mcview_t * view)
|
||||
{
|
||||
off_t search_line, search_col, offset;
|
||||
|
||||
mcview_offset_to_coord (view, &search_line, &search_col, view->search_start);
|
||||
if (!view->hex_mode)
|
||||
search_col = 0;
|
||||
|
||||
mcview_coord_to_offset (view, &offset, search_line, search_col);
|
||||
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor = offset;
|
||||
view->dpy_start = offset - offset % view->bytes_per_line;
|
||||
} else {
|
||||
view->dpy_start = offset;
|
||||
}
|
||||
|
||||
mcview_scroll_to_cursor (view);
|
||||
view->dirty++;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for nroff-like view
|
||||
|
||||
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 "../src/global.h"
|
||||
#include "../src/main.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "../src/tty/color.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_nroff (mcview_t * view)
|
||||
{
|
||||
const screen_dimen left = view->data_area.left;
|
||||
const screen_dimen top = view->data_area.top;
|
||||
const screen_dimen width = view->data_area.width;
|
||||
const screen_dimen height = view->data_area.height;
|
||||
screen_dimen row, col;
|
||||
off_t from;
|
||||
int cw = 1;
|
||||
int c;
|
||||
int c_prev = 0;
|
||||
int c_next = 0;
|
||||
gboolean read_res = TRUE;
|
||||
struct hexedit_change_node *curr = view->change_list;
|
||||
|
||||
mcview_display_clean (view);
|
||||
mcview_display_ruler (view);
|
||||
|
||||
/* Find the first displayable changed byte */
|
||||
from = view->dpy_start;
|
||||
while (curr && (curr->offset < from)) {
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
for (row = 0, col = 0; row < height;) {
|
||||
#ifdef HAVE_CHARSET
|
||||
if (view->utf8) {
|
||||
c = mcview_get_utf (view, from, &cw, &read_res);
|
||||
if (!read_res)
|
||||
break;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (! mcview_get_byte (view, from, &c))
|
||||
break;
|
||||
}
|
||||
from++;
|
||||
if (cw > 1)
|
||||
from += cw - 1;
|
||||
|
||||
if (c == '\b') {
|
||||
if (from > 1) {
|
||||
mcview_get_byte (view, from - 2, &c_prev);
|
||||
mcview_get_byte (view, from, &c_next);
|
||||
}
|
||||
if (g_ascii_isprint (c_prev) && g_ascii_isprint (c_prev)
|
||||
&& (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o'))) {
|
||||
if (col == 0) {
|
||||
if (row == 0) {
|
||||
/* We're inside an nroff character sequence at the
|
||||
* beginning of the screen -- just skip the
|
||||
* backspace and continue with the next character. */
|
||||
continue;
|
||||
}
|
||||
row--;
|
||||
col = width;
|
||||
}
|
||||
col--;
|
||||
if (c_prev == '_'
|
||||
&& (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
|
||||
tty_setcolor (VIEW_UNDERLINED_COLOR);
|
||||
else
|
||||
tty_setcolor (MARKED_COLOR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((c == '\n') || (col >= width && view->text_wrap_mode)) {
|
||||
col = 0;
|
||||
row++;
|
||||
if (c == '\n' || row >= height)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\r') {
|
||||
mcview_get_byte_indexed (view, from, 1, &c);
|
||||
if (c == '\r' || c == '\n')
|
||||
continue;
|
||||
col = 0;
|
||||
row++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\t') {
|
||||
off_t line, column;
|
||||
mcview_offset_to_coord (view, &line, &column, from);
|
||||
col += (8 - column % 8);
|
||||
if (view->text_wrap_mode && col >= width && width != 0) {
|
||||
row += col / width;
|
||||
col %= width;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (view->search_start <= from && from < view->search_end) {
|
||||
tty_setcolor (SELECTED_COLOR);
|
||||
}
|
||||
|
||||
if (col >= view->dpy_text_column && col - view->dpy_text_column < width) {
|
||||
widget_move (view, top + row, left + (col - view->dpy_text_column));
|
||||
#ifdef HAVE_CHARSET
|
||||
if (utf8_display) {
|
||||
if (!view->utf8) {
|
||||
c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
|
||||
}
|
||||
if (!g_unichar_isprint (c))
|
||||
c = '.';
|
||||
} else {
|
||||
if (view->utf8) {
|
||||
c = convert_from_utf_to_current_c (c, view->converter);
|
||||
} else {
|
||||
#endif
|
||||
c = convert_to_display_c (c);
|
||||
#ifdef HAVE_CHARSET
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tty_print_anychar (c);
|
||||
}
|
||||
col++;
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
}
|
||||
view->dpy_end = from;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
|
||||
{
|
||||
mcview_nroff_t *nroff;
|
||||
int ret = 0;
|
||||
off_t i = 0;
|
||||
|
||||
nroff = mcview_nroff_seq_new_num (view, start);
|
||||
if (nroff == NULL)
|
||||
return 0;
|
||||
|
||||
while (i < length) {
|
||||
if (nroff->type != NROFF_TYPE_NONE) {
|
||||
ret += 2;
|
||||
}
|
||||
i++;
|
||||
mcview_nroff_seq_next (nroff);
|
||||
}
|
||||
|
||||
mcview_nroff_seq_free (&nroff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
mcview_nroff_t *
|
||||
mcview_nroff_seq_new_num (mcview_t * view, off_t index)
|
||||
{
|
||||
mcview_nroff_t *nroff;
|
||||
|
||||
nroff = g_malloc0 (sizeof (mcview_nroff_t));
|
||||
if (nroff == NULL)
|
||||
return NULL;
|
||||
nroff->index = index;
|
||||
nroff->view = view;
|
||||
mcview_nroff_seq_info (nroff);
|
||||
return nroff;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
mcview_nroff_t *
|
||||
mcview_nroff_seq_new (mcview_t * view)
|
||||
{
|
||||
return mcview_nroff_seq_new_num (view, (off_t) 0);
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_nroff_seq_free (mcview_nroff_t ** nroff)
|
||||
{
|
||||
if (nroff == NULL || *nroff == NULL)
|
||||
return;
|
||||
g_free (*nroff);
|
||||
nroff = NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
nroff_type_t
|
||||
mcview_nroff_seq_info (mcview_nroff_t * nroff)
|
||||
{
|
||||
int next, next2;
|
||||
|
||||
if (nroff == NULL)
|
||||
return NROFF_TYPE_NONE;
|
||||
nroff->type = NROFF_TYPE_NONE;
|
||||
|
||||
if (! mcview_get_byte (nroff->view, nroff->index, &nroff->current_char)
|
||||
|| !g_ascii_isprint (nroff->current_char)) /* FIXME: utf-8 and g_ascii_isprint */
|
||||
return nroff->type;
|
||||
|
||||
nroff->char_width = 1;
|
||||
|
||||
if (! mcview_get_byte (nroff->view, nroff->index + 1, &next) || next != '\b')
|
||||
return nroff->type;
|
||||
|
||||
if (! mcview_get_byte (nroff->view, nroff->index + 2, &next2)
|
||||
|| !g_ascii_isprint (next2)) /* FIXME: utf-8 and g_ascii_isprint */
|
||||
return nroff->type;
|
||||
|
||||
if (nroff->current_char == '_' && next2 == '_') {
|
||||
nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
|
||||
? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
|
||||
|
||||
} else if (nroff->current_char == next2) {
|
||||
nroff->type = NROFF_TYPE_BOLD;
|
||||
} else if (nroff->current_char == '_') {
|
||||
nroff->current_char = next2;
|
||||
nroff->type = NROFF_TYPE_UNDERLINE;
|
||||
} else if (nroff->current_char == '+' && next2 == 'o') {
|
||||
/* ??? */
|
||||
}
|
||||
|
||||
return nroff->type;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mcview_nroff_seq_next (mcview_nroff_t * nroff)
|
||||
{
|
||||
if (nroff == NULL)
|
||||
return -1;
|
||||
|
||||
nroff->prev_type = nroff->type;
|
||||
|
||||
nroff->index += nroff->char_width;
|
||||
|
||||
if (nroff->prev_type != NROFF_TYPE_NONE)
|
||||
nroff->index += 2;
|
||||
mcview_nroff_seq_info (nroff);
|
||||
return nroff->current_char;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for plain view
|
||||
|
||||
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 "../src/global.h"
|
||||
#include "../src/main.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "../src/tty/color.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_display_text (mcview_t * view)
|
||||
{
|
||||
const screen_dimen left = view->data_area.left;
|
||||
const screen_dimen top = view->data_area.top;
|
||||
const screen_dimen width = view->data_area.width;
|
||||
const screen_dimen height = view->data_area.height;
|
||||
screen_dimen row, col;
|
||||
off_t from;
|
||||
int cw = 1;
|
||||
int c;
|
||||
gboolean read_res = TRUE;
|
||||
struct hexedit_change_node *curr = view->change_list;
|
||||
|
||||
mcview_display_clean (view);
|
||||
mcview_display_ruler (view);
|
||||
|
||||
/* Find the first displayable changed byte */
|
||||
from = view->dpy_start;
|
||||
while (curr && (curr->offset < from)) {
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
for (row = 0, col = 0; row < height;) {
|
||||
#ifdef HAVE_CHARSET
|
||||
if (view->utf8) {
|
||||
c = mcview_get_utf (view, from, &cw, &read_res);
|
||||
if (!read_res)
|
||||
break;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (! mcview_get_byte (view, from, &c))
|
||||
break;
|
||||
}
|
||||
from++;
|
||||
if (cw > 1)
|
||||
from += cw - 1;
|
||||
|
||||
if ((c == '\n') || (col >= width && view->text_wrap_mode)) {
|
||||
col = 0;
|
||||
row++;
|
||||
if (c == '\n' || row >= height)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\r') {
|
||||
if (! mcview_get_byte_indexed (view, from, 1, &c))
|
||||
break;
|
||||
|
||||
if (c == '\r' || c == '\n')
|
||||
continue;
|
||||
col = 0;
|
||||
row++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\t') {
|
||||
off_t line, column;
|
||||
mcview_offset_to_coord (view, &line, &column, from);
|
||||
col += (8 - column % 8);
|
||||
if (view->text_wrap_mode && col >= width && width != 0) {
|
||||
row += col / width;
|
||||
col %= width;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (view->search_start <= from && from < view->search_end) {
|
||||
tty_setcolor (SELECTED_COLOR);
|
||||
}
|
||||
|
||||
if (col >= view->dpy_text_column && col - view->dpy_text_column < width) {
|
||||
widget_move (view, top + row, left + (col - view->dpy_text_column));
|
||||
#ifdef HAVE_CHARSET
|
||||
if (utf8_display) {
|
||||
if (!view->utf8) {
|
||||
c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
|
||||
}
|
||||
if (!g_unichar_isprint (c))
|
||||
c = '.';
|
||||
} else {
|
||||
if (view->utf8) {
|
||||
c = convert_from_utf_to_current_c (c, view->converter);
|
||||
} else {
|
||||
#endif
|
||||
c = convert_to_display_c (c);
|
||||
#ifdef HAVE_CHARSET
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tty_print_anychar (c);
|
||||
}
|
||||
col++;
|
||||
tty_setcolor (NORMAL_COLOR);
|
||||
}
|
||||
view->dpy_end = from;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
Internal file viewer for the Midnight Commander
|
||||
Function for search data
|
||||
|
||||
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 "../src/global.h"
|
||||
#include "../src/setup.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
static void
|
||||
mcview_search_update_steps (mcview_t * view)
|
||||
{
|
||||
off_t filesize = mcview_get_filesize (view);
|
||||
if (filesize != 0)
|
||||
view->update_steps = 40000;
|
||||
else /* viewing a data stream, not a file */
|
||||
view->update_steps = filesize / 100;
|
||||
|
||||
/* Do not update the percent display but every 20 ks */
|
||||
if (view->update_steps < 20000)
|
||||
view->update_steps = 20000;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mcview_find (mcview_t * view, gsize search_start, gsize * len)
|
||||
{
|
||||
gsize search_end;
|
||||
|
||||
view->search_numNeedSkipChar = 0;
|
||||
|
||||
if (view->search_backwards) {
|
||||
search_end = mcview_get_filesize (view);
|
||||
while ((int) search_start >= 0) {
|
||||
view->search_nroff_seq->index = search_start;
|
||||
mcview_nroff_seq_info (view->search_nroff_seq);
|
||||
|
||||
if (search_end > search_start + view->search->original_len
|
||||
&& mc_search_is_fixed_search_str (view->search))
|
||||
search_end = search_start + view->search->original_len;
|
||||
|
||||
if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
|
||||
&& view->search->normal_offset == search_start)
|
||||
return TRUE;
|
||||
|
||||
search_start--;
|
||||
}
|
||||
view->search->error_str = g_strdup (_(" Search string not found "));
|
||||
return FALSE;
|
||||
}
|
||||
view->search_nroff_seq->index = search_start;
|
||||
mcview_nroff_seq_info (view->search_nroff_seq);
|
||||
|
||||
return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
|
||||
len);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mcview_search_cmd_callback (const void *user_data, gsize char_offset)
|
||||
{
|
||||
int byte;
|
||||
mcview_t *view = (mcview_t *) user_data;
|
||||
|
||||
/* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
|
||||
if (!view->text_nroff_mode) {
|
||||
if (! mcview_get_byte (view, char_offset, &byte))
|
||||
return MC_SEARCH_CB_ABORT;
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
if (view->search_numNeedSkipChar) {
|
||||
view->search_numNeedSkipChar--;
|
||||
return MC_SEARCH_CB_SKIP;
|
||||
}
|
||||
|
||||
byte = view->search_nroff_seq->current_char;
|
||||
|
||||
if (byte == -1)
|
||||
return MC_SEARCH_CB_ABORT;
|
||||
|
||||
mcview_nroff_seq_next (view->search_nroff_seq);
|
||||
|
||||
if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
|
||||
view->search_numNeedSkipChar = 2;
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
|
||||
{
|
||||
mcview_t *view = (mcview_t *) user_data;
|
||||
|
||||
if (char_offset >= view->update_activate) {
|
||||
view->update_activate += view->update_steps;
|
||||
if (verbose) {
|
||||
mcview_percent (view, char_offset);
|
||||
tty_refresh ();
|
||||
}
|
||||
if (tty_got_interrupt ())
|
||||
return MC_SEARCH_CB_ABORT;
|
||||
}
|
||||
/* may be in future return from this callback will change current position
|
||||
* in searching block. Now this just constant return value.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_do_search (mcview_t * view)
|
||||
{
|
||||
off_t search_start;
|
||||
gboolean isFound = FALSE;
|
||||
|
||||
Dlg_head *d = NULL;
|
||||
|
||||
size_t match_len;
|
||||
|
||||
if (verbose) {
|
||||
d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
|
||||
tty_refresh ();
|
||||
}
|
||||
|
||||
/*for avoid infinite search loop we need to increase or decrease start offset of search */
|
||||
|
||||
if (view->search_start) {
|
||||
search_start = (view->search_backwards) ? -2 : 2;
|
||||
search_start = view->search_start + search_start +
|
||||
mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
|
||||
} else {
|
||||
search_start = view->search_start;
|
||||
}
|
||||
|
||||
if (view->search_backwards && (int) search_start < 0)
|
||||
search_start = 0;
|
||||
|
||||
/* Compute the percent steps */
|
||||
mcview_search_update_steps (view);
|
||||
view->update_activate = 0;
|
||||
|
||||
tty_enable_interrupt_key ();
|
||||
|
||||
do {
|
||||
if (mcview_find (view, search_start, &match_len)) {
|
||||
view->search_start = view->search->normal_offset +
|
||||
mcview__get_nroff_real_len (view,
|
||||
view->search->start_buffer,
|
||||
view->search->normal_offset -
|
||||
view->search->start_buffer);
|
||||
|
||||
if (!view->hex_mode)
|
||||
view->search_start++;
|
||||
|
||||
view->search_end = view->search_start + match_len +
|
||||
mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
|
||||
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor = view->search_start;
|
||||
view->hexedit_lownibble = FALSE;
|
||||
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
|
||||
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
dlg_run_done (d);
|
||||
destroy_dlg (d);
|
||||
d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
|
||||
tty_refresh ();
|
||||
}
|
||||
|
||||
mcview_moveto_match (view);
|
||||
isFound = TRUE;
|
||||
break;
|
||||
}
|
||||
} while (mcview_may_still_grow (view));
|
||||
|
||||
if (!isFound) {
|
||||
if (view->search->error_str)
|
||||
message (D_NORMAL, _("Search"), "%s", view->search->error_str);
|
||||
}
|
||||
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
|
||||
|
||||
tty_disable_interrupt_key ();
|
||||
if (verbose) {
|
||||
dlg_run_done (d);
|
||||
destroy_dlg (d);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
Loading…
Reference in New Issue